Use 1Mbits/s as beacon sending rate; it seems to fix TX performance issue
[dragonfly.git] / contrib / wpa_supplicant-0.5.8 / crypto_cryptoapi.c
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 */