[Wine-patches] [eterhack 3/3] crypt32: Find a provider for used algorithm (eterbug #5665).
Alexander Morozov
amorozov на etersoft.ru
Чт Июн 24 17:48:00 MSD 2010
----------- следующая часть -----------
From 3eb6a4447b320199bdde33cb8466ace372cd4e87 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Thu, 24 Jun 2010 15:44:32 +0400
Subject: [eterhack 3/3] crypt32: Find a provider for used algorithm (eterbug #5665).
---
dlls/crypt32/cert.c | 71 +++++++++++++++++++++++++++++----------
dlls/crypt32/crypt32_private.h | 2 +
dlls/crypt32/main.c | 71 ++++++++++++++++++++++++++++++++++++++++
dlls/crypt32/msg.c | 65 ------------------------------------
4 files changed, 126 insertions(+), 83 deletions(-)
diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c
index 12c013e..0346e04 100644
--- a/dlls/crypt32/cert.c
+++ b/dlls/crypt32/cert.c
@@ -1963,16 +1963,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);
@@ -1985,6 +1989,8 @@ BOOL WINAPI CryptHashCertificate(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid,
CryptDestroyHash(hHash);
}
}
+ if (releaseProv)
+ CryptReleaseContext(hCryptProv, 0);
return ret;
}
@@ -1992,21 +1998,25 @@ 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 ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
{
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
+ if (!Algid)
+ Algid = CALG_MD5;
+ if (!hCryptProv)
+ {
+ hCryptProv = CRYPT_GetProvForAlgId(Algid);
+ if (!hCryptProv) return FALSE;
+ releaseProv = TRUE;
+ }
if (ret)
{
BYTE *buf;
@@ -2029,6 +2039,8 @@ BOOL WINAPI CryptHashPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid,
LocalFree(buf);
}
}
+ if (releaseProv)
+ CryptReleaseContext(hCryptProv, 0);
return ret;
}
@@ -2036,7 +2048,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;
@@ -2050,8 +2062,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)
@@ -2061,7 +2071,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,
@@ -2071,6 +2090,8 @@ BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv,
pcbComputedHash, 0);
CryptDestroyHash(hHash);
}
+ if (releaseProv)
+ CryptReleaseContext(hCryptProv, 0);
}
LocalFree(info);
}
@@ -2082,7 +2103,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;
@@ -2100,8 +2121,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,
@@ -2111,6 +2139,8 @@ BOOL WINAPI CryptSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
pcbSignature, 0);
CryptDestroyHash(hHash);
}
+ if (releaseProv)
+ CryptReleaseContext(hCryptProv, 0);
}
else
{
@@ -2210,7 +2240,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;
@@ -2227,9 +2257,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)
@@ -2248,6 +2281,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 8385bf5..4fdb7e2 100644
--- a/dlls/crypt32/crypt32_private.h
+++ b/dlls/crypt32/crypt32_private.h
@@ -127,6 +127,8 @@ BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,
*/
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 db9dc1a..d876d17 100644
--- a/dlls/crypt32/main.c
+++ b/dlls/crypt32/main.c
@@ -75,6 +75,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 48b4c08..7ae579a 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)
{
--
1.6.5.8
Подробная информация о списке рассылки Wine-patches