e_capi.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812
  1. /* engines/e_capi.c */
  2. /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  3. * project.
  4. */
  5. /* ====================================================================
  6. * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. All advertising materials mentioning features or use of this
  21. * software must display the following acknowledgment:
  22. * "This product includes software developed by the OpenSSL Project
  23. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  24. *
  25. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  26. * endorse or promote products derived from this software without
  27. * prior written permission. For written permission, please contact
  28. * licensing@OpenSSL.org.
  29. *
  30. * 5. Products derived from this software may not be called "OpenSSL"
  31. * nor may "OpenSSL" appear in their names without prior written
  32. * permission of the OpenSSL Project.
  33. *
  34. * 6. Redistributions of any form whatsoever must retain the following
  35. * acknowledgment:
  36. * "This product includes software developed by the OpenSSL Project
  37. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  38. *
  39. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  40. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  42. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  43. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  48. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  49. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  50. * OF THE POSSIBILITY OF SUCH DAMAGE.
  51. * ====================================================================
  52. */
  53. #include <stdio.h>
  54. #include <string.h>
  55. #include <openssl/crypto.h>
  56. #include <openssl/buffer.h>
  57. #include <openssl/bn.h>
  58. #ifdef OPENSSL_SYS_WIN32
  59. #ifndef OPENSSL_NO_CAPIENG
  60. #include <openssl/rsa.h>
  61. #include <windows.h>
  62. #ifndef _WIN32_WINNT
  63. #define _WIN32_WINNT 0x0400
  64. #endif
  65. #include <wincrypt.h>
  66. /*
  67. * This module uses several "new" interfaces, among which is
  68. * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is
  69. * one of possible values you can pass to function in question. By
  70. * checking if it's defined we can see if wincrypt.h and accompanying
  71. * crypt32.lib are in shape. Yes, it's rather "weak" test and if
  72. * compilation fails, then re-configure with -DOPENSSL_NO_CAPIENG.
  73. */
  74. #ifdef CERT_KEY_PROV_INFO_PROP_ID
  75. # define __COMPILE_CAPIENG
  76. #endif /* CERT_KEY_PROV_INFO_PROP_ID */
  77. #endif /* OPENSSL_NO_CAPIENG */
  78. #endif /* OPENSSL_SYS_WIN32 */
  79. #ifdef __COMPILE_CAPIENG
  80. #undef X509_EXTENSIONS
  81. #undef X509_CERT_PAIR
  82. /* Definitions which may be missing from earlier version of headers */
  83. #ifndef CERT_STORE_OPEN_EXISTING_FLAG
  84. #define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
  85. #endif
  86. #ifndef CERT_STORE_CREATE_NEW_FLAG
  87. #define CERT_STORE_CREATE_NEW_FLAG 0x00002000
  88. #endif
  89. #include <openssl/engine.h>
  90. #include <openssl/pem.h>
  91. #include <openssl/x509v3.h>
  92. #include "e_capi_err.h"
  93. #include "e_capi_err.c"
  94. static const char *engine_capi_id = "capi";
  95. static const char *engine_capi_name = "CryptoAPI ENGINE";
  96. typedef struct CAPI_CTX_st CAPI_CTX;
  97. typedef struct CAPI_KEY_st CAPI_KEY;
  98. static void capi_addlasterror(void);
  99. static void capi_adderror(DWORD err);
  100. static void CAPI_trace(CAPI_CTX *ctx, char *format, ...);
  101. static int capi_list_providers(CAPI_CTX *ctx, BIO *out);
  102. static int capi_list_containers(CAPI_CTX *ctx, BIO *out);
  103. int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *storename);
  104. void capi_free_key(CAPI_KEY *key);
  105. static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, HCERTSTORE hstore);
  106. CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id);
  107. static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
  108. UI_METHOD *ui_method, void *callback_data);
  109. static int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
  110. unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
  111. static int capi_rsa_priv_enc(int flen, const unsigned char *from,
  112. unsigned char *to, RSA *rsa, int padding);
  113. static int capi_rsa_priv_dec(int flen, const unsigned char *from,
  114. unsigned char *to, RSA *rsa, int padding);
  115. static int capi_rsa_free(RSA *rsa);
  116. static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
  117. DSA *dsa);
  118. static int capi_dsa_free(DSA *dsa);
  119. static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
  120. STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
  121. STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data);
  122. static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
  123. #ifdef OPENSSL_CAPIENG_DIALOG
  124. static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
  125. #endif
  126. typedef PCCERT_CONTEXT (WINAPI *CERTDLG)(HCERTSTORE, HWND, LPCWSTR,
  127. LPCWSTR, DWORD, DWORD,
  128. void *);
  129. typedef HWND (WINAPI *GETCONSWIN)(void);
  130. /* This structure contains CAPI ENGINE specific data:
  131. * it contains various global options and affects how
  132. * other functions behave.
  133. */
  134. #define CAPI_DBG_TRACE 2
  135. #define CAPI_DBG_ERROR 1
  136. struct CAPI_CTX_st {
  137. int debug_level;
  138. char *debug_file;
  139. /* Parameters to use for container lookup */
  140. DWORD keytype;
  141. LPSTR cspname;
  142. DWORD csptype;
  143. /* Certificate store name to use */
  144. LPSTR storename;
  145. LPSTR ssl_client_store;
  146. /* System store flags */
  147. DWORD store_flags;
  148. /* Lookup string meanings in load_private_key */
  149. /* Substring of subject: uses "storename" */
  150. #define CAPI_LU_SUBSTR 1
  151. /* Friendly name: uses storename */
  152. #define CAPI_LU_FNAME 2
  153. /* Container name: uses cspname, keytype */
  154. #define CAPI_LU_CONTNAME 3
  155. int lookup_method;
  156. /* Info to dump with dumpcerts option */
  157. /* Issuer and serial name strings */
  158. #define CAPI_DMP_SUMMARY 0x1
  159. /* Friendly name */
  160. #define CAPI_DMP_FNAME 0x2
  161. /* Full X509_print dump */
  162. #define CAPI_DMP_FULL 0x4
  163. /* Dump PEM format certificate */
  164. #define CAPI_DMP_PEM 0x8
  165. /* Dump pseudo key (if possible) */
  166. #define CAPI_DMP_PSKEY 0x10
  167. /* Dump key info (if possible) */
  168. #define CAPI_DMP_PKEYINFO 0x20
  169. DWORD dump_flags;
  170. int (*client_cert_select)(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
  171. CERTDLG certselectdlg;
  172. GETCONSWIN getconswindow;
  173. };
  174. static CAPI_CTX *capi_ctx_new();
  175. static void capi_ctx_free(CAPI_CTX *ctx);
  176. static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int check);
  177. static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx);
  178. #define CAPI_CMD_LIST_CERTS ENGINE_CMD_BASE
  179. #define CAPI_CMD_LOOKUP_CERT (ENGINE_CMD_BASE + 1)
  180. #define CAPI_CMD_DEBUG_LEVEL (ENGINE_CMD_BASE + 2)
  181. #define CAPI_CMD_DEBUG_FILE (ENGINE_CMD_BASE + 3)
  182. #define CAPI_CMD_KEYTYPE (ENGINE_CMD_BASE + 4)
  183. #define CAPI_CMD_LIST_CSPS (ENGINE_CMD_BASE + 5)
  184. #define CAPI_CMD_SET_CSP_IDX (ENGINE_CMD_BASE + 6)
  185. #define CAPI_CMD_SET_CSP_NAME (ENGINE_CMD_BASE + 7)
  186. #define CAPI_CMD_SET_CSP_TYPE (ENGINE_CMD_BASE + 8)
  187. #define CAPI_CMD_LIST_CONTAINERS (ENGINE_CMD_BASE + 9)
  188. #define CAPI_CMD_LIST_OPTIONS (ENGINE_CMD_BASE + 10)
  189. #define CAPI_CMD_LOOKUP_METHOD (ENGINE_CMD_BASE + 11)
  190. #define CAPI_CMD_STORE_NAME (ENGINE_CMD_BASE + 12)
  191. #define CAPI_CMD_STORE_FLAGS (ENGINE_CMD_BASE + 13)
  192. static const ENGINE_CMD_DEFN capi_cmd_defns[] = {
  193. {CAPI_CMD_LIST_CERTS,
  194. "list_certs",
  195. "List all certificates in store",
  196. ENGINE_CMD_FLAG_NO_INPUT},
  197. {CAPI_CMD_LOOKUP_CERT,
  198. "lookup_cert",
  199. "Lookup and output certificates",
  200. ENGINE_CMD_FLAG_STRING},
  201. {CAPI_CMD_DEBUG_LEVEL,
  202. "debug_level",
  203. "debug level (1=errors, 2=trace)",
  204. ENGINE_CMD_FLAG_NUMERIC},
  205. {CAPI_CMD_DEBUG_FILE,
  206. "debug_file",
  207. "debugging filename)",
  208. ENGINE_CMD_FLAG_STRING},
  209. {CAPI_CMD_KEYTYPE,
  210. "key_type",
  211. "Key type: 1=AT_KEYEXCHANGE (default), 2=AT_SIGNATURE",
  212. ENGINE_CMD_FLAG_NUMERIC},
  213. {CAPI_CMD_LIST_CSPS,
  214. "list_csps",
  215. "List all CSPs",
  216. ENGINE_CMD_FLAG_NO_INPUT},
  217. {CAPI_CMD_SET_CSP_IDX,
  218. "csp_idx",
  219. "Set CSP by index",
  220. ENGINE_CMD_FLAG_NUMERIC},
  221. {CAPI_CMD_SET_CSP_NAME,
  222. "csp_name",
  223. "Set CSP name, (default CSP used if not specified)",
  224. ENGINE_CMD_FLAG_STRING},
  225. {CAPI_CMD_SET_CSP_TYPE,
  226. "csp_type",
  227. "Set CSP type, (default RSA_PROV_FULL)",
  228. ENGINE_CMD_FLAG_NUMERIC},
  229. {CAPI_CMD_LIST_CONTAINERS,
  230. "list_containers",
  231. "list container names",
  232. ENGINE_CMD_FLAG_NO_INPUT},
  233. {CAPI_CMD_LIST_OPTIONS,
  234. "list_options",
  235. "Set list options (1=summary,2=friendly name, 4=full printout, 8=PEM output, 16=XXX, "
  236. "32=private key info)",
  237. ENGINE_CMD_FLAG_NUMERIC},
  238. {CAPI_CMD_LOOKUP_METHOD,
  239. "lookup_method",
  240. "Set key lookup method (1=substring, 2=friendlyname, 3=container name)",
  241. ENGINE_CMD_FLAG_NUMERIC},
  242. {CAPI_CMD_STORE_NAME,
  243. "store_name",
  244. "certificate store name, default \"MY\"",
  245. ENGINE_CMD_FLAG_STRING},
  246. {CAPI_CMD_STORE_FLAGS,
  247. "store_flags",
  248. "Certificate store flags: 1 = system store",
  249. ENGINE_CMD_FLAG_NUMERIC},
  250. {0, NULL, NULL, 0}
  251. };
  252. static int capi_idx = -1;
  253. static int rsa_capi_idx = -1;
  254. static int dsa_capi_idx = -1;
  255. static int cert_capi_idx = -1;
  256. static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
  257. {
  258. int ret = 1;
  259. CAPI_CTX *ctx;
  260. BIO *out;
  261. if (capi_idx == -1)
  262. {
  263. CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED);
  264. return 0;
  265. }
  266. ctx = ENGINE_get_ex_data(e, capi_idx);
  267. out = BIO_new_fp(stdout, BIO_NOCLOSE);
  268. switch (cmd)
  269. {
  270. case CAPI_CMD_LIST_CSPS:
  271. ret = capi_list_providers(ctx, out);
  272. break;
  273. case CAPI_CMD_LIST_CERTS:
  274. ret = capi_list_certs(ctx, out, NULL);
  275. break;
  276. case CAPI_CMD_LOOKUP_CERT:
  277. ret = capi_list_certs(ctx, out, p);
  278. break;
  279. case CAPI_CMD_LIST_CONTAINERS:
  280. ret = capi_list_containers(ctx, out);
  281. break;
  282. case CAPI_CMD_STORE_NAME:
  283. if (ctx->storename)
  284. OPENSSL_free(ctx->storename);
  285. ctx->storename = BUF_strdup(p);
  286. CAPI_trace(ctx, "Setting store name to %s\n", p);
  287. break;
  288. case CAPI_CMD_STORE_FLAGS:
  289. if (i & 1)
  290. {
  291. ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
  292. ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
  293. }
  294. else
  295. {
  296. ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER;
  297. ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE;
  298. }
  299. CAPI_trace(ctx, "Setting flags to %d\n", i);
  300. break;
  301. case CAPI_CMD_DEBUG_LEVEL:
  302. ctx->debug_level = (int)i;
  303. CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level);
  304. break;
  305. case CAPI_CMD_DEBUG_FILE:
  306. ctx->debug_file = BUF_strdup(p);
  307. CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file);
  308. break;
  309. case CAPI_CMD_KEYTYPE:
  310. ctx->keytype = i;
  311. CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype);
  312. break;
  313. case CAPI_CMD_SET_CSP_IDX:
  314. ret = capi_ctx_set_provname_idx(ctx, i);
  315. break;
  316. case CAPI_CMD_LIST_OPTIONS:
  317. ctx->dump_flags = i;
  318. break;
  319. case CAPI_CMD_LOOKUP_METHOD:
  320. if (i < 1 || i > 3)
  321. {
  322. CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD);
  323. return 0;
  324. }
  325. ctx->lookup_method = i;
  326. break;
  327. case CAPI_CMD_SET_CSP_NAME:
  328. ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1);
  329. break;
  330. case CAPI_CMD_SET_CSP_TYPE:
  331. ctx->csptype = i;
  332. break;
  333. default:
  334. CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND);
  335. ret = 0;
  336. }
  337. BIO_free(out);
  338. return ret;
  339. }
  340. static RSA_METHOD capi_rsa_method =
  341. {
  342. "CryptoAPI RSA method",
  343. 0, /* pub_enc */
  344. 0, /* pub_dec */
  345. capi_rsa_priv_enc, /* priv_enc */
  346. capi_rsa_priv_dec, /* priv_dec */
  347. 0, /* rsa_mod_exp */
  348. 0, /* bn_mod_exp */
  349. 0, /* init */
  350. capi_rsa_free, /* finish */
  351. RSA_FLAG_SIGN_VER, /* flags */
  352. NULL, /* app_data */
  353. capi_rsa_sign, /* rsa_sign */
  354. 0 /* rsa_verify */
  355. };
  356. static DSA_METHOD capi_dsa_method =
  357. {
  358. "CryptoAPI DSA method",
  359. capi_dsa_do_sign, /* dsa_do_sign */
  360. 0, /* dsa_sign_setup */
  361. 0, /* dsa_do_verify */
  362. 0, /* dsa_mod_exp */
  363. 0, /* bn_mod_exp */
  364. 0, /* init */
  365. capi_dsa_free, /* finish */
  366. 0, /* flags */
  367. NULL, /* app_data */
  368. 0, /* dsa_paramgen */
  369. 0 /* dsa_keygen */
  370. };
  371. static int capi_init(ENGINE *e)
  372. {
  373. CAPI_CTX *ctx;
  374. const RSA_METHOD *ossl_rsa_meth;
  375. const DSA_METHOD *ossl_dsa_meth;
  376. capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
  377. cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0);
  378. ctx = capi_ctx_new();
  379. if (!ctx || (capi_idx < 0))
  380. goto memerr;
  381. ENGINE_set_ex_data(e, capi_idx, ctx);
  382. /* Setup RSA_METHOD */
  383. rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
  384. ossl_rsa_meth = RSA_PKCS1_SSLeay();
  385. capi_rsa_method.rsa_pub_enc = ossl_rsa_meth->rsa_pub_enc;
  386. capi_rsa_method.rsa_pub_dec = ossl_rsa_meth->rsa_pub_dec;
  387. capi_rsa_method.rsa_mod_exp = ossl_rsa_meth->rsa_mod_exp;
  388. capi_rsa_method.bn_mod_exp = ossl_rsa_meth->bn_mod_exp;
  389. /* Setup DSA Method */
  390. dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
  391. ossl_dsa_meth = DSA_OpenSSL();
  392. capi_dsa_method.dsa_do_verify = ossl_dsa_meth->dsa_do_verify;
  393. capi_dsa_method.dsa_mod_exp = ossl_dsa_meth->dsa_mod_exp;
  394. capi_dsa_method.bn_mod_exp = ossl_dsa_meth->bn_mod_exp;
  395. #ifdef OPENSSL_CAPIENG_DIALOG
  396. {
  397. HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL"));
  398. HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL"));
  399. if (cryptui)
  400. ctx->certselectdlg = (CERTDLG)GetProcAddress(cryptui, "CryptUIDlgSelectCertificateFromStore");
  401. if (kernel)
  402. ctx->getconswindow = (GETCONSWIN)GetProcAddress(kernel, "GetConsoleWindow");
  403. if (cryptui && !OPENSSL_isservice())
  404. ctx->client_cert_select = cert_select_dialog;
  405. }
  406. #endif
  407. return 1;
  408. memerr:
  409. CAPIerr(CAPI_F_CAPI_INIT, ERR_R_MALLOC_FAILURE);
  410. return 0;
  411. return 1;
  412. }
  413. static int capi_destroy(ENGINE *e)
  414. {
  415. ERR_unload_CAPI_strings();
  416. return 1;
  417. }
  418. static int capi_finish(ENGINE *e)
  419. {
  420. CAPI_CTX *ctx;
  421. ctx = ENGINE_get_ex_data(e, capi_idx);
  422. capi_ctx_free(ctx);
  423. ENGINE_set_ex_data(e, capi_idx, NULL);
  424. return 1;
  425. }
  426. /* CryptoAPI key application data. This contains
  427. * a handle to the private key container (for sign operations)
  428. * and a handle to the key (for decrypt operations).
  429. */
  430. struct CAPI_KEY_st
  431. {
  432. /* Associated certificate context (if any) */
  433. PCCERT_CONTEXT pcert;
  434. HCRYPTPROV hprov;
  435. HCRYPTKEY key;
  436. DWORD keyspec;
  437. };
  438. static int bind_capi(ENGINE *e)
  439. {
  440. if (!ENGINE_set_id(e, engine_capi_id)
  441. || !ENGINE_set_name(e, engine_capi_name)
  442. || !ENGINE_set_init_function(e, capi_init)
  443. || !ENGINE_set_finish_function(e, capi_finish)
  444. || !ENGINE_set_destroy_function(e, capi_destroy)
  445. || !ENGINE_set_RSA(e, &capi_rsa_method)
  446. || !ENGINE_set_DSA(e, &capi_dsa_method)
  447. || !ENGINE_set_load_privkey_function(e, capi_load_privkey)
  448. || !ENGINE_set_load_ssl_client_cert_function(e,
  449. capi_load_ssl_client_cert)
  450. || !ENGINE_set_cmd_defns(e, capi_cmd_defns)
  451. || !ENGINE_set_ctrl_function(e, capi_ctrl))
  452. return 0;
  453. ERR_load_CAPI_strings();
  454. return 1;
  455. }
  456. #ifndef OPENSSL_NO_DYNAMIC_ENGINE
  457. static int bind_helper(ENGINE *e, const char *id)
  458. {
  459. if(id && (strcmp(id, engine_capi_id) != 0))
  460. return 0;
  461. if(!bind_capi(e))
  462. return 0;
  463. return 1;
  464. }
  465. IMPLEMENT_DYNAMIC_CHECK_FN()
  466. IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
  467. #else
  468. static ENGINE *engine_capi(void)
  469. {
  470. ENGINE *ret = ENGINE_new();
  471. if(!ret)
  472. return NULL;
  473. if(!bind_capi(ret))
  474. {
  475. ENGINE_free(ret);
  476. return NULL;
  477. }
  478. return ret;
  479. }
  480. void ENGINE_load_capi(void)
  481. {
  482. /* Copied from eng_[openssl|dyn].c */
  483. ENGINE *toadd = engine_capi();
  484. if(!toadd) return;
  485. ENGINE_add(toadd);
  486. ENGINE_free(toadd);
  487. ERR_clear_error();
  488. }
  489. #endif
  490. static int lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen)
  491. {
  492. int i;
  493. /* Reverse buffer in place: since this is a keyblob structure
  494. * that will be freed up after conversion anyway it doesn't
  495. * matter if we change it.
  496. */
  497. for(i = 0; i < binlen / 2; i++)
  498. {
  499. unsigned char c;
  500. c = bin[i];
  501. bin[i] = bin[binlen - i - 1];
  502. bin[binlen - i - 1] = c;
  503. }
  504. if (!BN_bin2bn(bin, binlen, bn))
  505. return 0;
  506. return 1;
  507. }
  508. /* Given a CAPI_KEY get an EVP_PKEY structure */
  509. static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key)
  510. {
  511. unsigned char *pubkey = NULL;
  512. DWORD len;
  513. BLOBHEADER *bh;
  514. RSA *rkey = NULL;
  515. DSA *dkey = NULL;
  516. EVP_PKEY *ret = NULL;
  517. if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len))
  518. {
  519. CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR);
  520. capi_addlasterror();
  521. return NULL;
  522. }
  523. pubkey = OPENSSL_malloc(len);
  524. if (!pubkey)
  525. goto memerr;
  526. if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len))
  527. {
  528. CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR);
  529. capi_addlasterror();
  530. goto err;
  531. }
  532. bh = (BLOBHEADER *)pubkey;
  533. if (bh->bType != PUBLICKEYBLOB)
  534. {
  535. CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB);
  536. goto err;
  537. }
  538. if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX)
  539. {
  540. RSAPUBKEY *rp;
  541. DWORD rsa_modlen;
  542. unsigned char *rsa_modulus;
  543. rp = (RSAPUBKEY *)(bh + 1);
  544. if (rp->magic != 0x31415352)
  545. {
  546. char magstr[10];
  547. BIO_snprintf(magstr, 10, "%lx", rp->magic);
  548. CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
  549. ERR_add_error_data(2, "magic=0x", magstr);
  550. goto err;
  551. }
  552. rsa_modulus = (unsigned char *)(rp + 1);
  553. rkey = RSA_new_method(eng);
  554. if (!rkey)
  555. goto memerr;
  556. rkey->e = BN_new();
  557. rkey->n = BN_new();
  558. if (!rkey->e || !rkey->n)
  559. goto memerr;
  560. if (!BN_set_word(rkey->e, rp->pubexp))
  561. goto memerr;
  562. rsa_modlen = rp->bitlen / 8;
  563. if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen))
  564. goto memerr;
  565. RSA_set_ex_data(rkey, rsa_capi_idx, key);
  566. if (!(ret = EVP_PKEY_new()))
  567. goto memerr;
  568. EVP_PKEY_assign_RSA(ret, rkey);
  569. rkey = NULL;
  570. }
  571. else if (bh->aiKeyAlg == CALG_DSS_SIGN)
  572. {
  573. DSSPUBKEY *dp;
  574. DWORD dsa_plen;
  575. unsigned char *btmp;
  576. dp = (DSSPUBKEY *)(bh + 1);
  577. if (dp->magic != 0x31535344)
  578. {
  579. char magstr[10];
  580. BIO_snprintf(magstr, 10, "%lx", dp->magic);
  581. CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
  582. ERR_add_error_data(2, "magic=0x", magstr);
  583. goto err;
  584. }
  585. dsa_plen = dp->bitlen / 8;
  586. btmp = (unsigned char *)(dp + 1);
  587. dkey = DSA_new_method(eng);
  588. if (!dkey)
  589. goto memerr;
  590. dkey->p = BN_new();
  591. dkey->q = BN_new();
  592. dkey->g = BN_new();
  593. dkey->pub_key = BN_new();
  594. if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key)
  595. goto memerr;
  596. if (!lend_tobn(dkey->p, btmp, dsa_plen))
  597. goto memerr;
  598. btmp += dsa_plen;
  599. if (!lend_tobn(dkey->q, btmp, 20))
  600. goto memerr;
  601. btmp += 20;
  602. if (!lend_tobn(dkey->g, btmp, dsa_plen))
  603. goto memerr;
  604. btmp += dsa_plen;
  605. if (!lend_tobn(dkey->pub_key, btmp, dsa_plen))
  606. goto memerr;
  607. btmp += dsa_plen;
  608. DSA_set_ex_data(dkey, dsa_capi_idx, key);
  609. if (!(ret = EVP_PKEY_new()))
  610. goto memerr;
  611. EVP_PKEY_assign_DSA(ret, dkey);
  612. dkey = NULL;
  613. }
  614. else
  615. {
  616. char algstr[10];
  617. BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg);
  618. CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM);
  619. ERR_add_error_data(2, "aiKeyAlg=0x", algstr);
  620. goto err;
  621. }
  622. err:
  623. if (pubkey)
  624. OPENSSL_free(pubkey);
  625. if (!ret)
  626. {
  627. if (rkey)
  628. RSA_free(rkey);
  629. if (dkey)
  630. DSA_free(dkey);
  631. }
  632. return ret;
  633. memerr:
  634. CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE);
  635. goto err;
  636. }
  637. static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
  638. UI_METHOD *ui_method, void *callback_data)
  639. {
  640. CAPI_CTX *ctx;
  641. CAPI_KEY *key;
  642. EVP_PKEY *ret;
  643. ctx = ENGINE_get_ex_data(eng, capi_idx);
  644. if (!ctx)
  645. {
  646. CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT);
  647. return NULL;
  648. }
  649. key = capi_find_key(ctx, key_id);
  650. if (!key)
  651. return NULL;
  652. ret = capi_get_pkey(eng, key);
  653. if (!ret)
  654. capi_free_key(key);
  655. return ret;
  656. }
  657. /* CryptoAPI RSA operations */
  658. int capi_rsa_priv_enc(int flen, const unsigned char *from,
  659. unsigned char *to, RSA *rsa, int padding)
  660. {
  661. CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED);
  662. return -1;
  663. }
  664. int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
  665. unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
  666. {
  667. ALG_ID alg;
  668. HCRYPTHASH hash;
  669. DWORD slen;
  670. unsigned int i;
  671. int ret = -1;
  672. CAPI_KEY *capi_key;
  673. CAPI_CTX *ctx;
  674. ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
  675. CAPI_trace(ctx, "Called CAPI_rsa_sign()\n");
  676. capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
  677. if (!capi_key)
  678. {
  679. CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY);
  680. return -1;
  681. }
  682. /* Convert the signature type to a CryptoAPI algorithm ID */
  683. switch(dtype)
  684. {
  685. case NID_sha1:
  686. alg = CALG_SHA1;
  687. break;
  688. case NID_md5:
  689. alg = CALG_MD5;
  690. break;
  691. case NID_md5_sha1:
  692. alg = CALG_SSL3_SHAMD5;
  693. break;
  694. default:
  695. {
  696. char algstr[10];
  697. BIO_snprintf(algstr, 10, "%lx", dtype);
  698. CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID);
  699. ERR_add_error_data(2, "NID=0x", algstr);
  700. return -1;
  701. }
  702. }
  703. /* Create the hash object */
  704. if(!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash))
  705. {
  706. CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
  707. capi_addlasterror();
  708. return -1;
  709. }
  710. /* Set the hash value to the value passed */
  711. if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0))
  712. {
  713. CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
  714. capi_addlasterror();
  715. goto err;
  716. }
  717. /* Finally sign it */
  718. slen = RSA_size(rsa);
  719. if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, sigret, &slen))
  720. {
  721. CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH);
  722. capi_addlasterror();
  723. goto err;
  724. }
  725. else
  726. {
  727. ret = 1;
  728. /* Inplace byte reversal of signature */
  729. for(i = 0; i < slen / 2; i++)
  730. {
  731. unsigned char c;
  732. c = sigret[i];
  733. sigret[i] = sigret[slen - i - 1];
  734. sigret[slen - i - 1] = c;
  735. }
  736. *siglen = slen;
  737. }
  738. /* Now cleanup */
  739. err:
  740. CryptDestroyHash(hash);
  741. return ret;
  742. }
  743. int capi_rsa_priv_dec(int flen, const unsigned char *from,
  744. unsigned char *to, RSA *rsa, int padding)
  745. {
  746. int i;
  747. unsigned char *tmpbuf;
  748. CAPI_KEY *capi_key;
  749. CAPI_CTX *ctx;
  750. ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
  751. CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n");
  752. capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
  753. if (!capi_key)
  754. {
  755. CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY);
  756. return -1;
  757. }
  758. if(padding != RSA_PKCS1_PADDING)
  759. {
  760. char errstr[10];
  761. BIO_snprintf(errstr, 10, "%d", padding);
  762. CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING);
  763. ERR_add_error_data(2, "padding=", errstr);
  764. return -1;
  765. }
  766. /* Create temp reverse order version of input */
  767. if(!(tmpbuf = OPENSSL_malloc(flen)) )
  768. {
  769. CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE);
  770. return -1;
  771. }
  772. for(i = 0; i < flen; i++)
  773. tmpbuf[flen - i - 1] = from[i];
  774. /* Finally decrypt it */
  775. if(!CryptDecrypt(capi_key->key, 0, TRUE, 0, tmpbuf, &flen))
  776. {
  777. CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR);
  778. capi_addlasterror();
  779. OPENSSL_free(tmpbuf);
  780. return -1;
  781. }
  782. else memcpy(to, tmpbuf, flen);
  783. OPENSSL_free(tmpbuf);
  784. return flen;
  785. }
  786. static int capi_rsa_free(RSA *rsa)
  787. {
  788. CAPI_KEY *capi_key;
  789. capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
  790. capi_free_key(capi_key);
  791. RSA_set_ex_data(rsa, rsa_capi_idx, 0);
  792. return 1;
  793. }
  794. /* CryptoAPI DSA operations */
  795. static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
  796. DSA *dsa)
  797. {
  798. HCRYPTHASH hash;
  799. DWORD slen;
  800. DSA_SIG *ret = NULL;
  801. CAPI_KEY *capi_key;
  802. CAPI_CTX *ctx;
  803. unsigned char csigbuf[40];
  804. ctx = ENGINE_get_ex_data(dsa->engine, capi_idx);
  805. CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n");
  806. capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
  807. if (!capi_key)
  808. {
  809. CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY);
  810. return NULL;
  811. }
  812. if (dlen != 20)
  813. {
  814. CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH);
  815. return NULL;
  816. }
  817. /* Create the hash object */
  818. if(!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash))
  819. {
  820. CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
  821. capi_addlasterror();
  822. return NULL;
  823. }
  824. /* Set the hash value to the value passed */
  825. if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0))
  826. {
  827. CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
  828. capi_addlasterror();
  829. goto err;
  830. }
  831. /* Finally sign it */
  832. slen = sizeof(csigbuf);
  833. if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen))
  834. {
  835. CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH);
  836. capi_addlasterror();
  837. goto err;
  838. }
  839. else
  840. {
  841. ret = DSA_SIG_new();
  842. if (!ret)
  843. goto err;
  844. ret->r = BN_new();
  845. ret->s = BN_new();
  846. if (!ret->r || !ret->s)
  847. goto err;
  848. if (!lend_tobn(ret->r, csigbuf, 20)
  849. || !lend_tobn(ret->s, csigbuf + 20, 20))
  850. {
  851. DSA_SIG_free(ret);
  852. ret = NULL;
  853. goto err;
  854. }
  855. }
  856. /* Now cleanup */
  857. err:
  858. OPENSSL_cleanse(csigbuf, 40);
  859. CryptDestroyHash(hash);
  860. return ret;
  861. }
  862. static int capi_dsa_free(DSA *dsa)
  863. {
  864. CAPI_KEY *capi_key;
  865. capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
  866. capi_free_key(capi_key);
  867. DSA_set_ex_data(dsa, dsa_capi_idx, 0);
  868. return 1;
  869. }
  870. static void capi_vtrace(CAPI_CTX *ctx, int level, char *format, va_list argptr)
  871. {
  872. BIO *out;
  873. if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file))
  874. return;
  875. out = BIO_new_file(ctx->debug_file, "a+");
  876. BIO_vprintf(out, format, argptr);
  877. BIO_free(out);
  878. }
  879. static void CAPI_trace(CAPI_CTX *ctx, char *format, ...)
  880. {
  881. va_list args;
  882. va_start(args, format);
  883. capi_vtrace(ctx, CAPI_DBG_TRACE, format, args);
  884. va_end(args);
  885. }
  886. static void capi_addlasterror(void)
  887. {
  888. capi_adderror(GetLastError());
  889. }
  890. static void capi_adderror(DWORD err)
  891. {
  892. char errstr[10];
  893. BIO_snprintf(errstr, 10, "%lX", err);
  894. ERR_add_error_data(2, "Error code= 0x", errstr);
  895. }
  896. static char *wide_to_asc(LPWSTR wstr)
  897. {
  898. char *str;
  899. int len_0,sz;
  900. if (!wstr)
  901. return NULL;
  902. len_0 = (int)wcslen(wstr)+1; /* WideCharToMultiByte expects int */
  903. sz = WideCharToMultiByte(CP_ACP,0,wstr,len_0,NULL,0,NULL,NULL);
  904. if (!sz)
  905. {
  906. CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
  907. return NULL;
  908. }
  909. str = OPENSSL_malloc(sz);
  910. if (!str)
  911. {
  912. CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE);
  913. return NULL;
  914. }
  915. if (!WideCharToMultiByte(CP_ACP,0,wstr,len_0,str,sz,NULL,NULL))
  916. {
  917. OPENSSL_free(str);
  918. CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
  919. return NULL;
  920. }
  921. return str;
  922. }
  923. static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, DWORD idx)
  924. {
  925. LPSTR name;
  926. DWORD len, err;
  927. CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx);
  928. if (!CryptEnumProvidersA(idx, NULL, 0, ptype, NULL, &len))
  929. {
  930. err = GetLastError();
  931. if (err == ERROR_NO_MORE_ITEMS)
  932. return 2;
  933. CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
  934. capi_adderror(err);
  935. return 0;
  936. }
  937. name = OPENSSL_malloc(len);
  938. if (!CryptEnumProvidersA(idx, NULL, 0, ptype, name, &len))
  939. {
  940. err = GetLastError();
  941. if (err == ERROR_NO_MORE_ITEMS)
  942. return 2;
  943. CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
  944. capi_adderror(err);
  945. return 0;
  946. }
  947. *pname = name;
  948. CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", name, *ptype);
  949. return 1;
  950. }
  951. static int capi_list_providers(CAPI_CTX *ctx, BIO *out)
  952. {
  953. DWORD idx, ptype;
  954. int ret;
  955. LPSTR provname = NULL;
  956. CAPI_trace(ctx, "capi_list_providers\n");
  957. BIO_printf(out, "Available CSPs:\n");
  958. for(idx = 0; ; idx++)
  959. {
  960. ret = capi_get_provname(ctx, &provname, &ptype, idx);
  961. if (ret == 2)
  962. break;
  963. if (ret == 0)
  964. break;
  965. BIO_printf(out, "%d. %s, type %d\n", idx, provname, ptype);
  966. OPENSSL_free(provname);
  967. }
  968. return 1;
  969. }
  970. static int capi_list_containers(CAPI_CTX *ctx, BIO *out)
  971. {
  972. int ret = 1;
  973. HCRYPTPROV hprov;
  974. DWORD err, idx, flags, buflen = 0, clen;
  975. LPSTR cname;
  976. CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, ctx->csptype);
  977. if (!CryptAcquireContextA(&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT))
  978. {
  979. CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
  980. capi_addlasterror();
  981. return 0;
  982. }
  983. if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, NULL, &buflen, CRYPT_FIRST))
  984. {
  985. CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
  986. capi_addlasterror();
  987. return 0;
  988. }
  989. CAPI_trace(ctx, "Got max container len %d\n", buflen);
  990. if (buflen == 0)
  991. buflen = 1024;
  992. cname = OPENSSL_malloc(buflen);
  993. if (!cname)
  994. {
  995. CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
  996. goto err;
  997. }
  998. for (idx = 0;;idx++)
  999. {
  1000. clen = buflen;
  1001. cname[0] = 0;
  1002. if (idx == 0)
  1003. flags = CRYPT_FIRST;
  1004. else
  1005. flags = 0;
  1006. if(!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, cname, &clen, flags))
  1007. {
  1008. err = GetLastError();
  1009. if (err == ERROR_NO_MORE_ITEMS)
  1010. goto done;
  1011. CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
  1012. capi_adderror(err);
  1013. goto err;
  1014. }
  1015. CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n", cname, clen, idx, flags);
  1016. if (!cname[0] && (clen == buflen))
  1017. {
  1018. CAPI_trace(ctx, "Enumerate bug: using workaround\n");
  1019. goto done;
  1020. }
  1021. BIO_printf(out, "%d. %s\n", idx, cname);
  1022. }
  1023. err:
  1024. ret = 0;
  1025. done:
  1026. if (cname)
  1027. OPENSSL_free(cname);
  1028. CryptReleaseContext(hprov, 0);
  1029. return ret;
  1030. }
  1031. CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
  1032. {
  1033. DWORD len;
  1034. CRYPT_KEY_PROV_INFO *pinfo;
  1035. if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &len))
  1036. return NULL;
  1037. pinfo = OPENSSL_malloc(len);
  1038. if (!pinfo)
  1039. {
  1040. CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE);
  1041. return NULL;
  1042. }
  1043. if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len))
  1044. {
  1045. CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO);
  1046. capi_addlasterror();
  1047. OPENSSL_free(pinfo);
  1048. return NULL;
  1049. }
  1050. return pinfo;
  1051. }
  1052. static void capi_dump_prov_info(CAPI_CTX *ctx, BIO *out, CRYPT_KEY_PROV_INFO *pinfo)
  1053. {
  1054. char *provname = NULL, *contname = NULL;
  1055. if (!pinfo)
  1056. {
  1057. BIO_printf(out, " No Private Key\n");
  1058. return;
  1059. }
  1060. provname = wide_to_asc(pinfo->pwszProvName);
  1061. contname = wide_to_asc(pinfo->pwszContainerName);
  1062. if (!provname || !contname)
  1063. goto err;
  1064. BIO_printf(out, " Private Key Info:\n");
  1065. BIO_printf(out, " Provider Name: %s, Provider Type %d\n", provname, pinfo->dwProvType);
  1066. BIO_printf(out, " Container Name: %s, Key Type %d\n", contname, pinfo->dwKeySpec);
  1067. err:
  1068. if (provname)
  1069. OPENSSL_free(provname);
  1070. if (contname)
  1071. OPENSSL_free(contname);
  1072. }
  1073. char * capi_cert_get_fname(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
  1074. {
  1075. LPWSTR wfname;
  1076. DWORD dlen;
  1077. CAPI_trace(ctx, "capi_cert_get_fname\n");
  1078. if (!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dlen))
  1079. return NULL;
  1080. wfname = OPENSSL_malloc(dlen);
  1081. if (CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, wfname, &dlen))
  1082. {
  1083. char *fname = wide_to_asc(wfname);
  1084. OPENSSL_free(wfname);
  1085. return fname;
  1086. }
  1087. CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME);
  1088. capi_addlasterror();
  1089. OPENSSL_free(wfname);
  1090. return NULL;
  1091. }
  1092. void capi_dump_cert(CAPI_CTX *ctx, BIO *out, PCCERT_CONTEXT cert)
  1093. {
  1094. X509 *x;
  1095. unsigned char *p;
  1096. unsigned long flags = ctx->dump_flags;
  1097. if (flags & CAPI_DMP_FNAME)
  1098. {
  1099. char *fname;
  1100. fname = capi_cert_get_fname(ctx, cert);
  1101. if (fname)
  1102. {
  1103. BIO_printf(out, " Friendly Name \"%s\"\n", fname);
  1104. OPENSSL_free(fname);
  1105. }
  1106. else
  1107. BIO_printf(out, " <No Friendly Name>\n");
  1108. }
  1109. p = cert->pbCertEncoded;
  1110. x = d2i_X509(NULL, &p, cert->cbCertEncoded);
  1111. if (!x)
  1112. BIO_printf(out, " <Can't parse certificate>\n");
  1113. if (flags & CAPI_DMP_SUMMARY)
  1114. {
  1115. BIO_printf(out, " Subject: ");
  1116. X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
  1117. BIO_printf(out, "\n Issuer: ");
  1118. X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
  1119. BIO_printf(out, "\n");
  1120. }
  1121. if (flags & CAPI_DMP_FULL)
  1122. X509_print_ex(out, x, XN_FLAG_ONELINE,0);
  1123. if (flags & CAPI_DMP_PKEYINFO)
  1124. {
  1125. CRYPT_KEY_PROV_INFO *pinfo;
  1126. pinfo = capi_get_prov_info(ctx, cert);
  1127. capi_dump_prov_info(ctx, out, pinfo);
  1128. if (pinfo)
  1129. OPENSSL_free(pinfo);
  1130. }
  1131. if (flags & CAPI_DMP_PEM)
  1132. PEM_write_bio_X509(out, x);
  1133. X509_free(x);
  1134. }
  1135. HCERTSTORE capi_open_store(CAPI_CTX *ctx, char *storename)
  1136. {
  1137. HCERTSTORE hstore;
  1138. if (!storename)
  1139. storename = ctx->storename;
  1140. if (!storename)
  1141. storename = "MY";
  1142. CAPI_trace(ctx, "Opening certificate store %s\n", storename);
  1143. hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
  1144. ctx->store_flags, storename);
  1145. if (!hstore)
  1146. {
  1147. CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE);
  1148. capi_addlasterror();
  1149. }
  1150. return hstore;
  1151. }
  1152. int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *id)
  1153. {
  1154. char *storename;
  1155. int idx;
  1156. int ret = 1;
  1157. HCERTSTORE hstore;
  1158. PCCERT_CONTEXT cert = NULL;
  1159. storename = ctx->storename;
  1160. if (!storename)
  1161. storename = "MY";
  1162. CAPI_trace(ctx, "Listing certs for store %s\n", storename);
  1163. hstore = capi_open_store(ctx, storename);
  1164. if (!hstore)
  1165. return 0;
  1166. if (id)
  1167. {
  1168. cert = capi_find_cert(ctx, id, hstore);
  1169. if (!cert)
  1170. {
  1171. ret = 0;
  1172. goto err;
  1173. }
  1174. capi_dump_cert(ctx, out, cert);
  1175. CertFreeCertificateContext(cert);
  1176. }
  1177. else
  1178. {
  1179. for(idx = 0;;idx++)
  1180. {
  1181. LPWSTR fname = NULL;
  1182. cert = CertEnumCertificatesInStore(hstore, cert);
  1183. if (!cert)
  1184. break;
  1185. BIO_printf(out, "Certificate %d\n", idx);
  1186. capi_dump_cert(ctx, out, cert);
  1187. }
  1188. }
  1189. err:
  1190. CertCloseStore(hstore, 0);
  1191. return ret;
  1192. }
  1193. static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, HCERTSTORE hstore)
  1194. {
  1195. PCCERT_CONTEXT cert = NULL;
  1196. char *fname = NULL;
  1197. int match;
  1198. switch(ctx->lookup_method)
  1199. {
  1200. case CAPI_LU_SUBSTR:
  1201. return CertFindCertificateInStore(hstore,
  1202. X509_ASN_ENCODING, 0,
  1203. CERT_FIND_SUBJECT_STR_A, id, NULL);
  1204. case CAPI_LU_FNAME:
  1205. for(;;)
  1206. {
  1207. cert = CertEnumCertificatesInStore(hstore, cert);
  1208. if (!cert)
  1209. return NULL;
  1210. fname = capi_cert_get_fname(ctx, cert);
  1211. if (fname)
  1212. {
  1213. if (strcmp(fname, id))
  1214. match = 0;
  1215. else
  1216. match = 1;
  1217. OPENSSL_free(fname);
  1218. if (match)
  1219. return cert;
  1220. }
  1221. }
  1222. default:
  1223. return NULL;
  1224. }
  1225. }
  1226. static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const char *contname, char *provname, DWORD ptype, DWORD keyspec)
  1227. {
  1228. CAPI_KEY *key;
  1229. key = OPENSSL_malloc(sizeof(CAPI_KEY));
  1230. CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
  1231. contname, provname, ptype);
  1232. if (!CryptAcquireContextA(&key->hprov, contname, provname, ptype, 0))
  1233. {
  1234. CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
  1235. capi_addlasterror();
  1236. goto err;
  1237. }
  1238. if (!CryptGetUserKey(key->hprov, keyspec, &key->key))
  1239. {
  1240. CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR);
  1241. capi_addlasterror();
  1242. CryptReleaseContext(key->hprov, 0);
  1243. goto err;
  1244. }
  1245. key->keyspec = keyspec;
  1246. key->pcert = NULL;
  1247. return key;
  1248. err:
  1249. OPENSSL_free(key);
  1250. return NULL;
  1251. }
  1252. static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
  1253. {
  1254. CAPI_KEY *key = NULL;
  1255. CRYPT_KEY_PROV_INFO *pinfo = NULL;
  1256. char *provname = NULL, *contname = NULL;
  1257. pinfo = capi_get_prov_info(ctx, cert);
  1258. if (!pinfo)
  1259. goto err;
  1260. provname = wide_to_asc(pinfo->pwszProvName);
  1261. contname = wide_to_asc(pinfo->pwszContainerName);
  1262. if (!provname || !contname)
  1263. goto err;
  1264. key = capi_get_key(ctx, contname, provname,
  1265. pinfo->dwProvType, pinfo->dwKeySpec);
  1266. err:
  1267. if (pinfo)
  1268. OPENSSL_free(pinfo);
  1269. if (provname)
  1270. OPENSSL_free(provname);
  1271. if (contname)
  1272. OPENSSL_free(contname);
  1273. return key;
  1274. }
  1275. CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id)
  1276. {
  1277. PCCERT_CONTEXT cert;
  1278. HCERTSTORE hstore;
  1279. CAPI_KEY *key = NULL;
  1280. switch (ctx->lookup_method)
  1281. {
  1282. case CAPI_LU_SUBSTR:
  1283. case CAPI_LU_FNAME:
  1284. hstore = capi_open_store(ctx, NULL);
  1285. if (!hstore)
  1286. return NULL;
  1287. cert = capi_find_cert(ctx, id, hstore);
  1288. if (cert)
  1289. {
  1290. key = capi_get_cert_key(ctx, cert);
  1291. CertFreeCertificateContext(cert);
  1292. }
  1293. CertCloseStore(hstore, 0);
  1294. break;
  1295. case CAPI_LU_CONTNAME:
  1296. key = capi_get_key(ctx, id, ctx->cspname, ctx->csptype,
  1297. ctx->keytype);
  1298. break;
  1299. }
  1300. return key;
  1301. }
  1302. void capi_free_key(CAPI_KEY *key)
  1303. {
  1304. if (!key)
  1305. return;
  1306. CryptDestroyKey(key->key);
  1307. CryptReleaseContext(key->hprov, 0);
  1308. if (key->pcert)
  1309. CertFreeCertificateContext(key->pcert);
  1310. OPENSSL_free(key);
  1311. }
  1312. /* Initialize a CAPI_CTX structure */
  1313. static CAPI_CTX *capi_ctx_new()
  1314. {
  1315. CAPI_CTX *ctx;
  1316. ctx = OPENSSL_malloc(sizeof(CAPI_CTX));
  1317. if (!ctx)
  1318. {
  1319. CAPIerr(CAPI_F_CAPI_CTX_NEW, ERR_R_MALLOC_FAILURE);
  1320. return NULL;
  1321. }
  1322. ctx->cspname = NULL;
  1323. ctx->csptype = PROV_RSA_FULL;
  1324. ctx->dump_flags = CAPI_DMP_SUMMARY|CAPI_DMP_FNAME;
  1325. ctx->keytype = AT_KEYEXCHANGE;
  1326. ctx->storename = NULL;
  1327. ctx->ssl_client_store = NULL;
  1328. ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG |
  1329. CERT_STORE_READONLY_FLAG |
  1330. CERT_SYSTEM_STORE_CURRENT_USER;
  1331. ctx->lookup_method = CAPI_LU_SUBSTR;
  1332. ctx->debug_level = 0;
  1333. ctx->debug_file = NULL;
  1334. ctx->client_cert_select = cert_select_simple;
  1335. return ctx;
  1336. }
  1337. static void capi_ctx_free(CAPI_CTX *ctx)
  1338. {
  1339. CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx);
  1340. if (!ctx)
  1341. return;
  1342. if (ctx->cspname)
  1343. OPENSSL_free(ctx->cspname);
  1344. if (ctx->debug_file)
  1345. OPENSSL_free(ctx->debug_file);
  1346. if (ctx->storename)
  1347. OPENSSL_free(ctx->storename);
  1348. if (ctx->ssl_client_store)
  1349. OPENSSL_free(ctx->ssl_client_store);
  1350. OPENSSL_free(ctx);
  1351. }
  1352. static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int check)
  1353. {
  1354. CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type);
  1355. if (check)
  1356. {
  1357. HCRYPTPROV hprov;
  1358. if (!CryptAcquireContextA(&hprov, NULL, pname, type,
  1359. CRYPT_VERIFYCONTEXT))
  1360. {
  1361. CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
  1362. capi_addlasterror();
  1363. return 0;
  1364. }
  1365. CryptReleaseContext(hprov, 0);
  1366. }
  1367. ctx->cspname = BUF_strdup(pname);
  1368. ctx->csptype = type;
  1369. return 1;
  1370. }
  1371. static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx)
  1372. {
  1373. LPSTR pname;
  1374. DWORD type;
  1375. if (capi_get_provname(ctx, &pname, &type, idx) != 1)
  1376. return 0;
  1377. return capi_ctx_set_provname(ctx, pname, type, 0);
  1378. }
  1379. static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x)
  1380. {
  1381. int i;
  1382. X509_NAME *nm;
  1383. /* Special case: empty list: match anything */
  1384. if (sk_X509_NAME_num(ca_dn) <= 0)
  1385. return 1;
  1386. for (i = 0; i < sk_X509_NAME_num(ca_dn); i++)
  1387. {
  1388. nm = sk_X509_NAME_value(ca_dn, i);
  1389. if (!X509_NAME_cmp(nm, X509_get_issuer_name(x)))
  1390. return 1;
  1391. }
  1392. return 0;
  1393. }
  1394. static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
  1395. STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
  1396. STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data)
  1397. {
  1398. STACK_OF(X509) *certs = NULL;
  1399. X509 *x;
  1400. char *storename;
  1401. const char *p;
  1402. int i, client_cert_idx;
  1403. HCERTSTORE hstore;
  1404. PCCERT_CONTEXT cert = NULL, excert = NULL;
  1405. CAPI_CTX *ctx;
  1406. CAPI_KEY *key;
  1407. ctx = ENGINE_get_ex_data(e, capi_idx);
  1408. *pcert = NULL;
  1409. *pkey = NULL;
  1410. storename = ctx->ssl_client_store;
  1411. if (!storename)
  1412. storename = "MY";
  1413. hstore = capi_open_store(ctx, storename);
  1414. if (!hstore)
  1415. return 0;
  1416. /* Enumerate all certificates collect any matches */
  1417. for(i = 0;;i++)
  1418. {
  1419. cert = CertEnumCertificatesInStore(hstore, cert);
  1420. if (!cert)
  1421. break;
  1422. p = cert->pbCertEncoded;
  1423. x = d2i_X509(NULL, &p, cert->cbCertEncoded);
  1424. if (!x)
  1425. {
  1426. CAPI_trace(ctx, "Can't Parse Certificate %d\n", i);
  1427. continue;
  1428. }
  1429. if (cert_issuer_match(ca_dn, x)
  1430. && X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0))
  1431. {
  1432. key = capi_get_cert_key(ctx, cert);
  1433. if (!key)
  1434. {
  1435. X509_free(x);
  1436. continue;
  1437. }
  1438. /* Match found: attach extra data to it so
  1439. * we can retrieve the key later.
  1440. */
  1441. excert = CertDuplicateCertificateContext(cert);
  1442. key->pcert = excert;
  1443. X509_set_ex_data(x, cert_capi_idx, key);
  1444. if (!certs)
  1445. certs = sk_X509_new_null();
  1446. sk_X509_push(certs, x);
  1447. }
  1448. else
  1449. X509_free(x);
  1450. }
  1451. if (cert)
  1452. CertFreeCertificateContext(cert);
  1453. if (hstore)
  1454. CertCloseStore(hstore, 0);
  1455. if (!certs)
  1456. return 0;
  1457. /* Select the appropriate certificate */
  1458. client_cert_idx = ctx->client_cert_select(e, ssl, certs);
  1459. /* Set the selected certificate and free the rest */
  1460. for(i = 0; i < sk_X509_num(certs); i++)
  1461. {
  1462. x = sk_X509_value(certs, i);
  1463. if (i == client_cert_idx)
  1464. *pcert = x;
  1465. else
  1466. {
  1467. key = X509_get_ex_data(x, cert_capi_idx);
  1468. capi_free_key(key);
  1469. X509_free(x);
  1470. }
  1471. }
  1472. sk_X509_free(certs);
  1473. if (!*pcert)
  1474. return 0;
  1475. /* Setup key for selected certificate */
  1476. key = X509_get_ex_data(*pcert, cert_capi_idx);
  1477. *pkey = capi_get_pkey(e, key);
  1478. X509_set_ex_data(*pcert, cert_capi_idx, NULL);
  1479. return 1;
  1480. }
  1481. /* Simple client cert selection function: always select first */
  1482. static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
  1483. {
  1484. return 0;
  1485. }
  1486. #ifdef OPENSSL_CAPIENG_DIALOG
  1487. /* More complex cert selection function, using standard function
  1488. * CryptUIDlgSelectCertificateFromStore() to produce a dialog box.
  1489. */
  1490. /* Definitions which are in cryptuiapi.h but this is not present in older
  1491. * versions of headers.
  1492. */
  1493. #ifndef CRYPTUI_SELECT_LOCATION_COLUMN
  1494. #define CRYPTUI_SELECT_LOCATION_COLUMN 0x000000010
  1495. #define CRYPTUI_SELECT_INTENDEDUSE_COLUMN 0x000000004
  1496. #endif
  1497. #define dlg_title L"OpenSSL Application SSL Client Certificate Selection"
  1498. #define dlg_prompt L"Select a certificate to use for authentication"
  1499. #define dlg_columns CRYPTUI_SELECT_LOCATION_COLUMN \
  1500. |CRYPTUI_SELECT_INTENDEDUSE_COLUMN
  1501. static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
  1502. {
  1503. X509 *x;
  1504. HCERTSTORE dstore;
  1505. PCCERT_CONTEXT cert;
  1506. CAPI_CTX *ctx;
  1507. CAPI_KEY *key;
  1508. HWND hwnd;
  1509. int i, idx = -1;
  1510. if (sk_X509_num(certs) == 1)
  1511. return 0;
  1512. ctx = ENGINE_get_ex_data(e, capi_idx);
  1513. /* Create an in memory store of certificates */
  1514. dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
  1515. CERT_STORE_CREATE_NEW_FLAG, NULL);
  1516. if (!dstore)
  1517. {
  1518. CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE);
  1519. capi_addlasterror();
  1520. goto err;
  1521. }
  1522. /* Add all certificates to store */
  1523. for(i = 0; i < sk_X509_num(certs); i++)
  1524. {
  1525. x = sk_X509_value(certs, i);
  1526. key = X509_get_ex_data(x, cert_capi_idx);
  1527. if (!CertAddCertificateContextToStore(dstore, key->pcert,
  1528. CERT_STORE_ADD_NEW, NULL))
  1529. {
  1530. CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT);
  1531. capi_addlasterror();
  1532. goto err;
  1533. }
  1534. }
  1535. hwnd = GetForegroundWindow();
  1536. if (!hwnd)
  1537. hwnd = GetActiveWindow();
  1538. if (!hwnd && ctx->getconswindow)
  1539. hwnd = ctx->getconswindow();
  1540. /* Call dialog to select one */
  1541. cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt,
  1542. dlg_columns, 0, NULL);
  1543. /* Find matching cert from list */
  1544. if (cert)
  1545. {
  1546. for(i = 0; i < sk_X509_num(certs); i++)
  1547. {
  1548. x = sk_X509_value(certs, i);
  1549. key = X509_get_ex_data(x, cert_capi_idx);
  1550. if (CertCompareCertificate(
  1551. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1552. cert->pCertInfo,
  1553. key->pcert->pCertInfo))
  1554. {
  1555. idx = i;
  1556. break;
  1557. }
  1558. }
  1559. }
  1560. err:
  1561. if (dstore)
  1562. CertCloseStore(dstore, 0);
  1563. return idx;
  1564. }
  1565. #endif
  1566. #else /* !__COMPILE_CAPIENG */
  1567. #include <openssl/engine.h>
  1568. #ifndef OPENSSL_NO_DYNAMIC_ENGINE
  1569. OPENSSL_EXPORT
  1570. int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { return 0; }
  1571. IMPLEMENT_DYNAMIC_CHECK_FN()
  1572. #else
  1573. void ENGINE_load_capi(void){}
  1574. #endif
  1575. #endif