16f9291ceSJung-uk Kim /* 2*e71b7053SJung-uk Kim * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. 3*e71b7053SJung-uk Kim * 4*e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5*e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6*e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7*e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 8db522d3aSSimon L. B. Nielsen */ 9*e71b7053SJung-uk Kim 10*e71b7053SJung-uk Kim #ifdef _WIN32 11*e71b7053SJung-uk Kim # ifndef _WIN32_WINNT 12*e71b7053SJung-uk Kim # define _WIN32_WINNT 0x0400 13*e71b7053SJung-uk Kim # endif 14*e71b7053SJung-uk Kim # include <windows.h> 15*e71b7053SJung-uk Kim # include <wincrypt.h> 16db522d3aSSimon L. B. Nielsen 17db522d3aSSimon L. B. Nielsen # include <stdio.h> 18db522d3aSSimon L. B. Nielsen # include <string.h> 197bded2dbSJung-uk Kim # include <stdlib.h> 20*e71b7053SJung-uk Kim # include <malloc.h> 21*e71b7053SJung-uk Kim # ifndef alloca 22*e71b7053SJung-uk Kim # define alloca _alloca 23*e71b7053SJung-uk Kim # endif 247bded2dbSJung-uk Kim 25db522d3aSSimon L. B. Nielsen # include <openssl/crypto.h> 26db522d3aSSimon L. B. Nielsen 27db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_CAPIENG 28db522d3aSSimon L. B. Nielsen 297bded2dbSJung-uk Kim # include <openssl/buffer.h> 307bded2dbSJung-uk Kim # include <openssl/bn.h> 316a599222SSimon L. B. Nielsen # include <openssl/rsa.h> 32*e71b7053SJung-uk Kim # include <openssl/dsa.h> 33db522d3aSSimon L. B. Nielsen 341f13597dSJung-uk Kim /* 351f13597dSJung-uk Kim * This module uses several "new" interfaces, among which is 361f13597dSJung-uk Kim * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is 371f13597dSJung-uk Kim * one of possible values you can pass to function in question. By 381f13597dSJung-uk Kim * checking if it's defined we can see if wincrypt.h and accompanying 391f13597dSJung-uk Kim * crypt32.lib are in shape. The native MingW32 headers up to and 401f13597dSJung-uk Kim * including __W32API_VERSION 3.14 lack of struct DSSPUBKEY and the 411f13597dSJung-uk Kim * defines CERT_STORE_PROV_SYSTEM_A and CERT_STORE_READONLY_FLAG, 421f13597dSJung-uk Kim * so we check for these too and avoid compiling. 431f13597dSJung-uk Kim * Yes, it's rather "weak" test and if compilation fails, 441f13597dSJung-uk Kim * then re-configure with -DOPENSSL_NO_CAPIENG. 451f13597dSJung-uk Kim */ 461f13597dSJung-uk Kim # if defined(CERT_KEY_PROV_INFO_PROP_ID) && \ 471f13597dSJung-uk Kim defined(CERT_STORE_PROV_SYSTEM_A) && \ 481f13597dSJung-uk Kim defined(CERT_STORE_READONLY_FLAG) 491f13597dSJung-uk Kim # define __COMPILE_CAPIENG 501f13597dSJung-uk Kim # endif /* CERT_KEY_PROV_INFO_PROP_ID */ 511f13597dSJung-uk Kim # endif /* OPENSSL_NO_CAPIENG */ 52*e71b7053SJung-uk Kim #endif /* _WIN32 */ 531f13597dSJung-uk Kim 541f13597dSJung-uk Kim #ifdef __COMPILE_CAPIENG 551f13597dSJung-uk Kim 56db522d3aSSimon L. B. Nielsen # undef X509_EXTENSIONS 57db522d3aSSimon L. B. Nielsen 58db522d3aSSimon L. B. Nielsen /* Definitions which may be missing from earlier version of headers */ 59db522d3aSSimon L. B. Nielsen # ifndef CERT_STORE_OPEN_EXISTING_FLAG 60db522d3aSSimon L. B. Nielsen # define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 61db522d3aSSimon L. B. Nielsen # endif 62db522d3aSSimon L. B. Nielsen 63db522d3aSSimon L. B. Nielsen # ifndef CERT_STORE_CREATE_NEW_FLAG 64db522d3aSSimon L. B. Nielsen # define CERT_STORE_CREATE_NEW_FLAG 0x00002000 65db522d3aSSimon L. B. Nielsen # endif 66db522d3aSSimon L. B. Nielsen 67ab8565e2SSimon L. B. Nielsen # ifndef CERT_SYSTEM_STORE_CURRENT_USER 68ab8565e2SSimon L. B. Nielsen # define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000 69ab8565e2SSimon L. B. Nielsen # endif 70ab8565e2SSimon L. B. Nielsen 714c6a0400SJung-uk Kim # ifndef ALG_SID_SHA_256 724c6a0400SJung-uk Kim # define ALG_SID_SHA_256 12 734c6a0400SJung-uk Kim # endif 744c6a0400SJung-uk Kim # ifndef ALG_SID_SHA_384 754c6a0400SJung-uk Kim # define ALG_SID_SHA_384 13 764c6a0400SJung-uk Kim # endif 774c6a0400SJung-uk Kim # ifndef ALG_SID_SHA_512 784c6a0400SJung-uk Kim # define ALG_SID_SHA_512 14 794c6a0400SJung-uk Kim # endif 804c6a0400SJung-uk Kim 814c6a0400SJung-uk Kim # ifndef CALG_SHA_256 824c6a0400SJung-uk Kim # define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256) 834c6a0400SJung-uk Kim # endif 844c6a0400SJung-uk Kim # ifndef CALG_SHA_384 854c6a0400SJung-uk Kim # define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384) 864c6a0400SJung-uk Kim # endif 874c6a0400SJung-uk Kim # ifndef CALG_SHA_512 884c6a0400SJung-uk Kim # define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512) 894c6a0400SJung-uk Kim # endif 904c6a0400SJung-uk Kim 91*e71b7053SJung-uk Kim # ifndef PROV_RSA_AES 92*e71b7053SJung-uk Kim # define PROV_RSA_AES 24 93*e71b7053SJung-uk Kim # endif 94*e71b7053SJung-uk Kim 95db522d3aSSimon L. B. Nielsen # include <openssl/engine.h> 96db522d3aSSimon L. B. Nielsen # include <openssl/pem.h> 97db522d3aSSimon L. B. Nielsen # include <openssl/x509v3.h> 98db522d3aSSimon L. B. Nielsen 99db522d3aSSimon L. B. Nielsen # include "e_capi_err.h" 100db522d3aSSimon L. B. Nielsen # include "e_capi_err.c" 101db522d3aSSimon L. B. Nielsen 102db522d3aSSimon L. B. Nielsen static const char *engine_capi_id = "capi"; 103db522d3aSSimon L. B. Nielsen static const char *engine_capi_name = "CryptoAPI ENGINE"; 104db522d3aSSimon L. B. Nielsen 105db522d3aSSimon L. B. Nielsen typedef struct CAPI_CTX_st CAPI_CTX; 106db522d3aSSimon L. B. Nielsen typedef struct CAPI_KEY_st CAPI_KEY; 107db522d3aSSimon L. B. Nielsen 108db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void); 109db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err); 110db522d3aSSimon L. B. Nielsen 111db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX *ctx, char *format, ...); 112db522d3aSSimon L. B. Nielsen 113db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX *ctx, BIO *out); 114db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX *ctx, BIO *out); 115db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *storename); 116db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY *key); 117db522d3aSSimon L. B. Nielsen 1186f9291ceSJung-uk Kim static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, 1196f9291ceSJung-uk Kim HCERTSTORE hstore); 120db522d3aSSimon L. B. Nielsen 121db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id); 122db522d3aSSimon L. B. Nielsen 123db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id, 124db522d3aSSimon L. B. Nielsen UI_METHOD *ui_method, void *callback_data); 1256f9291ceSJung-uk Kim static int capi_rsa_sign(int dtype, const unsigned char *m, 1266f9291ceSJung-uk Kim unsigned int m_len, unsigned char *sigret, 1276f9291ceSJung-uk Kim unsigned int *siglen, const RSA *rsa); 128db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_enc(int flen, const unsigned char *from, 129db522d3aSSimon L. B. Nielsen unsigned char *to, RSA *rsa, int padding); 130db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_dec(int flen, const unsigned char *from, 131db522d3aSSimon L. B. Nielsen unsigned char *to, RSA *rsa, int padding); 132db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa); 133db522d3aSSimon L. B. Nielsen 134*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 135db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, 136db522d3aSSimon L. B. Nielsen DSA *dsa); 137db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa); 138*e71b7053SJung-uk Kim # endif 139db522d3aSSimon L. B. Nielsen 140db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, 1416f9291ceSJung-uk Kim STACK_OF(X509_NAME) *ca_dn, X509 **pcert, 1426f9291ceSJung-uk Kim EVP_PKEY **pkey, STACK_OF(X509) **pother, 1436f9291ceSJung-uk Kim UI_METHOD *ui_method, 1446f9291ceSJung-uk Kim void *callback_data); 145db522d3aSSimon L. B. Nielsen 146db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); 147db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG 148db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); 149db522d3aSSimon L. B. Nielsen # endif 150db522d3aSSimon L. B. Nielsen 151*e71b7053SJung-uk Kim void engine_load_capi_int(void); 152*e71b7053SJung-uk Kim 153db522d3aSSimon L. B. Nielsen typedef PCCERT_CONTEXT(WINAPI *CERTDLG)(HCERTSTORE, HWND, LPCWSTR, 1546f9291ceSJung-uk Kim LPCWSTR, DWORD, DWORD, void *); 155db522d3aSSimon L. B. Nielsen typedef HWND(WINAPI *GETCONSWIN)(void); 156db522d3aSSimon L. B. Nielsen 1576f9291ceSJung-uk Kim /* 1586f9291ceSJung-uk Kim * This structure contains CAPI ENGINE specific data: it contains various 1596f9291ceSJung-uk Kim * global options and affects how other functions behave. 160db522d3aSSimon L. B. Nielsen */ 161db522d3aSSimon L. B. Nielsen 162db522d3aSSimon L. B. Nielsen # define CAPI_DBG_TRACE 2 163db522d3aSSimon L. B. Nielsen # define CAPI_DBG_ERROR 1 164db522d3aSSimon L. B. Nielsen 165db522d3aSSimon L. B. Nielsen struct CAPI_CTX_st { 166db522d3aSSimon L. B. Nielsen int debug_level; 167db522d3aSSimon L. B. Nielsen char *debug_file; 168db522d3aSSimon L. B. Nielsen /* Parameters to use for container lookup */ 169db522d3aSSimon L. B. Nielsen DWORD keytype; 1706a599222SSimon L. B. Nielsen LPSTR cspname; 171db522d3aSSimon L. B. Nielsen DWORD csptype; 172db522d3aSSimon L. B. Nielsen /* Certificate store name to use */ 1736a599222SSimon L. B. Nielsen LPSTR storename; 1746a599222SSimon L. B. Nielsen LPSTR ssl_client_store; 175db522d3aSSimon L. B. Nielsen /* System store flags */ 176db522d3aSSimon L. B. Nielsen DWORD store_flags; 177db522d3aSSimon L. B. Nielsen /* Lookup string meanings in load_private_key */ 178*e71b7053SJung-uk Kim # define CAPI_LU_SUBSTR 1 /* Substring of subject: uses "storename" */ 179*e71b7053SJung-uk Kim # define CAPI_LU_FNAME 2 /* Friendly name: uses storename */ 180*e71b7053SJung-uk Kim # define CAPI_LU_CONTNAME 3 /* Container name: uses cspname, keytype */ 181db522d3aSSimon L. B. Nielsen int lookup_method; 182db522d3aSSimon L. B. Nielsen /* Info to dump with dumpcerts option */ 183*e71b7053SJung-uk Kim # define CAPI_DMP_SUMMARY 0x1 /* Issuer and serial name strings */ 184*e71b7053SJung-uk Kim # define CAPI_DMP_FNAME 0x2 /* Friendly name */ 185*e71b7053SJung-uk Kim # define CAPI_DMP_FULL 0x4 /* Full X509_print dump */ 186*e71b7053SJung-uk Kim # define CAPI_DMP_PEM 0x8 /* Dump PEM format certificate */ 187*e71b7053SJung-uk Kim # define CAPI_DMP_PSKEY 0x10 /* Dump pseudo key (if possible) */ 188*e71b7053SJung-uk Kim # define CAPI_DMP_PKEYINFO 0x20 /* Dump key info (if possible) */ 189db522d3aSSimon L. B. Nielsen DWORD dump_flags; 190db522d3aSSimon L. B. Nielsen int (*client_cert_select) (ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); 191db522d3aSSimon L. B. Nielsen CERTDLG certselectdlg; 192db522d3aSSimon L. B. Nielsen GETCONSWIN getconswindow; 193db522d3aSSimon L. B. Nielsen }; 194db522d3aSSimon L. B. Nielsen 195*e71b7053SJung-uk Kim static CAPI_CTX *capi_ctx_new(void); 196db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX *ctx); 1976f9291ceSJung-uk Kim static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, 1986f9291ceSJung-uk Kim int check); 199db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx); 200db522d3aSSimon L. B. Nielsen 201db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CERTS ENGINE_CMD_BASE 202db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LOOKUP_CERT (ENGINE_CMD_BASE + 1) 203db522d3aSSimon L. B. Nielsen # define CAPI_CMD_DEBUG_LEVEL (ENGINE_CMD_BASE + 2) 204db522d3aSSimon L. B. Nielsen # define CAPI_CMD_DEBUG_FILE (ENGINE_CMD_BASE + 3) 205db522d3aSSimon L. B. Nielsen # define CAPI_CMD_KEYTYPE (ENGINE_CMD_BASE + 4) 206db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CSPS (ENGINE_CMD_BASE + 5) 207db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_IDX (ENGINE_CMD_BASE + 6) 208db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_NAME (ENGINE_CMD_BASE + 7) 209db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_TYPE (ENGINE_CMD_BASE + 8) 210db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CONTAINERS (ENGINE_CMD_BASE + 9) 211db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_OPTIONS (ENGINE_CMD_BASE + 10) 212db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LOOKUP_METHOD (ENGINE_CMD_BASE + 11) 213db522d3aSSimon L. B. Nielsen # define CAPI_CMD_STORE_NAME (ENGINE_CMD_BASE + 12) 214db522d3aSSimon L. B. Nielsen # define CAPI_CMD_STORE_FLAGS (ENGINE_CMD_BASE + 13) 215db522d3aSSimon L. B. Nielsen 216db522d3aSSimon L. B. Nielsen static const ENGINE_CMD_DEFN capi_cmd_defns[] = { 217db522d3aSSimon L. B. Nielsen {CAPI_CMD_LIST_CERTS, 218db522d3aSSimon L. B. Nielsen "list_certs", 219db522d3aSSimon L. B. Nielsen "List all certificates in store", 220db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NO_INPUT}, 221db522d3aSSimon L. B. Nielsen {CAPI_CMD_LOOKUP_CERT, 222db522d3aSSimon L. B. Nielsen "lookup_cert", 223db522d3aSSimon L. B. Nielsen "Lookup and output certificates", 224db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_STRING}, 225db522d3aSSimon L. B. Nielsen {CAPI_CMD_DEBUG_LEVEL, 226db522d3aSSimon L. B. Nielsen "debug_level", 227db522d3aSSimon L. B. Nielsen "debug level (1=errors, 2=trace)", 228db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NUMERIC}, 229db522d3aSSimon L. B. Nielsen {CAPI_CMD_DEBUG_FILE, 230db522d3aSSimon L. B. Nielsen "debug_file", 231db522d3aSSimon L. B. Nielsen "debugging filename)", 232db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_STRING}, 233db522d3aSSimon L. B. Nielsen {CAPI_CMD_KEYTYPE, 234db522d3aSSimon L. B. Nielsen "key_type", 235db522d3aSSimon L. B. Nielsen "Key type: 1=AT_KEYEXCHANGE (default), 2=AT_SIGNATURE", 236db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NUMERIC}, 237db522d3aSSimon L. B. Nielsen {CAPI_CMD_LIST_CSPS, 238db522d3aSSimon L. B. Nielsen "list_csps", 239db522d3aSSimon L. B. Nielsen "List all CSPs", 240db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NO_INPUT}, 241db522d3aSSimon L. B. Nielsen {CAPI_CMD_SET_CSP_IDX, 242db522d3aSSimon L. B. Nielsen "csp_idx", 243db522d3aSSimon L. B. Nielsen "Set CSP by index", 244db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NUMERIC}, 245db522d3aSSimon L. B. Nielsen {CAPI_CMD_SET_CSP_NAME, 246db522d3aSSimon L. B. Nielsen "csp_name", 247db522d3aSSimon L. B. Nielsen "Set CSP name, (default CSP used if not specified)", 248db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_STRING}, 249db522d3aSSimon L. B. Nielsen {CAPI_CMD_SET_CSP_TYPE, 250db522d3aSSimon L. B. Nielsen "csp_type", 251db522d3aSSimon L. B. Nielsen "Set CSP type, (default RSA_PROV_FULL)", 252db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NUMERIC}, 253db522d3aSSimon L. B. Nielsen {CAPI_CMD_LIST_CONTAINERS, 254db522d3aSSimon L. B. Nielsen "list_containers", 255db522d3aSSimon L. B. Nielsen "list container names", 256db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NO_INPUT}, 257db522d3aSSimon L. B. Nielsen {CAPI_CMD_LIST_OPTIONS, 258db522d3aSSimon L. B. Nielsen "list_options", 259db522d3aSSimon L. B. Nielsen "Set list options (1=summary,2=friendly name, 4=full printout, 8=PEM output, 16=XXX, " 260db522d3aSSimon L. B. Nielsen "32=private key info)", 261db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NUMERIC}, 262db522d3aSSimon L. B. Nielsen {CAPI_CMD_LOOKUP_METHOD, 263db522d3aSSimon L. B. Nielsen "lookup_method", 264db522d3aSSimon L. B. Nielsen "Set key lookup method (1=substring, 2=friendlyname, 3=container name)", 265db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NUMERIC}, 266db522d3aSSimon L. B. Nielsen {CAPI_CMD_STORE_NAME, 267db522d3aSSimon L. B. Nielsen "store_name", 268db522d3aSSimon L. B. Nielsen "certificate store name, default \"MY\"", 269db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_STRING}, 270db522d3aSSimon L. B. Nielsen {CAPI_CMD_STORE_FLAGS, 271db522d3aSSimon L. B. Nielsen "store_flags", 272db522d3aSSimon L. B. Nielsen "Certificate store flags: 1 = system store", 273db522d3aSSimon L. B. Nielsen ENGINE_CMD_FLAG_NUMERIC}, 274db522d3aSSimon L. B. Nielsen 275db522d3aSSimon L. B. Nielsen {0, NULL, NULL, 0} 276db522d3aSSimon L. B. Nielsen }; 277db522d3aSSimon L. B. Nielsen 278db522d3aSSimon L. B. Nielsen static int capi_idx = -1; 279db522d3aSSimon L. B. Nielsen static int rsa_capi_idx = -1; 280db522d3aSSimon L. B. Nielsen static int dsa_capi_idx = -1; 281db522d3aSSimon L. B. Nielsen static int cert_capi_idx = -1; 282db522d3aSSimon L. B. Nielsen 283db522d3aSSimon L. B. Nielsen static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) 284db522d3aSSimon L. B. Nielsen { 285db522d3aSSimon L. B. Nielsen int ret = 1; 286db522d3aSSimon L. B. Nielsen CAPI_CTX *ctx; 287db522d3aSSimon L. B. Nielsen BIO *out; 288*e71b7053SJung-uk Kim LPSTR tmpstr; 2896f9291ceSJung-uk Kim if (capi_idx == -1) { 290db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED); 291db522d3aSSimon L. B. Nielsen return 0; 292db522d3aSSimon L. B. Nielsen } 293db522d3aSSimon L. B. Nielsen ctx = ENGINE_get_ex_data(e, capi_idx); 294db522d3aSSimon L. B. Nielsen out = BIO_new_fp(stdout, BIO_NOCLOSE); 295*e71b7053SJung-uk Kim if (out == NULL) { 296*e71b7053SJung-uk Kim CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_FILE_OPEN_ERROR); 297*e71b7053SJung-uk Kim return 0; 298*e71b7053SJung-uk Kim } 2996f9291ceSJung-uk Kim switch (cmd) { 300db522d3aSSimon L. B. Nielsen case CAPI_CMD_LIST_CSPS: 301db522d3aSSimon L. B. Nielsen ret = capi_list_providers(ctx, out); 302db522d3aSSimon L. B. Nielsen break; 303db522d3aSSimon L. B. Nielsen 304db522d3aSSimon L. B. Nielsen case CAPI_CMD_LIST_CERTS: 305db522d3aSSimon L. B. Nielsen ret = capi_list_certs(ctx, out, NULL); 306db522d3aSSimon L. B. Nielsen break; 307db522d3aSSimon L. B. Nielsen 308db522d3aSSimon L. B. Nielsen case CAPI_CMD_LOOKUP_CERT: 309db522d3aSSimon L. B. Nielsen ret = capi_list_certs(ctx, out, p); 310db522d3aSSimon L. B. Nielsen break; 311db522d3aSSimon L. B. Nielsen 312db522d3aSSimon L. B. Nielsen case CAPI_CMD_LIST_CONTAINERS: 313db522d3aSSimon L. B. Nielsen ret = capi_list_containers(ctx, out); 314db522d3aSSimon L. B. Nielsen break; 315db522d3aSSimon L. B. Nielsen 316db522d3aSSimon L. B. Nielsen case CAPI_CMD_STORE_NAME: 317*e71b7053SJung-uk Kim tmpstr = OPENSSL_strdup(p); 318*e71b7053SJung-uk Kim if (tmpstr != NULL) { 319db522d3aSSimon L. B. Nielsen OPENSSL_free(ctx->storename); 320*e71b7053SJung-uk Kim ctx->storename = tmpstr; 321db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Setting store name to %s\n", p); 322*e71b7053SJung-uk Kim } else { 323*e71b7053SJung-uk Kim CAPIerr(CAPI_F_CAPI_CTRL, ERR_R_MALLOC_FAILURE); 324*e71b7053SJung-uk Kim ret = 0; 325*e71b7053SJung-uk Kim } 326db522d3aSSimon L. B. Nielsen break; 327db522d3aSSimon L. B. Nielsen 328db522d3aSSimon L. B. Nielsen case CAPI_CMD_STORE_FLAGS: 3296f9291ceSJung-uk Kim if (i & 1) { 330db522d3aSSimon L. B. Nielsen ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE; 331db522d3aSSimon L. B. Nielsen ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER; 3326f9291ceSJung-uk Kim } else { 333db522d3aSSimon L. B. Nielsen ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER; 334db522d3aSSimon L. B. Nielsen ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE; 335db522d3aSSimon L. B. Nielsen } 336db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Setting flags to %d\n", i); 337db522d3aSSimon L. B. Nielsen break; 338db522d3aSSimon L. B. Nielsen 339db522d3aSSimon L. B. Nielsen case CAPI_CMD_DEBUG_LEVEL: 340db522d3aSSimon L. B. Nielsen ctx->debug_level = (int)i; 341db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level); 342db522d3aSSimon L. B. Nielsen break; 343db522d3aSSimon L. B. Nielsen 344db522d3aSSimon L. B. Nielsen case CAPI_CMD_DEBUG_FILE: 345*e71b7053SJung-uk Kim tmpstr = OPENSSL_strdup(p); 346*e71b7053SJung-uk Kim if (tmpstr != NULL) { 347*e71b7053SJung-uk Kim ctx->debug_file = tmpstr; 348db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file); 349*e71b7053SJung-uk Kim } else { 350*e71b7053SJung-uk Kim CAPIerr(CAPI_F_CAPI_CTRL, ERR_R_MALLOC_FAILURE); 351*e71b7053SJung-uk Kim ret = 0; 352*e71b7053SJung-uk Kim } 353db522d3aSSimon L. B. Nielsen break; 354db522d3aSSimon L. B. Nielsen 355db522d3aSSimon L. B. Nielsen case CAPI_CMD_KEYTYPE: 356db522d3aSSimon L. B. Nielsen ctx->keytype = i; 357db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype); 358db522d3aSSimon L. B. Nielsen break; 359db522d3aSSimon L. B. Nielsen 360db522d3aSSimon L. B. Nielsen case CAPI_CMD_SET_CSP_IDX: 361db522d3aSSimon L. B. Nielsen ret = capi_ctx_set_provname_idx(ctx, i); 362db522d3aSSimon L. B. Nielsen break; 363db522d3aSSimon L. B. Nielsen 364db522d3aSSimon L. B. Nielsen case CAPI_CMD_LIST_OPTIONS: 365db522d3aSSimon L. B. Nielsen ctx->dump_flags = i; 366db522d3aSSimon L. B. Nielsen break; 367db522d3aSSimon L. B. Nielsen 368db522d3aSSimon L. B. Nielsen case CAPI_CMD_LOOKUP_METHOD: 3696f9291ceSJung-uk Kim if (i < 1 || i > 3) { 370db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD); 371*e71b7053SJung-uk Kim BIO_free(out); 372db522d3aSSimon L. B. Nielsen return 0; 373db522d3aSSimon L. B. Nielsen } 374db522d3aSSimon L. B. Nielsen ctx->lookup_method = i; 375db522d3aSSimon L. B. Nielsen break; 376db522d3aSSimon L. B. Nielsen 377db522d3aSSimon L. B. Nielsen case CAPI_CMD_SET_CSP_NAME: 378db522d3aSSimon L. B. Nielsen ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1); 379db522d3aSSimon L. B. Nielsen break; 380db522d3aSSimon L. B. Nielsen 381db522d3aSSimon L. B. Nielsen case CAPI_CMD_SET_CSP_TYPE: 382db522d3aSSimon L. B. Nielsen ctx->csptype = i; 383db522d3aSSimon L. B. Nielsen break; 384db522d3aSSimon L. B. Nielsen 385db522d3aSSimon L. B. Nielsen default: 386db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND); 387db522d3aSSimon L. B. Nielsen ret = 0; 388db522d3aSSimon L. B. Nielsen } 389db522d3aSSimon L. B. Nielsen 390db522d3aSSimon L. B. Nielsen BIO_free(out); 391db522d3aSSimon L. B. Nielsen return ret; 392db522d3aSSimon L. B. Nielsen 393db522d3aSSimon L. B. Nielsen } 394db522d3aSSimon L. B. Nielsen 395*e71b7053SJung-uk Kim static RSA_METHOD *capi_rsa_method = NULL; 396*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 397*e71b7053SJung-uk Kim static DSA_METHOD *capi_dsa_method = NULL; 398*e71b7053SJung-uk Kim # endif 399db522d3aSSimon L. B. Nielsen 400*e71b7053SJung-uk Kim static int use_aes_csp = 0; 401*e71b7053SJung-uk Kim static const WCHAR rsa_aes_cspname[] = 402*e71b7053SJung-uk Kim L"Microsoft Enhanced RSA and AES Cryptographic Provider"; 403*e71b7053SJung-uk Kim static const WCHAR rsa_enh_cspname[] = 404*e71b7053SJung-uk Kim L"Microsoft Enhanced Cryptographic Provider v1.0"; 405db522d3aSSimon L. B. Nielsen 406db522d3aSSimon L. B. Nielsen static int capi_init(ENGINE *e) 407db522d3aSSimon L. B. Nielsen { 408db522d3aSSimon L. B. Nielsen CAPI_CTX *ctx; 409db522d3aSSimon L. B. Nielsen const RSA_METHOD *ossl_rsa_meth; 410*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 411db522d3aSSimon L. B. Nielsen const DSA_METHOD *ossl_dsa_meth; 412*e71b7053SJung-uk Kim # endif 413*e71b7053SJung-uk Kim HCRYPTPROV hprov; 414db522d3aSSimon L. B. Nielsen 4156f9291ceSJung-uk Kim if (capi_idx < 0) { 41612de4ed2SJung-uk Kim capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0); 41712de4ed2SJung-uk Kim if (capi_idx < 0) 418db522d3aSSimon L. B. Nielsen goto memerr; 419db522d3aSSimon L. B. Nielsen 42012de4ed2SJung-uk Kim cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0); 42112de4ed2SJung-uk Kim 422db522d3aSSimon L. B. Nielsen /* Setup RSA_METHOD */ 423db522d3aSSimon L. B. Nielsen rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0); 424*e71b7053SJung-uk Kim ossl_rsa_meth = RSA_PKCS1_OpenSSL(); 425*e71b7053SJung-uk Kim if ( !RSA_meth_set_pub_enc(capi_rsa_method, 426*e71b7053SJung-uk Kim RSA_meth_get_pub_enc(ossl_rsa_meth)) 427*e71b7053SJung-uk Kim || !RSA_meth_set_pub_dec(capi_rsa_method, 428*e71b7053SJung-uk Kim RSA_meth_get_pub_dec(ossl_rsa_meth)) 429*e71b7053SJung-uk Kim || !RSA_meth_set_priv_enc(capi_rsa_method, capi_rsa_priv_enc) 430*e71b7053SJung-uk Kim || !RSA_meth_set_priv_dec(capi_rsa_method, capi_rsa_priv_dec) 431*e71b7053SJung-uk Kim || !RSA_meth_set_mod_exp(capi_rsa_method, 432*e71b7053SJung-uk Kim RSA_meth_get_mod_exp(ossl_rsa_meth)) 433*e71b7053SJung-uk Kim || !RSA_meth_set_bn_mod_exp(capi_rsa_method, 434*e71b7053SJung-uk Kim RSA_meth_get_bn_mod_exp(ossl_rsa_meth)) 435*e71b7053SJung-uk Kim || !RSA_meth_set_finish(capi_rsa_method, capi_rsa_free) 436*e71b7053SJung-uk Kim || !RSA_meth_set_sign(capi_rsa_method, capi_rsa_sign)) { 437*e71b7053SJung-uk Kim goto memerr; 438*e71b7053SJung-uk Kim } 439db522d3aSSimon L. B. Nielsen 440*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 441db522d3aSSimon L. B. Nielsen /* Setup DSA Method */ 442db522d3aSSimon L. B. Nielsen dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0); 443db522d3aSSimon L. B. Nielsen ossl_dsa_meth = DSA_OpenSSL(); 444*e71b7053SJung-uk Kim if ( !DSA_meth_set_sign(capi_dsa_method, capi_dsa_do_sign) 445*e71b7053SJung-uk Kim || !DSA_meth_set_verify(capi_dsa_method, 446*e71b7053SJung-uk Kim DSA_meth_get_verify(ossl_dsa_meth)) 447*e71b7053SJung-uk Kim || !DSA_meth_set_finish(capi_dsa_method, capi_dsa_free) 448*e71b7053SJung-uk Kim || !DSA_meth_set_mod_exp(capi_dsa_method, 449*e71b7053SJung-uk Kim DSA_meth_get_mod_exp(ossl_dsa_meth)) 450*e71b7053SJung-uk Kim || !DSA_meth_set_bn_mod_exp(capi_dsa_method, 451*e71b7053SJung-uk Kim DSA_meth_get_bn_mod_exp(ossl_dsa_meth))) { 452*e71b7053SJung-uk Kim goto memerr; 453*e71b7053SJung-uk Kim } 454*e71b7053SJung-uk Kim # endif 45512de4ed2SJung-uk Kim } 45612de4ed2SJung-uk Kim 45712de4ed2SJung-uk Kim ctx = capi_ctx_new(); 458*e71b7053SJung-uk Kim if (ctx == NULL) 45912de4ed2SJung-uk Kim goto memerr; 46012de4ed2SJung-uk Kim 46112de4ed2SJung-uk Kim ENGINE_set_ex_data(e, capi_idx, ctx); 462db522d3aSSimon L. B. Nielsen 463db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG 464db522d3aSSimon L. B. Nielsen { 465db522d3aSSimon L. B. Nielsen HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL")); 4666a599222SSimon L. B. Nielsen HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL")); 467db522d3aSSimon L. B. Nielsen if (cryptui) 4686f9291ceSJung-uk Kim ctx->certselectdlg = 4696f9291ceSJung-uk Kim (CERTDLG) GetProcAddress(cryptui, 4706f9291ceSJung-uk Kim "CryptUIDlgSelectCertificateFromStore"); 471db522d3aSSimon L. B. Nielsen if (kernel) 4726f9291ceSJung-uk Kim ctx->getconswindow = 4736f9291ceSJung-uk Kim (GETCONSWIN) GetProcAddress(kernel, "GetConsoleWindow"); 474db522d3aSSimon L. B. Nielsen if (cryptui && !OPENSSL_isservice()) 475db522d3aSSimon L. B. Nielsen ctx->client_cert_select = cert_select_dialog; 476db522d3aSSimon L. B. Nielsen } 477db522d3aSSimon L. B. Nielsen # endif 478db522d3aSSimon L. B. Nielsen 479*e71b7053SJung-uk Kim /* See if there is RSA+AES CSP */ 480*e71b7053SJung-uk Kim if (CryptAcquireContextW(&hprov, NULL, rsa_aes_cspname, PROV_RSA_AES, 481*e71b7053SJung-uk Kim CRYPT_VERIFYCONTEXT)) { 482*e71b7053SJung-uk Kim use_aes_csp = 1; 483*e71b7053SJung-uk Kim CryptReleaseContext(hprov, 0); 484*e71b7053SJung-uk Kim } 485*e71b7053SJung-uk Kim 486db522d3aSSimon L. B. Nielsen return 1; 487db522d3aSSimon L. B. Nielsen 488db522d3aSSimon L. B. Nielsen memerr: 489db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_INIT, ERR_R_MALLOC_FAILURE); 490db522d3aSSimon L. B. Nielsen return 0; 491db522d3aSSimon L. B. Nielsen 492db522d3aSSimon L. B. Nielsen return 1; 493db522d3aSSimon L. B. Nielsen } 494db522d3aSSimon L. B. Nielsen 495db522d3aSSimon L. B. Nielsen static int capi_destroy(ENGINE *e) 496db522d3aSSimon L. B. Nielsen { 497*e71b7053SJung-uk Kim RSA_meth_free(capi_rsa_method); 498*e71b7053SJung-uk Kim capi_rsa_method = NULL; 499*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 500*e71b7053SJung-uk Kim DSA_meth_free(capi_dsa_method); 501*e71b7053SJung-uk Kim capi_dsa_method = NULL; 502*e71b7053SJung-uk Kim # endif 503db522d3aSSimon L. B. Nielsen ERR_unload_CAPI_strings(); 504db522d3aSSimon L. B. Nielsen return 1; 505db522d3aSSimon L. B. Nielsen } 506db522d3aSSimon L. B. Nielsen 507db522d3aSSimon L. B. Nielsen static int capi_finish(ENGINE *e) 508db522d3aSSimon L. B. Nielsen { 509db522d3aSSimon L. B. Nielsen CAPI_CTX *ctx; 510db522d3aSSimon L. B. Nielsen ctx = ENGINE_get_ex_data(e, capi_idx); 511db522d3aSSimon L. B. Nielsen capi_ctx_free(ctx); 512db522d3aSSimon L. B. Nielsen ENGINE_set_ex_data(e, capi_idx, NULL); 513db522d3aSSimon L. B. Nielsen return 1; 514db522d3aSSimon L. B. Nielsen } 515db522d3aSSimon L. B. Nielsen 5166f9291ceSJung-uk Kim /* 5176f9291ceSJung-uk Kim * CryptoAPI key application data. This contains a handle to the private key 5186f9291ceSJung-uk Kim * container (for sign operations) and a handle to the key (for decrypt 5196f9291ceSJung-uk Kim * operations). 520db522d3aSSimon L. B. Nielsen */ 521db522d3aSSimon L. B. Nielsen 5226f9291ceSJung-uk Kim struct CAPI_KEY_st { 523db522d3aSSimon L. B. Nielsen /* Associated certificate context (if any) */ 524db522d3aSSimon L. B. Nielsen PCCERT_CONTEXT pcert; 525db522d3aSSimon L. B. Nielsen HCRYPTPROV hprov; 526db522d3aSSimon L. B. Nielsen HCRYPTKEY key; 527db522d3aSSimon L. B. Nielsen DWORD keyspec; 528db522d3aSSimon L. B. Nielsen }; 529db522d3aSSimon L. B. Nielsen 530db522d3aSSimon L. B. Nielsen static int bind_capi(ENGINE *e) 531db522d3aSSimon L. B. Nielsen { 532*e71b7053SJung-uk Kim capi_rsa_method = RSA_meth_new("CryptoAPI RSA method", 0); 533*e71b7053SJung-uk Kim if (capi_rsa_method == NULL) 534*e71b7053SJung-uk Kim return 0; 535*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 536*e71b7053SJung-uk Kim capi_dsa_method = DSA_meth_new("CryptoAPI DSA method", 0); 537*e71b7053SJung-uk Kim if (capi_dsa_method == NULL) 538*e71b7053SJung-uk Kim goto memerr; 539*e71b7053SJung-uk Kim # endif 540db522d3aSSimon L. B. Nielsen if (!ENGINE_set_id(e, engine_capi_id) 541db522d3aSSimon L. B. Nielsen || !ENGINE_set_name(e, engine_capi_name) 5421f13597dSJung-uk Kim || !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) 543db522d3aSSimon L. B. Nielsen || !ENGINE_set_init_function(e, capi_init) 544db522d3aSSimon L. B. Nielsen || !ENGINE_set_finish_function(e, capi_finish) 545db522d3aSSimon L. B. Nielsen || !ENGINE_set_destroy_function(e, capi_destroy) 546*e71b7053SJung-uk Kim || !ENGINE_set_RSA(e, capi_rsa_method) 547*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 548*e71b7053SJung-uk Kim || !ENGINE_set_DSA(e, capi_dsa_method) 549*e71b7053SJung-uk Kim # endif 550db522d3aSSimon L. B. Nielsen || !ENGINE_set_load_privkey_function(e, capi_load_privkey) 551db522d3aSSimon L. B. Nielsen || !ENGINE_set_load_ssl_client_cert_function(e, 552db522d3aSSimon L. B. Nielsen capi_load_ssl_client_cert) 553db522d3aSSimon L. B. Nielsen || !ENGINE_set_cmd_defns(e, capi_cmd_defns) 554db522d3aSSimon L. B. Nielsen || !ENGINE_set_ctrl_function(e, capi_ctrl)) 555*e71b7053SJung-uk Kim goto memerr; 556db522d3aSSimon L. B. Nielsen ERR_load_CAPI_strings(); 557db522d3aSSimon L. B. Nielsen 558db522d3aSSimon L. B. Nielsen return 1; 559*e71b7053SJung-uk Kim memerr: 560*e71b7053SJung-uk Kim RSA_meth_free(capi_rsa_method); 561*e71b7053SJung-uk Kim capi_rsa_method = NULL; 562*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 563*e71b7053SJung-uk Kim DSA_meth_free(capi_dsa_method); 564*e71b7053SJung-uk Kim capi_dsa_method = NULL; 565*e71b7053SJung-uk Kim # endif 566*e71b7053SJung-uk Kim return 0; 567db522d3aSSimon L. B. Nielsen } 568db522d3aSSimon L. B. Nielsen 569db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_DYNAMIC_ENGINE 570db522d3aSSimon L. B. Nielsen static int bind_helper(ENGINE *e, const char *id) 571db522d3aSSimon L. B. Nielsen { 572db522d3aSSimon L. B. Nielsen if (id && (strcmp(id, engine_capi_id) != 0)) 573db522d3aSSimon L. B. Nielsen return 0; 574db522d3aSSimon L. B. Nielsen if (!bind_capi(e)) 575db522d3aSSimon L. B. Nielsen return 0; 576db522d3aSSimon L. B. Nielsen return 1; 577db522d3aSSimon L. B. Nielsen } 5786f9291ceSJung-uk Kim 579db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN() 580db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) 581db522d3aSSimon L. B. Nielsen # else 582db522d3aSSimon L. B. Nielsen static ENGINE *engine_capi(void) 583db522d3aSSimon L. B. Nielsen { 584db522d3aSSimon L. B. Nielsen ENGINE *ret = ENGINE_new(); 585*e71b7053SJung-uk Kim if (ret == NULL) 586db522d3aSSimon L. B. Nielsen return NULL; 5876f9291ceSJung-uk Kim if (!bind_capi(ret)) { 588db522d3aSSimon L. B. Nielsen ENGINE_free(ret); 589db522d3aSSimon L. B. Nielsen return NULL; 590db522d3aSSimon L. B. Nielsen } 591db522d3aSSimon L. B. Nielsen return ret; 592db522d3aSSimon L. B. Nielsen } 593db522d3aSSimon L. B. Nielsen 594*e71b7053SJung-uk Kim void engine_load_capi_int(void) 595db522d3aSSimon L. B. Nielsen { 596db522d3aSSimon L. B. Nielsen /* Copied from eng_[openssl|dyn].c */ 597db522d3aSSimon L. B. Nielsen ENGINE *toadd = engine_capi(); 5986f9291ceSJung-uk Kim if (!toadd) 5996f9291ceSJung-uk Kim return; 600db522d3aSSimon L. B. Nielsen ENGINE_add(toadd); 601db522d3aSSimon L. B. Nielsen ENGINE_free(toadd); 602db522d3aSSimon L. B. Nielsen ERR_clear_error(); 603db522d3aSSimon L. B. Nielsen } 604db522d3aSSimon L. B. Nielsen # endif 605db522d3aSSimon L. B. Nielsen 606db522d3aSSimon L. B. Nielsen static int lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen) 607db522d3aSSimon L. B. Nielsen { 608db522d3aSSimon L. B. Nielsen int i; 6096f9291ceSJung-uk Kim /* 6106f9291ceSJung-uk Kim * Reverse buffer in place: since this is a keyblob structure that will 6116f9291ceSJung-uk Kim * be freed up after conversion anyway it doesn't matter if we change 6126f9291ceSJung-uk Kim * it. 613db522d3aSSimon L. B. Nielsen */ 6146f9291ceSJung-uk Kim for (i = 0; i < binlen / 2; i++) { 615db522d3aSSimon L. B. Nielsen unsigned char c; 616db522d3aSSimon L. B. Nielsen c = bin[i]; 617db522d3aSSimon L. B. Nielsen bin[i] = bin[binlen - i - 1]; 618db522d3aSSimon L. B. Nielsen bin[binlen - i - 1] = c; 619db522d3aSSimon L. B. Nielsen } 620db522d3aSSimon L. B. Nielsen 621db522d3aSSimon L. B. Nielsen if (!BN_bin2bn(bin, binlen, bn)) 622db522d3aSSimon L. B. Nielsen return 0; 623db522d3aSSimon L. B. Nielsen return 1; 624db522d3aSSimon L. B. Nielsen } 625db522d3aSSimon L. B. Nielsen 626db522d3aSSimon L. B. Nielsen /* Given a CAPI_KEY get an EVP_PKEY structure */ 627db522d3aSSimon L. B. Nielsen 628db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key) 629db522d3aSSimon L. B. Nielsen { 630db522d3aSSimon L. B. Nielsen unsigned char *pubkey = NULL; 631db522d3aSSimon L. B. Nielsen DWORD len; 632db522d3aSSimon L. B. Nielsen BLOBHEADER *bh; 633db522d3aSSimon L. B. Nielsen RSA *rkey = NULL; 634db522d3aSSimon L. B. Nielsen DSA *dkey = NULL; 635db522d3aSSimon L. B. Nielsen EVP_PKEY *ret = NULL; 6366f9291ceSJung-uk Kim if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) { 637db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR); 638db522d3aSSimon L. B. Nielsen capi_addlasterror(); 639db522d3aSSimon L. B. Nielsen return NULL; 640db522d3aSSimon L. B. Nielsen } 641db522d3aSSimon L. B. Nielsen 642db522d3aSSimon L. B. Nielsen pubkey = OPENSSL_malloc(len); 643db522d3aSSimon L. B. Nielsen 644*e71b7053SJung-uk Kim if (pubkey == NULL) 645db522d3aSSimon L. B. Nielsen goto memerr; 646db522d3aSSimon L. B. Nielsen 6476f9291ceSJung-uk Kim if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) { 648db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR); 649db522d3aSSimon L. B. Nielsen capi_addlasterror(); 650db522d3aSSimon L. B. Nielsen goto err; 651db522d3aSSimon L. B. Nielsen } 652db522d3aSSimon L. B. Nielsen 653db522d3aSSimon L. B. Nielsen bh = (BLOBHEADER *) pubkey; 6546f9291ceSJung-uk Kim if (bh->bType != PUBLICKEYBLOB) { 655db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB); 656db522d3aSSimon L. B. Nielsen goto err; 657db522d3aSSimon L. B. Nielsen } 6586f9291ceSJung-uk Kim if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) { 659db522d3aSSimon L. B. Nielsen RSAPUBKEY *rp; 660db522d3aSSimon L. B. Nielsen DWORD rsa_modlen; 661*e71b7053SJung-uk Kim BIGNUM *e = NULL, *n = NULL; 662db522d3aSSimon L. B. Nielsen unsigned char *rsa_modulus; 663db522d3aSSimon L. B. Nielsen rp = (RSAPUBKEY *) (bh + 1); 6646f9291ceSJung-uk Kim if (rp->magic != 0x31415352) { 665db522d3aSSimon L. B. Nielsen char magstr[10]; 666db522d3aSSimon L. B. Nielsen BIO_snprintf(magstr, 10, "%lx", rp->magic); 6676f9291ceSJung-uk Kim CAPIerr(CAPI_F_CAPI_GET_PKEY, 6686f9291ceSJung-uk Kim CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); 669db522d3aSSimon L. B. Nielsen ERR_add_error_data(2, "magic=0x", magstr); 670db522d3aSSimon L. B. Nielsen goto err; 671db522d3aSSimon L. B. Nielsen } 672db522d3aSSimon L. B. Nielsen rsa_modulus = (unsigned char *)(rp + 1); 673db522d3aSSimon L. B. Nielsen rkey = RSA_new_method(eng); 674db522d3aSSimon L. B. Nielsen if (!rkey) 675db522d3aSSimon L. B. Nielsen goto memerr; 676db522d3aSSimon L. B. Nielsen 677*e71b7053SJung-uk Kim e = BN_new(); 678*e71b7053SJung-uk Kim n = BN_new(); 679db522d3aSSimon L. B. Nielsen 680*e71b7053SJung-uk Kim if (e == NULL || n == NULL) { 681*e71b7053SJung-uk Kim BN_free(e); 682*e71b7053SJung-uk Kim BN_free(n); 683db522d3aSSimon L. B. Nielsen goto memerr; 684*e71b7053SJung-uk Kim } 685db522d3aSSimon L. B. Nielsen 686*e71b7053SJung-uk Kim RSA_set0_key(rkey, n, e, NULL); 687*e71b7053SJung-uk Kim 688*e71b7053SJung-uk Kim if (!BN_set_word(e, rp->pubexp)) 689db522d3aSSimon L. B. Nielsen goto memerr; 690db522d3aSSimon L. B. Nielsen 691db522d3aSSimon L. B. Nielsen rsa_modlen = rp->bitlen / 8; 692*e71b7053SJung-uk Kim if (!lend_tobn(n, rsa_modulus, rsa_modlen)) 693db522d3aSSimon L. B. Nielsen goto memerr; 694db522d3aSSimon L. B. Nielsen 695db522d3aSSimon L. B. Nielsen RSA_set_ex_data(rkey, rsa_capi_idx, key); 696db522d3aSSimon L. B. Nielsen 697*e71b7053SJung-uk Kim if ((ret = EVP_PKEY_new()) == NULL) 698db522d3aSSimon L. B. Nielsen goto memerr; 699db522d3aSSimon L. B. Nielsen 700db522d3aSSimon L. B. Nielsen EVP_PKEY_assign_RSA(ret, rkey); 701db522d3aSSimon L. B. Nielsen rkey = NULL; 702db522d3aSSimon L. B. Nielsen 703*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 7046f9291ceSJung-uk Kim } else if (bh->aiKeyAlg == CALG_DSS_SIGN) { 705db522d3aSSimon L. B. Nielsen DSSPUBKEY *dp; 706db522d3aSSimon L. B. Nielsen DWORD dsa_plen; 707db522d3aSSimon L. B. Nielsen unsigned char *btmp; 708*e71b7053SJung-uk Kim BIGNUM *p, *q, *g, *pub_key; 709db522d3aSSimon L. B. Nielsen dp = (DSSPUBKEY *) (bh + 1); 7106f9291ceSJung-uk Kim if (dp->magic != 0x31535344) { 711db522d3aSSimon L. B. Nielsen char magstr[10]; 712db522d3aSSimon L. B. Nielsen BIO_snprintf(magstr, 10, "%lx", dp->magic); 7136f9291ceSJung-uk Kim CAPIerr(CAPI_F_CAPI_GET_PKEY, 7146f9291ceSJung-uk Kim CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); 715db522d3aSSimon L. B. Nielsen ERR_add_error_data(2, "magic=0x", magstr); 716db522d3aSSimon L. B. Nielsen goto err; 717db522d3aSSimon L. B. Nielsen } 718db522d3aSSimon L. B. Nielsen dsa_plen = dp->bitlen / 8; 719db522d3aSSimon L. B. Nielsen btmp = (unsigned char *)(dp + 1); 720db522d3aSSimon L. B. Nielsen dkey = DSA_new_method(eng); 721db522d3aSSimon L. B. Nielsen if (!dkey) 722db522d3aSSimon L. B. Nielsen goto memerr; 723*e71b7053SJung-uk Kim p = BN_new(); 724*e71b7053SJung-uk Kim q = BN_new(); 725*e71b7053SJung-uk Kim g = BN_new(); 726*e71b7053SJung-uk Kim pub_key = BN_new(); 727*e71b7053SJung-uk Kim if (p == NULL || q == NULL || g == NULL || pub_key == NULL) { 728*e71b7053SJung-uk Kim BN_free(p); 729*e71b7053SJung-uk Kim BN_free(q); 730*e71b7053SJung-uk Kim BN_free(g); 731*e71b7053SJung-uk Kim BN_free(pub_key); 732db522d3aSSimon L. B. Nielsen goto memerr; 733*e71b7053SJung-uk Kim } 734*e71b7053SJung-uk Kim DSA_set0_pqg(dkey, p, q, g); 735*e71b7053SJung-uk Kim DSA_set0_key(dkey, pub_key, NULL); 736*e71b7053SJung-uk Kim if (!lend_tobn(p, btmp, dsa_plen)) 737db522d3aSSimon L. B. Nielsen goto memerr; 738db522d3aSSimon L. B. Nielsen btmp += dsa_plen; 739*e71b7053SJung-uk Kim if (!lend_tobn(q, btmp, 20)) 740db522d3aSSimon L. B. Nielsen goto memerr; 741db522d3aSSimon L. B. Nielsen btmp += 20; 742*e71b7053SJung-uk Kim if (!lend_tobn(g, btmp, dsa_plen)) 743db522d3aSSimon L. B. Nielsen goto memerr; 744db522d3aSSimon L. B. Nielsen btmp += dsa_plen; 745*e71b7053SJung-uk Kim if (!lend_tobn(pub_key, btmp, dsa_plen)) 746db522d3aSSimon L. B. Nielsen goto memerr; 747db522d3aSSimon L. B. Nielsen btmp += dsa_plen; 748db522d3aSSimon L. B. Nielsen 749db522d3aSSimon L. B. Nielsen DSA_set_ex_data(dkey, dsa_capi_idx, key); 750db522d3aSSimon L. B. Nielsen 751*e71b7053SJung-uk Kim if ((ret = EVP_PKEY_new()) == NULL) 752db522d3aSSimon L. B. Nielsen goto memerr; 753db522d3aSSimon L. B. Nielsen 754db522d3aSSimon L. B. Nielsen EVP_PKEY_assign_DSA(ret, dkey); 755db522d3aSSimon L. B. Nielsen dkey = NULL; 756*e71b7053SJung-uk Kim # endif 7576f9291ceSJung-uk Kim } else { 758db522d3aSSimon L. B. Nielsen char algstr[10]; 759*e71b7053SJung-uk Kim BIO_snprintf(algstr, 10, "%ux", bh->aiKeyAlg); 7606f9291ceSJung-uk Kim CAPIerr(CAPI_F_CAPI_GET_PKEY, 7616f9291ceSJung-uk Kim CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM); 762db522d3aSSimon L. B. Nielsen ERR_add_error_data(2, "aiKeyAlg=0x", algstr); 763db522d3aSSimon L. B. Nielsen goto err; 764db522d3aSSimon L. B. Nielsen } 765db522d3aSSimon L. B. Nielsen 766db522d3aSSimon L. B. Nielsen err: 767db522d3aSSimon L. B. Nielsen OPENSSL_free(pubkey); 7686f9291ceSJung-uk Kim if (!ret) { 769db522d3aSSimon L. B. Nielsen RSA_free(rkey); 770*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 771db522d3aSSimon L. B. Nielsen DSA_free(dkey); 772*e71b7053SJung-uk Kim # endif 773db522d3aSSimon L. B. Nielsen } 774db522d3aSSimon L. B. Nielsen 775db522d3aSSimon L. B. Nielsen return ret; 776db522d3aSSimon L. B. Nielsen 777db522d3aSSimon L. B. Nielsen memerr: 778db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE); 779db522d3aSSimon L. B. Nielsen goto err; 780db522d3aSSimon L. B. Nielsen 781db522d3aSSimon L. B. Nielsen } 782db522d3aSSimon L. B. Nielsen 783db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id, 784db522d3aSSimon L. B. Nielsen UI_METHOD *ui_method, void *callback_data) 785db522d3aSSimon L. B. Nielsen { 786db522d3aSSimon L. B. Nielsen CAPI_CTX *ctx; 787db522d3aSSimon L. B. Nielsen CAPI_KEY *key; 788db522d3aSSimon L. B. Nielsen EVP_PKEY *ret; 789db522d3aSSimon L. B. Nielsen ctx = ENGINE_get_ex_data(eng, capi_idx); 790db522d3aSSimon L. B. Nielsen 7916f9291ceSJung-uk Kim if (!ctx) { 792db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT); 793db522d3aSSimon L. B. Nielsen return NULL; 794db522d3aSSimon L. B. Nielsen } 795db522d3aSSimon L. B. Nielsen 796db522d3aSSimon L. B. Nielsen key = capi_find_key(ctx, key_id); 797db522d3aSSimon L. B. Nielsen 798db522d3aSSimon L. B. Nielsen if (!key) 799db522d3aSSimon L. B. Nielsen return NULL; 800db522d3aSSimon L. B. Nielsen 801db522d3aSSimon L. B. Nielsen ret = capi_get_pkey(eng, key); 802db522d3aSSimon L. B. Nielsen 803db522d3aSSimon L. B. Nielsen if (!ret) 804db522d3aSSimon L. B. Nielsen capi_free_key(key); 805db522d3aSSimon L. B. Nielsen return ret; 806db522d3aSSimon L. B. Nielsen 807db522d3aSSimon L. B. Nielsen } 808db522d3aSSimon L. B. Nielsen 809db522d3aSSimon L. B. Nielsen /* CryptoAPI RSA operations */ 810db522d3aSSimon L. B. Nielsen 811db522d3aSSimon L. B. Nielsen int capi_rsa_priv_enc(int flen, const unsigned char *from, 812db522d3aSSimon L. B. Nielsen unsigned char *to, RSA *rsa, int padding) 813db522d3aSSimon L. B. Nielsen { 814db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED); 815db522d3aSSimon L. B. Nielsen return -1; 816db522d3aSSimon L. B. Nielsen } 817db522d3aSSimon L. B. Nielsen 818db522d3aSSimon L. B. Nielsen int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, 819db522d3aSSimon L. B. Nielsen unsigned char *sigret, unsigned int *siglen, const RSA *rsa) 820db522d3aSSimon L. B. Nielsen { 821db522d3aSSimon L. B. Nielsen ALG_ID alg; 822db522d3aSSimon L. B. Nielsen HCRYPTHASH hash; 823db522d3aSSimon L. B. Nielsen DWORD slen; 824db522d3aSSimon L. B. Nielsen unsigned int i; 825db522d3aSSimon L. B. Nielsen int ret = -1; 826db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_key; 827db522d3aSSimon L. B. Nielsen CAPI_CTX *ctx; 828db522d3aSSimon L. B. Nielsen 829*e71b7053SJung-uk Kim ctx = ENGINE_get_ex_data(RSA_get0_engine(rsa), capi_idx); 830db522d3aSSimon L. B. Nielsen 831db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Called CAPI_rsa_sign()\n"); 832db522d3aSSimon L. B. Nielsen 833db522d3aSSimon L. B. Nielsen capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); 8346f9291ceSJung-uk Kim if (!capi_key) { 835db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY); 836db522d3aSSimon L. B. Nielsen return -1; 837db522d3aSSimon L. B. Nielsen } 838db522d3aSSimon L. B. Nielsen /* Convert the signature type to a CryptoAPI algorithm ID */ 8396f9291ceSJung-uk Kim switch (dtype) { 8404c6a0400SJung-uk Kim case NID_sha256: 8414c6a0400SJung-uk Kim alg = CALG_SHA_256; 8424c6a0400SJung-uk Kim break; 8434c6a0400SJung-uk Kim 8444c6a0400SJung-uk Kim case NID_sha384: 8454c6a0400SJung-uk Kim alg = CALG_SHA_384; 8464c6a0400SJung-uk Kim break; 8474c6a0400SJung-uk Kim 8484c6a0400SJung-uk Kim case NID_sha512: 8494c6a0400SJung-uk Kim alg = CALG_SHA_512; 8504c6a0400SJung-uk Kim break; 8514c6a0400SJung-uk Kim 852db522d3aSSimon L. B. Nielsen case NID_sha1: 853db522d3aSSimon L. B. Nielsen alg = CALG_SHA1; 854db522d3aSSimon L. B. Nielsen break; 855db522d3aSSimon L. B. Nielsen 856db522d3aSSimon L. B. Nielsen case NID_md5: 857db522d3aSSimon L. B. Nielsen alg = CALG_MD5; 858db522d3aSSimon L. B. Nielsen break; 859db522d3aSSimon L. B. Nielsen 860db522d3aSSimon L. B. Nielsen case NID_md5_sha1: 861db522d3aSSimon L. B. Nielsen alg = CALG_SSL3_SHAMD5; 862db522d3aSSimon L. B. Nielsen break; 863db522d3aSSimon L. B. Nielsen default: 864db522d3aSSimon L. B. Nielsen { 865db522d3aSSimon L. B. Nielsen char algstr[10]; 866*e71b7053SJung-uk Kim BIO_snprintf(algstr, 10, "%x", dtype); 867db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID); 868db522d3aSSimon L. B. Nielsen ERR_add_error_data(2, "NID=0x", algstr); 869db522d3aSSimon L. B. Nielsen return -1; 870db522d3aSSimon L. B. Nielsen } 871db522d3aSSimon L. B. Nielsen } 872db522d3aSSimon L. B. Nielsen 873db522d3aSSimon L. B. Nielsen /* Create the hash object */ 8746f9291ceSJung-uk Kim if (!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) { 875db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); 876db522d3aSSimon L. B. Nielsen capi_addlasterror(); 877db522d3aSSimon L. B. Nielsen return -1; 878db522d3aSSimon L. B. Nielsen } 879db522d3aSSimon L. B. Nielsen /* Set the hash value to the value passed */ 880db522d3aSSimon L. B. Nielsen 8816f9291ceSJung-uk Kim if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) { 882db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE); 883db522d3aSSimon L. B. Nielsen capi_addlasterror(); 884db522d3aSSimon L. B. Nielsen goto err; 885db522d3aSSimon L. B. Nielsen } 886db522d3aSSimon L. B. Nielsen 887db522d3aSSimon L. B. Nielsen /* Finally sign it */ 888db522d3aSSimon L. B. Nielsen slen = RSA_size(rsa); 8897bded2dbSJung-uk Kim if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) { 890db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH); 891db522d3aSSimon L. B. Nielsen capi_addlasterror(); 892db522d3aSSimon L. B. Nielsen goto err; 8936f9291ceSJung-uk Kim } else { 894db522d3aSSimon L. B. Nielsen ret = 1; 895db522d3aSSimon L. B. Nielsen /* Inplace byte reversal of signature */ 8966f9291ceSJung-uk Kim for (i = 0; i < slen / 2; i++) { 897db522d3aSSimon L. B. Nielsen unsigned char c; 898db522d3aSSimon L. B. Nielsen c = sigret[i]; 899db522d3aSSimon L. B. Nielsen sigret[i] = sigret[slen - i - 1]; 900db522d3aSSimon L. B. Nielsen sigret[slen - i - 1] = c; 901db522d3aSSimon L. B. Nielsen } 902db522d3aSSimon L. B. Nielsen *siglen = slen; 903db522d3aSSimon L. B. Nielsen } 904db522d3aSSimon L. B. Nielsen 905db522d3aSSimon L. B. Nielsen /* Now cleanup */ 906db522d3aSSimon L. B. Nielsen 907db522d3aSSimon L. B. Nielsen err: 908db522d3aSSimon L. B. Nielsen CryptDestroyHash(hash); 909db522d3aSSimon L. B. Nielsen 910db522d3aSSimon L. B. Nielsen return ret; 911db522d3aSSimon L. B. Nielsen } 912db522d3aSSimon L. B. Nielsen 913db522d3aSSimon L. B. Nielsen int capi_rsa_priv_dec(int flen, const unsigned char *from, 914db522d3aSSimon L. B. Nielsen unsigned char *to, RSA *rsa, int padding) 915db522d3aSSimon L. B. Nielsen { 916db522d3aSSimon L. B. Nielsen int i; 917db522d3aSSimon L. B. Nielsen unsigned char *tmpbuf; 918db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_key; 919db522d3aSSimon L. B. Nielsen CAPI_CTX *ctx; 920*e71b7053SJung-uk Kim DWORD flags = 0; 921*e71b7053SJung-uk Kim DWORD dlen; 922*e71b7053SJung-uk Kim 923*e71b7053SJung-uk Kim if (flen <= 0) 924*e71b7053SJung-uk Kim return flen; 925*e71b7053SJung-uk Kim 926*e71b7053SJung-uk Kim ctx = ENGINE_get_ex_data(RSA_get0_engine(rsa), capi_idx); 927db522d3aSSimon L. B. Nielsen 928db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n"); 929db522d3aSSimon L. B. Nielsen 930db522d3aSSimon L. B. Nielsen capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); 9316f9291ceSJung-uk Kim if (!capi_key) { 932db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY); 933db522d3aSSimon L. B. Nielsen return -1; 934db522d3aSSimon L. B. Nielsen } 935db522d3aSSimon L. B. Nielsen 936*e71b7053SJung-uk Kim switch (padding) { 937*e71b7053SJung-uk Kim case RSA_PKCS1_PADDING: 938*e71b7053SJung-uk Kim /* Nothing to do */ 939*e71b7053SJung-uk Kim break; 940*e71b7053SJung-uk Kim #ifdef CRYPT_DECRYPT_RSA_NO_PADDING_CHECK 941*e71b7053SJung-uk Kim case RSA_NO_PADDING: 942*e71b7053SJung-uk Kim flags = CRYPT_DECRYPT_RSA_NO_PADDING_CHECK; 943*e71b7053SJung-uk Kim break; 944*e71b7053SJung-uk Kim #endif 945*e71b7053SJung-uk Kim default: 946*e71b7053SJung-uk Kim { 947db522d3aSSimon L. B. Nielsen char errstr[10]; 948db522d3aSSimon L. B. Nielsen BIO_snprintf(errstr, 10, "%d", padding); 949db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING); 950db522d3aSSimon L. B. Nielsen ERR_add_error_data(2, "padding=", errstr); 951db522d3aSSimon L. B. Nielsen return -1; 952db522d3aSSimon L. B. Nielsen } 953*e71b7053SJung-uk Kim } 954db522d3aSSimon L. B. Nielsen 955db522d3aSSimon L. B. Nielsen /* Create temp reverse order version of input */ 956*e71b7053SJung-uk Kim if ((tmpbuf = OPENSSL_malloc(flen)) == NULL) { 957db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE); 958db522d3aSSimon L. B. Nielsen return -1; 959db522d3aSSimon L. B. Nielsen } 960db522d3aSSimon L. B. Nielsen for (i = 0; i < flen; i++) 961db522d3aSSimon L. B. Nielsen tmpbuf[flen - i - 1] = from[i]; 962db522d3aSSimon L. B. Nielsen 963db522d3aSSimon L. B. Nielsen /* Finally decrypt it */ 964*e71b7053SJung-uk Kim dlen = flen; 965*e71b7053SJung-uk Kim if (!CryptDecrypt(capi_key->key, 0, TRUE, flags, tmpbuf, &dlen)) { 966db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR); 967db522d3aSSimon L. B. Nielsen capi_addlasterror(); 968*e71b7053SJung-uk Kim OPENSSL_cleanse(tmpbuf, dlen); 969db522d3aSSimon L. B. Nielsen OPENSSL_free(tmpbuf); 970db522d3aSSimon L. B. Nielsen return -1; 971*e71b7053SJung-uk Kim } else { 972*e71b7053SJung-uk Kim memcpy(to, tmpbuf, (flen = (int)dlen)); 973*e71b7053SJung-uk Kim } 974*e71b7053SJung-uk Kim OPENSSL_cleanse(tmpbuf, flen); 975db522d3aSSimon L. B. Nielsen OPENSSL_free(tmpbuf); 976db522d3aSSimon L. B. Nielsen 977db522d3aSSimon L. B. Nielsen return flen; 978db522d3aSSimon L. B. Nielsen } 979db522d3aSSimon L. B. Nielsen 980db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa) 981db522d3aSSimon L. B. Nielsen { 982db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_key; 983db522d3aSSimon L. B. Nielsen capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); 984db522d3aSSimon L. B. Nielsen capi_free_key(capi_key); 985db522d3aSSimon L. B. Nielsen RSA_set_ex_data(rsa, rsa_capi_idx, 0); 986db522d3aSSimon L. B. Nielsen return 1; 987db522d3aSSimon L. B. Nielsen } 988db522d3aSSimon L. B. Nielsen 989*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA 990db522d3aSSimon L. B. Nielsen /* CryptoAPI DSA operations */ 991db522d3aSSimon L. B. Nielsen 992db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, 993db522d3aSSimon L. B. Nielsen DSA *dsa) 994db522d3aSSimon L. B. Nielsen { 995db522d3aSSimon L. B. Nielsen HCRYPTHASH hash; 996db522d3aSSimon L. B. Nielsen DWORD slen; 997db522d3aSSimon L. B. Nielsen DSA_SIG *ret = NULL; 998db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_key; 999db522d3aSSimon L. B. Nielsen CAPI_CTX *ctx; 1000db522d3aSSimon L. B. Nielsen unsigned char csigbuf[40]; 1001db522d3aSSimon L. B. Nielsen 1002*e71b7053SJung-uk Kim ctx = ENGINE_get_ex_data(DSA_get0_engine(dsa), capi_idx); 1003db522d3aSSimon L. B. Nielsen 1004db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n"); 1005db522d3aSSimon L. B. Nielsen 1006db522d3aSSimon L. B. Nielsen capi_key = DSA_get_ex_data(dsa, dsa_capi_idx); 1007db522d3aSSimon L. B. Nielsen 10086f9291ceSJung-uk Kim if (!capi_key) { 1009db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY); 1010db522d3aSSimon L. B. Nielsen return NULL; 1011db522d3aSSimon L. B. Nielsen } 1012db522d3aSSimon L. B. Nielsen 10136f9291ceSJung-uk Kim if (dlen != 20) { 1014db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH); 1015db522d3aSSimon L. B. Nielsen return NULL; 1016db522d3aSSimon L. B. Nielsen } 1017db522d3aSSimon L. B. Nielsen 1018db522d3aSSimon L. B. Nielsen /* Create the hash object */ 10196f9291ceSJung-uk Kim if (!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash)) { 1020db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); 1021db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1022db522d3aSSimon L. B. Nielsen return NULL; 1023db522d3aSSimon L. B. Nielsen } 1024db522d3aSSimon L. B. Nielsen 1025db522d3aSSimon L. B. Nielsen /* Set the hash value to the value passed */ 10266f9291ceSJung-uk Kim if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0)) { 1027db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE); 1028db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1029db522d3aSSimon L. B. Nielsen goto err; 1030db522d3aSSimon L. B. Nielsen } 1031db522d3aSSimon L. B. Nielsen 1032db522d3aSSimon L. B. Nielsen /* Finally sign it */ 1033db522d3aSSimon L. B. Nielsen slen = sizeof(csigbuf); 10347bded2dbSJung-uk Kim if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) { 1035db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH); 1036db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1037db522d3aSSimon L. B. Nielsen goto err; 10386f9291ceSJung-uk Kim } else { 1039*e71b7053SJung-uk Kim BIGNUM *r = BN_new(), *s = BN_new(); 1040*e71b7053SJung-uk Kim 1041*e71b7053SJung-uk Kim if (r == NULL || s == NULL 1042*e71b7053SJung-uk Kim || !lend_tobn(r, csigbuf, 20) 1043*e71b7053SJung-uk Kim || !lend_tobn(s, csigbuf + 20, 20) 1044*e71b7053SJung-uk Kim || (ret = DSA_SIG_new()) == NULL) { 1045*e71b7053SJung-uk Kim BN_free(r); /* BN_free checks for BIGNUM * being NULL */ 1046*e71b7053SJung-uk Kim BN_free(s); 1047db522d3aSSimon L. B. Nielsen goto err; 1048db522d3aSSimon L. B. Nielsen } 1049*e71b7053SJung-uk Kim DSA_SIG_set0(ret, r, s); 1050db522d3aSSimon L. B. Nielsen } 1051db522d3aSSimon L. B. Nielsen 1052db522d3aSSimon L. B. Nielsen /* Now cleanup */ 1053db522d3aSSimon L. B. Nielsen 1054db522d3aSSimon L. B. Nielsen err: 1055db522d3aSSimon L. B. Nielsen OPENSSL_cleanse(csigbuf, 40); 1056db522d3aSSimon L. B. Nielsen CryptDestroyHash(hash); 1057db522d3aSSimon L. B. Nielsen return ret; 1058db522d3aSSimon L. B. Nielsen } 1059db522d3aSSimon L. B. Nielsen 1060db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa) 1061db522d3aSSimon L. B. Nielsen { 1062db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_key; 1063db522d3aSSimon L. B. Nielsen capi_key = DSA_get_ex_data(dsa, dsa_capi_idx); 1064db522d3aSSimon L. B. Nielsen capi_free_key(capi_key); 1065db522d3aSSimon L. B. Nielsen DSA_set_ex_data(dsa, dsa_capi_idx, 0); 1066db522d3aSSimon L. B. Nielsen return 1; 1067db522d3aSSimon L. B. Nielsen } 1068*e71b7053SJung-uk Kim # endif 1069db522d3aSSimon L. B. Nielsen 10706f9291ceSJung-uk Kim static void capi_vtrace(CAPI_CTX *ctx, int level, char *format, 10716f9291ceSJung-uk Kim va_list argptr) 1072db522d3aSSimon L. B. Nielsen { 1073db522d3aSSimon L. B. Nielsen BIO *out; 1074db522d3aSSimon L. B. Nielsen 1075db522d3aSSimon L. B. Nielsen if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file)) 1076db522d3aSSimon L. B. Nielsen return; 1077db522d3aSSimon L. B. Nielsen out = BIO_new_file(ctx->debug_file, "a+"); 1078*e71b7053SJung-uk Kim if (out == NULL) { 1079*e71b7053SJung-uk Kim CAPIerr(CAPI_F_CAPI_VTRACE, CAPI_R_FILE_OPEN_ERROR); 1080*e71b7053SJung-uk Kim return; 1081*e71b7053SJung-uk Kim } 1082db522d3aSSimon L. B. Nielsen BIO_vprintf(out, format, argptr); 1083db522d3aSSimon L. B. Nielsen BIO_free(out); 1084db522d3aSSimon L. B. Nielsen } 1085db522d3aSSimon L. B. Nielsen 1086db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX *ctx, char *format, ...) 1087db522d3aSSimon L. B. Nielsen { 1088db522d3aSSimon L. B. Nielsen va_list args; 1089db522d3aSSimon L. B. Nielsen va_start(args, format); 1090db522d3aSSimon L. B. Nielsen capi_vtrace(ctx, CAPI_DBG_TRACE, format, args); 1091db522d3aSSimon L. B. Nielsen va_end(args); 1092db522d3aSSimon L. B. Nielsen } 1093db522d3aSSimon L. B. Nielsen 1094db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void) 1095db522d3aSSimon L. B. Nielsen { 1096db522d3aSSimon L. B. Nielsen capi_adderror(GetLastError()); 1097db522d3aSSimon L. B. Nielsen } 1098db522d3aSSimon L. B. Nielsen 1099db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err) 1100db522d3aSSimon L. B. Nielsen { 1101db522d3aSSimon L. B. Nielsen char errstr[10]; 1102db522d3aSSimon L. B. Nielsen BIO_snprintf(errstr, 10, "%lX", err); 1103db522d3aSSimon L. B. Nielsen ERR_add_error_data(2, "Error code= 0x", errstr); 1104db522d3aSSimon L. B. Nielsen } 1105db522d3aSSimon L. B. Nielsen 11067bded2dbSJung-uk Kim static char *wide_to_asc(LPCWSTR wstr) 1107db522d3aSSimon L. B. Nielsen { 1108db522d3aSSimon L. B. Nielsen char *str; 11096a599222SSimon L. B. Nielsen int len_0, sz; 11106a599222SSimon L. B. Nielsen 1111db522d3aSSimon L. B. Nielsen if (!wstr) 1112db522d3aSSimon L. B. Nielsen return NULL; 11136a599222SSimon L. B. Nielsen len_0 = (int)wcslen(wstr) + 1; /* WideCharToMultiByte expects int */ 11146a599222SSimon L. B. Nielsen sz = WideCharToMultiByte(CP_ACP, 0, wstr, len_0, NULL, 0, NULL, NULL); 11156f9291ceSJung-uk Kim if (!sz) { 11166a599222SSimon L. B. Nielsen CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); 11176a599222SSimon L. B. Nielsen return NULL; 11186a599222SSimon L. B. Nielsen } 11196a599222SSimon L. B. Nielsen str = OPENSSL_malloc(sz); 1120*e71b7053SJung-uk Kim if (str == NULL) { 1121db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE); 1122db522d3aSSimon L. B. Nielsen return NULL; 1123db522d3aSSimon L. B. Nielsen } 11246f9291ceSJung-uk Kim if (!WideCharToMultiByte(CP_ACP, 0, wstr, len_0, str, sz, NULL, NULL)) { 11256a599222SSimon L. B. Nielsen OPENSSL_free(str); 11266a599222SSimon L. B. Nielsen CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); 11276a599222SSimon L. B. Nielsen return NULL; 11286a599222SSimon L. B. Nielsen } 1129db522d3aSSimon L. B. Nielsen return str; 1130db522d3aSSimon L. B. Nielsen } 1131db522d3aSSimon L. B. Nielsen 11326f9291ceSJung-uk Kim static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, 11336f9291ceSJung-uk Kim DWORD idx) 1134db522d3aSSimon L. B. Nielsen { 1135db522d3aSSimon L. B. Nielsen DWORD len, err; 11367bded2dbSJung-uk Kim LPTSTR name; 1137db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx); 11387bded2dbSJung-uk Kim if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len)) { 1139db522d3aSSimon L. B. Nielsen err = GetLastError(); 1140db522d3aSSimon L. B. Nielsen if (err == ERROR_NO_MORE_ITEMS) 1141db522d3aSSimon L. B. Nielsen return 2; 1142db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR); 1143db522d3aSSimon L. B. Nielsen capi_adderror(err); 1144db522d3aSSimon L. B. Nielsen return 0; 1145db522d3aSSimon L. B. Nielsen } 1146db522d3aSSimon L. B. Nielsen name = OPENSSL_malloc(len); 1147aeb5019cSJung-uk Kim if (name == NULL) { 1148aeb5019cSJung-uk Kim CAPIerr(CAPI_F_CAPI_GET_PROVNAME, ERR_R_MALLOC_FAILURE); 1149aeb5019cSJung-uk Kim return 0; 1150aeb5019cSJung-uk Kim } 11517bded2dbSJung-uk Kim if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) { 1152db522d3aSSimon L. B. Nielsen err = GetLastError(); 1153*e71b7053SJung-uk Kim OPENSSL_free(name); 1154db522d3aSSimon L. B. Nielsen if (err == ERROR_NO_MORE_ITEMS) 1155db522d3aSSimon L. B. Nielsen return 2; 1156db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR); 1157db522d3aSSimon L. B. Nielsen capi_adderror(err); 1158db522d3aSSimon L. B. Nielsen return 0; 1159db522d3aSSimon L. B. Nielsen } 1160*e71b7053SJung-uk Kim if (sizeof(TCHAR) != sizeof(char)) { 11617bded2dbSJung-uk Kim *pname = wide_to_asc((WCHAR *)name); 1162*e71b7053SJung-uk Kim OPENSSL_free(name); 1163*e71b7053SJung-uk Kim if (*pname == NULL) 1164*e71b7053SJung-uk Kim return 0; 1165*e71b7053SJung-uk Kim } else { 11667bded2dbSJung-uk Kim *pname = (char *)name; 1167*e71b7053SJung-uk Kim } 11687bded2dbSJung-uk Kim CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", *pname, 11696f9291ceSJung-uk Kim *ptype); 1170db522d3aSSimon L. B. Nielsen 1171db522d3aSSimon L. B. Nielsen return 1; 1172db522d3aSSimon L. B. Nielsen } 1173db522d3aSSimon L. B. Nielsen 1174db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX *ctx, BIO *out) 1175db522d3aSSimon L. B. Nielsen { 1176db522d3aSSimon L. B. Nielsen DWORD idx, ptype; 1177db522d3aSSimon L. B. Nielsen int ret; 11786a599222SSimon L. B. Nielsen LPSTR provname = NULL; 1179db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "capi_list_providers\n"); 1180db522d3aSSimon L. B. Nielsen BIO_printf(out, "Available CSPs:\n"); 11816f9291ceSJung-uk Kim for (idx = 0;; idx++) { 1182db522d3aSSimon L. B. Nielsen ret = capi_get_provname(ctx, &provname, &ptype, idx); 1183db522d3aSSimon L. B. Nielsen if (ret == 2) 1184db522d3aSSimon L. B. Nielsen break; 1185db522d3aSSimon L. B. Nielsen if (ret == 0) 1186db522d3aSSimon L. B. Nielsen break; 1187*e71b7053SJung-uk Kim BIO_printf(out, "%lu. %s, type %lu\n", idx, provname, ptype); 1188db522d3aSSimon L. B. Nielsen OPENSSL_free(provname); 1189db522d3aSSimon L. B. Nielsen } 1190db522d3aSSimon L. B. Nielsen return 1; 1191db522d3aSSimon L. B. Nielsen } 1192db522d3aSSimon L. B. Nielsen 1193db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX *ctx, BIO *out) 1194db522d3aSSimon L. B. Nielsen { 1195db522d3aSSimon L. B. Nielsen int ret = 1; 1196db522d3aSSimon L. B. Nielsen HCRYPTPROV hprov; 1197db522d3aSSimon L. B. Nielsen DWORD err, idx, flags, buflen = 0, clen; 1198db522d3aSSimon L. B. Nielsen LPSTR cname; 1199*e71b7053SJung-uk Kim LPWSTR cspname = NULL; 12007bded2dbSJung-uk Kim 12016f9291ceSJung-uk Kim CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, 12026f9291ceSJung-uk Kim ctx->csptype); 1203*e71b7053SJung-uk Kim if (ctx->cspname != NULL) { 1204*e71b7053SJung-uk Kim if ((clen = MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, 1205*e71b7053SJung-uk Kim NULL, 0))) { 12067bded2dbSJung-uk Kim cspname = alloca(clen * sizeof(WCHAR)); 12077bded2dbSJung-uk Kim MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, (WCHAR *)cspname, 12087bded2dbSJung-uk Kim clen); 12097bded2dbSJung-uk Kim } 1210*e71b7053SJung-uk Kim if (cspname == NULL) { 12117bded2dbSJung-uk Kim CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE); 12127bded2dbSJung-uk Kim capi_addlasterror(); 12137bded2dbSJung-uk Kim return 0; 12147bded2dbSJung-uk Kim } 1215*e71b7053SJung-uk Kim } 1216*e71b7053SJung-uk Kim if (!CryptAcquireContextW(&hprov, NULL, cspname, ctx->csptype, 1217*e71b7053SJung-uk Kim CRYPT_VERIFYCONTEXT)) { 12186f9291ceSJung-uk Kim CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, 12196f9291ceSJung-uk Kim CAPI_R_CRYPTACQUIRECONTEXT_ERROR); 1220db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1221db522d3aSSimon L. B. Nielsen return 0; 1222db522d3aSSimon L. B. Nielsen } 1223*e71b7053SJung-uk Kim if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, NULL, &buflen, 1224*e71b7053SJung-uk Kim CRYPT_FIRST)) { 1225db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR); 1226db522d3aSSimon L. B. Nielsen capi_addlasterror(); 122712de4ed2SJung-uk Kim CryptReleaseContext(hprov, 0); 1228db522d3aSSimon L. B. Nielsen return 0; 1229db522d3aSSimon L. B. Nielsen } 1230db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Got max container len %d\n", buflen); 1231db522d3aSSimon L. B. Nielsen if (buflen == 0) 1232db522d3aSSimon L. B. Nielsen buflen = 1024; 1233db522d3aSSimon L. B. Nielsen cname = OPENSSL_malloc(buflen); 1234*e71b7053SJung-uk Kim if (cname == NULL) { 1235db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE); 1236db522d3aSSimon L. B. Nielsen goto err; 1237db522d3aSSimon L. B. Nielsen } 1238db522d3aSSimon L. B. Nielsen 12396f9291ceSJung-uk Kim for (idx = 0;; idx++) { 1240db522d3aSSimon L. B. Nielsen clen = buflen; 1241db522d3aSSimon L. B. Nielsen cname[0] = 0; 1242db522d3aSSimon L. B. Nielsen 1243db522d3aSSimon L. B. Nielsen if (idx == 0) 1244db522d3aSSimon L. B. Nielsen flags = CRYPT_FIRST; 1245db522d3aSSimon L. B. Nielsen else 1246db522d3aSSimon L. B. Nielsen flags = 0; 1247*e71b7053SJung-uk Kim if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, (BYTE *)cname, 1248*e71b7053SJung-uk Kim &clen, flags)) { 1249db522d3aSSimon L. B. Nielsen err = GetLastError(); 1250db522d3aSSimon L. B. Nielsen if (err == ERROR_NO_MORE_ITEMS) 1251db522d3aSSimon L. B. Nielsen goto done; 1252db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR); 1253db522d3aSSimon L. B. Nielsen capi_adderror(err); 1254db522d3aSSimon L. B. Nielsen goto err; 1255db522d3aSSimon L. B. Nielsen } 12566f9291ceSJung-uk Kim CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n", 12576f9291ceSJung-uk Kim cname, clen, idx, flags); 12586f9291ceSJung-uk Kim if (!cname[0] && (clen == buflen)) { 1259db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Enumerate bug: using workaround\n"); 1260db522d3aSSimon L. B. Nielsen goto done; 1261db522d3aSSimon L. B. Nielsen } 1262*e71b7053SJung-uk Kim BIO_printf(out, "%lu. %s\n", idx, cname); 1263db522d3aSSimon L. B. Nielsen } 1264db522d3aSSimon L. B. Nielsen err: 1265db522d3aSSimon L. B. Nielsen 1266db522d3aSSimon L. B. Nielsen ret = 0; 1267db522d3aSSimon L. B. Nielsen 1268db522d3aSSimon L. B. Nielsen done: 1269db522d3aSSimon L. B. Nielsen OPENSSL_free(cname); 1270db522d3aSSimon L. B. Nielsen CryptReleaseContext(hprov, 0); 1271db522d3aSSimon L. B. Nielsen 1272db522d3aSSimon L. B. Nielsen return ret; 1273db522d3aSSimon L. B. Nielsen } 1274db522d3aSSimon L. B. Nielsen 1275*e71b7053SJung-uk Kim static CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX *ctx, 1276*e71b7053SJung-uk Kim PCCERT_CONTEXT cert) 1277db522d3aSSimon L. B. Nielsen { 1278db522d3aSSimon L. B. Nielsen DWORD len; 1279db522d3aSSimon L. B. Nielsen CRYPT_KEY_PROV_INFO *pinfo; 1280db522d3aSSimon L. B. Nielsen 1281*e71b7053SJung-uk Kim if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 1282*e71b7053SJung-uk Kim NULL, &len)) 1283db522d3aSSimon L. B. Nielsen return NULL; 1284db522d3aSSimon L. B. Nielsen pinfo = OPENSSL_malloc(len); 1285*e71b7053SJung-uk Kim if (pinfo == NULL) { 1286db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE); 1287db522d3aSSimon L. B. Nielsen return NULL; 1288db522d3aSSimon L. B. Nielsen } 1289*e71b7053SJung-uk Kim if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 1290*e71b7053SJung-uk Kim pinfo, &len)) { 12916f9291ceSJung-uk Kim CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, 12926f9291ceSJung-uk Kim CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO); 1293db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1294db522d3aSSimon L. B. Nielsen OPENSSL_free(pinfo); 1295db522d3aSSimon L. B. Nielsen return NULL; 1296db522d3aSSimon L. B. Nielsen } 1297db522d3aSSimon L. B. Nielsen return pinfo; 1298db522d3aSSimon L. B. Nielsen } 1299db522d3aSSimon L. B. Nielsen 13006f9291ceSJung-uk Kim static void capi_dump_prov_info(CAPI_CTX *ctx, BIO *out, 13016f9291ceSJung-uk Kim CRYPT_KEY_PROV_INFO *pinfo) 1302db522d3aSSimon L. B. Nielsen { 1303db522d3aSSimon L. B. Nielsen char *provname = NULL, *contname = NULL; 13046f9291ceSJung-uk Kim if (!pinfo) { 1305db522d3aSSimon L. B. Nielsen BIO_printf(out, " No Private Key\n"); 1306db522d3aSSimon L. B. Nielsen return; 1307db522d3aSSimon L. B. Nielsen } 1308db522d3aSSimon L. B. Nielsen provname = wide_to_asc(pinfo->pwszProvName); 1309db522d3aSSimon L. B. Nielsen contname = wide_to_asc(pinfo->pwszContainerName); 1310db522d3aSSimon L. B. Nielsen if (!provname || !contname) 1311db522d3aSSimon L. B. Nielsen goto err; 1312db522d3aSSimon L. B. Nielsen 1313db522d3aSSimon L. B. Nielsen BIO_printf(out, " Private Key Info:\n"); 1314*e71b7053SJung-uk Kim BIO_printf(out, " Provider Name: %s, Provider Type %lu\n", provname, 13156f9291ceSJung-uk Kim pinfo->dwProvType); 1316*e71b7053SJung-uk Kim BIO_printf(out, " Container Name: %s, Key Type %lu\n", contname, 13176f9291ceSJung-uk Kim pinfo->dwKeySpec); 1318db522d3aSSimon L. B. Nielsen err: 1319db522d3aSSimon L. B. Nielsen OPENSSL_free(provname); 1320db522d3aSSimon L. B. Nielsen OPENSSL_free(contname); 1321db522d3aSSimon L. B. Nielsen } 1322db522d3aSSimon L. B. Nielsen 1323*e71b7053SJung-uk Kim static char *capi_cert_get_fname(CAPI_CTX *ctx, PCCERT_CONTEXT cert) 1324db522d3aSSimon L. B. Nielsen { 1325db522d3aSSimon L. B. Nielsen LPWSTR wfname; 1326db522d3aSSimon L. B. Nielsen DWORD dlen; 1327db522d3aSSimon L. B. Nielsen 1328db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "capi_cert_get_fname\n"); 1329*e71b7053SJung-uk Kim if (!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, 1330*e71b7053SJung-uk Kim NULL, &dlen)) 1331db522d3aSSimon L. B. Nielsen return NULL; 1332db522d3aSSimon L. B. Nielsen wfname = OPENSSL_malloc(dlen); 1333*e71b7053SJung-uk Kim if (wfname == NULL) 1334aeb5019cSJung-uk Kim return NULL; 1335*e71b7053SJung-uk Kim if (CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, 1336*e71b7053SJung-uk Kim wfname, &dlen)) { 1337db522d3aSSimon L. B. Nielsen char *fname = wide_to_asc(wfname); 1338db522d3aSSimon L. B. Nielsen OPENSSL_free(wfname); 1339db522d3aSSimon L. B. Nielsen return fname; 1340db522d3aSSimon L. B. Nielsen } 1341db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME); 1342db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1343db522d3aSSimon L. B. Nielsen 1344db522d3aSSimon L. B. Nielsen OPENSSL_free(wfname); 1345db522d3aSSimon L. B. Nielsen return NULL; 1346db522d3aSSimon L. B. Nielsen } 1347db522d3aSSimon L. B. Nielsen 1348*e71b7053SJung-uk Kim static void capi_dump_cert(CAPI_CTX *ctx, BIO *out, PCCERT_CONTEXT cert) 1349db522d3aSSimon L. B. Nielsen { 1350db522d3aSSimon L. B. Nielsen X509 *x; 1351*e71b7053SJung-uk Kim const unsigned char *p; 1352db522d3aSSimon L. B. Nielsen unsigned long flags = ctx->dump_flags; 13536f9291ceSJung-uk Kim if (flags & CAPI_DMP_FNAME) { 1354db522d3aSSimon L. B. Nielsen char *fname; 1355db522d3aSSimon L. B. Nielsen fname = capi_cert_get_fname(ctx, cert); 13566f9291ceSJung-uk Kim if (fname) { 1357db522d3aSSimon L. B. Nielsen BIO_printf(out, " Friendly Name \"%s\"\n", fname); 1358db522d3aSSimon L. B. Nielsen OPENSSL_free(fname); 1359*e71b7053SJung-uk Kim } else { 1360db522d3aSSimon L. B. Nielsen BIO_printf(out, " <No Friendly Name>\n"); 1361db522d3aSSimon L. B. Nielsen } 1362*e71b7053SJung-uk Kim } 1363db522d3aSSimon L. B. Nielsen 1364db522d3aSSimon L. B. Nielsen p = cert->pbCertEncoded; 1365db522d3aSSimon L. B. Nielsen x = d2i_X509(NULL, &p, cert->cbCertEncoded); 1366db522d3aSSimon L. B. Nielsen if (!x) 1367db522d3aSSimon L. B. Nielsen BIO_printf(out, " <Can't parse certificate>\n"); 13686f9291ceSJung-uk Kim if (flags & CAPI_DMP_SUMMARY) { 1369db522d3aSSimon L. B. Nielsen BIO_printf(out, " Subject: "); 1370db522d3aSSimon L. B. Nielsen X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE); 1371db522d3aSSimon L. B. Nielsen BIO_printf(out, "\n Issuer: "); 1372db522d3aSSimon L. B. Nielsen X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE); 1373db522d3aSSimon L. B. Nielsen BIO_printf(out, "\n"); 1374db522d3aSSimon L. B. Nielsen } 1375db522d3aSSimon L. B. Nielsen if (flags & CAPI_DMP_FULL) 1376db522d3aSSimon L. B. Nielsen X509_print_ex(out, x, XN_FLAG_ONELINE, 0); 1377db522d3aSSimon L. B. Nielsen 13786f9291ceSJung-uk Kim if (flags & CAPI_DMP_PKEYINFO) { 1379db522d3aSSimon L. B. Nielsen CRYPT_KEY_PROV_INFO *pinfo; 1380db522d3aSSimon L. B. Nielsen pinfo = capi_get_prov_info(ctx, cert); 1381db522d3aSSimon L. B. Nielsen capi_dump_prov_info(ctx, out, pinfo); 1382db522d3aSSimon L. B. Nielsen OPENSSL_free(pinfo); 1383db522d3aSSimon L. B. Nielsen } 1384db522d3aSSimon L. B. Nielsen 1385db522d3aSSimon L. B. Nielsen if (flags & CAPI_DMP_PEM) 1386db522d3aSSimon L. B. Nielsen PEM_write_bio_X509(out, x); 1387db522d3aSSimon L. B. Nielsen X509_free(x); 1388db522d3aSSimon L. B. Nielsen } 1389db522d3aSSimon L. B. Nielsen 1390*e71b7053SJung-uk Kim static HCERTSTORE capi_open_store(CAPI_CTX *ctx, char *storename) 1391db522d3aSSimon L. B. Nielsen { 1392db522d3aSSimon L. B. Nielsen HCERTSTORE hstore; 1393db522d3aSSimon L. B. Nielsen 1394db522d3aSSimon L. B. Nielsen if (!storename) 1395db522d3aSSimon L. B. Nielsen storename = ctx->storename; 1396db522d3aSSimon L. B. Nielsen if (!storename) 1397db522d3aSSimon L. B. Nielsen storename = "MY"; 1398db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Opening certificate store %s\n", storename); 1399db522d3aSSimon L. B. Nielsen 1400db522d3aSSimon L. B. Nielsen hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, 1401db522d3aSSimon L. B. Nielsen ctx->store_flags, storename); 14026f9291ceSJung-uk Kim if (!hstore) { 1403db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE); 1404db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1405db522d3aSSimon L. B. Nielsen } 1406db522d3aSSimon L. B. Nielsen return hstore; 1407db522d3aSSimon L. B. Nielsen } 1408db522d3aSSimon L. B. Nielsen 1409db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *id) 1410db522d3aSSimon L. B. Nielsen { 1411db522d3aSSimon L. B. Nielsen char *storename; 1412db522d3aSSimon L. B. Nielsen int idx; 1413db522d3aSSimon L. B. Nielsen int ret = 1; 1414db522d3aSSimon L. B. Nielsen HCERTSTORE hstore; 1415db522d3aSSimon L. B. Nielsen PCCERT_CONTEXT cert = NULL; 1416db522d3aSSimon L. B. Nielsen 1417db522d3aSSimon L. B. Nielsen storename = ctx->storename; 1418db522d3aSSimon L. B. Nielsen if (!storename) 1419db522d3aSSimon L. B. Nielsen storename = "MY"; 1420db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Listing certs for store %s\n", storename); 1421db522d3aSSimon L. B. Nielsen 1422db522d3aSSimon L. B. Nielsen hstore = capi_open_store(ctx, storename); 1423db522d3aSSimon L. B. Nielsen if (!hstore) 1424db522d3aSSimon L. B. Nielsen return 0; 14256f9291ceSJung-uk Kim if (id) { 1426db522d3aSSimon L. B. Nielsen cert = capi_find_cert(ctx, id, hstore); 14276f9291ceSJung-uk Kim if (!cert) { 1428db522d3aSSimon L. B. Nielsen ret = 0; 1429db522d3aSSimon L. B. Nielsen goto err; 1430db522d3aSSimon L. B. Nielsen } 1431db522d3aSSimon L. B. Nielsen capi_dump_cert(ctx, out, cert); 1432db522d3aSSimon L. B. Nielsen CertFreeCertificateContext(cert); 14336f9291ceSJung-uk Kim } else { 14346f9291ceSJung-uk Kim for (idx = 0;; idx++) { 1435db522d3aSSimon L. B. Nielsen cert = CertEnumCertificatesInStore(hstore, cert); 1436db522d3aSSimon L. B. Nielsen if (!cert) 1437db522d3aSSimon L. B. Nielsen break; 1438db522d3aSSimon L. B. Nielsen BIO_printf(out, "Certificate %d\n", idx); 1439db522d3aSSimon L. B. Nielsen capi_dump_cert(ctx, out, cert); 1440db522d3aSSimon L. B. Nielsen } 1441db522d3aSSimon L. B. Nielsen } 1442db522d3aSSimon L. B. Nielsen err: 1443db522d3aSSimon L. B. Nielsen CertCloseStore(hstore, 0); 1444db522d3aSSimon L. B. Nielsen return ret; 1445db522d3aSSimon L. B. Nielsen } 1446db522d3aSSimon L. B. Nielsen 14476f9291ceSJung-uk Kim static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, 14486f9291ceSJung-uk Kim HCERTSTORE hstore) 1449db522d3aSSimon L. B. Nielsen { 1450db522d3aSSimon L. B. Nielsen PCCERT_CONTEXT cert = NULL; 1451db522d3aSSimon L. B. Nielsen char *fname = NULL; 1452db522d3aSSimon L. B. Nielsen int match; 14536f9291ceSJung-uk Kim switch (ctx->lookup_method) { 1454db522d3aSSimon L. B. Nielsen case CAPI_LU_SUBSTR: 1455*e71b7053SJung-uk Kim return CertFindCertificateInStore(hstore, X509_ASN_ENCODING, 0, 1456db522d3aSSimon L. B. Nielsen CERT_FIND_SUBJECT_STR_A, id, NULL); 1457db522d3aSSimon L. B. Nielsen case CAPI_LU_FNAME: 14586f9291ceSJung-uk Kim for (;;) { 1459db522d3aSSimon L. B. Nielsen cert = CertEnumCertificatesInStore(hstore, cert); 1460db522d3aSSimon L. B. Nielsen if (!cert) 1461db522d3aSSimon L. B. Nielsen return NULL; 1462db522d3aSSimon L. B. Nielsen fname = capi_cert_get_fname(ctx, cert); 14636f9291ceSJung-uk Kim if (fname) { 1464db522d3aSSimon L. B. Nielsen if (strcmp(fname, id)) 1465db522d3aSSimon L. B. Nielsen match = 0; 1466db522d3aSSimon L. B. Nielsen else 1467db522d3aSSimon L. B. Nielsen match = 1; 1468db522d3aSSimon L. B. Nielsen OPENSSL_free(fname); 1469db522d3aSSimon L. B. Nielsen if (match) 1470db522d3aSSimon L. B. Nielsen return cert; 1471db522d3aSSimon L. B. Nielsen } 1472db522d3aSSimon L. B. Nielsen } 1473db522d3aSSimon L. B. Nielsen default: 1474db522d3aSSimon L. B. Nielsen return NULL; 1475db522d3aSSimon L. B. Nielsen } 1476db522d3aSSimon L. B. Nielsen } 1477db522d3aSSimon L. B. Nielsen 1478*e71b7053SJung-uk Kim static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const WCHAR *contname, 1479*e71b7053SJung-uk Kim const WCHAR *provname, DWORD ptype, 1480*e71b7053SJung-uk Kim DWORD keyspec) 1481db522d3aSSimon L. B. Nielsen { 148209286989SJung-uk Kim DWORD dwFlags = 0; 1483*e71b7053SJung-uk Kim CAPI_KEY *key = OPENSSL_malloc(sizeof(*key)); 1484*e71b7053SJung-uk Kim 1485*e71b7053SJung-uk Kim if (key == NULL) 1486*e71b7053SJung-uk Kim return NULL; 1487*e71b7053SJung-uk Kim /* If PROV_RSA_AES supported use it instead */ 1488*e71b7053SJung-uk Kim if (ptype == PROV_RSA_FULL && use_aes_csp && 1489*e71b7053SJung-uk Kim wcscmp(provname, rsa_enh_cspname) == 0) { 1490*e71b7053SJung-uk Kim provname = rsa_aes_cspname; 1491*e71b7053SJung-uk Kim ptype = PROV_RSA_AES; 1492aeb5019cSJung-uk Kim } 1493*e71b7053SJung-uk Kim if (ctx && ctx->debug_level >= CAPI_DBG_TRACE && ctx->debug_file) { 1494*e71b7053SJung-uk Kim /* 1495*e71b7053SJung-uk Kim * above 'if' is [complementary] copy from CAPI_trace and serves 1496*e71b7053SJung-uk Kim * as optimization to minimize [below] malloc-ations 1497*e71b7053SJung-uk Kim */ 1498*e71b7053SJung-uk Kim char *_contname = wide_to_asc(contname); 1499*e71b7053SJung-uk Kim char *_provname = wide_to_asc(provname); 15007bded2dbSJung-uk Kim 15017bded2dbSJung-uk Kim CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n", 15027bded2dbSJung-uk Kim _contname, _provname, ptype); 15037bded2dbSJung-uk Kim OPENSSL_free(_provname); 15047bded2dbSJung-uk Kim OPENSSL_free(_contname); 15057bded2dbSJung-uk Kim } 150609286989SJung-uk Kim if (ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE) 150709286989SJung-uk Kim dwFlags = CRYPT_MACHINE_KEYSET; 1508*e71b7053SJung-uk Kim if (!CryptAcquireContextW(&key->hprov, contname, provname, ptype, 1509*e71b7053SJung-uk Kim dwFlags)) { 1510db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); 1511db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1512db522d3aSSimon L. B. Nielsen goto err; 1513db522d3aSSimon L. B. Nielsen } 15146f9291ceSJung-uk Kim if (!CryptGetUserKey(key->hprov, keyspec, &key->key)) { 1515db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR); 1516db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1517db522d3aSSimon L. B. Nielsen CryptReleaseContext(key->hprov, 0); 1518db522d3aSSimon L. B. Nielsen goto err; 1519db522d3aSSimon L. B. Nielsen } 1520db522d3aSSimon L. B. Nielsen key->keyspec = keyspec; 1521db522d3aSSimon L. B. Nielsen key->pcert = NULL; 1522db522d3aSSimon L. B. Nielsen return key; 1523db522d3aSSimon L. B. Nielsen 1524db522d3aSSimon L. B. Nielsen err: 1525db522d3aSSimon L. B. Nielsen OPENSSL_free(key); 1526db522d3aSSimon L. B. Nielsen return NULL; 1527db522d3aSSimon L. B. Nielsen } 1528db522d3aSSimon L. B. Nielsen 1529db522d3aSSimon L. B. Nielsen static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert) 1530db522d3aSSimon L. B. Nielsen { 1531db522d3aSSimon L. B. Nielsen CAPI_KEY *key = NULL; 1532db522d3aSSimon L. B. Nielsen CRYPT_KEY_PROV_INFO *pinfo = NULL; 1533db522d3aSSimon L. B. Nielsen 1534*e71b7053SJung-uk Kim pinfo = capi_get_prov_info(ctx, cert); 1535*e71b7053SJung-uk Kim 1536*e71b7053SJung-uk Kim if (pinfo != NULL) 1537*e71b7053SJung-uk Kim key = capi_get_key(ctx, pinfo->pwszContainerName, pinfo->pwszProvName, 1538*e71b7053SJung-uk Kim pinfo->dwProvType, pinfo->dwKeySpec); 1539*e71b7053SJung-uk Kim 1540db522d3aSSimon L. B. Nielsen OPENSSL_free(pinfo); 1541db522d3aSSimon L. B. Nielsen return key; 1542db522d3aSSimon L. B. Nielsen } 1543db522d3aSSimon L. B. Nielsen 1544db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id) 1545db522d3aSSimon L. B. Nielsen { 1546db522d3aSSimon L. B. Nielsen PCCERT_CONTEXT cert; 1547db522d3aSSimon L. B. Nielsen HCERTSTORE hstore; 1548db522d3aSSimon L. B. Nielsen CAPI_KEY *key = NULL; 1549*e71b7053SJung-uk Kim 15506f9291ceSJung-uk Kim switch (ctx->lookup_method) { 1551db522d3aSSimon L. B. Nielsen case CAPI_LU_SUBSTR: 1552db522d3aSSimon L. B. Nielsen case CAPI_LU_FNAME: 1553db522d3aSSimon L. B. Nielsen hstore = capi_open_store(ctx, NULL); 1554db522d3aSSimon L. B. Nielsen if (!hstore) 1555db522d3aSSimon L. B. Nielsen return NULL; 1556db522d3aSSimon L. B. Nielsen cert = capi_find_cert(ctx, id, hstore); 15576f9291ceSJung-uk Kim if (cert) { 1558db522d3aSSimon L. B. Nielsen key = capi_get_cert_key(ctx, cert); 1559db522d3aSSimon L. B. Nielsen CertFreeCertificateContext(cert); 1560db522d3aSSimon L. B. Nielsen } 1561db522d3aSSimon L. B. Nielsen CertCloseStore(hstore, 0); 1562db522d3aSSimon L. B. Nielsen break; 1563db522d3aSSimon L. B. Nielsen 1564db522d3aSSimon L. B. Nielsen case CAPI_LU_CONTNAME: 1565*e71b7053SJung-uk Kim { 15667bded2dbSJung-uk Kim WCHAR *contname, *provname; 15677bded2dbSJung-uk Kim DWORD len; 15687bded2dbSJung-uk Kim 15697bded2dbSJung-uk Kim if ((len = MultiByteToWideChar(CP_ACP, 0, id, -1, NULL, 0)) && 15707bded2dbSJung-uk Kim (contname = alloca(len * sizeof(WCHAR)), 15717bded2dbSJung-uk Kim MultiByteToWideChar(CP_ACP, 0, id, -1, contname, len)) && 1572*e71b7053SJung-uk Kim (len = MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, 1573*e71b7053SJung-uk Kim NULL, 0)) && 1574*e71b7053SJung-uk Kim (provname = alloca(len * sizeof(WCHAR)), 1575*e71b7053SJung-uk Kim MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, 1576*e71b7053SJung-uk Kim provname, len))) 1577*e71b7053SJung-uk Kim key = capi_get_key(ctx, contname, provname, 15787bded2dbSJung-uk Kim ctx->csptype, ctx->keytype); 1579*e71b7053SJung-uk Kim } 1580db522d3aSSimon L. B. Nielsen break; 1581db522d3aSSimon L. B. Nielsen } 1582db522d3aSSimon L. B. Nielsen 1583db522d3aSSimon L. B. Nielsen return key; 1584db522d3aSSimon L. B. Nielsen } 1585db522d3aSSimon L. B. Nielsen 1586db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY *key) 1587db522d3aSSimon L. B. Nielsen { 1588db522d3aSSimon L. B. Nielsen if (!key) 1589db522d3aSSimon L. B. Nielsen return; 1590db522d3aSSimon L. B. Nielsen CryptDestroyKey(key->key); 1591db522d3aSSimon L. B. Nielsen CryptReleaseContext(key->hprov, 0); 1592db522d3aSSimon L. B. Nielsen if (key->pcert) 1593db522d3aSSimon L. B. Nielsen CertFreeCertificateContext(key->pcert); 1594db522d3aSSimon L. B. Nielsen OPENSSL_free(key); 1595db522d3aSSimon L. B. Nielsen } 1596db522d3aSSimon L. B. Nielsen 1597db522d3aSSimon L. B. Nielsen /* Initialize a CAPI_CTX structure */ 1598db522d3aSSimon L. B. Nielsen 1599*e71b7053SJung-uk Kim static CAPI_CTX *capi_ctx_new(void) 1600db522d3aSSimon L. B. Nielsen { 1601*e71b7053SJung-uk Kim CAPI_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); 1602*e71b7053SJung-uk Kim 1603*e71b7053SJung-uk Kim if (ctx == NULL) { 1604db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CAPI_CTX_NEW, ERR_R_MALLOC_FAILURE); 1605db522d3aSSimon L. B. Nielsen return NULL; 1606db522d3aSSimon L. B. Nielsen } 1607db522d3aSSimon L. B. Nielsen ctx->csptype = PROV_RSA_FULL; 1608db522d3aSSimon L. B. Nielsen ctx->dump_flags = CAPI_DMP_SUMMARY | CAPI_DMP_FNAME; 1609db522d3aSSimon L. B. Nielsen ctx->keytype = AT_KEYEXCHANGE; 1610db522d3aSSimon L. B. Nielsen ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG | 16116f9291ceSJung-uk Kim CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER; 1612db522d3aSSimon L. B. Nielsen ctx->lookup_method = CAPI_LU_SUBSTR; 1613db522d3aSSimon L. B. Nielsen ctx->client_cert_select = cert_select_simple; 1614db522d3aSSimon L. B. Nielsen return ctx; 1615db522d3aSSimon L. B. Nielsen } 1616db522d3aSSimon L. B. Nielsen 1617db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX *ctx) 1618db522d3aSSimon L. B. Nielsen { 1619db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx); 1620db522d3aSSimon L. B. Nielsen if (!ctx) 1621db522d3aSSimon L. B. Nielsen return; 1622db522d3aSSimon L. B. Nielsen OPENSSL_free(ctx->cspname); 1623db522d3aSSimon L. B. Nielsen OPENSSL_free(ctx->debug_file); 1624db522d3aSSimon L. B. Nielsen OPENSSL_free(ctx->storename); 1625db522d3aSSimon L. B. Nielsen OPENSSL_free(ctx->ssl_client_store); 1626db522d3aSSimon L. B. Nielsen OPENSSL_free(ctx); 1627db522d3aSSimon L. B. Nielsen } 1628db522d3aSSimon L. B. Nielsen 16296f9291ceSJung-uk Kim static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, 16306f9291ceSJung-uk Kim int check) 1631db522d3aSSimon L. B. Nielsen { 1632*e71b7053SJung-uk Kim LPSTR tmpcspname; 1633*e71b7053SJung-uk Kim 1634db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type); 16356f9291ceSJung-uk Kim if (check) { 1636db522d3aSSimon L. B. Nielsen HCRYPTPROV hprov; 1637*e71b7053SJung-uk Kim LPWSTR name = NULL; 16387bded2dbSJung-uk Kim DWORD len; 1639*e71b7053SJung-uk Kim 16407bded2dbSJung-uk Kim if ((len = MultiByteToWideChar(CP_ACP, 0, pname, -1, NULL, 0))) { 16417bded2dbSJung-uk Kim name = alloca(len * sizeof(WCHAR)); 16427bded2dbSJung-uk Kim MultiByteToWideChar(CP_ACP, 0, pname, -1, (WCHAR *)name, len); 16437bded2dbSJung-uk Kim } 1644*e71b7053SJung-uk Kim if (name == NULL || !CryptAcquireContextW(&hprov, NULL, name, type, 16456f9291ceSJung-uk Kim CRYPT_VERIFYCONTEXT)) { 16466f9291ceSJung-uk Kim CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, 16476f9291ceSJung-uk Kim CAPI_R_CRYPTACQUIRECONTEXT_ERROR); 1648db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1649db522d3aSSimon L. B. Nielsen return 0; 1650db522d3aSSimon L. B. Nielsen } 1651db522d3aSSimon L. B. Nielsen CryptReleaseContext(hprov, 0); 1652db522d3aSSimon L. B. Nielsen } 1653*e71b7053SJung-uk Kim tmpcspname = OPENSSL_strdup(pname); 1654*e71b7053SJung-uk Kim if (tmpcspname == NULL) { 1655*e71b7053SJung-uk Kim CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, ERR_R_MALLOC_FAILURE); 1656*e71b7053SJung-uk Kim return 0; 1657*e71b7053SJung-uk Kim } 165812de4ed2SJung-uk Kim OPENSSL_free(ctx->cspname); 1659*e71b7053SJung-uk Kim ctx->cspname = tmpcspname; 1660db522d3aSSimon L. B. Nielsen ctx->csptype = type; 1661db522d3aSSimon L. B. Nielsen return 1; 1662db522d3aSSimon L. B. Nielsen } 1663db522d3aSSimon L. B. Nielsen 1664db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx) 1665db522d3aSSimon L. B. Nielsen { 1666db522d3aSSimon L. B. Nielsen LPSTR pname; 1667db522d3aSSimon L. B. Nielsen DWORD type; 166812de4ed2SJung-uk Kim int res; 1669db522d3aSSimon L. B. Nielsen if (capi_get_provname(ctx, &pname, &type, idx) != 1) 1670db522d3aSSimon L. B. Nielsen return 0; 167112de4ed2SJung-uk Kim res = capi_ctx_set_provname(ctx, pname, type, 0); 167212de4ed2SJung-uk Kim OPENSSL_free(pname); 167312de4ed2SJung-uk Kim return res; 1674db522d3aSSimon L. B. Nielsen } 1675db522d3aSSimon L. B. Nielsen 1676db522d3aSSimon L. B. Nielsen static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x) 1677db522d3aSSimon L. B. Nielsen { 1678db522d3aSSimon L. B. Nielsen int i; 1679db522d3aSSimon L. B. Nielsen X509_NAME *nm; 1680db522d3aSSimon L. B. Nielsen /* Special case: empty list: match anything */ 1681db522d3aSSimon L. B. Nielsen if (sk_X509_NAME_num(ca_dn) <= 0) 1682db522d3aSSimon L. B. Nielsen return 1; 16836f9291ceSJung-uk Kim for (i = 0; i < sk_X509_NAME_num(ca_dn); i++) { 1684db522d3aSSimon L. B. Nielsen nm = sk_X509_NAME_value(ca_dn, i); 1685db522d3aSSimon L. B. Nielsen if (!X509_NAME_cmp(nm, X509_get_issuer_name(x))) 1686db522d3aSSimon L. B. Nielsen return 1; 1687db522d3aSSimon L. B. Nielsen } 1688db522d3aSSimon L. B. Nielsen return 0; 1689db522d3aSSimon L. B. Nielsen } 1690db522d3aSSimon L. B. Nielsen 1691db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, 16926f9291ceSJung-uk Kim STACK_OF(X509_NAME) *ca_dn, X509 **pcert, 16936f9291ceSJung-uk Kim EVP_PKEY **pkey, STACK_OF(X509) **pother, 16946f9291ceSJung-uk Kim UI_METHOD *ui_method, 16956f9291ceSJung-uk Kim void *callback_data) 1696db522d3aSSimon L. B. Nielsen { 1697db522d3aSSimon L. B. Nielsen STACK_OF(X509) *certs = NULL; 1698db522d3aSSimon L. B. Nielsen X509 *x; 1699db522d3aSSimon L. B. Nielsen char *storename; 1700*e71b7053SJung-uk Kim const unsigned char *p; 1701db522d3aSSimon L. B. Nielsen int i, client_cert_idx; 1702db522d3aSSimon L. B. Nielsen HCERTSTORE hstore; 1703db522d3aSSimon L. B. Nielsen PCCERT_CONTEXT cert = NULL, excert = NULL; 1704db522d3aSSimon L. B. Nielsen CAPI_CTX *ctx; 1705db522d3aSSimon L. B. Nielsen CAPI_KEY *key; 1706db522d3aSSimon L. B. Nielsen ctx = ENGINE_get_ex_data(e, capi_idx); 1707db522d3aSSimon L. B. Nielsen 1708db522d3aSSimon L. B. Nielsen *pcert = NULL; 1709db522d3aSSimon L. B. Nielsen *pkey = NULL; 1710db522d3aSSimon L. B. Nielsen 1711db522d3aSSimon L. B. Nielsen storename = ctx->ssl_client_store; 1712db522d3aSSimon L. B. Nielsen if (!storename) 1713db522d3aSSimon L. B. Nielsen storename = "MY"; 1714db522d3aSSimon L. B. Nielsen 1715db522d3aSSimon L. B. Nielsen hstore = capi_open_store(ctx, storename); 1716db522d3aSSimon L. B. Nielsen if (!hstore) 1717db522d3aSSimon L. B. Nielsen return 0; 1718db522d3aSSimon L. B. Nielsen /* Enumerate all certificates collect any matches */ 17196f9291ceSJung-uk Kim for (i = 0;; i++) { 1720db522d3aSSimon L. B. Nielsen cert = CertEnumCertificatesInStore(hstore, cert); 1721db522d3aSSimon L. B. Nielsen if (!cert) 1722db522d3aSSimon L. B. Nielsen break; 1723db522d3aSSimon L. B. Nielsen p = cert->pbCertEncoded; 1724db522d3aSSimon L. B. Nielsen x = d2i_X509(NULL, &p, cert->cbCertEncoded); 17256f9291ceSJung-uk Kim if (!x) { 1726db522d3aSSimon L. B. Nielsen CAPI_trace(ctx, "Can't Parse Certificate %d\n", i); 1727db522d3aSSimon L. B. Nielsen continue; 1728db522d3aSSimon L. B. Nielsen } 1729db522d3aSSimon L. B. Nielsen if (cert_issuer_match(ca_dn, x) 17306f9291ceSJung-uk Kim && X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0)) { 1731db522d3aSSimon L. B. Nielsen key = capi_get_cert_key(ctx, cert); 17326f9291ceSJung-uk Kim if (!key) { 1733db522d3aSSimon L. B. Nielsen X509_free(x); 1734db522d3aSSimon L. B. Nielsen continue; 1735db522d3aSSimon L. B. Nielsen } 17366f9291ceSJung-uk Kim /* 17376f9291ceSJung-uk Kim * Match found: attach extra data to it so we can retrieve the 17386f9291ceSJung-uk Kim * key later. 1739db522d3aSSimon L. B. Nielsen */ 1740db522d3aSSimon L. B. Nielsen excert = CertDuplicateCertificateContext(cert); 1741db522d3aSSimon L. B. Nielsen key->pcert = excert; 1742db522d3aSSimon L. B. Nielsen X509_set_ex_data(x, cert_capi_idx, key); 1743db522d3aSSimon L. B. Nielsen 1744db522d3aSSimon L. B. Nielsen if (!certs) 1745db522d3aSSimon L. B. Nielsen certs = sk_X509_new_null(); 1746db522d3aSSimon L. B. Nielsen 1747db522d3aSSimon L. B. Nielsen sk_X509_push(certs, x); 1748*e71b7053SJung-uk Kim } else { 1749db522d3aSSimon L. B. Nielsen X509_free(x); 1750*e71b7053SJung-uk Kim } 1751db522d3aSSimon L. B. Nielsen } 1752db522d3aSSimon L. B. Nielsen 1753db522d3aSSimon L. B. Nielsen if (cert) 1754db522d3aSSimon L. B. Nielsen CertFreeCertificateContext(cert); 1755db522d3aSSimon L. B. Nielsen if (hstore) 1756db522d3aSSimon L. B. Nielsen CertCloseStore(hstore, 0); 1757db522d3aSSimon L. B. Nielsen 1758db522d3aSSimon L. B. Nielsen if (!certs) 1759db522d3aSSimon L. B. Nielsen return 0; 1760db522d3aSSimon L. B. Nielsen 1761db522d3aSSimon L. B. Nielsen /* Select the appropriate certificate */ 1762db522d3aSSimon L. B. Nielsen 1763db522d3aSSimon L. B. Nielsen client_cert_idx = ctx->client_cert_select(e, ssl, certs); 1764db522d3aSSimon L. B. Nielsen 1765db522d3aSSimon L. B. Nielsen /* Set the selected certificate and free the rest */ 1766db522d3aSSimon L. B. Nielsen 17676f9291ceSJung-uk Kim for (i = 0; i < sk_X509_num(certs); i++) { 1768db522d3aSSimon L. B. Nielsen x = sk_X509_value(certs, i); 1769db522d3aSSimon L. B. Nielsen if (i == client_cert_idx) 1770db522d3aSSimon L. B. Nielsen *pcert = x; 17716f9291ceSJung-uk Kim else { 1772db522d3aSSimon L. B. Nielsen key = X509_get_ex_data(x, cert_capi_idx); 1773db522d3aSSimon L. B. Nielsen capi_free_key(key); 1774db522d3aSSimon L. B. Nielsen X509_free(x); 1775db522d3aSSimon L. B. Nielsen } 1776db522d3aSSimon L. B. Nielsen } 1777db522d3aSSimon L. B. Nielsen 1778db522d3aSSimon L. B. Nielsen sk_X509_free(certs); 1779db522d3aSSimon L. B. Nielsen 1780db522d3aSSimon L. B. Nielsen if (!*pcert) 1781db522d3aSSimon L. B. Nielsen return 0; 1782db522d3aSSimon L. B. Nielsen 1783db522d3aSSimon L. B. Nielsen /* Setup key for selected certificate */ 1784db522d3aSSimon L. B. Nielsen 1785db522d3aSSimon L. B. Nielsen key = X509_get_ex_data(*pcert, cert_capi_idx); 1786db522d3aSSimon L. B. Nielsen *pkey = capi_get_pkey(e, key); 1787db522d3aSSimon L. B. Nielsen X509_set_ex_data(*pcert, cert_capi_idx, NULL); 1788db522d3aSSimon L. B. Nielsen 1789db522d3aSSimon L. B. Nielsen return 1; 1790db522d3aSSimon L. B. Nielsen 1791db522d3aSSimon L. B. Nielsen } 1792db522d3aSSimon L. B. Nielsen 1793db522d3aSSimon L. B. Nielsen /* Simple client cert selection function: always select first */ 1794db522d3aSSimon L. B. Nielsen 1795db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) 1796db522d3aSSimon L. B. Nielsen { 1797db522d3aSSimon L. B. Nielsen return 0; 1798db522d3aSSimon L. B. Nielsen } 1799db522d3aSSimon L. B. Nielsen 1800db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG 1801db522d3aSSimon L. B. Nielsen 18026f9291ceSJung-uk Kim /* 18036f9291ceSJung-uk Kim * More complex cert selection function, using standard function 1804db522d3aSSimon L. B. Nielsen * CryptUIDlgSelectCertificateFromStore() to produce a dialog box. 1805db522d3aSSimon L. B. Nielsen */ 1806db522d3aSSimon L. B. Nielsen 18076f9291ceSJung-uk Kim /* 18086f9291ceSJung-uk Kim * Definitions which are in cryptuiapi.h but this is not present in older 1809db522d3aSSimon L. B. Nielsen * versions of headers. 1810db522d3aSSimon L. B. Nielsen */ 1811db522d3aSSimon L. B. Nielsen 1812db522d3aSSimon L. B. Nielsen # ifndef CRYPTUI_SELECT_LOCATION_COLUMN 1813db522d3aSSimon L. B. Nielsen # define CRYPTUI_SELECT_LOCATION_COLUMN 0x000000010 1814db522d3aSSimon L. B. Nielsen # define CRYPTUI_SELECT_INTENDEDUSE_COLUMN 0x000000004 1815db522d3aSSimon L. B. Nielsen # endif 1816db522d3aSSimon L. B. Nielsen 1817db522d3aSSimon L. B. Nielsen # define dlg_title L"OpenSSL Application SSL Client Certificate Selection" 1818db522d3aSSimon L. B. Nielsen # define dlg_prompt L"Select a certificate to use for authentication" 1819db522d3aSSimon L. B. Nielsen # define dlg_columns CRYPTUI_SELECT_LOCATION_COLUMN \ 1820db522d3aSSimon L. B. Nielsen |CRYPTUI_SELECT_INTENDEDUSE_COLUMN 1821db522d3aSSimon L. B. Nielsen 1822db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) 1823db522d3aSSimon L. B. Nielsen { 1824db522d3aSSimon L. B. Nielsen X509 *x; 1825db522d3aSSimon L. B. Nielsen HCERTSTORE dstore; 1826db522d3aSSimon L. B. Nielsen PCCERT_CONTEXT cert; 1827db522d3aSSimon L. B. Nielsen CAPI_CTX *ctx; 1828db522d3aSSimon L. B. Nielsen CAPI_KEY *key; 1829db522d3aSSimon L. B. Nielsen HWND hwnd; 1830db522d3aSSimon L. B. Nielsen int i, idx = -1; 1831db522d3aSSimon L. B. Nielsen if (sk_X509_num(certs) == 1) 1832db522d3aSSimon L. B. Nielsen return 0; 1833db522d3aSSimon L. B. Nielsen ctx = ENGINE_get_ex_data(e, capi_idx); 1834db522d3aSSimon L. B. Nielsen /* Create an in memory store of certificates */ 1835db522d3aSSimon L. B. Nielsen dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 1836db522d3aSSimon L. B. Nielsen CERT_STORE_CREATE_NEW_FLAG, NULL); 18376f9291ceSJung-uk Kim if (!dstore) { 1838db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE); 1839db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1840db522d3aSSimon L. B. Nielsen goto err; 1841db522d3aSSimon L. B. Nielsen } 1842db522d3aSSimon L. B. Nielsen /* Add all certificates to store */ 18436f9291ceSJung-uk Kim for (i = 0; i < sk_X509_num(certs); i++) { 1844db522d3aSSimon L. B. Nielsen x = sk_X509_value(certs, i); 1845db522d3aSSimon L. B. Nielsen key = X509_get_ex_data(x, cert_capi_idx); 1846db522d3aSSimon L. B. Nielsen 1847db522d3aSSimon L. B. Nielsen if (!CertAddCertificateContextToStore(dstore, key->pcert, 18486f9291ceSJung-uk Kim CERT_STORE_ADD_NEW, NULL)) { 1849db522d3aSSimon L. B. Nielsen CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT); 1850db522d3aSSimon L. B. Nielsen capi_addlasterror(); 1851db522d3aSSimon L. B. Nielsen goto err; 1852db522d3aSSimon L. B. Nielsen } 1853db522d3aSSimon L. B. Nielsen 1854db522d3aSSimon L. B. Nielsen } 1855db522d3aSSimon L. B. Nielsen hwnd = GetForegroundWindow(); 1856db522d3aSSimon L. B. Nielsen if (!hwnd) 1857db522d3aSSimon L. B. Nielsen hwnd = GetActiveWindow(); 1858db522d3aSSimon L. B. Nielsen if (!hwnd && ctx->getconswindow) 1859db522d3aSSimon L. B. Nielsen hwnd = ctx->getconswindow(); 1860db522d3aSSimon L. B. Nielsen /* Call dialog to select one */ 1861db522d3aSSimon L. B. Nielsen cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt, 1862db522d3aSSimon L. B. Nielsen dlg_columns, 0, NULL); 1863db522d3aSSimon L. B. Nielsen 1864db522d3aSSimon L. B. Nielsen /* Find matching cert from list */ 18656f9291ceSJung-uk Kim if (cert) { 18666f9291ceSJung-uk Kim for (i = 0; i < sk_X509_num(certs); i++) { 1867db522d3aSSimon L. B. Nielsen x = sk_X509_value(certs, i); 1868db522d3aSSimon L. B. Nielsen key = X509_get_ex_data(x, cert_capi_idx); 18696f9291ceSJung-uk Kim if (CertCompareCertificate 18706f9291ceSJung-uk Kim (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert->pCertInfo, 18716f9291ceSJung-uk Kim key->pcert->pCertInfo)) { 1872db522d3aSSimon L. B. Nielsen idx = i; 1873db522d3aSSimon L. B. Nielsen break; 1874db522d3aSSimon L. B. Nielsen } 1875db522d3aSSimon L. B. Nielsen } 1876db522d3aSSimon L. B. Nielsen } 1877db522d3aSSimon L. B. Nielsen 1878db522d3aSSimon L. B. Nielsen err: 1879db522d3aSSimon L. B. Nielsen if (dstore) 1880db522d3aSSimon L. B. Nielsen CertCloseStore(dstore, 0); 1881db522d3aSSimon L. B. Nielsen return idx; 1882db522d3aSSimon L. B. Nielsen 1883db522d3aSSimon L. B. Nielsen } 1884db522d3aSSimon L. B. Nielsen # endif 1885db522d3aSSimon L. B. Nielsen 18861f13597dSJung-uk Kim #else /* !__COMPILE_CAPIENG */ 1887db522d3aSSimon L. B. Nielsen # include <openssl/engine.h> 1888db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_DYNAMIC_ENGINE 1889db522d3aSSimon L. B. Nielsen OPENSSL_EXPORT 18901f13597dSJung-uk Kim int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); 18911f13597dSJung-uk Kim OPENSSL_EXPORT 18926f9291ceSJung-uk Kim int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) 18936f9291ceSJung-uk Kim { 18946f9291ceSJung-uk Kim return 0; 18956f9291ceSJung-uk Kim } 18966f9291ceSJung-uk Kim 1897db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN() 18981f13597dSJung-uk Kim # else 1899*e71b7053SJung-uk Kim void engine_load_capi_int(void); 1900*e71b7053SJung-uk Kim void engine_load_capi_int(void) 19016f9291ceSJung-uk Kim { 19026f9291ceSJung-uk Kim } 1903db522d3aSSimon L. B. Nielsen # endif 1904db522d3aSSimon L. B. Nielsen #endif 1905