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, ...@@ -1261,11 +1261,70 @@ static BOOL compare_cert_by_cert_id(PCCERT_CONTEXT pCertContext, DWORD dwType,
return ret; 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) DWORD dwFlags, const void *pvPara)
{ {
BOOL ret = FALSE; const CRYPT_HASH_BLOB *hash = pvPara;
PCCERT_CONTEXT subject = 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; PCERT_EXTENSION ext;
DWORD size; DWORD size;
...@@ -1289,18 +1348,17 @@ static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType, ...@@ -1289,18 +1348,17 @@ static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType,
sizeof(CERT_NAME_BLOB)); sizeof(CERT_NAME_BLOB));
memcpy(&id.u.IssuerSerialNumber.SerialNumber, memcpy(&id.u.IssuerSerialNumber.SerialNumber,
&info->CertSerialNumber, sizeof(CRYPT_INTEGER_BLOB)); &info->CertSerialNumber, sizeof(CRYPT_INTEGER_BLOB));
ret = compare_cert_by_cert_id(pCertContext, dwType, dwFlags,
&id);
} }
else if (info->KeyId.cbData) else if (info->KeyId.cbData)
{ {
id.dwIdChoice = CERT_ID_KEY_IDENTIFIER; id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB)); memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
ret = compare_cert_by_cert_id(pCertContext, dwType, dwFlags,
&id);
} }
else else
ret = FALSE; ret = FALSE;
if (ret)
found = cert_compare_certs_in_store(store, prev,
compare_cert_by_cert_id, dwType, dwFlags, &id);
LocalFree(info); LocalFree(info);
} }
} }
...@@ -1337,8 +1395,6 @@ static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType, ...@@ -1337,8 +1395,6 @@ static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType,
memcpy(&id.u.IssuerSerialNumber.SerialNumber, memcpy(&id.u.IssuerSerialNumber.SerialNumber,
&info->AuthorityCertSerialNumber, &info->AuthorityCertSerialNumber,
sizeof(CRYPT_INTEGER_BLOB)); sizeof(CRYPT_INTEGER_BLOB));
ret = compare_cert_by_cert_id(pCertContext, dwType, dwFlags,
&id);
} }
else else
{ {
...@@ -1350,78 +1406,20 @@ static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType, ...@@ -1350,78 +1406,20 @@ static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext, DWORD dwType,
{ {
id.dwIdChoice = CERT_ID_KEY_IDENTIFIER; id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB)); memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
ret = compare_cert_by_cert_id(pCertContext, dwType, dwFlags,
&id);
} }
else else
ret = FALSE; ret = FALSE;
if (ret)
found = cert_compare_certs_in_store(store, prev,
compare_cert_by_cert_id, dwType, dwFlags, &id);
LocalFree(info); LocalFree(info);
} }
} }
else else
ret = compare_cert_by_name(pCertContext, found = cert_compare_certs_in_store(store, prev,
CERT_COMPARE_NAME | CERT_COMPARE_SUBJECT_CERT, dwFlags, compare_cert_by_name, CERT_COMPARE_NAME | CERT_COMPARE_SUBJECT_CERT,
&subject->pCertInfo->Issuer); dwFlags, &subject->pCertInfo->Issuer);
return ret; return found;
}
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);
} }
PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
...@@ -1459,7 +1457,7 @@ PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore, ...@@ -1459,7 +1457,7 @@ PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
compare = compare_cert_by_cert_id; compare = compare_cert_by_cert_id;
break; break;
case CERT_COMPARE_ISSUER_OF: case CERT_COMPARE_ISSUER_OF:
compare = compare_cert_by_issuer; find = find_cert_by_issuer;
break; break;
case CERT_COMPARE_EXISTING: case CERT_COMPARE_EXISTING:
compare = compare_existing_cert; 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