Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
      3  * Copyright (c) 2005, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 /*
     16  * FIX: Go through all SSPI functions and verify what needs to be freed
     17  * FIX: session resumption
     18  * TODO: add support for server cert chain validation
     19  * TODO: add support for CA cert validation
     20  * TODO: add support for EAP-TLS (client cert/key conf)
     21  */
     22 
     23 #include "includes.h"
     24 #include <windows.h>
     25 #include <wincrypt.h>
     26 #include <schannel.h>
     27 #define SECURITY_WIN32
     28 #include <security.h>
     29 #include <sspi.h>
     30 
     31 #include "common.h"
     32 #include "tls.h"
     33 
     34 
     35 struct tls_global {
     36 	HMODULE hsecurity;
     37 	PSecurityFunctionTable sspi;
     38 	HCERTSTORE my_cert_store;
     39 };
     40 
     41 struct tls_connection {
     42 	int established, start;
     43 	int failed, read_alerts, write_alerts;
     44 
     45 	SCHANNEL_CRED schannel_cred;
     46 	CredHandle creds;
     47 	CtxtHandle context;
     48 
     49 	u8 eap_tls_prf[128];
     50 	int eap_tls_prf_set;
     51 };
     52 
     53 
     54 static int schannel_load_lib(struct tls_global *global)
     55 {
     56 	INIT_SECURITY_INTERFACE pInitSecurityInterface;
     57 
     58 	global->hsecurity = LoadLibrary(TEXT("Secur32.dll"));
     59 	if (global->hsecurity == NULL) {
     60 		wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x",
     61 			   __func__, (unsigned int) GetLastError());
     62 		return -1;
     63 	}
     64 
     65 	pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(
     66 		global->hsecurity, "InitSecurityInterfaceA");
     67 	if (pInitSecurityInterface == NULL) {
     68 		wpa_printf(MSG_ERROR, "%s: Could not find "
     69 			   "InitSecurityInterfaceA from Secur32.dll",
     70 			   __func__);
     71 		FreeLibrary(global->hsecurity);
     72 		global->hsecurity = NULL;
     73 		return -1;
     74 	}
     75 
     76 	global->sspi = pInitSecurityInterface();
     77 	if (global->sspi == NULL) {
     78 		wpa_printf(MSG_ERROR, "%s: Could not read security "
     79 			   "interface - 0x%x",
     80 			   __func__, (unsigned int) GetLastError());
     81 		FreeLibrary(global->hsecurity);
     82 		global->hsecurity = NULL;
     83 		return -1;
     84 	}
     85 
     86 	return 0;
     87 }
     88 
     89 
     90 void * tls_init(const struct tls_config *conf)
     91 {
     92 	struct tls_global *global;
     93 
     94 	global = os_zalloc(sizeof(*global));
     95 	if (global == NULL)
     96 		return NULL;
     97 	if (schannel_load_lib(global)) {
     98 		os_free(global);
     99 		return NULL;
    100 	}
    101 	return global;
    102 }
    103 
    104 
    105 void tls_deinit(void *ssl_ctx)
    106 {
    107 	struct tls_global *global = ssl_ctx;
    108 
    109 	if (global->my_cert_store)
    110 		CertCloseStore(global->my_cert_store, 0);
    111 	FreeLibrary(global->hsecurity);
    112 	os_free(global);
    113 }
    114 
    115 
    116 int tls_get_errors(void *ssl_ctx)
    117 {
    118 	return 0;
    119 }
    120 
    121 
    122 struct tls_connection * tls_connection_init(void *ssl_ctx)
    123 {
    124 	struct tls_connection *conn;
    125 
    126 	conn = os_zalloc(sizeof(*conn));
    127 	if (conn == NULL)
    128 		return NULL;
    129 	conn->start = 1;
    130 
    131 	return conn;
    132 }
    133 
    134 
    135 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
    136 {
    137 	if (conn == NULL)
    138 		return;
    139 
    140 	os_free(conn);
    141 }
    142 
    143 
    144 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
    145 {
    146 	return conn ? conn->established : 0;
    147 }
    148 
    149 
    150 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
    151 {
    152 	struct tls_global *global = ssl_ctx;
    153 	if (conn == NULL)
    154 		return -1;
    155 
    156 	conn->eap_tls_prf_set = 0;
    157 	conn->established = conn->failed = 0;
    158 	conn->read_alerts = conn->write_alerts = 0;
    159 	global->sspi->DeleteSecurityContext(&conn->context);
    160 	/* FIX: what else needs to be reseted? */
    161 
    162 	return 0;
    163 }
    164 
    165 
    166 int tls_global_set_params(void *tls_ctx,
    167 			  const struct tls_connection_params *params)
    168 {
    169 	return -1;
    170 }
    171 
    172 
    173 int tls_global_set_verify(void *ssl_ctx, int check_crl)
    174 {
    175 	return -1;
    176 }
    177 
    178 
    179 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
    180 			      int verify_peer)
    181 {
    182 	return -1;
    183 }
    184 
    185 
    186 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
    187 			    struct tls_keys *keys)
    188 {
    189 	/* Schannel does not export master secret or client/server random. */
    190 	return -1;
    191 }
    192 
    193 
    194 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
    195 		       const char *label, int server_random_first,
    196 		       u8 *out, size_t out_len)
    197 {
    198 	/*
    199 	 * Cannot get master_key from Schannel, but EapKeyBlock can be used to
    200 	 * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and
    201 	 * EAP-TTLS cannot use this, though, since they are using different
    202 	 * labels. The only option could be to implement TLSv1 completely here
    203 	 * and just use Schannel or CryptoAPI for low-level crypto
    204 	 * functionality..
    205 	 */
    206 
    207 	if (conn == NULL || !conn->eap_tls_prf_set || server_random_first ||
    208 	    os_strcmp(label, "client EAP encryption") != 0 ||
    209 	    out_len > sizeof(conn->eap_tls_prf))
    210 		return -1;
    211 
    212 	os_memcpy(out, conn->eap_tls_prf, out_len);
    213 
    214 	return 0;
    215 }
    216 
    217 
    218 static u8 * tls_conn_hs_clienthello(struct tls_global *global,
    219 				    struct tls_connection *conn,
    220 				    size_t *out_len)
    221 {
    222 	DWORD sspi_flags, sspi_flags_out;
    223 	SecBufferDesc outbuf;
    224 	SecBuffer outbufs[1];
    225 	SECURITY_STATUS status;
    226 	TimeStamp ts_expiry;
    227 
    228 	sspi_flags = ISC_REQ_REPLAY_DETECT |
    229 		ISC_REQ_CONFIDENTIALITY |
    230 		ISC_RET_EXTENDED_ERROR |
    231 		ISC_REQ_ALLOCATE_MEMORY |
    232 		ISC_REQ_MANUAL_CRED_VALIDATION;
    233 
    234 	wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
    235 
    236 	outbufs[0].pvBuffer = NULL;
    237 	outbufs[0].BufferType = SECBUFFER_TOKEN;
    238 	outbufs[0].cbBuffer = 0;
    239 
    240 	outbuf.cBuffers = 1;
    241 	outbuf.pBuffers = outbufs;
    242 	outbuf.ulVersion = SECBUFFER_VERSION;
    243 
    244 #ifdef UNICODE
    245 	status = global->sspi->InitializeSecurityContextW(
    246 		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
    247 		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
    248 		&outbuf, &sspi_flags_out, &ts_expiry);
    249 #else /* UNICODE */
    250 	status = global->sspi->InitializeSecurityContextA(
    251 		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
    252 		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
    253 		&outbuf, &sspi_flags_out, &ts_expiry);
    254 #endif /* UNICODE */
    255 	if (status != SEC_I_CONTINUE_NEEDED) {
    256 		wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
    257 			   "failed - 0x%x",
    258 			   __func__, (unsigned int) status);
    259 		return NULL;
    260 	}
    261 
    262 	if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
    263 		u8 *buf;
    264 		wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
    265 			    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
    266 		conn->start = 0;
    267 		*out_len = outbufs[0].cbBuffer;
    268 		buf = os_malloc(*out_len);
    269 		if (buf == NULL)
    270 			return NULL;
    271 		os_memcpy(buf, outbufs[0].pvBuffer, *out_len);
    272 		global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
    273 		return buf;
    274 	}
    275 
    276 	wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
    277 
    278 	return NULL;
    279 }
    280 
    281 
    282 #ifndef SECPKG_ATTR_EAP_KEY_BLOCK
    283 #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
    284 
    285 typedef struct _SecPkgContext_EapKeyBlock {
    286 	BYTE rgbKeys[128];
    287 	BYTE rgbIVs[64];
    288 } SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
    289 #endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
    290 
    291 static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
    292 {
    293 	SECURITY_STATUS status;
    294 	SecPkgContext_EapKeyBlock kb;
    295 
    296 	/* Note: Windows NT and Windows Me/98/95 do not support getting
    297 	 * EapKeyBlock */
    298 
    299 	status = global->sspi->QueryContextAttributes(
    300 		&conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb);
    301 	if (status != SEC_E_OK) {
    302 		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes("
    303 			   "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)",
    304 			   __func__, (int) status);
    305 		return -1;
    306 	}
    307 
    308 	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys",
    309 			kb.rgbKeys, sizeof(kb.rgbKeys));
    310 	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
    311 			kb.rgbIVs, sizeof(kb.rgbIVs));
    312 
    313 	os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
    314 	conn->eap_tls_prf_set = 1;
    315 	return 0;
    316 }
    317 
    318 
    319 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
    320 			      const u8 *in_data, size_t in_len,
    321 			      size_t *out_len, u8 **appl_data,
    322 			      size_t *appl_data_len)
    323 {
    324 	struct tls_global *global = ssl_ctx;
    325 	DWORD sspi_flags, sspi_flags_out;
    326 	SecBufferDesc inbuf, outbuf;
    327 	SecBuffer inbufs[2], outbufs[1];
    328 	SECURITY_STATUS status;
    329 	TimeStamp ts_expiry;
    330 	u8 *out_buf = NULL;
    331 
    332 	if (appl_data)
    333 		*appl_data = NULL;
    334 
    335 	if (conn->start) {
    336 		return tls_conn_hs_clienthello(global, conn, out_len);
    337 	}
    338 
    339 	wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
    340 		   in_len);
    341 
    342 	sspi_flags = ISC_REQ_REPLAY_DETECT |
    343 		ISC_REQ_CONFIDENTIALITY |
    344 		ISC_RET_EXTENDED_ERROR |
    345 		ISC_REQ_ALLOCATE_MEMORY |
    346 		ISC_REQ_MANUAL_CRED_VALIDATION;
    347 
    348 	/* Input buffer for Schannel */
    349 	inbufs[0].pvBuffer = (u8 *) in_data;
    350 	inbufs[0].cbBuffer = in_len;
    351 	inbufs[0].BufferType = SECBUFFER_TOKEN;
    352 
    353 	/* Place for leftover data from Schannel */
    354 	inbufs[1].pvBuffer = NULL;
    355 	inbufs[1].cbBuffer = 0;
    356 	inbufs[1].BufferType = SECBUFFER_EMPTY;
    357 
    358 	inbuf.cBuffers = 2;
    359 	inbuf.pBuffers = inbufs;
    360 	inbuf.ulVersion = SECBUFFER_VERSION;
    361 
    362 	/* Output buffer for Schannel */
    363 	outbufs[0].pvBuffer = NULL;
    364 	outbufs[0].cbBuffer = 0;
    365 	outbufs[0].BufferType = SECBUFFER_TOKEN;
    366 
    367 	outbuf.cBuffers = 1;
    368 	outbuf.pBuffers = outbufs;
    369 	outbuf.ulVersion = SECBUFFER_VERSION;
    370 
    371 #ifdef UNICODE
    372 	status = global->sspi->InitializeSecurityContextW(
    373 		&conn->creds, &conn->context, NULL, sspi_flags, 0,
    374 		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
    375 		&outbuf, &sspi_flags_out, &ts_expiry);
    376 #else /* UNICODE */
    377 	status = global->sspi->InitializeSecurityContextA(
    378 		&conn->creds, &conn->context, NULL, sspi_flags, 0,
    379 		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
    380 		&outbuf, &sspi_flags_out, &ts_expiry);
    381 #endif /* UNICODE */
    382 
    383 	wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> "
    384 		   "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
    385 		   "intype[1]=%d outlen[0]=%d",
    386 		   (int) status, (int) inbufs[0].cbBuffer,
    387 		   (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
    388 		   (int) inbufs[1].BufferType,
    389 		   (int) outbufs[0].cbBuffer);
    390 	if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
    391 	    (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
    392 		if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
    393 			wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
    394 				    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
    395 			*out_len = outbufs[0].cbBuffer;
    396 			out_buf = os_malloc(*out_len);
    397 			if (out_buf)
    398 				os_memcpy(out_buf, outbufs[0].pvBuffer,
    399 					  *out_len);
    400 			global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
    401 			outbufs[0].pvBuffer = NULL;
    402 			if (out_buf == NULL)
    403 				return NULL;
    404 		}
    405 	}
    406 
    407 	switch (status) {
    408 	case SEC_E_INCOMPLETE_MESSAGE:
    409 		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
    410 		break;
    411 	case SEC_I_CONTINUE_NEEDED:
    412 		wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
    413 		break;
    414 	case SEC_E_OK:
    415 		/* TODO: verify server certificate chain */
    416 		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
    417 			   "completed successfully");
    418 		conn->established = 1;
    419 		tls_get_eap(global, conn);
    420 
    421 		/* Need to return something to get final TLS ACK. */
    422 		if (out_buf == NULL)
    423 			out_buf = os_malloc(1);
    424 
    425 		if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
    426 			wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
    427 				    "application data",
    428 				    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
    429 			if (appl_data) {
    430 				*appl_data_len = outbufs[1].cbBuffer;
    431 				appl_data = os_malloc(*appl_data_len);
    432 				if (appl_data)
    433 					os_memcpy(appl_data,
    434 						  outbufs[1].pvBuffer,
    435 						  *appl_data_len);
    436 			}
    437 			global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
    438 			inbufs[1].pvBuffer = NULL;
    439 		}
    440 		break;
    441 	case SEC_I_INCOMPLETE_CREDENTIALS:
    442 		wpa_printf(MSG_DEBUG,
    443 			   "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
    444 		break;
    445 	case SEC_E_WRONG_PRINCIPAL:
    446 		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
    447 		break;
    448 	case SEC_E_INTERNAL_ERROR:
    449 		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
    450 		break;
    451 	}
    452 
    453 	if (FAILED(status)) {
    454 		wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
    455 			   "(out_buf=%p)", out_buf);
    456 		conn->failed++;
    457 		global->sspi->DeleteSecurityContext(&conn->context);
    458 		return out_buf;
    459 	}
    460 
    461 	if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
    462 		/* TODO: Can this happen? What to do with this data? */
    463 		wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
    464 			    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
    465 		global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
    466 		inbufs[1].pvBuffer = NULL;
    467 	}
    468 
    469 	return out_buf;
    470 }
    471 
    472 
    473 u8 * tls_connection_server_handshake(void *ssl_ctx,
    474 				     struct tls_connection *conn,
    475 				     const u8 *in_data, size_t in_len,
    476 				     size_t *out_len)
    477 {
    478 	return NULL;
    479 }
    480 
    481 
    482 int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
    483 			   const u8 *in_data, size_t in_len,
    484 			   u8 *out_data, size_t out_len)
    485 {
    486 	struct tls_global *global = ssl_ctx;
    487 	SECURITY_STATUS status;
    488 	SecBufferDesc buf;
    489 	SecBuffer bufs[4];
    490 	SecPkgContext_StreamSizes sizes;
    491 	int i;
    492 	size_t total_len;
    493 
    494 	status = global->sspi->QueryContextAttributes(&conn->context,
    495 						      SECPKG_ATTR_STREAM_SIZES,
    496 						      &sizes);
    497 	if (status != SEC_E_OK) {
    498 		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
    499 			   __func__);
    500 		return -1;
    501 	}
    502 	wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
    503 		   __func__,
    504 		   (unsigned int) sizes.cbHeader,
    505 		   (unsigned int) sizes.cbTrailer);
    506 
    507 	total_len = sizes.cbHeader + in_len + sizes.cbTrailer;
    508 
    509 	if (out_len < total_len) {
    510 		wpa_printf(MSG_DEBUG, "%s: too short out_data (out_len=%lu "
    511 			   "in_len=%lu total_len=%lu)", __func__,
    512 			   (unsigned long) out_len, (unsigned long) in_len,
    513 			   (unsigned long) total_len);
    514 		return -1;
    515 	}
    516 
    517 	os_memset(&bufs, 0, sizeof(bufs));
    518 	bufs[0].pvBuffer = out_data;
    519 	bufs[0].cbBuffer = sizes.cbHeader;
    520 	bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
    521 
    522 	os_memcpy(out_data + sizes.cbHeader, in_data, in_len);
    523 	bufs[1].pvBuffer = out_data + sizes.cbHeader;
    524 	bufs[1].cbBuffer = in_len;
    525 	bufs[1].BufferType = SECBUFFER_DATA;
    526 
    527 	bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len;
    528 	bufs[2].cbBuffer = sizes.cbTrailer;
    529 	bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
    530 
    531 	buf.ulVersion = SECBUFFER_VERSION;
    532 	buf.cBuffers = 3;
    533 	buf.pBuffers = bufs;
    534 
    535 	status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
    536 
    537 	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
    538 		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
    539 		   "len[2]=%d type[2]=%d",
    540 		   (int) status,
    541 		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
    542 		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
    543 		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
    544 	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
    545 		   "out_data=%p bufs %p %p %p",
    546 		   out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
    547 		   bufs[2].pvBuffer);
    548 
    549 	for (i = 0; i < 3; i++) {
    550 		if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
    551 		{
    552 			wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
    553 				    bufs[i].pvBuffer, bufs[i].cbBuffer);
    554 		}
    555 	}
    556 
    557 	if (status == SEC_E_OK) {
    558 		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
    559 		wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Encrypted data from "
    560 				"EncryptMessage", out_data, total_len);
    561 		return total_len;
    562 	}
    563 
    564 	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
    565 		   __func__, (int) status);
    566 	return -1;
    567 }
    568 
    569 
    570 int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
    571 			   const u8 *in_data, size_t in_len,
    572 			   u8 *out_data, size_t out_len)
    573 {
    574 	struct tls_global *global = ssl_ctx;
    575 	SECURITY_STATUS status;
    576 	SecBufferDesc buf;
    577 	SecBuffer bufs[4];
    578 	int i;
    579 
    580 	if (out_len < in_len) {
    581 		wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__,
    582 			   (unsigned long) out_len, (unsigned long) in_len);
    583 		return -1;
    584 	}
    585 
    586 	wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage",
    587 		    in_data, in_len);
    588 	os_memset(&bufs, 0, sizeof(bufs));
    589 	os_memcpy(out_data, in_data, in_len);
    590 	bufs[0].pvBuffer = out_data;
    591 	bufs[0].cbBuffer = in_len;
    592 	bufs[0].BufferType = SECBUFFER_DATA;
    593 
    594 	bufs[1].BufferType = SECBUFFER_EMPTY;
    595 	bufs[2].BufferType = SECBUFFER_EMPTY;
    596 	bufs[3].BufferType = SECBUFFER_EMPTY;
    597 
    598 	buf.ulVersion = SECBUFFER_VERSION;
    599 	buf.cBuffers = 4;
    600 	buf.pBuffers = bufs;
    601 
    602 	status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
    603 						    NULL);
    604 	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
    605 		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
    606 		   "len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
    607 		   (int) status,
    608 		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
    609 		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
    610 		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
    611 		   (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
    612 	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
    613 		   "out_data=%p bufs %p %p %p %p",
    614 		   out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
    615 		   bufs[2].pvBuffer, bufs[3].pvBuffer);
    616 
    617 	switch (status) {
    618 	case SEC_E_INCOMPLETE_MESSAGE:
    619 		wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
    620 			   __func__);
    621 		break;
    622 	case SEC_E_OK:
    623 		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
    624 		for (i = 0; i < 4; i++) {
    625 			if (bufs[i].BufferType == SECBUFFER_DATA)
    626 				break;
    627 		}
    628 		if (i == 4) {
    629 			wpa_printf(MSG_DEBUG, "%s: No output data from "
    630 				   "DecryptMessage", __func__);
    631 			return -1;
    632 		}
    633 		wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
    634 				"DecryptMessage",
    635 				bufs[i].pvBuffer, bufs[i].cbBuffer);
    636 		if (bufs[i].cbBuffer > out_len) {
    637 			wpa_printf(MSG_DEBUG, "%s: Too long output data",
    638 				   __func__);
    639 			return -1;
    640 		}
    641 		os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
    642 		return bufs[i].cbBuffer;
    643 	}
    644 
    645 	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
    646 		   __func__, (int) status);
    647 	return -1;
    648 }
    649 
    650 
    651 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
    652 {
    653 	return 0;
    654 }
    655 
    656 
    657 int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
    658 				  const u8 *key, size_t key_len)
    659 {
    660 	return -1;
    661 }
    662 
    663 
    664 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
    665 				   u8 *ciphers)
    666 {
    667 	return -1;
    668 }
    669 
    670 
    671 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
    672 		   char *buf, size_t buflen)
    673 {
    674 	return -1;
    675 }
    676 
    677 
    678 int tls_connection_enable_workaround(void *ssl_ctx,
    679 				     struct tls_connection *conn)
    680 {
    681 	return 0;
    682 }
    683 
    684 
    685 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
    686 				    int ext_type, const u8 *data,
    687 				    size_t data_len)
    688 {
    689 	return -1;
    690 }
    691 
    692 
    693 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
    694 {
    695 	if (conn == NULL)
    696 		return -1;
    697 	return conn->failed;
    698 }
    699 
    700 
    701 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
    702 {
    703 	if (conn == NULL)
    704 		return -1;
    705 	return conn->read_alerts;
    706 }
    707 
    708 
    709 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
    710 {
    711 	if (conn == NULL)
    712 		return -1;
    713 	return conn->write_alerts;
    714 }
    715 
    716 
    717 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
    718 			      const struct tls_connection_params *params)
    719 {
    720 	struct tls_global *global = tls_ctx;
    721 	ALG_ID algs[1];
    722 	SECURITY_STATUS status;
    723 	TimeStamp ts_expiry;
    724 
    725 	if (conn == NULL)
    726 		return -1;
    727 
    728 	if (global->my_cert_store == NULL &&
    729 	    (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
    730 	    NULL) {
    731 		wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
    732 			   __func__, (unsigned int) GetLastError());
    733 		return -1;
    734 	}
    735 
    736 	os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
    737 	conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
    738 	conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
    739 	algs[0] = CALG_RSA_KEYX;
    740 	conn->schannel_cred.cSupportedAlgs = 1;
    741 	conn->schannel_cred.palgSupportedAlgs = algs;
    742 	conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
    743 #ifdef UNICODE
    744 	status = global->sspi->AcquireCredentialsHandleW(
    745 		NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
    746 		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
    747 #else /* UNICODE */
    748 	status = global->sspi->AcquireCredentialsHandleA(
    749 		NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
    750 		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
    751 #endif /* UNICODE */
    752 	if (status != SEC_E_OK) {
    753 		wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
    754 			   "0x%x", __func__, (unsigned int) status);
    755 		return -1;
    756 	}
    757 
    758 	return 0;
    759 }
    760 
    761 
    762 unsigned int tls_capabilities(void *tls_ctx)
    763 {
    764 	return 0;
    765 }
    766 
    767 
    768 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
    769 			  int tls_ia)
    770 {
    771 	return -1;
    772 }
    773 
    774 
    775 int tls_connection_ia_send_phase_finished(void *tls_ctx,
    776 					  struct tls_connection *conn,
    777 					  int final,
    778 					  u8 *out_data, size_t out_len)
    779 {
    780 	return -1;
    781 }
    782 
    783 
    784 int tls_connection_ia_final_phase_finished(void *tls_ctx,
    785 					   struct tls_connection *conn)
    786 {
    787 	return -1;
    788 }
    789 
    790 
    791 int tls_connection_ia_permute_inner_secret(void *tls_ctx,
    792 					   struct tls_connection *conn,
    793 					   const u8 *key, size_t key_len)
    794 {
    795 	return -1;
    796 }
    797