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