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