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

« back to all changes in this revision

Viewing changes to src/crypto/crypto_cryptoapi.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 / Crypto wrapper for Microsoft CryptoAPI
3
 
 * Copyright (c) 2005-2006, 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
 
#include "includes.h"
16
 
#include <windows.h>
17
 
#include <wincrypt.h>
18
 
 
19
 
#include "common.h"
20
 
#include "crypto.h"
21
 
 
22
 
#ifndef MS_ENH_RSA_AES_PROV
23
 
#ifdef UNICODE
24
 
#define MS_ENH_RSA_AES_PROV \
25
 
L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
26
 
#else
27
 
#define MS_ENH_RSA_AES_PROV \
28
 
"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
29
 
#endif
30
 
#endif /* MS_ENH_RSA_AES_PROV */
31
 
 
32
 
#ifndef CALG_HMAC
33
 
#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
34
 
#endif
35
 
 
36
 
#ifdef CONFIG_TLS_INTERNAL
37
 
#ifdef __MINGW32_VERSION
38
 
/*
39
 
 * MinGW does not yet include all the needed definitions for CryptoAPI, so
40
 
 * define here whatever extra is needed.
41
 
 */
42
 
 
43
 
static PCCERT_CONTEXT WINAPI
44
 
(*CertCreateCertificateContext)(DWORD dwCertEncodingType,
45
 
                                const BYTE *pbCertEncoded,
46
 
                                DWORD cbCertEncoded)
47
 
= NULL; /* to be loaded from crypt32.dll */
48
 
 
49
 
static BOOL WINAPI
50
 
(*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType,
51
 
                            PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
52
 
= NULL; /* to be loaded from crypt32.dll */
53
 
 
54
 
 
55
 
static int mingw_load_crypto_func(void)
56
 
{
57
 
        HINSTANCE dll;
58
 
 
59
 
        /* MinGW does not yet have full CryptoAPI support, so load the needed
60
 
         * function here. */
61
 
 
62
 
        if (CertCreateCertificateContext)
63
 
                return 0;
64
 
 
65
 
        dll = LoadLibrary("crypt32");
66
 
        if (dll == NULL) {
67
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 "
68
 
                           "library");
69
 
                return -1;
70
 
        }
71
 
 
72
 
        CertCreateCertificateContext = (void *) GetProcAddress(
73
 
                dll, "CertCreateCertificateContext");
74
 
        if (CertCreateCertificateContext == NULL) {
75
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get "
76
 
                           "CertCreateCertificateContext() address from "
77
 
                           "crypt32 library");
78
 
                return -1;
79
 
        }
80
 
 
81
 
        CryptImportPublicKeyInfo = GetProcAddress(
82
 
                dll, "CryptImportPublicKeyInfo");
83
 
        if (CryptImportPublicKeyInfo == NULL) {
84
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get "
85
 
                           "CryptImportPublicKeyInfo() address from "
86
 
                           "crypt32 library");
87
 
                return -1;
88
 
        }
89
 
 
90
 
        return 0;
91
 
}
92
 
 
93
 
#else /* __MINGW32_VERSION */
94
 
 
95
 
static int mingw_load_crypto_func(void)
96
 
{
97
 
        return 0;
98
 
}
99
 
 
100
 
#endif /* __MINGW32_VERSION */
101
 
#endif /* CONFIG_TLS_INTERNAL */
102
 
 
103
 
 
104
 
static void cryptoapi_report_error(const char *msg)
105
 
{
106
 
        char *s, *pos;
107
 
        DWORD err = GetLastError();
108
 
 
109
 
        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
110
 
                          FORMAT_MESSAGE_FROM_SYSTEM,
111
 
                          NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) {
112
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err);
113
 
        }
114
 
 
115
 
        pos = s;
116
 
        while (*pos) {
117
 
                if (*pos == '\n' || *pos == '\r') {
118
 
                        *pos = '\0';
119
 
                        break;
120
 
                }
121
 
                pos++;
122
 
        }
123
 
 
124
 
        wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s);
125
 
        LocalFree(s);
126
 
}
127
 
 
128
 
 
129
 
int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem,
130
 
                          const u8 *addr[], const size_t *len, u8 *mac)
131
 
{
132
 
        HCRYPTPROV prov;
133
 
        HCRYPTHASH hash;
134
 
        size_t i;
135
 
        DWORD hlen;
136
 
        int ret = 0;
137
 
 
138
 
        if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) {
139
 
                cryptoapi_report_error("CryptAcquireContext");
140
 
                return -1;
141
 
        }
