18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SSL/TLS interface functions for Microsoft Schannel
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FIX: Go through all SSPI functions and verify what needs to be freed
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FIX: session resumption
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: add support for server cert chain validation
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: add support for CA cert validation
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: add support for EAP-TLS (client cert/key conf)
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <windows.h>
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <wincrypt.h>
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <schannel.h>
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define SECURITY_WIN32
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <security.h>
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sspi.h>
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tls.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_global {
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HMODULE hsecurity;
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PSecurityFunctionTable sspi;
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCERTSTORE my_cert_store;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection {
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int established, start;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int failed, read_alerts, write_alerts;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SCHANNEL_CRED schannel_cred;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CredHandle creds;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CtxtHandle context;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 eap_tls_prf[128];
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int eap_tls_prf_set;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int schannel_load_lib(struct tls_global *global)
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INIT_SECURITY_INTERFACE pInitSecurityInterface;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	global->hsecurity = LoadLibrary(TEXT("Secur32.dll"));
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global->hsecurity == NULL) {
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x",
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, (unsigned int) GetLastError());
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		global->hsecurity, "InitSecurityInterfaceA");
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pInitSecurityInterface == NULL) {
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s: Could not find "
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "InitSecurityInterfaceA from Secur32.dll",
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FreeLibrary(global->hsecurity);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		global->hsecurity = NULL;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	global->sspi = pInitSecurityInterface();
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global->sspi == NULL) {
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s: Could not read security "
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "interface - 0x%x",
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, (unsigned int) GetLastError());
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FreeLibrary(global->hsecurity);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		global->hsecurity = NULL;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * tls_init(const struct tls_config *conf)
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_global *global;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	global = os_zalloc(sizeof(*global));
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global == NULL)
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (schannel_load_lib(global)) {
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(global);
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return global;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_deinit(void *ssl_ctx)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_global *global = ssl_ctx;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global->my_cert_store)
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CertCloseStore(global->my_cert_store, 0);
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FreeLibrary(global->hsecurity);
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(global);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_errors(void *ssl_ctx)
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection * tls_connection_init(void *ssl_ctx)
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_connection *conn;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn = os_zalloc(sizeof(*conn));
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->start = 1;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn);
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn ? conn->established : 0;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_global *global = ssl_ctx;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->eap_tls_prf_set = 0;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->established = conn->failed = 0;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->read_alerts = conn->write_alerts = 0;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	global->sspi->DeleteSecurityContext(&conn->context);
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* FIX: what else needs to be reseted? */
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_params(void *tls_ctx,
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const struct tls_connection_params *params)
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_verify(void *ssl_ctx, int check_crl)
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      int verify_peer)
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct tls_keys *keys)
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Schannel does not export master secret or client/server random. */
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       const char *label, int server_random_first,
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       u8 *out, size_t out_len)
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Cannot get master_key from Schannel, but EapKeyBlock can be used to
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAP-TTLS cannot use this, though, since they are using different
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * labels. The only option could be to implement TLSv1 completely here
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * and just use Schannel or CryptoAPI for low-level crypto
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * functionality..
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL || !conn->eap_tls_prf_set || server_random_first ||
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_strcmp(label, "client EAP encryption") != 0 ||
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    out_len > sizeof(conn->eap_tls_prf))
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(out, conn->eap_tls_prf, out_len);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       struct tls_connection *conn)
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD sspi_flags, sspi_flags_out;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecBufferDesc outbuf;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecBuffer outbufs[1];
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SECURITY_STATUS status;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TimeStamp ts_expiry;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sspi_flags = ISC_REQ_REPLAY_DETECT |
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ISC_REQ_CONFIDENTIALITY |
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ISC_RET_EXTENDED_ERROR |
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ISC_REQ_ALLOCATE_MEMORY |
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ISC_REQ_MANUAL_CRED_VALIDATION;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbufs[0].pvBuffer = NULL;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbufs[0].BufferType = SECBUFFER_TOKEN;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbufs[0].cbBuffer = 0;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbuf.cBuffers = 1;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbuf.pBuffers = outbufs;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbuf.ulVersion = SECBUFFER_VERSION;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->InitializeSecurityContextW(
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&outbuf, &sspi_flags_out, &ts_expiry);
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->InitializeSecurityContextA(
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&outbuf, &sspi_flags_out, &ts_expiry);
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status != SEC_I_CONTINUE_NEEDED) {
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed - 0x%x",
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, (unsigned int) status);
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpabuf *buf;
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->start = 0;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					outbufs[0].cbBuffer);
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf == NULL)
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return buf;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef SECPKG_ATTR_EAP_KEY_BLOCK
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct _SecPkgContext_EapKeyBlock {
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BYTE rgbKeys[128];
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BYTE rgbIVs[64];
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SECURITY_STATUS status;
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecPkgContext_EapKeyBlock kb;
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Note: Windows NT and Windows Me/98/95 do not support getting
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EapKeyBlock */
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->QueryContextAttributes(
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb);
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status != SEC_E_OK) {
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes("
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)",
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, (int) status);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys",
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			kb.rgbKeys, sizeof(kb.rgbKeys));
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			kb.rgbIVs, sizeof(kb.rgbIVs));
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->eap_tls_prf_set = 1;
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_handshake(void *tls_ctx,
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct tls_connection *conn,
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const struct wpabuf *in_data,
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct wpabuf **appl_data)
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_global *global = tls_ctx;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD sspi_flags, sspi_flags_out;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecBufferDesc inbuf, outbuf;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecBuffer inbufs[2], outbufs[1];
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SECURITY_STATUS status;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TimeStamp ts_expiry;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *out_buf = NULL;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (appl_data)
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*appl_data = NULL;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->start)
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_conn_hs_clienthello(global, conn);
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) wpabuf_len(in_data));
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sspi_flags = ISC_REQ_REPLAY_DETECT |
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ISC_REQ_CONFIDENTIALITY |
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ISC_RET_EXTENDED_ERROR |
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ISC_REQ_ALLOCATE_MEMORY |
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ISC_REQ_MANUAL_CRED_VALIDATION;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Input buffer for Schannel */
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inbufs[0].cbBuffer = wpabuf_len(in_data);
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inbufs[0].BufferType = SECBUFFER_TOKEN;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Place for leftover data from Schannel */
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inbufs[1].pvBuffer = NULL;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inbufs[1].cbBuffer = 0;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inbufs[1].BufferType = SECBUFFER_EMPTY;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inbuf.cBuffers = 2;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inbuf.pBuffers = inbufs;
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inbuf.ulVersion = SECBUFFER_VERSION;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Output buffer for Schannel */
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbufs[0].pvBuffer = NULL;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbufs[0].cbBuffer = 0;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbufs[0].BufferType = SECBUFFER_TOKEN;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbuf.cBuffers = 1;
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbuf.pBuffers = outbufs;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbuf.ulVersion = SECBUFFER_VERSION;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->InitializeSecurityContextW(
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&conn->creds, &conn->context, NULL, sspi_flags, 0,
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&outbuf, &sspi_flags_out, &ts_expiry);
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->InitializeSecurityContextA(
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&conn->creds, &conn->context, NULL, sspi_flags, 0,
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&outbuf, &sspi_flags_out, &ts_expiry);
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> "
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "intype[1]=%d outlen[0]=%d",
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) status, (int) inbufs[0].cbBuffer,
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) inbufs[1].BufferType,
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) outbufs[0].cbBuffer);
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    outbufs[0].cbBuffer);
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			outbufs[0].pvBuffer = NULL;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (out_buf == NULL)
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (status) {
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SEC_E_INCOMPLETE_MESSAGE:
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SEC_I_CONTINUE_NEEDED:
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SEC_E_OK:
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: verify server certificate chain */
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "completed successfully");
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->established = 1;
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_get_eap(global, conn);
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Need to return something to get final TLS ACK. */
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (out_buf == NULL)
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			out_buf = wpabuf_alloc(0);
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "application data",
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (appl_data) {
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				*appl_data = wpabuf_alloc_copy(
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					outbufs[1].pvBuffer,
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					outbufs[1].cbBuffer);
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			inbufs[1].pvBuffer = NULL;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SEC_I_INCOMPLETE_CREDENTIALS:
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG,
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SEC_E_WRONG_PRINCIPAL:
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SEC_E_INTERNAL_ERROR:
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (FAILED(status)) {
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(out_buf=%p)", out_buf);
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->failed++;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		global->sspi->DeleteSecurityContext(&conn->context);
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return out_buf;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: Can this happen? What to do with this data? */
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		inbufs[1].pvBuffer = NULL;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return out_buf;
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_server_handshake(void *tls_ctx,
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct tls_connection *conn,
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						const struct wpabuf *in_data,
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						struct wpabuf **appl_data)
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_encrypt(void *tls_ctx,
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct tls_connection *conn,
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpabuf *in_data)
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_global *global = tls_ctx;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SECURITY_STATUS status;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecBufferDesc buf;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecBuffer bufs[4];
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecPkgContext_StreamSizes sizes;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *out;
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->QueryContextAttributes(&conn->context,
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      SECPKG_ATTR_STREAM_SIZES,
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      &sizes);
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status != SEC_E_OK) {
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   __func__,
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned int) sizes.cbHeader,
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned int) sizes.cbTrailer);
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizes.cbTrailer);
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&bufs, 0, sizeof(bufs));
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader);
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[0].cbBuffer = sizes.cbHeader;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[1].pvBuffer = wpabuf_put(out, 0);
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_buf(out, in_data);
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[1].cbBuffer = wpabuf_len(in_data);
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[1].BufferType = SECBUFFER_DATA;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[2].cbBuffer = sizes.cbTrailer;
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf.ulVersion = SECBUFFER_VERSION;
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf.cBuffers = 3;
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf.pBuffers = bufs;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "len[2]=%d type[2]=%d",
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) status,
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "out_data=%p bufs %p %p %p",
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer,
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   bufs[2].pvBuffer);
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 3; i++) {
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    bufs[i].pvBuffer, bufs[i].cbBuffer);
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status == SEC_E_OK) {
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "from EncryptMessage", out);
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return out;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   __func__, (int) status);
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(out);
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_decrypt(void *tls_ctx,
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct tls_connection *conn,
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpabuf *in_data)
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_global *global = tls_ctx;
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SECURITY_STATUS status;
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecBufferDesc buf;
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SecBuffer bufs[4];
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *out, *tmp;
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_buf(MSG_MSGDUMP,
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Schannel: Encrypted data to DecryptMessage", in_data);
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&bufs, 0, sizeof(bufs));
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = wpabuf_dup(in_data);
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[0].pvBuffer = wpabuf_mhead(tmp);
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[0].cbBuffer = wpabuf_len(in_data);
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[0].BufferType = SECBUFFER_DATA;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[1].BufferType = SECBUFFER_EMPTY;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[2].BufferType = SECBUFFER_EMPTY;
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bufs[3].BufferType = SECBUFFER_EMPTY;
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf.ulVersion = SECBUFFER_VERSION;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf.cBuffers = 4;
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf.pBuffers = bufs;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    NULL);
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) status,
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "out_data=%p bufs %p %p %p %p",
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer,
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   bufs[2].pvBuffer, bufs[3].pvBuffer);
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (status) {
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SEC_E_INCOMPLETE_MESSAGE:
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__);
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SEC_E_OK:
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < 4; i++) {
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (bufs[i].BufferType == SECBUFFER_DATA)
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (i == 4) {
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "%s: No output data from "
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "DecryptMessage", __func__);
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_free(tmp);
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"DecryptMessage",
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				bufs[i].pvBuffer, bufs[i].cbBuffer);
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(tmp);
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return out;
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   __func__, (int) status);
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(tmp);
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   u8 *ciphers)
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   char *buf, size_t buflen)
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_enable_workaround(void *ssl_ctx,
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct tls_connection *conn)
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    int ext_type, const u8 *data,
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    size_t data_len)
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn->failed;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn->read_alerts;
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return conn->write_alerts;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const struct tls_connection_params *params)
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_global *global = tls_ctx;
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ALG_ID algs[1];
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SECURITY_STATUS status;
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TimeStamp ts_expiry;
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn == NULL)
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (global->my_cert_store == NULL &&
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    NULL) {
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, (unsigned int) GetLastError());
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	algs[0] = CALG_RSA_KEYX;
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->schannel_cred.cSupportedAlgs = 1;
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->schannel_cred.palgSupportedAlgs = algs;
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->AcquireCredentialsHandleW(
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* UNICODE */
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = global->sspi->AcquireCredentialsHandleA(
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* UNICODE */
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status != SEC_E_OK) {
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "0x%x", __func__, (unsigned int) status);
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int tls_capabilities(void *tls_ctx)
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
733