1 /*
2  * SSL/TLS interface functions for Microsoft Schannel
3  * Copyright (c) 2005-2009, Jouni Malinen <j@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 
schannel_load_lib(struct tls_global * global)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 
tls_init(const struct tls_config * conf)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 
tls_deinit(void * ssl_ctx)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 
tls_get_errors(void * ssl_ctx)116 int tls_get_errors(void *ssl_ctx)
117 {
118 	return 0;
119 }
120 
121 
tls_connection_init(void * ssl_ctx)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 
tls_connection_deinit(void * ssl_ctx,struct tls_connection * conn)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 
tls_connection_established(void * ssl_ctx,struct tls_connection * conn)144 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
145 {
146 	return conn ? conn->established : 0;
147 }
148 
149 
tls_connection_shutdown(void * ssl_ctx,struct tls_connection * conn)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 
tls_global_set_params(void * tls_ctx,const struct tls_connection_params * params)166 int tls_global_set_params(void *tls_ctx,
167 			  const struct tls_connection_params *params)
168 {
169 	return -1;
170 }
171 
172 
tls_global_set_verify(void * ssl_ctx,int check_crl)173 int tls_global_set_verify(void *ssl_ctx, int check_crl)
174 {
175 	return -1;
176 }
177 
178 
tls_connection_set_verify(void * ssl_ctx,struct tls_connection * conn,int verify_peer)179 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
180 			      int verify_peer)
181 {
182 	return -1;
183 }
184 
185 
tls_connection_get_keys(void * ssl_ctx,struct tls_connection * conn,struct tls_keys * keys)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 
tls_connection_prf(void * tls_ctx,struct tls_connection * conn,const char * label,int server_random_first,u8 * out,size_t out_len)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 
tls_conn_hs_clienthello(struct tls_global * global,struct tls_connection * conn)218 static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
219 					       struct tls_connection *conn)
220 {
221 	DWORD sspi_flags, sspi_flags_out;
222 	SecBufferDesc outbuf;
223 	SecBuffer outbufs[1];
224 	SECURITY_STATUS status;
225 	TimeStamp ts_expiry;
226 
227 	sspi_flags = ISC_REQ_REPLAY_DETECT |
228 		ISC_REQ_CONFIDENTIALITY |
229 		ISC_RET_EXTENDED_ERROR |
230 		ISC_REQ_ALLOCATE_MEMORY |
231 		ISC_REQ_MANUAL_CRED_VALIDATION;
232 
233 	wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
234 
235 	outbufs[0].pvBuffer = NULL;
236 	outbufs[0].BufferType = SECBUFFER_TOKEN;
237 	outbufs[0].cbBuffer = 0;
238 
239 	outbuf.cBuffers = 1;
240 	outbuf.pBuffers = outbufs;
241 	outbuf.ulVersion = SECBUFFER_VERSION;
242 
243 #ifdef UNICODE
244 	status = global->sspi->InitializeSecurityContextW(
245 		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
246 		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
247 		&outbuf, &sspi_flags_out, &ts_expiry);
248 #else /* UNICODE */
249 	status = global->sspi->InitializeSecurityContextA(
250 		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
251 		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
252 		&outbuf, &sspi_flags_out, &ts_expiry);
253 #endif /* UNICODE */
254 	if (status != SEC_I_CONTINUE_NEEDED) {
255 		wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
256 			   "failed - 0x%x",
257 			   __func__, (unsigned int) status);
258 		return NULL;
259 	}
260 
261 	if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
262 		struct wpabuf *buf;
263 		wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
264 			    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
265 		conn->start = 0;
266 		buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
267 					outbufs[0].cbBuffer);
268 		if (buf == NULL)
269 			return NULL;
270 		global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
271 		return buf;
272 	}
273 
274 	wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
275 
276 	return NULL;
277 }
278 
279 
280 #ifndef SECPKG_ATTR_EAP_KEY_BLOCK
281 #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
282 
283 typedef struct _SecPkgContext_EapKeyBlock {
284 	BYTE rgbKeys[128];
285 	BYTE rgbIVs[64];
286 } SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
287 #endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
288 
tls_get_eap(struct tls_global * global,struct tls_connection * conn)289 static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
290 {
291 	SECURITY_STATUS status;
292 	SecPkgContext_EapKeyBlock kb;
293 
294 	/* Note: Windows NT and Windows Me/98/95 do not support getting
295 	 * EapKeyBlock */
296 
297 	status = global->sspi->QueryContextAttributes(
298 		&conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb);
299 	if (status != SEC_E_OK) {
300 		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes("
301 			   "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)",
302 			   __func__, (int) status);
303 		return -1;
304 	}
305 
306 	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys",
307 			kb.rgbKeys, sizeof(kb.rgbKeys));
308 	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
309 			kb.rgbIVs, sizeof(kb.rgbIVs));
310 
311 	os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
312 	conn->eap_tls_prf_set = 1;
313 	return 0;
314 }
315 
316 
tls_connection_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)317 struct wpabuf * tls_connection_handshake(void *tls_ctx,
318 					 struct tls_connection *conn,
319 					 const struct wpabuf *in_data,
320 					 struct wpabuf **appl_data)
321 {
322 	struct tls_global *global = tls_ctx;
323 	DWORD sspi_flags, sspi_flags_out;
324 	SecBufferDesc inbuf, outbuf;
325 	SecBuffer inbufs[2], outbufs[1];
326 	SECURITY_STATUS status;
327 	TimeStamp ts_expiry;
328 	struct wpabuf *out_buf = NULL;
329 
330 	if (appl_data)
331 		*appl_data = NULL;
332 
333 	if (conn->start)
334 		return tls_conn_hs_clienthello(global, conn);
335 
336 	wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
337 		   (int) wpabuf_len(in_data));
338 
339 	sspi_flags = ISC_REQ_REPLAY_DETECT |
340 		ISC_REQ_CONFIDENTIALITY |
341 		ISC_RET_EXTENDED_ERROR |
342 		ISC_REQ_ALLOCATE_MEMORY |
343 		ISC_REQ_MANUAL_CRED_VALIDATION;
344 
345 	/* Input buffer for Schannel */
346 	inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
347 	inbufs[0].cbBuffer = wpabuf_len(in_data);
348 	inbufs[0].BufferType = SECBUFFER_TOKEN;
349 
350 	/* Place for leftover data from Schannel */
351 	inbufs[1].pvBuffer = NULL;
352 	inbufs[1].cbBuffer = 0;
353 	inbufs[1].BufferType = SECBUFFER_EMPTY;
354 
355 	inbuf.cBuffers = 2;
356 	inbuf.pBuffers = inbufs;
357 	inbuf.ulVersion = SECBUFFER_VERSION;
358 
359 	/* Output buffer for Schannel */
360 	outbufs[0].pvBuffer = NULL;
361 	outbufs[0].cbBuffer = 0;
362 	outbufs[0].BufferType = SECBUFFER_TOKEN;
363 
364 	outbuf.cBuffers = 1;
365 	outbuf.pBuffers = outbufs;
366 	outbuf.ulVersion = SECBUFFER_VERSION;
367 
368 #ifdef UNICODE
369 	status = global->sspi->InitializeSecurityContextW(
370 		&conn->creds, &conn->context, NULL, sspi_flags, 0,
371 		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
372 		&outbuf, &sspi_flags_out, &ts_expiry);
373 #else /* UNICODE */
374 	status = global->sspi->InitializeSecurityContextA(
375 		&conn->creds, &conn->context, NULL, sspi_flags, 0,
376 		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
377 		&outbuf, &sspi_flags_out, &ts_expiry);
378 #endif /* UNICODE */
379 
380 	wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> "
381 		   "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
382 		   "intype[1]=%d outlen[0]=%d",
383 		   (int) status, (int) inbufs[0].cbBuffer,
384 		   (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
385 		   (int) inbufs[1].BufferType,
386 		   (int) outbufs[0].cbBuffer);
387 	if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
388 	    (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
389 		if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
390 			wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
391 				    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
392 			out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
393 						    outbufs[0].cbBuffer);
394 			global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
395 			outbufs[0].pvBuffer = NULL;
396 			if (out_buf == NULL)
397 				return NULL;
398 		}
399 	}
400 
401 	switch (status) {
402 	case SEC_E_INCOMPLETE_MESSAGE:
403 		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
404 		break;
405 	case SEC_I_CONTINUE_NEEDED:
406 		wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
407 		break;
408 	case SEC_E_OK:
409 		/* TODO: verify server certificate chain */
410 		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
411 			   "completed successfully");
412 		conn->established = 1;
413 		tls_get_eap(global, conn);
414 
415 		/* Need to return something to get final TLS ACK. */
416 		if (out_buf == NULL)
417 			out_buf = wpabuf_alloc(0);
418 
419 		if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
420 			wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
421 				    "application data",
422 				    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
423 			if (appl_data) {
424 				*appl_data = wpabuf_alloc_copy(
425 					outbufs[1].pvBuffer,
426 					outbufs[1].cbBuffer);
427 			}
428 			global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
429 			inbufs[1].pvBuffer = NULL;
430 		}
431 		break;
432 	case SEC_I_INCOMPLETE_CREDENTIALS:
433 		wpa_printf(MSG_DEBUG,
434 			   "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
435 		break;
436 	case SEC_E_WRONG_PRINCIPAL:
437 		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
438 		break;
439 	case SEC_E_INTERNAL_ERROR:
440 		wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
441 		break;
442 	}
443 
444 	if (FAILED(status)) {
445 		wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
446 			   "(out_buf=%p)", out_buf);
447 		conn->failed++;
448 		global->sspi->DeleteSecurityContext(&conn->context);
449 		return out_buf;
450 	}
451 
452 	if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
453 		/* TODO: Can this happen? What to do with this data? */
454 		wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
455 			    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
456 		global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
457 		inbufs[1].pvBuffer = NULL;
458 	}
459 
460 	return out_buf;
461 }
462 
463 
tls_connection_server_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)464 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
465 						struct tls_connection *conn,
466 						const struct wpabuf *in_data,
467 						struct wpabuf **appl_data)
468 {
469 	return NULL;
470 }
471 
472 
tls_connection_encrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)473 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
474 				       struct tls_connection *conn,
475 				       const struct wpabuf *in_data)
476 {
477 	struct tls_global *global = tls_ctx;
478 	SECURITY_STATUS status;
479 	SecBufferDesc buf;
480 	SecBuffer bufs[4];
481 	SecPkgContext_StreamSizes sizes;
482 	int i;
483 	struct wpabuf *out;
484 
485 	status = global->sspi->QueryContextAttributes(&conn->context,
486 						      SECPKG_ATTR_STREAM_SIZES,
487 						      &sizes);
488 	if (status != SEC_E_OK) {
489 		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
490 			   __func__);
491 		return NULL;
492 	}
493 	wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
494 		   __func__,
495 		   (unsigned int) sizes.cbHeader,
496 		   (unsigned int) sizes.cbTrailer);
497 
498 	out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
499 			   sizes.cbTrailer);
500 
501 	os_memset(&bufs, 0, sizeof(bufs));
502 	bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader);
503 	bufs[0].cbBuffer = sizes.cbHeader;
504 	bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
505 
506 	bufs[1].pvBuffer = wpabuf_put(out, 0);
507 	wpabuf_put_buf(out, in_data);
508 	bufs[1].cbBuffer = wpabuf_len(in_data);
509 	bufs[1].BufferType = SECBUFFER_DATA;
510 
511 	bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
512 	bufs[2].cbBuffer = sizes.cbTrailer;
513 	bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
514 
515 	buf.ulVersion = SECBUFFER_VERSION;
516 	buf.cBuffers = 3;
517 	buf.pBuffers = bufs;
518 
519 	status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
520 
521 	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
522 		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
523 		   "len[2]=%d type[2]=%d",
524 		   (int) status,
525 		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
526 		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
527 		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
528 	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
529 		   "out_data=%p bufs %p %p %p",
530 		   wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer,
531 		   bufs[2].pvBuffer);
532 
533 	for (i = 0; i < 3; i++) {
534 		if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
535 		{
536 			wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
537 				    bufs[i].pvBuffer, bufs[i].cbBuffer);
538 		}
539 	}
540 
541 	if (status == SEC_E_OK) {
542 		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
543 		wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
544 				    "from EncryptMessage", out);
545 		return out;
546 	}
547 
548 	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
549 		   __func__, (int) status);
550 	wpabuf_free(out);
551 	return NULL;
552 }
553 
554 
tls_connection_decrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)555 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
556 				       struct tls_connection *conn,
557 				       const struct wpabuf *in_data)
558 {
559 	struct tls_global *global = tls_ctx;
560 	SECURITY_STATUS status;
561 	SecBufferDesc buf;
562 	SecBuffer bufs[4];
563 	int i;
564 	struct wpabuf *out, *tmp;
565 
566 	wpa_hexdump_buf(MSG_MSGDUMP,
567 			"Schannel: Encrypted data to DecryptMessage", in_data);
568 	os_memset(&bufs, 0, sizeof(bufs));
569 	tmp = wpabuf_dup(in_data);
570 	if (tmp == NULL)
571 		return NULL;
572 	bufs[0].pvBuffer = wpabuf_mhead(tmp);
573 	bufs[0].cbBuffer = wpabuf_len(in_data);
574 	bufs[0].BufferType = SECBUFFER_DATA;
575 
576 	bufs[1].BufferType = SECBUFFER_EMPTY;
577 	bufs[2].BufferType = SECBUFFER_EMPTY;
578 	bufs[3].BufferType = SECBUFFER_EMPTY;
579 
580 	buf.ulVersion = SECBUFFER_VERSION;
581 	buf.cBuffers = 4;
582 	buf.pBuffers = bufs;
583 
584 	status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
585 						    NULL);
586 	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
587 		   "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
588 		   "len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
589 		   (int) status,
590 		   (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
591 		   (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
592 		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
593 		   (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
594 	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
595 		   "out_data=%p bufs %p %p %p %p",
596 		   wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer,
597 		   bufs[2].pvBuffer, bufs[3].pvBuffer);
598 
599 	switch (status) {
600 	case SEC_E_INCOMPLETE_MESSAGE:
601 		wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
602 			   __func__);
603 		break;
604 	case SEC_E_OK:
605 		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
606 		for (i = 0; i < 4; i++) {
607 			if (bufs[i].BufferType == SECBUFFER_DATA)
608 				break;
609 		}
610 		if (i == 4) {
611 			wpa_printf(MSG_DEBUG, "%s: No output data from "
612 				   "DecryptMessage", __func__);
613 			wpabuf_free(tmp);
614 			return NULL;
615 		}
616 		wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
617 				"DecryptMessage",
618 				bufs[i].pvBuffer, bufs[i].cbBuffer);
619 		out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
620 		wpabuf_free(tmp);
621 		return out;
622 	}
623 
624 	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
625 		   __func__, (int) status);
626 	wpabuf_free(tmp);
627 	return NULL;
628 }
629 
630 
tls_connection_resumed(void * ssl_ctx,struct tls_connection * conn)631 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
632 {
633 	return 0;
634 }
635 
636 
tls_connection_set_cipher_list(void * tls_ctx,struct tls_connection * conn,u8 * ciphers)637 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
638 				   u8 *ciphers)
639 {
640 	return -1;
641 }
642 
643 
tls_get_cipher(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)644 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
645 		   char *buf, size_t buflen)
646 {
647 	return -1;
648 }
649 
650 
tls_connection_enable_workaround(void * ssl_ctx,struct tls_connection * conn)651 int tls_connection_enable_workaround(void *ssl_ctx,
652 				     struct tls_connection *conn)
653 {
654 	return 0;
655 }
656 
657 
tls_connection_client_hello_ext(void * ssl_ctx,struct tls_connection * conn,int ext_type,const u8 * data,size_t data_len)658 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
659 				    int ext_type, const u8 *data,
660 				    size_t data_len)
661 {
662 	return -1;
663 }
664 
665 
tls_connection_get_failed(void * ssl_ctx,struct tls_connection * conn)666 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
667 {
668 	if (conn == NULL)
669 		return -1;
670 	return conn->failed;
671 }
672 
673 
tls_connection_get_read_alerts(void * ssl_ctx,struct tls_connection * conn)674 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
675 {
676 	if (conn == NULL)
677 		return -1;
678 	return conn->read_alerts;
679 }
680 
681 
tls_connection_get_write_alerts(void * ssl_ctx,struct tls_connection * conn)682 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
683 {
684 	if (conn == NULL)
685 		return -1;
686 	return conn->write_alerts;
687 }
688 
689 
tls_connection_set_params(void * tls_ctx,struct tls_connection * conn,const struct tls_connection_params * params)690 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
691 			      const struct tls_connection_params *params)
692 {
693 	struct tls_global *global = tls_ctx;
694 	ALG_ID algs[1];
695 	SECURITY_STATUS status;
696 	TimeStamp ts_expiry;
697 
698 	if (conn == NULL)
699 		return -1;
700 
701 	if (global->my_cert_store == NULL &&
702 	    (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
703 	    NULL) {
704 		wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
705 			   __func__, (unsigned int) GetLastError());
706 		return -1;
707 	}
708 
709 	os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
710 	conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
711 	conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
712 	algs[0] = CALG_RSA_KEYX;
713 	conn->schannel_cred.cSupportedAlgs = 1;
714 	conn->schannel_cred.palgSupportedAlgs = algs;
715 	conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
716 #ifdef UNICODE
717 	status = global->sspi->AcquireCredentialsHandleW(
718 		NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
719 		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
720 #else /* UNICODE */
721 	status = global->sspi->AcquireCredentialsHandleA(
722 		NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
723 		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
724 #endif /* UNICODE */
725 	if (status != SEC_E_OK) {
726 		wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
727 			   "0x%x", __func__, (unsigned int) status);
728 		return -1;
729 	}
730 
731 	return 0;
732 }
733 
734 
tls_capabilities(void * tls_ctx)735 unsigned int tls_capabilities(void *tls_ctx)
736 {
737 	return 0;
738 }
739 
740 
tls_connection_set_ia(void * tls_ctx,struct tls_connection * conn,int tls_ia)741 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
742 			  int tls_ia)
743 {
744 	return -1;
745 }
746 
747 
748 struct wpabuf * tls_connection_ia_send_phase_finished(
749 	void *tls_ctx, struct tls_connection *conn, int final);
750 {
751 	return NULL;
752 }
753 
754 
tls_connection_ia_final_phase_finished(void * tls_ctx,struct tls_connection * conn)755 int tls_connection_ia_final_phase_finished(void *tls_ctx,
756 					   struct tls_connection *conn)
757 {
758 	return -1;
759 }
760 
761 
tls_connection_ia_permute_inner_secret(void * tls_ctx,struct tls_connection * conn,const u8 * key,size_t key_len)762 int tls_connection_ia_permute_inner_secret(void *tls_ctx,
763 					   struct tls_connection *conn,
764 					   const u8 *key, size_t key_len)
765 {
766 	return -1;
767 }
768