Home | History | Annotate | Download | only in crypto
      1 /*
      2  * Crypto wrapper for Microsoft CryptoAPI
      3  * Copyright (c) 2005-2009, Jouni Malinen <j (at) 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 
     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 
     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 
     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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    326 void * aes_decrypt_init(const u8 *key, size_t len)
    327 {
    328 	return aes_encrypt_init(key, len);
    329 }
    330 
    331 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    774 int crypto_global_init(void)
    775 {
    776 	return mingw_load_crypto_func();
    777 }
    778 
    779 
    780 void crypto_global_deinit(void)
    781 {
    782 }
    783 
    784 #endif /* CONFIG_TLS_INTERNAL */
    785 
    786 #endif /* EAP_TLS_FUNCS */
    787