crypt32: Avoid repeatedly decoding authority key id extensions when searching for...
authorJuan Lang <juan.lang@gmail.com>
Thu, 15 Oct 2009 18:14:23 +0000 (11:14 -0700)
committerAlexandre Julliard <julliard@winehq.org>
Mon, 19 Oct 2009 09:35:46 +0000 (11:35 +0200)
dlls/crypt32/cert.c

index 618c578b7317858f65705f87d19f845825e7ec31..281f55f7598b5f425f5cdb0dfc0f542243a080fd 100644 (file)
@@ -1261,11 +1261,70 @@ static BOOL compare_cert_by_cert_id(PCCERT_CONTEXT pCertContext, DWORD dwType,
     return ret;
 }
 
-static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType,
+static BOOL compare_existing_cert(PCCERT_CONTEXT pCertContext, DWORD dwType,
+ DWORD dwFlags, const void *pvPara)
+{
+    PCCERT_CONTEXT toCompare = pvPara;
+    return CertCompareCertificate(pCertContext->dwCertEncodingType,
+     pCertContext->pCertInfo, toCompare->pCertInfo);
+}
+
+static BOOL compare_cert_by_signature_hash(PCCERT_CONTEXT pCertContext, DWORD dwType,
  DWORD dwFlags, const void *pvPara)
 {
-    BOOL ret = FALSE;
-    PCCERT_CONTEXT subject = pvPara;
+    const CRYPT_HASH_BLOB *hash = pvPara;
+    DWORD size = 0;
+    BOOL ret;
+
+    ret = CertGetCertificateContextProperty(pCertContext,
+     CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
+    if (ret && size == hash->cbData)
+    {
+        LPBYTE buf = CryptMemAlloc(size);
+
+        if (buf)
+        {
+            CertGetCertificateContextProperty(pCertContext,
+             CERT_SIGNATURE_HASH_PROP_ID, buf, &size);
+            ret = !memcmp(buf, hash->pbData, size);
+            CryptMemFree(buf);
+        }
+    }
+    else
+        ret = FALSE;
+    return ret;
+}
+
+static inline PCCERT_CONTEXT cert_compare_certs_in_store(HCERTSTORE store,
+ PCCERT_CONTEXT prev, CertCompareFunc compare, DWORD dwType, DWORD dwFlags,
+ const void *pvPara)
+{
+    BOOL matches = FALSE;
+    PCCERT_CONTEXT ret;
+
+    ret = prev;
+    do {
+        ret = CertEnumCertificatesInStore(store, ret);
+        if (ret)
+            matches = compare(ret, dwType, dwFlags, pvPara);
+    } while (ret != NULL && !matches);
+    return ret;
+}
+
+typedef PCCERT_CONTEXT (*CertFindFunc)(HCERTSTORE store, DWORD dwType,
+ DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev);
+
+static PCCERT_CONTEXT find_cert_any(HCERTSTORE store, DWORD dwType,
+ DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev)
+{
+    return CertEnumCertificatesInStore(store, prev);
+}
+
+static PCCERT_CONTEXT find_cert_by_issuer(HCERTSTORE store, DWORD dwType,
+ DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev)
+{
+    BOOL ret;
+    PCCERT_CONTEXT found = NULL, subject = pvPara;
     PCERT_EXTENSION ext;
     DWORD size;
 
@@ -1289,18 +1348,17 @@ static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType,
                  sizeof(CERT_NAME_BLOB));
                 memcpy(&id.u.IssuerSerialNumber.SerialNumber,
                  &info->CertSerialNumber, sizeof(CRYPT_INTEGER_BLOB));
-                ret = compare_cert_by_cert_id(pCertContext, dwType, dwFlags,
-                 &id);
             }
             else if (info->KeyId.cbData)
             {
                 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
                 memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
-                ret = compare_cert_by_cert_id(pCertContext, dwType, dwFlags,
-                 &id);
             }
             else
                 ret = FALSE;
