[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