tls_schannel.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
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
35struct tls_global {
36	HMODULE hsecurity;
37	PSecurityFunctionTable sspi;
38	HCERTSTORE my_cert_store;
39};
40
41struct 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
54static 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
90void * 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
105void 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
116int tls_get_errors(void *ssl_ctx)
117{
118	return 0;
119}
120
121
122struct 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
135void 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
144int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
145{
146	return conn ? conn->established : 0;
147}
148
149
150int 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
166int tls_global_set_params(void *tls_ctx,
167			  const struct tls_connection_params *params)
168{
169	return -1;
170}
171
172
173int tls_global_set_verify(void *ssl_ctx, int check_crl)
174{
175	return -1;
176}
177
178
179int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
180			      int verify_peer)
181{
182	return -1;
183}
184
185
186int 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
194int 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
218static 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
283typedef struct _SecPkgContext_EapKeyBlock {
284	BYTE rgbKeys[128];
285	BYTE rgbIVs[64];
286} SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
287#endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
288
289static 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
317struct 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
464struct 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
473struct 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
555struct 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
631int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
632{
633	return 0;
634}
635
636
637int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
638				   u8 *ciphers)
639{
640	return -1;
641}
642
643
644int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
645		   char *buf, size_t buflen)
646{
647	return -1;
648}
649
650
651int tls_connection_enable_workaround(void *ssl_ctx,
652				     struct tls_connection *conn)
653{
654	return 0;
655}
656
657
658int 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
666int 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
674int 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
682int 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
690int 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
735unsigned int tls_capabilities(void *tls_ctx)
736{
737	return 0;
738}
739