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