142
 
 
143
 
        if (!CryptCreateHash(prov, alg, 0, 0, &hash)) {
144
 
                cryptoapi_report_error("CryptCreateHash");
145
 
                CryptReleaseContext(prov, 0);
146
 
                return -1;
147
 
        }
148
 
 
149
 
        for (i = 0; i < num_elem; i++) {
150
 
                if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) {
151
 
                        cryptoapi_report_error("CryptHashData");
152
 
                        CryptDestroyHash(hash);
153
 
                        CryptReleaseContext(prov, 0);
154
 
                }
155
 
        }
156
 
 
157
 
        hlen = hash_len;
158
 
        if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) {
159
 
                cryptoapi_report_error("CryptGetHashParam");
160
 
                ret = -1;
161
 
        }
162
 
 
163
 
        CryptDestroyHash(hash);
164
 
        CryptReleaseContext(prov, 0);
165
 
 
166
 
        return ret;
167
 
}
168
 
 
169
 
 
170
 
void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
171
 
{
172
 
        cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac);
173
 
}
174
 
 
175
 
 
176
 
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
177
 
{
178
 
        u8 next, tmp;
179
 
        int i;
180
 
        HCRYPTPROV prov;
181
 
        HCRYPTKEY ckey;
182
 
        DWORD dlen;
183
 
        struct {
184
 
                BLOBHEADER hdr;
185
 
                DWORD len;
186
 
                BYTE key[8];
187
 
        } key_blob;
188
 
        DWORD mode = CRYPT_MODE_ECB;
189
 
 
190
 
        key_blob.hdr.bType = PLAINTEXTKEYBLOB;
191
 
        key_blob.hdr.bVersion = CUR_BLOB_VERSION;
192
 
        key_blob.hdr.reserved = 0;
193
 
        key_blob.hdr.aiKeyAlg = CALG_DES;
194
 
        key_blob.len = 8;
195
 
 
196
 
        /* Add parity bits to the key */
197
 
        next = 0;
198
 
        for (i = 0; i < 7; i++) {
199
 
                tmp = key[i];
200
 
                key_blob.key[i] = (tmp >> i) | next | 1;
201
 
                next = tmp << (7 - i);
202
 
        }
203
 
        key_blob.key[i] = next | 1;
204
 
 
205
 
        if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL,
206
 
                                 CRYPT_VERIFYCONTEXT)) {
207
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
208
 
                           "%d", (int) GetLastError());
209
 
                return;
210
 
        }
211
 
 
212
 
        if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0,
213
 
                            &ckey)) {
214
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
215
 
                           (int) GetLastError());
216
 
                CryptReleaseContext(prov, 0);
217
 
                return;
218
 
        }
219
 
 
220
 
        if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) {
221
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
222
 
                           "failed: %d", (int) GetLastError());
223
 
                CryptDestroyKey(ckey);
224
 
                CryptReleaseContext(prov, 0);
225
 
                return;
226
 
        }
227
 
 
228
 
        os_memcpy(cypher, clear, 8);
229
 
        dlen = 8;
230
 
        if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) {
231
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
232
 
                           (int) GetLastError());
233
 
                os_memset(cypher, 0, 8);
234
 
        }
235
 
 
236
 
        CryptDestroyKey(ckey);
237
 
        CryptReleaseContext(prov, 0);
238
 
}
239
 
 
240
 
 
241
 
#ifdef EAP_TLS_FUNCS
242
 
void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
243
 
{
244
 
        cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);
245
 
}
246
 
 
247
 
 
248
 
void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
249
 
{
250
 
        cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac);
251
 
}
252
 
 
253
 
 
254
 
struct aes_context {
255
 
        HCRYPTPROV prov;
256
 
        HCRYPTKEY ckey;
257
 
};
258
 
 
259
 
 
260
 
void * aes_encrypt_init(const u8 *key, size_t len)
261
 
