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

« back to all changes in this revision

Viewing changes to src/crypto/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
 
}