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