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