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