1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * FIX: Go through all SSPI functions and verify what needs to be freed
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * FIX: session resumption
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * TODO: add support for server cert chain validation
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * TODO: add support for CA cert validation
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * TODO: add support for EAP-TLS (client cert/key conf)
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <windows.h>
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <wincrypt.h>
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <schannel.h>
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define SECURITY_WIN32
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <security.h>
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sspi.h>
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "tls.h"
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct tls_global {
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HMODULE hsecurity;
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	PSecurityFunctionTable sspi;
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HCERTSTORE my_cert_store;
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct tls_connection {
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int established, start;
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int failed, read_alerts, write_alerts;
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SCHANNEL_CRED schannel_cred;
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	CredHandle creds;
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	CtxtHandle context;
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 eap_tls_prf[128];
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int eap_tls_prf_set;
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int schannel_load_lib(struct tls_global *global)
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INIT_SECURITY_INTERFACE pInitSecurityInterface;
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	global->hsecurity = LoadLibrary(TEXT("Secur32.dll"));
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (global->hsecurity == NULL) {
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x",
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   __func__, (unsigned int) GetLastError());
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global->hsecurity, "InitSecurityInterfaceA");
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pInitSecurityInterface == NULL) {
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: Could not find "
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "InitSecurityInterfaceA from Secur32.dll",
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   __func__);
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		FreeLibrary(global->hsecurity);
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global->hsecurity = NULL;
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	global->sspi = pInitSecurityInterface();
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (global->sspi == NULL) {
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: Could not read security "
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "interface - 0x%x",
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   __func__, (unsigned int) GetLastError());
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		FreeLibrary(global->hsecurity);
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global->hsecurity = NULL;
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid * tls_init(const struct tls_config *conf)
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct tls_global *global;
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	global = os_zalloc(sizeof(*global));
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (global == NULL)
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (schannel_load_lib(global)) {
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(global);
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return global;
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid tls_deinit(void *ssl_ctx)
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct tls_global *global = ssl_ctx;
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (global->my_cert_store)
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CertCloseStore(global->my_cert_store, 0);
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	FreeLibrary(global->hsecurity);
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(global);
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_get_errors(void *ssl_ctx)
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct tls_connection * tls_connection_init(void *ssl_ctx)
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct tls_connection *conn;
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn = os_zalloc(sizeof(*conn));
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conn == NULL)
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->start = 1;
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return conn;
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conn == NULL)
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(conn);
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return conn ? conn->established : 0;
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct tls_global *global = ssl_ctx;
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conn == NULL)
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->eap_tls_prf_set = 0;
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->established = conn->failed = 0;
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->read_alerts = conn->write_alerts = 0;
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	global->sspi->DeleteSecurityContext(&conn->context);
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* FIX: what else needs to be reseted? */
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_global_set_params(void *tls_ctx,
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  const struct tls_connection_params *params)
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_global_set_verify(void *ssl_ctx, int check_crl)
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      int verify_peer)
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    struct tls_keys *keys)
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Schannel does not export master secret or client/server random. */
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       const char *label, int server_random_first,
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       u8 *out, size_t out_len)
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * Cannot get master_key from Schannel, but EapKeyBlock can be used to
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * EAP-TTLS cannot use this, though, since they are using different
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * labels. The only option could be to implement TLSv1 completely here
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * and just use Schannel or CryptoAPI for low-level crypto
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * functionality..
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conn == NULL || !conn->eap_tls_prf_set || server_random_first ||
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    os_strcmp(label, "client EAP encryption") != 0 ||
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    out_len > sizeof(conn->eap_tls_prf))
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(out, conn->eap_tls_prf, out_len);
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * tls_conn_hs_clienthello(struct tls_global *global,
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    struct tls_connection *conn,
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    size_t *out_len)
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD sspi_flags, sspi_flags_out;
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecBufferDesc outbuf;
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecBuffer outbufs[1];
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SECURITY_STATUS status;
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TimeStamp ts_expiry;
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sspi_flags = ISC_REQ_REPLAY_DETECT |
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ISC_REQ_CONFIDENTIALITY |
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ISC_RET_EXTENDED_ERROR |
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ISC_REQ_ALLOCATE_MEMORY |
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ISC_REQ_MANUAL_CRED_VALIDATION;
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbufs[0].pvBuffer = NULL;
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbufs[0].BufferType = SECBUFFER_TOKEN;
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbufs[0].cbBuffer = 0;
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbuf.cBuffers = 1;
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbuf.pBuffers = outbufs;
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbuf.ulVersion = SECBUFFER_VERSION;
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->InitializeSecurityContextW(
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&outbuf, &sspi_flags_out, &ts_expiry);
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* UNICODE */
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->InitializeSecurityContextA(
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&outbuf, &sspi_flags_out, &ts_expiry);
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* UNICODE */
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (status != SEC_I_CONTINUE_NEEDED) {
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "failed - 0x%x",
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   __func__, (unsigned int) status);
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		u8 *buf;
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		conn->start = 0;
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*out_len = outbufs[0].cbBuffer;
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		buf = os_malloc(*out_len);
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (buf == NULL)
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(buf, outbufs[0].pvBuffer, *out_len);
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return buf;
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return NULL;
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef SECPKG_ATTR_EAP_KEY_BLOCK
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidttypedef struct _SecPkgContext_EapKeyBlock {
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BYTE rgbKeys[128];
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BYTE rgbIVs[64];
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SECURITY_STATUS status;
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecPkgContext_EapKeyBlock kb;
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Note: Windows NT and Windows Me/98/95 do not support getting
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * EapKeyBlock */
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->QueryContextAttributes(
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb);
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (status != SEC_E_OK) {
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes("
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)",
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   __func__, (int) status);
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys",
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			kb.rgbKeys, sizeof(kb.rgbKeys));
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			kb.rgbIVs, sizeof(kb.rgbIVs));
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->eap_tls_prf_set = 1;
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtu8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      const u8 *in_data, size_t in_len,
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      size_t *out_len, u8 **appl_data,
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      size_t *appl_data_len)
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct tls_global *global = ssl_ctx;
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD sspi_flags, sspi_flags_out;
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecBufferDesc inbuf, outbuf;
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecBuffer inbufs[2], outbufs[1];
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SECURITY_STATUS status;
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TimeStamp ts_expiry;
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *out_buf = NULL;
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (appl_data)
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*appl_data = NULL;
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conn->start) {
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return tls_conn_hs_clienthello(global, conn, out_len);
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   in_len);
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sspi_flags = ISC_REQ_REPLAY_DETECT |
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ISC_REQ_CONFIDENTIALITY |
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ISC_RET_EXTENDED_ERROR |
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ISC_REQ_ALLOCATE_MEMORY |
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ISC_REQ_MANUAL_CRED_VALIDATION;
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Input buffer for Schannel */
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	inbufs[0].pvBuffer = (u8 *) in_data;
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	inbufs[0].cbBuffer = in_len;
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	inbufs[0].BufferType = SECBUFFER_TOKEN;
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Place for leftover data from Schannel */
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	inbufs[1].pvBuffer = NULL;
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	inbufs[1].cbBuffer = 0;
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	inbufs[1].BufferType = SECBUFFER_EMPTY;
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	inbuf.cBuffers = 2;
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	inbuf.pBuffers = inbufs;
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	inbuf.ulVersion = SECBUFFER_VERSION;
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Output buffer for Schannel */
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbufs[0].pvBuffer = NULL;
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbufs[0].cbBuffer = 0;
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbufs[0].BufferType = SECBUFFER_TOKEN;
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbuf.cBuffers = 1;
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbuf.pBuffers = outbufs;
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outbuf.ulVersion = SECBUFFER_VERSION;
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->InitializeSecurityContextW(
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&conn->creds, &conn->context, NULL, sspi_flags, 0,
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&outbuf, &sspi_flags_out, &ts_expiry);
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* UNICODE */
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->InitializeSecurityContextA(
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&conn->creds, &conn->context, NULL, sspi_flags, 0,
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&outbuf, &sspi_flags_out, &ts_expiry);
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* UNICODE */
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> "
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "intype[1]=%d outlen[0]=%d",
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) status, (int) inbufs[0].cbBuffer,
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) inbufs[1].BufferType,
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) outbufs[0].cbBuffer);
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*out_len = outbufs[0].cbBuffer;
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			out_buf = os_malloc(*out_len);
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (out_buf)
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				os_memcpy(out_buf, outbufs[0].pvBuffer,
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  *out_len);
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			outbufs[0].pvBuffer = NULL;
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (out_buf == NULL)
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				return NULL;
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (status) {
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case SEC_E_INCOMPLETE_MESSAGE:
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case SEC_I_CONTINUE_NEEDED:
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case SEC_E_OK:
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* TODO: verify server certificate chain */
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "completed successfully");
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		conn->established = 1;
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		tls_get_eap(global, conn);
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Need to return something to get final TLS ACK. */
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (out_buf == NULL)
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			out_buf = os_malloc(1);
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    "application data",
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (appl_data) {
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				*appl_data_len = outbufs[1].cbBuffer;
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				appl_data = os_malloc(*appl_data_len);
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				if (appl_data)
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					os_memcpy(appl_data,
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						  outbufs[1].pvBuffer,
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						  *appl_data_len);
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			inbufs[1].pvBuffer = NULL;
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case SEC_I_INCOMPLETE_CREDENTIALS:
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG,
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case SEC_E_WRONG_PRINCIPAL:
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case SEC_E_INTERNAL_ERROR:
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (FAILED(status)) {
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "(out_buf=%p)", out_buf);
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		conn->failed++;
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global->sspi->DeleteSecurityContext(&conn->context);
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return out_buf;
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* TODO: Can this happen? What to do with this data? */
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		inbufs[1].pvBuffer = NULL;
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return out_buf;
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtu8 * tls_connection_server_handshake(void *ssl_ctx,
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				     struct tls_connection *conn,
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				     const u8 *in_data, size_t in_len,
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				     size_t *out_len)
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return NULL;
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   const u8 *in_data, size_t in_len,
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   u8 *out_data, size_t out_len)
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct tls_global *global = ssl_ctx;
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SECURITY_STATUS status;
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecBufferDesc buf;
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecBuffer bufs[4];
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecPkgContext_StreamSizes sizes;
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i;
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t total_len;
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->QueryContextAttributes(&conn->context,
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						      SECPKG_ATTR_STREAM_SIZES,
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						      &sizes);
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (status != SEC_E_OK) {
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   __func__);
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__,
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (unsigned int) sizes.cbHeader,
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (unsigned int) sizes.cbTrailer);
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	total_len = sizes.cbHeader + in_len + sizes.cbTrailer;
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (out_len < total_len) {
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: too short out_data (out_len=%lu "
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "in_len=%lu total_len=%lu)", __func__,
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) out_len, (unsigned long) in_len,
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) total_len);
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&bufs, 0, sizeof(bufs));
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[0].pvBuffer = out_data;
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[0].cbBuffer = sizes.cbHeader;
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(out_data + sizes.cbHeader, in_data, in_len);
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[1].pvBuffer = out_data + sizes.cbHeader;
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[1].cbBuffer = in_len;
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[1].BufferType = SECBUFFER_DATA;
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len;
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[2].cbBuffer = sizes.cbTrailer;
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf.ulVersion = SECBUFFER_VERSION;
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf.cBuffers = 3;
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf.pBuffers = bufs;
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "len[2]=%d type[2]=%d",
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) status,
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "out_data=%p bufs %p %p %p",
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   bufs[2].pvBuffer);
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < 3; i++) {
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		{
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    bufs[i].pvBuffer, bufs[i].cbBuffer);
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (status == SEC_E_OK) {
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Encrypted data from "
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				"EncryptMessage", out_data, total_len);
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return total_len;
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, (int) status);
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   const u8 *in_data, size_t in_len,
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   u8 *out_data, size_t out_len)
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct tls_global *global = ssl_ctx;
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SECURITY_STATUS status;
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecBufferDesc buf;
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SecBuffer bufs[4];
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i;
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (out_len < in_len) {
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__,
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) out_len, (unsigned long) in_len);
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage",
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    in_data, in_len);
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&bufs, 0, sizeof(bufs));
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(out_data, in_data, in_len);
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[0].pvBuffer = out_data;
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[0].cbBuffer = in_len;
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[0].BufferType = SECBUFFER_DATA;
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[1].BufferType = SECBUFFER_EMPTY;
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[2].BufferType = SECBUFFER_EMPTY;
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bufs[3].BufferType = SECBUFFER_EMPTY;
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf.ulVersion = SECBUFFER_VERSION;
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf.cBuffers = 4;
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf.pBuffers = bufs;
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						    NULL);
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) status,
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "out_data=%p bufs %p %p %p %p",
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   bufs[2].pvBuffer, bufs[3].pvBuffer);
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (status) {
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case SEC_E_INCOMPLETE_MESSAGE:
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   __func__);
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case SEC_E_OK:
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < 4; i++) {
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (bufs[i].BufferType == SECBUFFER_DATA)
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				break;
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (i == 4) {
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "%s: No output data from "
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "DecryptMessage", __func__);
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				"DecryptMessage",
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				bufs[i].pvBuffer, bufs[i].cbBuffer);
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (bufs[i].cbBuffer > out_len) {
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "%s: Too long output data",
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   __func__);
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return bufs[i].cbBuffer;
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, (int) status);
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   u8 *ciphers)
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   char *buf, size_t buflen)
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_enable_workaround(void *ssl_ctx,
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				     struct tls_connection *conn)
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    int ext_type, const u8 *data,
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    size_t data_len)
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conn == NULL)
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return conn->failed;
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conn == NULL)
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return conn->read_alerts;
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conn == NULL)
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return conn->write_alerts;
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      const struct tls_connection_params *params)
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct tls_global *global = tls_ctx;
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ALG_ID algs[1];
715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SECURITY_STATUS status;
716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TimeStamp ts_expiry;
717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conn == NULL)
719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (global->my_cert_store == NULL &&
722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    NULL) {
724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   __func__, (unsigned int) GetLastError());
726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	algs[0] = CALG_RSA_KEYX;
733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->schannel_cred.cSupportedAlgs = 1;
734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->schannel_cred.palgSupportedAlgs = algs;
735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE
737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->AcquireCredentialsHandleW(
738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* UNICODE */
741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	status = global->sspi->AcquireCredentialsHandleA(
742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* UNICODE */
745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (status != SEC_E_OK) {
746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "0x%x", __func__, (unsigned int) status);
748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtunsigned int tls_capabilities(void *tls_ctx)
756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  int tls_ia)
763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_ia_send_phase_finished(void *tls_ctx,
769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  struct tls_connection *conn,
770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  int final,
771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  u8 *out_data, size_t out_len)
772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_ia_final_phase_finished(void *tls_ctx,
778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   struct tls_connection *conn)
779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint tls_connection_ia_permute_inner_secret(void *tls_ctx,
785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   struct tls_connection *conn,
786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   const u8 *key, size_t key_len)
787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
790