hostapd: Update vendor branch to 0.6.10
[dragonfly.git] / contrib / hostapd / src / crypto / tls_schannel.c
blob87e74353dcf9c2f762c0eb68dc97b26c8d3d0046
1 /*
2 * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
3 * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
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)
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>
31 #include "common.h"
32 #include "tls.h"
35 struct tls_global {
36 HMODULE hsecurity;
37 PSecurityFunctionTable sspi;
38 HCERTSTORE my_cert_store;
41 struct tls_connection {
42 int established, start;
43 int failed, read_alerts, write_alerts;
45 SCHANNEL_CRED schannel_cred;
46 CredHandle creds;
47 CtxtHandle context;
49 u8 eap_tls_prf[128];
50 int eap_tls_prf_set;
54 static int schannel_load_lib(struct tls_global *global)
56 INIT_SECURITY_INTERFACE pInitSecurityInterface;
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;
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;
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;
86 return 0;
90 void * tls_init(const struct tls_config *conf)
92 struct tls_global *global;
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;
101 return global;
105 void tls_deinit(void *ssl_ctx)
107 struct tls_global *global = ssl_ctx;
109 if (global->my_cert_store)
110 CertCloseStore(global->my_cert_store, 0);
111 FreeLibrary(global->hsecurity);
112 os_free(global);
116 int tls_get_errors(void *ssl_ctx)
118 return 0;
122 struct tls_connection * tls_connection_init(void *ssl_ctx)
124 struct tls_connection *conn;
126 conn = os_zalloc(sizeof(*conn));
127 if (conn == NULL)
128 return NULL;
129 conn->start = 1;
131 return conn;
135 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
137 if (conn == NULL)
138 return;
140 os_free(conn);
144 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
146 return conn ? conn->established : 0;
150 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
152 struct tls_global *global = ssl_ctx;
153 if (conn == NULL)
154 return -1;
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? */
162 return 0;
166 int tls_global_set_params(void *tls_ctx,
167 const struct tls_connection_params *params)
169 return -1;
173 int tls_global_set_verify(void *ssl_ctx, int check_crl)
175 return -1;
179 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
180 int verify_peer)
182 return -1;
186 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
187 struct tls_keys *keys)
189 /* Schannel does not export master secret or client/server random. */
190 return -1;
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)
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..
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;
212 os_memcpy(out, conn->eap_tls_prf, out_len);
214 return 0;
218 static u8 * tls_conn_hs_clienthello(struct tls_global *global,
219 struct tls_connection *conn,
220 size_t *out_len)
222 DWORD sspi_flags, sspi_flags_out;
223 SecBufferDesc outbuf;
224 SecBuffer outbufs[1];
225 SECURITY_STATUS status;
226 TimeStamp ts_expiry;
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;
234 wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
236 outbufs[0].pvBuffer = NULL;
237 outbufs[0].BufferType = SECBUFFER_TOKEN;
238 outbufs[0].cbBuffer = 0;
240 outbuf.cBuffers = 1;
241 outbuf.pBuffers = outbufs;
242 outbuf.ulVersion = SECBUFFER_VERSION;
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;
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;
276 wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
278 return NULL;
282 #ifndef SECPKG_ATTR_EAP_KEY_BLOCK
283 #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
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 */
291 static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
293 SECURITY_STATUS status;
294 SecPkgContext_EapKeyBlock kb;
296 /* Note: Windows NT and Windows Me/98/95 do not support getting
297 * EapKeyBlock */
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;
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));
313 os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
314 conn->eap_tls_prf_set = 1;
315 return 0;
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)
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;
332 if (appl_data)
333 *appl_data = NULL;
335 if (conn->start) {
336 return tls_conn_hs_clienthello(global, conn, out_len);
339 wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
340 in_len);
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;
348 /* Input buffer for Schannel */
349 inbufs[0].pvBuffer = (u8 *) in_data;
350 inbufs[0].cbBuffer = in_len;
351 inbufs[0].BufferType = SECBUFFER_TOKEN;
353 /* Place for leftover data from Schannel */
354 inbufs[1].pvBuffer = NULL;
355 inbufs[1].cbBuffer = 0;
356 inbufs[1].BufferType = SECBUFFER_EMPTY;
358 inbuf.cBuffers = 2;
359 inbuf.pBuffers = inbufs;
360 inbuf.ulVersion = SECBUFFER_VERSION;
362 /* Output buffer for Schannel */
363 outbufs[0].pvBuffer = NULL;
364 outbufs[0].cbBuffer = 0;
365 outbufs[0].BufferType = SECBUFFER_TOKEN;
367 outbuf.cBuffers = 1;
368 outbuf.pBuffers = outbufs;
369 outbuf.ulVersion = SECBUFFER_VERSION;
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 */
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;
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);
421 /* Need to return something to get final TLS ACK. */
422 if (out_buf == NULL)
423 out_buf = os_malloc(1);
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);
437 global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
438 inbufs[1].pvBuffer = NULL;
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;
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;
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;
469 return out_buf;
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)
478 return NULL;
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)
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;
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;
502 wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
503 __func__,
504 (unsigned int) sizes.cbHeader,
505 (unsigned int) sizes.cbTrailer);
507 total_len = sizes.cbHeader + in_len + sizes.cbTrailer;
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;
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;
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;
527 bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len;
528 bufs[2].cbBuffer = sizes.cbTrailer;
529 bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
531 buf.ulVersion = SECBUFFER_VERSION;
532 buf.cBuffers = 3;
533 buf.pBuffers = bufs;
535 status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
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);
549 for (i = 0; i < 3; i++) {
550 if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
552 wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
553 bufs[i].pvBuffer, bufs[i].cbBuffer);
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;
564 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
565 __func__, (int) status);
566 return -1;
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)
574 struct tls_global *global = ssl_ctx;
575 SECURITY_STATUS status;
576 SecBufferDesc buf;
577 SecBuffer bufs[4];
578 int i;
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;
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;
594 bufs[1].BufferType = SECBUFFER_EMPTY;
595 bufs[2].BufferType = SECBUFFER_EMPTY;
596 bufs[3].BufferType = SECBUFFER_EMPTY;
598 buf.ulVersion = SECBUFFER_VERSION;
599 buf.cBuffers = 4;
600 buf.pBuffers = bufs;
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);
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;
628 if (i == 4) {
629 wpa_printf(MSG_DEBUG, "%s: No output data from "
630 "DecryptMessage", __func__);
631 return -1;
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;
641 os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
642 return bufs[i].cbBuffer;
645 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
646 __func__, (int) status);
647 return -1;
651 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
653 return 0;
657 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
658 u8 *ciphers)
660 return -1;
664 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
665 char *buf, size_t buflen)
667 return -1;
671 int tls_connection_enable_workaround(void *ssl_ctx,
672 struct tls_connection *conn)
674 return 0;
678 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
679 int ext_type, const u8 *data,
680 size_t data_len)
682 return -1;
686 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
688 if (conn == NULL)
689 return -1;
690 return conn->failed;
694 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
696 if (conn == NULL)
697 return -1;
698 return conn->read_alerts;
702 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
704 if (conn == NULL)
705 return -1;
706 return conn->write_alerts;
710 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
711 const struct tls_connection_params *params)
713 struct tls_global *global = tls_ctx;
714 ALG_ID algs[1];
715 SECURITY_STATUS status;
716 TimeStamp ts_expiry;
718 if (conn == NULL)
719 return -1;
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;
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;
751 return 0;
755 unsigned int tls_capabilities(void *tls_ctx)
757 return 0;
761 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
762 int tls_ia)
764 return -1;
768 int 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)
773 return -1;
777 int tls_connection_ia_final_phase_finished(void *tls_ctx,
778 struct tls_connection *conn)
780 return -1;
784 int tls_connection_ia_permute_inner_secret(void *tls_ctx,
785 struct tls_connection *conn,
786 const u8 *key, size_t key_len)
788 return -1;