$search
00001 /* 00002 * SSL/TLS interface functions for Microsoft Schannel 00003 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 /* 00016 * FIX: Go through all SSPI functions and verify what needs to be freed 00017 * FIX: session resumption 00018 * TODO: add support for server cert chain validation 00019 * TODO: add support for CA cert validation 00020 * TODO: add support for EAP-TLS (client cert/key conf) 00021 */ 00022 00023 #include "includes.h" 00024 #include <windows.h> 00025 #include <wincrypt.h> 00026 #include <schannel.h> 00027 #define SECURITY_WIN32 00028 #include <security.h> 00029 #include <sspi.h> 00030 00031 #include "common.h" 00032 #include "tls.h" 00033 00034 00035 struct tls_global { 00036 HMODULE hsecurity; 00037 PSecurityFunctionTable sspi; 00038 HCERTSTORE my_cert_store; 00039 }; 00040 00041 struct tls_connection { 00042 int established, start; 00043 int failed, read_alerts, write_alerts; 00044 00045 SCHANNEL_CRED schannel_cred; 00046 CredHandle creds; 00047 CtxtHandle context; 00048 00049 u8 eap_tls_prf[128]; 00050 int eap_tls_prf_set; 00051 }; 00052 00053 00054 static int schannel_load_lib(struct tls_global *global) 00055 { 00056 INIT_SECURITY_INTERFACE pInitSecurityInterface; 00057 00058 global->hsecurity = LoadLibrary(TEXT("Secur32.dll")); 00059 if (global->hsecurity == NULL) { 00060 wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x", 00061 __func__, (unsigned int) GetLastError()); 00062 return -1; 00063 } 00064 00065 pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress( 00066 global->hsecurity, "InitSecurityInterfaceA"); 00067 if (pInitSecurityInterface == NULL) { 00068 wpa_printf(MSG_ERROR, "%s: Could not find " 00069 "InitSecurityInterfaceA from Secur32.dll", 00070 __func__); 00071 FreeLibrary(global->hsecurity); 00072 global->hsecurity = NULL; 00073 return -1; 00074 } 00075 00076 global->sspi = pInitSecurityInterface(); 00077 if (global->sspi == NULL) { 00078 wpa_printf(MSG_ERROR, "%s: Could not read security " 00079 "interface - 0x%x", 00080 __func__, (unsigned int) GetLastError()); 00081 FreeLibrary(global->hsecurity); 00082 global->hsecurity = NULL; 00083 return -1; 00084 } 00085 00086 return 0; 00087 } 00088 00089 00090 void * tls_init(const struct tls_config *conf) 00091 { 00092 struct tls_global *global; 00093 00094 global = os_zalloc(sizeof(*global)); 00095 if (global == NULL) 00096 return NULL; 00097 if (schannel_load_lib(global)) { 00098 os_free(global); 00099 return NULL; 00100 } 00101 return global; 00102 } 00103 00104 00105 void tls_deinit(void *ssl_ctx) 00106 { 00107 struct tls_global *global = ssl_ctx; 00108 00109 if (global->my_cert_store) 00110 CertCloseStore(global->my_cert_store, 0); 00111 FreeLibrary(global->hsecurity); 00112 os_free(global); 00113 } 00114 00115 00116 int tls_get_errors(void *ssl_ctx) 00117 { 00118 return 0; 00119 } 00120 00121 00122 struct tls_connection * tls_connection_init(void *ssl_ctx) 00123 { 00124 struct tls_connection *conn; 00125 00126 conn = os_zalloc(sizeof(*conn)); 00127 if (conn == NULL) 00128 return NULL; 00129 conn->start = 1; 00130 00131 return conn; 00132 } 00133 00134 00135 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) 00136 { 00137 if (conn == NULL) 00138 return; 00139 00140 os_free(conn); 00141 } 00142 00143 00144 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) 00145 { 00146 return conn ? conn->established : 0; 00147 } 00148 00149 00150 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) 00151 { 00152 struct tls_global *global = ssl_ctx; 00153 if (conn == NULL) 00154 return -1; 00155 00156 conn->eap_tls_prf_set = 0; 00157 conn->established = conn->failed = 0; 00158 conn->read_alerts = conn->write_alerts = 0; 00159 global->sspi->DeleteSecurityContext(&conn->context); 00160 /* FIX: what else needs to be reseted? */ 00161 00162 return 0; 00163 } 00164 00165 00166 int tls_global_set_params(void *tls_ctx, 00167 const struct tls_connection_params *params) 00168 { 00169 return -1; 00170 } 00171 00172 00173 int tls_global_set_verify(void *ssl_ctx, int check_crl) 00174 { 00175 return -1; 00176 } 00177 00178 00179 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, 00180 int verify_peer) 00181 { 00182 return -1; 00183 } 00184 00185 00186 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, 00187 struct tls_keys *keys) 00188 { 00189 /* Schannel does not export master secret or client/server random. */ 00190 return -1; 00191 } 00192 00193 00194 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 00195 const char *label, int server_random_first, 00196 u8 *out, size_t out_len) 00197 { 00198 /* 00199 * Cannot get master_key from Schannel, but EapKeyBlock can be used to 00200 * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and 00201 * EAP-TTLS cannot use this, though, since they are using different 00202 * labels. The only option could be to implement TLSv1 completely here 00203 * and just use Schannel or CryptoAPI for low-level crypto 00204 * functionality.. 00205 */ 00206 00207 if (conn == NULL || !conn->eap_tls_prf_set || server_random_first || 00208 os_strcmp(label, "client EAP encryption") != 0 || 00209 out_len > sizeof(conn->eap_tls_prf)) 00210 return -1; 00211 00212 os_memcpy(out, conn->eap_tls_prf, out_len); 00213 00214 return 0; 00215 } 00216 00217 00218 static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global, 00219 struct tls_connection *conn) 00220 { 00221 DWORD sspi_flags, sspi_flags_out; 00222 SecBufferDesc outbuf; 00223 SecBuffer outbufs[1]; 00224 SECURITY_STATUS status; 00225 TimeStamp ts_expiry; 00226 00227 sspi_flags = ISC_REQ_REPLAY_DETECT | 00228 ISC_REQ_CONFIDENTIALITY | 00229 ISC_RET_EXTENDED_ERROR | 00230 ISC_REQ_ALLOCATE_MEMORY | 00231 ISC_REQ_MANUAL_CRED_VALIDATION; 00232 00233 wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__); 00234 00235 outbufs[0].pvBuffer = NULL; 00236 outbufs[0].BufferType = SECBUFFER_TOKEN; 00237 outbufs[0].cbBuffer = 0; 00238 00239 outbuf.cBuffers = 1; 00240 outbuf.pBuffers = outbufs; 00241 outbuf.ulVersion = SECBUFFER_VERSION; 00242 00243 #ifdef UNICODE 00244 status = global->sspi->InitializeSecurityContextW( 00245 &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, 00246 SECURITY_NATIVE_DREP, NULL, 0, &conn->context, 00247 &outbuf, &sspi_flags_out, &ts_expiry); 00248 #else /* UNICODE */ 00249 status = global->sspi->InitializeSecurityContextA( 00250 &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, 00251 SECURITY_NATIVE_DREP, NULL, 0, &conn->context, 00252 &outbuf, &sspi_flags_out, &ts_expiry); 00253 #endif /* UNICODE */ 00254 if (status != SEC_I_CONTINUE_NEEDED) { 00255 wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA " 00256 "failed - 0x%x", 00257 __func__, (unsigned int) status); 00258 return NULL; 00259 } 00260 00261 if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { 00262 struct wpabuf *buf; 00263 wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello", 00264 outbufs[0].pvBuffer, outbufs[0].cbBuffer); 00265 conn->start = 0; 00266 buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, 00267 outbufs[0].cbBuffer); 00268 if (buf == NULL) 00269 return NULL; 00270 global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); 00271 return buf; 00272 } 00273 00274 wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello"); 00275 00276 return NULL; 00277 } 00278 00279 00280 #ifndef SECPKG_ATTR_EAP_KEY_BLOCK 00281 #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b 00282 00283 typedef struct _SecPkgContext_EapKeyBlock { 00284 BYTE rgbKeys[128]; 00285 BYTE rgbIVs[64]; 00286 } SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock; 00287 #endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */ 00288 00289 static int tls_get_eap(struct tls_global *global, struct tls_connection *conn) 00290 { 00291 SECURITY_STATUS status; 00292 SecPkgContext_EapKeyBlock kb; 00293 00294 /* Note: Windows NT and Windows Me/98/95 do not support getting 00295 * EapKeyBlock */ 00296 00297 status = global->sspi->QueryContextAttributes( 00298 &conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb); 00299 if (status != SEC_E_OK) { 00300 wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes(" 00301 "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)", 00302 __func__, (int) status); 00303 return -1; 00304 } 00305 00306 wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys", 00307 kb.rgbKeys, sizeof(kb.rgbKeys)); 00308 wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs", 00309 kb.rgbIVs, sizeof(kb.rgbIVs)); 00310 00311 os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys)); 00312 conn->eap_tls_prf_set = 1; 00313 return 0; 00314 } 00315 00316 00317 struct wpabuf * tls_connection_handshake(void *tls_ctx, 00318 struct tls_connection *conn, 00319 const struct wpabuf *in_data, 00320 struct wpabuf **appl_data) 00321 { 00322 struct tls_global *global = tls_ctx; 00323 DWORD sspi_flags, sspi_flags_out; 00324 SecBufferDesc inbuf, outbuf; 00325 SecBuffer inbufs[2], outbufs[1]; 00326 SECURITY_STATUS status; 00327 TimeStamp ts_expiry; 00328 struct wpabuf *out_buf = NULL; 00329 00330 if (appl_data) 00331 *appl_data = NULL; 00332 00333 if (conn->start) 00334 return tls_conn_hs_clienthello(global, conn); 00335 00336 wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process", 00337 (int) wpabuf_len(in_data)); 00338 00339 sspi_flags = ISC_REQ_REPLAY_DETECT | 00340 ISC_REQ_CONFIDENTIALITY | 00341 ISC_RET_EXTENDED_ERROR | 00342 ISC_REQ_ALLOCATE_MEMORY | 00343 ISC_REQ_MANUAL_CRED_VALIDATION; 00344 00345 /* Input buffer for Schannel */ 00346 inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data); 00347 inbufs[0].cbBuffer = wpabuf_len(in_data); 00348 inbufs[0].BufferType = SECBUFFER_TOKEN; 00349 00350 /* Place for leftover data from Schannel */ 00351 inbufs[1].pvBuffer = NULL; 00352 inbufs[1].cbBuffer = 0; 00353 inbufs[1].BufferType = SECBUFFER_EMPTY; 00354 00355 inbuf.cBuffers = 2; 00356 inbuf.pBuffers = inbufs; 00357 inbuf.ulVersion = SECBUFFER_VERSION; 00358 00359 /* Output buffer for Schannel */ 00360 outbufs[0].pvBuffer = NULL; 00361 outbufs[0].cbBuffer = 0; 00362 outbufs[0].BufferType = SECBUFFER_TOKEN; 00363 00364 outbuf.cBuffers = 1; 00365 outbuf.pBuffers = outbufs; 00366 outbuf.ulVersion = SECBUFFER_VERSION; 00367 00368 #ifdef UNICODE 00369 status = global->sspi->InitializeSecurityContextW( 00370 &conn->creds, &conn->context, NULL, sspi_flags, 0, 00371 SECURITY_NATIVE_DREP, &inbuf, 0, NULL, 00372 &outbuf, &sspi_flags_out, &ts_expiry); 00373 #else /* UNICODE */ 00374 status = global->sspi->InitializeSecurityContextA( 00375 &conn->creds, &conn->context, NULL, sspi_flags, 0, 00376 SECURITY_NATIVE_DREP, &inbuf, 0, NULL, 00377 &outbuf, &sspi_flags_out, &ts_expiry); 00378 #endif /* UNICODE */ 00379 00380 wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> " 00381 "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d " 00382 "intype[1]=%d outlen[0]=%d", 00383 (int) status, (int) inbufs[0].cbBuffer, 00384 (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer, 00385 (int) inbufs[1].BufferType, 00386 (int) outbufs[0].cbBuffer); 00387 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED || 00388 (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) { 00389 if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { 00390 wpa_hexdump(MSG_MSGDUMP, "SChannel - output", 00391 outbufs[0].pvBuffer, outbufs[0].cbBuffer); 00392 out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, 00393 outbufs[0].cbBuffer); 00394 global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); 00395 outbufs[0].pvBuffer = NULL; 00396 if (out_buf == NULL) 00397 return NULL; 00398 } 00399 } 00400 00401 switch (status) { 00402 case SEC_E_INCOMPLETE_MESSAGE: 00403 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE"); 00404 break; 00405 case SEC_I_CONTINUE_NEEDED: 00406 wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED"); 00407 break; 00408 case SEC_E_OK: 00409 /* TODO: verify server certificate chain */ 00410 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake " 00411 "completed successfully"); 00412 conn->established = 1; 00413 tls_get_eap(global, conn); 00414 00415 /* Need to return something to get final TLS ACK. */ 00416 if (out_buf == NULL) 00417 out_buf = wpabuf_alloc(0); 00418 00419 if (inbufs[1].BufferType == SECBUFFER_EXTRA) { 00420 wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted " 00421 "application data", 00422 inbufs[1].pvBuffer, inbufs[1].cbBuffer); 00423 if (appl_data) { 00424 *appl_data = wpabuf_alloc_copy( 00425 outbufs[1].pvBuffer, 00426 outbufs[1].cbBuffer); 00427 } 00428 global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); 00429 inbufs[1].pvBuffer = NULL; 00430 } 00431 break; 00432 case SEC_I_INCOMPLETE_CREDENTIALS: 00433 wpa_printf(MSG_DEBUG, 00434 "Schannel: SEC_I_INCOMPLETE_CREDENTIALS"); 00435 break; 00436 case SEC_E_WRONG_PRINCIPAL: 00437 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL"); 00438 break; 00439 case SEC_E_INTERNAL_ERROR: 00440 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR"); 00441 break; 00442 } 00443 00444 if (FAILED(status)) { 00445 wpa_printf(MSG_DEBUG, "Schannel: Handshake failed " 00446 "(out_buf=%p)", out_buf); 00447 conn->failed++; 00448 global->sspi->DeleteSecurityContext(&conn->context); 00449 return out_buf; 00450 } 00451 00452 if (inbufs[1].BufferType == SECBUFFER_EXTRA) { 00453 /* TODO: Can this happen? What to do with this data? */ 00454 wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data", 00455 inbufs[1].pvBuffer, inbufs[1].cbBuffer); 00456 global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); 00457 inbufs[1].pvBuffer = NULL; 00458 } 00459 00460 return out_buf; 00461 } 00462 00463 00464 struct wpabuf * tls_connection_server_handshake(void *tls_ctx, 00465 struct tls_connection *conn, 00466 const struct wpabuf *in_data, 00467 struct wpabuf **appl_data) 00468 { 00469 return NULL; 00470 } 00471 00472 00473 struct wpabuf * tls_connection_encrypt(void *tls_ctx, 00474 struct tls_connection *conn, 00475 const struct wpabuf *in_data) 00476 { 00477 struct tls_global *global = tls_ctx; 00478 SECURITY_STATUS status; 00479 SecBufferDesc buf; 00480 SecBuffer bufs[4]; 00481 SecPkgContext_StreamSizes sizes; 00482 int i; 00483 struct wpabuf *out; 00484 00485 status = global->sspi->QueryContextAttributes(&conn->context, 00486 SECPKG_ATTR_STREAM_SIZES, 00487 &sizes); 00488 if (status != SEC_E_OK) { 00489 wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed", 00490 __func__); 00491 return NULL; 00492 } 00493 wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u", 00494 __func__, 00495 (unsigned int) sizes.cbHeader, 00496 (unsigned int) sizes.cbTrailer); 00497 00498 out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) + 00499 sizes.cbTrailer); 00500 00501 os_memset(&bufs, 0, sizeof(bufs)); 00502 bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader); 00503 bufs[0].cbBuffer = sizes.cbHeader; 00504 bufs[0].BufferType = SECBUFFER_STREAM_HEADER; 00505 00506 bufs[1].pvBuffer = wpabuf_put(out, 0); 00507 wpabuf_put_buf(out, in_data); 00508 bufs[1].cbBuffer = wpabuf_len(in_data); 00509 bufs[1].BufferType = SECBUFFER_DATA; 00510 00511 bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer); 00512 bufs[2].cbBuffer = sizes.cbTrailer; 00513 bufs[2].BufferType = SECBUFFER_STREAM_TRAILER; 00514 00515 buf.ulVersion = SECBUFFER_VERSION; 00516 buf.cBuffers = 3; 00517 buf.pBuffers = bufs; 00518 00519 status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0); 00520 00521 wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> " 00522 "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " 00523 "len[2]=%d type[2]=%d", 00524 (int) status, 00525 (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, 00526 (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, 00527 (int) bufs[2].cbBuffer, (int) bufs[2].BufferType); 00528 wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: " 00529 "out_data=%p bufs %p %p %p", 00530 wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer, 00531 bufs[2].pvBuffer); 00532 00533 for (i = 0; i < 3; i++) { 00534 if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY) 00535 { 00536 wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs", 00537 bufs[i].pvBuffer, bufs[i].cbBuffer); 00538 } 00539 } 00540 00541 if (status == SEC_E_OK) { 00542 wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); 00543 wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data " 00544 "from EncryptMessage", out); 00545 return out; 00546 } 00547 00548 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", 00549 __func__, (int) status); 00550 wpabuf_free(out); 00551 return NULL; 00552 } 00553 00554 00555 struct wpabuf * tls_connection_decrypt(void *tls_ctx, 00556 struct tls_connection *conn, 00557 const struct wpabuf *in_data) 00558 { 00559 struct tls_global *global = tls_ctx; 00560 SECURITY_STATUS status; 00561 SecBufferDesc buf; 00562 SecBuffer bufs[4]; 00563 int i; 00564 struct wpabuf *out, *tmp; 00565 00566 wpa_hexdump_buf(MSG_MSGDUMP, 00567 "Schannel: Encrypted data to DecryptMessage", in_data); 00568 os_memset(&bufs, 0, sizeof(bufs)); 00569 tmp = wpabuf_dup(in_data); 00570 if (tmp == NULL) 00571 return NULL; 00572 bufs[0].pvBuffer = wpabuf_mhead(tmp); 00573 bufs[0].cbBuffer = wpabuf_len(in_data); 00574 bufs[0].BufferType = SECBUFFER_DATA; 00575 00576 bufs[1].BufferType = SECBUFFER_EMPTY; 00577 bufs[2].BufferType = SECBUFFER_EMPTY; 00578 bufs[3].BufferType = SECBUFFER_EMPTY; 00579 00580 buf.ulVersion = SECBUFFER_VERSION; 00581 buf.cBuffers = 4; 00582 buf.pBuffers = bufs; 00583 00584 status = global->sspi->DecryptMessage(&conn->context, &buf, 0, 00585 NULL); 00586 wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> " 00587 "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " 00588 "len[2]=%d type[2]=%d len[3]=%d type[3]=%d", 00589 (int) status, 00590 (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, 00591 (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, 00592 (int) bufs[2].cbBuffer, (int) bufs[2].BufferType, 00593 (int) bufs[3].cbBuffer, (int) bufs[3].BufferType); 00594 wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: " 00595 "out_data=%p bufs %p %p %p %p", 00596 wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer, 00597 bufs[2].pvBuffer, bufs[3].pvBuffer); 00598 00599 switch (status) { 00600 case SEC_E_INCOMPLETE_MESSAGE: 00601 wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE", 00602 __func__); 00603 break; 00604 case SEC_E_OK: 00605 wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); 00606 for (i = 0; i < 4; i++) { 00607 if (bufs[i].BufferType == SECBUFFER_DATA) 00608 break; 00609 } 00610 if (i == 4) { 00611 wpa_printf(MSG_DEBUG, "%s: No output data from " 00612 "DecryptMessage", __func__); 00613 wpabuf_free(tmp); 00614 return NULL; 00615 } 00616 wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from " 00617 "DecryptMessage", 00618 bufs[i].pvBuffer, bufs[i].cbBuffer); 00619 out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer); 00620 wpabuf_free(tmp); 00621 return out; 00622 } 00623 00624 wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", 00625 __func__, (int) status); 00626 wpabuf_free(tmp); 00627 return NULL; 00628 } 00629 00630 00631 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) 00632 { 00633 return 0; 00634 } 00635 00636 00637 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 00638 u8 *ciphers) 00639 { 00640 return -1; 00641 } 00642 00643 00644 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, 00645 char *buf, size_t buflen) 00646 { 00647 return -1; 00648 } 00649 00650 00651 int tls_connection_enable_workaround(void *ssl_ctx, 00652 struct tls_connection *conn) 00653 { 00654 return 0; 00655 } 00656 00657 00658 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, 00659 int ext_type, const u8 *data, 00660 size_t data_len) 00661 { 00662 return -1; 00663 } 00664 00665 00666 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) 00667 { 00668 if (conn == NULL) 00669 return -1; 00670 return conn->failed; 00671 } 00672 00673 00674 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) 00675 { 00676 if (conn == NULL) 00677 return -1; 00678 return conn->read_alerts; 00679 } 00680 00681 00682 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) 00683 { 00684 if (conn == NULL) 00685 return -1; 00686 return conn->write_alerts; 00687 } 00688 00689 00690 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 00691 const struct tls_connection_params *params) 00692 { 00693 struct tls_global *global = tls_ctx; 00694 ALG_ID algs[1]; 00695 SECURITY_STATUS status; 00696 TimeStamp ts_expiry; 00697 00698 if (conn == NULL) 00699 return -1; 00700 00701 if (global->my_cert_store == NULL && 00702 (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) == 00703 NULL) { 00704 wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x", 00705 __func__, (unsigned int) GetLastError()); 00706 return -1; 00707 } 00708 00709 os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred)); 00710 conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; 00711 conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1; 00712 algs[0] = CALG_RSA_KEYX; 00713 conn->schannel_cred.cSupportedAlgs = 1; 00714 conn->schannel_cred.palgSupportedAlgs = algs; 00715 conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; 00716 #ifdef UNICODE 00717 status = global->sspi->AcquireCredentialsHandleW( 00718 NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, 00719 &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); 00720 #else /* UNICODE */ 00721 status = global->sspi->AcquireCredentialsHandleA( 00722 NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, 00723 &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); 00724 #endif /* UNICODE */ 00725 if (status != SEC_E_OK) { 00726 wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - " 00727 "0x%x", __func__, (unsigned int) status); 00728 return -1; 00729 } 00730 00731 return 0; 00732 } 00733 00734 00735 unsigned int tls_capabilities(void *tls_ctx) 00736 { 00737 return 0; 00738 } 00739 00740 00741 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, 00742 int tls_ia) 00743 { 00744 return -1; 00745 } 00746 00747 00748 struct wpabuf * tls_connection_ia_send_phase_finished( 00749 void *tls_ctx, struct tls_connection *conn, int final); 00750 { 00751 return NULL; 00752 } 00753 00754 00755 int tls_connection_ia_final_phase_finished(void *tls_ctx, 00756 struct tls_connection *conn) 00757 { 00758 return -1; 00759 } 00760 00761 00762 int tls_connection_ia_permute_inner_secret(void *tls_ctx, 00763 struct tls_connection *conn, 00764 const u8 *key, size_t key_len) 00765 { 00766 return -1; 00767 }