{
262
 
        struct aes_context *akey;
263
 
        struct {
264
 
                BLOBHEADER hdr;
265
 
                DWORD len;
266
 
                BYTE key[16];
267
 
        } key_blob;
268
 
        DWORD mode = CRYPT_MODE_ECB;
269
 
 
270
 
        if (len != 16)
271
 
                return NULL;
272
 
 
273
 
        key_blob.hdr.bType = PLAINTEXTKEYBLOB;
274
 
        key_blob.hdr.bVersion = CUR_BLOB_VERSION;
275
 
        key_blob.hdr.reserved = 0;
276
 
        key_blob.hdr.aiKeyAlg = CALG_AES_128;
277
 
        key_blob.len = len;
278
 
        os_memcpy(key_blob.key, key, len);
279
 
 
280
 
        akey = os_zalloc(sizeof(*akey));
281
 
        if (akey == NULL)
282
 
                return NULL;
283
 
 
284
 
        if (!CryptAcquireContext(&akey->prov, NULL,
285
 
                                 MS_ENH_RSA_AES_PROV, PROV_RSA_AES,
286
 
                                 CRYPT_VERIFYCONTEXT)) {
287
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
288
 
                           "%d", (int) GetLastError());
289
 
                os_free(akey);
290
 
                return NULL;
291
 
        }
292
 
 
293
 
        if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob),
294
 
                            0, 0, &akey->ckey)) {
295
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
296
 
                           (int) GetLastError());
297
 
                CryptReleaseContext(akey->prov, 0);
298
 
                os_free(akey);
299
 
                return NULL;
300
 
        }
301
 
 
302
 
        if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) {
303
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
304
 
                           "failed: %d", (int) GetLastError());
305
 
                CryptDestroyKey(akey->ckey);
306
 
                CryptReleaseContext(akey->prov, 0);
307
 
                os_free(akey);
308
 
                return NULL;
309
 
        }
310
 
 
311
 
        return akey;
312
 
}
313
 
 
314
 
 
315
 
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
316
 
{
317
 
        struct aes_context *akey = ctx;
318
 
        DWORD dlen;
319
 
 
320
 
        os_memcpy(crypt, plain, 16);
321
 
        dlen = 16;
322
 
        if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) {
323
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
324
 
                           (int) GetLastError());
325
 
                os_memset(crypt, 0, 16);
326
 
        }
327
 
}
328
 
 
329
 
 
330
 
void aes_encrypt_deinit(void *ctx)
331
 
{
332
 
        struct aes_context *akey = ctx;
333
 
        if (akey) {
334
 
                CryptDestroyKey(akey->ckey);
335
 
                CryptReleaseContext(akey->prov, 0);
336
 
                os_free(akey);
337
 
        }
338
 
}
339
 
 
340
 
 
341
 
void * aes_decrypt_init(const u8 *key, size_t len)
342
 
{
343
 
        return aes_encrypt_init(key, len);
344
 
}
345
 
 
346
 
 
347
 
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
348
 
{
349
 
        struct aes_context *akey = ctx;
350
 
        DWORD dlen;
351
 
 
352
 
        os_memcpy(plain, crypt, 16);
353
 
        dlen = 16;
354
 
 
355
 
        if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) {
356
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d",
357
 
                           (int) GetLastError());
358
 
        }
359
 
}
360
 
 
361
 
 
362
 
void aes_decrypt_deinit(void *ctx)
363
 
{
364
 
        aes_encrypt_deinit(ctx);
365
 
}
366
 
 
367
 
#ifdef CONFIG_TLS_INTERNAL
368
 
 
369
 
struct crypto_hash {
370
 
        enum crypto_hash_alg alg;
371
 
        int error;
372
 
        HCRYPTPROV prov;
373
 
        HCRYPTHASH hash;
374
 
        HCRYPTKEY key;
375
 
};
376
 
 
377
 
struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
378
 
                                      size_t key_len)
379
 
{
380
 
        struct crypto_hash *ctx;
381
 
        ALG_ID calg;
382
 
        struct {
383
 
                BLOBHEADER hdr;
384
 
                DWORD len;
385
 
                BYTE key[32];
386
 
        } key_blob;
387
 
 
388
 
        os_memset(&key_blob, 0, sizeof(key_blob));
389
 
        switch (alg) {
390
 
        case CRYPTO_HASH_ALG_MD5:
391
 
                calg = CALG_MD5;
392
 
                break;
393
 
        case CRYPTO_HASH_ALG_SHA1:
394
 
                calg = CALG_SHA;
395
 
                break;
396
 
        case CRYPTO_HASH_ALG_HMAC_MD5:
397
 
        case CRYPTO_HASH_ALG_HMAC_SHA1:
398
 
                calg = CALG_HMAC;
399
 
                key_blob.hdr.bType = PLAINTEXTKEYBLOB;
400
 
                key_blob.hdr.bVersion = CUR_BLOB_VERSION;
401
 
                key_blob.hdr.reserved = 0;
402
 
                /*
403
 
                 * Note: RC2 is not really used, but that can be used to
404
 
                 * import HMAC keys of up to 16 byte long.
405
 
                 * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to
406
 
                 * be able to import longer keys (HMAC-SHA1 uses 20-byte key).
407
 
                 */
408
 
                key_blob.hdr.aiKeyAlg = CALG_RC2;
409
 
                key_blob.len = key_len;
410
 
                if (key_len > sizeof(key_blob.key))
411
 
                        return NULL;
412
 
                os_memcpy(key_blob.key, key, key_len);
413
 
                break;
414
 
        default:
415
 
                return NULL;
416
 
        }
417
 
 
418
 
        ctx = os_zalloc(sizeof(*ctx));
419
 
        if (ctx == NULL)
420
 
                return NULL;
421
 
 
422
 
        ctx->alg = alg;
423
 
 
424
 
        if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) {
425
 
                cryptoapi_report_error("CryptAcquireContext");
426
 
                os_free(ctx);
427
 
                return NULL;
428
 
        }
