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
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 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
285typedef struct _SecPkgContext_EapKeyBlock {
286	BYTE rgbKeys[128];
287	BYTE rgbIVs[64];
288} SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
289#endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
290
291static 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
319u8 * 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
473u8 * 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
482int 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
570int 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
651int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
652{
653	return 0;
654}
655
656
657int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
658				   u8 *ciphers)
659{
660	return -1;
661}
662
663
664int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
665		   char *buf, size_t buflen)
666{
667	return -1;
668}
669
670
671int tls_connection_enable_workaround(void *ssl_ctx,
672				     struct tls_connection *conn)
673{
674	return 0;
675}
676
677
678int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
679				    int ext_type, const u8 *data,
680				    size_t data_len)
681{
682	return -1;
683}
684
685
686int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
687{
688	if (conn == NULL)
689		return -1;
690	return conn->failed;
691}
692
693
694int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
695{
696	if (conn == NULL)
697		return -1;
698	return conn->read_alerts;
699}
700
701
702int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
703{
704	if (conn == NULL)
705		return -1;
706	return conn->write_alerts;
707}
708
709
710int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
711			      const struct tls_connection_params *params)
712{
713	struct tls_global *global = tls_ctx;
714	ALG_ID algs[1];
715	SECURITY_STATUS status;
716	TimeStamp ts_expiry;
717
718	if (conn == NULL)
719		return -1;
720
721	if (global->my_cert_store == NULL &&
722	    (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
723	    NULL) {
724		wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
725			   __func__, (unsigned int) GetLastError());
726		return -1;
727	}
728
729	os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
730	conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
731	conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
732	algs[0] = CALG_RSA_KEYX;
733	conn->schannel_cred.cSupportedAlgs = 1;
734	conn->schannel_cred.palgSupportedAlgs = algs;
735	conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
736#ifdef UNICODE
737	status = global->sspi->AcquireCredentialsHandleW(
738		NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
739		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
740#else /* UNICODE */
741	status = global->sspi->AcquireCredentialsHandleA(
742		NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
743		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
744#endif /* UNICODE */
745	if (status != SEC_E_OK) {
746		wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
747			   "0x%x", __func__, (unsigned int) status);
748		return -1;
749	}
750
751	return 0;
752}
753
754
755unsigned int tls_capabilities(void *tls_ctx)
756{
757	return 0;
758}
759
760
761int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
762			  int tls_ia)
763{
764	return -1;
765}
766
767
768int tls_connection_ia_send_phase_finished(void *tls_ctx,
769					  struct tls_connection *conn,
770					  int final,
771					  u8 *out_data, size_t out_len)
772{
773	return -1;
774}
775
776
777int tls_connection_ia_final_phase_finished(void *tls_ctx,
778					   struct tls_connection *conn)
779{
780	return -1;
781}
782
783
784int tls_connection_ia_permute_inner_secret(void *tls_ctx,
785					   struct tls_connection *conn,
786					   const u8 *key, size_t key_len)
787{
788	return -1;
789}
790