Search code examples
c++winapiwinverifytrust

WinVerifyTrust only works when using a file not a memory blob


I am trying to the WinVerifyTrust function to verify the signature of a msi.

And while this works for files on the file system I cannot get it to work with a memory blob.
This basis of my example to show the problem is the example program from microsoft

BOOL VerifyEmbeddedSignature(LPCWSTR pwszSourceFile)
{
   std::basic_ifstream<BYTE> file(pwszSourceFile, std::ios::binary);
  std::vector<BYTE> data((std::istreambuf_iterator<BYTE>(file)),std::istreambuf_iterator<BYTE>());

  LONG lStatus;

  /*
  // this works
  WINTRUST_FILE_INFO FileData;
  memset(&FileData, 0, sizeof(FileData));
  FileData.cbStruct = sizeof(WINTRUST_FILE_INFO);
  FileData.pcwszFilePath = pwszSourceFile;
  FileData.hFile = NULL;
  FileData.pgKnownSubject = NULL;
  */
  WINTRUST_BLOB_INFO FileData{};
  memset(&FileData, 0, sizeof(FileData));
  FileData.cbStruct = sizeof(WINTRUST_BLOB_INFO);
  FileData.gSubject = WIN_TRUST_SUBJTYPE_RAW_FILE;
  FileData.cbMemObject = static_cast<DWORD>(data.size());
  FileData.pbMemObject = data.data();

  GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  WINTRUST_DATA WinTrustData;
  memset(&WinTrustData, 0, sizeof(WinTrustData));
  WinTrustData.cbStruct = sizeof(WinTrustData);
  WinTrustData.pPolicyCallbackData = NULL;
  WinTrustData.pSIPClientData = NULL;
  WinTrustData.dwUIChoice = WTD_UI_NONE;
  WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
  //WinTrustData.dwUnionChoice = WTD_CHOICE_FILE; -- works
  WinTrustData.dwUnionChoice = WTD_CHOICE_BLOB;
  WinTrustData.dwStateAction = WTD_STATEACTION_VERIFY;
  WinTrustData.hWVTStateData = NULL;
  WinTrustData.pwszURLReference = NULL;
  WinTrustData.dwUIContext = 0;
  WinTrustData.pBlob = &FileData;
  //WinTrustData.pFile = &FileData; -- works

  lStatus = WinVerifyTrust(
    NULL,
    &WVTPolicyGUID,
    &WinTrustData);

  WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE;
  WinVerifyTrust(
    NULL,
    &WVTPolicyGUID,
    &WinTrustData);

  return lStatus == ERROR_SUCCESS;
}

In the above example using the WINTRUST_FILE_INFO works but the WINTRUST_BLOB_INFO does not. The error that I get with a memory blob is always TRUST_E_PROVIDER_UNKNOWN.

I assume that the problem might be the WIN_TRUST_SUBJTYPE_RAW_FILE subject type but I don't know which one I should use for a msi file. I am wondering if the sign check is possible at all with memory blobs of msi files.


Solution

  • The WIN_TRUST_SUBJTYPE_RAW_FILE is not the suitable subject GUID. You could The function CryptSIPRetrieveSubjectGuid retrieves a GUID based on the header information in a specified file.