18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Crypto wrapper for Microsoft CryptoAPI
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <windows.h>
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <wincrypt.h>
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef MS_ENH_RSA_AES_PROV
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNICODE
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MS_ENH_RSA_AES_PROV \
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtL"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MS_ENH_RSA_AES_PROV \
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* MS_ENH_RSA_AES_PROV */
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CALG_HMAC
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __MINGW32_VERSION
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MinGW does not yet include all the needed definitions for CryptoAPI, so
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * define here whatever extra is needed.
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic BOOL WINAPI
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt(*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType,
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt= NULL; /* to be loaded from crypt32.dll */
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int mingw_load_crypto_func(void)
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HINSTANCE dll;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* MinGW does not yet have full CryptoAPI support, so load the needed
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * function here. */
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (CryptImportPublicKeyInfo)
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dll = LoadLibrary("crypt32");
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dll == NULL) {
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 "
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "library");
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptImportPublicKeyInfo = GetProcAddress(
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dll, "CryptImportPublicKeyInfo");
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (CryptImportPublicKeyInfo == NULL) {
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get "
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "CryptImportPublicKeyInfo() address from "
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "crypt32 library");
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* __MINGW32_VERSION */
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int mingw_load_crypto_func(void)
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __MINGW32_VERSION */
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void cryptoapi_report_error(const char *msg)
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *s, *pos;
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD err = GetLastError();
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  FORMAT_MESSAGE_FROM_SYSTEM,
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) {
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err);
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = s;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*pos) {
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\n' || *pos == '\r') {
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*pos = '\0';
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s);
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LocalFree(s);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem,
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const u8 *addr[], const size_t *len, u8 *mac)
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV prov;
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTHASH hash;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD hlen;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_report_error("CryptAcquireContext");
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptCreateHash(prov, alg, 0, 0, &hash)) {
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_report_error("CryptCreateHash");
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(prov, 0);
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_elem; i++) {
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) {
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cryptoapi_report_error("CryptHashData");
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			CryptDestroyHash(hash);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			CryptReleaseContext(prov, 0);
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = hash_len;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) {
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_report_error("CryptGetHashParam");
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -1;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptDestroyHash(hash);
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptReleaseContext(prov, 0);
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac);
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 next, tmp;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV prov;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTKEY ckey;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dlen;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct {
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BLOBHEADER hdr;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DWORD len;
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BYTE key[8];
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} key_blob;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD mode = CRYPT_MODE_ECB;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.bType = PLAINTEXTKEYBLOB;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.bVersion = CUR_BLOB_VERSION;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.reserved = 0;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.aiKeyAlg = CALG_DES;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.len = 8;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Add parity bits to the key */
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	next = 0;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 7; i++) {
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = key[i];
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.key[i] = (tmp >> i) | next | 1;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next = tmp << (7 - i);
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.key[i] = next | 1;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL,
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 CRYPT_VERIFYCONTEXT)) {
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d", (int) GetLastError());
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0,
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    &ckey)) {
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(prov, 0);
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) {
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %d", (int) GetLastError());
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptDestroyKey(ckey);
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(prov, 0);
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(cypher, clear, 8);
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dlen = 8;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) {
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(cypher, 0, 8);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptDestroyKey(ckey);
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptReleaseContext(prov, 0);
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac);
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct aes_context {
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV prov;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTKEY ckey;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * aes_encrypt_init(const u8 *key, size_t len)
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct aes_context *akey;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct {
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BLOBHEADER hdr;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DWORD len;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BYTE key[16];
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} key_blob;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD mode = CRYPT_MODE_ECB;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != 16)
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.bType = PLAINTEXTKEYBLOB;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.bVersion = CUR_BLOB_VERSION;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.reserved = 0;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.aiKeyAlg = CALG_AES_128;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.len = len;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(key_blob.key, key, len);
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	akey = os_zalloc(sizeof(*akey));
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (akey == NULL)
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptAcquireContext(&akey->prov, NULL,
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 MS_ENH_RSA_AES_PROV, PROV_RSA_AES,
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 CRYPT_VERIFYCONTEXT)) {
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d", (int) GetLastError());
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(akey);
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob),
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    0, 0, &akey->ckey)) {
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(akey->prov, 0);
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(akey);
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) {
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %d", (int) GetLastError());
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptDestroyKey(akey->ckey);
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(akey->prov, 0);
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(akey);
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return akey;
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct aes_context *akey = ctx;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dlen;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(crypt, plain, 16);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dlen = 16;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) {
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(crypt, 0, 16);
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_encrypt_deinit(void *ctx)
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct aes_context *akey = ctx;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (akey) {
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptDestroyKey(akey->ckey);
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(akey->prov, 0);
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(akey);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * aes_decrypt_init(const u8 *key, size_t len)
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return aes_encrypt_init(key, len);
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct aes_context *akey = ctx;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dlen;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(plain, crypt, 16);
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dlen = 16;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) {
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d",
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid aes_decrypt_deinit(void *ctx)
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	aes_encrypt_deinit(ctx);
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_hash {
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum crypto_hash_alg alg;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int error;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV prov;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTHASH hash;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTKEY key;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      size_t key_len)
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct crypto_hash *ctx;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ALG_ID calg;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct {
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BLOBHEADER hdr;
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DWORD len;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BYTE key[32];
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} key_blob;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&key_blob, 0, sizeof(key_blob));
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (alg) {
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_MD5:
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		calg = CALG_MD5;
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_SHA1:
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		calg = CALG_SHA;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_MD5:
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_SHA1:
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		calg = CALG_HMAC;
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.hdr.bType = PLAINTEXTKEYBLOB;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.hdr.bVersion = CUR_BLOB_VERSION;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.hdr.reserved = 0;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Note: RC2 is not really used, but that can be used to
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * import HMAC keys of up to 16 byte long.
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * be able to import longer keys (HMAC-SHA1 uses 20-byte key).
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.hdr.aiKeyAlg = CALG_RC2;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.len = key_len;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_len > sizeof(key_blob.key))
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(key_blob.key, key, key_len);
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->alg = alg;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) {
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_report_error("CryptAcquireContext");
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (calg == CALG_HMAC) {
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CRYPT_IPSEC_HMAC_KEY
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CRYPT_IPSEC_HMAC_KEY 0x00000100
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY,
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    &ctx->key)) {
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cryptoapi_report_error("CryptImportKey");
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			CryptReleaseContext(ctx->prov, 0);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) {
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_report_error("CryptCreateHash");
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(ctx->prov, 0);
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (calg == CALG_HMAC) {
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		HMAC_INFO info;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&info, 0, sizeof(info));
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (alg) {
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case CRYPTO_HASH_ALG_HMAC_MD5:
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			info.HashAlgid = CALG_MD5;
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case CRYPTO_HASH_ALG_HMAC_SHA1:
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			info.HashAlgid = CALG_SHA;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* unreachable */
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info,
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       0)) {
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cryptoapi_report_error("CryptSetHashParam");
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			CryptDestroyHash(ctx->hash);
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			CryptReleaseContext(ctx->prov, 0);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctx);
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ctx;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL || ctx->error)
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) {
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_report_error("CryptHashData");
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctx->error = 1;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD hlen;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (mac == NULL || len == NULL)
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto done;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx->error) {
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -2;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto done;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = *len;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) {
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_report_error("CryptGetHashParam");
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -2;
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = hlen;
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone:
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 ||
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5)
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptDestroyKey(ctx->key);
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_cipher {
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV prov;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTKEY key;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *iv, const u8 *key,
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t key_len)
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct crypto_cipher *ctx;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct {
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BLOBHEADER hdr;
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		DWORD len;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		BYTE key[32];
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} key_blob;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD mode = CRYPT_MODE_CBC;
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.bType = PLAINTEXTKEYBLOB;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.bVersion = CUR_BLOB_VERSION;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.hdr.reserved = 0;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_blob.len = key_len;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_len > sizeof(key_blob.key))
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(key_blob.key, key, key_len);
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (alg) {
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_AES:
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_len == 32)
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			key_blob.hdr.aiKeyAlg = CALG_AES_256;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (key_len == 24)
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			key_blob.hdr.aiKeyAlg = CALG_AES_192;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			key_blob.hdr.aiKeyAlg = CALG_AES_128;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_3DES:
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.hdr.aiKeyAlg = CALG_3DES;
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_DES:
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.hdr.aiKeyAlg = CALG_DES;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_RC2:
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.hdr.aiKeyAlg = CALG_RC2;
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CRYPTO_CIPHER_ALG_RC4:
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_blob.hdr.aiKeyAlg = CALG_RC4;
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV,
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cryptoapi_report_error("CryptAcquireContext");
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail1;
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sizeof(key_blob), 0, 0, &ctx->key)) {
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		cryptoapi_report_error("CryptImportKey");
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail2;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) {
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		cryptoapi_report_error("CryptSetKeyParam(KP_MODE)");
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail3;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) {
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		cryptoapi_report_error("CryptSetKeyParam(KP_IV)");
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail3;
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ctx;
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail3:
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptDestroyKey(ctx->key);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail2:
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptReleaseContext(ctx->prov, 0);
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail1:
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u8 *crypt, size_t len)
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dlen;
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(crypt, plain, len);
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dlen = len;
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) {
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		cryptoapi_report_error("CryptEncrypt");
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(crypt, 0, len);
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  u8 *plain, size_t len)
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dlen;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(plain, crypt, len);
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dlen = len;
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) {
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		cryptoapi_report_error("CryptDecrypt");
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_cipher_deinit(struct crypto_cipher *ctx)
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptDestroyKey(ctx->key);
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CryptReleaseContext(ctx->prov, 0);
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctx);
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_public_key {
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV prov;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTKEY rsa;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_private_key {
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTPROV prov;
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HCRYPTKEY rsa;
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Use crypto_public_key_from_cert() instead. */
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_private_key * crypto_private_key_import(const u8 *key,
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      size_t len,
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      const char *passwd)
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO */
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       size_t len)
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct crypto_public_key *pk;
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PCCERT_CONTEXT cc;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pk = os_zalloc(sizeof(*pk));
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pk == NULL)
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cc = CertCreateCertificateContext(X509_ASN_ENCODING |
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  PKCS_7_ASN_ENCODING, buf, len);
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!cc) {
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		cryptoapi_report_error("CryptCreateCertificateContext");
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pk);
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 0)) {
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		cryptoapi_report_error("CryptAcquireContext");
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pk);
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CertFreeCertificateContext(cc);
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING |
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      PKCS_7_ASN_ENCODING,
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      &cc->pCertInfo->SubjectPublicKeyInfo,
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      &pk->rsa)) {
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 		cryptoapi_report_error("CryptImportPublicKeyInfo");
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(pk->prov, 0);
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pk);
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CertFreeCertificateContext(cc);
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CertFreeCertificateContext(cc);
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pk;
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *in, size_t inlen,
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					u8 *out, size_t *outlen)
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD clen;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *tmp;
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*outlen < inlen)
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = malloc(*outlen);
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(tmp, in, inlen);
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	clen = inlen;
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) {
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using "
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "public key: %d", (int) GetLastError());
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(tmp);
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*outlen = clen;
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Reverse the output */
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < *outlen; i++)
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		out[i] = tmp[*outlen - 1 - i];
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(tmp);
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *in, size_t inlen,
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  u8 *out, size_t *outlen)
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO */
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_public_key_free(struct crypto_public_key *key)
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key) {
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptDestroyKey(key->rsa);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(key->prov, 0);
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(key);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_private_key_free(struct crypto_private_key *key)
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key) {
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptDestroyKey(key->rsa);
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CryptReleaseContext(key->prov, 0);
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(key);
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_global_init(void)
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return mingw_load_crypto_func();
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_global_deinit(void)
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_mod_exp(const u8 *base, size_t base_len,
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *power, size_t power_len,
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   const u8 *modulus, size_t modulus_len,
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   u8 *result, size_t *result_len)
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO */
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
784