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