429
 
 
430
 
        if (calg == CALG_HMAC) {
431
 
#ifndef CRYPT_IPSEC_HMAC_KEY
432
 
#define CRYPT_IPSEC_HMAC_KEY 0x00000100
433
 
#endif
434
 
                if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
435
 
                                    sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY,
436
 
                                    &ctx->key)) {
437
 
                        cryptoapi_report_error("CryptImportKey");
438
 
                        CryptReleaseContext(ctx->prov, 0);
439
 
                        os_free(ctx);
440
 
                        return NULL;
441
 
                }
442
 
        }
443
 
 
444
 
        if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) {
445
 
                cryptoapi_report_error("CryptCreateHash");
446
 
                CryptReleaseContext(ctx->prov, 0);
447
 
                os_free(ctx);
448
 
                return NULL;
449
 
        }
450
 
 
451
 
        if (calg == CALG_HMAC) {
452
 
                HMAC_INFO info;
453
 
                os_memset(&info, 0, sizeof(info));
454
 
                switch (alg) {
455
 
                case CRYPTO_HASH_ALG_HMAC_MD5:
456
 
                        info.HashAlgid = CALG_MD5;
457
 
                        break;
458
 
                case CRYPTO_HASH_ALG_HMAC_SHA1:
459
 
                        info.HashAlgid = CALG_SHA;
460
 
                        break;
461
 
                default:
462
 
                        /* unreachable */
463
 
                        break;
464
 
                }
465
 
 
466
 
                if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info,
467
 
                                       0)) {
468
 
                        cryptoapi_report_error("CryptSetHashParam");
469
 
                        CryptDestroyHash(ctx->hash);
470
 
                        CryptReleaseContext(ctx->prov, 0);
471
 
                        os_free(ctx);
472
 
                        return NULL;
473
 
                }
474
 
        }
475
 
 
476
 
        return ctx;
477
 
}
478
 
 
479
 
 
480
 
void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
481
 
{
482
 
        if (ctx == NULL || ctx->error)
483
 
                return;
484
 
 
485
 
        if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) {
486
 
                cryptoapi_report_error("CryptHashData");
487
 
                ctx->error = 1;
488
 
        }
489
 
}
490
 
 
491
 
 
492
 
int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
493
 
{
494
 
        int ret = 0;
495
 
        DWORD hlen;
496
 
 
497
 
        if (ctx == NULL)
498
 
                return -2;
499
 
 
500
 
        if (mac == NULL || len == NULL)
501
 
                goto done;
502
 
 
503
 
        if (ctx->error) {
504
 
                ret = -2;
505
 
                goto done;
506
 
        }
507
 
 
508
 
        hlen = *len;
509
 
        if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) {
510
 
                cryptoapi_report_error("CryptGetHashParam");
511
 
                ret = -2;
512
 
        }
513
 
        *len = hlen;
514
 
 
515
 
done:
516
 
        if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 ||
517
 
            ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5)
518
 
                CryptDestroyKey(ctx->key);
519
 
 
520
 
        os_free(ctx);
521
 
 
522
 
        return ret;
523
 
}
524
 
 
525
 
 
526
 
struct crypto_cipher {
527
 
        HCRYPTPROV prov;
528
 
        HCRYPTKEY key;
529
 
};
530
 
 
531
 
 
532
 
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
533
 
                                          const u8 *iv, const u8 *key,
534
 
                                          size_t key_len)
535
 
