windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/pkitrust/wintrust/certtrst.cpp
2020-09-26 16:20:57 +08:00

700 lines
23 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: certtrst.cpp
//
// Contents: Microsoft Internet Security Provider
//
// Functions: WintrustCertificateTrust
//
// *** local functions ***
// _WalkChain
// _IsLifetimeSigningCert
//
// History: 07-Jun-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
//
// support for MS test roots!!!!
//
static BYTE rgbTestRoot[] =
{
# include "certs\\mstest1.h"
};
static BYTE rgbTestRootCorrected[] =
{
# include "certs\\mstest2.h"
};
static BYTE rgbTestRootBeta1[] =
{
# include "certs\\mstestb1.h"
};
#define NTESTROOTS 3
static CERT_PUBLIC_KEY_INFO rgTestRootPublicKeyInfo[NTESTROOTS] =
{
{szOID_RSA_RSA, 0, NULL, sizeof(rgbTestRoot), rgbTestRoot, 0},
{szOID_RSA_RSA, 0, NULL, sizeof(rgbTestRootCorrected), rgbTestRootCorrected, 0},
{szOID_RSA_RSA, 0, NULL, sizeof(rgbTestRootBeta1), rgbTestRootBeta1, 0}
};
BOOL _WalkChain(
CRYPT_PROVIDER_DATA *pProvData,
DWORD idxSigner,
DWORD *pdwError,
BOOL fCounterSigner,
DWORD idxCounterSigner,
BOOL fTimeStamped,
BOOL *pfLifetimeSigning // IN OUT, only accessed for fTimeStamped
);
BOOL WINAPI _IsLifetimeSigningCert(
PCCERT_CONTEXT pCertContext
);
HRESULT WINAPI WintrustCertificateTrust(CRYPT_PROVIDER_DATA *pProvData)
{
if ((_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, fRecallWithState)) &&
(pProvData->fRecallWithState == TRUE))
{
return(S_OK);
}
DWORD dwError;
dwError = S_OK;
if (pProvData->csSigners < 1)
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = TRUST_E_NOSIGNATURE;
return(S_FALSE);
}
//
// loop through all signers
//
for (int i = 0; i < (int)pProvData->csSigners; i++)
{
BOOL fTimeStamped = FALSE;
BOOL fLifetimeSigning = FALSE;
if (pProvData->pasSigners[i].csCertChain < 1)
{
pProvData->pasSigners[i].dwError = TRUST_E_NO_SIGNER_CERT;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = TRUST_E_NO_SIGNER_CERT;
continue;
}
// Check if timestamped.
if (0 < pProvData->pasSigners[i].csCounterSigners &&
(pProvData->pasSigners[i].pasCounterSigners[0].dwSignerType &
SGNR_TYPE_TIMESTAMP))
{
fTimeStamped = TRUE;
// See if LifeTime Signing has been enabled
if (pProvData->dwProvFlags & WTD_LIFETIME_SIGNING_FLAG)
{
fLifetimeSigning = TRUE;
}
else
{
// Check if the signer certificate has the LIFETIME_SIGNING
// EKU.
fLifetimeSigning = _IsLifetimeSigningCert(
pProvData->pasSigners[i].pasCertChain[0].pCert);
}
}
_WalkChain(pProvData, i, &dwError, FALSE, 0,
fTimeStamped, &fLifetimeSigning);
for (int i2 = 0; i2 < (int)pProvData->pasSigners[i].csCounterSigners; i2++)
{
if (pProvData->pasSigners[i].pasCounterSigners[i2].csCertChain < 1)
{
pProvData->pasSigners[i].pasCounterSigners[i2].dwError = TRUST_E_NO_SIGNER_CERT;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = TRUST_E_COUNTER_SIGNER;
dwError = S_FALSE;
continue;
}
// If lifetime signing has been enabled, use current time instead
// of timestamp time.
if (fLifetimeSigning)
{
memcpy(&pProvData->pasSigners[i].pasCounterSigners[i2].sftVerifyAsOf,
&pProvData->sftSystemTime, sizeof(FILETIME));
}
_WalkChain(pProvData, i, &dwError, TRUE, i2, FALSE, NULL);
}
}
return(dwError);
}
HCERTCHAINENGINE GetChainEngine(
IN CRYPT_PROVIDER_DATA *pProvData
)
{
CERT_CHAIN_ENGINE_CONFIG Config;
HCERTSTORE hStore = NULL;
HCERTCHAINENGINE hChainEngine = NULL;
if (NULL == pProvData->pWintrustData ||
pProvData->pWintrustData->dwUnionChoice != WTD_CHOICE_CERT ||
!_ISINSTRUCT(WINTRUST_CERT_INFO,
pProvData->pWintrustData->pCert->cbStruct, dwFlags) ||
0 == (pProvData->pWintrustData->pCert->dwFlags &
(WTCI_DONT_OPEN_STORES | WTCI_OPEN_ONLY_ROOT)))
return NULL;
memset(&Config, 0, sizeof(Config));
Config.cbSize = sizeof(Config);
if (NULL == (hStore = CertOpenStore(
CERT_STORE_PROV_MEMORY,
0, // dwEncodingType
0, // hCryptProv
0, // dwFlags
NULL // pvPara
)))
goto OpenMemoryStoreError;
if (pProvData->pWintrustData->pCert->dwFlags & WTCI_DONT_OPEN_STORES)
Config.hRestrictedRoot = hStore;
Config.hRestrictedTrust = hStore;
Config.hRestrictedOther = hStore;
if (!CertCreateCertificateChainEngine(
&Config,
&hChainEngine
))
goto CreateChainEngineError;
CommonReturn:
CertCloseStore(hStore, 0);
return hChainEngine;
ErrorReturn:
hChainEngine = NULL;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS, OpenMemoryStoreError)
TRACE_ERROR_EX(DBG_SS, CreateChainEngineError)
}
HCERTSTORE GetChainAdditionalStore(
IN CRYPT_PROVIDER_DATA *pProvData
)
{
HCERTSTORE hStore = NULL;
if (0 == pProvData->chStores)
return NULL;
if (1 < pProvData->chStores) {
if (hStore = CertOpenStore(
CERT_STORE_PROV_COLLECTION,
0, // dwEncodingType
0, // hCryptProv
0, // dwFlags
NULL // pvPara
)) {
DWORD i;
for (i = 0; i < pProvData->chStores; i++)
CertAddStoreToCollection(
hStore,
pProvData->pahStores[i],
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
0 // dwPriority
);
}
} else
hStore = CertDuplicateStore(pProvData->pahStores[0]);
#if 0
CertSaveStore(
hStore,
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
CERT_STORE_SAVE_AS_STORE,
CERT_STORE_SAVE_TO_FILENAME_A,
(void *) "C:\\temp\\wintrust.sto",
0 // dwFlags
);
#endif
return hStore;
}
BOOL UpdateCertProvChain(
IN OUT PCRYPT_PROVIDER_DATA pProvData,
IN DWORD idxSigner,
OUT DWORD *pdwError,
IN BOOL fCounterSigner,
IN DWORD idxCounterSigner,
IN PCRYPT_PROVIDER_SGNR pSgnr,
IN PCCERT_CHAIN_CONTEXT pChainContext
)
{
BOOL fTestCert = FALSE;
DWORD dwSgnrError = 0;
DWORD i;
// The chain better have at least the certificate we passed in
assert(0 < pChainContext->cChain &&
0 < pChainContext->rgpChain[0]->cElement);
for (i = 0; i < pChainContext->cChain; i++) {
DWORD j;
PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[i];
for (j = 0; j < pChain->cElement; j++) {
PCERT_CHAIN_ELEMENT pEle = pChain->rgpElement[j];
DWORD dwEleError = pEle->TrustStatus.dwErrorStatus;
DWORD dwEleInfo = pEle->TrustStatus.dwInfoStatus;
PCRYPT_PROVIDER_CERT pProvCert;
if (0 != i || 0 != j) {
if (!(pProvData->psPfns->pfnAddCert2Chain(
pProvData, idxSigner, fCounterSigner,
idxCounterSigner, pEle->pCertContext)))
{
pProvData->dwError = GetLastError();
dwSgnrError = TRUST_E_SYSTEM_ERROR;
goto CommonReturn;
}
}
//
// else
// Signer cert has already been added
pProvCert = &pSgnr->pasCertChain[pSgnr->csCertChain -1];
//DSIE: 12-Oct-2000 added to get pChainElement.
pProvCert->pChainElement = pEle;
pProvCert->fSelfSigned =
0 != (dwEleInfo & CERT_TRUST_IS_SELF_SIGNED) &&
0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID);
pProvCert->fTrustedRoot =
pProvCert->fSelfSigned &&
i == pChainContext->cChain - 1 &&
j == pChain->cElement - 1 &&
0 == (dwEleError & CERT_TRUST_IS_UNTRUSTED_ROOT);
if (pProvCert->fSelfSigned) {
// Check if one of the "test" roots
DWORD k;
for (k = 0; k < NTESTROOTS; k++)
{
if (CertComparePublicKeyInfo(
pProvData->dwEncoding,
&pProvCert->pCert->pCertInfo->SubjectPublicKeyInfo,
&rgTestRootPublicKeyInfo[k]))
{
pProvCert->fTestCert = TRUE;
fTestCert = TRUE;
if (pProvData->dwRegPolicySettings & WTPF_TRUSTTEST)
pProvCert->fTrustedRoot = TRUE;
break;
}
}
}
// First Element in all but the first simple chain
pProvCert->fTrustListSignerCert = (0 < i && 0 == j);
pProvCert->fIsCyclic = (0 != (dwEleError & CERT_TRUST_IS_CYCLIC));
// Map to IE4Trust confidence
if (0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
pProvCert->dwConfidence |= CERT_CONFIDENCE_SIG;
if (0 == (dwEleError & CERT_TRUST_IS_NOT_TIME_VALID))
pProvCert->dwConfidence |= CERT_CONFIDENCE_TIME;
// On Sep 10, 1998 Trevor/Brian wanted time nesting checks to
// be disabled
// if (0 == (dwEleError & CERT_TRUST_IS_NOT_TIME_NESTED))
pProvCert->dwConfidence |= CERT_CONFIDENCE_TIMENEST;
if (0 != (dwEleInfo & CERT_TRUST_HAS_EXACT_MATCH_ISSUER))
pProvCert->dwConfidence |= CERT_CONFIDENCE_AUTHIDEXT;
if (0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID) &&
0 != (dwEleInfo & CERT_TRUST_HAS_EXACT_MATCH_ISSUER))
pProvCert->dwConfidence |= CERT_CONFIDENCE_HYGIENE;
if (pEle->pRevocationInfo) {
pProvCert->dwRevokedReason =
pEle->pRevocationInfo->dwRevocationResult;
}
// Update any signature or revocations errors
if (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID) {
pProvCert->dwError = TRUST_E_CERT_SIGNATURE;
assert(pChainContext->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_NOT_SIGNATURE_VALID);
dwSgnrError = TRUST_E_CERT_SIGNATURE;
} else if (dwEleError & CERT_TRUST_IS_REVOKED) {
pProvCert->dwError = CERT_E_REVOKED;
assert(pChainContext->TrustStatus.dwErrorStatus &
CERT_TRUST_IS_REVOKED);
if (0 == dwSgnrError ||
CERT_E_REVOCATION_FAILURE == dwSgnrError)
dwSgnrError = CERT_E_REVOKED;
} else if (dwEleError & CERT_TRUST_IS_OFFLINE_REVOCATION) {
// Ignore NO_CHECK errors
if (pProvData->pWintrustData->fdwRevocationChecks ==
WTD_REVOKE_WHOLECHAIN) {
pProvCert->dwError = CERT_E_REVOCATION_FAILURE;
assert(pChainContext->TrustStatus.dwErrorStatus &
CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
if (0 == dwSgnrError)
dwSgnrError = CERT_E_REVOCATION_FAILURE;
}
}
// If last element in simple chain, check if it was in a
// CTL and update CryptProvData if it was.
if (j == pChain->cElement - 1 && pChain->pTrustListInfo &&
pChain->pTrustListInfo->pCtlContext) {
DWORD dwChainError = pChain->TrustStatus.dwErrorStatus;
// Note, don't need to AddRef since we already hold an
// AddRef on the ChainContext.
pProvCert->pCtlContext = pChain->pTrustListInfo->pCtlContext;
if (dwChainError & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID) {
pProvCert->dwCtlError = TRUST_E_CERT_SIGNATURE;
dwSgnrError = TRUST_E_CERT_SIGNATURE;
} else if (dwChainError & CERT_TRUST_CTL_IS_NOT_TIME_VALID) {
if (0 == (pProvData->dwRegPolicySettings &
WTPF_IGNOREEXPIRATION))
pProvCert->dwCtlError = CERT_E_EXPIRED;
} else if (dwChainError &
CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) {
pProvCert->dwCtlError = CERT_E_WRONG_USAGE;
}
}
if (pProvData->psPfns->pfnCertCheckPolicy) {
if (! (*pProvData->psPfns->pfnCertCheckPolicy)(
pProvData, idxSigner, fCounterSigner, idxCounterSigner))
goto CommonReturn;
}
}
}
CommonReturn:
if (fTestCert) {
if (CERT_TRUST_IS_REVOKED == dwSgnrError ||
CERT_E_REVOCATION_FAILURE == dwSgnrError) {
// No revocation errors for "test" roots
dwSgnrError = 0;
// Loop through certs and remove any revocation error status
for (i = 0; i < pSgnr->csCertChain; i++) {
PCRYPT_PROVIDER_CERT pProvCert = &pSgnr->pasCertChain[i];
pProvCert->dwError = 0;
pProvCert->dwRevokedReason = 0;
}
}
}
if (CERT_E_REVOCATION_FAILURE == dwSgnrError &&
pProvData->pWintrustData->fdwRevocationChecks !=
WTD_REVOKE_WHOLECHAIN)
// Will check during Final Policy
dwSgnrError = 0;
if (dwSgnrError) {
pSgnr->dwError = dwSgnrError;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
dwSgnrError;
*pdwError = S_FALSE;
return FALSE;
} else
return TRUE;
}
BOOL _WalkChain(
CRYPT_PROVIDER_DATA *pProvData,
DWORD idxSigner,
DWORD *pdwError,
BOOL fCounterSigner,
DWORD idxCounterSigner,
BOOL fTimeStamped,
BOOL *pfLifetimeSigning // IN OUT, only accessed for fTimeStamped
)
{
BOOL fResult;
DWORD dwCreateChainFlags;
DWORD dwSgnrError = 0;
CRYPT_PROVIDER_SGNR *pSgnr; // not allocated
PCCERT_CONTEXT pCertContext; // not allocated
CERT_CHAIN_PARA ChainPara;
HCERTCHAINENGINE hChainEngine = NULL;
HCERTSTORE hAdditionalStore = NULL;
PCCERT_CHAIN_CONTEXT pChainContext = NULL;
LPSTR pszUsage = NULL;
if (fCounterSigner)
pSgnr = &pProvData->pasSigners[idxSigner].pasCounterSigners[
idxCounterSigner];
else
pSgnr = &pProvData->pasSigners[idxSigner];
assert(pSgnr);
//
// at this stage, the last cert in the chain "should be" the signers cert.
// eg: there should only be one cert in the chain from the Signature
// Provider
//
if (1 != pSgnr->csCertChain ||
(NULL == (pCertContext =
pSgnr->pasCertChain[pSgnr->csCertChain - 1].pCert))) {
dwSgnrError = TRUST_E_NO_SIGNER_CERT;
goto NoSignerCertError;
}
memset(&ChainPara, 0, sizeof(ChainPara));
ChainPara.cbSize = sizeof(ChainPara);
if (fCounterSigner && SGNR_TYPE_TIMESTAMP == pSgnr->dwSignerType) {
pszUsage = szOID_PKIX_KP_TIMESTAMP_SIGNING;
} else if(NULL != pProvData->pRequestUsage) {
ChainPara.RequestedUsage = *pProvData->pRequestUsage;
} else {
pszUsage = pProvData->pszUsageOID;
}
if ( (0 == (pProvData->dwProvFlags & WTD_NO_POLICY_USAGE_FLAG)) && pszUsage) {
ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
ChainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = &pszUsage;
}
hChainEngine = GetChainEngine(pProvData);
hAdditionalStore = GetChainAdditionalStore(pProvData);
dwCreateChainFlags = 0;
if (pProvData->dwProvFlags & CPD_REVOCATION_CHECK_NONE) {
;
} else if (pProvData->dwProvFlags & CPD_REVOCATION_CHECK_END_CERT) {
dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_END_CERT;
} else if (pProvData->dwProvFlags & CPD_REVOCATION_CHECK_CHAIN) {
dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
} else if (pProvData->dwProvFlags &
CPD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT) {
dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
} else if (pProvData->dwProvFlags & WTD_REVOCATION_CHECK_NONE) {
;
} else if (pProvData->dwProvFlags & WTD_REVOCATION_CHECK_END_CERT) {
dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_END_CERT;
} else if (pProvData->dwProvFlags & WTD_REVOCATION_CHECK_CHAIN) {
dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
} else if (pProvData->dwProvFlags &
WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT) {
dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
} else if (pProvData->pWintrustData->fdwRevocationChecks ==
WTD_REVOKE_WHOLECHAIN) {
dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
} else if (fCounterSigner && SGNR_TYPE_TIMESTAMP == pSgnr->dwSignerType) {
if (0 == (pProvData->dwRegPolicySettings & WTPF_IGNOREREVOCATIONONTS))
// On 4-12-01 changed from END_CERT to EXCLUDE_ROOT
dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
} else if (0 == (pProvData->dwRegPolicySettings & WTPF_IGNOREREVOKATION))
// On 4-12-01 changed from END_CERT to EXCLUDE_ROOT
dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
if (!(pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_CERT ||
pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_SIGNER))
// Certificate was obtained from either the message store, or one
// of our known stores
dwCreateChainFlags |= CERT_CHAIN_CACHE_END_CERT;
// else
// Can't implicitly cache a context passed to us
#if 0
{
HCERTSTORE hDebugStore;
if (hDebugStore = CertOpenSystemStoreA(0, "wintrust")) {
CertAddCertificateContextToStore(
hDebugStore,
pCertContext,
CERT_STORE_ADD_ALWAYS,
NULL
);
CertCloseStore(hDebugStore, 0);
}
}
#endif
FILETIME fileTime;
memset(&fileTime, 0, sizeof(fileTime));
if (fTimeStamped && *pfLifetimeSigning)
dwCreateChainFlags |= CERT_CHAIN_TIMESTAMP_TIME;
if (!CertGetCertificateChain (
hChainEngine,
pCertContext,
(memcmp(&pSgnr->sftVerifyAsOf, &fileTime, sizeof(fileTime)) == 0) ?
NULL : &pSgnr->sftVerifyAsOf,
hAdditionalStore,
&ChainPara,
dwCreateChainFlags,
NULL, // pvReserved,
&pChainContext
)) {
pProvData->dwError = GetLastError();
dwSgnrError = TRUST_E_SYSTEM_ERROR;
goto GetChainError;
}
if (fTimeStamped && !*pfLifetimeSigning) {
// See if resultant application policy has the LIFETIME_SIGNING OID
PCERT_ENHKEY_USAGE pAppUsage =
pChainContext->rgpChain[0]->rgpElement[0]->pApplicationUsage;
if (pAppUsage) {
DWORD i;
for (i = 0; i < pAppUsage->cUsageIdentifier; i++) {
if (0 == strcmp(pAppUsage->rgpszUsageIdentifier[i],
szOID_KP_LIFETIME_SIGNING)) {
*pfLifetimeSigning = TRUE;
break;
}
}
}
if (*pfLifetimeSigning) {
CertFreeCertificateChain(pChainContext);
pChainContext = NULL;
dwCreateChainFlags |= CERT_CHAIN_TIMESTAMP_TIME;
if (!CertGetCertificateChain (
hChainEngine,
pCertContext,
(memcmp(&pSgnr->sftVerifyAsOf, &fileTime, sizeof(fileTime)) == 0) ?
NULL : &pSgnr->sftVerifyAsOf,
hAdditionalStore,
&ChainPara,
dwCreateChainFlags,
NULL, // pvReserved,
&pChainContext
)) {
pProvData->dwError = GetLastError();
dwSgnrError = TRUST_E_SYSTEM_ERROR;
goto GetChainError;
}
}
}
pSgnr->pChainContext = pChainContext;
if (pProvData->dwProvFlags & WTD_NO_IE4_CHAIN_FLAG) {
pProvData->dwProvFlags |= CPD_USE_NT5_CHAIN_FLAG;
fResult = TRUE;
} else
fResult = UpdateCertProvChain(
pProvData,
idxSigner,
pdwError,
fCounterSigner,
idxCounterSigner,
pSgnr,
pChainContext
);
CommonReturn:
if (hChainEngine)
CertFreeCertificateChainEngine(hChainEngine);
if (hAdditionalStore)
CertCloseStore(hAdditionalStore, 0);
return fResult;
ErrorReturn:
pSgnr->dwError = dwSgnrError;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
dwSgnrError;
*pdwError = S_FALSE;
fResult = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS, NoSignerCertError)
TRACE_ERROR_EX(DBG_SS, GetChainError)
}
BOOL WINAPI _IsLifetimeSigningCert(
PCCERT_CONTEXT pCertContext
)
{
DWORD cbSize;
PCERT_ENHKEY_USAGE pCertEKU;
//
// see if the certificate has the proper enhanced key usage OID
//
cbSize = 0;
CertGetEnhancedKeyUsage(pCertContext,
CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
NULL,
&cbSize);
if (cbSize == 0)
{
return(FALSE);
}
if (!(pCertEKU = (PCERT_ENHKEY_USAGE)new BYTE[cbSize]))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(FALSE);
}
if (!(CertGetEnhancedKeyUsage(pCertContext,
CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
pCertEKU,
&cbSize)))
{
delete pCertEKU;
return(FALSE);
}
for (int i = 0; i < (int)pCertEKU->cUsageIdentifier; i++)
{
if (strcmp(pCertEKU->rgpszUsageIdentifier[i], szOID_KP_LIFETIME_SIGNING) == 0)
{
delete pCertEKU;
return(TRUE);
}
}
delete pCertEKU;
return(FALSE);
}