add place-holder directory for the a3000 wd533c93 scsi controller implementation.
[AROS.git] / workbench / network / WirelessManager / src / crypto / tls_schannel.c
blob4a94e9911982175c5a6bec036060177c69be7cf6
1 /*
2 * SSL/TLS interface functions for Microsoft Schannel
3 * Copyright (c) 2005-2009, 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 struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
219 struct tls_connection *conn)
221 DWORD sspi_flags, sspi_flags_out;
222 SecBufferDesc outbuf;
223 SecBuffer outbufs[1];
224 SECURITY_STATUS status;
225 TimeStamp ts_expiry;
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;
233 wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
235 outbufs[0].pvBuffer = NULL;
236 outbufs[0].BufferType = SECBUFFER_TOKEN;
237 outbufs[0].cbBuffer = 0;
239 outbuf.cBuffers = 1;
240 outbuf.pBuffers = outbufs;
241 outbuf.ulVersion = SECBUFFER_VERSION;
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;
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;
274 wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
276 return NULL;
280 #ifndef SECPKG_ATTR_EAP_KEY_BLOCK
281 #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
283 typedef struct _SecPkgContext_EapKeyBlock {
284 BYTE rgbKeys[128];
285 BYTE rgbIVs[64];
286 } SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
287 #endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
289 static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
291 SECURITY_STATUS status;
292 SecPkgContext_EapKeyBlock kb;
294 /* Note: Windows NT and Windows Me/98/95 do not support getting
295 * EapKeyBlock */
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;
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));
311 os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
312 conn->eap_tls_prf_set = 1;
313 return 0;
317 struct wpabuf * tls_connection_handshake(void *tls_ctx,
318 struct tls_connection *conn,
319 const struct wpabuf *in_data,
320 struct wpabuf **appl_data)
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;
330 if (appl_data)
331 *appl_data = NULL;
333 if (conn->start)
334 return tls_conn_hs_clienthello(global, conn);
336 wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
337 (int) wpabuf_len(in_data));
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;
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;
350 /* Place for leftover data from Schannel */
351 inbufs[1].pvBuffer = NULL;
352 inbufs[1].cbBuffer = 0;
353 inbufs[1].BufferType = SECBUFFER_EMPTY;
355 inbuf.cBuffers = 2;
356 inbuf.pBuffers = inbufs;
357 inbuf.ulVersion = SECBUFFER_VERSION;
359 /* Output buffer for Schannel */
360 outbufs[0].pvBuffer = NULL;
361 outbufs[0].cbBuffer = 0;
362 outbufs[0].BufferType = SECBUFFER_TOKEN;
364 outbuf.cBuffers = 1;
365 outbuf.pBuffers = outbufs;
366 outbuf.ulVersion = SECBUFFER_VERSION;
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 */
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;
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);
415 /* Need to return something to get final TLS ACK. */
416 if (out_buf == NULL)
417 out_buf = wpabuf_alloc(0);
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);
428 global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
429 inbufs[1].pvBuffer = NULL;
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;
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;
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;
460 return out_buf;
464 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
465 struct tls_connection *conn,
466 const struct wpabuf *in_data,
467 struct wpabuf **appl_data)
469 return NULL;
473 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
474 struct tls_connection *conn,
475 const struct wpabuf *in_data)
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;
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;
493 wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
494 __func__,
495 (unsigned int) sizes.cbHeader,
496 (unsigned int) sizes.cbTrailer);
498 out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
499 sizes.cbTrailer);
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;
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;
511 bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
512 bufs[2].cbBuffer = sizes.cbTrailer;
513 bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
515 buf.ulVersion = SECBUFFER_VERSION;
516 buf.cBuffers = 3;
517 buf.pBuffers = bufs;
519 status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
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);
533 for (i = 0; i < 3; i++) {
534 if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
536 wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
537 bufs[i].pvBuffer, bufs[i].cbBuffer);
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;
548 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
549 __func__, (int) status);
550 wpabuf_free(out);
551 return NULL;
555 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
556 struct tls_connection *conn,
557 const struct wpabuf *in_data)
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;
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;
576 bufs[1].BufferType = SECBUFFER_EMPTY;
577 bufs[2].BufferType = SECBUFFER_EMPTY;
578 bufs[3].BufferType = SECBUFFER_EMPTY;
580 buf.ulVersion = SECBUFFER_VERSION;
581 buf.cBuffers = 4;
582 buf.pBuffers = bufs;
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);
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;
610 if (i == 4) {
611 wpa_printf(MSG_DEBUG, "%s: No output data from "
612 "DecryptMessage", __func__);
613 wpabuf_free(tmp);
614 return NULL;
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;
624 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
625 __func__, (int) status);
626 wpabuf_free(tmp);
627 return NULL;
631 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
633 return 0;
637 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
638 u8 *ciphers)
640 return -1;
644 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
645 char *buf, size_t buflen)
647 return -1;
651 int tls_connection_enable_workaround(void *ssl_ctx,
652 struct tls_connection *conn)
654 return 0;
658 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
659 int ext_type, const u8 *data,
660 size_t data_len)
662 return -1;
666 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
668 if (conn == NULL)
669 return -1;
670 return conn->failed;
674 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
676 if (conn == NULL)
677 return -1;
678 return conn->read_alerts;
682 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
684 if (conn == NULL)
685 return -1;
686 return conn->write_alerts;
690 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
691 const struct tls_connection_params *params)
693 struct tls_global *global = tls_ctx;
694 ALG_ID algs[1];
695 SECURITY_STATUS status;
696 TimeStamp ts_expiry;
698 if (conn == NULL)
699 return -1;
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;
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;
731 return 0;
735 unsigned int tls_capabilities(void *tls_ctx)
737 return 0;
741 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
742 int tls_ia)
744 return -1;
748 struct wpabuf * tls_connection_ia_send_phase_finished(
749 void *tls_ctx, struct tls_connection *conn, int final);
751 return NULL;
755 int tls_connection_ia_final_phase_finished(void *tls_ctx,
756 struct tls_connection *conn)
758 return -1;
762 int tls_connection_ia_permute_inner_secret(void *tls_ctx,
763 struct tls_connection *conn,
764 const u8 *key, size_t key_len)
766 return -1;