automake build system
[mech_eap.orig] / src / crypto / tls_schannel.c
1 /*
2  * SSL/TLS interface functions for Microsoft Schannel
3  * Copyright (c) 2005-2009, 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 struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
219                                                struct tls_connection *conn)
220 {
221         DWORD sspi_flags, sspi_flags_out;
222         SecBufferDesc outbuf;
223         SecBuffer outbufs[1];
224         SECURITY_STATUS status;
225         TimeStamp ts_expiry;
226
227         sspi_flags = ISC_REQ_REPLAY_DETECT |
228                 ISC_REQ_CONFIDENTIALITY |
229                 ISC_RET_EXTENDED_ERROR |
230                 ISC_REQ_ALLOCATE_MEMORY |
231                 ISC_REQ_MANUAL_CRED_VALIDATION;
232
233         wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
234
235         outbufs[0].pvBuffer = NULL;
236         outbufs[0].BufferType = SECBUFFER_TOKEN;
237         outbufs[0].cbBuffer = 0;
238
239         outbuf.cBuffers = 1;
240         outbuf.pBuffers = outbufs;
241         outbuf.ulVersion = SECBUFFER_VERSION;
242
243 #ifdef UNICODE
244         status = global->sspi->InitializeSecurityContextW(
245                 &conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
246                 SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
247                 &outbuf, &sspi_flags_out, &ts_expiry);
248 #else /* UNICODE */
249         status = global->sspi->InitializeSecurityContextA(
250                 &conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
251                 SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
252                 &outbuf, &sspi_flags_out, &ts_expiry);
253 #endif /* UNICODE */
254         if (status != SEC_I_CONTINUE_NEEDED) {
255                 wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
256                            "failed - 0x%x",
257                            __func__, (unsigned int) status);
258                 return NULL;
259         }
260
261         if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
262                 struct wpabuf *buf;
263                 wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
264                             outbufs[0].pvBuffer, outbufs[0].cbBuffer);
265                 conn->start = 0;
266                 buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
267                                         outbufs[0].cbBuffer);
268                 if (buf == NULL)
269                         return NULL;
270                 global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
271                 return buf;
272         }
273
274         wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
275
276         return NULL;
277 }
278
279
280 #ifndef SECPKG_ATTR_EAP_KEY_BLOCK
281 #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
282
283 typedef struct _SecPkgContext_EapKeyBlock {
284         BYTE rgbKeys[128];
285         BYTE rgbIVs[64];
286 } SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
287 #endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
288
289 static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
290 {
291         SECURITY_STATUS status;
292         SecPkgContext_EapKeyBlock kb;
293
294         /* Note: Windows NT and Windows Me/98/95 do not support getting
295          * EapKeyBlock */
296
297         status = global->sspi->QueryContextAttributes(
298                 &conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb);
299         if (status != SEC_E_OK) {
300                 wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes("
301                            "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)",
302                            __func__, (int) status);
303                 return -1;
304         }
305
306         wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys",
307                         kb.rgbKeys, sizeof(kb.rgbKeys));
308         wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
309                         kb.rgbIVs, sizeof(kb.rgbIVs));
310
311         os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
312         conn->eap_tls_prf_set = 1;
313         return 0;
314 }
315
316
317 struct wpabuf * tls_connection_handshake(void *tls_ctx,
318                                          struct tls_connection *conn,
319                                          const struct wpabuf *in_data,
320                                          struct wpabuf **appl_data)
321 {
322         struct tls_global *global = tls_ctx;
323         DWORD sspi_flags, sspi_flags_out;
324         SecBufferDesc inbuf, outbuf;
325         SecBuffer inbufs[2], outbufs[1];
326         SECURITY_STATUS status;
327         TimeStamp ts_expiry;
328         struct wpabuf *out_buf = NULL;
329
330         if (appl_data)
331                 *appl_data = NULL;
332
333         if (conn->start)
334                 return tls_conn_hs_clienthello(global, conn);
335
336         wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
337                    (int) wpabuf_len(in_data));
338
339         sspi_flags = ISC_REQ_REPLAY_DETECT |
340                 ISC_REQ_CONFIDENTIALITY |
341                 ISC_RET_EXTENDED_ERROR |
342                 ISC_REQ_ALLOCATE_MEMORY |
343                 ISC_REQ_MANUAL_CRED_VALIDATION;
344
345         /* Input buffer for Schannel */
346         inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
347         inbufs[0].cbBuffer = wpabuf_len(in_data);
348         inbufs[0].BufferType = SECBUFFER_TOKEN;
349
350         /* Place for leftover data from Schannel */
351         inbufs[1].pvBuffer = NULL;
352         inbufs[1].cbBuffer = 0;
353         inbufs[1].BufferType = SECBUFFER_EMPTY;
354
355         inbuf.cBuffers = 2;
356         inbuf.pBuffers = inbufs;
357         inbuf.ulVersion = SECBUFFER_VERSION;
358
359         /* Output buffer for Schannel */
360         outbufs[0].pvBuffer = NULL;
361         outbufs[0].cbBuffer = 0;
362         outbufs[0].BufferType = SECBUFFER_TOKEN;
363
364         outbuf.cBuffers = 1;
365         outbuf.pBuffers = outbufs;
366         outbuf.ulVersion = SECBUFFER_VERSION;
367
368 #ifdef UNICODE
369         status = global->sspi->InitializeSecurityContextW(
370                 &conn->creds, &conn->context, NULL, sspi_flags, 0,
371                 SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
372                 &outbuf, &sspi_flags_out, &ts_expiry);
373 #else /* UNICODE */
374         status = global->sspi->InitializeSecurityContextA(
375                 &conn->creds, &conn->context, NULL, sspi_flags, 0,
376                 SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
377                 &outbuf, &sspi_flags_out, &ts_expiry);
378 #endif /* UNICODE */
379
380         wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> "
381                    "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
382                    "intype[1]=%d outlen[0]=%d",
383                    (int) status, (int) inbufs[0].cbBuffer,
384                    (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
385                    (int) inbufs[1].BufferType,
386                    (int) outbufs[0].cbBuffer);
387         if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
388             (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
389                 if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
390                         wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
391                                     outbufs[0].pvBuffer, outbufs[0].cbBuffer);
392                         out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
393                                                     outbufs[0].cbBuffer);
394                         global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
395                         outbufs[0].pvBuffer = NULL;
396                         if (out_buf == NULL)
397                                 return NULL;
398                 }
399         }
400
401         switch (status) {
402         case SEC_E_INCOMPLETE_MESSAGE:
403                 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
404                 break;
405         case SEC_I_CONTINUE_NEEDED:
406                 wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
407                 break;
408         case SEC_E_OK:
409                 /* TODO: verify server certificate chain */
410                 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
411                            "completed successfully");
412                 conn->established = 1;
413                 tls_get_eap(global, conn);
414
415                 /* Need to return something to get final TLS ACK. */
416                 if (out_buf == NULL)
417                         out_buf = wpabuf_alloc(0);
418
419                 if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
420                         wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
421                                     "application data",
422                                     inbufs[1].pvBuffer, inbufs[1].cbBuffer);
423                         if (appl_data) {
424                                 *appl_data = wpabuf_alloc_copy(
425                                         outbufs[1].pvBuffer,
426                                         outbufs[1].cbBuffer);
427                         }
428                         global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
429                         inbufs[1].pvBuffer = NULL;
430                 }
431                 break;
432         case SEC_I_INCOMPLETE_CREDENTIALS:
433                 wpa_printf(MSG_DEBUG,
434                            "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
435                 break;
436         case SEC_E_WRONG_PRINCIPAL:
437                 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
438                 break;
439         case SEC_E_INTERNAL_ERROR:
440                 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
441                 break;
442         }
443
444         if (FAILED(status)) {
445                 wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
446                            "(out_buf=%p)", out_buf);
447                 conn->failed++;
448                 global->sspi->DeleteSecurityContext(&conn->context);
449                 return out_buf;
450         }
451
452         if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
453                 /* TODO: Can this happen? What to do with this data? */
454                 wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
455                             inbufs[1].pvBuffer, inbufs[1].cbBuffer);
456                 global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
457                 inbufs[1].pvBuffer = NULL;
458         }
459
460         return out_buf;
461 }
462
463
464 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
465                                                 struct tls_connection *conn,
466                                                 const struct wpabuf *in_data,
467                                                 struct wpabuf **appl_data)
468 {
469         return NULL;
470 }
471
472
473 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
474                                        struct tls_connection *conn,
475                                        const struct wpabuf *in_data)
476 {
477         struct tls_global *global = tls_ctx;
478         SECURITY_STATUS status;
479         SecBufferDesc buf;
480         SecBuffer bufs[4];
481         SecPkgContext_StreamSizes sizes;
482         int i;
483         struct wpabuf *out;
484
485         status = global->sspi->QueryContextAttributes(&conn->context,
486                                                       SECPKG_ATTR_STREAM_SIZES,
487                                                       &sizes);
488         if (status != SEC_E_OK) {
489                 wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
490                            __func__);
491                 return NULL;
492         }
493         wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
494                    __func__,
495                    (unsigned int) sizes.cbHeader,
496                    (unsigned int) sizes.cbTrailer);
497
498         out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
499                            sizes.cbTrailer);
500
501         os_memset(&bufs, 0, sizeof(bufs));
502         bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader);
503         bufs[0].cbBuffer = sizes.cbHeader;
504         bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
505
506         bufs[1].pvBuffer = wpabuf_put(out, 0);
507         wpabuf_put_buf(out, in_data);
508         bufs[1].cbBuffer = wpabuf_len(in_data);
509         bufs[1].BufferType = SECBUFFER_DATA;
510
511         bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
512         bufs[2].cbBuffer = sizes.cbTrailer;
513         bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
514
515         buf.ulVersion = SECBUFFER_VERSION;
516         buf.cBuffers = 3;
517         buf.pBuffers = bufs;
518
519         status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
520
521         wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
522                    "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
523                    "len[2]=%d type[2]=%d",
524                    (int) status,
525                    (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
526                    (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
527                    (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
528         wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
529                    "out_data=%p bufs %p %p %p",
530                    wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer,
531                    bufs[2].pvBuffer);
532
533         for (i = 0; i < 3; i++) {
534                 if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
535                 {
536                         wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
537                                     bufs[i].pvBuffer, bufs[i].cbBuffer);
538                 }
539         }
540
541         if (status == SEC_E_OK) {
542                 wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
543                 wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
544                                     "from EncryptMessage", out);
545                 return out;
546         }
547
548         wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
549                    __func__, (int) status);
550         wpabuf_free(out);
551         return NULL;
552 }
553
554
555 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
556                                        struct tls_connection *conn,
557                                        const struct wpabuf *in_data)
558 {
559         struct tls_global *global = tls_ctx;
560         SECURITY_STATUS status;
561         SecBufferDesc buf;
562         SecBuffer bufs[4];
563         int i;
564         struct wpabuf *out, *tmp;
565
566         wpa_hexdump_buf(MSG_MSGDUMP,
567                         "Schannel: Encrypted data to DecryptMessage", in_data);
568         os_memset(&bufs, 0, sizeof(bufs));
569         tmp = wpabuf_dup(in_data);
570         if (tmp == NULL)
571                 return NULL;
572         bufs[0].pvBuffer = wpabuf_mhead(tmp);
573         bufs[0].cbBuffer = wpabuf_len(in_data);
574         bufs[0].BufferType = SECBUFFER_DATA;
575
576         bufs[1].BufferType = SECBUFFER_EMPTY;
577         bufs[2].BufferType = SECBUFFER_EMPTY;
578         bufs[3].BufferType = SECBUFFER_EMPTY;
579
580         buf.ulVersion = SECBUFFER_VERSION;
581         buf.cBuffers = 4;
582         buf.pBuffers = bufs;
583
584         status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
585                                                     NULL);
586         wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
587                    "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
588                    "len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
589                    (int) status,
590                    (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
591                    (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
592                    (int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
593                    (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
594         wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
595                    "out_data=%p bufs %p %p %p %p",
596                    wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer,
597                    bufs[2].pvBuffer, bufs[3].pvBuffer);
598
599         switch (status) {
600         case SEC_E_INCOMPLETE_MESSAGE:
601                 wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
602                            __func__);
603                 break;
604         case SEC_E_OK:
605                 wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
606                 for (i = 0; i < 4; i++) {
607                         if (bufs[i].BufferType == SECBUFFER_DATA)
608                                 break;
609                 }
610                 if (i == 4) {
611                         wpa_printf(MSG_DEBUG, "%s: No output data from "
612                                    "DecryptMessage", __func__);
613                         wpabuf_free(tmp);
614                         return NULL;
615                 }
616                 wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
617                                 "DecryptMessage",
618                                 bufs[i].pvBuffer, bufs[i].cbBuffer);
619                 out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
620                 wpabuf_free(tmp);
621                 return out;
622         }
623
624         wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
625                    __func__, (int) status);
626         wpabuf_free(tmp);
627         return NULL;
628 }
629
630
631 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
632 {
633         return 0;
634 }
635
636
637 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
638                                    u8 *ciphers)
639 {
640         return -1;
641 }
642
643
644 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
645                    char *buf, size_t buflen)
646 {
647         return -1;
648 }
649
650
651 int tls_connection_enable_workaround(void *ssl_ctx,
652                                      struct tls_connection *conn)
653 {
654         return 0;
655 }
656
657
658 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
659                                     int ext_type, const u8 *data,
660                                     size_t data_len)
661 {
662         return -1;
663 }
664
665
666 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
667 {
668         if (conn == NULL)
669                 return -1;
670         return conn->failed;
671 }
672
673
674 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
675 {
676         if (conn == NULL)
677                 return -1;
678         return conn->read_alerts;
679 }
680
681
682 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
683 {
684         if (conn == NULL)
685                 return -1;
686         return conn->write_alerts;
687 }
688
689
690 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
691                               const struct tls_connection_params *params)
692 {
693         struct tls_global *global = tls_ctx;
694         ALG_ID algs[1];
695         SECURITY_STATUS status;
696         TimeStamp ts_expiry;
697
698         if (conn == NULL)
699                 return -1;
700
701         if (global->my_cert_store == NULL &&
702             (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
703             NULL) {
704                 wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
705                            __func__, (unsigned int) GetLastError());
706                 return -1;
707         }
708
709         os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
710         conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
711         conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
712         algs[0] = CALG_RSA_KEYX;
713         conn->schannel_cred.cSupportedAlgs = 1;
714         conn->schannel_cred.palgSupportedAlgs = algs;
715         conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
716 #ifdef UNICODE
717         status = global->sspi->AcquireCredentialsHandleW(
718                 NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
719                 &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
720 #else /* UNICODE */
721         status = global->sspi->AcquireCredentialsHandleA(
722                 NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
723                 &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
724 #endif /* UNICODE */
725         if (status != SEC_E_OK) {
726                 wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
727                            "0x%x", __func__, (unsigned int) status);
728                 return -1;
729         }
730
731         return 0;
732 }
733
734
735 unsigned int tls_capabilities(void *tls_ctx)
736 {
737         return 0;
738 }
739
740
741 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
742                           int tls_ia)
743 {
744         return -1;
745 }
746
747
748 struct wpabuf * tls_connection_ia_send_phase_finished(
749         void *tls_ctx, struct tls_connection *conn, int final);
750 {
751         return NULL;
752 }
753
754
755 int tls_connection_ia_final_phase_finished(void *tls_ctx,
756                                            struct tls_connection *conn)
757 {
758         return -1;
759 }
760
761
762 int tls_connection_ia_permute_inner_secret(void *tls_ctx,
763                                            struct tls_connection *conn,
764                                            const u8 *key, size_t key_len)
765 {
766         return -1;
767 }