X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=engines%2Fe_capi.c;h=c1085b56cdabc46d0b46eef62481cab50500be46;hp=c2e5e6445882347cba4663aa4d0f2453e8289657;hb=712548231e101f11c06e729e2330a7f3155b2d7e;hpb=2836cb3816b87ec785ac6969b33136f293286382 diff --git a/engines/e_capi.c b/engines/e_capi.c index c2e5e64458..c1085b56cd 100644 --- a/engines/e_capi.c +++ b/engines/e_capi.c @@ -56,18 +56,59 @@ #include #include #include -#include #include #ifdef OPENSSL_SYS_WIN32 #ifndef OPENSSL_NO_CAPIENG +#include + #include + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif + #include +/* + * 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. 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. + */ +#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 */ +#endif /* OPENSSL_SYS_WIN32 */ + +#ifdef __COMPILE_CAPIENG + #undef X509_EXTENSIONS #undef X509_CERT_PAIR +/* Definitions which may be missing from earlier version of headers */ +#ifndef CERT_STORE_OPEN_EXISTING_FLAG +#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 +#endif + +#ifndef CERT_STORE_CREATE_NEW_FLAG +#define CERT_STORE_CREATE_NEW_FLAG 0x00002000 +#endif + +#ifndef CERT_SYSTEM_STORE_CURRENT_USER +#define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000 +#endif + #include #include #include @@ -137,21 +178,21 @@ struct CAPI_CTX_st { char *debug_file; /* Parameters to use for container lookup */ DWORD keytype; - LPTSTR cspname; + LPSTR cspname; DWORD csptype; /* Certificate store name to use */ - LPTSTR storename; - LPTSTR ssl_client_store; + LPSTR storename; + LPSTR ssl_client_store; /* System store flags */ DWORD store_flags; /* Lookup string meanings in load_private_key */ /* Substring of subject: uses "storename" */ -#define CAPI_LU_SUBSTR 0 +#define CAPI_LU_SUBSTR 1 /* Friendly name: uses storename */ -#define CAPI_LU_FNAME 1 +#define CAPI_LU_FNAME 2 /* Container name: uses cspname, keytype */ -#define CAPI_LU_CONTNAME 2 +#define CAPI_LU_CONTNAME 3 int lookup_method; /* Info to dump with dumpcerts option */ /* Issuer and serial name strings */ @@ -401,33 +442,41 @@ 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 { HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL")); - HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL")); + HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL")); if (cryptui) ctx->certselectdlg = (CERTDLG)GetProcAddress(cryptui, "CryptUIDlgSelectCertificateFromStore"); if (kernel) @@ -481,6 +530,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) @@ -701,7 +751,7 @@ static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key) return ret; memerr: - CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); + CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE); goto err; } @@ -808,7 +858,7 @@ int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, /* Finally sign it */ slen = RSA_size(rsa); - if(!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) + if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); @@ -946,7 +996,7 @@ static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, /* Finally sign it */ slen = sizeof(csigbuf); - if(!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) + if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); @@ -1021,15 +1071,29 @@ static void capi_adderror(DWORD err) static char *wide_to_asc(LPWSTR wstr) { char *str; + int len_0,sz; + if (!wstr) return NULL; - str = OPENSSL_malloc(wcslen(wstr) + 1); + len_0 = (int)wcslen(wstr)+1; /* WideCharToMultiByte expects int */ + sz = WideCharToMultiByte(CP_ACP,0,wstr,len_0,NULL,0,NULL,NULL); + if (!sz) + { + CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); + return NULL; + } + str = OPENSSL_malloc(sz); if (!str) { CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE); return NULL; } - sprintf(str, "%S", wstr); + if (!WideCharToMultiByte(CP_ACP,0,wstr,len_0,str,sz,NULL,NULL)) + { + OPENSSL_free(str); + CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); + return NULL; + } return str; } @@ -1038,7 +1102,7 @@ static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, DWORD id LPSTR name; DWORD len, err; CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx); - if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len)) + if (!CryptEnumProvidersA(idx, NULL, 0, ptype, NULL, &len)) { err = GetLastError(); if (err == ERROR_NO_MORE_ITEMS) @@ -1048,7 +1112,7 @@ static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, DWORD id return 0; } name = OPENSSL_malloc(len); - if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) + if (!CryptEnumProvidersA(idx, NULL, 0, ptype, name, &len)) { err = GetLastError(); if (err == ERROR_NO_MORE_ITEMS) @@ -1067,7 +1131,7 @@ static int capi_list_providers(CAPI_CTX *ctx, BIO *out) { DWORD idx, ptype; int ret; - LPTSTR provname = NULL; + LPSTR provname = NULL; CAPI_trace(ctx, "capi_list_providers\n"); BIO_printf(out, "Available CSPs:\n"); for(idx = 0; ; idx++) @@ -1090,7 +1154,7 @@ static int capi_list_containers(CAPI_CTX *ctx, BIO *out) DWORD err, idx, flags, buflen = 0, clen; LPSTR cname; CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, ctx->csptype); - if (!CryptAcquireContext(&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) + if (!CryptAcquireContextA(&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) { CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); @@ -1100,6 +1164,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); @@ -1367,10 +1432,13 @@ 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) { 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", contname, provname, ptype); - if (!CryptAcquireContext(&key->hprov, contname, provname, ptype, 0)) + if(ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE) + dwFlags = CRYPT_MACHINE_KEYSET; + if (!CryptAcquireContextA(&key->hprov, contname, provname, ptype, dwFlags)) { CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); @@ -1508,7 +1576,7 @@ static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int che if (check) { HCRYPTPROV hprov; - if (!CryptAcquireContext(&hprov, NULL, pname, type, + if (!CryptAcquireContextA(&hprov, NULL, pname, type, CRYPT_VERIFYCONTEXT)) { CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); @@ -1517,6 +1585,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; @@ -1526,9 +1596,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) @@ -1670,8 +1743,14 @@ static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) * CryptUIDlgSelectCertificateFromStore() to produce a dialog box. */ -#include -#include +/* Definitions which are in cryptuiapi.h but this is not present in older + * versions of headers. + */ + +#ifndef CRYPTUI_SELECT_LOCATION_COLUMN +#define CRYPTUI_SELECT_LOCATION_COLUMN 0x000000010 +#define CRYPTUI_SELECT_INTENDEDUSE_COLUMN 0x000000004 +#endif #define dlg_title L"OpenSSL Application SSL Client Certificate Selection" #define dlg_prompt L"Select a certificate to use for authentication" @@ -1695,7 +1774,7 @@ static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) CERT_STORE_CREATE_NEW_FLAG, NULL); if (!dstore) { - CAPIerr(CAPI_F_CLIENT_CERT_SELECT, CAPI_R_ERROR_CREATING_STORE); + CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE); capi_addlasterror(); goto err; } @@ -1708,13 +1787,15 @@ static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) if (!CertAddCertificateContextToStore(dstore, key->pcert, CERT_STORE_ADD_NEW, NULL)) { - CAPIerr(CAPI_F_CLIENT_CERT_SELECT, CAPI_R_ERROR_ADDING_CERT); + CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT); capi_addlasterror(); goto err; } } - hwnd = GetActiveWindow(); + hwnd = GetForegroundWindow(); + if (!hwnd) + hwnd = GetActiveWindow(); if (!hwnd && ctx->getconswindow) hwnd = ctx->getconswindow(); /* Call dialog to select one */ @@ -1747,5 +1828,15 @@ static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) } #endif +#else /* !__COMPILE_CAPIENG */ +#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 +void ENGINE_load_capi(void){} #endif #endif