~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to tls_schannel.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}