+            if (ret)
+                found = cert_compare_certs_in_store(store, prev,
+                 compare_cert_by_cert_id, dwType, dwFlags, &id);
             LocalFree(info);
         }
     }
@@ -1337,8 +1395,6 @@ static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType,
                     memcpy(&id.u.IssuerSerialNumber.SerialNumber,
                      &info->AuthorityCertSerialNumber,
                      sizeof(CRYPT_INTEGER_BLOB));
-                    ret = compare_cert_by_cert_id(pCertContext, dwType, dwFlags,
-                     &id);
                 }
                 else
                 {
@@ -1350,78 +1406,20 @@ static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType,
             {
                 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
                 memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
-                ret = compare_cert_by_cert_id(pCertContext, dwType, dwFlags,
-                 &id);
             }
             else
                 ret = FALSE;
+            if (ret)
+                found = cert_compare_certs_in_store(store, prev,
+                 compare_cert_by_cert_id, dwType, dwFlags, &id);
             LocalFree(info);
         }
     }
     else
-       ret = compare_cert_by_name(pCertContext,
-        CERT_COMPARE_NAME | CERT_COMPARE_SUBJECT_CERT, dwFlags,
-        &subject->pCertInfo->Issuer);
-    return ret;
-}
-
-static BOOL compare_existing_cert(PCCERT_CONTEXT pCertContext, DWORD dwType,
- DWORD dwFlags, const void *pvPara)
-{
-    PCCERT_CONTEXT toCompare = pvPara;
-    return CertCompareCertificate(pCertContext->dwCertEncodingType,
-     pCertContext->pCertInfo, toCompare->pCertInfo);
-}
-
-static BOOL compare_cert_by_signature_hash(PCCERT_CONTEXT pCertContext, DWORD dwType,
- DWORD dwFlags, const void *pvPara)
-{
-    const CRYPT_HASH_BLOB *hash = pvPara;
-    DWORD size = 0;
-    BOOL ret;
-
-    ret = CertGetCertificateContextProperty(pCertContext,
-     CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
-    if (ret && size == hash->cbData)
-    {
-        LPBYTE buf = CryptMemAlloc(size);
-
-        if (buf)
-        {
-            CertGetCertificateContextProperty(pCertContext,
-             CERT_SIGNATURE_HASH_PROP_ID, buf, &size);
-            ret = !memcmp(buf, hash->pbData, size);
-            CryptMemFree(buf);
-        }
-    }
-    else
-        ret = FALSE;
-    return ret;
-}
-
-static inline PCCERT_CONTEXT cert_compare_certs_in_store(HCERTSTORE store,
- PCCERT_CONTEXT prev, CertCompareFunc compare, DWORD dwType, DWORD dwFlags,
- const void *pvPara)
-{
-    BOOL matches = FALSE;
-    PCCERT_CONTEXT ret;
-
-    ret = prev;
-    do {
-        ret = CertEnumCertificatesInStore(store, ret);
-        if (ret)
-            matches = compare(ret, dwType, dwFlags, pvPara);
-    } while (ret != NULL && !matches);
-    return ret;
-}
-
-typedef PCCERT_CONTEXT (*CertFindFunc)(HCERTSTORE store, DWORD dwType,
- DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev);
-
-static PCCERT_CONTEXT find_cert_any(HCERTSTORE store, DWORD dwType,
- DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev)
-{
-    return CertEnumCertificatesInStore(store, prev);
+       found = cert_compare_certs_in_store(store, prev,
+        compare_cert_by_name, CERT_COMPARE_NAME | CERT_COMPARE_SUBJECT_CERT,
+        dwFlags, &subject->pCertInfo->Issuer);
+    return found;
 }
 
 PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
@@ -1459,7 +1457,7 @@ PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
         compare = compare_cert_by_cert_id;
         break;
     case CERT_COMPARE_ISSUER_OF:
-        compare = compare_cert_by_issuer;
+        find = find_cert_by_issuer;
         break;
     case CERT_COMPARE_EXISTING:
         compare = compare_existing_cert;