crypto_cryptoapi.c 16 KB

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