Re-enable hardware UDP/TCP checksum calculation with pseudo header on
[dragonfly/port-amd64.git] / contrib / wpa_supplicant-0.4.9 / tls_schannel.c
blobd06a1c34b41a25f751a4a9708f618a687d9de05a
1 /*
2 * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
3 * Copyright (c) 2005, Jouni Malinen <jkmaline@cc.hut.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 <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <windows.h>
27 #include <wincrypt.h>
28 #include <schannel.h>
29 #define SECURITY_WIN32
30 #include <security.h>
31 #include <sspi.h>
33 #include "common.h"
34 #include "tls.h"
37 struct tls_global {
38 HMODULE hsecurity;
39 PSecurityFunctionTable sspi;
40 HCERTSTORE my_cert_store;
43 struct tls_connection {
44 int established, start;
45 int failed, read_alerts, write_alerts;
47 SCHANNEL_CRED schannel_cred;
48 CredHandle creds;
49 CtxtHandle context;
51 u8 eap_tls_prf[128];
52 int eap_tls_prf_set;
56 static int schannel_load_lib(struct tls_global *global)
58 INIT_SECURITY_INTERFACE pInitSecurityInterface;
60 global->hsecurity = LoadLibrary("Secur32.dll");
61 if (global->hsecurity == NULL) {
62 wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x",
63 __func__, (unsigned int) GetLastError());
64 return -1;
67 pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(
68 global->hsecurity, "InitSecurityInterfaceA");
69 if (pInitSecurityInterface == NULL) {
70 wpa_printf(MSG_ERROR, "%s: Could not find "
71 "InitSecurityInterfaceA from Secur32.dll",
72 __func__);
73 FreeLibrary(global->hsecurity);
74 global->hsecurity = NULL;
75 return -1;
78 global->sspi = pInitSecurityInterface();
79 if (global->sspi == NULL) {
80 wpa_printf(MSG_ERROR, "%s: Could not read security "
81 "interface - 0x%x",
82 __func__, (unsigned int) GetLastError());
83 FreeLibrary(global->hsecurity);
84 global->hsecurity = NULL;
85 return -1;
88 return 0;
92 void * tls_init(const struct tls_config *conf)
94 struct tls_global *global;
96 global = malloc(sizeof(*global));
97 if (global == NULL)
98 return NULL;
99 memset(global, 0, sizeof(*global));
100 if (schannel_load_lib(global)) {
101 free(global);
102 return NULL;
104 return global;
108 void tls_deinit(void *ssl_ctx)
110 struct tls_global *global = ssl_ctx;
112 if (global->my_cert_store)
113 CertCloseStore(global->my_cert_store, 0);
114 FreeLibrary(global->hsecurity);
115 free(global);
119 int tls_get_errors(void *ssl_ctx)
121 return 0;
125 struct tls_connection * tls_connection_init(void *ssl_ctx)
127 struct tls_connection *conn;
129 conn = malloc(sizeof(*conn));
130 if (conn == NULL)
131 return NULL;
132 memset(conn, 0, sizeof(*conn));
133 conn->start = 1;
135 return conn;
139 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
141 if (conn == NULL)
142 return;
144 free(conn);
148 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
150 return conn ? conn->established : 0;
154 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
156 struct tls_global *global = ssl_ctx;
157 if (conn == NULL)
158 return -1;
160 conn->eap_tls_prf_set = 0;
161 conn->established = conn->failed = 0;
162 conn->read_alerts = conn->write_alerts = 0;
163 global->sspi->DeleteSecurityContext(&conn->context);
164 /* FIX: what else needs to be reseted? */
166 return 0;
170 int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert)
172 return -1;
176 int tls_global_set_verify(void *ssl_ctx, int check_crl)
178 return -1;
182 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
183 int verify_peer)
185 return -1;
189 int tls_global_client_cert(void *_ssl_ctx, const char *client_cert)
191 return -1;
195 int tls_global_private_key(void *_ssl_ctx, const char *private_key,
196 const char *private_key_passwd)
198 return -1;
202 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
203 struct tls_keys *keys)
205 if (conn == NULL || keys == NULL || !conn->eap_tls_prf_set)
206 return -1;
208 memset(keys, 0, sizeof(*keys));
211 * Cannot get master_key from Schannel, but EapKeyBlock can be used to
212 * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and
213 * EAP-TTLS cannot use this, though, since they are using different
214 * labels. The only option could be to implement TLSv1 completely here
215 * and just use Schannel or CryptoAPI for low-level crypto
216 * functionality..
218 keys->eap_tls_prf = conn->eap_tls_prf;
219 keys->eap_tls_prf_len = sizeof(conn->eap_tls_prf);
221 return 0;
225 static u8 * tls_conn_hs_clienthello(struct tls_global *global,
226 struct tls_connection *conn,
227 size_t *out_len)
229 DWORD sspi_flags, sspi_flags_out;
230 SecBufferDesc outbuf;
231 SecBuffer outbufs[1];
232 SECURITY_STATUS status;
233 TimeStamp ts_expiry;
235 sspi_flags = ISC_REQ_REPLAY_DETECT |
236 ISC_REQ_CONFIDENTIALITY |
237 ISC_RET_EXTENDED_ERROR |
238 ISC_REQ_ALLOCATE_MEMORY |
239 ISC_REQ_MANUAL_CRED_VALIDATION;
241 wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
243 outbufs[0].pvBuffer = NULL;
244 outbufs[0].BufferType = SECBUFFER_TOKEN;
245 outbufs[0].cbBuffer = 0;
247 outbuf.cBuffers = 1;
248 outbuf.pBuffers = outbufs;
249 outbuf.ulVersion = SECBUFFER_VERSION;
251 status = global->sspi->InitializeSecurityContextA(
252 &conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
253 SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
254 &outbuf, &sspi_flags_out, &ts_expiry);
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 = malloc(*out_len);
269 if (buf == NULL)
270 return NULL;
271 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 memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
314 conn->eap_tls_prf_set = 1;
318 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
319 const u8 *in_data, size_t in_len,
320 size_t *out_len)
322 struct tls_global *global = ssl_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 u8 *out_buf = NULL;
330 if (conn->start) {
331 return tls_conn_hs_clienthello(global, conn, out_len);
334 wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
335 in_len);
337 sspi_flags = ISC_REQ_REPLAY_DETECT |
338 ISC_REQ_CONFIDENTIALITY |
339 ISC_RET_EXTENDED_ERROR |
340 ISC_REQ_ALLOCATE_MEMORY |
341 ISC_REQ_MANUAL_CRED_VALIDATION;
343 /* Input buffer for Schannel */
344 inbufs[0].pvBuffer = (u8 *) in_data;
345 inbufs[0].cbBuffer = in_len;
346 inbufs[0].BufferType = SECBUFFER_TOKEN;
348 /* Place for leftover data from Schannel */
349 inbufs[1].pvBuffer = NULL;
350 inbufs[1].cbBuffer = 0;
351 inbufs[1].BufferType = SECBUFFER_EMPTY;
353 inbuf.cBuffers = 2;
354 inbuf.pBuffers = inbufs;
355 inbuf.ulVersion = SECBUFFER_VERSION;
357 /* Output buffer for Schannel */
358 outbufs[0].pvBuffer = NULL;
359 outbufs[0].cbBuffer = 0;
360 outbufs[0].BufferType = SECBUFFER_TOKEN;
362 outbuf.cBuffers = 1;
363 outbuf.pBuffers = outbufs;
364 outbuf.ulVersion = SECBUFFER_VERSION;
366 status = global->sspi->InitializeSecurityContextA(
367 &conn->creds, &conn->context, NULL, sspi_flags, 0,
368 SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
369 &outbuf, &sspi_flags_out, &ts_expiry);
371 wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContextA -> "
372 "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
373 "intype[1]=%d outlen[0]=%d",
374 (int) status, (int) inbufs[0].cbBuffer,
375 (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
376 (int) inbufs[1].BufferType,
377 (int) outbufs[0].cbBuffer);
378 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
379 (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
380 if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
381 wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
382 outbufs[0].pvBuffer, outbufs[0].cbBuffer);
383 *out_len = outbufs[0].cbBuffer;
384 out_buf = malloc(*out_len);
385 if (out_buf == NULL)
386 return NULL;
387 memcpy(out_buf, outbufs[0].pvBuffer, *out_len);
388 global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
389 outbufs[0].pvBuffer = NULL;
393 switch (status) {
394 case SEC_E_INCOMPLETE_MESSAGE:
395 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
396 break;
397 case SEC_I_CONTINUE_NEEDED:
398 wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
399 break;
400 case SEC_E_OK:
401 /* TODO: verify server certificate chain */
402 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
403 "completed successfully");
404 conn->established = 1;
405 tls_get_eap(global, conn);
407 /* Need to return something to get final TLS ACK. */
408 if (out_buf == NULL)
409 out_buf = malloc(1);
411 if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
412 wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
413 "application data",
414 inbufs[1].pvBuffer, inbufs[1].cbBuffer);
415 /* FIX: need to fix TLS API to allow this data to be
416 * passed to the caller */
417 global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
418 inbufs[1].pvBuffer = NULL;
420 break;
421 case SEC_I_INCOMPLETE_CREDENTIALS:
422 wpa_printf(MSG_DEBUG,
423 "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
424 break;
425 case SEC_E_WRONG_PRINCIPAL:
426 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
427 break;
428 case SEC_E_INTERNAL_ERROR:
429 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
430 break;
433 if (FAILED(status)) {
434 wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
435 "(out_buf=%p)", out_buf);
436 conn->failed++;
437 global->sspi->DeleteSecurityContext(&conn->context);
438 return out_buf;
441 if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
442 /* TODO: Can this happen? What to do with this data? */
443 wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
444 inbufs[1].pvBuffer, inbufs[1].cbBuffer);
445 global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
446 inbufs[1].pvBuffer = NULL;
449 return out_buf;
453 u8 * tls_connection_server_handshake(void *ssl_ctx,
454 struct tls_connection *conn,
455 const u8 *in_data, size_t in_len,
456 size_t *out_len)
458 return NULL;
462 int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
463 const u8 *in_data, size_t in_len,
464 u8 *out_data, size_t out_len)
466 struct tls_global *global = ssl_ctx;
467 SECURITY_STATUS status;
468 SecBufferDesc buf;
469 SecBuffer bufs[4];
470 SecPkgContext_StreamSizes sizes;
471 int i;
472 size_t total_len;
474 status = global->sspi->QueryContextAttributes(&conn->context,
475 SECPKG_ATTR_STREAM_SIZES,
476 &sizes);
477 if (status != SEC_E_OK) {
478 wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
479 __func__);
480 return -1;
482 wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
483 __func__,
484 (unsigned int) sizes.cbHeader,
485 (unsigned int) sizes.cbTrailer);
487 total_len = sizes.cbHeader + in_len + sizes.cbTrailer;
489 if (out_len < total_len) {
490 wpa_printf(MSG_DEBUG, "%s: too short out_data (out_len=%lu "
491 "in_len=%lu total_len=%lu)", __func__,
492 (unsigned long) out_len, (unsigned long) in_len,
493 (unsigned long) total_len);
494 return -1;
497 memset(&bufs, 0, sizeof(bufs));
498 bufs[0].pvBuffer = out_data;
499 bufs[0].cbBuffer = sizes.cbHeader;
500 bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
502 memcpy(out_data + sizes.cbHeader, in_data, in_len);
503 bufs[1].pvBuffer = out_data + sizes.cbHeader;
504 bufs[1].cbBuffer = in_len;
505 bufs[1].BufferType = SECBUFFER_DATA;
507 bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len;
508 bufs[2].cbBuffer = sizes.cbTrailer;
509 bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
511 buf.ulVersion = SECBUFFER_VERSION;
512 buf.cBuffers = 3;
513 buf.pBuffers = bufs;
515 status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
517 wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
518 "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
519 "len[2]=%d type[2]=%d",
520 (int) status,
521 (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
522 (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
523 (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
524 wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
525 "out_data=%p bufs %p %p %p",
526 out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
527 bufs[2].pvBuffer);
529 for (i = 0; i < 3; i++) {
530 if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
532 wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
533 bufs[i].pvBuffer, bufs[i].cbBuffer);
537 if (status == SEC_E_OK) {
538 wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
539 wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Encrypted data from "
540 "EncryptMessage", out_data, total_len);
541 return total_len;
544 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
545 __func__, (int) status);
546 return -1;
550 int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
551 const u8 *in_data, size_t in_len,
552 u8 *out_data, size_t out_len)
554 struct tls_global *global = ssl_ctx;
555 SECURITY_STATUS status;
556 SecBufferDesc buf;
557 SecBuffer bufs[4];
558 int i;
560 if (out_len < in_len) {
561 wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__,
562 (unsigned long) out_len, (unsigned long) in_len);
563 return -1;
566 wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage",
567 in_data, in_len);
568 memset(&bufs, 0, sizeof(bufs));
569 memcpy(out_data, in_data, in_len);
570 bufs[0].pvBuffer = out_data;
571 bufs[0].cbBuffer = in_len;
572 bufs[0].BufferType = SECBUFFER_DATA;
574 bufs[1].BufferType = SECBUFFER_EMPTY;
575 bufs[2].BufferType = SECBUFFER_EMPTY;
576 bufs[3].BufferType = SECBUFFER_EMPTY;
578 buf.ulVersion = SECBUFFER_VERSION;
579 buf.cBuffers = 4;
580 buf.pBuffers = bufs;
582 status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
583 NULL);
584 wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
585 "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
586 "len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
587 (int) status,
588 (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
589 (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
590 (int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
591 (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
592 wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
593 "out_data=%p bufs %p %p %p %p",
594 out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
595 bufs[2].pvBuffer, bufs[3].pvBuffer);
597 switch (status) {
598 case SEC_E_INCOMPLETE_MESSAGE:
599 wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
600 __func__);
601 break;
602 case SEC_E_OK:
603 wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
604 for (i = 0; i < 4; i++) {
605 if (bufs[i].BufferType == SECBUFFER_DATA)
606 break;
608 if (i == 4) {
609 wpa_printf(MSG_DEBUG, "%s: No output data from "
610 "DecryptMessage", __func__);
611 return -1;
613 wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
614 "DecryptMessage",
615 bufs[i].pvBuffer, bufs[i].cbBuffer);
616 if (bufs[i].cbBuffer > out_len) {
617 wpa_printf(MSG_DEBUG, "%s: Too long output data",
618 __func__);
619 return -1;
621 memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
622 return bufs[i].cbBuffer;
625 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
626 __func__, (int) status);
627 return -1;
631 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
633 return 0;
637 #ifdef EAP_FAST
638 int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
639 const u8 *key, size_t key_len)
641 return -1;
643 #endif /* EAP_FAST */
646 int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn)
648 return -1;
652 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
653 char *buf, size_t buflen)
655 return -1;
659 int tls_connection_enable_workaround(void *ssl_ctx,
660 struct tls_connection *conn)
662 return 0;
666 #ifdef EAP_FAST
667 /* ClientHello TLS extensions require a patch to openssl, so this function is
668 * commented out unless explicitly needed for EAP-FAST in order to be able to
669 * build this file with unmodified openssl. */
670 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
671 int ext_type, const u8 *data,
672 size_t data_len)
674 return -1;
676 #endif /* EAP_FAST */
679 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
681 if (conn == NULL)
682 return -1;
683 return conn->failed;
687 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
689 if (conn == NULL)
690 return -1;
691 return conn->read_alerts;
695 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
697 if (conn == NULL)
698 return -1;
699 return conn->write_alerts;
703 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
704 const struct tls_connection_params *params)
706 struct tls_global *global = tls_ctx;
707 ALG_ID algs[1];
708 SECURITY_STATUS status;
709 TimeStamp ts_expiry;
711 if (conn == NULL)
712 return -1;
714 if (global->my_cert_store == NULL &&
715 (global->my_cert_store = CertOpenSystemStore(0, "MY")) == NULL) {
716 wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
717 __func__, (unsigned int) GetLastError());
718 return -1;
721 memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
722 conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
723 conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
724 algs[0] = CALG_RSA_KEYX;
725 conn->schannel_cred.cSupportedAlgs = 1;
726 conn->schannel_cred.palgSupportedAlgs = algs;
727 conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
728 status = global->sspi->AcquireCredentialsHandleA(
729 NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
730 &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
731 if (status != SEC_E_OK) {
732 wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
733 "0x%x", __func__, (unsigned int) status);
734 return -1;
737 return 0;