I am trying to write code that reads signatures (certificates) from DLLs or and EXEs. Most DLLs or EXEs have only one signature, and my code reads all certificates associate
Expanding the Dima's answer, I want to provide a sample code which demonstrates how to check all embedded (and nested) leaf (not in the middle of the certificate chain) certificates.
BOOL CheckCertificateIssuer(HANDLE hWVTStateData, const std::set &stValidIssuers)
{
CRYPT_PROVIDER_DATA *pCryptProvData = WTHelperProvDataFromStateData(hWVTStateData);
CRYPT_PROVIDER_SGNR *pSigner = WTHelperGetProvSignerFromChain(pCryptProvData, 0, FALSE, 0);
CRYPT_PROVIDER_CERT *pCert = WTHelperGetProvCertFromChain(pSigner, 0);
CString sIssuer;
int nLength = CertGetNameString(pCert->pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0);
if (!nLength)
{
ASSERT(FALSE && "Cannot get the length of the Issuer string");
return FALSE;
}
if (!CertGetNameString(pCert->pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, sIssuer.GetBuffer(nLength), nLength))
{
ASSERT(FALSE && "Cannot get the Issuer string");
return FALSE;
}
sIssuer.ReleaseBuffer(nLength);
if (stValidIssuers.find(sIssuer) == stValidIssuers.end())
{
ASSERT(FALSE && "Certificate issuer is invalid");
return FALSE;
}
return TRUE;
}
BOOL CheckCertificate(CString filename)
{
std::set stValidIssuers;
stValidIssuers.insert(L"VeriSign Class 3 Code Signing 2010 CA");
stValidIssuers.insert(L"Symantec Class 3 SHA256 Code Signing CA");
bool UseStrongSigPolicy = false;
DWORD Error = ERROR_SUCCESS;
bool WintrustCalled = false;
GUID GenericActionId = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_DATA WintrustData = {};
WINTRUST_FILE_INFO FileInfo = {};
WINTRUST_SIGNATURE_SETTINGS SignatureSettings = {};
CERT_STRONG_SIGN_PARA StrongSigPolicy = {};
// Setup data structures for calling WinVerifyTrust
WintrustData.cbStruct = sizeof(WINTRUST_DATA);
WintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
WintrustData.dwUIChoice = WTD_UI_NONE;
WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WintrustData.dwUnionChoice = WTD_CHOICE_FILE;
FileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO_);
FileInfo.pcwszFilePath = filename;
WintrustData.pFile = &FileInfo;
//
// First verify the primary signature (index 0) to determine how many secondary signatures
// are present. We use WSS_VERIFY_SPECIFIC and dwIndex to do this, also setting
// WSS_GET_SECONDARY_SIG_COUNT to have the number of secondary signatures returned.
//
SignatureSettings.cbStruct = sizeof(WINTRUST_SIGNATURE_SETTINGS);
SignatureSettings.dwFlags = WSS_GET_SECONDARY_SIG_COUNT | WSS_VERIFY_SPECIFIC;
SignatureSettings.dwIndex = 0;
WintrustData.pSignatureSettings = &SignatureSettings;
if (UseStrongSigPolicy != false)
{
StrongSigPolicy.cbSize = sizeof(CERT_STRONG_SIGN_PARA);
StrongSigPolicy.dwInfoChoice = CERT_STRONG_SIGN_OID_INFO_CHOICE;
StrongSigPolicy.pszOID = szOID_CERT_STRONG_SIGN_OS_CURRENT;
WintrustData.pSignatureSettings->pCryptoPolicy = &StrongSigPolicy;
}
BOOL bResult = E_NOT_SET;
TRACE(L"Verifying primary signature... ");
Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
WintrustCalled = true;
if (Error == ERROR_SUCCESS)
{
if (CheckCertificateIssuer(WintrustData.hWVTStateData, stValidIssuers))
{
if (bResult == E_NOT_SET)
bResult = TRUE;
}
else
{
bResult = FALSE;
}
TRACE(L"Success!\n");
TRACE(L"Found %d secondary signatures\n", WintrustData.pSignatureSettings->cSecondarySigs);
// Now attempt to verify all secondary signatures that were found
for (DWORD x = 1; x <= WintrustData.pSignatureSettings->cSecondarySigs; x++)
{
TRACE(L"Verify secondary signature at index %d... ", x);
// Need to clear the previous state data from the last call to WinVerifyTrust
WintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
if (Error != ERROR_SUCCESS)
{
//No need to call WinVerifyTrust again
WintrustCalled = false;
TRACE(L"%s", utils::error::getText(Error));
ASSERT(FALSE);
break;
}
WintrustData.hWVTStateData = NULL;
// Caller must reset dwStateAction as it may have been changed during the last call
WintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
WintrustData.pSignatureSettings->dwIndex = x;
Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
if (Error != ERROR_SUCCESS)
{
TRACE(L"%s", utils::error::getText(Error));
ASSERT(FALSE);
break;
}
if (CheckCertificateIssuer(WintrustData.hWVTStateData, stValidIssuers))
{
if (bResult == E_NOT_SET)
bResult = TRUE;
}
else
{
bResult = FALSE;
}
TRACE(L"Success!\n");
}
}
else
{
TRACE(utils::error::getText(Error));
ASSERT(FALSE);
}
//
// Caller must call WinVerifyTrust with WTD_STATEACTION_CLOSE to free memory
// allocate by WinVerifyTrust
//
if (WintrustCalled != false)
{
WintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
}
return bResult;
}