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