• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
3  * Copyright (c) 2005, 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,size_t * out_len)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 
tls_get_eap(struct tls_global * global,struct tls_connection * conn)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 
tls_connection_handshake(void * ssl_ctx,struct tls_connection * conn,const u8 * in_data,size_t in_len,size_t * out_len,u8 ** appl_data,size_t * appl_data_len)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 
tls_connection_server_handshake(void * ssl_ctx,struct tls_connection * conn,const u8 * in_data,size_t in_len,size_t * out_len)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 
tls_connection_encrypt(void * ssl_ctx,struct tls_connection * conn,const u8 * in_data,size_t in_len,u8 * out_data,size_t out_len)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 
tls_connection_decrypt(void * ssl_ctx,struct tls_connection * conn,const u8 * in_data,size_t in_len,u8 * out_data,size_t out_len)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 
tls_connection_resumed(void * ssl_ctx,struct tls_connection * conn)651 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
652 {
653 	return 0;
654 }
655 
656 
tls_connection_set_master_key(void * ssl_ctx,struct tls_connection * conn,const u8 * key,size_t key_len)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 
tls_connection_set_cipher_list(void * tls_ctx,struct tls_connection * conn,u8 * ciphers)664 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
665 				   u8 *ciphers)
666 {
667 	return -1;
668 }
669 
670 
tls_get_cipher(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)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 
tls_connection_enable_workaround(void * ssl_ctx,struct tls_connection * conn)678 int tls_connection_enable_workaround(void *ssl_ctx,
679 				     struct tls_connection *conn)
680 {
681 	return 0;
682 }
683 
684 
tls_connection_client_hello_ext(void * ssl_ctx,struct tls_connection * conn,int ext_type,const u8 * data,size_t data_len)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 
tls_connection_get_failed(void * ssl_ctx,struct tls_connection * conn)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 
tls_connection_get_read_alerts(void * ssl_ctx,struct tls_connection * conn)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 
tls_connection_get_write_alerts(void * ssl_ctx,struct tls_connection * conn)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 
tls_connection_set_params(void * tls_ctx,struct tls_connection * conn,const struct tls_connection_params * params)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 
tls_capabilities(void * tls_ctx)762 unsigned int tls_capabilities(void *tls_ctx)
763 {
764 	return 0;
765 }
766 
767 
tls_connection_set_ia(void * tls_ctx,struct tls_connection * conn,int tls_ia)768 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
769 			  int tls_ia)
770 {
771 	return -1;
772 }
773 
774 
tls_connection_ia_send_phase_finished(void * tls_ctx,struct tls_connection * conn,int final,u8 * out_data,size_t out_len)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 
tls_connection_ia_final_phase_finished(void * tls_ctx,struct tls_connection * conn)784 int tls_connection_ia_final_phase_finished(void *tls_ctx,
785 					   struct tls_connection *conn)
786 {
787 	return -1;
788 }
789 
790 
tls_connection_ia_permute_inner_secret(void * tls_ctx,struct tls_connection * conn,const u8 * key,size_t key_len)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