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