Zebediah Figura : crypt32: Copy the CRL_INFO structure instead of recalculating it.

Alexandre Julliard julliard at winehq.org
Wed Jul 21 16:04:31 CDT 2021


Module: wine
Branch: master
Commit: bdcddf024ff36a731acfd8a2086af1f34a21cc7d
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=bdcddf024ff36a731acfd8a2086af1f34a21cc7d

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Thu Jul 15 11:25:17 2021 -0500

crypt32: Copy the CRL_INFO structure instead of recalculating it.

Steam calls CertGetCertificateChain() on a certificate with a 20 MB CRL, which
can take over 400 ms to parse each time. Avoid parsing it more often than we
need to.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/crypt32/crl.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 104 insertions(+), 7 deletions(-)

diff --git a/dlls/crypt32/crl.c b/dlls/crypt32/crl.c
index 4dc77c2a246..657810e0c6b 100644
--- a/dlls/crypt32/crl.c
+++ b/dlls/crypt32/crl.c
@@ -38,6 +38,108 @@ static void CRL_free(context_t *context)
 
 static const context_vtbl_t crl_vtbl;
 
+static char *copy_string(char *p, char **dst, const char *src)
+{
+    size_t size = strlen(src) + 1;
+
+    *dst = memcpy(p, src, size);
+    return p + size;
+}
+
+static char *copy_blob(char *p, DATA_BLOB *dst, const DATA_BLOB *src)
+{
+    size_t size = src->cbData;
+
+    dst->cbData = size;
+    dst->pbData = memcpy(p, src->pbData, size);
+    return p + size;
+}
+
+static char *copy_extension(char *p, CERT_EXTENSION *dst, const CERT_EXTENSION *src)
+{
+    p = copy_string(p, &dst->pszObjId, src->pszObjId);
+    dst->fCritical = src->fCritical;
+    return copy_blob(p, &dst->Value, &src->Value);
+}
+
+static CRL_INFO *clone_crl_info(const CRL_INFO *src)
+{
+    size_t size = sizeof(CRL_INFO);
+    CRL_INFO *dst;
+    DWORD i, j;
+    char *p;
+
+    if (src->SignatureAlgorithm.pszObjId)
+        size += strlen(src->SignatureAlgorithm.pszObjId) + 1;
+    size += src->SignatureAlgorithm.Parameters.cbData;
+    size += src->Issuer.cbData;
+    for (i = 0; i < src->cCRLEntry; ++i)
+    {
+        const CRL_ENTRY *entry = &src->rgCRLEntry[i];
+
+        size += sizeof(CRL_ENTRY);
+        size += entry->SerialNumber.cbData;
+        for (j = 0; j < entry->cExtension; ++j)
+        {
+            const CERT_EXTENSION *ext = &entry->rgExtension[j];
+
+            size += sizeof(CERT_EXTENSION);
+            size += strlen(ext->pszObjId) + 1;
+            size += ext->Value.cbData;
+        }
+    }
+
+    for (j = 0; j < src->cExtension; ++j)
+    {
+        const CERT_EXTENSION *ext = &src->rgExtension[j];
+
+        size += sizeof(CERT_EXTENSION);
+        size += strlen(ext->pszObjId) + 1;
+        size += ext->Value.cbData;
+    }
+
+    if (!(dst = LocalAlloc(LPTR, size)))
+        return NULL;
+    p = (char *)(dst + 1);
+
+    dst->dwVersion = src->dwVersion;
+    if (src->SignatureAlgorithm.pszObjId)
+        p = copy_string(p, &dst->SignatureAlgorithm.pszObjId, src->SignatureAlgorithm.pszObjId);
+    p = copy_blob(p, &dst->SignatureAlgorithm.Parameters, &src->SignatureAlgorithm.Parameters);
+    p = copy_blob(p, &dst->Issuer, &src->Issuer);
+    dst->ThisUpdate = src->ThisUpdate;
+    dst->NextUpdate = src->NextUpdate;
+
+    dst->cCRLEntry = src->cCRLEntry;
+    dst->rgCRLEntry = (CRL_ENTRY *)p;
+    p += src->cCRLEntry * sizeof(CRL_ENTRY);
+
+    dst->cExtension = src->cExtension;
+    dst->rgExtension = (CERT_EXTENSION *)p;
+    p += src->cExtension * sizeof(CERT_EXTENSION);
+
+    for (i = 0; i < src->cCRLEntry; ++i)
+    {
+        const CRL_ENTRY *src_entry = &src->rgCRLEntry[i];
+        CRL_ENTRY *dst_entry = &dst->rgCRLEntry[i];
+
+        p = copy_blob(p, &dst_entry->SerialNumber, &src_entry->SerialNumber);
+        dst_entry->RevocationDate = src_entry->RevocationDate;
+        dst_entry->cExtension = src_entry->cExtension;
+        dst_entry->rgExtension = (CERT_EXTENSION *)p;
+        p += src_entry->cExtension * sizeof(CERT_EXTENSION);
+
+        for (j = 0; j < src_entry->cExtension; ++j)
+            p = copy_extension(p, &dst_entry->rgExtension[j], &src_entry->rgExtension[j]);
+    }
+
+    for (j = 0; j < src->cExtension; ++j)
+        p = copy_extension(p, &dst->rgExtension[j], &src->rgExtension[j]);
+
+    assert(p - (char *)dst == size);
+    return dst;
+}
+
 static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link)
 {
     crl_t *dst;
@@ -47,8 +149,6 @@ static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL
             return NULL;
     }else {
         const crl_t *src = (const crl_t*)context;
-        DWORD size = 0;
-        BOOL res;
 
         if (!(dst = (crl_t *)Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, store)))
             return NULL;
@@ -60,11 +160,8 @@ static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL
         memcpy(dst->ctx.pbCrlEncoded, src->ctx.pbCrlEncoded, src->ctx.cbCrlEncoded);
         dst->ctx.cbCrlEncoded = src->ctx.cbCrlEncoded;
 
-        /* FIXME: We don't need to decode the object here, we could just clone dst info. */
-        res = CryptDecodeObjectEx(dst->ctx.dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED,
-                dst->ctx.pbCrlEncoded, dst->ctx.cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
-                &dst->ctx.pCrlInfo, &size);
-        if(!res) {
+        if (!(dst->ctx.pCrlInfo = clone_crl_info(src->ctx.pCrlInfo)))
+        {
             CertFreeCRLContext(&dst->ctx);
             return NULL;
         }




More information about the wine-cvs mailing list