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