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