blob: 55a069b0d036efd3f48242aef1aca8b45238f342 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Crypto wrapper for Microsoft CryptoAPI
3 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
4 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
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 \
19L"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
36static 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
42static 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
73static int mingw_load_crypto_func(void)
74{
75 return 0;
76}
77
78#endif /* __MINGW32_VERSION */
79
80
81static 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
106int 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
147int 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
153void 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
218int 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
224int 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
230struct aes_context {
231 HCRYPTPROV prov;
232 HCRYPTKEY ckey;
233};
234
235
236void * 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
291void 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
306void 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
317void * aes_decrypt_init(const u8 *key, size_t len)
318{
319 return aes_encrypt_init(key, len);
320}
321
322
323void 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
338void aes_decrypt_deinit(void *ctx)
339{
340 aes_encrypt_deinit(ctx);
341}
342
343
344struct crypto_hash {
345 enum crypto_hash_alg alg;
346 int error;
347 HCRYPTPROV prov;
348 HCRYPTHASH hash;
349 HCRYPTKEY key;
350};
351
352struct 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
455void 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
467int 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
490done:
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
501struct crypto_cipher {
502 HCRYPTPROV prov;
503 HCRYPTKEY key;
504};
505
506
507struct 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
580fail3:
581 CryptDestroyKey(ctx->key);
582fail2:
583 CryptReleaseContext(ctx->prov, 0);
584fail1:
585 os_free(ctx);
586 return NULL;
587}
588
589
590int 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
607int 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
623void crypto_cipher_deinit(struct crypto_cipher *ctx)
624{
625 CryptDestroyKey(ctx->key);
626 CryptReleaseContext(ctx->prov, 0);
627 os_free(ctx);
628}
629
630
631struct crypto_public_key {
632 HCRYPTPROV prov;
633 HCRYPTKEY rsa;
634};
635
636struct crypto_private_key {
637 HCRYPTPROV prov;
638 HCRYPTKEY rsa;
639};
640
641
642struct 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
649struct 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
658struct 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
701int 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
736int 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
745void 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
755void 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
765int crypto_global_init(void)
766{
767 return mingw_load_crypto_func();
768}
769
770
771void crypto_global_deinit(void)
772{
773}
774
775
776int 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}