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