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
mingw_load_crypto_func(void)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
mingw_load_crypto_func(void)73 static int mingw_load_crypto_func(void)
74 {
75 return 0;
76 }
77
78 #endif /* __MINGW32_VERSION */
79
80
cryptoapi_report_error(const char * msg)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
cryptoapi_hash_vector(ALG_ID alg,size_t hash_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
md4_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
des_encrypt(const u8 * clear,const u8 * key,u8 * cypher)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
md5_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
sha1_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
aes_encrypt_init(const u8 * key,size_t len)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
aes_encrypt(void * ctx,const u8 * plain,u8 * crypt)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
aes_encrypt_deinit(void * ctx)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
aes_decrypt_init(const u8 * key,size_t len)317 void * aes_decrypt_init(const u8 *key, size_t len)
318 {
319 return aes_encrypt_init(key, len);
320 }
321
322
aes_decrypt(void * ctx,const u8 * crypt,u8 * plain)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
aes_decrypt_deinit(void * ctx)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
crypto_hash_init(enum crypto_hash_alg alg,const u8 * key,size_t key_len)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
crypto_hash_update(struct crypto_hash * ctx,const u8 * data,size_t len)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
crypto_hash_finish(struct crypto_hash * ctx,u8 * mac,size_t * len)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
crypto_cipher_init(enum crypto_cipher_alg alg,const u8 * iv,const u8 * key,size_t key_len)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
crypto_cipher_encrypt(struct crypto_cipher * ctx,const u8 * plain,u8 * crypt,size_t len)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
crypto_cipher_decrypt(struct crypto_cipher * ctx,const u8 * crypt,u8 * plain,size_t len)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
crypto_cipher_deinit(struct crypto_cipher * ctx)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
crypto_public_key_import(const u8 * key,size_t len)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
crypto_private_key_import(const u8 * key,size_t len,const char * passwd)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
crypto_public_key_from_cert(const u8 * buf,size_t len)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
crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key * key,const u8 * in,size_t inlen,u8 * out,size_t * outlen)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
crypto_private_key_sign_pkcs1(struct crypto_private_key * key,const u8 * in,size_t inlen,u8 * out,size_t * outlen)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
crypto_public_key_free(struct crypto_public_key * key)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
crypto_private_key_free(struct crypto_private_key * key)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
crypto_global_init(void)765 int crypto_global_init(void)
766 {
767 return mingw_load_crypto_func();
768 }
769
770
crypto_global_deinit(void)771 void crypto_global_deinit(void)
772 {
773 }
774
775
crypto_mod_exp(const u8 * base,size_t base_len,const u8 * power,size_t power_len,const u8 * modulus,size_t modulus_len,u8 * result,size_t * result_len)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 }
784