{       
536
 
        struct crypto_cipher *ctx;
537
 
        struct {
538
 
                BLOBHEADER hdr;
539
 
                DWORD len;
540
 
                BYTE key[32];
541
 
        } key_blob;
542
 
        DWORD mode = CRYPT_MODE_CBC;
543
 
 
544
 
        key_blob.hdr.bType = PLAINTEXTKEYBLOB;
545
 
        key_blob.hdr.bVersion = CUR_BLOB_VERSION;
546
 
        key_blob.hdr.reserved = 0;
547
 
        key_blob.len = key_len;
548
 
        if (key_len > sizeof(key_blob.key))
549
 
                return NULL;
550
 
        os_memcpy(key_blob.key, key, key_len);
551
 
 
552
 
        switch (alg) {
553
 
        case CRYPTO_CIPHER_ALG_AES:
554
 
                if (key_len == 32)
555
 
                        key_blob.hdr.aiKeyAlg = CALG_AES_256;
556
 
                else if (key_len == 24)
557
 
                        key_blob.hdr.aiKeyAlg = CALG_AES_192;
558
 
                else
559
 
                        key_blob.hdr.aiKeyAlg = CALG_AES_128;
560
 
                break;
561
 
        case CRYPTO_CIPHER_ALG_3DES:
562
 
                key_blob.hdr.aiKeyAlg = CALG_3DES;
563
 
                break;
564
 
        case CRYPTO_CIPHER_ALG_DES:
565
 
                key_blob.hdr.aiKeyAlg = CALG_DES;
566
 
                break;
567
 
        case CRYPTO_CIPHER_ALG_RC2:
568
 
                key_blob.hdr.aiKeyAlg = CALG_RC2;
569
 
                break;
570
 
        case CRYPTO_CIPHER_ALG_RC4:
571
 
                key_blob.hdr.aiKeyAlg = CALG_RC4;
572
 
                break;
573
 
        default:
574
 
                return NULL;
575
 
        }
576
 
 
577
 
        ctx = os_zalloc(sizeof(*ctx));
578
 
        if (ctx == NULL)
579
 
                return NULL;
580
 
 
581
 
        if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV,
582
 
                                 PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
583
 
                cryptoapi_report_error("CryptAcquireContext");
584
 
                goto fail1;
585
 
        }
586
 
 
587
 
        if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
588
 
                            sizeof(key_blob), 0, 0, &ctx->key)) {
589
 
                cryptoapi_report_error("CryptImportKey");
590
 
                goto fail2;
591
 
        }
592
 
 
593
 
        if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) {
594
 
                cryptoapi_report_error("CryptSetKeyParam(KP_MODE)");
595
 
                goto fail3;
596
 
        }
597
 
 
598
 
        if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) {
599
 
                cryptoapi_report_error("CryptSetKeyParam(KP_IV)");
600
 
                goto fail3;
601
 
        }
602
 
 
603
 
        return ctx;
604
 
 
605
 
fail3:
606
 
        CryptDestroyKey(ctx->key);
607
 
fail2:
608
 
        CryptReleaseContext(ctx->prov, 0);
609
 
fail1:
610
 
        os_free(ctx);
611
 
        return NULL;
612
 
}
613
 
 
614
 
 
615
 
int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
616
 
                          u8 *crypt, size_t len)
617
 
{
618
 
        DWORD dlen;
619
 
 
620
 
        os_memcpy(crypt, plain, len);
621
 
        dlen = len;
622
 
        if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) {
623
 
                cryptoapi_report_error("CryptEncrypt");
624
 
                os_memset(crypt, 0, len);
625
 
                return -1;
626
 
        }
627
 
 
628
 
        return 0;
629
 
}
630
 
 
631
 
 
632
 
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
633
 
                          u8 *plain, size_t len)
634
 
{
635
 
        DWORD dlen;
636
 
 
637
 
        os_memcpy(plain, crypt, len);
638
 
        dlen = len;
639
 
        if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) {
640
 
                cryptoapi_report_error("CryptDecrypt");
641
 
                return -1;
642
 
        }
643
 
 
644
 
        return 0;
645
 
}
646
 
 
647
 
 
648
 
void crypto_cipher_deinit(struct crypto_cipher *ctx)
649
 
{
650
 
        CryptDestroyKey(ctx->key);
651
 
        CryptReleaseContext(ctx->prov, 0);
652
 
        os_free(ctx);
653
 
}
654
 
 
655
 
 
656
 
struct crypto_public_key {
657
 
        HCRYPTPROV prov;
658
 
        HCRYPTKEY rsa;
659
 
};
660
 
 
661
 
struct crypto_private_key {
662
 
