1/* 2 * SSL/TLS interface functions for Microsoft Schannel 3 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 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 212static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global, 213 struct tls_connection *conn) 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) { 256 struct wpabuf *buf; 257 wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello", 258 outbufs[0].pvBuffer, outbufs[0].cbBuffer); 259 conn->start = 0; 260 buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, 261 outbufs[0].cbBuffer); 262 if (buf == NULL) 263 return NULL; 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 311struct wpabuf * tls_connection_handshake(void *tls_ctx, 312 struct tls_connection *conn, 313 const struct wpabuf *in_data, 314 struct wpabuf **appl_data) 315{ 316 struct tls_global *global = tls_ctx; 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; 322 struct wpabuf *out_buf = NULL; 323 324 if (appl_data) 325 *appl_data = NULL; 326 327 if (conn->start) 328 return tls_conn_hs_clienthello(global, conn); 329 330 wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process", 331 (int) wpabuf_len(in_data)); 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 */ 340 inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data); 341 inbufs[0].cbBuffer = wpabuf_len(in_data); 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); 386 out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, 387 outbufs[0].cbBuffer); 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) 411 out_buf = wpabuf_alloc(0); 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) { 418 *appl_data = wpabuf_alloc_copy( 419 outbufs[1].pvBuffer, 420 outbufs[1].cbBuffer); 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 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) 462{ 463 return NULL; 464} 465 466 467struct wpabuf * tls_connection_encrypt(void *tls_ctx, 468 struct tls_connection *conn, 469 const struct wpabuf *in_data) 470{ 471 struct tls_global *global = tls_ctx; 472 SECURITY_STATUS status; 473 SecBufferDesc buf; 474 SecBuffer bufs[4]; 475 SecPkgContext_StreamSizes sizes; 476 int i; 477 struct wpabuf *out; 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__); 485 return NULL; 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 492 out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) + 493 sizes.cbTrailer); 494 495 os_memset(&bufs, 0, sizeof(bufs)); 496 bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader); 497 bufs[0].cbBuffer = sizes.cbHeader; 498 bufs[0].BufferType = SECBUFFER_STREAM_HEADER; 499 500 bufs[1].pvBuffer = wpabuf_put(out, 0); 501 wpabuf_put_buf(out, in_data); 502 bufs[1].cbBuffer = wpabuf_len(in_data); 503 bufs[1].BufferType = SECBUFFER_DATA; 504 505 bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer); 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", 524 wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer, 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__); 537 wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data " 538 "from EncryptMessage", out); 539 return out; 540 } 541 542 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", 543 __func__, (int) status); 544 wpabuf_free(out); 545 return NULL; 546} 547 548 549struct wpabuf * tls_connection_decrypt(void *tls_ctx, 550 struct tls_connection *conn, 551 const struct wpabuf *in_data) 552{ 553 struct tls_global *global = tls_ctx; 554 SECURITY_STATUS status; 555 SecBufferDesc buf; 556 SecBuffer bufs[4]; 557 int i; 558 struct wpabuf *out, *tmp; 559 560 wpa_hexdump_buf(MSG_MSGDUMP, 561 "Schannel: Encrypted data to DecryptMessage", in_data); 562 os_memset(&bufs, 0, sizeof(bufs)); 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); 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", 590 wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer, 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__); 607 wpabuf_free(tmp); 608 return NULL; 609 } 610 wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from " 611 "DecryptMessage", 612 bufs[i].pvBuffer, bufs[i].cbBuffer); 613 out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer); 614 wpabuf_free(tmp); 615 return out; 616 } 617 618 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", 619 __func__, (int) status); 620 wpabuf_free(tmp); 621 return NULL; 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} 733