From: Alexander Morozov Date: Thu, 24 Jun 2010 11:44:32 +0000 (+0400) Subject: crypt32: Find a provider for used algorithm (eterbug #5665). X-Git-Tag: 1.0.12-alt6.6~26 X-Git-Url: http://git.etersoft.ru/projects/?a=commitdiff_plain;h=282037871a29ae439a121c380abf264c721c5dad;p=wine%2Feterwine.git crypt32: Find a provider for used algorithm (eterbug #5665). --- diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c index 2780cba634..9e2541352f 100644 --- a/dlls/crypt32/cert.c +++ b/dlls/crypt32/cert.c @@ -1742,16 +1742,20 @@ BOOL WINAPI CryptHashCertificate(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, DWORD dwFlags, const BYTE *pbEncoded, DWORD cbEncoded, BYTE *pbComputedHash, DWORD *pcbComputedHash) { - BOOL ret = TRUE; + BOOL ret = TRUE, releaseProv = FALSE; HCRYPTHASH hHash = 0; TRACE("(%08lx, %d, %08x, %p, %d, %p, %p)\n", hCryptProv, Algid, dwFlags, pbEncoded, cbEncoded, pbComputedHash, pcbComputedHash); - if (!hCryptProv) - hCryptProv = CRYPT_GetDefaultProvider(); if (!Algid) Algid = CALG_SHA1; + if (!hCryptProv) + { + hCryptProv = CRYPT_GetProvForAlgId(Algid); + if (!hCryptProv) return FALSE; + releaseProv = TRUE; + } if (ret) { ret = CryptCreateHash(hCryptProv, Algid, 0, 0, &hHash); @@ -1764,6 +1768,8 @@ BOOL WINAPI CryptHashCertificate(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, CryptDestroyHash(hHash); } } + if (releaseProv) + CryptReleaseContext(hCryptProv, 0); return ret; } @@ -1771,16 +1777,20 @@ BOOL WINAPI CryptHashPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, DWORD dwFlags, DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, BYTE *pbComputedHash, DWORD *pcbComputedHash) { - BOOL ret = TRUE; + BOOL ret = TRUE, releaseProv = FALSE; HCRYPTHASH hHash = 0; TRACE("(%08lx, %d, %08x, %d, %p, %p, %p)\n", hCryptProv, Algid, dwFlags, dwCertEncodingType, pInfo, pbComputedHash, pcbComputedHash); - if (!hCryptProv) - hCryptProv = CRYPT_GetDefaultProvider(); if (!Algid) Algid = CALG_MD5; + if (!hCryptProv) + { + hCryptProv = CRYPT_GetProvForAlgId(Algid); + if (!hCryptProv) return FALSE; + releaseProv = TRUE; + } if (ret) { BYTE *buf; @@ -1802,6 +1812,8 @@ BOOL WINAPI CryptHashPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, LocalFree(buf); } } + if (releaseProv) + CryptReleaseContext(hCryptProv, 0); return ret; } @@ -1809,7 +1821,7 @@ BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded, BYTE *pbComputedHash, DWORD *pcbComputedHash) { - BOOL ret; + BOOL ret, releaseProv = FALSE; CERT_SIGNED_CONTENT_INFO *info; DWORD size; @@ -1823,8 +1835,6 @@ BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv, PCCRYPT_OID_INFO oidInfo; HCRYPTHASH hHash; - if (!hCryptProv) - hCryptProv = CRYPT_GetDefaultProvider(); oidInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, info->SignatureAlgorithm.pszObjId, 0); if (!oidInfo) @@ -1834,7 +1844,16 @@ BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv, } else { - ret = CryptCreateHash(hCryptProv, oidInfo->u.Algid, 0, 0, &hHash); + if (!hCryptProv) + { + hCryptProv = CRYPT_GetProvForAlgId(oidInfo->u.Algid); + if (hCryptProv) + releaseProv = TRUE; + else + ret = FALSE; + } + if (ret) + ret = CryptCreateHash(hCryptProv, oidInfo->u.Algid, 0, 0, &hHash); if (ret) { ret = CryptHashData(hHash, info->ToBeSigned.pbData, @@ -1844,6 +1863,8 @@ BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv, pcbComputedHash, 0); CryptDestroyHash(hHash); } + if (releaseProv) + CryptReleaseContext(hCryptProv, 0); } LocalFree(info); } @@ -1855,7 +1876,7 @@ BOOL WINAPI CryptSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD cbEncodedToBeSigned, PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, const void *pvHashAuxInfo, BYTE *pbSignature, DWORD *pcbSignature) { - BOOL ret; + BOOL ret = TRUE, releaseProv = FALSE; PCCRYPT_OID_INFO info; HCRYPTHASH hHash; @@ -1873,8 +1894,15 @@ BOOL WINAPI CryptSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, if (info->dwGroupId == CRYPT_HASH_ALG_OID_GROUP_ID) { if (!hCryptProv) - hCryptProv = CRYPT_GetDefaultProvider(); - ret = CryptCreateHash(hCryptProv, info->u.Algid, 0, 0, &hHash); + { + hCryptProv = CRYPT_GetProvForAlgId(info->u.Algid); + if (hCryptProv) + releaseProv = TRUE; + else + ret = FALSE; + } + if (ret) + ret = CryptCreateHash(hCryptProv, info->u.Algid, 0, 0, &hHash); if (ret) { ret = CryptHashData(hHash, pbEncodedToBeSigned, @@ -1884,6 +1912,8 @@ BOOL WINAPI CryptSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, pcbSignature, 0); CryptDestroyHash(hHash); } + if (releaseProv) + CryptReleaseContext(hCryptProv, 0); } else { @@ -1983,7 +2013,7 @@ static BOOL CRYPT_VerifyCertSignatureFromPublicKeyInfo(HCRYPTPROV_LEGACY hCryptP DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pubKeyInfo, const CERT_SIGNED_CONTENT_INFO *signedCert) { - BOOL ret; + BOOL ret, releaseProv = FALSE; HCRYPTKEY key; PCCRYPT_OID_INFO info; ALG_ID pubKeyID, hashID; @@ -2000,9 +2030,12 @@ static BOOL CRYPT_VerifyCertSignatureFromPublicKeyInfo(HCRYPTPROV_LEGACY hCryptP pubKeyID = *(ALG_ID *)info->ExtraInfo.pbData; else pubKeyID = hashID; - /* Load the default provider if necessary */ if (!hCryptProv) - hCryptProv = CRYPT_GetDefaultProvider(); + { + hCryptProv = CRYPT_GetProvForAlgId(pubKeyID); + if (!hCryptProv) return FALSE; + releaseProv = TRUE; + } ret = CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pubKeyInfo, pubKeyID, 0, NULL, &key); if (ret) @@ -2021,6 +2054,8 @@ static BOOL CRYPT_VerifyCertSignatureFromPublicKeyInfo(HCRYPTPROV_LEGACY hCryptP } CryptDestroyKey(key); } + if (releaseProv) + CryptReleaseContext(hCryptProv, 0); return ret; } diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index 46d4797b68..f6fe119457 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -123,6 +123,8 @@ BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded, */ HCRYPTPROV CRYPT_GetDefaultProvider(void); +HCRYPTPROV CRYPT_GetProvForAlgId(ALG_ID algID); + HINSTANCE hInstance; void crypt_oid_init(void); diff --git a/dlls/crypt32/main.c b/dlls/crypt32/main.c index d93163c193..c38dd52790 100644 --- a/dlls/crypt32/main.c +++ b/dlls/crypt32/main.c @@ -74,6 +74,77 @@ HCRYPTPROV CRYPT_GetDefaultProvider(void) return hDefProv; } +static CRITICAL_SECTION prov_param_cs; +static CRITICAL_SECTION_DEBUG prov_param_cs_debug = +{ + 0, 0, &prov_param_cs, + { &prov_param_cs_debug.ProcessLocksList, + &prov_param_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": prov_param_cs") } +}; +static CRITICAL_SECTION prov_param_cs = { &prov_param_cs_debug, -1, 0, 0, 0, 0 }; + +static BOOL CRYPT_AlgIsSupported(HCRYPTPROV hProv, ALG_ID algID) +{ + PROV_ENUMALGS provEnumalgs; + DWORD size = sizeof(provEnumalgs); + + /* This enumeration is not thread safe */ + EnterCriticalSection(&prov_param_cs); + if (CryptGetProvParam(hProv, PP_ENUMALGS, (BYTE *)&provEnumalgs, &size, + CRYPT_FIRST)) + { + do { + if (algID == provEnumalgs.aiAlgid) + return TRUE; + } while (CryptGetProvParam(hProv, PP_ENUMALGS, (BYTE *)&provEnumalgs, + &size, CRYPT_NEXT)); + } + LeaveCriticalSection(&prov_param_cs); + return FALSE; +} + +HCRYPTPROV CRYPT_GetProvForAlgId(ALG_ID algID) +{ + LPWSTR provName; + HCRYPTPROV prov; + DWORD i = 0, type, nameSize; + + if (CRYPT_AlgIsSupported(hDefProv, algID)) + { + CryptContextAddRef(hDefProv, NULL, 0); + return hDefProv; + } + + while (CryptEnumProvidersW(i, NULL, 0, &type, NULL, &nameSize)) + { + provName = CryptMemAlloc(nameSize); + if (!provName) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + if (!CryptEnumProvidersW(i, NULL, 0, &type, provName, &nameSize)) + { + CryptMemFree(provName); + return 0; + } + if (!CryptAcquireContextW(&prov, NULL, provName, type, + CRYPT_VERIFYCONTEXT)) + { + CryptMemFree(provName); + return 0; + } + CryptMemFree(provName); + if (CRYPT_AlgIsSupported(prov, algID)) + return prov; + CryptReleaseContext(prov, 0); + ++i; + } + SetLastError(NTE_BAD_ALGID); + return 0; +} + typedef void * HLRUCACHE; /* this function is called by Internet Explorer when it is about to verify a diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index bb89ae6b1a..8851de28dc 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -550,71 +550,6 @@ static BOOL CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, return ret; } -static CRITICAL_SECTION prov_param_cs; -static CRITICAL_SECTION_DEBUG prov_param_cs_debug = -{ - 0, 0, &prov_param_cs, - { &prov_param_cs_debug.ProcessLocksList, - &prov_param_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": prov_param_cs") } -}; -static CRITICAL_SECTION prov_param_cs = { &prov_param_cs_debug, -1, 0, 0, 0, 0 }; - -static BOOL CRYPT_AlgIsSupported(HCRYPTPROV hProv, ALG_ID algID) -{ - PROV_ENUMALGS provEnumalgs; - DWORD size = sizeof(provEnumalgs); - - /* This enumeration is not thread safe */ - EnterCriticalSection(&prov_param_cs); - if (CryptGetProvParam(hProv, PP_ENUMALGS, (BYTE *)&provEnumalgs, &size, - CRYPT_FIRST)) - { - do { - if (algID == provEnumalgs.aiAlgid) - return TRUE; - } while (CryptGetProvParam(hProv, PP_ENUMALGS, (BYTE *)&provEnumalgs, - &size, CRYPT_NEXT)); - } - LeaveCriticalSection(&prov_param_cs); - return FALSE; -} - -static HCRYPTPROV CRYPT_GetProvForAlgId(ALG_ID algID) -{ - LPWSTR provName; - HCRYPTPROV prov; - DWORD i = 0, type, nameSize; - - while (CryptEnumProvidersW(i, NULL, 0, &type, NULL, &nameSize)) - { - provName = CryptMemAlloc(nameSize); - if (!provName) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - if (!CryptEnumProvidersW(i, NULL, 0, &type, provName, &nameSize)) - { - CryptMemFree(provName); - return 0; - } - if (!CryptAcquireContextW(&prov, NULL, provName, type, - CRYPT_VERIFYCONTEXT)) - { - CryptMemFree(provName); - return 0; - } - CryptMemFree(provName); - if (CRYPT_AlgIsSupported(prov, algID)) - return prov; - CryptReleaseContext(prov, 0); - ++i; - } - SetLastError(NTE_BAD_ALGID); - return 0; -} - static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo) {