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