VerifySignature.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. //-------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. // Example of verifying the embedded signature of a PE file by using
  4. // the WinVerifyTrust function.
  5. #define _UNICODE 1
  6. #define UNICODE 1
  7. #include "../stdafx.h"
  8. #include <windows.h>
  9. #include <tchar.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <Softpub.h>
  13. #include <wincrypt.h>
  14. #include <wintrust.h>
  15. void OutputDebugStringFmt2(LPCTSTR lpOutputString, ...)
  16. {
  17. //setup the variable argument list
  18. va_list args;
  19. va_start(args, lpOutputString);
  20. int nCount = _vsctprintf(lpOutputString, args ) + 1;
  21. //allocate the fromatted string
  22. TCHAR *pszFormatted = new TCHAR[nCount];
  23. if(pszFormatted)
  24. {
  25. //format the string
  26. _vstprintf_s(pszFormatted, nCount, lpOutputString, args);
  27. //copy to the output buffer
  28. OutputDebugString(pszFormatted);
  29. //cleanup local pointers
  30. delete [] pszFormatted;
  31. pszFormatted = NULL;
  32. }
  33. return;
  34. }
  35. #ifndef TRACE
  36. #ifdef _DEBUG
  37. #define TRACE OutputDebugStringFmt2
  38. #else //#ifdef _DEBUG
  39. #define TRACE
  40. #endif //#ifdef _DEBUG
  41. #endif //#ifndef TRACE
  42. // Link with the Wintrust.lib file.
  43. #pragma comment (lib, "wintrust")
  44. BOOL VerifyEmbeddedSignature( LPCWSTR pwszSourceFile )
  45. {
  46. return TRUE;
  47. // Initialize the WINTRUST_FILE_INFO structure.
  48. WINTRUST_FILE_INFO FileData;
  49. memset(&FileData, 0, sizeof(FileData));
  50. FileData.cbStruct = sizeof(WINTRUST_FILE_INFO);
  51. FileData.pcwszFilePath = pwszSourceFile;
  52. FileData.hFile = NULL;
  53. FileData.pgKnownSubject = NULL;
  54. /*
  55. WVTPolicyGUID specifies the policy to apply on the file
  56. WINTRUST_ACTION_GENERIC_VERIFY_V2 policy checks:
  57. 1) The certificate used to sign the file chains up to a root
  58. certificate located in the trusted root certificate store. This
  59. implies that the identity of the publisher has been verified by
  60. a certification authority.
  61. 2) In cases where user interface is displayed (which this example
  62. does not do), WinVerifyTrust will check for whether the
  63. end entity certificate is stored in the trusted publisher store,
  64. implying that the user trusts content from this publisher.
  65. 3) The end entity certificate has sufficient permission to sign
  66. code, as indicated by the presence of a code signing EKU or no
  67. EKU.
  68. */
  69. GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  70. // Initialize the WinVerifyTrust input data structure.
  71. WINTRUST_DATA WinTrustData;
  72. memset(&WinTrustData, 0, sizeof(WinTrustData)); // Default all fields to 0.
  73. WinTrustData.cbStruct = sizeof(WinTrustData);
  74. WinTrustData.pPolicyCallbackData = NULL; // Use default code signing EKU.
  75. WinTrustData.pSIPClientData = NULL; // No data to pass to SIP.
  76. WinTrustData.dwUIChoice = WTD_UI_NOGOOD; // Disable WVT UI. //WTD_UI_NONE; WTD_UI_ALL; WTD_UI_NOGOOD; //NOGOOD will not display a dialog for no signature
  77. WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE; // No revocation checking.
  78. WinTrustData.dwUnionChoice = WTD_CHOICE_FILE; // Verify an embedded signature on a file.
  79. WinTrustData.dwStateAction = 0; // Default verification.
  80. WinTrustData.hWVTStateData = NULL; // Not applicable for default verification of embedded signature.
  81. WinTrustData.pwszURLReference = NULL; // Not used.
  82. WinTrustData.dwProvFlags = WTD_SAFER_FLAG; // Default.
  83. WinTrustData.dwUIContext = 0; // This is not applicable if there is no UI because it changes the UI to accommodate running applications instead of installing applications.
  84. WinTrustData.pFile = &FileData; // Set pFile.
  85. // WinVerifyTrust verifies signatures as specified by the GUID and Wintrust_Data.
  86. LONG lStatus = WinVerifyTrust( NULL, &WVTPolicyGUID, &WinTrustData );
  87. switch (lStatus)
  88. {
  89. case ERROR_SUCCESS:
  90. /*
  91. Signed file:
  92. - Hash that represents the subject is trusted.
  93. - Trusted publisher without any verification errors.
  94. - UI was disabled in dwUIChoice. No publisher or time stamp chain errors.
  95. - UI was enabled in dwUIChoice and the user clicked "Yes" when asked to run the signed subject.
  96. */
  97. TRACE( _T("The file \"%s\" is signed and the signature was verified.\n"), pwszSourceFile );
  98. break;
  99. case TRUST_E_NOSIGNATURE:
  100. {
  101. // The file was not signed or had a signature that was not valid.
  102. // Get the reason for no signature.
  103. DWORD dwLastError = GetLastError();
  104. if( dwLastError == TRUST_E_NOSIGNATURE
  105. || dwLastError == TRUST_E_SUBJECT_FORM_UNKNOWN
  106. || dwLastError == TRUST_E_PROVIDER_UNKNOWN )
  107. {
  108. // The file was not signed.
  109. TRACE( _T("The file \"%s\" is not signed.\n"), pwszSourceFile );
  110. if(IDYES==::MessageBox( NULL, L"The TWAIN DSM is not signed.\nContinue to load this DSM?", L"The TWAIN DSM Signature", MB_YESNO|MB_ICONQUESTION))
  111. {
  112. lStatus = ERROR_SUCCESS;
  113. }
  114. }
  115. else
  116. {
  117. // The signature was not valid or there was an error opening the file.
  118. TRACE( _T("An unknown error occurred trying to verify the signature of the \"%s\" file.\n"), pwszSourceFile );
  119. lStatus = dwLastError;
  120. }
  121. }
  122. break;
  123. case TRUST_E_EXPLICIT_DISTRUST:
  124. // The hash that represents the subject or the publisher is not allowed by the admin or user.
  125. TRACE( _T("The signature is present, but specifically disallowed.\n") );
  126. break;
  127. case TRUST_E_SUBJECT_NOT_TRUSTED:
  128. // The user clicked "No" when asked to install and run.
  129. TRACE( _T("The signature is present, but not trusted.\n") );
  130. break;
  131. case CRYPT_E_SECURITY_SETTINGS:
  132. // The hash that represents the subject or the publisher was not explicitly trusted
  133. // by the admin and the admin policy has disabled user trust. No signature, publisher
  134. // or time stamp errors.
  135. TRACE( _T("CRYPT_E_SECURITY_SETTINGS - The hash representing the subject or the ")
  136. _T("publisher wasn't explicitly trusted by the admin and admin policy has ")
  137. _T("disabled user trust. No signature, publisher or timestamp errors.\n") );
  138. break;
  139. case CERT_E_UNTRUSTEDROOT:
  140. TRACE( _T("A certificate chain processed, but terminated in a root ")
  141. _T("certificate which is not trusted by the trust provider.\n") );
  142. break;
  143. default:
  144. // The UI was disabled in dwUIChoice or the admin policy
  145. // has disabled user trust. lStatus contains the
  146. // publisher or time stamp chain error.
  147. TRACE( _T("Error is:%d \n"), lStatus );
  148. break;
  149. }
  150. LPVOID lpMsgBuf;
  151. if( lStatus != ERROR_SUCCESS
  152. && FormatMessage(
  153. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  154. FORMAT_MESSAGE_FROM_SYSTEM |
  155. FORMAT_MESSAGE_IGNORE_INSERTS,
  156. NULL,
  157. (DWORD)lStatus,
  158. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  159. (LPTSTR) &lpMsgBuf,
  160. 0,
  161. NULL ))
  162. {
  163. TRACE(_T("Error: %s \n"), (LPCTSTR)lpMsgBuf);
  164. {
  165. HWND hWnd = NULL;
  166. ::MessageBox( hWnd, (LPCTSTR)lpMsgBuf, L"signature", MB_OK|MB_ICONEXCLAMATION);
  167. }
  168. // Free the buffer.
  169. LocalFree( lpMsgBuf );
  170. }
  171. return lStatus==ERROR_SUCCESS;
  172. }