1 /* 2 * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel 3 * Copyright (c) 2005, Jouni Malinen <j (at) w1.fi> 4 * 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. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 /* 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) 21 */ 22 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> 30 31 #include "common.h" 32 #include "tls.h" 33 34 35 struct tls_global { 36 HMODULE hsecurity; 37 PSecurityFunctionTable sspi; 38 HCERTSTORE my_cert_store; 39 }; 40 41 struct tls_connection { 42 int established, start; 43 int failed, read_alerts, write_alerts; 44 45 SCHANNEL_CRED schannel_cred; 46 CredHandle creds; 47 CtxtHandle context; 48 49 u8 eap_tls_prf[128]; 50 int eap_tls_prf_set; 51 }; 52 53 54 static int schannel_load_lib(struct tls_global *global) 55 { 56 INIT_SECURITY_INTERFACE pInitSecurityInterface; 57 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; 63 } 64 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; 74 } 75 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; 84 } 85 86 return 0; 87 } 88 89 90 void * tls_init(const struct tls_config *conf) 91 { 92 struct tls_global *global; 93 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; 100 } 101 return global; 102 } 103 104 105 void tls_deinit(void *ssl_ctx) 106 { 107 struct tls_global *global = ssl_ctx; 108 109 if (global->my_cert_store) 110 CertCloseStore(global->my_cert_store, 0); 111 FreeLibrary(global->hsecurity); 112 os_free(global); 113 } 114 115 116 int tls_get_errors(void *ssl_ctx) 117 { 118 return 0; 119 } 120 121 122 struct tls_connection * tls_connection_init(void *ssl_ctx) 123 { 124 struct tls_connection *conn; 125 126 conn = os_zalloc(sizeof(*conn)); 127 if (conn == NULL) 128 return NULL; 129 conn->start = 1; 130 131 return conn; 132 } 133 134 135 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) 136 { 137 if (conn == NULL) 138 return; 139 140 os_free(conn); 141 } 142 143 144 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) 145 { 146 return conn ? conn->established : 0; 147 } 148 149 150 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) 151 { 152 struct tls_global *global = ssl_ctx; 153 if (conn == NULL) 154 return -1; 155 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? */ 161 162 return 0; 163 } 164 165 166 int tls_global_set_params(void *tls_ctx, 167 const struct tls_connection_params *params) 168 { 169 return -1; 170 } 171 172 173 int tls_global_set_verify(void *ssl_ctx, int check_crl) 174 { 175 return -1; 176 } 177 178 179 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, 180 int verify_peer) 181 { 182 return -1; 183 } 184 185 186 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, 187 struct tls_keys *keys) 188 { 189 /* Schannel does not export master secret or client/server random. */ 190 return -1; 191 } 192 193 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) 197 { 198 /* 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.. 205 */ 206 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; 211 212 os_memcpy(out, conn->eap_tls_prf, out_len); 213 214 return 0; 215 } 216 217 218 static u8 * tls_conn_hs_clienthello(struct tls_global *global, 219 struct tls_connection *conn, 220 size_t *out_len) 221 { 222 DWORD sspi_flags, sspi_flags_out; 223 SecBufferDesc outbuf; 224 SecBuffer outbufs[1]; 225 SECURITY_STATUS status; 226 TimeStamp ts_expiry; 227 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; 233 234 wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__); 235 236 outbufs[0].pvBuffer = NULL; 237 outbufs[0].BufferType = SECBUFFER_TOKEN; 238 outbufs[0].cbBuffer = 0; 239 240 outbuf.cBuffers = 1; 241 outbuf.pBuffers = outbufs; 242 outbuf.ulVersion = SECBUFFER_VERSION; 243 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; 260 } 261 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; 274 } 275 276 wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello"); 277 278 return NULL; 279 } 280 281 282 #ifndef SECPKG_ATTR_EAP_KEY_BLOCK 283 #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b 284 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 */ 290 291 static int tls_get_eap(struct tls_global *global, struct tls_connection *conn) 292 { 293 SECURITY_STATUS status; 294 SecPkgContext_EapKeyBlock kb; 295 296 /* Note: Windows NT and Windows Me/98/95 do not support getting 297 * EapKeyBlock */ 298 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; 306 } 307 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)); 312 313 os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys)); 314 conn->eap_tls_prf_set = 1; 315 return 0; 316 } 317 318 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) 323 { 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; 331 332 if (appl_data) 333 *appl_data = NULL; 334 335 if (conn->start) { 336 return tls_conn_hs_clienthello(global, conn, out_len); 337 } 338 339 wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process", 340 in_len); 341 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; 347 348 /* Input buffer for Schannel */ 349 inbufs[0].pvBuffer = (u8 *) in_data; 350 inbufs[0].cbBuffer = in_len; 351 inbufs[0].BufferType = SECBUFFER_TOKEN; 352 353 /* Place for leftover data from Schannel */ 354 inbufs[1].pvBuffer = NULL; 355 inbufs[1].cbBuffer = 0; 356 inbufs[1].BufferType = SECBUFFER_EMPTY; 357 358 inbuf.cBuffers = 2; 359 inbuf.pBuffers = inbufs; 360 inbuf.ulVersion = SECBUFFER_VERSION; 361 362 /* Output buffer for Schannel */ 363 outbufs[0].pvBuffer = NULL; 364 outbufs[0].cbBuffer = 0; 365 outbufs[0].BufferType = SECBUFFER_TOKEN; 366 367 outbuf.cBuffers = 1; 368 outbuf.pBuffers = outbufs; 369 outbuf.ulVersion = SECBUFFER_VERSION; 370 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 */ 382 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; 404 } 405 } 406 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); 420 421 /* Need to return something to get final TLS ACK. */ 422 if (out_buf == NULL) 423 out_buf = os_malloc(1); 424 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); 436 } 437 global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); 438 inbufs[1].pvBuffer = NULL; 439 } 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; 451 } 452 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; 459 } 460 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; 467 } 468 469 return out_buf; 470 } 471 472 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) 477 { 478 return NULL; 479 } 480 481 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) 485 { 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; 493 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; 501 } 502 wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u", 503 __func__, 504 (unsigned int) sizes.cbHeader, 505 (unsigned int) sizes.cbTrailer); 506 507 total_len = sizes.cbHeader + in_len + sizes.cbTrailer; 508 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; 515 } 516 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; 521 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; 526 527 bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len; 528 bufs[2].cbBuffer = sizes.cbTrailer; 529 bufs[2].BufferType = SECBUFFER_STREAM_TRAILER; 530 531 buf.ulVersion = SECBUFFER_VERSION; 532 buf.cBuffers = 3; 533 buf.pBuffers = bufs; 534 535 status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0); 536 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); 548 549 for (i = 0; i < 3; i++) { 550 if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY) 551 { 552 wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs", 553 bufs[i].pvBuffer, bufs[i].cbBuffer); 554 } 555 } 556 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; 562 } 563 564 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", 565 __func__, (int) status); 566 return -1; 567 } 568 569 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) 573 { 574 struct tls_global *global = ssl_ctx; 575 SECURITY_STATUS status; 576 SecBufferDesc buf; 577 SecBuffer bufs[4]; 578 int i; 579 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; 584 } 585 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; 593 594 bufs[1].BufferType = SECBUFFER_EMPTY; 595 bufs[2].BufferType = SECBUFFER_EMPTY; 596 bufs[3].BufferType = SECBUFFER_EMPTY; 597 598 buf.ulVersion = SECBUFFER_VERSION; 599 buf.cBuffers = 4; 600 buf.pBuffers = bufs; 601 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); 616 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; 627 } 628 if (i == 4) { 629 wpa_printf(MSG_DEBUG, "%s: No output data from " 630 "DecryptMessage", __func__); 631 return -1; 632 } 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; 640 } 641 os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer); 642 return bufs[i].cbBuffer; 643 } 644 645 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", 646 __func__, (int) status); 647 return -1; 648 } 649 650 651 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) 652 { 653 return 0; 654 } 655 656 657 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 658 u8 *ciphers) 659 { 660 return -1; 661 } 662 663 664 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, 665 char *buf, size_t buflen) 666 { 667 return -1; 668 } 669 670 671 int tls_connection_enable_workaround(void *ssl_ctx, 672 struct tls_connection *conn) 673 { 674 return 0; 675 } 676 677 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) 681 { 682 return -1; 683 } 684 685 686 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) 687 { 688 if (conn == NULL) 689 return -1; 690 return conn->failed; 691 } 692 693 694 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) 695 { 696 if (conn == NULL) 697 return -1; 698 return conn->read_alerts; 699 } 700 701 702 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) 703 { 704 if (conn == NULL) 705 return -1; 706 return conn->write_alerts; 707 } 708 709 710 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 711 const struct tls_connection_params *params) 712 { 713 struct tls_global *global = tls_ctx; 714 ALG_ID algs[1]; 715 SECURITY_STATUS status; 716 TimeStamp ts_expiry; 717 718 if (conn == NULL) 719 return -1; 720 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; 727 } 728 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; 749 } 750 751 return 0; 752 } 753 754 755 unsigned int tls_capabilities(void *tls_ctx) 756 { 757 return 0; 758 } 759 760 761 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, 762 int tls_ia) 763 { 764 return -1; 765 } 766 767 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) 772 { 773 return -1; 774 } 775 776 777 int tls_connection_ia_final_phase_finished(void *tls_ctx, 778 struct tls_connection *conn) 779 { 780 return -1; 781 } 782 783 784 int tls_connection_ia_permute_inner_secret(void *tls_ctx, 785 struct tls_connection *conn, 786 const u8 *key, size_t key_len) 787 { 788 return -1; 789 } 790