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