Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 797 lines (652 sloc) 20.534 kb
845e012 auto import from //depot/cupcake/@135843
The Android Open Source Project authored
1 /*
2 * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
3 * Copyright (c) 2005, Jouni Malinen <j@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_master_key(void *ssl_ctx, struct tls_connection *conn,
658 const u8 *key, size_t key_len)
659 {
660 return -1;
661 }
662
663
664 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
665 u8 *ciphers)
666 {
667 return -1;
668 }
669
670
671 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
672 char *buf, size_t buflen)
673 {
674 return -1;
675 }
676
677
678 int tls_connection_enable_workaround(void *ssl_ctx,
679 struct tls_connection *conn)
680 {
681 return 0;
682 }
683
684
685 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
686 int ext_type, const u8 *data,
687 size_t data_len)
688 {
689 return -1;
690 }
691
692
693 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
694 {
695 if (conn == NULL)
696 return -1;
697 return conn->failed;
698 }
699
700
701 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
702 {
703 if (conn == NULL)
704 return -1;
705 return conn->read_alerts;
706 }
707
708
709 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
710 {
711 if (conn == NULL)
712 return -1;
713 return conn->write_alerts;
714 }
715
716
717 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
718 const struct tls_connection_params *params)
719 {
720 struct tls_global *global = tls_ctx;
721 ALG_ID algs[1];
722 SECURITY_STATUS status;
723 TimeStamp ts_expiry;
724
725 if (conn == NULL)
726 return -1;
727
728 if (global->my_cert_store == NULL &&
729 (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
730 NULL) {
731 wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
732 __func__, (unsigned int) GetLastError());
733 return -1;
734 }
735
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;
743 #ifdef UNICODE
744 status = global->sspi->AcquireCredentialsHandleW(
745 NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
746 &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
747 #else /* UNICODE */
748 status = global->sspi->AcquireCredentialsHandleA(
749 NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
750 &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
751 #endif /* UNICODE */
752 if (status != SEC_E_OK) {
753 wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
754 "0x%x", __func__, (unsigned int) status);
755 return -1;
756 }
757
758 return 0;
759 }
760
761
762 unsigned int tls_capabilities(void *tls_ctx)
763 {
764 return 0;
765 }
766
767
768 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
769 int tls_ia)
770 {
771 return -1;
772 }
773
774
775 int tls_connection_ia_send_phase_finished(void *tls_ctx,
776 struct tls_connection *conn,
777 int final,
778 u8 *out_data, size_t out_len)
779 {
780 return -1;
781 }
782
783
784 int tls_connection_ia_final_phase_finished(void *tls_ctx,
785 struct tls_connection *conn)
786 {
787 return -1;
788 }
789
790
791 int tls_connection_ia_permute_inner_secret(void *tls_ctx,
792 struct tls_connection *conn,
793 const u8 *key, size_t key_len)
794 {
795 return -1;
796 }
Something went wrong with that request. Please try again.