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