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