Commit 3740e415 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: Avoid repeatedly decoding authority key id extensions when searching for a cert's issuer.

parent b2d27097
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment