Additions to 'hammer pfs-*':
[dragonfly.git] / contrib / wpa_supplicant-0.5.8 / tls_schannel.c
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 }