|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1999
//
// File: verify.cpp
//
//--------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include "cscsp.h"
#define __dwFILE__ __dwFILE_CERTUTIL_VERIFY_CPP__
HRESULT cuVerifyKeyAuthority( IN CERT_NAME_BLOB const *pIssuer, IN CERT_INFO const *pCertInfoCA, IN BYTE const *pbData, IN DWORD cbData, IN BOOL fQuiet, OUT BOOL *pfKeyAuthorityMatch) { CERT_AUTHORITY_KEY_ID2_INFO const *pcaki = NULL; DWORD cbcaki; HRESULT hr = S_OK; BOOL fDisplayIssuer = !fQuiet && g_fVerbose; CERT_NAME_BLOB const *pAuthorityCertIssuerName = NULL; BYTE *pbHash = NULL; DWORD cbHash;
*pfKeyAuthorityMatch = TRUE;
if (!myDecodeKeyAuthority2( X509_ASN_ENCODING, pbData, cbData, CERTLIB_USE_LOCALALLOC, &pcaki, &cbcaki)) { hr = myHLastError(); _JumpError(hr, error, "myDecodeKeyAuthority(IssuerKey)"); } if (0 != pcaki->KeyId.cbData) { //DumpHex(DH_NOTABPREFIX | 4, pcaki->KeyId.pbData, pcaki->KeyId.cbData);
hr = myGetPublicKeyHash( pCertInfoCA, &pCertInfoCA->SubjectPublicKeyInfo, &pbHash, &cbHash); _JumpIfError(hr, error, "myGetPublicKeyHash");
//DumpHex(DH_NOTABPREFIX | 4, pbHash, cbHash);
if (cbHash == pcaki->KeyId.cbData && 0 == memcmp(pbHash, pcaki->KeyId.pbData, cbHash)) { if (!fQuiet) { wprintf(myLoadResourceString(IDS_KEYID_IS_KEYAUTHORITY)); // "CA Key Id matches Key Id"
} } else { if (!fQuiet) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_ERR_KEYID_NOT_KEYAUTHORITY)); // "ERROR: CA Key Id does not match Key Id"
wprintf(wszNewLine); } *pfKeyAuthorityMatch = FALSE; } } else { if (!fQuiet) { wprintf(myLoadResourceString(IDS_NO_KEYID)); // "No Key Id"
} } if (!fQuiet) { wprintf(wszNewLine); }
if (1 == pcaki->AuthorityCertIssuer.cAltEntry && CERT_ALT_NAME_DIRECTORY_NAME == pcaki->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice) {
pAuthorityCertIssuerName = &pcaki->AuthorityCertIssuer.rgAltEntry[0].DirectoryName;
// The Issuer's Issuer name and the Issuer's SerialNumber combined
// should uniquely identify the Issuer cert.
// Verify Issuer's Issuer name:
// -------- ------ ----
if (!CertCompareCertificateName( X509_ASN_ENCODING, const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Issuer), const_cast<CERT_NAME_BLOB *>(pAuthorityCertIssuerName))) { // This API doesn't set LastError
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
if (!fQuiet) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_ERR_FORMAT_ISSUER_NOT_KEYAUTHORITY), // "ERROR: CA Issuer name does not match Key Authority name (%x)"
hr);
hr = S_OK; fDisplayIssuer = TRUE; } *pfKeyAuthorityMatch = FALSE; } else { if (!fQuiet) { wprintf(myLoadResourceString(IDS_ISSUER_IS_KEYAUTHORITY)); // "CA Issuer name matches Key Authority name"
} } } else { if (!fQuiet) { wprintf(myLoadResourceString(IDS_NO_KEYAUTHORITY)); // "No Key Authority name"
} } if (!fQuiet) { wprintf(wszNewLine); }
if (0 != pcaki->AuthorityCertSerialNumber.cbData) { if (pCertInfoCA->SerialNumber.cbData != pcaki->AuthorityCertSerialNumber.cbData || 0 != memcmp( pCertInfoCA->SerialNumber.pbData, pcaki->AuthorityCertSerialNumber.pbData, pcaki->AuthorityCertSerialNumber.cbData)) { if (!fQuiet) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_SERIAL_NOT_KEYAUTHORITY)); // "ERROR: Issuer serial number does not match Key Authority"
wprintf(wszNewLine);
fDisplayIssuer = TRUE; } *pfKeyAuthorityMatch = FALSE; } else { if (!fQuiet) { wprintf(myLoadResourceString(IDS_SERIAL_IS_KEYAUTHORITY)); // "Issuer serial number matches Key Authority"
} } } else { if (!fQuiet) { wprintf(myLoadResourceString(IDS_NO_KEYAUTHORITYSERIAL)); // "No Key Authority serial number"
} } if (!fQuiet) { wprintf(wszNewLine); }
if (!fQuiet && fDisplayIssuer) { hr = cuDisplayCertName( TRUE, NULL, myLoadResourceString(IDS_ISSUERNAME), // "Issuer Name"
g_wszPad4, pIssuer, NULL); _JumpIfError(hr, error, "cuDisplayCertName(Issuer)");
if (NULL != pAuthorityCertIssuerName) { hr = cuDisplayCertName( TRUE, NULL, myLoadResourceString(IDS_KEYAUTHORITYNAME), // "KeyAuthority
g_wszPad4, pAuthorityCertIssuerName, NULL); _JumpIfError(hr, error, "cuDisplayCertName(KeyAuthority)"); }
wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_KEYID)); // "KeyId:"
wprintf(wszNewLine);
DumpHex(DH_NOTABPREFIX | 4, pcaki->KeyId.pbData, pcaki->KeyId.cbData);
wprintf(wszNewLine);
hr = cuDumpSerial( NULL, IDS_KEYAUTHORITYSERIAL, &pcaki->AuthorityCertSerialNumber); _JumpIfError(hr, error, "cuDumpSerial");
wprintf(wszNewLine);
hr = cuDumpSerial(NULL, IDS_CASERIAL, &pCertInfoCA->SerialNumber); _JumpIfError(hr, error, "cuDumpSerial"); }
error: if (NULL != pcaki) { LocalFree(const_cast<CERT_AUTHORITY_KEY_ID2_INFO *>(pcaki)); } if (NULL != pbHash) { LocalFree(pbHash); } return(hr); }
static DWORD s_adwProvType[] = { PROV_RSA_FULL, PROV_RSA_SIG, PROV_DSS, PROV_FORTEZZA, PROV_MS_EXCHANGE, PROV_SSL, PROV_RSA_SCHANNEL, PROV_DSS_DH, PROV_EC_ECDSA_SIG, PROV_EC_ECNRA_SIG, PROV_EC_ECDSA_FULL, PROV_EC_ECNRA_FULL, PROV_DH_SCHANNEL, PROV_SPYRUS_LYNKS, PROV_RNG, PROV_INTEL_SEC, };
HRESULT cuLoadKeys( OPTIONAL IN WCHAR const *pwszProvName, IN OUT DWORD *pdwProvType, IN WCHAR const *pwszKeyContainerName, IN BOOL fMachineKeyset, IN BOOL fSoftFail, OPTIONAL OUT HCRYPTPROV *phProv, OPTIONAL OUT CERT_PUBLIC_KEY_INFO **ppPubKeyInfo, OPTIONAL OUT CERT_PUBLIC_KEY_INFO **ppPubKeyInfoXchg) { HRESULT hr; HRESULT hr2; HCRYPTPROV hProv = NULL; DWORD cb; DWORD *pdwProvTypeT = pdwProvType; DWORD *pdwProvTypeEnd = &pdwProvTypeT[1]; DWORD dwSilent = g_fCryptSilent? CRYPT_SILENT : 0; CERT_PUBLIC_KEY_INFO *pPubKeyInfo = NULL; CERT_PUBLIC_KEY_INFO *pPubKeyInfoXchg = NULL;
if (NULL != phProv) { *phProv = NULL; } if (NULL != ppPubKeyInfo) { *ppPubKeyInfo = NULL; } if (NULL != ppPubKeyInfoXchg) { *ppPubKeyInfoXchg = NULL; }
// If no provider type was specified, try them all
if (0 == *pdwProvTypeT) { pdwProvTypeT = s_adwProvType; pdwProvTypeEnd = &s_adwProvType[ARRAYSIZE(s_adwProvType)]; }
hr = S_OK; for ( ; pdwProvTypeT < pdwProvTypeEnd; pdwProvTypeT++) { DBGPRINT(( DBG_SS_CERTUTILI, "myCertSrvCryptAcquireContext(%ws, t=%x, f=%x, m=%x)\n", pwszKeyContainerName, *pdwProvTypeT, dwSilent, fMachineKeyset));
if (myCertSrvCryptAcquireContext( &hProv, pwszKeyContainerName, pwszProvName, *pdwProvTypeT, dwSilent, // dwFlags
fMachineKeyset)) { hr = S_OK; break; } hr2 = myHLastError(); if (S_OK == hr || (NTE_BAD_PROV_TYPE != hr2 && NTE_PROV_TYPE_NOT_DEF != hr2 && NTE_BAD_KEYSET != hr2)) { hr = hr2; } _PrintErrorStr2( hr2, "myCertSrvCryptAcquireContext", pwszKeyContainerName, hr2); if (NTE_BAD_FLAGS == hr2 && PROV_MS_EXCHANGE == *pdwProvTypeT && ((CRYPT_SILENT & dwSilent) || fMachineKeyset)) { DBGPRINT(( DBG_SS_CERTUTILI, "myCertSrvCryptAcquireContext(%ws, t=%x, f=%x, m=%x)\n", pwszKeyContainerName, *pdwProvTypeT, 0, FALSE));
if (myCertSrvCryptAcquireContext( &hProv, pwszKeyContainerName, pwszProvName, *pdwProvTypeT, 0, // dwFlags
FALSE)) { hr = S_OK; break; } hr2 = myHLastError(); _PrintErrorStr2( hr2, "myCertSrvCryptAcquireContext", pwszKeyContainerName, hr2); } } if (S_OK != hr) { cuPrintErrorAndString( L"CryptAcquireContext", 0, hr, pwszKeyContainerName); goto error; }
// export the public key blob
if (NULL != ppPubKeyInfo && !myCryptExportPublicKeyInfo( hProv, AT_SIGNATURE, CERTLIB_USE_LOCALALLOC, &pPubKeyInfo, &cb)) { hr = myHLastError(); if (!fSoftFail) { cuPrintErrorAndString( L"CryptExportPublicKeyInfo", 0, hr, L"AT_SIGNATURE"); goto error; } }
if (NULL != ppPubKeyInfoXchg && !myCryptExportPublicKeyInfo( hProv, AT_KEYEXCHANGE, CERTLIB_USE_LOCALALLOC, &pPubKeyInfoXchg, &cb)) { hr = myHLastError(); if (!fSoftFail) { cuPrintErrorAndString( L"CryptExportPublicKeyInfo", 0, hr, L"AT_KEYEXCHANGE"); goto error; } } *pdwProvType = *pdwProvTypeT; if (NULL != phProv) { *phProv = hProv; hProv = NULL; } if (NULL != ppPubKeyInfo) { *ppPubKeyInfo = pPubKeyInfo; pPubKeyInfo = NULL; } if (NULL != ppPubKeyInfoXchg) { *ppPubKeyInfoXchg = pPubKeyInfoXchg; pPubKeyInfoXchg = NULL; } hr = S_OK;
error: if (NULL != pPubKeyInfo) { LocalFree(pPubKeyInfo); } if (NULL != pPubKeyInfoXchg) { LocalFree(pPubKeyInfoXchg); } if (NULL != hProv) { CryptReleaseContext(hProv, 0); } return(hr); }
HRESULT VerifyPrivateKey( IN CERT_CONTEXT const *pCertContextCA, IN WCHAR const *pwszSanitizedCA, IN WCHAR const *pwszKeyContainerName, OUT BOOL *pfMatchFailed, OUT BOOL *pfSigningTestAttempted, OUT BOOL *pfKeyUsageCountSupported, OUT BOOL *pfKeyUsageCountEnabled, OUT ULARGE_INTEGER *puliKeyUsageCount) { HRESULT hr; HCRYPTPROV hProv = NULL; DWORD dwProvType; WCHAR *pwszProvName = NULL; ALG_ID idAlg; BOOL fMachineKeyset;
*pfMatchFailed = TRUE; *pfSigningTestAttempted = FALSE; *pfKeyUsageCountSupported = FALSE; *pfKeyUsageCountEnabled = FALSE; puliKeyUsageCount->QuadPart = 0;
// get provider name
hr = myGetCertSrvCSP( FALSE, // fEncryptionCSP
pwszSanitizedCA, &dwProvType, &pwszProvName, &idAlg, &fMachineKeyset, NULL); // pdwKeySize
_JumpIfError(hr, error, "myGetCertSrvCSP");
hr = myValidateSigningKey( pwszKeyContainerName, pwszProvName, dwProvType, g_fCryptSilent, fMachineKeyset, g_fForce, // fForceSignatureTest
pCertContextCA, NULL, // pPublicKeyInfo
idAlg, pfSigningTestAttempted, &hProv); _JumpIfError(hr, error, "myValidateSigningKey");
*pfMatchFailed = FALSE; hr = myGetSigningKeyUsageCount( hProv, pfKeyUsageCountSupported, pfKeyUsageCountEnabled, puliKeyUsageCount); _JumpIfError(hr, error, "myGetSigningKeyUsageCount");
error: if (NULL != hProv) { CryptReleaseContext(hProv, 0); } if (NULL != pwszProvName) { LocalFree(pwszProvName); } return(hr); }
HRESULT VerifyCAKeys( IN CERT_CONTEXT const *pCertContextCA, IN WCHAR const *pwszSanitizedCA, IN WCHAR const *pwszCertNameCA, IN WCHAR const *pwszKeyContainerName) { HRESULT hr; CERT_PUBLIC_KEY_INFO *pPubKeyInfo = NULL; BOOL fMatchFailed = FALSE; BOOL fSigningTestFailed = FALSE; BOOL fSigningTestAttempted = FALSE; BOOL fKeyUsageCountSupported = FALSE; BOOL fKeyUsageCountEnabled = FALSE; ULARGE_INTEGER uliKeyUsageCount; WCHAR *pwszRevert = NULL; DWORD dwNameId; CRYPT_KEY_PROV_INFO kpi; CRYPT_KEY_PROV_INFO *pkpi = NULL; DWORD cbkpi;
ZeroMemory(&kpi, sizeof(kpi)); hr = myGetNameId(pCertContextCA, &dwNameId); if (S_OK != hr) { _PrintError(hr, "myGetNameId"); dwNameId = MAXDWORD; } hr = myRevertSanitizeName(pwszKeyContainerName, &pwszRevert); _JumpIfError(hr, error, "myRevertSanitizeName");
if (!myCertGetCertificateContextProperty( pCertContextCA, CERT_KEY_PROV_INFO_PROP_ID, CERTLIB_USE_LOCALALLOC, (VOID **) &pkpi, &cbkpi)) { hr = myHLastError(); _PrintError(hr, "myCertGetCertificateContextProperty");
kpi.pwszContainerName = const_cast<WCHAR *>(pwszKeyContainerName); } else { kpi = *pkpi; if (0 != lstrcmp(pwszKeyContainerName, pkpi->pwszContainerName)) { wprintf( L"%ws --> %ws\n", pwszKeyContainerName, pkpi->pwszContainerName);
kpi.pwszContainerName = pkpi->pwszContainerName; } }
// Load public key
hr = cuLoadKeys( kpi.pwszProvName, &kpi.dwProvType, kpi.pwszContainerName, TRUE, // fMachineKeyset
FALSE, // fSoftFail
NULL, // phProv
&pPubKeyInfo, NULL); if (S_OK != hr) { cuPrintError(IDS_ERR_FORMAT_LOADKEYS, hr); _JumpError(hr, error, "cuLoadKeys"); }
// see if the public key matches the certificate's public key
if (!CertComparePublicKeyInfo( X509_ASN_ENCODING, pPubKeyInfo, &pCertContextCA->pCertInfo->SubjectPublicKeyInfo)) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_ERR_PUBLICKEY_MISMATCH)); // "ERROR: Certificate public key does NOT match stored keyset"
wprintf(wszNewLine); wprintf(wszNewLine);
fMatchFailed = TRUE; } if (g_fVerbose || fMatchFailed) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CONTAINER_PUBLIC_KEY)); // "Container Public Key:"
wprintf(wszNewLine); DumpHex( DH_NOTABPREFIX | 4, pPubKeyInfo->PublicKey.pbData, pPubKeyInfo->PublicKey.cbData);
wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CERT_PUBLIC_KEY)); // "Certificate Public Key:"
wprintf(wszNewLine); DumpHex( DH_NOTABPREFIX | 4, pCertContextCA->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, pCertContextCA->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData); }
if (!fMatchFailed) { hr = VerifyPrivateKey( pCertContextCA, pwszSanitizedCA, kpi.pwszContainerName, &fSigningTestFailed, &fSigningTestAttempted, &fKeyUsageCountSupported, &fKeyUsageCountEnabled, &uliKeyUsageCount); _PrintIfError(hr, "VerifyPrivateKey"); } wprintf( myLoadResourceString( fMatchFailed? IDS_FORMAT_KEY_NOT_VERIFY : // "%ws does NOT verify as the public key in %ws"
IDS_FORMAT_KEY_IS_VERIFY), // "%ws verifies as the public key in %ws"
pwszRevert, pwszCertNameCA); wprintf(wszNewLine);
if (MAXDWORD != dwNameId) { wprintf( L" V%u.%u\n", CANAMEIDTOICERT(dwNameId), CANAMEIDTOIKEY(dwNameId)); } if (fSigningTestAttempted) { wprintf( L" %ws\n", myLoadResourceString( fSigningTestFailed? IDS_SIGNATURE_BAD : // "Signature test FAILED"
IDS_SIGNATURE_OK)); // "Signature test passed"
}
if (fKeyUsageCountEnabled) { wprintf( L" %ws: %I64u (0x%I64x)\n", myLoadResourceString(IDS_KEY_USAGE_COUNT), // "Key usage count:"
uliKeyUsageCount.QuadPart, uliKeyUsageCount.QuadPart); } else if (g_fVerbose) { wprintf( L" %ws: %ws\n", myLoadResourceString(IDS_KEY_USAGE_COUNT), // "Key usage count:"
myLoadResourceString( fKeyUsageCountSupported? IDS_KEY_USAGE_COUNT_DISABLED : // "Disabled"
IDS_KEY_USAGE_COUNT_NOTSUPPORTED)); // "Not supported"
} wprintf(wszNewLine);
if (fMatchFailed || fSigningTestFailed) { hr = E_INVALIDARG; _JumpError(hr, error, "fMatchFailed || fSigningTestFailed"); } hr = S_OK;
error: if (NULL != pwszRevert) { LocalFree(pwszRevert); } if (NULL != pPubKeyInfo) { LocalFree(pPubKeyInfo); } if (NULL != pkpi) { LocalFree(pkpi); } return(hr); }
HRESULT VerifyAllCAKeys( IN WCHAR const *pwszCA, IN WCHAR const *pwszSanitizedCA) { HRESULT hr; HRESULT hr2; WCHAR *pwszCertName = NULL; DWORD cCACerts; DWORD iHash; HCERTSTORE hMyStore = NULL; CERT_CONTEXT const *pccCA = NULL; CRYPT_KEY_PROV_INFO *pkpi = NULL; DWORD cbkpi;
hr = myGetCARegHashCount(pwszSanitizedCA, CSRH_CASIGCERT, &cCACerts); if (S_OK == hr && 0 == cCACerts) { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); } _JumpIfError(hr, error, "myGetCARegHashCount");
// open MY store
hMyStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING, NULL, // hProv
CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, wszMY_CERTSTORE); if (NULL == hMyStore) { hr = myHLastError(); _JumpError(hr, error, "CertOpenStore"); }
hr2 = S_OK; for (iHash = 0; iHash < cCACerts; iHash++) { DWORD NameId; hr = myFindCACertByHashIndex( hMyStore, pwszSanitizedCA, CSRH_CASIGCERT, iHash, &NameId, &pccCA); if (S_FALSE == hr) { continue; } _JumpIfError(hr, error, "myFindCACertByHashIndex");
// get the private key provider info
if (!myCertGetCertificateContextProperty( pccCA, CERT_KEY_PROV_INFO_PROP_ID, CERTLIB_USE_LOCALALLOC, (VOID **) &pkpi, &cbkpi)) { hr = myHLastError(); _JumpError(hr, error, "myCertGetCertificateContextProperty"); }
if (MAXDWORD == NameId) { NameId = MAKECANAMEID(iHash, iHash); } hr = myAllocIndexedName( pwszCA, CANAMEIDTOICERT(NameId), MAXDWORD, // IndexTarget
&pwszCertName); _JumpIfError(hr, error, "myAllocIndexedName");
hr = VerifyCAKeys( pccCA, pwszSanitizedCA, pwszCertName, pkpi->pwszContainerName); _PrintIfError(hr, "VerifyCAKeys"); if (S_OK == hr2) { hr2 = hr; } CertFreeCertificateContext(pccCA); pccCA = NULL;
LocalFree(pkpi); pkpi = NULL;
LocalFree(pwszCertName); pwszCertName = NULL; } hr = hr2;
error: if (NULL != pkpi) { LocalFree(pkpi); } if (NULL != pccCA) { CertFreeCertificateContext(pccCA); } if (NULL != hMyStore) { CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG); } if (NULL != pwszCertName) { LocalFree(pwszCertName); } return(hr); }
HRESULT verbVerifyKeys( IN WCHAR const *pwszOption, OPTIONAL IN WCHAR const *pwszKeyContainerName, OPTIONAL IN WCHAR const *pwszfnCertCA, OPTIONAL IN WCHAR const *pwszArg3, OPTIONAL IN WCHAR const *pwszArg4) { HRESULT hr; CERT_CONTEXT const *pCertContextCA = NULL; WCHAR *pwszCA = NULL; WCHAR *pwszSanitizedCA = NULL; WCHAR *pwszRevertContainer = NULL; WCHAR *pwszSanitizedContainer = NULL;
hr = cuGetLocalCANameFromConfig(NULL, &pwszCA); _JumpIfError(hr, error, "GetLocalCANameFromConfig");
hr = mySanitizeName(pwszCA, &pwszSanitizedCA); _JumpIfError(hr, error, "mySanitizeName");
if (NULL == pwszfnCertCA) { if (NULL != pwszKeyContainerName) { hr = E_INVALIDARG; _JumpError(hr, error, "extra arg"); }
hr = VerifyAllCAKeys(pwszCA, pwszSanitizedCA); _JumpIfError(hr, error, "VerifyAllCAKeys"); } else { hr = myRevertSanitizeName(pwszKeyContainerName, &pwszRevertContainer); _JumpIfError(hr, error, "myRevertSanitizeName");
hr = cuSanitizeNameWithSuffix( pwszRevertContainer, &pwszSanitizedContainer); _JumpIfError(hr, error, "cuSanitizeNameWithSuffix");
// Load and decode CA certificate
hr = cuLoadCert(pwszfnCertCA, &pCertContextCA); if (S_OK != hr) { cuPrintError(IDS_ERR_FORMAT_LOADCACERT, hr); goto error; }
hr = VerifyCAKeys( pCertContextCA, pwszSanitizedCA, pwszfnCertCA, pwszSanitizedContainer); _JumpIfError(hr, error, "VerifyCAKeys"); }
error: cuUnloadCert(&pCertContextCA); if (NULL != pwszSanitizedCA) { LocalFree(pwszSanitizedCA); } if (NULL != pwszCA) { LocalFree(pwszCA); } if (NULL != pwszSanitizedContainer) { LocalFree(pwszSanitizedContainer); } if (NULL != pwszRevertContainer) { LocalFree(pwszRevertContainer); } return(hr); }
VOID cuDumpPolicies( IN UINT idMsg, IN WCHAR const *pwszzPolicies) { wprintf(L"%ws:", myLoadResourceString(idMsg)); if (NULL == pwszzPolicies) { wprintf(L" %ws\n", myLoadResourceString(IDS_ALL_POLICIES)); } else if (L'\0' == *pwszzPolicies) { wprintf(L" %ws\n", myLoadResourceString(IDS_NO_POLICIES)); } else { wprintf(wszNewLine); for ( ; L'\0' != *pwszzPolicies; pwszzPolicies += wcslen(pwszzPolicies) + 1) { wprintf(g_wszPad4); cuDumpOIDAndDescription(pwszzPolicies); wprintf(wszNewLine); } } }
FNSIMPLECHAINELEMENTCALLBACK cuSimpleChainElementCallback;
VOID cuSimpleChainElementCallback( IN DWORD dwFlags, IN DWORD iElement, IN CERT_SIMPLE_CHAIN const *pChain) { CERT_CHAIN_ELEMENT const *pElement = pChain->rgpElement[iElement]; CERT_REVOCATION_INFO *pRevocationInfo; WCHAR const *pwszFmtHeader = L" ----------------%ws%ws%ws----------------\n";
CSASSERT(iElement < pChain->cElement); pElement = pChain->rgpElement[iElement];
wprintf( pwszFmtHeader, g_wszPad2, myLoadResourceString(IDS_CERT_AIA), // "Certificate AIA"
g_wszPad2); cuDisplayAIAUrlsFromCert(pElement->pCertContext);
wprintf( pwszFmtHeader, g_wszPad2, myLoadResourceString(IDS_CERT_CDP), // "Certificate CDP"
g_wszPad2); cuDisplayCDPUrlsFromCertOrCRL(pElement->pCertContext, NULL);
pRevocationInfo = pElement->pRevocationInfo;
if (NULL != pRevocationInfo && CCSIZEOF_STRUCT(CERT_REVOCATION_INFO, pCrlInfo) <= pRevocationInfo->cbSize && NULL != pRevocationInfo->pCrlInfo) { CERT_REVOCATION_CRL_INFO *pCrlInfo;
pCrlInfo = pRevocationInfo->pCrlInfo; if (NULL != pCrlInfo) { if (NULL != pCrlInfo->pBaseCrlContext) { wprintf( pwszFmtHeader, g_wszPad2, myLoadResourceString(IDS_BASECRL_CDP), // "Base CRL CDP"
g_wszPad2); cuDisplayCDPUrlsFromCertOrCRL(NULL, pCrlInfo->pBaseCrlContext); } //if (NULL != pCrlInfo->pDeltaCrlContext)
} } wprintf( pwszFmtHeader, g_wszEmpty, g_wszEmpty, g_wszEmpty); }
HRESULT cuVerifyCertContext( IN CERT_CONTEXT const *pCert, OPTIONAL IN HCERTSTORE hStoreCA, IN DWORD cApplicationPolicies, OPTIONAL IN char const * const *apszApplicationPolicies, IN DWORD cIssuancePolicies, OPTIONAL IN char const * const *apszIssuancePolicies, IN BOOL fNTAuth, OUT DWORD *pVerifyState) { HRESULT hr; DWORD idMsg; WCHAR *pwszMissingIssuer = NULL; WCHAR *pwszzIssuancePolicies = NULL; WCHAR *pwszzApplicationPolicies = NULL; WCHAR *pwszExtendedErrorInfo = NULL; DWORD Flags;
*pVerifyState = 0; if (CertCompareCertificateName( X509_ASN_ENCODING, &pCert->pCertInfo->Issuer, &pCert->pCertInfo->Subject)) { *pVerifyState |= VS_ROOT; #if 0
hr = cuVerifySignature( pCert->pbCertEncoded, pCert->cbCertEncoded, &pCert->pCertInfo->SubjectPublicKeyInfo, FALSE, FALSE); if (S_OK == hr) { *pVerifyState |= VS_ROOTSIGOK; } _PrintIfError(hr, "cuVerifySignature"); #endif
}
// Verify the cert and chain:
Flags = 0; if (fNTAuth || g_fEnterpriseRegistry) { Flags |= CA_VERIFY_FLAGS_NT_AUTH; } if (g_fForce) { Flags |= CA_VERIFY_FLAGS_FULL_CHAIN_REVOCATION; Flags |= CA_VERIFY_FLAGS_IGNORE_OFFLINE | CA_VERIFY_FLAGS_ALLOW_UNTRUSTED_ROOT; if (1 < g_fForce) { Flags |= CA_VERIFY_FLAGS_NO_REVOCATION; } } if (!g_fQuiet) { Flags |= CA_VERIFY_FLAGS_DUMP_CHAIN; } if (g_fSplitASN) { Flags |= CA_VERIFY_FLAGS_SAVE_CHAIN; }
hr = myVerifyCertContextEx( pCert, Flags, g_dwmsTimeout, cApplicationPolicies, apszApplicationPolicies, cIssuancePolicies, apszIssuancePolicies, g_fUserRegistry? HCCE_CURRENT_USER : HCCE_LOCAL_MACHINE, NULL, // pft
hStoreCA, // hAdditionalStore
g_fURLFetch? cuSimpleChainElementCallback : NULL, &pwszMissingIssuer, &pwszzIssuancePolicies, &pwszzApplicationPolicies, &pwszExtendedErrorInfo, NULL); // pTrustStatus
if (S_OK == hr && (NULL != pwszzIssuancePolicies || NULL != pwszzApplicationPolicies || IsWhistler())) { // Suppress misleading "All Policies" display on Windows 2000.
cuDumpPolicies(IDS_ISSUANCE_POLICIES, pwszzIssuancePolicies); cuDumpPolicies(IDS_APPLICATION_POLICIES, pwszzApplicationPolicies); } if (NULL != pwszExtendedErrorInfo) { wprintf(L"%ws\n", pwszExtendedErrorInfo); }
idMsg = 0; if (CRYPT_E_REVOKED == hr || CERT_E_REVOKED == hr) { idMsg = IDS_REVOKED_CERT; // "Certificate is REVOKED"
*pVerifyState |= VS_REVOKED; } else if (CERT_E_UNTRUSTEDROOT == hr) { idMsg = IDS_UNTRUSTED_ROOT; // "Verifies against UNTRUSTED root"
*pVerifyState |= VS_UNTRUSTEDROOT; } else if (CERT_E_CHAINING == hr) { idMsg = IDS_INCOMPLETE_CHAIN; // "Incomplete certificate chain"
*pVerifyState |= VS_INCOMPLETECHAIN; } else if (CERT_E_EXPIRED == hr) { idMsg = IDS_EXPIRED_CERT; // "Expired certificate"
*pVerifyState |= VS_EXPIRED; } else if (CRYPT_E_REVOCATION_OFFLINE == hr) { idMsg = IDS_REVOCATION_OFFLINE; // "Revocation check skipped -- server offline"
*pVerifyState |= VS_REVOCATIONOFFLINE; } else if (CRYPT_E_NO_REVOCATION_CHECK == hr) { idMsg = IDS_NO_REVOCATION_CHECK; // "Revocation check skipped -- no revocation information available"
*pVerifyState |= VS_NOREVOCATIONCHECK; } if (0 != idMsg) { wprintf(myLoadResourceString(idMsg)); wprintf(wszNewLine); if (NULL != pwszMissingIssuer) { wprintf(myLoadResourceString(IDS_MISSING_CERT)); wprintf(L"\n %ws\n", pwszMissingIssuer); } hr = S_OK; } if (S_OK != hr) { *pVerifyState |= VS_OTHERERROR; } _JumpIfError(hr, error, "cuVerifyCertContext");
error: if (NULL != pwszMissingIssuer) { LocalFree(pwszMissingIssuer); } if (NULL != pwszzIssuancePolicies) { LocalFree(pwszzIssuancePolicies); } if (NULL != pwszzApplicationPolicies) { LocalFree(pwszzApplicationPolicies); } if (NULL != pwszExtendedErrorInfo) { LocalFree(pwszExtendedErrorInfo); } return(hr); }
#define RS_INCOMPLETE 0
#define RS_PASS 1
#define RS_FAIL 2
#define RS_REVOKED 3
DWORD VerifyRevocation( IN CERT_CONTEXT const *pCertContext, OPTIONAL IN CERT_CONTEXT const *pCertContextCA) { HRESULT hr; CERT_REVOCATION_PARA crp; CERT_REVOCATION_STATUS crs; DWORD RevState = RS_INCOMPLETE;
ZeroMemory(&crp, sizeof(crp)); crp.cbSize = sizeof(crp); crp.pIssuerCert = pCertContextCA;
ZeroMemory(&crs, sizeof(crs)); crs.cbSize = sizeof(crs);
crp.hCrlStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING, NULL, // hProv
cuGetSystemStoreFlags() | CERT_STORE_READONLY_FLAG, wszCA_CERTSTORE); if (NULL == crp.hCrlStore) { hr = myHLastError(); _JumpError(hr, error, "CertOpenStore"); }
if (!CertVerifyRevocation( X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, // cContext
(VOID **) &pCertContext, // rgpContext
0, // dwFlags
&crp, &crs)) { hr = myHLastError(); if (CRYPT_E_REVOKED == hr || CERT_E_REVOKED == hr) { wprintf( myLoadResourceString(IDS_FORMAT_IS_REVOKED), // "Leaf certificate is REVOKED (Reason=%x)"
crs.dwReason); wprintf(wszNewLine); RevState = RS_REVOKED; goto error; } if (CRYPT_E_NO_REVOCATION_CHECK != hr) { wprintf(wszNewLine); cuPrintError(IDS_ERR_FORMAT_VERIFY_REVSTATUS, hr); // "ERROR: Verifying leaf certificate revocation status returned %ws"
cuPrintErrorMessageText(hr); wprintf(wszNewLine);
RevState = RS_FAIL; goto error; } wprintf(myLoadResourceString(IDS_CANNOT_CHECK_REVSTATUS)); // "Cannot check leaf certificate revocation status"
wprintf(wszNewLine);
RevState = RS_INCOMPLETE; goto error; } wprintf(myLoadResourceString(IDS_REVSTATUS_OK)); // "Leaf certificate revocation check passed"
wprintf(wszNewLine); RevState = RS_PASS;
error: if (NULL != crp.hCrlStore) { CertCloseStore(crp.hCrlStore, CERT_CLOSE_STORE_CHECK_FLAG); } return(RevState); }
#define CAS_UNKNOWN 0
#define CAS_CA 1
#define CAS_ENDENTITY 2
VOID VerifyCACert( IN CERT_INFO const *pCertInfo, IN BOOL fCA, OUT DWORD *pState) { HRESULT hr; CERT_EXTENSION *pExt; UINT id = 0;
*pState = CAS_UNKNOWN;
pExt = CertFindExtension( szOID_BASIC_CONSTRAINTS2, pCertInfo->cExtension, pCertInfo->rgExtension); if (NULL == pExt) { // This API doesn't set LastError
//hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
//_PrintError(hr, "CertFindExtension");
if (fCA) { id = IDS_NOBASICCONSTRAINTS2_ERROR; // "ERROR: CA Cert has no Basic Constraints2 Extension"
} } else { DWORD cb; CERT_BASIC_CONSTRAINTS2_INFO Constraints;
cb = sizeof(Constraints); if (!CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, pExt->Value.pbData, pExt->Value.cbData, 0, &Constraints, &cb)) { hr = myHLastError(); _PrintError(hr, "CryptDecodeObject");
id = IDS_CANNOTDECODEBASICCONSTRAINTS2_ERROR; // "ERROR: Cannot decode CA Cert Basic Constraints2 Extension"
} else { *pState = Constraints.fCA? CAS_CA : CAS_ENDENTITY; if (!Constraints.fCA) { id = IDS_ENDENTITYCACERT_ERROR; // "ERROR: CA Cert is an End Entity certificate"
} } } if (fCA && 0 != id) { wprintf(wszNewLine); wprintf(myLoadResourceString(id)); wprintf(wszNewLine); wprintf(wszNewLine); } if (!fCA) { switch (*pState) { case CAS_CA: wprintf(myLoadResourceString(IDS_CACERT)); // "Cert is a CA certificate"
wprintf(wszNewLine); break;
case CAS_ENDENTITY: wprintf(myLoadResourceString(IDS_ENDENTITYCERT)); // "Cert is an End Entity certificate"
wprintf(wszNewLine); break; } } }
HRESULT VerifyCertAgainstChain( IN WCHAR const *pwszfnCert, IN DWORD cApplicationPolicies, OPTIONAL IN char const * const *apszApplicationPolicies, IN DWORD cIssuancePolicies, OPTIONAL IN char const * const *apszIssuancePolicies) { HRESULT hr; CERT_CONTEXT const *pCertContext = NULL; DWORD VerifyState; DWORD CertState; DWORD RevState;
// Load and decode certificates
hr = cuLoadCert(pwszfnCert, &pCertContext); if (S_OK != hr) { cuPrintError(IDS_FORMAT_LOADTESTCERT, hr); goto error; }
// Display name info:
hr = cuDisplayCertNames(TRUE, NULL, pCertContext->pCertInfo); _JumpIfError(hr, error, "cuDisplayCertNames(Cert)");
cuDumpSerial(NULL, IDS_CERT_SERIAL, &pCertContext->pCertInfo->SerialNumber); wprintf(wszNewLine);
hr = cuVerifyCertContext( pCertContext, // pCert
NULL, // hStoreCA
cApplicationPolicies, apszApplicationPolicies, cIssuancePolicies, apszIssuancePolicies, FALSE, // fNTAuth
&VerifyState); _JumpIfError(hr, error, "cuVerifyCertContext");
VerifyCACert(pCertContext->pCertInfo, FALSE, &CertState);
if (!g_fCryptSilent) { RevState = VerifyRevocation(pCertContext, NULL); }
error: cuUnloadCert(&pCertContext); return(hr); }
HRESULT VerifyCertAgainstParent( IN WCHAR const *pwszfnCert, IN WCHAR const *pwszfnCertCA, OPTIONAL IN WCHAR const *pwszfnCertCACrossed, OUT BOOL *pfCertLoaded) { HRESULT hr; CERT_INFO const *pCertInfo; CERT_INFO const *pCertInfoCA; CERT_INFO const *pCertInfoCACrossed; CERT_CONTEXT const *pCertContext = NULL; CERT_CONTEXT const *pCertContextCA = NULL; CERT_CONTEXT const *pCertContextCACrossed = NULL; DWORD dwFlags; BOOL fDisplayCANames = g_fVerbose; DWORD i; BOOL fCertInvalid = FALSE; DWORD RevState = RS_INCOMPLETE; BOOL fCheckRevocation = FALSE; SYSTEMTIME st; FILETIME ft; DWORD CAState; DWORD CertState; BYTE *pbKeyId = NULL; DWORD cbKeyId; BYTE *pbKeyIdCACrossed = NULL; DWORD cbKeyIdCACrossed;
// Load and decode certificates
*pfCertLoaded = FALSE; hr = cuLoadCert(pwszfnCert, &pCertContext); if (S_OK != hr) { if (CRYPT_E_ASN1_BADTAG != hr) { cuPrintError(IDS_FORMAT_LOADTESTCERT, hr); } goto error; } *pfCertLoaded = TRUE; pCertInfo = pCertContext->pCertInfo;
hr = cuLoadCert(pwszfnCertCA, &pCertContextCA); if (S_OK != hr) { cuPrintError(IDS_FORMAT_LOADCACERT, hr); goto error; } pCertInfoCA = pCertContextCA->pCertInfo;
if (NULL != pwszfnCertCACrossed) { hr = cuLoadCert(pwszfnCertCACrossed, &pCertContextCACrossed); if (S_OK != hr) { cuPrintError(IDS_FORMAT_LOADCACERT, hr); goto error; } pCertInfoCACrossed = pCertContextCACrossed->pCertInfo; }
// Display name info:
hr = cuDisplayCertNames( TRUE, myLoadResourceString(IDS_CERT), // "Cert"
pCertInfo); _JumpIfError(hr, error, "cuDisplayCertNames(Cert)");
hr = cuDisplayCertNames( TRUE, myLoadResourceString(IDS_ISSUINGCACERT), // "Issuing CA Cert"
pCertInfoCA); _JumpIfError(hr, error, "cuDisplayCertNames(CA)");
if (NULL != pwszfnCertCACrossed) { hr = cuDisplayCertNames( TRUE, myLoadResourceString(IDS_CROSSEDCACERT), // "Crossed CA Cert"
pCertInfoCACrossed); _JumpIfError(hr, error, "cuDisplayCertNames(CrossedCA)");
}
if (g_fVerbose) { wprintf(wszNewLine); cuDumpSerial(NULL, IDS_CERT_SERIAL, &pCertInfo->SerialNumber);
wprintf(wszNewLine); cuDumpSerial(NULL, IDS_ISSUINGCACERT_SERIAL, &pCertInfoCA->SerialNumber);
if (NULL != pwszfnCertCACrossed) { wprintf(wszNewLine); cuDumpSerial(NULL, IDS_CROSSEDCACERT_SERIAL, &pCertInfoCACrossed->SerialNumber);
} wprintf(wszNewLine); }
if (!CertCompareCertificateName( X509_ASN_ENCODING, const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Issuer), const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Subject))) { // This API doesn't set LastError
wprintf(myLoadResourceString(IDS_ISSUINGCA_NOT_ROOT)); // "Issuing CA is not a root: Subject name does not match Issuer"
wprintf(wszNewLine); wprintf(wszNewLine); hr = S_OK; }
if (!CertCompareCertificateName( X509_ASN_ENCODING, const_cast<CERT_NAME_BLOB *>(&pCertInfo->Issuer), const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Subject))) { // This API doesn't set LastError
wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_ISSUINGCA_SUBJECT_NOT_ISSUER)); // "ERROR: Issuing CA Subject name does not match Cert Issuer"
wprintf(wszNewLine); wprintf(wszNewLine); hr = S_OK; fCertInvalid = TRUE; } else { wprintf(myLoadResourceString(IDS_ISSUINGCA_SUBJECT_IS_ISSUER)); // "Issuing CA Subject name matches Cert Issuer"
wprintf(wszNewLine); } if (NULL != pwszfnCertCACrossed) { if (!CertCompareCertificateName( X509_ASN_ENCODING, const_cast<CERT_NAME_BLOB *>(&pCertInfo->Subject), const_cast<CERT_NAME_BLOB *>(&pCertInfoCACrossed->Subject))) { // This API doesn't set LastError
wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_CROSSEDCA_SUBJECT_NOT_SUBJECT)); // "ERROR: Crossed CA Subject name does not match Cert Subject"
wprintf(wszNewLine); wprintf(wszNewLine); hr = S_OK; fCertInvalid = TRUE; } else { wprintf(myLoadResourceString(IDS_CROSEDGCA_SUBJECT_IS_SUBJECT)); // "Crossed CA Subject name matches Cert Subject"
wprintf(wszNewLine); }
// see if the public key matches the certificate's public key
if (!CertComparePublicKeyInfo( X509_ASN_ENCODING, const_cast<CERT_PUBLIC_KEY_INFO *>(&pCertInfo->SubjectPublicKeyInfo), const_cast<CERT_PUBLIC_KEY_INFO *>(&pCertInfoCACrossed->SubjectPublicKeyInfo))) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CROSEDGCA_NOT_PUBLICKEY)); // "ERROR: Certificate public key does NOT match Cert key"
wprintf(wszNewLine); fCertInvalid = TRUE; } else { wprintf(myLoadResourceString(IDS_CROSEDGCA_NOT_IS_PUBLICKEY)); // "Crossed CA public key matches Cert key"
} wprintf(wszNewLine);
hr = myGetPublicKeyHash( pCertInfo, &pCertInfo->SubjectPublicKeyInfo, &pbKeyId, &cbKeyId); _JumpIfError(hr, error, "myGetPublicKeyHash");
hr = myGetPublicKeyHash( pCertInfoCACrossed, &pCertInfoCACrossed->SubjectPublicKeyInfo, &pbKeyIdCACrossed, &cbKeyIdCACrossed); _JumpIfError(hr, error, "myGetPublicKeyHash");
if (cbKeyId == cbKeyIdCACrossed && 0 == memcmp(pbKeyId, pbKeyIdCACrossed, cbKeyId)) { wprintf(myLoadResourceString(IDS_CROSSEDKEYID_IS_KEYID)); // "Crossed CA Key Id matches Key Id"
} else { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CROSSEDKEYID_NOT_KEYID)); // "ERROR: Crossed CA Key Id does not match Key Id"
wprintf(wszNewLine); fCertInvalid = TRUE; } wprintf(wszNewLine); }
GetSystemTime(&st); if (!SystemTimeToFileTime(&st, &ft)) { hr = myHLastError(); _JumpError(hr, error, "SystemTimeToFileTime"); } if (0 < CompareFileTime(&pCertInfo->NotBefore, &ft)) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_NOWNOTBEFORE_ERROR)); // "ERROR: Cert is not yet valid"
wprintf(wszNewLine); wprintf(wszNewLine); fCertInvalid = TRUE; } if (0 > CompareFileTime(&pCertInfo->NotAfter, &ft)) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_NOWNOTAFTER_ERROR)); // "ERROR: Cert has expired"
wprintf(wszNewLine); wprintf(wszNewLine); fCertInvalid = TRUE; }
if (0 < CompareFileTime(&pCertInfoCA->NotBefore, &pCertInfo->NotBefore)) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_CANOTBEFORE_ERROR)); // "ERROR: Cert Valid before issuing CA Cert Valid"
wprintf(wszNewLine); wprintf(wszNewLine); //fCertInvalid = TRUE;
} if (0 > CompareFileTime(&pCertInfoCA->NotAfter, &pCertInfo->NotAfter)) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_CANOTAFTER_ERROR)); // "ERROR: Cert Expires after issuing CA Cert Expires"
wprintf(wszNewLine); wprintf(wszNewLine); //fCertInvalid = TRUE;
}
VerifyCACert(pCertInfoCA, TRUE, &CAState); VerifyCACert(pCertInfo, FALSE, &CertState);
hr = S_OK;
dwFlags = CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG; //CERT_STORE_REVOCATION_FLAG;
if (g_fVerbose) { wprintf( myLoadResourceString(IDS_FORMAT_CERTVERIFYSUBJECTCERTIFICATECONTEXT_FLAGS), // "CertVerifySubjectCertificateContext Flags = %x --> "
dwFlags); }
if (!CertVerifySubjectCertificateContext( pCertContext, pCertContextCA, &dwFlags)) { hr = myHLastError(); if (g_fVerbose) { wprintf(wszNewLine); fflush(stdout); } _JumpError(hr, error, "CertVerifySubjectCertificateContext"); } if (g_fVerbose) { wprintf(L"%x\n", dwFlags); } if (0 != dwFlags) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_ERR_FORMAT_VALIDATION), // "ERROR: Certificate validation failure: %x"
dwFlags); wprintf(wszNewLine); } if (CERT_STORE_SIGNATURE_FLAG & dwFlags) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_ERR_CA_SIG_NOT_ISSUER)); // "ERROR: CA did not issue Certificate: Signature check failed"
wprintf(wszNewLine); } else { wprintf(myLoadResourceString(IDS_CERT_SIG_OK)); // "Certificate signature is valid"
} wprintf(wszNewLine);
if (CERT_STORE_TIME_VALIDITY_FLAG & dwFlags) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_ERR_EXPIRED)); // "ERROR: Certificate has expired"
wprintf(wszNewLine); } else { wprintf(myLoadResourceString(IDS_CERT_CURRENT)); // "Certificate is current"
} wprintf(wszNewLine);
if (0 != dwFlags) { wprintf(wszNewLine); fCertInvalid = TRUE; }
for (i = 0; i < pCertInfo->cExtension; i++) { CERT_EXTENSION *pce;
pce = &pCertInfo->rgExtension[i]; //wprintf(L"%d: %hs: %d, %x (%x)\n", i, pce->pszObjId, pce->fCritical, pce->Value.pbData, pce->Value.cbData);
if (0 == strcmp(pce->pszObjId, szOID_AUTHORITY_KEY_IDENTIFIER2)) { BOOL fKeyAuthorityMatch;
//wprintf(L"%d: %ws\n", i, L"szOID_AUTHORITY_KEY_IDENTIFIER2");
hr = cuVerifyKeyAuthority( &pCertInfo->Issuer, pCertInfoCA, pce->Value.pbData, pce->Value.cbData, FALSE, &fKeyAuthorityMatch); _JumpIfError(hr, error, "cuVerifyKeyAuthority");
if (!fKeyAuthorityMatch) { fCertInvalid = TRUE; } } else if (0 == strcmp(pce->pszObjId, szOID_KEY_ATTRIBUTES)) { //wprintf(L"%d: %ws\n", i, L"szOID_KEY_ATTRIBUTES");
} else if (0 == strcmp(pce->pszObjId, szOID_CRL_DIST_POINTS)) { //wprintf(L"%d: %ws\n", i, L"szOID_CRL_DIST_POINTS");
wprintf(myLoadResourceString(IDS_CRL_DIST_POINTS)); // "Contains CRL_DIST_POINTS revocation-check extension"
wprintf(wszNewLine); fCheckRevocation = TRUE; } else if (0 == strcmp(pce->pszObjId, szOID_NETSCAPE_REVOCATION_URL)) { //wprintf(L"%d: %ws\n", i, L"szOID_NETSCAPE_REVOCATION_URL");
wprintf(myLoadResourceString(IDS_NETSCAPE_REVOCATION_URL)); // "Contains NETSCAPE_REVOCATION_URL revocation-check extension"
wprintf(wszNewLine); fCheckRevocation = TRUE; } } if (fCheckRevocation) { if (!g_fCryptSilent) { RevState = VerifyRevocation(pCertContext, pCertContextCA); } } else { wprintf(myLoadResourceString(IDS_NO_REVCHECKEXTENSION)); // "Certificate has no revocation-check extension"
wprintf(wszNewLine); RevState = RS_INCOMPLETE; }
error: cuUnloadCert(&pCertContext); cuUnloadCert(&pCertContextCA); if (NULL != pbKeyId) { LocalFree(pbKeyId); } if (NULL != pbKeyIdCACrossed) { LocalFree(pbKeyIdCACrossed); } if (S_OK == hr) { DWORD msgid;
wprintf(wszNewLine); wprintf( myLoadResourceString( fCertInvalid? IDS_FORMAT_NOT_VERIFY : // "%ws does NOT verify as issued by %ws"
IDS_FORMAT_IS_VERIFY), // "%ws verifies as issued by %ws"
pwszfnCert, pwszfnCertCA);
switch (RevState) { case RS_FAIL: msgid = IDS_FORMAT_REVCHECK_FAIL; // " -- Revocation check FAILED."
break;
case RS_PASS: msgid = IDS_FORMAT_REVCHECK_PASS; // " -- Revocation check passed."
break;
case RS_REVOKED: msgid = IDS_FORMAT_REVCHECK_REVOKED; // " -- Revocation check: REVOKED."
break;
default: msgid = IDS_FORMAT_REVCHECK_SKIPPED; // " -- Revocation check skipped."
break; } wprintf(myLoadResourceString(msgid)); wprintf(wszNewLine); if (fCertInvalid) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); } } return(hr); }
HRESULT VerifyCRLAgainstCACert( IN WCHAR const *pwszfnCRL, IN WCHAR const *pwszfnCertCA, OPTIONAL IN WCHAR const *pwszfnCertEE, // or delta CRL
OUT BOOL *pfCRLLoaded) { HRESULT hr; CRL_CONTEXT const *pCRLContext = NULL; CRL_CONTEXT const *pCRLContextDelta = NULL; CERT_CONTEXT const *pCertContextCA = NULL; CERT_CONTEXT const *pCertContextEE = NULL; CRL_INFO const *pCRLInfo; CRL_INFO const *pCRLInfoDelta; CERT_INFO const *pCertInfoCA; CERT_INFO const *pCertInfoEE; BOOL fDisplayCANames = g_fVerbose; DWORD i; BOOL fCRLInvalid = FALSE; SYSTEMTIME st; FILETIME ft; DWORD dwNameIdCRL; DWORD dwNameIdCert;
// Load and decode CRL and certificate
*pfCRLLoaded = FALSE; hr = cuLoadCRL(pwszfnCRL, &pCRLContext); if (S_OK != hr) { cuPrintError(IDS_FORMAT_LOADTESTCRL, hr); goto error; } *pfCRLLoaded = TRUE; pCRLInfo = pCRLContext->pCrlInfo;
hr = cuLoadCert(pwszfnCertCA, &pCertContextCA); if (S_OK != hr) { cuPrintError(IDS_FORMAT_LOADCACERT, hr); goto error; } pCertInfoCA = pCertContextCA->pCertInfo; if (NULL != pwszfnCertEE) { hr = cuLoadCert(pwszfnCertEE, &pCertContextEE); if (S_OK != hr) { hr = cuLoadCRL(pwszfnCertEE, &pCRLContextDelta); if (S_OK != hr) { cuPrintError(IDS_FORMAT_LOADTESTCERT, hr); goto error; } pCRLInfoDelta = pCRLContextDelta->pCrlInfo; } else { pCertInfoEE = pCertContextEE->pCertInfo; } }
// Display name info:
hr = cuDisplayCertName( TRUE, myLoadResourceString(IDS_CRL), // "CRL"
myLoadResourceString(IDS_ISSUER), // "Issuer"
g_wszPad4, &pCRLInfo->Issuer, NULL); _JumpIfError(hr, error, "cuDisplayCertName(CRL Issuer)");
hr = cuDisplayCertNames( TRUE, myLoadResourceString(IDS_ISSUINGCACERT), // "Issuing CA Cert"
pCertInfoCA); _JumpIfError(hr, error, "cuDisplayCertNames(CA)");
if (g_fVerbose) { wprintf(wszNewLine); cuDumpSerial(NULL, IDS_ISSUINGCACERT_SERIAL, &pCertInfoCA->SerialNumber);
wprintf(wszNewLine); }
if (!CertCompareCertificateName( X509_ASN_ENCODING, const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Issuer), const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Subject))) { // This API doesn't set LastError
wprintf(myLoadResourceString(IDS_ISSUINGCA_NOT_ROOT)); // "Issuing CA is not a root: Subject name does not match Issuer"
wprintf(wszNewLine); wprintf(wszNewLine); } if (fDisplayCANames) { hr = cuDisplayCertNames( TRUE, myLoadResourceString(IDS_ISSUINGCACERT), // "Issuing CA Cert"
pCertInfoCA); _JumpIfError(hr, error, "cuDisplayCertNames(CA)"); }
if (!CertCompareCertificateName( X509_ASN_ENCODING, const_cast<CERT_NAME_BLOB *>(&pCRLInfo->Issuer), const_cast<CERT_NAME_BLOB *>(&pCertInfoCA->Subject))) { // This API doesn't set LastError
wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_ISSUINGCA_CRLSUBJECT_NOT_ISSUER)); // "ERROR: Issuing CA Subject name does not match CRL Issuer"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; } else { wprintf(myLoadResourceString(IDS_ISSUINGCA_CRLSUBJECT_IS_ISSUER)); // "Issuing CA Subject name matches CRL Issuer"
wprintf(wszNewLine); }
GetSystemTime(&st); if (!SystemTimeToFileTime(&st, &ft)) { hr = myHLastError(); _JumpError(hr, error, "SystemTimeToFileTime"); } if (0 < CompareFileTime(&pCRLInfo->ThisUpdate, &ft)) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_NOWNOTBEFORECRL_ERROR)); // "ERROR: CRL is not yet valid"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; } if ((0 != pCRLInfo->NextUpdate.dwLowDateTime || 0 != pCRLInfo->NextUpdate.dwHighDateTime) && 0 > CompareFileTime(&pCRLInfo->NextUpdate, &ft)) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_NOWNOTAFTERCRL_ERROR)); // "ERROR: CRL has expired"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; }
if (0 < CompareFileTime(&pCertInfoCA->NotBefore, &pCRLInfo->ThisUpdate)) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_CANOTBEFORECRL_ERROR)); // "ERROR: CRL Valid before issuing CA Cert Valid"
wprintf(wszNewLine); wprintf(wszNewLine); //fCRLInvalid = TRUE;
} if ((0 != pCRLInfo->NextUpdate.dwLowDateTime || 0 != pCRLInfo->NextUpdate.dwHighDateTime) && 0 > CompareFileTime(&pCertInfoCA->NotAfter, &pCRLInfo->NextUpdate)) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_CANOTAFTERCRL_ERROR)); // "ERROR: CRL Expires after issuing CA Cert Expires"
wprintf(wszNewLine); wprintf(wszNewLine); //fCRLInvalid = TRUE;
}
// verify CRL signature with the CA Cert public key
if (CryptVerifyCertificateSignature( NULL, X509_ASN_ENCODING, pCRLContext->pbCrlEncoded, pCRLContext->cbCrlEncoded, &pCertContextCA->pCertInfo->SubjectPublicKeyInfo)) { wprintf(myLoadResourceString(IDS_CRL_SIG_OK)); // "CRL signature is valid"
wprintf(wszNewLine); } else { hr = myHLastError(); _PrintError(hr, "CryptVerifyCertificateSignature"); wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_ERR_CA_SIG_NOT_CRLISSUER)); // "ERROR: CA did not issue CRL: Signature check failed"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; }
for (i = 0; i < pCRLInfo->cExtension; i++) { CERT_EXTENSION *pce;
pce = &pCRLInfo->rgExtension[i]; //wprintf(L"%d: %hs: %d, %x (%x)\n", i, pce->pszObjId, pce->fCritical, pce->Value.pbData, pce->Value.cbData);
if (0 == strcmp(pce->pszObjId, szOID_AUTHORITY_KEY_IDENTIFIER2)) { BOOL fKeyAuthorityMatch;
//wprintf(L"%d: %ws\n", i, L"szOID_AUTHORITY_KEY_IDENTIFIER2");
hr = cuVerifyKeyAuthority( &pCRLInfo->Issuer, pCertInfoCA, pce->Value.pbData, pce->Value.cbData, FALSE, &fKeyAuthorityMatch); _JumpIfError(hr, error, "cuVerifyKeyAuthority");
if (!fKeyAuthorityMatch) { fCRLInvalid = TRUE; } } } hr = myGetCRLNameId(pCRLContext, &dwNameIdCRL); _PrintIfError(hr, "myGetCRLNameId");
hr = myGetNameId(pCertContextCA, &dwNameIdCert); _PrintIfError(hr, "myGetNameId");
if (MAXDWORD != dwNameIdCRL && MAXDWORD != dwNameIdCert && dwNameIdCRL != dwNameIdCert) { wprintf(myLoadResourceString(IDS_CRLNAMEID_NOT_CERTNAMEID)); // "WARNING: CRL CA Version does not match Cert CA Version"
wprintf(wszNewLine); wprintf(wszNewLine); //fCRLInvalid = TRUE;
}
if (NULL != pCertContextEE) { BOOL fCertLoaded; wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_VERIFYING_ISSUED_CERT)); // "Verifying Issued Certificate:"
wprintf(wszNewLine); hr = VerifyCertAgainstParent( pwszfnCertEE, pwszfnCertCA, NULL, // pwszfnCertCACrossed
&fCertLoaded); if (S_OK != hr) { _PrintError(hr, "VerifyCertAgainstParent"); fCRLInvalid = TRUE; } wprintf(wszNewLine);
if (!CertCompareCertificateName( X509_ASN_ENCODING, const_cast<CERT_NAME_BLOB *>(&pCertInfoEE->Issuer), const_cast<CERT_NAME_BLOB *>(&pCRLInfo->Issuer))) { // This API doesn't set LastError
wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CRLISSUER_NOT_EEISSUER)); // "ERROR: CRL Issuer does not match Cert Issuer"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; } else { wprintf(myLoadResourceString(IDS_CRLISSUER_IS_EEISSUER)); // "CRL Issuer matches Cert Issuer"
wprintf(wszNewLine); } if (!cuVerifyIDP(pCertContextEE, pCRLContext)) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CRL_IDP_MISMATCH)); // "ERROR: CRL IDP extension does not match Cert CDP"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; } } else if (NULL != pCRLContextDelta) { BOOL fCRLLoaded; BOOL fDelta; DWORD dwNameIdDelta; wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_VERIFYING_DELTA_CRL)); // "Verifying Delta CRL:"
wprintf(wszNewLine); hr = VerifyCRLAgainstCACert( pwszfnCertEE, // pwszfnCRL
pwszfnCertCA, NULL, // pwszfnCertEE
&fCRLLoaded); if (S_OK != hr) { _PrintError(hr, "VerifyCRLAgainstCACert"); fCRLInvalid = TRUE; } wprintf(wszNewLine);
if (!CertCompareCertificateName( X509_ASN_ENCODING, const_cast<CERT_NAME_BLOB *>(&pCRLInfoDelta->Issuer), const_cast<CERT_NAME_BLOB *>(&pCRLInfo->Issuer))) { // This API doesn't set LastError
wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CRLISSUER_NOT_DELTAISSUER)); // "ERROR: CRL Issuer does not match Delta CRL Issuer"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; } else { wprintf(myLoadResourceString(IDS_CRLISSUER_IS_DELTAISSUER)); // "CRL Issuer matches Delta CRL Issuer"
wprintf(wszNewLine); } hr = myIsDeltaCRL(pCRLContext, &fDelta); _JumpIfError(hr, error, "myIsDeltaCRL");
if (fDelta) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CRL_NOT_BASE)); // "ERROR: CRL is not a Base CRL"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; }
hr = myIsDeltaCRL(pCRLContextDelta, &fDelta); _JumpIfError(hr, error, "myIsDeltaCRL");
if (!fDelta) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CRL_NOT_DELTA)); // "ERROR: CRL is not a Delta CRL"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; } hr = myGetCRLNameId(pCRLContextDelta, &dwNameIdDelta); _PrintIfError(hr, "myGetCRLNameId");
if (MAXDWORD != dwNameIdCRL && MAXDWORD != dwNameIdDelta && dwNameIdCRL != dwNameIdDelta) { wprintf(myLoadResourceString(IDS_CRLNAMEID_NOT_DELTANAMEID)); // "WARNING: CRL CA Version does not match Delta CRL CA Version"
wprintf(wszNewLine); wprintf(wszNewLine); //fCRLInvalid = TRUE;
} if (fDelta && !cuVerifyMinimumBaseCRL(pCRLContext, pCRLContextDelta)) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CRL_MINBASE_MISMATCH)); // "ERROR: CRL Number less than Delta CRL Minimum Base"
wprintf(wszNewLine); wprintf(wszNewLine); fCRLInvalid = TRUE; } } hr = S_OK;
error: cuUnloadCRL(&pCRLContext); cuUnloadCert(&pCertContextCA); cuUnloadCert(&pCertContextEE); if (S_OK == hr) { wprintf(wszNewLine); wprintf( myLoadResourceString( fCRLInvalid? IDS_FORMAT_NOT_VERIFY : // "%ws does NOT verify as issued by %ws"
IDS_FORMAT_IS_VERIFY), // "%ws verifies as issued by %ws"
pwszfnCRL, pwszfnCertCA); wprintf(wszNewLine); if (fCRLInvalid) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); } } return(hr); }
HRESULT VerifyBlobAgainstCACert( IN WCHAR const *pwszfnBlob, IN WCHAR const *pwszfnCertCA) { HRESULT hr; CERT_CONTEXT const *pCertContextCA = NULL; CERT_INFO const *pCertInfoCA; BYTE *pbBlob = NULL; DWORD cbBlob; CERT_SIGNED_CONTENT_INFO *pcsci = NULL; DWORD cbcsci; BOOL fSigInvalid = FALSE;
// Load blob and load and decode certificate
hr = DecodeFileW(pwszfnBlob, &pbBlob, &cbBlob, CRYPT_STRING_ANY); if (S_OK != hr) { cuPrintError(IDS_ERR_FORMAT_DECODEFILE, hr); goto error; } if (!myDecodeObject( X509_ASN_ENCODING, X509_CERT, pbBlob, cbBlob, CERTLIB_USE_LOCALALLOC, (VOID **) &pcsci, &cbcsci)) { hr = myHLastError(); _PrintError3( hr, "myDecodeObject", CRYPT_E_ASN1_BADTAG, CRYPT_E_ASN1_EOD); }
hr = cuLoadCert(pwszfnCertCA, &pCertContextCA); if (S_OK != hr) { cuPrintError(IDS_FORMAT_LOADCACERT, hr); goto error; } pCertInfoCA = pCertContextCA->pCertInfo;
hr = cuDumpAsnBinary(pbBlob, cbBlob, MAXDWORD); if (S_OK != hr) { cuPrintError(IDS_ERR_FORMAT_CANNOT_DECODE, hr); goto error; }
// Display name info:
hr = cuDisplayCertNames( TRUE, myLoadResourceString(IDS_ISSUINGCACERT), // "Issuing CA Cert"
pCertInfoCA); _JumpIfError(hr, error, "cuDisplayCertNames(CA)");
if (g_fVerbose) { wprintf(wszNewLine); cuDumpSerial(NULL, IDS_ISSUINGCACERT_SERIAL, &pCertInfoCA->SerialNumber);
wprintf(wszNewLine); }
// verify blob signature with the CA Cert public key
if (CryptVerifyCertificateSignature( NULL, X509_ASN_ENCODING, pbBlob, cbBlob, &pCertContextCA->pCertInfo->SubjectPublicKeyInfo)) { wprintf(myLoadResourceString(IDS_CRL_SIG_OK)); // "CRL signature is valid"
wprintf(wszNewLine); } else { hr = myHLastError(); _PrintError(hr, "CryptVerifyCertificateSignature"); wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_ERR_CA_SIG_NOT_CRLISSUER)); // "ERROR: CA did not issue CRL: Signature check failed"
wprintf(wszNewLine); wprintf(wszNewLine); fSigInvalid = TRUE; } hr = S_OK;
error: if (NULL != pcsci) { LocalFree(pcsci); } if (NULL != pbBlob) { LocalFree(pbBlob); } cuUnloadCert(&pCertContextCA); if (S_OK == hr) { wprintf(wszNewLine); wprintf( myLoadResourceString( fSigInvalid? IDS_FORMAT_NOT_VERIFY : // "%ws does NOT verify as issued by %ws"
IDS_FORMAT_IS_VERIFY), // "%ws verifies as issued by %ws"
pwszfnBlob, pwszfnCertCA); wprintf(wszNewLine); } return(hr); }
HRESULT cuParseOIDList( IN WCHAR const *pwszIn, OUT DWORD *pcOut, OUT char ***pppszOut) { HRESULT hr; WCHAR **ppwszOID = NULL; char **ppszOID = NULL; DWORD cOID; DWORD i;
hr = cuParseStrings(pwszIn, FALSE, NULL, NULL, &ppwszOID, NULL); _JumpIfError2(hr, error, "cuParseStrings", hr);
for (i = 0; NULL != ppwszOID[i]; i++) { hr = myVerifyObjId(ppwszOID[i]); _JumpIfErrorStr2(hr, error, "myVerifyObjId", ppwszOID[i], hr); } if (0 == i) { hr = E_INVALIDARG; _JumpError(hr, error, "No OIDs"); } cOID = i;
ppszOID = (char **) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, (cOID + 1) * sizeof(*ppszOID)); if (NULL == ppszOID) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } for (i = 0; NULL != ppwszOID[i]; i++) { if (!myConvertWszToSz(&ppszOID[i], ppwszOID[i], -1)) { _JumpError(hr, error, "myConvertWszToSz"); } } *pcOut = cOID; *pppszOut = ppszOID; ppszOID = NULL; hr = S_OK;
error: cuFreeStringArray(ppwszOID); cuFreeStringArrayA(ppszOID); return(hr); }
HRESULT verbVerifyCert( IN WCHAR const *pwszOption, IN WCHAR const *pwszfnCert, IN WCHAR const *pwszfnCertCA, IN WCHAR const *pwszfnCertCACrossed, IN WCHAR const *pwszArg4) { HRESULT hr; DWORD cApplicationPolicies; char **ppszApplicationPolicies = NULL; DWORD cIssuancePolicies; char **ppszIssuancePolicies = NULL;
// First check for Application and Issuance policy OID lists
cApplicationPolicies = 0; cIssuancePolicies = 0; if (NULL != pwszfnCertCA) { hr = S_OK; if (!myIsMinusSignString(pwszfnCertCA)) { hr = cuParseOIDList( pwszfnCertCA, &cApplicationPolicies, &ppszApplicationPolicies); _PrintIfErrorStr2(hr, "cuParseOIDList", L"Application", hr); } if (S_OK == hr) { if (NULL != pwszfnCertCACrossed) { hr = cuParseOIDList( pwszfnCertCACrossed, &cIssuancePolicies, &ppszIssuancePolicies); _JumpIfErrorStr2(hr, error, "cuParseOIDList", L"Issuance", hr);
pwszfnCertCACrossed = NULL; } pwszfnCertCA = NULL; } } if (NULL != pwszfnCertCA) { BOOL fCertLoaded;
hr = VerifyCertAgainstParent( pwszfnCert, pwszfnCertCA, pwszfnCertCACrossed, &fCertLoaded); if (S_OK != hr && !fCertLoaded) { BOOL fCRLLoaded;
hr = VerifyCRLAgainstCACert( pwszfnCert, pwszfnCertCA, pwszfnCertCACrossed, &fCRLLoaded); if (S_OK != hr && !fCRLLoaded) { hr = VerifyBlobAgainstCACert(pwszfnCert, pwszfnCertCA); } } } else { hr = VerifyCertAgainstChain( pwszfnCert, cApplicationPolicies, ppszApplicationPolicies, cIssuancePolicies, ppszIssuancePolicies); }
error: cuFreeStringArrayA(ppszApplicationPolicies); cuFreeStringArrayA(ppszIssuancePolicies); return(hr); }
DWORD amsgidState[CHECK7F_COUNT] = { //IDS_CHECK7F_FIELD_UNKNOWN, // "???"
IDS_CHECK7F_FIELD_NONE, // "None"
IDS_CHECK7F_FIELD_OTHER, // "Other"
IDS_CHECK7F_FIELD_ISSUER, // "Issuer"
IDS_CHECK7F_FIELD_ISSUERRDN, // "IssuerRDN"
IDS_CHECK7F_FIELD_ISSUERRDNATTRIBUTE, // "IssuerRDNAttribute"
IDS_CHECK7F_FIELD_ISSUERRDNSTRING, // "IssuerRDNString"
IDS_CHECK7F_FIELD_SUBJECT, // "Subject"
IDS_CHECK7F_FIELD_SUBJECTRDN, // "SubjectRDN"
IDS_CHECK7F_FIELD_SUBJECTRDNATTRIBUTE, // "SubjectRDNAttribute"
IDS_CHECK7F_FIELD_SUBJECTRDNSTRING, // "SubjectRDNString"
IDS_CHECK7F_FIELD_EXTENSIONS, // "Extensions"
IDS_CHECK7F_FIELD_EXTENSIONARRAY, // "ExtensionArray"
IDS_CHECK7F_FIELD_EXTENSION, // "Extension"
IDS_CHECK7F_FIELD_EXTENSIONVALUE, // "ExtensionValue"
IDS_CHECK7F_FIELD_EXTENSIONVALUERAW, // "ExtensionValueRaw"
};
HRESULT verbCheck7f( IN WCHAR const *pwszOption, IN WCHAR const *pwszfnCert, IN WCHAR const *pwszArg2, IN WCHAR const *pwszArg3, IN WCHAR const *pwszArg4) { HRESULT hr; CERT_CONTEXT const *pCertContext = NULL; CERT_INFO const *pCertInfo; WCHAR const *pwszObjectIdDescription = NULL; DWORD i; DWORD dwLen; DWORD index; DWORD index2; DWORD state; DWORD cwcField; DWORD cwcObjectId; WCHAR wszField[128]; WCHAR wszObjectId[40];
// Load and decode certificates
hr = cuLoadCert(pwszfnCert, &pCertContext); if (S_OK != hr) { cuPrintError(IDS_FORMAT_LOADTESTCERT, hr); goto error; } pCertInfo = pCertContext->pCertInfo;
if (g_fVerbose) { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_CERTCOLON)); // "Cert:"
wprintf(wszNewLine); DumpHex(0, pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
// Display name info:
hr = cuDisplayCertNames( TRUE, myLoadResourceString(IDS_CERT), // "Cert"
pCertInfo); _JumpIfError(hr, error, "cuDisplayCertNames(Cert)"); }
cwcField = sizeof(wszField)/sizeof(wszField[0]); cwcObjectId = sizeof(wszObjectId)/sizeof(wszObjectId[0]); hr = myCheck7f( pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, g_fVerbose, &state, &index, &index2, &cwcField, wszField, &cwcObjectId, wszObjectId, &pwszObjectIdDescription); _JumpIfError(hr, error, "myCheck7f");
if (CHECK7F_NONE != state) { DWORD msgid = IDS_CHECK7F_FIELD_UNKNOWN; // "???"
CSASSERT(0 != amsgidState[CHECK7F_COUNT - 1]); if (CHECK7F_COUNT > state) { msgid = amsgidState[state]; } CSASSERT(0 != msgid); wprintf(myLoadResourceString(IDS_FORMAT_SUSPECT_LENGTH)); // "Suspect length in"
wprintf(myLoadResourceString(msgid)); if (0 != index) { wprintf( 0 != index2? L"[%u,%u]" : L"[%u]", index - 1, index2 - 1); } wprintf(L": field=%ws", wszField); wprintf( myLoadResourceString(IDS_FORMAT_FIELD), // ": field=%ws"
wszField); if (0 != index) { wprintf( 0 != index2? L"[%u,%u]" : L"[%u]", index - 1, index2 - 1); } if (L'\0' != wszObjectId[0]) { wprintf( myLoadResourceString(IDS_FORMAT_OID), // ", oid=%ws"
wszObjectId); } if (NULL != pwszObjectIdDescription) { wprintf(L" (%ws)", pwszObjectIdDescription); } wprintf(wszNewLine); hr = CERTSRV_E_ENCODING_LENGTH; }
for (i = 0; i < pCertInfo->cExtension; i++) { CERT_EXTENSION *pce; WCHAR const *pwszDescriptiveName;
pce = &pCertInfo->rgExtension[i]; if (g_fVerbose) { wprintf(wszNewLine); wprintf( myLoadResourceString(IDS_FORMAT_EXTENSION_OID), // "Extension %d: oid=""%hs"" fcrit=%u length=%x"
i, pce->pszObjId, pce->fCritical, pce->Value.cbData); pwszDescriptiveName = cuGetOIDNameA(pce->pszObjId); if (NULL != pwszDescriptiveName) { wprintf(L" (%ws)", pwszDescriptiveName); } wprintf(wszNewLine); DumpHex(0, pce->Value.pbData, pce->Value.cbData); } }
error: cuUnloadCert(&pCertContext); return(hr); }
HRESULT cuVerifySignature( IN BYTE const *pbEncoded, IN DWORD cbEncoded, IN CERT_PUBLIC_KEY_INFO const *pcpki, IN BOOL fSuppressSuccess, IN BOOL fSuppressError) { HRESULT hr; DWORD id = 0;
// verify with the passed public key
if (!CryptVerifyCertificateSignature( NULL, X509_ASN_ENCODING, const_cast<BYTE *>(pbEncoded), cbEncoded, const_cast<CERT_PUBLIC_KEY_INFO *>(pcpki))) { hr = myHLastError(); if (E_INVALIDARG == hr) { CRYPT_DATA_BLOB Blob;
Blob.cbData = cbEncoded; Blob.pbData = const_cast<BYTE *>(pbEncoded); if (!CryptVerifyCertificateSignatureEx( NULL, // hCryptProv
X509_ASN_ENCODING, CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &Blob, CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, // pvIssuer
0, // dwFlags
NULL)) // pvReserved
{ HRESULT hr2 = myHLastError();
_PrintError(hr2, "CryptVerifyCertificateSignatureEx"); } else { hr = S_OK; if (!fSuppressSuccess) { id = IDS_NULL_SIGNATUREMATCHES; // "NULL signature verifies"
} } } if (S_OK != hr && !fSuppressError) { id = IDS_ERR_FORMAT_NO_SIGNATUREMATCHES; // "Signature does not match Public key: %x"
} } else { hr = S_OK; if (!fSuppressSuccess) { id = IDS_SIGNATUREMATCHES; // "Signature matches Public Key"
} } if (0 != id) { wprintf(myLoadResourceString(id), hr); wprintf(wszNewLine); } return(hr); }
|