        HCRYPTPROV prov;
663
 
        HCRYPTKEY rsa;
664
 
};
665
 
 
666
 
 
667
 
struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
668
 
{
669
 
        /* Use crypto_public_key_from_cert() instead. */
670
 
        return NULL;
671
 
}
672
 
 
673
 
 
674
 
struct crypto_private_key * crypto_private_key_import(const u8 *key,
675
 
                                                      size_t len)
676
 
{
677
 
        /* TODO */
678
 
        return NULL;
679
 
}
680
 
 
681
 
 
682
 
struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
683
 
                                                       size_t len)
684
 
{
685
 
        struct crypto_public_key *pk;
686
 
        PCCERT_CONTEXT cc;
687
 
 
688
 
        pk = os_zalloc(sizeof(*pk));
689
 
        if (pk == NULL)
690
 
                return NULL;
691
 
 
692
 
        cc = CertCreateCertificateContext(X509_ASN_ENCODING |
693
 
                                          PKCS_7_ASN_ENCODING, buf, len);
694
 
        if (!cc) {
695
 
                cryptoapi_report_error("CryptCreateCertificateContext");
696
 
                os_free(pk);
697
 
                return NULL;
698
 
        }
699
 
 
700
 
        if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
701
 
                                 0)) {
702
 
                cryptoapi_report_error("CryptAcquireContext");
703
 
                os_free(pk);
704
 
                CertFreeCertificateContext(cc);
705
 
                return NULL;
706
 
        }
707
 
 
708
 
        if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING |
709
 
                                      PKCS_7_ASN_ENCODING,
710
 
                                      &cc->pCertInfo->SubjectPublicKeyInfo,
711
 
                                      &pk->rsa)) {
712
 
                cryptoapi_report_error("CryptImportPublicKeyInfo");
713
 
                CryptReleaseContext(pk->prov, 0);
714
 
                os_free(pk);
715
 
                CertFreeCertificateContext(cc);
716
 
                return NULL;
717
 
        }
718
 
 
719
 
        CertFreeCertificateContext(cc);
720
 
 
721
 
        return pk;
722
 
}
723
 
 
724
 
 
725
 
int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
726
 
                                        const u8 *in, size_t inlen,
727
 
                                        u8 *out, size_t *outlen)
728
 
{
729
 
        DWORD clen;
730
 
        u8 *tmp;
731
 
        size_t i;
732
 
 
733
 
        if (*outlen < inlen)
734
 
                return -1;
735
 
        tmp = malloc(*outlen);
736
 
        if (tmp == NULL)
737
 
                return -1;
738
 
 
739
 
        os_memcpy(tmp, in, inlen);
740
 
        clen = inlen;
741
 
        if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) {
742
 
                wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using "
743
 
                           "public key: %d", (int) GetLastError());
744
 
                os_free(tmp);
745
 
                return -1;
746
 
        }
747
 
 
748
 
        *outlen = clen;
749
 
 
750
 
        /* Reverse the output */
751
 
        for (i = 0; i < *outlen; i++)
752
 
                out[i] = tmp[*outlen - 1 - i];
753
 
 
754
 
        os_free(tmp);
755
 
 
756
 
        return 0;
757
 
}
758
 
 
759
 
 
760
 
int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
761
 
                                  const u8 *in, size_t inlen,
762
 
                                  u8 *out, size_t *outlen)
763
 
{
764
 
        /* TODO */
765
 
        return -1;
766
 
}
767
 
 
768
 
 
769
 
void crypto_public_key_free(struct crypto_public_key *key)
770
 
{
771
 
        if (key) {
772
 
                CryptDestroyKey(key->rsa);
773
 
                CryptReleaseContext(key->prov, 0);
774
 
                os_free(key);
775
 
        }
776
 
}
777
 
 
778
 
 
779
 
void crypto_private_key_free(struct crypto_private_key *key)
780
 
{
781
 
        if (key) {
782
 
                CryptDestroyKey(key->rsa);
783
 
                CryptReleaseContext(key->prov, 0);
784
 
                os_free(key);
785
 
        }
786
 
}
787
 
 
788
 
 
789
 
int crypto_global_init(void)
790
 
{
791
 
        return mingw_load_crypto_func();
792
 
}
793
 
 
794
 
 
795
 
void crypto_global_deinit(void)
796
 
{
797
 
}
798
 
 
799
 
#endif /* CONFIG_TLS_INTERNAL */
800
 
 
801
 
#endif /* EAP_TLS_FUNCS */