From 51948b0c980e6f7a9e2725958c16f8c712bfcc69 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Thu, 30 Aug 2007 17:58:36 -0700 Subject: [PATCH] crypt32: Check time of each element in chain against requested time. --- dlls/crypt32/chain.c | 69 +++++++++++++++++++++++++------------- dlls/crypt32/tests/chain.c | 10 +++--- 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c index 58f3806f16f..4372a8d2379 100644 --- a/dlls/crypt32/chain.c +++ b/dlls/crypt32/chain.c @@ -296,7 +296,6 @@ static BOOL CRYPT_AddCertToSimpleChain(PCertificateChainEngine engine, if (dwFlags & CERT_STORE_SIGNATURE_FLAG) element->TrustStatus.dwErrorStatus |= CERT_TRUST_IS_NOT_SIGNATURE_VALID; - /* FIXME: check valid usages and name constraints */ /* FIXME: initialize the rest of element */ chain->rgpElement[chain->cElement++] = element; if (chain->cElement % engine->CycleDetectionModulus) @@ -341,6 +340,50 @@ static void CRYPT_CheckTrustedStatus(HCERTSTORE hRoot, CertFreeCertificateContext(trustedRoot); } +static BOOL CRYPT_CheckRootCert(HCERTCHAINENGINE hRoot, + PCERT_CHAIN_ELEMENT rootElement) +{ + PCCERT_CONTEXT root = rootElement->pCertContext; + BOOL ret; + + if (!(ret = CryptVerifyCertificateSignatureEx(0, root->dwCertEncodingType, + CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, (void *)root, + CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)root, 0, NULL))) + { + TRACE("Last certificate's signature is invalid\n"); + rootElement->TrustStatus.dwErrorStatus |= + CERT_TRUST_IS_NOT_SIGNATURE_VALID; + } + CRYPT_CheckTrustedStatus(hRoot, rootElement); + return ret; +} + +static BOOL CRYPT_CheckSimpleChain(PCertificateChainEngine engine, + PCERT_SIMPLE_CHAIN chain, LPFILETIME time) +{ + PCERT_CHAIN_ELEMENT rootElement = chain->rgpElement[chain->cElement - 1]; + DWORD i; + BOOL ret = TRUE; + + for (i = 0; i < chain->cElement; i++) + { + if (CertVerifyTimeValidity(time, + chain->rgpElement[i]->pCertContext->pCertInfo) != 0) + chain->rgpElement[i]->TrustStatus.dwErrorStatus |= + CERT_TRUST_IS_NOT_TIME_VALID; + /* FIXME: check valid usages and name constraints */ + CRYPT_CombineTrustStatus(&chain->TrustStatus, + &chain->rgpElement[i]->TrustStatus); + } + if (CRYPT_IsCertificateSelfSigned(rootElement->pCertContext)) + { + rootElement->TrustStatus.dwInfoStatus |= CERT_TRUST_IS_SELF_SIGNED; + ret = CRYPT_CheckRootCert(engine->hRoot, rootElement); + } + CRYPT_CombineTrustStatus(&chain->TrustStatus, &rootElement->TrustStatus); + return ret; +} + static BOOL CRYPT_BuildSimpleChain(HCERTCHAINENGINE hChainEngine, PCCERT_CONTEXT cert, LPFILETIME pTime, HCERTSTORE hAdditionalStore, PCERT_SIMPLE_CHAIN *ppChain) @@ -384,29 +427,7 @@ static BOOL CRYPT_BuildSimpleChain(HCERTCHAINENGINE hChainEngine, } } if (ret) - { - PCERT_CHAIN_ELEMENT rootElement = - chain->rgpElement[chain->cElement - 1]; - PCCERT_CONTEXT root = rootElement->pCertContext; - - if (CRYPT_IsCertificateSelfSigned(root)) - { - rootElement->TrustStatus.dwInfoStatus |= - CERT_TRUST_IS_SELF_SIGNED; - if (!(ret = CryptVerifyCertificateSignatureEx(0, - root->dwCertEncodingType, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, - (void *)root, CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)root, - 0, NULL))) - { - TRACE("Last certificate's signature is invalid\n"); - rootElement->TrustStatus.dwErrorStatus |= - CERT_TRUST_IS_NOT_SIGNATURE_VALID; - } - CRYPT_CheckTrustedStatus(engine->hRoot, rootElement); - } - CRYPT_CombineTrustStatus(&chain->TrustStatus, - &rootElement->TrustStatus); - } + ret = CRYPT_CheckSimpleChain(engine, chain, pTime); if (!ret) { CRYPT_FreeSimpleChain(chain); diff --git a/dlls/crypt32/tests/chain.c b/dlls/crypt32/tests/chain.c index 565cf50c868..507ab24519a 100644 --- a/dlls/crypt32/tests/chain.c +++ b/dlls/crypt32/tests/chain.c @@ -1485,7 +1485,7 @@ static ChainCheck chainCheck[] = { { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_TIME_VALID, 0 }, 1, simpleStatus0 }, - TODO_ERROR | TODO_INFO }, + TODO_INFO }, { { sizeof(chain1) / sizeof(chain1[0]), chain1 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_SIGNATURE_VALID | @@ -1496,7 +1496,7 @@ static ChainCheck chainCheck[] = { { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_TIME_VALID, 0 }, 1, simpleStatus2 }, - TODO_ERROR | TODO_INFO }, + TODO_INFO }, { { sizeof(chain3) / sizeof(chain3[0]), chain3 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_UNTRUSTED_ROOT | @@ -1518,11 +1518,11 @@ static ChainCheck chainCheck[] = { { { sizeof(chain6) / sizeof(chain6[0]), chain6 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus6 }, - TODO_ERROR | TODO_INFO }, + TODO_INFO }, { { sizeof(chain7) / sizeof(chain7[0]), chain7 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus7 }, - TODO_ERROR | TODO_INFO }, + TODO_INFO }, { { sizeof(chain8) / sizeof(chain8[0]), chain8 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_UNTRUSTED_ROOT | @@ -1547,7 +1547,7 @@ static ChainCheck chainCheck[] = { { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_NOT_TIME_VALID | CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, selfSignedSimpleStatus }, - TODO_ERROR | TODO_INFO }, + TODO_INFO }, /* The iTunes chain may or may not have its root trusted, so ignore the * error */