crypto_cryptoapi.c revision 214734
1189251Ssam/* 2209158Srpaulo * Crypto wrapper for Microsoft CryptoAPI 3209158Srpaulo * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> 4189251Ssam * 5189251Ssam * This program is free software; you can redistribute it and/or modify 6189251Ssam * it under the terms of the GNU General Public License version 2 as 7189251Ssam * published by the Free Software Foundation. 8189251Ssam * 9189251Ssam * Alternatively, this software may be distributed under the terms of BSD 10189251Ssam * license. 11189251Ssam * 12189251Ssam * See README and COPYING for more details. 13189251Ssam */ 14189251Ssam 15189251Ssam#include "includes.h" 16189251Ssam#include <windows.h> 17189251Ssam#include <wincrypt.h> 18189251Ssam 19189251Ssam#include "common.h" 20189251Ssam#include "crypto.h" 21189251Ssam 22189251Ssam#ifndef MS_ENH_RSA_AES_PROV 23189251Ssam#ifdef UNICODE 24189251Ssam#define MS_ENH_RSA_AES_PROV \ 25189251SsamL"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" 26189251Ssam#else 27189251Ssam#define MS_ENH_RSA_AES_PROV \ 28189251Ssam"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" 29189251Ssam#endif 30189251Ssam#endif /* MS_ENH_RSA_AES_PROV */ 31189251Ssam 32189251Ssam#ifndef CALG_HMAC 33189251Ssam#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC) 34189251Ssam#endif 35189251Ssam 36189251Ssam#ifdef __MINGW32_VERSION 37189251Ssam/* 38189251Ssam * MinGW does not yet include all the needed definitions for CryptoAPI, so 39189251Ssam * define here whatever extra is needed. 40189251Ssam */ 41189251Ssam 42189251Ssamstatic BOOL WINAPI 43189251Ssam(*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType, 44189251Ssam PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) 45189251Ssam= NULL; /* to be loaded from crypt32.dll */ 46189251Ssam 47189251Ssam 48189251Ssamstatic int mingw_load_crypto_func(void) 49189251Ssam{ 50189251Ssam HINSTANCE dll; 51189251Ssam 52189251Ssam /* MinGW does not yet have full CryptoAPI support, so load the needed 53189251Ssam * function here. */ 54189251Ssam 55209158Srpaulo if (CryptImportPublicKeyInfo) 56189251Ssam return 0; 57189251Ssam 58189251Ssam dll = LoadLibrary("crypt32"); 59189251Ssam if (dll == NULL) { 60189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 " 61189251Ssam "library"); 62189251Ssam return -1; 63189251Ssam } 64189251Ssam 65189251Ssam CryptImportPublicKeyInfo = GetProcAddress( 66189251Ssam dll, "CryptImportPublicKeyInfo"); 67189251Ssam if (CryptImportPublicKeyInfo == NULL) { 68189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " 69189251Ssam "CryptImportPublicKeyInfo() address from " 70189251Ssam "crypt32 library"); 71189251Ssam return -1; 72189251Ssam } 73189251Ssam 74189251Ssam return 0; 75189251Ssam} 76189251Ssam 77189251Ssam#else /* __MINGW32_VERSION */ 78189251Ssam 79189251Ssamstatic int mingw_load_crypto_func(void) 80189251Ssam{ 81189251Ssam return 0; 82189251Ssam} 83189251Ssam 84189251Ssam#endif /* __MINGW32_VERSION */ 85189251Ssam 86189251Ssam 87189251Ssamstatic void cryptoapi_report_error(const char *msg) 88189251Ssam{ 89189251Ssam char *s, *pos; 90189251Ssam DWORD err = GetLastError(); 91189251Ssam 92189251Ssam if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 93189251Ssam FORMAT_MESSAGE_FROM_SYSTEM, 94189251Ssam NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) { 95189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err); 96189251Ssam } 97189251Ssam 98189251Ssam pos = s; 99189251Ssam while (*pos) { 100189251Ssam if (*pos == '\n' || *pos == '\r') { 101189251Ssam *pos = '\0'; 102189251Ssam break; 103189251Ssam } 104189251Ssam pos++; 105189251Ssam } 106189251Ssam 107189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s); 108189251Ssam LocalFree(s); 109189251Ssam} 110189251Ssam 111189251Ssam 112189251Ssamint cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem, 113189251Ssam const u8 *addr[], const size_t *len, u8 *mac) 114189251Ssam{ 115189251Ssam HCRYPTPROV prov; 116189251Ssam HCRYPTHASH hash; 117189251Ssam size_t i; 118189251Ssam DWORD hlen; 119189251Ssam int ret = 0; 120189251Ssam 121189251Ssam if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) { 122189251Ssam cryptoapi_report_error("CryptAcquireContext"); 123189251Ssam return -1; 124189251Ssam } 125189251Ssam 126189251Ssam if (!CryptCreateHash(prov, alg, 0, 0, &hash)) { 127189251Ssam cryptoapi_report_error("CryptCreateHash"); 128189251Ssam CryptReleaseContext(prov, 0); 129189251Ssam return -1; 130189251Ssam } 131189251Ssam 132189251Ssam for (i = 0; i < num_elem; i++) { 133189251Ssam if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) { 134189251Ssam cryptoapi_report_error("CryptHashData"); 135189251Ssam CryptDestroyHash(hash); 136189251Ssam CryptReleaseContext(prov, 0); 137189251Ssam } 138189251Ssam } 139189251Ssam 140189251Ssam hlen = hash_len; 141189251Ssam if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) { 142189251Ssam cryptoapi_report_error("CryptGetHashParam"); 143189251Ssam ret = -1; 144189251Ssam } 145189251Ssam 146189251Ssam CryptDestroyHash(hash); 147189251Ssam CryptReleaseContext(prov, 0); 148189251Ssam 149189251Ssam return ret; 150189251Ssam} 151189251Ssam 152189251Ssam 153214734Srpauloint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 154189251Ssam{ 155214734Srpaulo return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac); 156189251Ssam} 157189251Ssam 158189251Ssam 159189251Ssamvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 160189251Ssam{ 161189251Ssam u8 next, tmp; 162189251Ssam int i; 163189251Ssam HCRYPTPROV prov; 164189251Ssam HCRYPTKEY ckey; 165189251Ssam DWORD dlen; 166189251Ssam struct { 167189251Ssam BLOBHEADER hdr; 168189251Ssam DWORD len; 169189251Ssam BYTE key[8]; 170189251Ssam } key_blob; 171189251Ssam DWORD mode = CRYPT_MODE_ECB; 172189251Ssam 173189251Ssam key_blob.hdr.bType = PLAINTEXTKEYBLOB; 174189251Ssam key_blob.hdr.bVersion = CUR_BLOB_VERSION; 175189251Ssam key_blob.hdr.reserved = 0; 176189251Ssam key_blob.hdr.aiKeyAlg = CALG_DES; 177189251Ssam key_blob.len = 8; 178189251Ssam 179189251Ssam /* Add parity bits to the key */ 180189251Ssam next = 0; 181189251Ssam for (i = 0; i < 7; i++) { 182189251Ssam tmp = key[i]; 183189251Ssam key_blob.key[i] = (tmp >> i) | next | 1; 184189251Ssam next = tmp << (7 - i); 185189251Ssam } 186189251Ssam key_blob.key[i] = next | 1; 187189251Ssam 188189251Ssam if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 189189251Ssam CRYPT_VERIFYCONTEXT)) { 190189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " 191189251Ssam "%d", (int) GetLastError()); 192189251Ssam return; 193189251Ssam } 194189251Ssam 195189251Ssam if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, 196189251Ssam &ckey)) { 197189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", 198189251Ssam (int) GetLastError()); 199189251Ssam CryptReleaseContext(prov, 0); 200189251Ssam return; 201189251Ssam } 202189251Ssam 203189251Ssam if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) { 204189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " 205189251Ssam "failed: %d", (int) GetLastError()); 206189251Ssam CryptDestroyKey(ckey); 207189251Ssam CryptReleaseContext(prov, 0); 208189251Ssam return; 209189251Ssam } 210189251Ssam 211189251Ssam os_memcpy(cypher, clear, 8); 212189251Ssam dlen = 8; 213189251Ssam if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) { 214189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", 215189251Ssam (int) GetLastError()); 216189251Ssam os_memset(cypher, 0, 8); 217189251Ssam } 218189251Ssam 219189251Ssam CryptDestroyKey(ckey); 220189251Ssam CryptReleaseContext(prov, 0); 221189251Ssam} 222189251Ssam 223189251Ssam 224214734Srpauloint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 225189251Ssam{ 226214734Srpaulo return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); 227189251Ssam} 228189251Ssam 229189251Ssam 230214734Srpauloint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 231189251Ssam{ 232214734Srpaulo return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac); 233189251Ssam} 234189251Ssam 235189251Ssam 236189251Ssamstruct aes_context { 237189251Ssam HCRYPTPROV prov; 238189251Ssam HCRYPTKEY ckey; 239189251Ssam}; 240189251Ssam 241189251Ssam 242189251Ssamvoid * aes_encrypt_init(const u8 *key, size_t len) 243189251Ssam{ 244189251Ssam struct aes_context *akey; 245189251Ssam struct { 246189251Ssam BLOBHEADER hdr; 247189251Ssam DWORD len; 248189251Ssam BYTE key[16]; 249189251Ssam } key_blob; 250189251Ssam DWORD mode = CRYPT_MODE_ECB; 251189251Ssam 252189251Ssam if (len != 16) 253189251Ssam return NULL; 254189251Ssam 255189251Ssam key_blob.hdr.bType = PLAINTEXTKEYBLOB; 256189251Ssam key_blob.hdr.bVersion = CUR_BLOB_VERSION; 257189251Ssam key_blob.hdr.reserved = 0; 258189251Ssam key_blob.hdr.aiKeyAlg = CALG_AES_128; 259189251Ssam key_blob.len = len; 260189251Ssam os_memcpy(key_blob.key, key, len); 261189251Ssam 262189251Ssam akey = os_zalloc(sizeof(*akey)); 263189251Ssam if (akey == NULL) 264189251Ssam return NULL; 265189251Ssam 266189251Ssam if (!CryptAcquireContext(&akey->prov, NULL, 267189251Ssam MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 268189251Ssam CRYPT_VERIFYCONTEXT)) { 269189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " 270189251Ssam "%d", (int) GetLastError()); 271189251Ssam os_free(akey); 272189251Ssam return NULL; 273189251Ssam } 274189251Ssam 275189251Ssam if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob), 276189251Ssam 0, 0, &akey->ckey)) { 277189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", 278189251Ssam (int) GetLastError()); 279189251Ssam CryptReleaseContext(akey->prov, 0); 280189251Ssam os_free(akey); 281189251Ssam return NULL; 282189251Ssam } 283189251Ssam 284189251Ssam if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) { 285189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " 286189251Ssam "failed: %d", (int) GetLastError()); 287189251Ssam CryptDestroyKey(akey->ckey); 288189251Ssam CryptReleaseContext(akey->prov, 0); 289189251Ssam os_free(akey); 290189251Ssam return NULL; 291189251Ssam } 292189251Ssam 293189251Ssam return akey; 294189251Ssam} 295189251Ssam 296189251Ssam 297189251Ssamvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 298189251Ssam{ 299189251Ssam struct aes_context *akey = ctx; 300189251Ssam DWORD dlen; 301189251Ssam 302189251Ssam os_memcpy(crypt, plain, 16); 303189251Ssam dlen = 16; 304189251Ssam if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) { 305189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", 306189251Ssam (int) GetLastError()); 307189251Ssam os_memset(crypt, 0, 16); 308189251Ssam } 309189251Ssam} 310189251Ssam 311189251Ssam 312189251Ssamvoid aes_encrypt_deinit(void *ctx) 313189251Ssam{ 314189251Ssam struct aes_context *akey = ctx; 315189251Ssam if (akey) { 316189251Ssam CryptDestroyKey(akey->ckey); 317189251Ssam CryptReleaseContext(akey->prov, 0); 318189251Ssam os_free(akey); 319189251Ssam } 320189251Ssam} 321189251Ssam 322189251Ssam 323189251Ssamvoid * aes_decrypt_init(const u8 *key, size_t len) 324189251Ssam{ 325189251Ssam return aes_encrypt_init(key, len); 326189251Ssam} 327189251Ssam 328189251Ssam 329189251Ssamvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 330189251Ssam{ 331189251Ssam struct aes_context *akey = ctx; 332189251Ssam DWORD dlen; 333189251Ssam 334189251Ssam os_memcpy(plain, crypt, 16); 335189251Ssam dlen = 16; 336189251Ssam 337189251Ssam if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) { 338189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d", 339189251Ssam (int) GetLastError()); 340189251Ssam } 341189251Ssam} 342189251Ssam 343189251Ssam 344189251Ssamvoid aes_decrypt_deinit(void *ctx) 345189251Ssam{ 346189251Ssam aes_encrypt_deinit(ctx); 347189251Ssam} 348189251Ssam 349189251Ssam 350189251Ssamstruct crypto_hash { 351189251Ssam enum crypto_hash_alg alg; 352189251Ssam int error; 353189251Ssam HCRYPTPROV prov; 354189251Ssam HCRYPTHASH hash; 355189251Ssam HCRYPTKEY key; 356189251Ssam}; 357189251Ssam 358189251Ssamstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 359189251Ssam size_t key_len) 360189251Ssam{ 361189251Ssam struct crypto_hash *ctx; 362189251Ssam ALG_ID calg; 363189251Ssam struct { 364189251Ssam BLOBHEADER hdr; 365189251Ssam DWORD len; 366189251Ssam BYTE key[32]; 367189251Ssam } key_blob; 368189251Ssam 369189251Ssam os_memset(&key_blob, 0, sizeof(key_blob)); 370189251Ssam switch (alg) { 371189251Ssam case CRYPTO_HASH_ALG_MD5: 372189251Ssam calg = CALG_MD5; 373189251Ssam break; 374189251Ssam case CRYPTO_HASH_ALG_SHA1: 375189251Ssam calg = CALG_SHA; 376189251Ssam break; 377189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 378189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 379189251Ssam calg = CALG_HMAC; 380189251Ssam key_blob.hdr.bType = PLAINTEXTKEYBLOB; 381189251Ssam key_blob.hdr.bVersion = CUR_BLOB_VERSION; 382189251Ssam key_blob.hdr.reserved = 0; 383189251Ssam /* 384189251Ssam * Note: RC2 is not really used, but that can be used to 385189251Ssam * import HMAC keys of up to 16 byte long. 386189251Ssam * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to 387189251Ssam * be able to import longer keys (HMAC-SHA1 uses 20-byte key). 388189251Ssam */ 389189251Ssam key_blob.hdr.aiKeyAlg = CALG_RC2; 390189251Ssam key_blob.len = key_len; 391189251Ssam if (key_len > sizeof(key_blob.key)) 392189251Ssam return NULL; 393189251Ssam os_memcpy(key_blob.key, key, key_len); 394189251Ssam break; 395189251Ssam default: 396189251Ssam return NULL; 397189251Ssam } 398189251Ssam 399189251Ssam ctx = os_zalloc(sizeof(*ctx)); 400189251Ssam if (ctx == NULL) 401189251Ssam return NULL; 402189251Ssam 403189251Ssam ctx->alg = alg; 404189251Ssam 405189251Ssam if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) { 406189251Ssam cryptoapi_report_error("CryptAcquireContext"); 407189251Ssam os_free(ctx); 408189251Ssam return NULL; 409189251Ssam } 410189251Ssam 411189251Ssam if (calg == CALG_HMAC) { 412189251Ssam#ifndef CRYPT_IPSEC_HMAC_KEY 413189251Ssam#define CRYPT_IPSEC_HMAC_KEY 0x00000100 414189251Ssam#endif 415189251Ssam if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, 416189251Ssam sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY, 417189251Ssam &ctx->key)) { 418189251Ssam cryptoapi_report_error("CryptImportKey"); 419189251Ssam CryptReleaseContext(ctx->prov, 0); 420189251Ssam os_free(ctx); 421189251Ssam return NULL; 422189251Ssam } 423189251Ssam } 424189251Ssam 425189251Ssam if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) { 426189251Ssam cryptoapi_report_error("CryptCreateHash"); 427189251Ssam CryptReleaseContext(ctx->prov, 0); 428189251Ssam os_free(ctx); 429189251Ssam return NULL; 430189251Ssam } 431189251Ssam 432189251Ssam if (calg == CALG_HMAC) { 433189251Ssam HMAC_INFO info; 434189251Ssam os_memset(&info, 0, sizeof(info)); 435189251Ssam switch (alg) { 436189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 437189251Ssam info.HashAlgid = CALG_MD5; 438189251Ssam break; 439189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 440189251Ssam info.HashAlgid = CALG_SHA; 441189251Ssam break; 442189251Ssam default: 443189251Ssam /* unreachable */ 444189251Ssam break; 445189251Ssam } 446189251Ssam 447189251Ssam if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info, 448189251Ssam 0)) { 449189251Ssam cryptoapi_report_error("CryptSetHashParam"); 450189251Ssam CryptDestroyHash(ctx->hash); 451189251Ssam CryptReleaseContext(ctx->prov, 0); 452189251Ssam os_free(ctx); 453189251Ssam return NULL; 454189251Ssam } 455189251Ssam } 456189251Ssam 457189251Ssam return ctx; 458189251Ssam} 459189251Ssam 460189251Ssam 461189251Ssamvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 462189251Ssam{ 463189251Ssam if (ctx == NULL || ctx->error) 464189251Ssam return; 465189251Ssam 466189251Ssam if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) { 467189251Ssam cryptoapi_report_error("CryptHashData"); 468189251Ssam ctx->error = 1; 469189251Ssam } 470189251Ssam} 471189251Ssam 472189251Ssam 473189251Ssamint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 474189251Ssam{ 475189251Ssam int ret = 0; 476189251Ssam DWORD hlen; 477189251Ssam 478189251Ssam if (ctx == NULL) 479189251Ssam return -2; 480189251Ssam 481189251Ssam if (mac == NULL || len == NULL) 482189251Ssam goto done; 483189251Ssam 484189251Ssam if (ctx->error) { 485189251Ssam ret = -2; 486189251Ssam goto done; 487189251Ssam } 488189251Ssam 489189251Ssam hlen = *len; 490189251Ssam if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) { 491189251Ssam cryptoapi_report_error("CryptGetHashParam"); 492189251Ssam ret = -2; 493189251Ssam } 494189251Ssam *len = hlen; 495189251Ssam 496189251Ssamdone: 497189251Ssam if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 || 498189251Ssam ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5) 499189251Ssam CryptDestroyKey(ctx->key); 500189251Ssam 501189251Ssam os_free(ctx); 502189251Ssam 503189251Ssam return ret; 504189251Ssam} 505189251Ssam 506189251Ssam 507189251Ssamstruct crypto_cipher { 508189251Ssam HCRYPTPROV prov; 509189251Ssam HCRYPTKEY key; 510189251Ssam}; 511189251Ssam 512189251Ssam 513189251Ssamstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 514189251Ssam const u8 *iv, const u8 *key, 515189251Ssam size_t key_len) 516189251Ssam{ 517189251Ssam struct crypto_cipher *ctx; 518189251Ssam struct { 519189251Ssam BLOBHEADER hdr; 520189251Ssam DWORD len; 521189251Ssam BYTE key[32]; 522189251Ssam } key_blob; 523189251Ssam DWORD mode = CRYPT_MODE_CBC; 524189251Ssam 525189251Ssam key_blob.hdr.bType = PLAINTEXTKEYBLOB; 526189251Ssam key_blob.hdr.bVersion = CUR_BLOB_VERSION; 527189251Ssam key_blob.hdr.reserved = 0; 528189251Ssam key_blob.len = key_len; 529189251Ssam if (key_len > sizeof(key_blob.key)) 530189251Ssam return NULL; 531189251Ssam os_memcpy(key_blob.key, key, key_len); 532189251Ssam 533189251Ssam switch (alg) { 534189251Ssam case CRYPTO_CIPHER_ALG_AES: 535189251Ssam if (key_len == 32) 536189251Ssam key_blob.hdr.aiKeyAlg = CALG_AES_256; 537189251Ssam else if (key_len == 24) 538189251Ssam key_blob.hdr.aiKeyAlg = CALG_AES_192; 539189251Ssam else 540189251Ssam key_blob.hdr.aiKeyAlg = CALG_AES_128; 541189251Ssam break; 542189251Ssam case CRYPTO_CIPHER_ALG_3DES: 543189251Ssam key_blob.hdr.aiKeyAlg = CALG_3DES; 544189251Ssam break; 545189251Ssam case CRYPTO_CIPHER_ALG_DES: 546189251Ssam key_blob.hdr.aiKeyAlg = CALG_DES; 547189251Ssam break; 548189251Ssam case CRYPTO_CIPHER_ALG_RC2: 549189251Ssam key_blob.hdr.aiKeyAlg = CALG_RC2; 550189251Ssam break; 551189251Ssam case CRYPTO_CIPHER_ALG_RC4: 552189251Ssam key_blob.hdr.aiKeyAlg = CALG_RC4; 553189251Ssam break; 554189251Ssam default: 555189251Ssam return NULL; 556189251Ssam } 557189251Ssam 558189251Ssam ctx = os_zalloc(sizeof(*ctx)); 559189251Ssam if (ctx == NULL) 560189251Ssam return NULL; 561189251Ssam 562189251Ssam if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV, 563189251Ssam PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { 564189251Ssam cryptoapi_report_error("CryptAcquireContext"); 565189251Ssam goto fail1; 566189251Ssam } 567189251Ssam 568189251Ssam if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, 569189251Ssam sizeof(key_blob), 0, 0, &ctx->key)) { 570189251Ssam cryptoapi_report_error("CryptImportKey"); 571189251Ssam goto fail2; 572189251Ssam } 573189251Ssam 574189251Ssam if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) { 575189251Ssam cryptoapi_report_error("CryptSetKeyParam(KP_MODE)"); 576189251Ssam goto fail3; 577189251Ssam } 578189251Ssam 579189251Ssam if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) { 580189251Ssam cryptoapi_report_error("CryptSetKeyParam(KP_IV)"); 581189251Ssam goto fail3; 582189251Ssam } 583189251Ssam 584189251Ssam return ctx; 585189251Ssam 586189251Ssamfail3: 587189251Ssam CryptDestroyKey(ctx->key); 588189251Ssamfail2: 589189251Ssam CryptReleaseContext(ctx->prov, 0); 590189251Ssamfail1: 591189251Ssam os_free(ctx); 592189251Ssam return NULL; 593189251Ssam} 594189251Ssam 595189251Ssam 596189251Ssamint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 597189251Ssam u8 *crypt, size_t len) 598189251Ssam{ 599189251Ssam DWORD dlen; 600189251Ssam 601189251Ssam os_memcpy(crypt, plain, len); 602189251Ssam dlen = len; 603189251Ssam if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) { 604189251Ssam cryptoapi_report_error("CryptEncrypt"); 605189251Ssam os_memset(crypt, 0, len); 606189251Ssam return -1; 607189251Ssam } 608189251Ssam 609189251Ssam return 0; 610189251Ssam} 611189251Ssam 612189251Ssam 613189251Ssamint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 614189251Ssam u8 *plain, size_t len) 615189251Ssam{ 616189251Ssam DWORD dlen; 617189251Ssam 618189251Ssam os_memcpy(plain, crypt, len); 619189251Ssam dlen = len; 620189251Ssam if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) { 621189251Ssam cryptoapi_report_error("CryptDecrypt"); 622189251Ssam return -1; 623189251Ssam } 624189251Ssam 625189251Ssam return 0; 626189251Ssam} 627189251Ssam 628189251Ssam 629189251Ssamvoid crypto_cipher_deinit(struct crypto_cipher *ctx) 630189251Ssam{ 631189251Ssam CryptDestroyKey(ctx->key); 632189251Ssam CryptReleaseContext(ctx->prov, 0); 633189251Ssam os_free(ctx); 634189251Ssam} 635189251Ssam 636189251Ssam 637189251Ssamstruct crypto_public_key { 638189251Ssam HCRYPTPROV prov; 639189251Ssam HCRYPTKEY rsa; 640189251Ssam}; 641189251Ssam 642189251Ssamstruct crypto_private_key { 643189251Ssam HCRYPTPROV prov; 644189251Ssam HCRYPTKEY rsa; 645189251Ssam}; 646189251Ssam 647189251Ssam 648189251Ssamstruct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) 649189251Ssam{ 650189251Ssam /* Use crypto_public_key_from_cert() instead. */ 651189251Ssam return NULL; 652189251Ssam} 653189251Ssam 654189251Ssam 655189251Ssamstruct crypto_private_key * crypto_private_key_import(const u8 *key, 656214734Srpaulo size_t len, 657214734Srpaulo const char *passwd) 658189251Ssam{ 659189251Ssam /* TODO */ 660189251Ssam return NULL; 661189251Ssam} 662189251Ssam 663189251Ssam 664189251Ssamstruct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, 665189251Ssam size_t len) 666189251Ssam{ 667189251Ssam struct crypto_public_key *pk; 668189251Ssam PCCERT_CONTEXT cc; 669189251Ssam 670189251Ssam pk = os_zalloc(sizeof(*pk)); 671189251Ssam if (pk == NULL) 672189251Ssam return NULL; 673189251Ssam 674189251Ssam cc = CertCreateCertificateContext(X509_ASN_ENCODING | 675189251Ssam PKCS_7_ASN_ENCODING, buf, len); 676189251Ssam if (!cc) { 677189251Ssam cryptoapi_report_error("CryptCreateCertificateContext"); 678189251Ssam os_free(pk); 679189251Ssam return NULL; 680189251Ssam } 681189251Ssam 682189251Ssam if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, 683189251Ssam 0)) { 684189251Ssam cryptoapi_report_error("CryptAcquireContext"); 685189251Ssam os_free(pk); 686189251Ssam CertFreeCertificateContext(cc); 687189251Ssam return NULL; 688189251Ssam } 689189251Ssam 690189251Ssam if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING | 691189251Ssam PKCS_7_ASN_ENCODING, 692189251Ssam &cc->pCertInfo->SubjectPublicKeyInfo, 693189251Ssam &pk->rsa)) { 694189251Ssam cryptoapi_report_error("CryptImportPublicKeyInfo"); 695189251Ssam CryptReleaseContext(pk->prov, 0); 696189251Ssam os_free(pk); 697189251Ssam CertFreeCertificateContext(cc); 698189251Ssam return NULL; 699189251Ssam } 700189251Ssam 701189251Ssam CertFreeCertificateContext(cc); 702189251Ssam 703189251Ssam return pk; 704189251Ssam} 705189251Ssam 706189251Ssam 707189251Ssamint crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, 708189251Ssam const u8 *in, size_t inlen, 709189251Ssam u8 *out, size_t *outlen) 710189251Ssam{ 711189251Ssam DWORD clen; 712189251Ssam u8 *tmp; 713189251Ssam size_t i; 714189251Ssam 715189251Ssam if (*outlen < inlen) 716189251Ssam return -1; 717189251Ssam tmp = malloc(*outlen); 718189251Ssam if (tmp == NULL) 719189251Ssam return -1; 720189251Ssam 721189251Ssam os_memcpy(tmp, in, inlen); 722189251Ssam clen = inlen; 723189251Ssam if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) { 724189251Ssam wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using " 725189251Ssam "public key: %d", (int) GetLastError()); 726189251Ssam os_free(tmp); 727189251Ssam return -1; 728189251Ssam } 729189251Ssam 730189251Ssam *outlen = clen; 731189251Ssam 732189251Ssam /* Reverse the output */ 733189251Ssam for (i = 0; i < *outlen; i++) 734189251Ssam out[i] = tmp[*outlen - 1 - i]; 735189251Ssam 736189251Ssam os_free(tmp); 737189251Ssam 738189251Ssam return 0; 739189251Ssam} 740189251Ssam 741189251Ssam 742189251Ssamint crypto_private_key_sign_pkcs1(struct crypto_private_key *key, 743189251Ssam const u8 *in, size_t inlen, 744189251Ssam u8 *out, size_t *outlen) 745189251Ssam{ 746189251Ssam /* TODO */ 747189251Ssam return -1; 748189251Ssam} 749189251Ssam 750189251Ssam 751189251Ssamvoid crypto_public_key_free(struct crypto_public_key *key) 752189251Ssam{ 753189251Ssam if (key) { 754189251Ssam CryptDestroyKey(key->rsa); 755189251Ssam CryptReleaseContext(key->prov, 0); 756189251Ssam os_free(key); 757189251Ssam } 758189251Ssam} 759189251Ssam 760189251Ssam 761189251Ssamvoid crypto_private_key_free(struct crypto_private_key *key) 762189251Ssam{ 763189251Ssam if (key) { 764189251Ssam CryptDestroyKey(key->rsa); 765189251Ssam CryptReleaseContext(key->prov, 0); 766189251Ssam os_free(key); 767189251Ssam } 768189251Ssam} 769189251Ssam 770189251Ssam 771189251Ssamint crypto_global_init(void) 772189251Ssam{ 773189251Ssam return mingw_load_crypto_func(); 774189251Ssam} 775189251Ssam 776189251Ssam 777189251Ssamvoid crypto_global_deinit(void) 778189251Ssam{ 779189251Ssam} 780189251Ssam 781189251Ssam 782214734Srpauloint crypto_mod_exp(const u8 *base, size_t base_len, 783214734Srpaulo const u8 *power, size_t power_len, 784214734Srpaulo const u8 *modulus, size_t modulus_len, 785214734Srpaulo u8 *result, size_t *result_len) 786214734Srpaulo{ 787214734Srpaulo /* TODO */ 788214734Srpaulo return -1; 789214734Srpaulo} 790