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