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