1183234Ssimon/* engines/e_capi.c */ 2296341Sdelphij/* 3296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4183234Ssimon * project. 5183234Ssimon */ 6183234Ssimon/* ==================================================================== 7183234Ssimon * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 8183234Ssimon * 9183234Ssimon * Redistribution and use in source and binary forms, with or without 10183234Ssimon * modification, are permitted provided that the following conditions 11183234Ssimon * are met: 12183234Ssimon * 13183234Ssimon * 1. Redistributions of source code must retain the above copyright 14296341Sdelphij * notice, this list of conditions and the following disclaimer. 15183234Ssimon * 16183234Ssimon * 2. Redistributions in binary form must reproduce the above copyright 17183234Ssimon * notice, this list of conditions and the following disclaimer in 18183234Ssimon * the documentation and/or other materials provided with the 19183234Ssimon * distribution. 20183234Ssimon * 21183234Ssimon * 3. All advertising materials mentioning features or use of this 22183234Ssimon * software must display the following acknowledgment: 23183234Ssimon * "This product includes software developed by the OpenSSL Project 24183234Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25183234Ssimon * 26183234Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27183234Ssimon * endorse or promote products derived from this software without 28183234Ssimon * prior written permission. For written permission, please contact 29183234Ssimon * licensing@OpenSSL.org. 30183234Ssimon * 31183234Ssimon * 5. Products derived from this software may not be called "OpenSSL" 32183234Ssimon * nor may "OpenSSL" appear in their names without prior written 33183234Ssimon * permission of the OpenSSL Project. 34183234Ssimon * 35183234Ssimon * 6. Redistributions of any form whatsoever must retain the following 36183234Ssimon * acknowledgment: 37183234Ssimon * "This product includes software developed by the OpenSSL Project 38183234Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39183234Ssimon * 40183234Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41183234Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42183234Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43183234Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44183234Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45183234Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46183234Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47183234Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48183234Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49183234Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50183234Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51183234Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 52183234Ssimon * ==================================================================== 53183234Ssimon */ 54183234Ssimon 55183234Ssimon#include <stdio.h> 56183234Ssimon#include <string.h> 57183234Ssimon#include <openssl/crypto.h> 58183234Ssimon#include <openssl/buffer.h> 59183234Ssimon#include <openssl/bn.h> 60183234Ssimon 61183234Ssimon#ifdef OPENSSL_SYS_WIN32 62296341Sdelphij# ifndef OPENSSL_NO_CAPIENG 63183234Ssimon 64296341Sdelphij# include <openssl/rsa.h> 65183234Ssimon 66296341Sdelphij# include <windows.h> 67183234Ssimon 68296341Sdelphij# ifndef _WIN32_WINNT 69296341Sdelphij# define _WIN32_WINNT 0x0400 70296341Sdelphij# endif 71183234Ssimon 72296341Sdelphij# include <wincrypt.h> 73183234Ssimon 74238405Sjkim/* 75238405Sjkim * This module uses several "new" interfaces, among which is 76238405Sjkim * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is 77238405Sjkim * one of possible values you can pass to function in question. By 78238405Sjkim * checking if it's defined we can see if wincrypt.h and accompanying 79238405Sjkim * crypt32.lib are in shape. The native MingW32 headers up to and 80238405Sjkim * including __W32API_VERSION 3.14 lack of struct DSSPUBKEY and the 81238405Sjkim * defines CERT_STORE_PROV_SYSTEM_A and CERT_STORE_READONLY_FLAG, 82238405Sjkim * so we check for these too and avoid compiling. 83238405Sjkim * Yes, it's rather "weak" test and if compilation fails, 84238405Sjkim * then re-configure with -DOPENSSL_NO_CAPIENG. 85238405Sjkim */ 86296341Sdelphij# if defined(CERT_KEY_PROV_INFO_PROP_ID) && \ 87238405Sjkim defined(CERT_STORE_PROV_SYSTEM_A) && \ 88238405Sjkim defined(CERT_STORE_READONLY_FLAG) 89296341Sdelphij# define __COMPILE_CAPIENG 90296341Sdelphij# endif /* CERT_KEY_PROV_INFO_PROP_ID */ 91296341Sdelphij# endif /* OPENSSL_NO_CAPIENG */ 92296341Sdelphij#endif /* OPENSSL_SYS_WIN32 */ 93238405Sjkim 94238405Sjkim#ifdef __COMPILE_CAPIENG 95238405Sjkim 96296341Sdelphij# undef X509_EXTENSIONS 97296341Sdelphij# undef X509_CERT_PAIR 98183234Ssimon 99183234Ssimon/* Definitions which may be missing from earlier version of headers */ 100296341Sdelphij# ifndef CERT_STORE_OPEN_EXISTING_FLAG 101296341Sdelphij# define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 102296341Sdelphij# endif 103183234Ssimon 104296341Sdelphij# ifndef CERT_STORE_CREATE_NEW_FLAG 105296341Sdelphij# define CERT_STORE_CREATE_NEW_FLAG 0x00002000 106296341Sdelphij# endif 107183234Ssimon 108296341Sdelphij# ifndef CERT_SYSTEM_STORE_CURRENT_USER 109296341Sdelphij# define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000 110296341Sdelphij# endif 111206046Ssimon 112296341Sdelphij# include <openssl/engine.h> 113296341Sdelphij# include <openssl/pem.h> 114296341Sdelphij# include <openssl/x509v3.h> 115183234Ssimon 116296341Sdelphij# include "e_capi_err.h" 117296341Sdelphij# include "e_capi_err.c" 118183234Ssimon 119183234Ssimonstatic const char *engine_capi_id = "capi"; 120183234Ssimonstatic const char *engine_capi_name = "CryptoAPI ENGINE"; 121183234Ssimon 122183234Ssimontypedef struct CAPI_CTX_st CAPI_CTX; 123183234Ssimontypedef struct CAPI_KEY_st CAPI_KEY; 124183234Ssimon 125183234Ssimonstatic void capi_addlasterror(void); 126183234Ssimonstatic void capi_adderror(DWORD err); 127183234Ssimon 128296341Sdelphijstatic void CAPI_trace(CAPI_CTX * ctx, char *format, ...); 129183234Ssimon 130296341Sdelphijstatic int capi_list_providers(CAPI_CTX * ctx, BIO *out); 131296341Sdelphijstatic int capi_list_containers(CAPI_CTX * ctx, BIO *out); 132296341Sdelphijint capi_list_certs(CAPI_CTX * ctx, BIO *out, char *storename); 133296341Sdelphijvoid capi_free_key(CAPI_KEY * key); 134183234Ssimon 135296341Sdelphijstatic PCCERT_CONTEXT capi_find_cert(CAPI_CTX * ctx, const char *id, 136296341Sdelphij HCERTSTORE hstore); 137183234Ssimon 138296341SdelphijCAPI_KEY *capi_find_key(CAPI_CTX * ctx, const char *id); 139183234Ssimon 140183234Ssimonstatic EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id, 141296341Sdelphij UI_METHOD *ui_method, void *callback_data); 142296341Sdelphijstatic int capi_rsa_sign(int dtype, const unsigned char *m, 143296341Sdelphij unsigned int m_len, unsigned char *sigret, 144296341Sdelphij unsigned int *siglen, const RSA *rsa); 145183234Ssimonstatic int capi_rsa_priv_enc(int flen, const unsigned char *from, 146296341Sdelphij unsigned char *to, RSA *rsa, int padding); 147183234Ssimonstatic int capi_rsa_priv_dec(int flen, const unsigned char *from, 148296341Sdelphij unsigned char *to, RSA *rsa, int padding); 149183234Ssimonstatic int capi_rsa_free(RSA *rsa); 150183234Ssimon 151183234Ssimonstatic DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, 152296341Sdelphij DSA *dsa); 153183234Ssimonstatic int capi_dsa_free(DSA *dsa); 154183234Ssimon 155183234Ssimonstatic int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, 156296341Sdelphij STACK_OF(X509_NAME) *ca_dn, X509 **pcert, 157296341Sdelphij EVP_PKEY **pkey, STACK_OF(X509) **pother, 158296341Sdelphij UI_METHOD *ui_method, 159296341Sdelphij void *callback_data); 160183234Ssimon 161183234Ssimonstatic int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); 162296341Sdelphij# ifdef OPENSSL_CAPIENG_DIALOG 163183234Ssimonstatic int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); 164296341Sdelphij# endif 165183234Ssimon 166296341Sdelphijtypedef PCCERT_CONTEXT(WINAPI *CERTDLG) (HCERTSTORE, HWND, LPCWSTR, 167296341Sdelphij LPCWSTR, DWORD, DWORD, void *); 168296341Sdelphijtypedef HWND(WINAPI *GETCONSWIN) (void); 169183234Ssimon 170296341Sdelphij/* 171296341Sdelphij * This structure contains CAPI ENGINE specific data: it contains various 172296341Sdelphij * global options and affects how other functions behave. 173183234Ssimon */ 174183234Ssimon 175296341Sdelphij# define CAPI_DBG_TRACE 2 176296341Sdelphij# define CAPI_DBG_ERROR 1 177183234Ssimon 178183234Ssimonstruct CAPI_CTX_st { 179296341Sdelphij int debug_level; 180296341Sdelphij char *debug_file; 181296341Sdelphij /* Parameters to use for container lookup */ 182296341Sdelphij DWORD keytype; 183296341Sdelphij LPSTR cspname; 184296341Sdelphij DWORD csptype; 185296341Sdelphij /* Certificate store name to use */ 186296341Sdelphij LPSTR storename; 187296341Sdelphij LPSTR ssl_client_store; 188296341Sdelphij /* System store flags */ 189296341Sdelphij DWORD store_flags; 190183234Ssimon/* Lookup string meanings in load_private_key */ 191183234Ssimon/* Substring of subject: uses "storename" */ 192296341Sdelphij# define CAPI_LU_SUBSTR 1 193183234Ssimon/* Friendly name: uses storename */ 194296341Sdelphij# define CAPI_LU_FNAME 2 195183234Ssimon/* Container name: uses cspname, keytype */ 196296341Sdelphij# define CAPI_LU_CONTNAME 3 197296341Sdelphij int lookup_method; 198183234Ssimon/* Info to dump with dumpcerts option */ 199183234Ssimon/* Issuer and serial name strings */ 200296341Sdelphij# define CAPI_DMP_SUMMARY 0x1 201183234Ssimon/* Friendly name */ 202296341Sdelphij# define CAPI_DMP_FNAME 0x2 203183234Ssimon/* Full X509_print dump */ 204296341Sdelphij# define CAPI_DMP_FULL 0x4 205183234Ssimon/* Dump PEM format certificate */ 206296341Sdelphij# define CAPI_DMP_PEM 0x8 207183234Ssimon/* Dump pseudo key (if possible) */ 208296341Sdelphij# define CAPI_DMP_PSKEY 0x10 209183234Ssimon/* Dump key info (if possible) */ 210296341Sdelphij# define CAPI_DMP_PKEYINFO 0x20 211296341Sdelphij DWORD dump_flags; 212296341Sdelphij int (*client_cert_select) (ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); 213296341Sdelphij CERTDLG certselectdlg; 214296341Sdelphij GETCONSWIN getconswindow; 215183234Ssimon}; 216183234Ssimon 217183234Ssimonstatic CAPI_CTX *capi_ctx_new(); 218296341Sdelphijstatic void capi_ctx_free(CAPI_CTX * ctx); 219296341Sdelphijstatic int capi_ctx_set_provname(CAPI_CTX * ctx, LPSTR pname, DWORD type, 220296341Sdelphij int check); 221296341Sdelphijstatic int capi_ctx_set_provname_idx(CAPI_CTX * ctx, int idx); 222183234Ssimon 223296341Sdelphij# define CAPI_CMD_LIST_CERTS ENGINE_CMD_BASE 224296341Sdelphij# define CAPI_CMD_LOOKUP_CERT (ENGINE_CMD_BASE + 1) 225296341Sdelphij# define CAPI_CMD_DEBUG_LEVEL (ENGINE_CMD_BASE + 2) 226296341Sdelphij# define CAPI_CMD_DEBUG_FILE (ENGINE_CMD_BASE + 3) 227296341Sdelphij# define CAPI_CMD_KEYTYPE (ENGINE_CMD_BASE + 4) 228296341Sdelphij# define CAPI_CMD_LIST_CSPS (ENGINE_CMD_BASE + 5) 229296341Sdelphij# define CAPI_CMD_SET_CSP_IDX (ENGINE_CMD_BASE + 6) 230296341Sdelphij# define CAPI_CMD_SET_CSP_NAME (ENGINE_CMD_BASE + 7) 231296341Sdelphij# define CAPI_CMD_SET_CSP_TYPE (ENGINE_CMD_BASE + 8) 232296341Sdelphij# define CAPI_CMD_LIST_CONTAINERS (ENGINE_CMD_BASE + 9) 233296341Sdelphij# define CAPI_CMD_LIST_OPTIONS (ENGINE_CMD_BASE + 10) 234296341Sdelphij# define CAPI_CMD_LOOKUP_METHOD (ENGINE_CMD_BASE + 11) 235296341Sdelphij# define CAPI_CMD_STORE_NAME (ENGINE_CMD_BASE + 12) 236296341Sdelphij# define CAPI_CMD_STORE_FLAGS (ENGINE_CMD_BASE + 13) 237183234Ssimon 238183234Ssimonstatic const ENGINE_CMD_DEFN capi_cmd_defns[] = { 239296341Sdelphij {CAPI_CMD_LIST_CERTS, 240296341Sdelphij "list_certs", 241296341Sdelphij "List all certificates in store", 242296341Sdelphij ENGINE_CMD_FLAG_NO_INPUT}, 243296341Sdelphij {CAPI_CMD_LOOKUP_CERT, 244296341Sdelphij "lookup_cert", 245296341Sdelphij "Lookup and output certificates", 246296341Sdelphij ENGINE_CMD_FLAG_STRING}, 247296341Sdelphij {CAPI_CMD_DEBUG_LEVEL, 248296341Sdelphij "debug_level", 249296341Sdelphij "debug level (1=errors, 2=trace)", 250296341Sdelphij ENGINE_CMD_FLAG_NUMERIC}, 251296341Sdelphij {CAPI_CMD_DEBUG_FILE, 252296341Sdelphij "debug_file", 253296341Sdelphij "debugging filename)", 254296341Sdelphij ENGINE_CMD_FLAG_STRING}, 255296341Sdelphij {CAPI_CMD_KEYTYPE, 256296341Sdelphij "key_type", 257296341Sdelphij "Key type: 1=AT_KEYEXCHANGE (default), 2=AT_SIGNATURE", 258296341Sdelphij ENGINE_CMD_FLAG_NUMERIC}, 259296341Sdelphij {CAPI_CMD_LIST_CSPS, 260296341Sdelphij "list_csps", 261296341Sdelphij "List all CSPs", 262296341Sdelphij ENGINE_CMD_FLAG_NO_INPUT}, 263296341Sdelphij {CAPI_CMD_SET_CSP_IDX, 264296341Sdelphij "csp_idx", 265296341Sdelphij "Set CSP by index", 266296341Sdelphij ENGINE_CMD_FLAG_NUMERIC}, 267296341Sdelphij {CAPI_CMD_SET_CSP_NAME, 268296341Sdelphij "csp_name", 269296341Sdelphij "Set CSP name, (default CSP used if not specified)", 270296341Sdelphij ENGINE_CMD_FLAG_STRING}, 271296341Sdelphij {CAPI_CMD_SET_CSP_TYPE, 272296341Sdelphij "csp_type", 273296341Sdelphij "Set CSP type, (default RSA_PROV_FULL)", 274296341Sdelphij ENGINE_CMD_FLAG_NUMERIC}, 275296341Sdelphij {CAPI_CMD_LIST_CONTAINERS, 276296341Sdelphij "list_containers", 277296341Sdelphij "list container names", 278296341Sdelphij ENGINE_CMD_FLAG_NO_INPUT}, 279296341Sdelphij {CAPI_CMD_LIST_OPTIONS, 280296341Sdelphij "list_options", 281296341Sdelphij "Set list options (1=summary,2=friendly name, 4=full printout, 8=PEM output, 16=XXX, " 282296341Sdelphij "32=private key info)", 283296341Sdelphij ENGINE_CMD_FLAG_NUMERIC}, 284296341Sdelphij {CAPI_CMD_LOOKUP_METHOD, 285296341Sdelphij "lookup_method", 286296341Sdelphij "Set key lookup method (1=substring, 2=friendlyname, 3=container name)", 287296341Sdelphij ENGINE_CMD_FLAG_NUMERIC}, 288296341Sdelphij {CAPI_CMD_STORE_NAME, 289296341Sdelphij "store_name", 290296341Sdelphij "certificate store name, default \"MY\"", 291296341Sdelphij ENGINE_CMD_FLAG_STRING}, 292296341Sdelphij {CAPI_CMD_STORE_FLAGS, 293296341Sdelphij "store_flags", 294296341Sdelphij "Certificate store flags: 1 = system store", 295296341Sdelphij ENGINE_CMD_FLAG_NUMERIC}, 296183234Ssimon 297296341Sdelphij {0, NULL, NULL, 0} 298296341Sdelphij}; 299183234Ssimon 300183234Ssimonstatic int capi_idx = -1; 301183234Ssimonstatic int rsa_capi_idx = -1; 302183234Ssimonstatic int dsa_capi_idx = -1; 303183234Ssimonstatic int cert_capi_idx = -1; 304183234Ssimon 305296341Sdelphijstatic int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) 306296341Sdelphij{ 307296341Sdelphij int ret = 1; 308296341Sdelphij CAPI_CTX *ctx; 309296341Sdelphij BIO *out; 310296341Sdelphij if (capi_idx == -1) { 311296341Sdelphij CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED); 312296341Sdelphij return 0; 313296341Sdelphij } 314296341Sdelphij ctx = ENGINE_get_ex_data(e, capi_idx); 315296341Sdelphij out = BIO_new_fp(stdout, BIO_NOCLOSE); 316296341Sdelphij switch (cmd) { 317296341Sdelphij case CAPI_CMD_LIST_CSPS: 318296341Sdelphij ret = capi_list_providers(ctx, out); 319296341Sdelphij break; 320183234Ssimon 321296341Sdelphij case CAPI_CMD_LIST_CERTS: 322296341Sdelphij ret = capi_list_certs(ctx, out, NULL); 323296341Sdelphij break; 324183234Ssimon 325296341Sdelphij case CAPI_CMD_LOOKUP_CERT: 326296341Sdelphij ret = capi_list_certs(ctx, out, p); 327296341Sdelphij break; 328183234Ssimon 329296341Sdelphij case CAPI_CMD_LIST_CONTAINERS: 330296341Sdelphij ret = capi_list_containers(ctx, out); 331296341Sdelphij break; 332183234Ssimon 333296341Sdelphij case CAPI_CMD_STORE_NAME: 334296341Sdelphij if (ctx->storename) 335296341Sdelphij OPENSSL_free(ctx->storename); 336296341Sdelphij ctx->storename = BUF_strdup(p); 337296341Sdelphij CAPI_trace(ctx, "Setting store name to %s\n", p); 338296341Sdelphij break; 339183234Ssimon 340296341Sdelphij case CAPI_CMD_STORE_FLAGS: 341296341Sdelphij if (i & 1) { 342296341Sdelphij ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE; 343296341Sdelphij ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER; 344296341Sdelphij } else { 345296341Sdelphij ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER; 346296341Sdelphij ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE; 347296341Sdelphij } 348296341Sdelphij CAPI_trace(ctx, "Setting flags to %d\n", i); 349296341Sdelphij break; 350183234Ssimon 351296341Sdelphij case CAPI_CMD_DEBUG_LEVEL: 352296341Sdelphij ctx->debug_level = (int)i; 353296341Sdelphij CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level); 354296341Sdelphij break; 355183234Ssimon 356296341Sdelphij case CAPI_CMD_DEBUG_FILE: 357296341Sdelphij ctx->debug_file = BUF_strdup(p); 358296341Sdelphij CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file); 359296341Sdelphij break; 360183234Ssimon 361296341Sdelphij case CAPI_CMD_KEYTYPE: 362296341Sdelphij ctx->keytype = i; 363296341Sdelphij CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype); 364296341Sdelphij break; 365183234Ssimon 366296341Sdelphij case CAPI_CMD_SET_CSP_IDX: 367296341Sdelphij ret = capi_ctx_set_provname_idx(ctx, i); 368296341Sdelphij break; 369183234Ssimon 370296341Sdelphij case CAPI_CMD_LIST_OPTIONS: 371296341Sdelphij ctx->dump_flags = i; 372296341Sdelphij break; 373183234Ssimon 374296341Sdelphij case CAPI_CMD_LOOKUP_METHOD: 375296341Sdelphij if (i < 1 || i > 3) { 376296341Sdelphij CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD); 377296341Sdelphij return 0; 378296341Sdelphij } 379296341Sdelphij ctx->lookup_method = i; 380296341Sdelphij break; 381183234Ssimon 382296341Sdelphij case CAPI_CMD_SET_CSP_NAME: 383296341Sdelphij ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1); 384296341Sdelphij break; 385183234Ssimon 386296341Sdelphij case CAPI_CMD_SET_CSP_TYPE: 387296341Sdelphij ctx->csptype = i; 388296341Sdelphij break; 389183234Ssimon 390296341Sdelphij default: 391296341Sdelphij CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND); 392296341Sdelphij ret = 0; 393296341Sdelphij } 394183234Ssimon 395296341Sdelphij BIO_free(out); 396296341Sdelphij return ret; 397183234Ssimon 398296341Sdelphij} 399183234Ssimon 400296341Sdelphijstatic RSA_METHOD capi_rsa_method = { 401296341Sdelphij "CryptoAPI RSA method", 402296341Sdelphij 0, /* pub_enc */ 403296341Sdelphij 0, /* pub_dec */ 404296341Sdelphij capi_rsa_priv_enc, /* priv_enc */ 405296341Sdelphij capi_rsa_priv_dec, /* priv_dec */ 406296341Sdelphij 0, /* rsa_mod_exp */ 407296341Sdelphij 0, /* bn_mod_exp */ 408296341Sdelphij 0, /* init */ 409296341Sdelphij capi_rsa_free, /* finish */ 410296341Sdelphij RSA_FLAG_SIGN_VER, /* flags */ 411296341Sdelphij NULL, /* app_data */ 412296341Sdelphij capi_rsa_sign, /* rsa_sign */ 413296341Sdelphij 0 /* rsa_verify */ 414296341Sdelphij}; 415183234Ssimon 416296341Sdelphijstatic DSA_METHOD capi_dsa_method = { 417296341Sdelphij "CryptoAPI DSA method", 418296341Sdelphij capi_dsa_do_sign, /* dsa_do_sign */ 419296341Sdelphij 0, /* dsa_sign_setup */ 420296341Sdelphij 0, /* dsa_do_verify */ 421296341Sdelphij 0, /* dsa_mod_exp */ 422296341Sdelphij 0, /* bn_mod_exp */ 423296341Sdelphij 0, /* init */ 424296341Sdelphij capi_dsa_free, /* finish */ 425296341Sdelphij 0, /* flags */ 426296341Sdelphij NULL, /* app_data */ 427296341Sdelphij 0, /* dsa_paramgen */ 428296341Sdelphij 0 /* dsa_keygen */ 429296341Sdelphij}; 430183234Ssimon 431183234Ssimonstatic int capi_init(ENGINE *e) 432296341Sdelphij{ 433296341Sdelphij CAPI_CTX *ctx; 434296341Sdelphij const RSA_METHOD *ossl_rsa_meth; 435296341Sdelphij const DSA_METHOD *ossl_dsa_meth; 436183234Ssimon 437296341Sdelphij if (capi_idx < 0) { 438296341Sdelphij capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0); 439296341Sdelphij if (capi_idx < 0) 440296341Sdelphij goto memerr; 441237657Sjkim 442296341Sdelphij cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0); 443237657Sjkim 444296341Sdelphij /* Setup RSA_METHOD */ 445296341Sdelphij rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0); 446296341Sdelphij ossl_rsa_meth = RSA_PKCS1_SSLeay(); 447296341Sdelphij capi_rsa_method.rsa_pub_enc = ossl_rsa_meth->rsa_pub_enc; 448296341Sdelphij capi_rsa_method.rsa_pub_dec = ossl_rsa_meth->rsa_pub_dec; 449296341Sdelphij capi_rsa_method.rsa_mod_exp = ossl_rsa_meth->rsa_mod_exp; 450296341Sdelphij capi_rsa_method.bn_mod_exp = ossl_rsa_meth->bn_mod_exp; 451237657Sjkim 452296341Sdelphij /* Setup DSA Method */ 453296341Sdelphij dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0); 454296341Sdelphij ossl_dsa_meth = DSA_OpenSSL(); 455296341Sdelphij capi_dsa_method.dsa_do_verify = ossl_dsa_meth->dsa_do_verify; 456296341Sdelphij capi_dsa_method.dsa_mod_exp = ossl_dsa_meth->dsa_mod_exp; 457296341Sdelphij capi_dsa_method.bn_mod_exp = ossl_dsa_meth->bn_mod_exp; 458296341Sdelphij } 459237657Sjkim 460296341Sdelphij ctx = capi_ctx_new(); 461296341Sdelphij if (!ctx) 462296341Sdelphij goto memerr; 463183234Ssimon 464296341Sdelphij ENGINE_set_ex_data(e, capi_idx, ctx); 465183234Ssimon 466296341Sdelphij# ifdef OPENSSL_CAPIENG_DIALOG 467296341Sdelphij { 468296341Sdelphij HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL")); 469296341Sdelphij HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL")); 470296341Sdelphij if (cryptui) 471296341Sdelphij ctx->certselectdlg = 472296341Sdelphij (CERTDLG) GetProcAddress(cryptui, 473296341Sdelphij "CryptUIDlgSelectCertificateFromStore"); 474296341Sdelphij if (kernel) 475296341Sdelphij ctx->getconswindow = 476296341Sdelphij (GETCONSWIN) GetProcAddress(kernel, "GetConsoleWindow"); 477296341Sdelphij if (cryptui && !OPENSSL_isservice()) 478296341Sdelphij ctx->client_cert_select = cert_select_dialog; 479296341Sdelphij } 480296341Sdelphij# endif 481183234Ssimon 482296341Sdelphij return 1; 483183234Ssimon 484296341Sdelphij memerr: 485296341Sdelphij CAPIerr(CAPI_F_CAPI_INIT, ERR_R_MALLOC_FAILURE); 486296341Sdelphij return 0; 487183234Ssimon 488296341Sdelphij return 1; 489296341Sdelphij} 490183234Ssimon 491183234Ssimonstatic int capi_destroy(ENGINE *e) 492296341Sdelphij{ 493296341Sdelphij ERR_unload_CAPI_strings(); 494296341Sdelphij return 1; 495296341Sdelphij} 496183234Ssimon 497183234Ssimonstatic int capi_finish(ENGINE *e) 498296341Sdelphij{ 499296341Sdelphij CAPI_CTX *ctx; 500296341Sdelphij ctx = ENGINE_get_ex_data(e, capi_idx); 501296341Sdelphij capi_ctx_free(ctx); 502296341Sdelphij ENGINE_set_ex_data(e, capi_idx, NULL); 503296341Sdelphij return 1; 504296341Sdelphij} 505183234Ssimon 506296341Sdelphij/* 507296341Sdelphij * CryptoAPI key application data. This contains a handle to the private key 508296341Sdelphij * container (for sign operations) and a handle to the key (for decrypt 509296341Sdelphij * operations). 510183234Ssimon */ 511183234Ssimon 512296341Sdelphijstruct CAPI_KEY_st { 513296341Sdelphij /* Associated certificate context (if any) */ 514296341Sdelphij PCCERT_CONTEXT pcert; 515296341Sdelphij HCRYPTPROV hprov; 516296341Sdelphij HCRYPTKEY key; 517296341Sdelphij DWORD keyspec; 518296341Sdelphij}; 519183234Ssimon 520183234Ssimonstatic int bind_capi(ENGINE *e) 521296341Sdelphij{ 522296341Sdelphij if (!ENGINE_set_id(e, engine_capi_id) 523296341Sdelphij || !ENGINE_set_name(e, engine_capi_name) 524296341Sdelphij || !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) 525296341Sdelphij || !ENGINE_set_init_function(e, capi_init) 526296341Sdelphij || !ENGINE_set_finish_function(e, capi_finish) 527296341Sdelphij || !ENGINE_set_destroy_function(e, capi_destroy) 528296341Sdelphij || !ENGINE_set_RSA(e, &capi_rsa_method) 529296341Sdelphij || !ENGINE_set_DSA(e, &capi_dsa_method) 530296341Sdelphij || !ENGINE_set_load_privkey_function(e, capi_load_privkey) 531296341Sdelphij || !ENGINE_set_load_ssl_client_cert_function(e, 532296341Sdelphij capi_load_ssl_client_cert) 533296341Sdelphij || !ENGINE_set_cmd_defns(e, capi_cmd_defns) 534296341Sdelphij || !ENGINE_set_ctrl_function(e, capi_ctrl)) 535296341Sdelphij return 0; 536296341Sdelphij ERR_load_CAPI_strings(); 537183234Ssimon 538296341Sdelphij return 1; 539183234Ssimon 540296341Sdelphij} 541183234Ssimon 542296341Sdelphij# ifndef OPENSSL_NO_DYNAMIC_ENGINE 543183234Ssimonstatic int bind_helper(ENGINE *e, const char *id) 544296341Sdelphij{ 545296341Sdelphij if (id && (strcmp(id, engine_capi_id) != 0)) 546296341Sdelphij return 0; 547296341Sdelphij if (!bind_capi(e)) 548296341Sdelphij return 0; 549296341Sdelphij return 1; 550296341Sdelphij} 551296341Sdelphij 552183234SsimonIMPLEMENT_DYNAMIC_CHECK_FN() 553296341Sdelphij IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) 554296341Sdelphij# else 555183234Ssimonstatic ENGINE *engine_capi(void) 556296341Sdelphij{ 557296341Sdelphij ENGINE *ret = ENGINE_new(); 558296341Sdelphij if (!ret) 559296341Sdelphij return NULL; 560296341Sdelphij if (!bind_capi(ret)) { 561296341Sdelphij ENGINE_free(ret); 562296341Sdelphij return NULL; 563296341Sdelphij } 564296341Sdelphij return ret; 565296341Sdelphij} 566183234Ssimon 567183234Ssimonvoid ENGINE_load_capi(void) 568296341Sdelphij{ 569296341Sdelphij /* Copied from eng_[openssl|dyn].c */ 570296341Sdelphij ENGINE *toadd = engine_capi(); 571296341Sdelphij if (!toadd) 572296341Sdelphij return; 573296341Sdelphij ENGINE_add(toadd); 574296341Sdelphij ENGINE_free(toadd); 575296341Sdelphij ERR_clear_error(); 576296341Sdelphij} 577296341Sdelphij# endif 578183234Ssimon 579183234Ssimonstatic int lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen) 580296341Sdelphij{ 581296341Sdelphij int i; 582296341Sdelphij /* 583296341Sdelphij * Reverse buffer in place: since this is a keyblob structure that will 584296341Sdelphij * be freed up after conversion anyway it doesn't matter if we change 585296341Sdelphij * it. 586296341Sdelphij */ 587296341Sdelphij for (i = 0; i < binlen / 2; i++) { 588296341Sdelphij unsigned char c; 589296341Sdelphij c = bin[i]; 590296341Sdelphij bin[i] = bin[binlen - i - 1]; 591296341Sdelphij bin[binlen - i - 1] = c; 592296341Sdelphij } 593183234Ssimon 594296341Sdelphij if (!BN_bin2bn(bin, binlen, bn)) 595296341Sdelphij return 0; 596296341Sdelphij return 1; 597296341Sdelphij} 598183234Ssimon 599183234Ssimon/* Given a CAPI_KEY get an EVP_PKEY structure */ 600183234Ssimon 601296341Sdelphijstatic EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY * key) 602296341Sdelphij{ 603296341Sdelphij unsigned char *pubkey = NULL; 604296341Sdelphij DWORD len; 605296341Sdelphij BLOBHEADER *bh; 606296341Sdelphij RSA *rkey = NULL; 607296341Sdelphij DSA *dkey = NULL; 608296341Sdelphij EVP_PKEY *ret = NULL; 609296341Sdelphij if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) { 610296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR); 611296341Sdelphij capi_addlasterror(); 612296341Sdelphij return NULL; 613296341Sdelphij } 614183234Ssimon 615296341Sdelphij pubkey = OPENSSL_malloc(len); 616183234Ssimon 617296341Sdelphij if (!pubkey) 618296341Sdelphij goto memerr; 619183234Ssimon 620296341Sdelphij if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) { 621296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR); 622296341Sdelphij capi_addlasterror(); 623296341Sdelphij goto err; 624296341Sdelphij } 625183234Ssimon 626296341Sdelphij bh = (BLOBHEADER *) pubkey; 627296341Sdelphij if (bh->bType != PUBLICKEYBLOB) { 628296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB); 629296341Sdelphij goto err; 630296341Sdelphij } 631296341Sdelphij if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) { 632296341Sdelphij RSAPUBKEY *rp; 633296341Sdelphij DWORD rsa_modlen; 634296341Sdelphij unsigned char *rsa_modulus; 635296341Sdelphij rp = (RSAPUBKEY *) (bh + 1); 636296341Sdelphij if (rp->magic != 0x31415352) { 637296341Sdelphij char magstr[10]; 638296341Sdelphij BIO_snprintf(magstr, 10, "%lx", rp->magic); 639296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PKEY, 640296341Sdelphij CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); 641296341Sdelphij ERR_add_error_data(2, "magic=0x", magstr); 642296341Sdelphij goto err; 643296341Sdelphij } 644296341Sdelphij rsa_modulus = (unsigned char *)(rp + 1); 645296341Sdelphij rkey = RSA_new_method(eng); 646296341Sdelphij if (!rkey) 647296341Sdelphij goto memerr; 648183234Ssimon 649296341Sdelphij rkey->e = BN_new(); 650296341Sdelphij rkey->n = BN_new(); 651183234Ssimon 652296341Sdelphij if (!rkey->e || !rkey->n) 653296341Sdelphij goto memerr; 654183234Ssimon 655296341Sdelphij if (!BN_set_word(rkey->e, rp->pubexp)) 656296341Sdelphij goto memerr; 657183234Ssimon 658296341Sdelphij rsa_modlen = rp->bitlen / 8; 659296341Sdelphij if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen)) 660296341Sdelphij goto memerr; 661183234Ssimon 662296341Sdelphij RSA_set_ex_data(rkey, rsa_capi_idx, key); 663183234Ssimon 664296341Sdelphij if (!(ret = EVP_PKEY_new())) 665296341Sdelphij goto memerr; 666183234Ssimon 667296341Sdelphij EVP_PKEY_assign_RSA(ret, rkey); 668296341Sdelphij rkey = NULL; 669183234Ssimon 670296341Sdelphij } else if (bh->aiKeyAlg == CALG_DSS_SIGN) { 671296341Sdelphij DSSPUBKEY *dp; 672296341Sdelphij DWORD dsa_plen; 673296341Sdelphij unsigned char *btmp; 674296341Sdelphij dp = (DSSPUBKEY *) (bh + 1); 675296341Sdelphij if (dp->magic != 0x31535344) { 676296341Sdelphij char magstr[10]; 677296341Sdelphij BIO_snprintf(magstr, 10, "%lx", dp->magic); 678296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PKEY, 679296341Sdelphij CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); 680296341Sdelphij ERR_add_error_data(2, "magic=0x", magstr); 681296341Sdelphij goto err; 682296341Sdelphij } 683296341Sdelphij dsa_plen = dp->bitlen / 8; 684296341Sdelphij btmp = (unsigned char *)(dp + 1); 685296341Sdelphij dkey = DSA_new_method(eng); 686296341Sdelphij if (!dkey) 687296341Sdelphij goto memerr; 688296341Sdelphij dkey->p = BN_new(); 689296341Sdelphij dkey->q = BN_new(); 690296341Sdelphij dkey->g = BN_new(); 691296341Sdelphij dkey->pub_key = BN_new(); 692296341Sdelphij if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key) 693296341Sdelphij goto memerr; 694296341Sdelphij if (!lend_tobn(dkey->p, btmp, dsa_plen)) 695296341Sdelphij goto memerr; 696296341Sdelphij btmp += dsa_plen; 697296341Sdelphij if (!lend_tobn(dkey->q, btmp, 20)) 698296341Sdelphij goto memerr; 699296341Sdelphij btmp += 20; 700296341Sdelphij if (!lend_tobn(dkey->g, btmp, dsa_plen)) 701296341Sdelphij goto memerr; 702296341Sdelphij btmp += dsa_plen; 703296341Sdelphij if (!lend_tobn(dkey->pub_key, btmp, dsa_plen)) 704296341Sdelphij goto memerr; 705296341Sdelphij btmp += dsa_plen; 706183234Ssimon 707296341Sdelphij DSA_set_ex_data(dkey, dsa_capi_idx, key); 708183234Ssimon 709296341Sdelphij if (!(ret = EVP_PKEY_new())) 710296341Sdelphij goto memerr; 711183234Ssimon 712296341Sdelphij EVP_PKEY_assign_DSA(ret, dkey); 713296341Sdelphij dkey = NULL; 714296341Sdelphij } else { 715296341Sdelphij char algstr[10]; 716296341Sdelphij BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg); 717296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PKEY, 718296341Sdelphij CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM); 719296341Sdelphij ERR_add_error_data(2, "aiKeyAlg=0x", algstr); 720296341Sdelphij goto err; 721296341Sdelphij } 722183234Ssimon 723296341Sdelphij err: 724296341Sdelphij if (pubkey) 725296341Sdelphij OPENSSL_free(pubkey); 726296341Sdelphij if (!ret) { 727296341Sdelphij if (rkey) 728296341Sdelphij RSA_free(rkey); 729296341Sdelphij if (dkey) 730296341Sdelphij DSA_free(dkey); 731296341Sdelphij } 732183234Ssimon 733296341Sdelphij return ret; 734183234Ssimon 735296341Sdelphij memerr: 736296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE); 737296341Sdelphij goto err; 738183234Ssimon 739296341Sdelphij} 740183234Ssimon 741183234Ssimonstatic EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id, 742296341Sdelphij UI_METHOD *ui_method, void *callback_data) 743296341Sdelphij{ 744296341Sdelphij CAPI_CTX *ctx; 745296341Sdelphij CAPI_KEY *key; 746296341Sdelphij EVP_PKEY *ret; 747296341Sdelphij ctx = ENGINE_get_ex_data(eng, capi_idx); 748183234Ssimon 749296341Sdelphij if (!ctx) { 750296341Sdelphij CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT); 751296341Sdelphij return NULL; 752296341Sdelphij } 753183234Ssimon 754296341Sdelphij key = capi_find_key(ctx, key_id); 755183234Ssimon 756296341Sdelphij if (!key) 757296341Sdelphij return NULL; 758183234Ssimon 759296341Sdelphij ret = capi_get_pkey(eng, key); 760183234Ssimon 761296341Sdelphij if (!ret) 762296341Sdelphij capi_free_key(key); 763296341Sdelphij return ret; 764183234Ssimon 765296341Sdelphij} 766183234Ssimon 767183234Ssimon/* CryptoAPI RSA operations */ 768183234Ssimon 769183234Ssimonint capi_rsa_priv_enc(int flen, const unsigned char *from, 770296341Sdelphij unsigned char *to, RSA *rsa, int padding) 771296341Sdelphij{ 772296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED); 773296341Sdelphij return -1; 774296341Sdelphij} 775183234Ssimon 776183234Ssimonint capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, 777296341Sdelphij unsigned char *sigret, unsigned int *siglen, const RSA *rsa) 778296341Sdelphij{ 779296341Sdelphij ALG_ID alg; 780296341Sdelphij HCRYPTHASH hash; 781296341Sdelphij DWORD slen; 782296341Sdelphij unsigned int i; 783296341Sdelphij int ret = -1; 784296341Sdelphij CAPI_KEY *capi_key; 785296341Sdelphij CAPI_CTX *ctx; 786183234Ssimon 787296341Sdelphij ctx = ENGINE_get_ex_data(rsa->engine, capi_idx); 788183234Ssimon 789296341Sdelphij CAPI_trace(ctx, "Called CAPI_rsa_sign()\n"); 790183234Ssimon 791296341Sdelphij capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); 792296341Sdelphij if (!capi_key) { 793296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY); 794296341Sdelphij return -1; 795296341Sdelphij } 796183234Ssimon/* Convert the signature type to a CryptoAPI algorithm ID */ 797296341Sdelphij switch (dtype) { 798296341Sdelphij case NID_sha1: 799296341Sdelphij alg = CALG_SHA1; 800296341Sdelphij break; 801183234Ssimon 802296341Sdelphij case NID_md5: 803296341Sdelphij alg = CALG_MD5; 804296341Sdelphij break; 805183234Ssimon 806296341Sdelphij case NID_md5_sha1: 807296341Sdelphij alg = CALG_SSL3_SHAMD5; 808296341Sdelphij break; 809296341Sdelphij default: 810296341Sdelphij { 811296341Sdelphij char algstr[10]; 812296341Sdelphij BIO_snprintf(algstr, 10, "%lx", dtype); 813296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID); 814296341Sdelphij ERR_add_error_data(2, "NID=0x", algstr); 815296341Sdelphij return -1; 816296341Sdelphij } 817296341Sdelphij } 818183234Ssimon 819183234Ssimon/* Create the hash object */ 820296341Sdelphij if (!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) { 821296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); 822296341Sdelphij capi_addlasterror(); 823296341Sdelphij return -1; 824296341Sdelphij } 825183234Ssimon/* Set the hash value to the value passed */ 826183234Ssimon 827296341Sdelphij if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) { 828296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE); 829296341Sdelphij capi_addlasterror(); 830296341Sdelphij goto err; 831296341Sdelphij } 832183234Ssimon 833183234Ssimon/* Finally sign it */ 834296341Sdelphij slen = RSA_size(rsa); 835296341Sdelphij if (!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) { 836296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH); 837296341Sdelphij capi_addlasterror(); 838296341Sdelphij goto err; 839296341Sdelphij } else { 840296341Sdelphij ret = 1; 841296341Sdelphij /* Inplace byte reversal of signature */ 842296341Sdelphij for (i = 0; i < slen / 2; i++) { 843296341Sdelphij unsigned char c; 844296341Sdelphij c = sigret[i]; 845296341Sdelphij sigret[i] = sigret[slen - i - 1]; 846296341Sdelphij sigret[slen - i - 1] = c; 847296341Sdelphij } 848296341Sdelphij *siglen = slen; 849296341Sdelphij } 850183234Ssimon 851296341Sdelphij /* Now cleanup */ 852183234Ssimon 853296341Sdelphij err: 854296341Sdelphij CryptDestroyHash(hash); 855183234Ssimon 856296341Sdelphij return ret; 857296341Sdelphij} 858183234Ssimon 859183234Ssimonint capi_rsa_priv_dec(int flen, const unsigned char *from, 860296341Sdelphij unsigned char *to, RSA *rsa, int padding) 861296341Sdelphij{ 862296341Sdelphij int i; 863296341Sdelphij unsigned char *tmpbuf; 864296341Sdelphij CAPI_KEY *capi_key; 865296341Sdelphij CAPI_CTX *ctx; 866296341Sdelphij ctx = ENGINE_get_ex_data(rsa->engine, capi_idx); 867183234Ssimon 868296341Sdelphij CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n"); 869183234Ssimon 870296341Sdelphij capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); 871296341Sdelphij if (!capi_key) { 872296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY); 873296341Sdelphij return -1; 874296341Sdelphij } 875183234Ssimon 876296341Sdelphij if (padding != RSA_PKCS1_PADDING) { 877296341Sdelphij char errstr[10]; 878296341Sdelphij BIO_snprintf(errstr, 10, "%d", padding); 879296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING); 880296341Sdelphij ERR_add_error_data(2, "padding=", errstr); 881296341Sdelphij return -1; 882296341Sdelphij } 883183234Ssimon 884296341Sdelphij /* Create temp reverse order version of input */ 885296341Sdelphij if (!(tmpbuf = OPENSSL_malloc(flen))) { 886296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE); 887296341Sdelphij return -1; 888296341Sdelphij } 889296341Sdelphij for (i = 0; i < flen; i++) 890296341Sdelphij tmpbuf[flen - i - 1] = from[i]; 891183234Ssimon 892296341Sdelphij /* Finally decrypt it */ 893296341Sdelphij if (!CryptDecrypt(capi_key->key, 0, TRUE, 0, tmpbuf, &flen)) { 894296341Sdelphij CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR); 895296341Sdelphij capi_addlasterror(); 896296341Sdelphij OPENSSL_free(tmpbuf); 897296341Sdelphij return -1; 898296341Sdelphij } else 899296341Sdelphij memcpy(to, tmpbuf, flen); 900183234Ssimon 901296341Sdelphij OPENSSL_free(tmpbuf); 902183234Ssimon 903296341Sdelphij return flen; 904296341Sdelphij} 905183234Ssimon 906183234Ssimonstatic int capi_rsa_free(RSA *rsa) 907296341Sdelphij{ 908296341Sdelphij CAPI_KEY *capi_key; 909296341Sdelphij capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); 910296341Sdelphij capi_free_key(capi_key); 911296341Sdelphij RSA_set_ex_data(rsa, rsa_capi_idx, 0); 912296341Sdelphij return 1; 913296341Sdelphij} 914183234Ssimon 915183234Ssimon/* CryptoAPI DSA operations */ 916183234Ssimon 917183234Ssimonstatic DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, 918296341Sdelphij DSA *dsa) 919296341Sdelphij{ 920296341Sdelphij HCRYPTHASH hash; 921296341Sdelphij DWORD slen; 922296341Sdelphij DSA_SIG *ret = NULL; 923296341Sdelphij CAPI_KEY *capi_key; 924296341Sdelphij CAPI_CTX *ctx; 925296341Sdelphij unsigned char csigbuf[40]; 926183234Ssimon 927296341Sdelphij ctx = ENGINE_get_ex_data(dsa->engine, capi_idx); 928183234Ssimon 929296341Sdelphij CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n"); 930183234Ssimon 931296341Sdelphij capi_key = DSA_get_ex_data(dsa, dsa_capi_idx); 932183234Ssimon 933296341Sdelphij if (!capi_key) { 934296341Sdelphij CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY); 935296341Sdelphij return NULL; 936296341Sdelphij } 937183234Ssimon 938296341Sdelphij if (dlen != 20) { 939296341Sdelphij CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH); 940296341Sdelphij return NULL; 941296341Sdelphij } 942183234Ssimon 943296341Sdelphij /* Create the hash object */ 944296341Sdelphij if (!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash)) { 945296341Sdelphij CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); 946296341Sdelphij capi_addlasterror(); 947296341Sdelphij return NULL; 948296341Sdelphij } 949183234Ssimon 950296341Sdelphij /* Set the hash value to the value passed */ 951296341Sdelphij if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0)) { 952296341Sdelphij CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE); 953296341Sdelphij capi_addlasterror(); 954296341Sdelphij goto err; 955296341Sdelphij } 956183234Ssimon 957296341Sdelphij /* Finally sign it */ 958296341Sdelphij slen = sizeof(csigbuf); 959296341Sdelphij if (!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) { 960296341Sdelphij CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH); 961296341Sdelphij capi_addlasterror(); 962296341Sdelphij goto err; 963296341Sdelphij } else { 964296341Sdelphij ret = DSA_SIG_new(); 965296341Sdelphij if (!ret) 966296341Sdelphij goto err; 967296341Sdelphij ret->r = BN_new(); 968296341Sdelphij ret->s = BN_new(); 969296341Sdelphij if (!ret->r || !ret->s) 970296341Sdelphij goto err; 971296341Sdelphij if (!lend_tobn(ret->r, csigbuf, 20) 972296341Sdelphij || !lend_tobn(ret->s, csigbuf + 20, 20)) { 973296341Sdelphij DSA_SIG_free(ret); 974296341Sdelphij ret = NULL; 975296341Sdelphij goto err; 976296341Sdelphij } 977296341Sdelphij } 978183234Ssimon 979296341Sdelphij /* Now cleanup */ 980183234Ssimon 981296341Sdelphij err: 982296341Sdelphij OPENSSL_cleanse(csigbuf, 40); 983296341Sdelphij CryptDestroyHash(hash); 984296341Sdelphij return ret; 985296341Sdelphij} 986183234Ssimon 987183234Ssimonstatic int capi_dsa_free(DSA *dsa) 988296341Sdelphij{ 989296341Sdelphij CAPI_KEY *capi_key; 990296341Sdelphij capi_key = DSA_get_ex_data(dsa, dsa_capi_idx); 991296341Sdelphij capi_free_key(capi_key); 992296341Sdelphij DSA_set_ex_data(dsa, dsa_capi_idx, 0); 993296341Sdelphij return 1; 994296341Sdelphij} 995183234Ssimon 996296341Sdelphijstatic void capi_vtrace(CAPI_CTX * ctx, int level, char *format, 997296341Sdelphij va_list argptr) 998296341Sdelphij{ 999296341Sdelphij BIO *out; 1000183234Ssimon 1001296341Sdelphij if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file)) 1002296341Sdelphij return; 1003296341Sdelphij out = BIO_new_file(ctx->debug_file, "a+"); 1004296341Sdelphij BIO_vprintf(out, format, argptr); 1005296341Sdelphij BIO_free(out); 1006296341Sdelphij} 1007183234Ssimon 1008296341Sdelphijstatic void CAPI_trace(CAPI_CTX * ctx, char *format, ...) 1009296341Sdelphij{ 1010296341Sdelphij va_list args; 1011296341Sdelphij va_start(args, format); 1012296341Sdelphij capi_vtrace(ctx, CAPI_DBG_TRACE, format, args); 1013296341Sdelphij va_end(args); 1014296341Sdelphij} 1015183234Ssimon 1016183234Ssimonstatic void capi_addlasterror(void) 1017296341Sdelphij{ 1018296341Sdelphij capi_adderror(GetLastError()); 1019296341Sdelphij} 1020183234Ssimon 1021183234Ssimonstatic void capi_adderror(DWORD err) 1022296341Sdelphij{ 1023296341Sdelphij char errstr[10]; 1024296341Sdelphij BIO_snprintf(errstr, 10, "%lX", err); 1025296341Sdelphij ERR_add_error_data(2, "Error code= 0x", errstr); 1026296341Sdelphij} 1027183234Ssimon 1028183234Ssimonstatic char *wide_to_asc(LPWSTR wstr) 1029296341Sdelphij{ 1030296341Sdelphij char *str; 1031296341Sdelphij int len_0, sz; 1032205128Ssimon 1033296341Sdelphij if (!wstr) 1034296341Sdelphij return NULL; 1035296341Sdelphij len_0 = (int)wcslen(wstr) + 1; /* WideCharToMultiByte expects int */ 1036296341Sdelphij sz = WideCharToMultiByte(CP_ACP, 0, wstr, len_0, NULL, 0, NULL, NULL); 1037296341Sdelphij if (!sz) { 1038296341Sdelphij CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); 1039296341Sdelphij return NULL; 1040296341Sdelphij } 1041296341Sdelphij str = OPENSSL_malloc(sz); 1042296341Sdelphij if (!str) { 1043296341Sdelphij CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE); 1044296341Sdelphij return NULL; 1045296341Sdelphij } 1046296341Sdelphij if (!WideCharToMultiByte(CP_ACP, 0, wstr, len_0, str, sz, NULL, NULL)) { 1047296341Sdelphij OPENSSL_free(str); 1048296341Sdelphij CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); 1049296341Sdelphij return NULL; 1050296341Sdelphij } 1051296341Sdelphij return str; 1052296341Sdelphij} 1053183234Ssimon 1054296341Sdelphijstatic int capi_get_provname(CAPI_CTX * ctx, LPSTR * pname, DWORD * ptype, 1055296341Sdelphij DWORD idx) 1056296341Sdelphij{ 1057296341Sdelphij LPSTR name; 1058296341Sdelphij DWORD len, err; 1059296341Sdelphij CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx); 1060296341Sdelphij if (!CryptEnumProvidersA(idx, NULL, 0, ptype, NULL, &len)) { 1061296341Sdelphij err = GetLastError(); 1062296341Sdelphij if (err == ERROR_NO_MORE_ITEMS) 1063296341Sdelphij return 2; 1064296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR); 1065296341Sdelphij capi_adderror(err); 1066296341Sdelphij return 0; 1067296341Sdelphij } 1068296341Sdelphij name = OPENSSL_malloc(len); 1069296341Sdelphij if (!CryptEnumProvidersA(idx, NULL, 0, ptype, name, &len)) { 1070296341Sdelphij err = GetLastError(); 1071296341Sdelphij if (err == ERROR_NO_MORE_ITEMS) 1072296341Sdelphij return 2; 1073296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR); 1074296341Sdelphij capi_adderror(err); 1075296341Sdelphij return 0; 1076296341Sdelphij } 1077296341Sdelphij *pname = name; 1078296341Sdelphij CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", name, 1079296341Sdelphij *ptype); 1080183234Ssimon 1081296341Sdelphij return 1; 1082296341Sdelphij} 1083183234Ssimon 1084296341Sdelphijstatic int capi_list_providers(CAPI_CTX * ctx, BIO *out) 1085296341Sdelphij{ 1086296341Sdelphij DWORD idx, ptype; 1087296341Sdelphij int ret; 1088296341Sdelphij LPSTR provname = NULL; 1089296341Sdelphij CAPI_trace(ctx, "capi_list_providers\n"); 1090296341Sdelphij BIO_printf(out, "Available CSPs:\n"); 1091296341Sdelphij for (idx = 0;; idx++) { 1092296341Sdelphij ret = capi_get_provname(ctx, &provname, &ptype, idx); 1093296341Sdelphij if (ret == 2) 1094296341Sdelphij break; 1095296341Sdelphij if (ret == 0) 1096296341Sdelphij break; 1097296341Sdelphij BIO_printf(out, "%d. %s, type %d\n", idx, provname, ptype); 1098296341Sdelphij OPENSSL_free(provname); 1099296341Sdelphij } 1100296341Sdelphij return 1; 1101296341Sdelphij} 1102183234Ssimon 1103296341Sdelphijstatic int capi_list_containers(CAPI_CTX * ctx, BIO *out) 1104296341Sdelphij{ 1105296341Sdelphij int ret = 1; 1106296341Sdelphij HCRYPTPROV hprov; 1107296341Sdelphij DWORD err, idx, flags, buflen = 0, clen; 1108296341Sdelphij LPSTR cname; 1109296341Sdelphij CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, 1110296341Sdelphij ctx->csptype); 1111296341Sdelphij if (!CryptAcquireContextA 1112296341Sdelphij (&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) { 1113296341Sdelphij CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, 1114296341Sdelphij CAPI_R_CRYPTACQUIRECONTEXT_ERROR); 1115296341Sdelphij capi_addlasterror(); 1116296341Sdelphij return 0; 1117296341Sdelphij } 1118296341Sdelphij if (!CryptGetProvParam 1119296341Sdelphij (hprov, PP_ENUMCONTAINERS, NULL, &buflen, CRYPT_FIRST)) { 1120296341Sdelphij CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR); 1121296341Sdelphij capi_addlasterror(); 1122296341Sdelphij CryptReleaseContext(hprov, 0); 1123296341Sdelphij return 0; 1124296341Sdelphij } 1125296341Sdelphij CAPI_trace(ctx, "Got max container len %d\n", buflen); 1126296341Sdelphij if (buflen == 0) 1127296341Sdelphij buflen = 1024; 1128296341Sdelphij cname = OPENSSL_malloc(buflen); 1129296341Sdelphij if (!cname) { 1130296341Sdelphij CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE); 1131296341Sdelphij goto err; 1132296341Sdelphij } 1133183234Ssimon 1134296341Sdelphij for (idx = 0;; idx++) { 1135296341Sdelphij clen = buflen; 1136296341Sdelphij cname[0] = 0; 1137183234Ssimon 1138296341Sdelphij if (idx == 0) 1139296341Sdelphij flags = CRYPT_FIRST; 1140296341Sdelphij else 1141296341Sdelphij flags = 0; 1142296341Sdelphij if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, cname, &clen, flags)) { 1143296341Sdelphij err = GetLastError(); 1144296341Sdelphij if (err == ERROR_NO_MORE_ITEMS) 1145296341Sdelphij goto done; 1146296341Sdelphij CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR); 1147296341Sdelphij capi_adderror(err); 1148296341Sdelphij goto err; 1149296341Sdelphij } 1150296341Sdelphij CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n", 1151296341Sdelphij cname, clen, idx, flags); 1152296341Sdelphij if (!cname[0] && (clen == buflen)) { 1153296341Sdelphij CAPI_trace(ctx, "Enumerate bug: using workaround\n"); 1154296341Sdelphij goto done; 1155296341Sdelphij } 1156296341Sdelphij BIO_printf(out, "%d. %s\n", idx, cname); 1157296341Sdelphij } 1158296341Sdelphij err: 1159183234Ssimon 1160296341Sdelphij ret = 0; 1161183234Ssimon 1162296341Sdelphij done: 1163296341Sdelphij if (cname) 1164296341Sdelphij OPENSSL_free(cname); 1165296341Sdelphij CryptReleaseContext(hprov, 0); 1166183234Ssimon 1167296341Sdelphij return ret; 1168296341Sdelphij} 1169183234Ssimon 1170296341SdelphijCRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX * ctx, PCCERT_CONTEXT cert) 1171296341Sdelphij{ 1172296341Sdelphij DWORD len; 1173296341Sdelphij CRYPT_KEY_PROV_INFO *pinfo; 1174183234Ssimon 1175296341Sdelphij if (!CertGetCertificateContextProperty 1176296341Sdelphij (cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &len)) 1177296341Sdelphij return NULL; 1178296341Sdelphij pinfo = OPENSSL_malloc(len); 1179296341Sdelphij if (!pinfo) { 1180296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE); 1181296341Sdelphij return NULL; 1182296341Sdelphij } 1183296341Sdelphij if (!CertGetCertificateContextProperty 1184296341Sdelphij (cert, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) { 1185296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, 1186296341Sdelphij CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO); 1187296341Sdelphij capi_addlasterror(); 1188296341Sdelphij OPENSSL_free(pinfo); 1189296341Sdelphij return NULL; 1190296341Sdelphij } 1191296341Sdelphij return pinfo; 1192296341Sdelphij} 1193183234Ssimon 1194296341Sdelphijstatic void capi_dump_prov_info(CAPI_CTX * ctx, BIO *out, 1195296341Sdelphij CRYPT_KEY_PROV_INFO * pinfo) 1196296341Sdelphij{ 1197296341Sdelphij char *provname = NULL, *contname = NULL; 1198296341Sdelphij if (!pinfo) { 1199296341Sdelphij BIO_printf(out, " No Private Key\n"); 1200296341Sdelphij return; 1201296341Sdelphij } 1202296341Sdelphij provname = wide_to_asc(pinfo->pwszProvName); 1203296341Sdelphij contname = wide_to_asc(pinfo->pwszContainerName); 1204296341Sdelphij if (!provname || !contname) 1205296341Sdelphij goto err; 1206183234Ssimon 1207296341Sdelphij BIO_printf(out, " Private Key Info:\n"); 1208296341Sdelphij BIO_printf(out, " Provider Name: %s, Provider Type %d\n", provname, 1209296341Sdelphij pinfo->dwProvType); 1210296341Sdelphij BIO_printf(out, " Container Name: %s, Key Type %d\n", contname, 1211296341Sdelphij pinfo->dwKeySpec); 1212296341Sdelphij err: 1213296341Sdelphij if (provname) 1214296341Sdelphij OPENSSL_free(provname); 1215296341Sdelphij if (contname) 1216296341Sdelphij OPENSSL_free(contname); 1217296341Sdelphij} 1218183234Ssimon 1219296341Sdelphijchar *capi_cert_get_fname(CAPI_CTX * ctx, PCCERT_CONTEXT cert) 1220296341Sdelphij{ 1221296341Sdelphij LPWSTR wfname; 1222296341Sdelphij DWORD dlen; 1223183234Ssimon 1224296341Sdelphij CAPI_trace(ctx, "capi_cert_get_fname\n"); 1225296341Sdelphij if (!CertGetCertificateContextProperty 1226296341Sdelphij (cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dlen)) 1227296341Sdelphij return NULL; 1228296341Sdelphij wfname = OPENSSL_malloc(dlen); 1229296341Sdelphij if (CertGetCertificateContextProperty 1230296341Sdelphij (cert, CERT_FRIENDLY_NAME_PROP_ID, wfname, &dlen)) { 1231296341Sdelphij char *fname = wide_to_asc(wfname); 1232296341Sdelphij OPENSSL_free(wfname); 1233296341Sdelphij return fname; 1234296341Sdelphij } 1235296341Sdelphij CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME); 1236296341Sdelphij capi_addlasterror(); 1237183234Ssimon 1238296341Sdelphij OPENSSL_free(wfname); 1239296341Sdelphij return NULL; 1240296341Sdelphij} 1241183234Ssimon 1242296341Sdelphijvoid capi_dump_cert(CAPI_CTX * ctx, BIO *out, PCCERT_CONTEXT cert) 1243296341Sdelphij{ 1244296341Sdelphij X509 *x; 1245296341Sdelphij unsigned char *p; 1246296341Sdelphij unsigned long flags = ctx->dump_flags; 1247296341Sdelphij if (flags & CAPI_DMP_FNAME) { 1248296341Sdelphij char *fname; 1249296341Sdelphij fname = capi_cert_get_fname(ctx, cert); 1250296341Sdelphij if (fname) { 1251296341Sdelphij BIO_printf(out, " Friendly Name \"%s\"\n", fname); 1252296341Sdelphij OPENSSL_free(fname); 1253296341Sdelphij } else 1254296341Sdelphij BIO_printf(out, " <No Friendly Name>\n"); 1255296341Sdelphij } 1256183234Ssimon 1257296341Sdelphij p = cert->pbCertEncoded; 1258296341Sdelphij x = d2i_X509(NULL, &p, cert->cbCertEncoded); 1259296341Sdelphij if (!x) 1260296341Sdelphij BIO_printf(out, " <Can't parse certificate>\n"); 1261296341Sdelphij if (flags & CAPI_DMP_SUMMARY) { 1262296341Sdelphij BIO_printf(out, " Subject: "); 1263296341Sdelphij X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE); 1264296341Sdelphij BIO_printf(out, "\n Issuer: "); 1265296341Sdelphij X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE); 1266296341Sdelphij BIO_printf(out, "\n"); 1267296341Sdelphij } 1268296341Sdelphij if (flags & CAPI_DMP_FULL) 1269296341Sdelphij X509_print_ex(out, x, XN_FLAG_ONELINE, 0); 1270183234Ssimon 1271296341Sdelphij if (flags & CAPI_DMP_PKEYINFO) { 1272296341Sdelphij CRYPT_KEY_PROV_INFO *pinfo; 1273296341Sdelphij pinfo = capi_get_prov_info(ctx, cert); 1274296341Sdelphij capi_dump_prov_info(ctx, out, pinfo); 1275296341Sdelphij if (pinfo) 1276296341Sdelphij OPENSSL_free(pinfo); 1277296341Sdelphij } 1278183234Ssimon 1279296341Sdelphij if (flags & CAPI_DMP_PEM) 1280296341Sdelphij PEM_write_bio_X509(out, x); 1281296341Sdelphij X509_free(x); 1282296341Sdelphij} 1283183234Ssimon 1284296341SdelphijHCERTSTORE capi_open_store(CAPI_CTX * ctx, char *storename) 1285296341Sdelphij{ 1286296341Sdelphij HCERTSTORE hstore; 1287183234Ssimon 1288296341Sdelphij if (!storename) 1289296341Sdelphij storename = ctx->storename; 1290296341Sdelphij if (!storename) 1291296341Sdelphij storename = "MY"; 1292296341Sdelphij CAPI_trace(ctx, "Opening certificate store %s\n", storename); 1293183234Ssimon 1294296341Sdelphij hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, 1295296341Sdelphij ctx->store_flags, storename); 1296296341Sdelphij if (!hstore) { 1297296341Sdelphij CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE); 1298296341Sdelphij capi_addlasterror(); 1299296341Sdelphij } 1300296341Sdelphij return hstore; 1301296341Sdelphij} 1302183234Ssimon 1303296341Sdelphijint capi_list_certs(CAPI_CTX * ctx, BIO *out, char *id) 1304296341Sdelphij{ 1305296341Sdelphij char *storename; 1306296341Sdelphij int idx; 1307296341Sdelphij int ret = 1; 1308296341Sdelphij HCERTSTORE hstore; 1309296341Sdelphij PCCERT_CONTEXT cert = NULL; 1310183234Ssimon 1311296341Sdelphij storename = ctx->storename; 1312296341Sdelphij if (!storename) 1313296341Sdelphij storename = "MY"; 1314296341Sdelphij CAPI_trace(ctx, "Listing certs for store %s\n", storename); 1315183234Ssimon 1316296341Sdelphij hstore = capi_open_store(ctx, storename); 1317296341Sdelphij if (!hstore) 1318296341Sdelphij return 0; 1319296341Sdelphij if (id) { 1320296341Sdelphij cert = capi_find_cert(ctx, id, hstore); 1321296341Sdelphij if (!cert) { 1322296341Sdelphij ret = 0; 1323296341Sdelphij goto err; 1324296341Sdelphij } 1325296341Sdelphij capi_dump_cert(ctx, out, cert); 1326296341Sdelphij CertFreeCertificateContext(cert); 1327296341Sdelphij } else { 1328296341Sdelphij for (idx = 0;; idx++) { 1329296341Sdelphij LPWSTR fname = NULL; 1330296341Sdelphij cert = CertEnumCertificatesInStore(hstore, cert); 1331296341Sdelphij if (!cert) 1332296341Sdelphij break; 1333296341Sdelphij BIO_printf(out, "Certificate %d\n", idx); 1334296341Sdelphij capi_dump_cert(ctx, out, cert); 1335296341Sdelphij } 1336296341Sdelphij } 1337296341Sdelphij err: 1338296341Sdelphij CertCloseStore(hstore, 0); 1339296341Sdelphij return ret; 1340296341Sdelphij} 1341183234Ssimon 1342296341Sdelphijstatic PCCERT_CONTEXT capi_find_cert(CAPI_CTX * ctx, const char *id, 1343296341Sdelphij HCERTSTORE hstore) 1344296341Sdelphij{ 1345296341Sdelphij PCCERT_CONTEXT cert = NULL; 1346296341Sdelphij char *fname = NULL; 1347296341Sdelphij int match; 1348296341Sdelphij switch (ctx->lookup_method) { 1349296341Sdelphij case CAPI_LU_SUBSTR: 1350296341Sdelphij return CertFindCertificateInStore(hstore, 1351296341Sdelphij X509_ASN_ENCODING, 0, 1352296341Sdelphij CERT_FIND_SUBJECT_STR_A, id, NULL); 1353296341Sdelphij case CAPI_LU_FNAME: 1354296341Sdelphij for (;;) { 1355296341Sdelphij cert = CertEnumCertificatesInStore(hstore, cert); 1356296341Sdelphij if (!cert) 1357296341Sdelphij return NULL; 1358296341Sdelphij fname = capi_cert_get_fname(ctx, cert); 1359296341Sdelphij if (fname) { 1360296341Sdelphij if (strcmp(fname, id)) 1361296341Sdelphij match = 0; 1362296341Sdelphij else 1363296341Sdelphij match = 1; 1364296341Sdelphij OPENSSL_free(fname); 1365296341Sdelphij if (match) 1366296341Sdelphij return cert; 1367296341Sdelphij } 1368296341Sdelphij } 1369296341Sdelphij default: 1370296341Sdelphij return NULL; 1371296341Sdelphij } 1372296341Sdelphij} 1373183234Ssimon 1374296341Sdelphijstatic CAPI_KEY *capi_get_key(CAPI_CTX * ctx, const char *contname, 1375296341Sdelphij char *provname, DWORD ptype, DWORD keyspec) 1376296341Sdelphij{ 1377296341Sdelphij CAPI_KEY *key; 1378296341Sdelphij DWORD dwFlags = 0; 1379296341Sdelphij key = OPENSSL_malloc(sizeof(CAPI_KEY)); 1380296341Sdelphij CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n", 1381296341Sdelphij contname, provname, ptype); 1382296341Sdelphij if (ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE) 1383246772Sjkim dwFlags = CRYPT_MACHINE_KEYSET; 1384296341Sdelphij if (!CryptAcquireContextA 1385296341Sdelphij (&key->hprov, contname, provname, ptype, dwFlags)) { 1386296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); 1387296341Sdelphij capi_addlasterror(); 1388296341Sdelphij goto err; 1389296341Sdelphij } 1390296341Sdelphij if (!CryptGetUserKey(key->hprov, keyspec, &key->key)) { 1391296341Sdelphij CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR); 1392296341Sdelphij capi_addlasterror(); 1393296341Sdelphij CryptReleaseContext(key->hprov, 0); 1394296341Sdelphij goto err; 1395296341Sdelphij } 1396296341Sdelphij key->keyspec = keyspec; 1397296341Sdelphij key->pcert = NULL; 1398296341Sdelphij return key; 1399183234Ssimon 1400296341Sdelphij err: 1401296341Sdelphij OPENSSL_free(key); 1402296341Sdelphij return NULL; 1403296341Sdelphij} 1404183234Ssimon 1405296341Sdelphijstatic CAPI_KEY *capi_get_cert_key(CAPI_CTX * ctx, PCCERT_CONTEXT cert) 1406296341Sdelphij{ 1407296341Sdelphij CAPI_KEY *key = NULL; 1408296341Sdelphij CRYPT_KEY_PROV_INFO *pinfo = NULL; 1409296341Sdelphij char *provname = NULL, *contname = NULL; 1410296341Sdelphij pinfo = capi_get_prov_info(ctx, cert); 1411296341Sdelphij if (!pinfo) 1412296341Sdelphij goto err; 1413296341Sdelphij provname = wide_to_asc(pinfo->pwszProvName); 1414296341Sdelphij contname = wide_to_asc(pinfo->pwszContainerName); 1415296341Sdelphij if (!provname || !contname) 1416296341Sdelphij goto err; 1417296341Sdelphij key = capi_get_key(ctx, contname, provname, 1418296341Sdelphij pinfo->dwProvType, pinfo->dwKeySpec); 1419183234Ssimon 1420296341Sdelphij err: 1421296341Sdelphij if (pinfo) 1422296341Sdelphij OPENSSL_free(pinfo); 1423296341Sdelphij if (provname) 1424296341Sdelphij OPENSSL_free(provname); 1425296341Sdelphij if (contname) 1426296341Sdelphij OPENSSL_free(contname); 1427296341Sdelphij return key; 1428296341Sdelphij} 1429183234Ssimon 1430296341SdelphijCAPI_KEY *capi_find_key(CAPI_CTX * ctx, const char *id) 1431296341Sdelphij{ 1432296341Sdelphij PCCERT_CONTEXT cert; 1433296341Sdelphij HCERTSTORE hstore; 1434296341Sdelphij CAPI_KEY *key = NULL; 1435296341Sdelphij switch (ctx->lookup_method) { 1436296341Sdelphij case CAPI_LU_SUBSTR: 1437296341Sdelphij case CAPI_LU_FNAME: 1438296341Sdelphij hstore = capi_open_store(ctx, NULL); 1439296341Sdelphij if (!hstore) 1440296341Sdelphij return NULL; 1441296341Sdelphij cert = capi_find_cert(ctx, id, hstore); 1442296341Sdelphij if (cert) { 1443296341Sdelphij key = capi_get_cert_key(ctx, cert); 1444296341Sdelphij CertFreeCertificateContext(cert); 1445296341Sdelphij } 1446296341Sdelphij CertCloseStore(hstore, 0); 1447296341Sdelphij break; 1448183234Ssimon 1449296341Sdelphij case CAPI_LU_CONTNAME: 1450296341Sdelphij key = capi_get_key(ctx, id, ctx->cspname, ctx->csptype, ctx->keytype); 1451296341Sdelphij break; 1452296341Sdelphij } 1453183234Ssimon 1454296341Sdelphij return key; 1455296341Sdelphij} 1456183234Ssimon 1457296341Sdelphijvoid capi_free_key(CAPI_KEY * key) 1458296341Sdelphij{ 1459296341Sdelphij if (!key) 1460296341Sdelphij return; 1461296341Sdelphij CryptDestroyKey(key->key); 1462296341Sdelphij CryptReleaseContext(key->hprov, 0); 1463296341Sdelphij if (key->pcert) 1464296341Sdelphij CertFreeCertificateContext(key->pcert); 1465296341Sdelphij OPENSSL_free(key); 1466296341Sdelphij} 1467183234Ssimon 1468183234Ssimon/* Initialize a CAPI_CTX structure */ 1469183234Ssimon 1470183234Ssimonstatic CAPI_CTX *capi_ctx_new() 1471296341Sdelphij{ 1472296341Sdelphij CAPI_CTX *ctx; 1473296341Sdelphij ctx = OPENSSL_malloc(sizeof(CAPI_CTX)); 1474296341Sdelphij if (!ctx) { 1475296341Sdelphij CAPIerr(CAPI_F_CAPI_CTX_NEW, ERR_R_MALLOC_FAILURE); 1476296341Sdelphij return NULL; 1477296341Sdelphij } 1478296341Sdelphij ctx->cspname = NULL; 1479296341Sdelphij ctx->csptype = PROV_RSA_FULL; 1480296341Sdelphij ctx->dump_flags = CAPI_DMP_SUMMARY | CAPI_DMP_FNAME; 1481296341Sdelphij ctx->keytype = AT_KEYEXCHANGE; 1482296341Sdelphij ctx->storename = NULL; 1483296341Sdelphij ctx->ssl_client_store = NULL; 1484296341Sdelphij ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG | 1485296341Sdelphij CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER; 1486296341Sdelphij ctx->lookup_method = CAPI_LU_SUBSTR; 1487296341Sdelphij ctx->debug_level = 0; 1488296341Sdelphij ctx->debug_file = NULL; 1489296341Sdelphij ctx->client_cert_select = cert_select_simple; 1490296341Sdelphij return ctx; 1491296341Sdelphij} 1492183234Ssimon 1493296341Sdelphijstatic void capi_ctx_free(CAPI_CTX * ctx) 1494296341Sdelphij{ 1495296341Sdelphij CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx); 1496296341Sdelphij if (!ctx) 1497296341Sdelphij return; 1498296341Sdelphij if (ctx->cspname) 1499296341Sdelphij OPENSSL_free(ctx->cspname); 1500296341Sdelphij if (ctx->debug_file) 1501296341Sdelphij OPENSSL_free(ctx->debug_file); 1502296341Sdelphij if (ctx->storename) 1503296341Sdelphij OPENSSL_free(ctx->storename); 1504296341Sdelphij if (ctx->ssl_client_store) 1505296341Sdelphij OPENSSL_free(ctx->ssl_client_store); 1506296341Sdelphij OPENSSL_free(ctx); 1507296341Sdelphij} 1508183234Ssimon 1509296341Sdelphijstatic int capi_ctx_set_provname(CAPI_CTX * ctx, LPSTR pname, DWORD type, 1510296341Sdelphij int check) 1511296341Sdelphij{ 1512296341Sdelphij CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type); 1513296341Sdelphij if (check) { 1514296341Sdelphij HCRYPTPROV hprov; 1515296341Sdelphij if (!CryptAcquireContextA(&hprov, NULL, pname, type, 1516296341Sdelphij CRYPT_VERIFYCONTEXT)) { 1517296341Sdelphij CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, 1518296341Sdelphij CAPI_R_CRYPTACQUIRECONTEXT_ERROR); 1519296341Sdelphij capi_addlasterror(); 1520296341Sdelphij return 0; 1521296341Sdelphij } 1522296341Sdelphij CryptReleaseContext(hprov, 0); 1523296341Sdelphij } 1524296341Sdelphij if (ctx->cspname) 1525296341Sdelphij OPENSSL_free(ctx->cspname); 1526296341Sdelphij ctx->cspname = BUF_strdup(pname); 1527296341Sdelphij ctx->csptype = type; 1528296341Sdelphij return 1; 1529296341Sdelphij} 1530183234Ssimon 1531296341Sdelphijstatic int capi_ctx_set_provname_idx(CAPI_CTX * ctx, int idx) 1532296341Sdelphij{ 1533296341Sdelphij LPSTR pname; 1534296341Sdelphij DWORD type; 1535296341Sdelphij int res; 1536296341Sdelphij if (capi_get_provname(ctx, &pname, &type, idx) != 1) 1537296341Sdelphij return 0; 1538296341Sdelphij res = capi_ctx_set_provname(ctx, pname, type, 0); 1539296341Sdelphij OPENSSL_free(pname); 1540296341Sdelphij return res; 1541296341Sdelphij} 1542183234Ssimon 1543183234Ssimonstatic int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x) 1544296341Sdelphij{ 1545296341Sdelphij int i; 1546296341Sdelphij X509_NAME *nm; 1547296341Sdelphij /* Special case: empty list: match anything */ 1548296341Sdelphij if (sk_X509_NAME_num(ca_dn) <= 0) 1549296341Sdelphij return 1; 1550296341Sdelphij for (i = 0; i < sk_X509_NAME_num(ca_dn); i++) { 1551296341Sdelphij nm = sk_X509_NAME_value(ca_dn, i); 1552296341Sdelphij if (!X509_NAME_cmp(nm, X509_get_issuer_name(x))) 1553296341Sdelphij return 1; 1554296341Sdelphij } 1555296341Sdelphij return 0; 1556296341Sdelphij} 1557183234Ssimon 1558183234Ssimonstatic int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, 1559296341Sdelphij STACK_OF(X509_NAME) *ca_dn, X509 **pcert, 1560296341Sdelphij EVP_PKEY **pkey, STACK_OF(X509) **pother, 1561296341Sdelphij UI_METHOD *ui_method, 1562296341Sdelphij void *callback_data) 1563296341Sdelphij{ 1564296341Sdelphij STACK_OF(X509) *certs = NULL; 1565296341Sdelphij X509 *x; 1566296341Sdelphij char *storename; 1567296341Sdelphij const char *p; 1568296341Sdelphij int i, client_cert_idx; 1569296341Sdelphij HCERTSTORE hstore; 1570296341Sdelphij PCCERT_CONTEXT cert = NULL, excert = NULL; 1571296341Sdelphij CAPI_CTX *ctx; 1572296341Sdelphij CAPI_KEY *key; 1573296341Sdelphij ctx = ENGINE_get_ex_data(e, capi_idx); 1574183234Ssimon 1575296341Sdelphij *pcert = NULL; 1576296341Sdelphij *pkey = NULL; 1577183234Ssimon 1578296341Sdelphij storename = ctx->ssl_client_store; 1579296341Sdelphij if (!storename) 1580296341Sdelphij storename = "MY"; 1581183234Ssimon 1582296341Sdelphij hstore = capi_open_store(ctx, storename); 1583296341Sdelphij if (!hstore) 1584296341Sdelphij return 0; 1585296341Sdelphij /* Enumerate all certificates collect any matches */ 1586296341Sdelphij for (i = 0;; i++) { 1587296341Sdelphij cert = CertEnumCertificatesInStore(hstore, cert); 1588296341Sdelphij if (!cert) 1589296341Sdelphij break; 1590296341Sdelphij p = cert->pbCertEncoded; 1591296341Sdelphij x = d2i_X509(NULL, &p, cert->cbCertEncoded); 1592296341Sdelphij if (!x) { 1593296341Sdelphij CAPI_trace(ctx, "Can't Parse Certificate %d\n", i); 1594296341Sdelphij continue; 1595296341Sdelphij } 1596296341Sdelphij if (cert_issuer_match(ca_dn, x) 1597296341Sdelphij && X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0)) { 1598296341Sdelphij key = capi_get_cert_key(ctx, cert); 1599296341Sdelphij if (!key) { 1600296341Sdelphij X509_free(x); 1601296341Sdelphij continue; 1602296341Sdelphij } 1603296341Sdelphij /* 1604296341Sdelphij * Match found: attach extra data to it so we can retrieve the 1605296341Sdelphij * key later. 1606296341Sdelphij */ 1607296341Sdelphij excert = CertDuplicateCertificateContext(cert); 1608296341Sdelphij key->pcert = excert; 1609296341Sdelphij X509_set_ex_data(x, cert_capi_idx, key); 1610183234Ssimon 1611296341Sdelphij if (!certs) 1612296341Sdelphij certs = sk_X509_new_null(); 1613183234Ssimon 1614296341Sdelphij sk_X509_push(certs, x); 1615296341Sdelphij } else 1616296341Sdelphij X509_free(x); 1617183234Ssimon 1618296341Sdelphij } 1619183234Ssimon 1620296341Sdelphij if (cert) 1621296341Sdelphij CertFreeCertificateContext(cert); 1622296341Sdelphij if (hstore) 1623296341Sdelphij CertCloseStore(hstore, 0); 1624183234Ssimon 1625296341Sdelphij if (!certs) 1626296341Sdelphij return 0; 1627183234Ssimon 1628296341Sdelphij /* Select the appropriate certificate */ 1629183234Ssimon 1630296341Sdelphij client_cert_idx = ctx->client_cert_select(e, ssl, certs); 1631183234Ssimon 1632296341Sdelphij /* Set the selected certificate and free the rest */ 1633183234Ssimon 1634296341Sdelphij for (i = 0; i < sk_X509_num(certs); i++) { 1635296341Sdelphij x = sk_X509_value(certs, i); 1636296341Sdelphij if (i == client_cert_idx) 1637296341Sdelphij *pcert = x; 1638296341Sdelphij else { 1639296341Sdelphij key = X509_get_ex_data(x, cert_capi_idx); 1640296341Sdelphij capi_free_key(key); 1641296341Sdelphij X509_free(x); 1642296341Sdelphij } 1643296341Sdelphij } 1644183234Ssimon 1645296341Sdelphij sk_X509_free(certs); 1646183234Ssimon 1647296341Sdelphij if (!*pcert) 1648296341Sdelphij return 0; 1649183234Ssimon 1650296341Sdelphij /* Setup key for selected certificate */ 1651183234Ssimon 1652296341Sdelphij key = X509_get_ex_data(*pcert, cert_capi_idx); 1653296341Sdelphij *pkey = capi_get_pkey(e, key); 1654296341Sdelphij X509_set_ex_data(*pcert, cert_capi_idx, NULL); 1655183234Ssimon 1656296341Sdelphij return 1; 1657183234Ssimon 1658296341Sdelphij} 1659183234Ssimon 1660183234Ssimon/* Simple client cert selection function: always select first */ 1661183234Ssimon 1662183234Ssimonstatic int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) 1663296341Sdelphij{ 1664296341Sdelphij return 0; 1665296341Sdelphij} 1666183234Ssimon 1667296341Sdelphij# ifdef OPENSSL_CAPIENG_DIALOG 1668183234Ssimon 1669296341Sdelphij/* 1670296341Sdelphij * More complex cert selection function, using standard function 1671183234Ssimon * CryptUIDlgSelectCertificateFromStore() to produce a dialog box. 1672183234Ssimon */ 1673183234Ssimon 1674296341Sdelphij/* 1675296341Sdelphij * Definitions which are in cryptuiapi.h but this is not present in older 1676183234Ssimon * versions of headers. 1677183234Ssimon */ 1678183234Ssimon 1679296341Sdelphij# ifndef CRYPTUI_SELECT_LOCATION_COLUMN 1680296341Sdelphij# define CRYPTUI_SELECT_LOCATION_COLUMN 0x000000010 1681296341Sdelphij# define CRYPTUI_SELECT_INTENDEDUSE_COLUMN 0x000000004 1682296341Sdelphij# endif 1683183234Ssimon 1684296341Sdelphij# define dlg_title L"OpenSSL Application SSL Client Certificate Selection" 1685296341Sdelphij# define dlg_prompt L"Select a certificate to use for authentication" 1686296341Sdelphij# define dlg_columns CRYPTUI_SELECT_LOCATION_COLUMN \ 1687296341Sdelphij |CRYPTUI_SELECT_INTENDEDUSE_COLUMN 1688183234Ssimon 1689183234Ssimonstatic int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) 1690296341Sdelphij{ 1691296341Sdelphij X509 *x; 1692296341Sdelphij HCERTSTORE dstore; 1693296341Sdelphij PCCERT_CONTEXT cert; 1694296341Sdelphij CAPI_CTX *ctx; 1695296341Sdelphij CAPI_KEY *key; 1696296341Sdelphij HWND hwnd; 1697296341Sdelphij int i, idx = -1; 1698296341Sdelphij if (sk_X509_num(certs) == 1) 1699296341Sdelphij return 0; 1700296341Sdelphij ctx = ENGINE_get_ex_data(e, capi_idx); 1701296341Sdelphij /* Create an in memory store of certificates */ 1702296341Sdelphij dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 1703296341Sdelphij CERT_STORE_CREATE_NEW_FLAG, NULL); 1704296341Sdelphij if (!dstore) { 1705296341Sdelphij CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE); 1706296341Sdelphij capi_addlasterror(); 1707296341Sdelphij goto err; 1708296341Sdelphij } 1709296341Sdelphij /* Add all certificates to store */ 1710296341Sdelphij for (i = 0; i < sk_X509_num(certs); i++) { 1711296341Sdelphij x = sk_X509_value(certs, i); 1712296341Sdelphij key = X509_get_ex_data(x, cert_capi_idx); 1713183234Ssimon 1714296341Sdelphij if (!CertAddCertificateContextToStore(dstore, key->pcert, 1715296341Sdelphij CERT_STORE_ADD_NEW, NULL)) { 1716296341Sdelphij CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT); 1717296341Sdelphij capi_addlasterror(); 1718296341Sdelphij goto err; 1719296341Sdelphij } 1720183234Ssimon 1721296341Sdelphij } 1722296341Sdelphij hwnd = GetForegroundWindow(); 1723296341Sdelphij if (!hwnd) 1724296341Sdelphij hwnd = GetActiveWindow(); 1725296341Sdelphij if (!hwnd && ctx->getconswindow) 1726296341Sdelphij hwnd = ctx->getconswindow(); 1727296341Sdelphij /* Call dialog to select one */ 1728296341Sdelphij cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt, 1729296341Sdelphij dlg_columns, 0, NULL); 1730183234Ssimon 1731296341Sdelphij /* Find matching cert from list */ 1732296341Sdelphij if (cert) { 1733296341Sdelphij for (i = 0; i < sk_X509_num(certs); i++) { 1734296341Sdelphij x = sk_X509_value(certs, i); 1735296341Sdelphij key = X509_get_ex_data(x, cert_capi_idx); 1736296341Sdelphij if (CertCompareCertificate 1737296341Sdelphij (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert->pCertInfo, 1738296341Sdelphij key->pcert->pCertInfo)) { 1739296341Sdelphij idx = i; 1740296341Sdelphij break; 1741296341Sdelphij } 1742296341Sdelphij } 1743296341Sdelphij } 1744183234Ssimon 1745296341Sdelphij err: 1746296341Sdelphij if (dstore) 1747296341Sdelphij CertCloseStore(dstore, 0); 1748296341Sdelphij return idx; 1749183234Ssimon 1750296341Sdelphij} 1751296341Sdelphij# endif 1752183234Ssimon 1753296341Sdelphij#else /* !__COMPILE_CAPIENG */ 1754296341Sdelphij# include <openssl/engine.h> 1755296341Sdelphij# ifndef OPENSSL_NO_DYNAMIC_ENGINE 1756183234SsimonOPENSSL_EXPORT 1757296341Sdelphij int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); 1758238405SjkimOPENSSL_EXPORT 1759296341Sdelphij int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) 1760296341Sdelphij{ 1761296341Sdelphij return 0; 1762296341Sdelphij} 1763296341Sdelphij 1764183234SsimonIMPLEMENT_DYNAMIC_CHECK_FN() 1765296341Sdelphij# else 1766296341Sdelphijvoid ENGINE_load_capi(void) 1767296341Sdelphij{ 1768296341Sdelphij} 1769296341Sdelphij# endif 1770183234Ssimon#endif 1771