$search
00001 /* 00002 * Crypto wrapper for Microsoft CryptoAPI 00003 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 #include <windows.h> 00017 #include <wincrypt.h> 00018 00019 #include "common.h" 00020 #include "crypto.h" 00021 00022 #ifndef MS_ENH_RSA_AES_PROV 00023 #ifdef UNICODE 00024 #define MS_ENH_RSA_AES_PROV \ 00025 L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" 00026 #else 00027 #define MS_ENH_RSA_AES_PROV \ 00028 "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" 00029 #endif 00030 #endif /* MS_ENH_RSA_AES_PROV */ 00031 00032 #ifndef CALG_HMAC 00033 #define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC) 00034 #endif 00035 00036 #ifdef __MINGW32_VERSION 00037 /* 00038 * MinGW does not yet include all the needed definitions for CryptoAPI, so 00039 * define here whatever extra is needed. 00040 */ 00041 00042 static BOOL WINAPI 00043 (*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType, 00044 PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) 00045 = NULL; /* to be loaded from crypt32.dll */ 00046 00047 00048 static int mingw_load_crypto_func(void) 00049 { 00050 HINSTANCE dll; 00051 00052 /* MinGW does not yet have full CryptoAPI support, so load the needed 00053 * function here. */ 00054 00055 if (CryptImportPublicKeyInfo) 00056 return 0; 00057 00058 dll = LoadLibrary("crypt32"); 00059 if (dll == NULL) { 00060 wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 " 00061 "library"); 00062 return -1; 00063 } 00064 00065 CryptImportPublicKeyInfo = GetProcAddress( 00066 dll, "CryptImportPublicKeyInfo"); 00067 if (CryptImportPublicKeyInfo == NULL) { 00068 wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " 00069 "CryptImportPublicKeyInfo() address from " 00070 "crypt32 library"); 00071 return -1; 00072 } 00073 00074 return 0; 00075 } 00076 00077 #else /* __MINGW32_VERSION */ 00078 00079 static int mingw_load_crypto_func(void) 00080 { 00081 return 0; 00082 } 00083 00084 #endif /* __MINGW32_VERSION */ 00085 00086 00087 static void cryptoapi_report_error(const char *msg) 00088 { 00089 char *s, *pos; 00090 DWORD err = GetLastError(); 00091 00092 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 00093 FORMAT_MESSAGE_FROM_SYSTEM, 00094 NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) { 00095 wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err); 00096 } 00097 00098 pos = s; 00099 while (*pos) { 00100 if (*pos == '\n' || *pos == '\r') { 00101 *pos = '\0'; 00102 break; 00103 } 00104 pos++; 00105 } 00106 00107 wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s); 00108 LocalFree(s); 00109 } 00110 00111 00112 int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem, 00113 const u8 *addr[], const size_t *len, u8 *mac) 00114 { 00115 HCRYPTPROV prov; 00116 HCRYPTHASH hash; 00117 size_t i; 00118 DWORD hlen; 00119 int ret = 0; 00120 00121 if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) { 00122 cryptoapi_report_error("CryptAcquireContext"); 00123 return -1; 00124 } 00125 00126 if (!CryptCreateHash(prov, alg, 0, 0, &hash)) { 00127 cryptoapi_report_error("CryptCreateHash"); 00128 CryptReleaseContext(prov, 0); 00129 return -1; 00130 } 00131 00132 for (i = 0; i < num_elem; i++) { 00133 if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) { 00134 cryptoapi_report_error("CryptHashData"); 00135 CryptDestroyHash(hash); 00136 CryptReleaseContext(prov, 0); 00137 } 00138 } 00139 00140 hlen = hash_len; 00141 if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) { 00142 cryptoapi_report_error("CryptGetHashParam"); 00143 ret = -1; 00144 } 00145 00146 CryptDestroyHash(hash); 00147 CryptReleaseContext(prov, 0); 00148 00149 return ret; 00150 } 00151 00152 00153 int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 00154 { 00155 return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac); 00156 } 00157 00158 00159 void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 00160 { 00161 u8 next, tmp; 00162 int i; 00163 HCRYPTPROV prov; 00164 HCRYPTKEY ckey; 00165 DWORD dlen; 00166 struct { 00167 BLOBHEADER hdr; 00168 DWORD len; 00169 BYTE key[8]; 00170 } key_blob; 00171 DWORD mode = CRYPT_MODE_ECB; 00172 00173 key_blob.hdr.bType = PLAINTEXTKEYBLOB; 00174 key_blob.hdr.bVersion = CUR_BLOB_VERSION; 00175 key_blob.hdr.reserved = 0; 00176 key_blob.hdr.aiKeyAlg = CALG_DES; 00177 key_blob.len = 8; 00178 00179 /* Add parity bits to the key */ 00180 next = 0; 00181 for (i = 0; i < 7; i++) { 00182 tmp = key[i]; 00183 key_blob.key[i] = (tmp >> i) | next | 1; 00184 next = tmp << (7 - i); 00185 } 00186 key_blob.key[i] = next | 1; 00187 00188 if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 00189 CRYPT_VERIFYCONTEXT)) { 00190 wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " 00191 "%d", (int) GetLastError()); 00192 return; 00193 } 00194 00195 if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, 00196 &ckey)) { 00197 wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", 00198 (int) GetLastError()); 00199 CryptReleaseContext(prov, 0); 00200 return; 00201 } 00202 00203 if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) { 00204 wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " 00205 "failed: %d", (int) GetLastError()); 00206 CryptDestroyKey(ckey); 00207 CryptReleaseContext(prov, 0); 00208 return; 00209 } 00210 00211 os_memcpy(cypher, clear, 8); 00212 dlen = 8; 00213 if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) { 00214 wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", 00215 (int) GetLastError()); 00216 os_memset(cypher, 0, 8); 00217 } 00218 00219 CryptDestroyKey(ckey); 00220 CryptReleaseContext(prov, 0); 00221 } 00222 00223 00224 int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 00225 { 00226 return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); 00227 } 00228 00229 00230 int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 00231 { 00232 return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac); 00233 } 00234 00235 00236 struct aes_context { 00237 HCRYPTPROV prov; 00238 HCRYPTKEY ckey; 00239 }; 00240 00241 00242 void * aes_encrypt_init(const u8 *key, size_t len) 00243 { 00244 struct aes_context *akey; 00245 struct { 00246 BLOBHEADER hdr; 00247 DWORD len; 00248 BYTE key[16]; 00249 } key_blob; 00250 DWORD mode = CRYPT_MODE_ECB; 00251 00252 if (len != 16) 00253 return NULL; 00254 00255 key_blob.hdr.bType = PLAINTEXTKEYBLOB; 00256 key_blob.hdr.bVersion = CUR_BLOB_VERSION; 00257 key_blob.hdr.reserved = 0; 00258 key_blob.hdr.aiKeyAlg = CALG_AES_128; 00259 key_blob.len = len; 00260 os_memcpy(key_blob.key, key, len); 00261 00262 akey = os_zalloc(sizeof(*akey)); 00263 if (akey == NULL) 00264 return NULL; 00265 00266 if (!CryptAcquireContext(&akey->prov, NULL, 00267 MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 00268 CRYPT_VERIFYCONTEXT)) { 00269 wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " 00270 "%d", (int) GetLastError()); 00271 os_free(akey); 00272 return NULL; 00273 } 00274 00275 if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob), 00276 0, 0, &akey->ckey)) { 00277 wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", 00278 (int) GetLastError()); 00279 CryptReleaseContext(akey->prov, 0); 00280 os_free(akey); 00281 return NULL; 00282 } 00283 00284 if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) { 00285 wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " 00286 "failed: %d", (int) GetLastError()); 00287 CryptDestroyKey(akey->ckey); 00288 CryptReleaseContext(akey->prov, 0); 00289 os_free(akey); 00290 return NULL; 00291 } 00292 00293 return akey; 00294 } 00295 00296 00297 void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 00298 { 00299 struct aes_context *akey = ctx; 00300 DWORD dlen; 00301 00302 os_memcpy(crypt, plain, 16); 00303 dlen = 16; 00304 if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) { 00305 wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", 00306 (int) GetLastError()); 00307 os_memset(crypt, 0, 16); 00308 } 00309 } 00310 00311 00312 void aes_encrypt_deinit(void *ctx) 00313 { 00314 struct aes_context *akey = ctx; 00315 if (akey) { 00316 CryptDestroyKey(akey->ckey); 00317 CryptReleaseContext(akey->prov, 0); 00318 os_free(akey); 00319 } 00320 } 00321 00322 00323 void * aes_decrypt_init(const u8 *key, size_t len) 00324 { 00325 return aes_encrypt_init(key, len); 00326 } 00327 00328 00329 void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 00330 { 00331 struct aes_context *akey = ctx; 00332 DWORD dlen; 00333 00334 os_memcpy(plain, crypt, 16); 00335 dlen = 16; 00336 00337 if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) { 00338 wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d", 00339 (int) GetLastError()); 00340 } 00341 } 00342 00343 00344 void aes_decrypt_deinit(void *ctx) 00345 { 00346 aes_encrypt_deinit(ctx); 00347 } 00348 00349 00350 struct crypto_hash { 00351 enum crypto_hash_alg alg; 00352 int error; 00353 HCRYPTPROV prov; 00354 HCRYPTHASH hash; 00355 HCRYPTKEY key; 00356 }; 00357 00358 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 00359 size_t key_len) 00360 { 00361 struct crypto_hash *ctx; 00362 ALG_ID calg; 00363 struct { 00364 BLOBHEADER hdr; 00365 DWORD len; 00366 BYTE key[32]; 00367 } key_blob; 00368 00369 os_memset(&key_blob, 0, sizeof(key_blob)); 00370 switch (alg) { 00371 case CRYPTO_HASH_ALG_MD5: 00372 calg = CALG_MD5; 00373 break; 00374 case CRYPTO_HASH_ALG_SHA1: 00375 calg = CALG_SHA; 00376 break; 00377 case CRYPTO_HASH_ALG_HMAC_MD5: 00378 case CRYPTO_HASH_ALG_HMAC_SHA1: 00379 calg = CALG_HMAC; 00380 key_blob.hdr.bType = PLAINTEXTKEYBLOB; 00381 key_blob.hdr.bVersion = CUR_BLOB_VERSION; 00382 key_blob.hdr.reserved = 0; 00383 /* 00384 * Note: RC2 is not really used, but that can be used to 00385 * import HMAC keys of up to 16 byte long. 00386 * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to 00387 * be able to import longer keys (HMAC-SHA1 uses 20-byte key). 00388 */ 00389 key_blob.hdr.aiKeyAlg = CALG_RC2; 00390 key_blob.len = key_len; 00391 if (key_len > sizeof(key_blob.key)) 00392 return NULL; 00393 os_memcpy(key_blob.key, key, key_len); 00394 break; 00395 default: 00396 return NULL; 00397 } 00398 00399 ctx = os_zalloc(sizeof(*ctx)); 00400 if (ctx == NULL) 00401 return NULL; 00402 00403 ctx->alg = alg; 00404 00405 if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) { 00406 cryptoapi_report_error("CryptAcquireContext"); 00407 os_free(ctx); 00408 return NULL; 00409 } 00410 00411 if (calg == CALG_HMAC) { 00412 #ifndef CRYPT_IPSEC_HMAC_KEY 00413 #define CRYPT_IPSEC_HMAC_KEY 0x00000100 00414 #endif 00415 if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, 00416 sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY, 00417 &ctx->key)) { 00418 cryptoapi_report_error("CryptImportKey"); 00419 CryptReleaseContext(ctx->prov, 0); 00420 os_free(ctx); 00421 return NULL; 00422 } 00423 } 00424 00425 if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) { 00426 cryptoapi_report_error("CryptCreateHash"); 00427 CryptReleaseContext(ctx->prov, 0); 00428 os_free(ctx); 00429 return NULL; 00430 } 00431 00432 if (calg == CALG_HMAC) { 00433 HMAC_INFO info; 00434 os_memset(&info, 0, sizeof(info)); 00435 switch (alg) { 00436 case CRYPTO_HASH_ALG_HMAC_MD5: 00437 info.HashAlgid = CALG_MD5; 00438 break; 00439 case CRYPTO_HASH_ALG_HMAC_SHA1: 00440 info.HashAlgid = CALG_SHA; 00441 break; 00442 default: 00443 /* unreachable */ 00444 break; 00445 } 00446 00447 if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info, 00448 0)) { 00449 cryptoapi_report_error("CryptSetHashParam"); 00450 CryptDestroyHash(ctx->hash); 00451 CryptReleaseContext(ctx->prov, 0); 00452 os_free(ctx); 00453 return NULL; 00454 } 00455 } 00456 00457 return ctx; 00458 } 00459 00460 00461 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 00462 { 00463 if (ctx == NULL || ctx->error) 00464 return; 00465 00466 if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) { 00467 cryptoapi_report_error("CryptHashData"); 00468 ctx->error = 1; 00469 } 00470 } 00471 00472 00473 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 00474 { 00475 int ret = 0; 00476 DWORD hlen; 00477 00478 if (ctx == NULL) 00479 return -2; 00480 00481 if (mac == NULL || len == NULL) 00482 goto done; 00483 00484 if (ctx->error) { 00485 ret = -2; 00486 goto done; 00487 } 00488 00489 hlen = *len; 00490 if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) { 00491 cryptoapi_report_error("CryptGetHashParam"); 00492 ret = -2; 00493 } 00494 *len = hlen; 00495 00496 done: 00497 if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 || 00498 ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5) 00499 CryptDestroyKey(ctx->key); 00500 00501 os_free(ctx); 00502 00503 return ret; 00504 } 00505 00506 00507 struct crypto_cipher { 00508 HCRYPTPROV prov; 00509 HCRYPTKEY key; 00510 }; 00511 00512 00513 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 00514 const u8 *iv, const u8 *key, 00515 size_t key_len) 00516 { 00517 struct crypto_cipher *ctx; 00518 struct { 00519 BLOBHEADER hdr; 00520 DWORD len; 00521 BYTE key[32]; 00522 } key_blob; 00523 DWORD mode = CRYPT_MODE_CBC; 00524 00525 key_blob.hdr.bType = PLAINTEXTKEYBLOB; 00526 key_blob.hdr.bVersion = CUR_BLOB_VERSION; 00527 key_blob.hdr.reserved = 0; 00528 key_blob.len = key_len; 00529 if (key_len > sizeof(key_blob.key)) 00530 return NULL; 00531 os_memcpy(key_blob.key, key, key_len); 00532 00533 switch (alg) { 00534 case CRYPTO_CIPHER_ALG_AES: 00535 if (key_len == 32) 00536 key_blob.hdr.aiKeyAlg = CALG_AES_256; 00537 else if (key_len == 24) 00538 key_blob.hdr.aiKeyAlg = CALG_AES_192; 00539 else 00540 key_blob.hdr.aiKeyAlg = CALG_AES_128; 00541 break; 00542 case CRYPTO_CIPHER_ALG_3DES: 00543 key_blob.hdr.aiKeyAlg = CALG_3DES; 00544 break; 00545 case CRYPTO_CIPHER_ALG_DES: 00546 key_blob.hdr.aiKeyAlg = CALG_DES; 00547 break; 00548 case CRYPTO_CIPHER_ALG_RC2: 00549 key_blob.hdr.aiKeyAlg = CALG_RC2; 00550 break; 00551 case CRYPTO_CIPHER_ALG_RC4: 00552 key_blob.hdr.aiKeyAlg = CALG_RC4; 00553 break; 00554 default: 00555 return NULL; 00556 } 00557 00558 ctx = os_zalloc(sizeof(*ctx)); 00559 if (ctx == NULL) 00560 return NULL; 00561 00562 if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV, 00563 PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { 00564 cryptoapi_report_error("CryptAcquireContext"); 00565 goto fail1; 00566 } 00567 00568 if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, 00569 sizeof(key_blob), 0, 0, &ctx->key)) { 00570 cryptoapi_report_error("CryptImportKey"); 00571 goto fail2; 00572 } 00573 00574 if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) { 00575 cryptoapi_report_error("CryptSetKeyParam(KP_MODE)"); 00576 goto fail3; 00577 } 00578 00579 if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) { 00580 cryptoapi_report_error("CryptSetKeyParam(KP_IV)"); 00581 goto fail3; 00582 } 00583 00584 return ctx; 00585 00586 fail3: 00587 CryptDestroyKey(ctx->key); 00588 fail2: 00589 CryptReleaseContext(ctx->prov, 0); 00590 fail1: 00591 os_free(ctx); 00592 return NULL; 00593 } 00594 00595 00596 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 00597 u8 *crypt, size_t len) 00598 { 00599 DWORD dlen; 00600 00601 os_memcpy(crypt, plain, len); 00602 dlen = len; 00603 if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) { 00604 cryptoapi_report_error("CryptEncrypt"); 00605 os_memset(crypt, 0, len); 00606 return -1; 00607 } 00608 00609 return 0; 00610 } 00611 00612 00613 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 00614 u8 *plain, size_t len) 00615 { 00616 DWORD dlen; 00617 00618 os_memcpy(plain, crypt, len); 00619 dlen = len; 00620 if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) { 00621 cryptoapi_report_error("CryptDecrypt"); 00622 return -1; 00623 } 00624 00625 return 0; 00626 } 00627 00628 00629 void crypto_cipher_deinit(struct crypto_cipher *ctx) 00630 { 00631 CryptDestroyKey(ctx->key); 00632 CryptReleaseContext(ctx->prov, 0); 00633 os_free(ctx); 00634 } 00635 00636 00637 struct crypto_public_key { 00638 HCRYPTPROV prov; 00639 HCRYPTKEY rsa; 00640 }; 00641 00642 struct crypto_private_key { 00643 HCRYPTPROV prov; 00644 HCRYPTKEY rsa; 00645 }; 00646 00647 00648 struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) 00649 { 00650 /* Use crypto_public_key_from_cert() instead. */ 00651 return NULL; 00652 } 00653 00654 00655 struct crypto_private_key * crypto_private_key_import(const u8 *key, 00656 size_t len, 00657 const char *passwd) 00658 { 00659 /* TODO */ 00660 return NULL; 00661 } 00662 00663 00664 struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, 00665 size_t len) 00666 { 00667 struct crypto_public_key *pk; 00668 PCCERT_CONTEXT cc; 00669 00670 pk = os_zalloc(sizeof(*pk)); 00671 if (pk == NULL) 00672 return NULL; 00673 00674 cc = CertCreateCertificateContext(X509_ASN_ENCODING | 00675 PKCS_7_ASN_ENCODING, buf, len); 00676 if (!cc) { 00677 cryptoapi_report_error("CryptCreateCertificateContext"); 00678 os_free(pk); 00679 return NULL; 00680 } 00681 00682 if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, 00683 0)) { 00684 cryptoapi_report_error("CryptAcquireContext"); 00685 os_free(pk); 00686 CertFreeCertificateContext(cc); 00687 return NULL; 00688 } 00689 00690 if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING | 00691 PKCS_7_ASN_ENCODING, 00692 &cc->pCertInfo->SubjectPublicKeyInfo, 00693 &pk->rsa)) { 00694 cryptoapi_report_error("CryptImportPublicKeyInfo"); 00695 CryptReleaseContext(pk->prov, 0); 00696 os_free(pk); 00697 CertFreeCertificateContext(cc); 00698 return NULL; 00699 } 00700 00701 CertFreeCertificateContext(cc); 00702 00703 return pk; 00704 } 00705 00706 00707 int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, 00708 const u8 *in, size_t inlen, 00709 u8 *out, size_t *outlen) 00710 { 00711 DWORD clen; 00712 u8 *tmp; 00713 size_t i; 00714 00715 if (*outlen < inlen) 00716 return -1; 00717 tmp = malloc(*outlen); 00718 if (tmp == NULL) 00719 return -1; 00720 00721 os_memcpy(tmp, in, inlen); 00722 clen = inlen; 00723 if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) { 00724 wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using " 00725 "public key: %d", (int) GetLastError()); 00726 os_free(tmp); 00727 return -1; 00728 } 00729 00730 *outlen = clen; 00731 00732 /* Reverse the output */ 00733 for (i = 0; i < *outlen; i++) 00734 out[i] = tmp[*outlen - 1 - i]; 00735 00736 os_free(tmp); 00737 00738 return 0; 00739 } 00740 00741 00742 int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, 00743 const u8 *in, size_t inlen, 00744 u8 *out, size_t *outlen) 00745 { 00746 /* TODO */ 00747 return -1; 00748 } 00749 00750 00751 void crypto_public_key_free(struct crypto_public_key *key) 00752 { 00753 if (key) { 00754 CryptDestroyKey(key->rsa); 00755 CryptReleaseContext(key->prov, 0); 00756 os_free(key); 00757 } 00758 } 00759 00760 00761 void crypto_private_key_free(struct crypto_private_key *key) 00762 { 00763 if (key) { 00764 CryptDestroyKey(key->rsa); 00765 CryptReleaseContext(key->prov, 0); 00766 os_free(key); 00767 } 00768 } 00769 00770 00771 int crypto_global_init(void) 00772 { 00773 return mingw_load_crypto_func(); 00774 } 00775 00776 00777 void crypto_global_deinit(void) 00778 { 00779 } 00780 00781 00782 int crypto_mod_exp(const u8 *base, size_t base_len, 00783 const u8 *power, size_t power_len, 00784 const u8 *modulus, size_t modulus_len, 00785 u8 *result, size_t *result_len) 00786 { 00787 /* TODO */ 00788 return -1; 00789 }