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