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