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