• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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