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