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