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
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)
27 #define SECURITY_WIN32
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
;
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());
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",
71 FreeLibrary(global
->hsecurity
);
72 global
->hsecurity
= NULL
;
76 global
->sspi
= pInitSecurityInterface();
77 if (global
->sspi
== NULL
) {
78 wpa_printf(MSG_ERROR
, "%s: Could not read security "
80 __func__
, (unsigned int) GetLastError());
81 FreeLibrary(global
->hsecurity
);
82 global
->hsecurity
= NULL
;
90 void * tls_init(const struct tls_config
*conf
)
92 struct tls_global
*global
;
94 global
= os_zalloc(sizeof(*global
));
97 if (schannel_load_lib(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
);
116 int tls_get_errors(void *ssl_ctx
)
122 struct tls_connection
* tls_connection_init(void *ssl_ctx
)
124 struct tls_connection
*conn
;
126 conn
= os_zalloc(sizeof(*conn
));
135 void tls_connection_deinit(void *ssl_ctx
, struct tls_connection
*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
;
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? */
166 int tls_global_set_params(void *tls_ctx
,
167 const struct tls_connection_params
*params
)
173 int tls_global_set_verify(void *ssl_ctx
, int check_crl
)
179 int tls_connection_set_verify(void *ssl_ctx
, struct tls_connection
*conn
,
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. */
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
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
))
212 os_memcpy(out
, conn
->eap_tls_prf
, out_len
);
218 static u8
* tls_conn_hs_clienthello(struct tls_global
*global
,
219 struct tls_connection
*conn
,
222 DWORD sspi_flags
, sspi_flags_out
;
223 SecBufferDesc outbuf
;
224 SecBuffer outbufs
[1];
225 SECURITY_STATUS status
;
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;
241 outbuf
.pBuffers
= outbufs
;
242 outbuf
.ulVersion
= SECBUFFER_VERSION
;
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
);
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
);
255 if (status
!= SEC_I_CONTINUE_NEEDED
) {
256 wpa_printf(MSG_ERROR
, "%s: InitializeSecurityContextA "
258 __func__
, (unsigned int) status
);
262 if (outbufs
[0].cbBuffer
!= 0 && outbufs
[0].pvBuffer
) {
264 wpa_hexdump(MSG_MSGDUMP
, "SChannel - ClientHello",
265 outbufs
[0].pvBuffer
, outbufs
[0].cbBuffer
);
267 *out_len
= outbufs
[0].cbBuffer
;
268 buf
= os_malloc(*out_len
);
271 os_memcpy(buf
, outbufs
[0].pvBuffer
, *out_len
);
272 global
->sspi
->FreeContextBuffer(outbufs
[0].pvBuffer
);
276 wpa_printf(MSG_ERROR
, "SChannel: Failed to generate ClientHello");
282 #ifndef SECPKG_ATTR_EAP_KEY_BLOCK
283 #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
285 typedef struct _SecPkgContext_EapKeyBlock
{
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
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
);
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;
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
;
336 return tls_conn_hs_clienthello(global
, conn
, out_len
);
339 wpa_printf(MSG_DEBUG
, "SChannel: %d bytes handshake data to process",
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
;
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
;
368 outbuf
.pBuffers
= outbufs
;
369 outbuf
.ulVersion
= SECBUFFER_VERSION
;
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
);
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
);
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
);
398 os_memcpy(out_buf
, outbufs
[0].pvBuffer
,
400 global
->sspi
->FreeContextBuffer(outbufs
[0].pvBuffer
);
401 outbufs
[0].pvBuffer
= NULL
;
408 case SEC_E_INCOMPLETE_MESSAGE
:
409 wpa_printf(MSG_DEBUG
, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
411 case SEC_I_CONTINUE_NEEDED
:
412 wpa_printf(MSG_DEBUG
, "Schannel: SEC_I_CONTINUE_NEEDED");
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. */
423 out_buf
= os_malloc(1);
425 if (inbufs
[1].BufferType
== SECBUFFER_EXTRA
) {
426 wpa_hexdump(MSG_MSGDUMP
, "SChannel - Encrypted "
428 inbufs
[1].pvBuffer
, inbufs
[1].cbBuffer
);
430 *appl_data_len
= outbufs
[1].cbBuffer
;
431 appl_data
= os_malloc(*appl_data_len
);
437 global
->sspi
->FreeContextBuffer(inbufs
[1].pvBuffer
);
438 inbufs
[1].pvBuffer
= NULL
;
441 case SEC_I_INCOMPLETE_CREDENTIALS
:
442 wpa_printf(MSG_DEBUG
,
443 "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
445 case SEC_E_WRONG_PRINCIPAL
:
446 wpa_printf(MSG_DEBUG
, "Schannel: SEC_E_WRONG_PRINCIPAL");
448 case SEC_E_INTERNAL_ERROR
:
449 wpa_printf(MSG_DEBUG
, "Schannel: SEC_E_INTERNAL_ERROR");
453 if (FAILED(status
)) {
454 wpa_printf(MSG_DEBUG
, "Schannel: Handshake failed "
455 "(out_buf=%p)", out_buf
);
457 global
->sspi
->DeleteSecurityContext(&conn
->context
);
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
;
473 u8
* tls_connection_server_handshake(void *ssl_ctx
,
474 struct tls_connection
*conn
,
475 const u8
*in_data
, size_t in_len
,
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
;
490 SecPkgContext_StreamSizes sizes
;
494 status
= global
->sspi
->QueryContextAttributes(&conn
->context
,
495 SECPKG_ATTR_STREAM_SIZES
,
497 if (status
!= SEC_E_OK
) {
498 wpa_printf(MSG_DEBUG
, "%s: QueryContextAttributes failed",
502 wpa_printf(MSG_DEBUG
, "%s: Stream sizes: header=%u trailer=%u",
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
);
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
;
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",
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
,
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
);
564 wpa_printf(MSG_DEBUG
, "%s: Failed - status=%d",
565 __func__
, (int) status
);
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
;
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
);
586 wpa_hexdump(MSG_MSGDUMP
, "Schannel: Encrypted data to DecryptMessage",
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
;
602 status
= global
->sspi
->DecryptMessage(&conn
->context
, &buf
, 0,
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",
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
);
618 case SEC_E_INCOMPLETE_MESSAGE
:
619 wpa_printf(MSG_DEBUG
, "%s: SEC_E_INCOMPLETE_MESSAGE",
623 wpa_printf(MSG_DEBUG
, "%s: SEC_E_OK", __func__
);
624 for (i
= 0; i
< 4; i
++) {
625 if (bufs
[i
].BufferType
== SECBUFFER_DATA
)
629 wpa_printf(MSG_DEBUG
, "%s: No output data from "
630 "DecryptMessage", __func__
);
633 wpa_hexdump_key(MSG_MSGDUMP
, "Schannel: Decrypted data from "
635 bufs
[i
].pvBuffer
, bufs
[i
].cbBuffer
);
636 if (bufs
[i
].cbBuffer
> out_len
) {
637 wpa_printf(MSG_DEBUG
, "%s: Too long output data",
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
);
651 int tls_connection_resumed(void *ssl_ctx
, struct tls_connection
*conn
)
657 int tls_connection_set_master_key(void *ssl_ctx
, struct tls_connection
*conn
,
658 const u8
*key
, size_t key_len
)
664 int tls_connection_set_cipher_list(void *tls_ctx
, struct tls_connection
*conn
,
671 int tls_get_cipher(void *ssl_ctx
, struct tls_connection
*conn
,
672 char *buf
, size_t buflen
)
678 int tls_connection_enable_workaround(void *ssl_ctx
,
679 struct tls_connection
*conn
)
685 int tls_connection_client_hello_ext(void *ssl_ctx
, struct tls_connection
*conn
,
686 int ext_type
, const u8
*data
,
693 int tls_connection_get_failed(void *ssl_ctx
, struct tls_connection
*conn
)
701 int tls_connection_get_read_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
705 return conn
->read_alerts
;
709 int tls_connection_get_write_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
713 return conn
->write_alerts
;
717 int tls_connection_set_params(void *tls_ctx
, struct tls_connection
*conn
,
718 const struct tls_connection_params
*params
)
720 struct tls_global
*global
= tls_ctx
;
722 SECURITY_STATUS status
;
728 if (global
->my_cert_store
== NULL
&&
729 (global
->my_cert_store
= CertOpenSystemStore(0, TEXT("MY"))) ==
731 wpa_printf(MSG_ERROR
, "%s: CertOpenSystemStore failed - 0x%x",
732 __func__
, (unsigned int) GetLastError());
736 os_memset(&conn
->schannel_cred
, 0, sizeof(conn
->schannel_cred
));
737 conn
->schannel_cred
.dwVersion
= SCHANNEL_CRED_VERSION
;
738 conn
->schannel_cred
.grbitEnabledProtocols
= SP_PROT_TLS1
;
739 algs
[0] = CALG_RSA_KEYX
;
740 conn
->schannel_cred
.cSupportedAlgs
= 1;
741 conn
->schannel_cred
.palgSupportedAlgs
= algs
;
742 conn
->schannel_cred
.dwFlags
|= SCH_CRED_NO_DEFAULT_CREDS
;
744 status
= global
->sspi
->AcquireCredentialsHandleW(
745 NULL
, UNISP_NAME_W
, SECPKG_CRED_OUTBOUND
, NULL
,
746 &conn
->schannel_cred
, NULL
, NULL
, &conn
->creds
, &ts_expiry
);
748 status
= global
->sspi
->AcquireCredentialsHandleA(
749 NULL
, UNISP_NAME_A
, SECPKG_CRED_OUTBOUND
, NULL
,
750 &conn
->schannel_cred
, NULL
, NULL
, &conn
->creds
, &ts_expiry
);
752 if (status
!= SEC_E_OK
) {
753 wpa_printf(MSG_DEBUG
, "%s: AcquireCredentialsHandleA failed - "
754 "0x%x", __func__
, (unsigned int) status
);
762 unsigned int tls_capabilities(void *tls_ctx
)
768 int tls_connection_set_ia(void *tls_ctx
, struct tls_connection
*conn
,
775 int tls_connection_ia_send_phase_finished(void *tls_ctx
,
776 struct tls_connection
*conn
,
778 u8
*out_data
, size_t out_len
)
784 int tls_connection_ia_final_phase_finished(void *tls_ctx
,
785 struct tls_connection
*conn
)
791 int tls_connection_ia_permute_inner_secret(void *tls_ctx
,
792 struct tls_connection
*conn
,
793 const u8
*key
, size_t key_len
)