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