[Wine-patches] [eter-1.0.12 3/3] crypt32: Find a provider for used algorithm (eterbug #5665).

Alexander Morozov amorozov на etersoft.ru
Чт Июн 24 17:50:54 MSD 2010


----------- следующая часть -----------
From 282037871a29ae439a121c380abf264c721c5dad Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Thu, 24 Jun 2010 15:44:32 +0400
Subject: [eter-1.0.12 3/3] crypt32: Find a provider for used algorithm (eterbug #5665).

---
 dlls/crypt32/cert.c            |   67 ++++++++++++++++++++++++++++---------
 dlls/crypt32/crypt32_private.h |    2 +
 dlls/crypt32/main.c            |   71 ++++++++++++++++++++++++++++++++++++++++
 dlls/crypt32/msg.c             |   65 ------------------------------------
 4 files changed, 124 insertions(+), 81 deletions(-)

diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c
index 2780cba..9e25413 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 46d4797..f6fe119 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 d93163c..c38dd52 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 bb89ae6..8851de2 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