X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=engines%2Fe_capi.c;h=41257ad568377eac7d52aba242ad77439e6013f0;hb=e95bbc3ca628eecc6f005ee54126e2d27fc54859;hp=8da67982b0be9a3292efbc468036b77e8dd0f1ea;hpb=f87e3078751ce04493f497c195d3b3547b0cf1e0;p=openssl.git diff --git a/engines/e_capi.c b/engines/e_capi.c index 8da67982b0..41257ad568 100644 --- a/engines/e_capi.c +++ b/engines/e_capi.c @@ -54,32 +54,44 @@ #include #include +#include + #include -#include -#include #ifdef OPENSSL_SYS_WIN32 #ifndef OPENSSL_NO_CAPIENG +#include +#include #include - -#include +#include #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif +#include #include +#include +#ifndef alloca +# define alloca _alloca +#endif /* * This module uses several "new" interfaces, among which is * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is * one of possible values you can pass to function in question. By * checking if it's defined we can see if wincrypt.h and accompanying - * crypt32.lib are in shape. Yes, it's rather "weak" test and if - * compilation fails, then re-configure with -DOPENSSL_NO_CAPIENG. + * crypt32.lib are in shape. The native MingW32 headers up to and + * including __W32API_VERSION 3.14 lack of struct DSSPUBKEY and the + * defines CERT_STORE_PROV_SYSTEM_A and CERT_STORE_READONLY_FLAG, + * so we check for these too and avoid compiling. + * Yes, it's rather "weak" test and if compilation fails, + * then re-configure with -DOPENSSL_NO_CAPIENG. */ -#ifdef CERT_KEY_PROV_INFO_PROP_ID +#if defined(CERT_KEY_PROV_INFO_PROP_ID) && \ + defined(CERT_STORE_PROV_SYSTEM_A) && \ + defined(CERT_STORE_READONLY_FLAG) # define __COMPILE_CAPIENG #endif /* CERT_KEY_PROV_INFO_PROP_ID */ #endif /* OPENSSL_NO_CAPIENG */ @@ -99,6 +111,30 @@ #define CERT_STORE_CREATE_NEW_FLAG 0x00002000 #endif +#ifndef CERT_SYSTEM_STORE_CURRENT_USER +#define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000 +#endif + +#ifndef ALG_SID_SHA_256 + #define ALG_SID_SHA_256 12 +#endif +#ifndef ALG_SID_SHA_384 + #define ALG_SID_SHA_384 13 +#endif +#ifndef ALG_SID_SHA_512 + #define ALG_SID_SHA_512 14 +#endif + +#ifndef CALG_SHA_256 + #define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256) +#endif +#ifndef CALG_SHA_384 + #define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384) +#endif +#ifndef CALG_SHA_512 + #define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512) +#endif + #include #include #include @@ -305,6 +341,11 @@ static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) } ctx = ENGINE_get_ex_data(e, capi_idx); out = BIO_new_fp(stdout, BIO_NOCLOSE); + if (out == NULL) + { + CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_FILE_OPEN_ERROR); + return 0; + } switch (cmd) { case CAPI_CMD_LIST_CSPS: @@ -371,6 +412,7 @@ static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) if (i < 1 || i > 3) { CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD); + BIO_free(out); return 0; } ctx->lookup_method = i; @@ -432,28 +474,36 @@ static int capi_init(ENGINE *e) CAPI_CTX *ctx; const RSA_METHOD *ossl_rsa_meth; const DSA_METHOD *ossl_dsa_meth; - capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0); - cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0); + + if (capi_idx < 0) + { + capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0); + if (capi_idx < 0) + goto memerr; + + cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0); + + /* Setup RSA_METHOD */ + rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0); + ossl_rsa_meth = RSA_PKCS1_SSLeay(); + capi_rsa_method.rsa_pub_enc = ossl_rsa_meth->rsa_pub_enc; + capi_rsa_method.rsa_pub_dec = ossl_rsa_meth->rsa_pub_dec; + capi_rsa_method.rsa_mod_exp = ossl_rsa_meth->rsa_mod_exp; + capi_rsa_method.bn_mod_exp = ossl_rsa_meth->bn_mod_exp; + + /* Setup DSA Method */ + dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0); + ossl_dsa_meth = DSA_OpenSSL(); + capi_dsa_method.dsa_do_verify = ossl_dsa_meth->dsa_do_verify; + capi_dsa_method.dsa_mod_exp = ossl_dsa_meth->dsa_mod_exp; + capi_dsa_method.bn_mod_exp = ossl_dsa_meth->bn_mod_exp; + } ctx = capi_ctx_new(); - if (!ctx || (capi_idx < 0)) + if (!ctx) goto memerr; ENGINE_set_ex_data(e, capi_idx, ctx); - /* Setup RSA_METHOD */ - rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0); - ossl_rsa_meth = RSA_PKCS1_SSLeay(); - capi_rsa_method.rsa_pub_enc = ossl_rsa_meth->rsa_pub_enc; - capi_rsa_method.rsa_pub_dec = ossl_rsa_meth->rsa_pub_dec; - capi_rsa_method.rsa_mod_exp = ossl_rsa_meth->rsa_mod_exp; - capi_rsa_method.bn_mod_exp = ossl_rsa_meth->bn_mod_exp; - - /* Setup DSA Method */ - dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0); - ossl_dsa_meth = DSA_OpenSSL(); - capi_dsa_method.dsa_do_verify = ossl_dsa_meth->dsa_do_verify; - capi_dsa_method.dsa_mod_exp = ossl_dsa_meth->dsa_mod_exp; - capi_dsa_method.bn_mod_exp = ossl_dsa_meth->bn_mod_exp; #ifdef OPENSSL_CAPIENG_DIALOG { @@ -512,6 +562,7 @@ static int bind_capi(ENGINE *e) { if (!ENGINE_set_id(e, engine_capi_id) || !ENGINE_set_name(e, engine_capi_name) + || !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) || !ENGINE_set_init_function(e, capi_init) || !ENGINE_set_finish_function(e, capi_finish) || !ENGINE_set_destroy_function(e, capi_destroy) @@ -797,6 +848,18 @@ int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, /* Convert the signature type to a CryptoAPI algorithm ID */ switch(dtype) { + case NID_sha256: + alg = CALG_SHA_256; + break; + + case NID_sha384: + alg = CALG_SHA_384; + break; + + case NID_sha512: + alg = CALG_SHA_512; + break; + case NID_sha1: alg = CALG_SHA1; break; @@ -839,7 +902,7 @@ int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, /* Finally sign it */ slen = RSA_size(rsa); - if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) + if(!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); @@ -977,7 +1040,7 @@ static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, /* Finally sign it */ slen = sizeof(csigbuf); - if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) + if(!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); @@ -1025,6 +1088,11 @@ static void capi_vtrace(CAPI_CTX *ctx, int level, char *format, va_list argptr) if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file)) return; out = BIO_new_file(ctx->debug_file, "a+"); + if (out == NULL) + { + CAPIerr(CAPI_F_CAPI_VTRACE, CAPI_R_FILE_OPEN_ERROR); + return; + } BIO_vprintf(out, format, argptr); BIO_free(out); } @@ -1049,7 +1117,7 @@ static void capi_adderror(DWORD err) ERR_add_error_data(2, "Error code= 0x", errstr); } -static char *wide_to_asc(LPWSTR wstr) +static char *wide_to_asc(LPCWSTR wstr) { char *str; int len_0,sz; @@ -1080,10 +1148,10 @@ static char *wide_to_asc(LPWSTR wstr) static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, DWORD idx) { - LPSTR name; DWORD len, err; + LPTSTR name; CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx); - if (!CryptEnumProvidersA(idx, NULL, 0, ptype, NULL, &len)) + if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len)) { err = GetLastError(); if (err == ERROR_NO_MORE_ITEMS) @@ -1093,17 +1161,31 @@ static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, DWORD id return 0; } name = OPENSSL_malloc(len); - if (!CryptEnumProvidersA(idx, NULL, 0, ptype, name, &len)) + if (name == NULL) + { + CAPIerr(CAPI_F_CAPI_GET_PROVNAME, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) { err = GetLastError(); + OPENSSL_free(name); if (err == ERROR_NO_MORE_ITEMS) return 2; CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR); capi_adderror(err); return 0; } - *pname = name; - CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", name, *ptype); + if (sizeof(TCHAR) != sizeof(char)) + { + *pname = wide_to_asc((WCHAR *)name); + OPENSSL_free(name); + if (*pname == NULL) + return 0; + } + else + *pname = (char *)name; + CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", *pname, *ptype); return 1; } @@ -1134,8 +1216,26 @@ static int capi_list_containers(CAPI_CTX *ctx, BIO *out) HCRYPTPROV hprov; DWORD err, idx, flags, buflen = 0, clen; LPSTR cname; + LPTSTR cspname = NULL; + CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, ctx->csptype); - if (!CryptAcquireContextA(&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) + if (ctx->cspname && sizeof(TCHAR)!=sizeof(char)) + { + if ((clen=MultiByteToWideChar(CP_ACP,0,ctx->cspname,-1,NULL,0))) + { + cspname = alloca(clen*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP,0,ctx->cspname,-1,(WCHAR *)cspname,clen); + } + if (!cspname) + { + CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE); + capi_addlasterror(); + return 0; + } + } + else + cspname = (TCHAR *)ctx->cspname; + if (!CryptAcquireContext(&hprov, NULL, cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) { CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); @@ -1145,6 +1245,7 @@ static int capi_list_containers(CAPI_CTX *ctx, BIO *out) { CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR); capi_addlasterror(); + CryptReleaseContext(hprov, 0); return 0; } CAPI_trace(ctx, "Got max container len %d\n", buflen); @@ -1166,7 +1267,7 @@ static int capi_list_containers(CAPI_CTX *ctx, BIO *out) flags = CRYPT_FIRST; else flags = 0; - if(!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, cname, &clen, flags)) + if(!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, (BYTE *)cname, &clen, flags)) { err = GetLastError(); if (err == ERROR_NO_MORE_ITEMS) @@ -1250,6 +1351,8 @@ char * capi_cert_get_fname(CAPI_CTX *ctx, PCCERT_CONTEXT cert) if (!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dlen)) return NULL; wfname = OPENSSL_malloc(dlen); + if (wfname == NULL) + return NULL; if (CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, wfname, &dlen)) { char *fname = wide_to_asc(wfname); @@ -1362,7 +1465,6 @@ int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *id) { for(idx = 0;;idx++) { - LPWSTR fname = NULL; cert = CertEnumCertificatesInStore(hstore, cert); if (!cert) break; @@ -1409,13 +1511,30 @@ static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, HCERTSTORE h } } -static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const char *contname, char *provname, DWORD ptype, DWORD keyspec) +static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const TCHAR *contname, TCHAR *provname, DWORD ptype, DWORD keyspec) { CAPI_KEY *key; + DWORD dwFlags = 0; key = OPENSSL_malloc(sizeof(CAPI_KEY)); - CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n", + if (key == NULL) + return NULL; + if (sizeof(TCHAR)==sizeof(char)) + CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n", contname, provname, ptype); - if (!CryptAcquireContextA(&key->hprov, contname, provname, ptype, 0)) + else if (ctx && ctx->debug_level>=CAPI_DBG_TRACE && ctx->debug_file) + { + /* above 'if' is optimization to minimize malloc-ations */ + char *_contname = wide_to_asc((WCHAR *)contname); + char *_provname = wide_to_asc((WCHAR *)provname); + + CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n", + _contname, _provname, ptype); + if (_provname) OPENSSL_free(_provname); + if (_contname) OPENSSL_free(_contname); + } + if(ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE) + dwFlags = CRYPT_MACHINE_KEYSET; + if (!CryptAcquireContext(&key->hprov, contname, provname, ptype, dwFlags)) { CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); @@ -1445,12 +1564,19 @@ static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert) pinfo = capi_get_prov_info(ctx, cert); if (!pinfo) goto err; - provname = wide_to_asc(pinfo->pwszProvName); - contname = wide_to_asc(pinfo->pwszContainerName); - if (!provname || !contname) - goto err; - key = capi_get_key(ctx, contname, provname, + if (sizeof(TCHAR) != sizeof(char)) + key = capi_get_key(ctx, (TCHAR *)pinfo->pwszContainerName, + (TCHAR *)pinfo->pwszProvName, + pinfo->dwProvType, pinfo->dwKeySpec); + else + { + provname = wide_to_asc(pinfo->pwszProvName); + contname = wide_to_asc(pinfo->pwszContainerName); + if (!provname || !contname) + goto err; + key = capi_get_key(ctx, (TCHAR *)contname, (TCHAR *)provname, pinfo->dwProvType, pinfo->dwKeySpec); + } err: if (pinfo) @@ -1484,8 +1610,25 @@ CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id) break; case CAPI_LU_CONTNAME: - key = capi_get_key(ctx, id, ctx->cspname, ctx->csptype, - ctx->keytype); + if (sizeof(TCHAR)!=sizeof(char)) + { + WCHAR *contname, *provname; + DWORD len; + + if ((len=MultiByteToWideChar(CP_ACP,0,id,-1,NULL,0)) && + (contname=alloca(len*sizeof(WCHAR)), + MultiByteToWideChar(CP_ACP,0,id,-1,contname,len)) && + (len=MultiByteToWideChar(CP_ACP,0,ctx->cspname,-1,NULL,0)) && + (provname=alloca(len*sizeof(WCHAR)), + MultiByteToWideChar(CP_ACP,0,ctx->cspname,-1,provname,len))) + key = capi_get_key(ctx,(TCHAR *)contname, + (TCHAR *)provname, + ctx->csptype,ctx->keytype); + } + else + key = capi_get_key(ctx, (TCHAR *)id, + (TCHAR *)ctx->cspname, + ctx->csptype,ctx->keytype); break; } @@ -1553,7 +1696,21 @@ static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int che if (check) { HCRYPTPROV hprov; - if (!CryptAcquireContextA(&hprov, NULL, pname, type, + LPTSTR name=NULL; + + if (sizeof(TCHAR)!=sizeof(char)) + { + DWORD len; + if ((len=MultiByteToWideChar(CP_ACP,0,pname,-1,NULL,0))) + { + name = alloca(len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP,0,pname,-1,(WCHAR *)name,len); + } + } + else + name = (TCHAR *)pname; + + if (!name || !CryptAcquireContext(&hprov, NULL, name, type, CRYPT_VERIFYCONTEXT)) { CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); @@ -1562,6 +1719,8 @@ static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int che } CryptReleaseContext(hprov, 0); } + if (ctx->cspname) + OPENSSL_free(ctx->cspname); ctx->cspname = BUF_strdup(pname); ctx->csptype = type; return 1; @@ -1571,9 +1730,12 @@ static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx) { LPSTR pname; DWORD type; + int res; if (capi_get_provname(ctx, &pname, &type, idx) != 1) return 0; - return capi_ctx_set_provname(ctx, pname, type, 0); + res = capi_ctx_set_provname(ctx, pname, type, 0); + OPENSSL_free(pname); + return res; } static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x) @@ -1804,6 +1966,8 @@ static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) #include #ifndef OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_EXPORT +int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); +OPENSSL_EXPORT int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { return 0; } IMPLEMENT_DYNAMIC_CHECK_FN() #else