Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

481 lines
21 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: protrust.h
  8. //
  9. // Contents: Protected Trust Provider
  10. // API Prototypes and Definitions
  11. //
  12. // Implements a generic trust provider that allows verification of certifciates
  13. // and uses a call back to check the policy. The policy is called for each signature
  14. // in the subject and for each signer within the signature
  15. //
  16. // Documentation is at the bottom of the file.
  17. //
  18. //--------------------------------------------------------------------------
  19. #ifndef _PROTRUST_H_
  20. #define _PROTRUST_H_
  21. #include "signcde.h"
  22. #ifdef __cplusplus
  23. extern "C" {
  24. #endif
  25. //+-------------------------------------------------------------------------
  26. // PROTRUST optional certificate verification checks (elements to check)
  27. //--------------------------------------------------------------------------
  28. // PROTRUST_CERT_SIGNATURE_FLAG - verify certificate signature
  29. // PROTRUST_CERT_TIME_VALIDITY_FLAG - verify certificate time
  30. // PROTRUST_CERT_REVOCATION_VALIDITY_FLAG - verify revocation of certificates
  31. //
  32. // PROTRUST_TIMESTAMP_SIGNATURE_FLAG - verify timestamp certificate
  33. // PROTRUST_TRUST_TEST_ROOT - verify up to the test root
  34. #define PROTRUST_CERT_SIGNATURE_FLAG CERT_STORE_SIGNATURE_FLAG
  35. #define PROTRUST_CERT_TIME_VALIDITY_FLAG CERT_STORE_TIME_VALIDITY_FLAG
  36. #define PROTRUST_CERT_REVOCATION_VALIDITY_FLAG CERT_STORE_REVOCATION_FLAG
  37. #define PROTRUST_TIMESTAMP_SIGNATURE_FLAG 0x00040000
  38. #define PROTRUST_TRUST_TEST_ROOT 0x00080000
  39. //+-------------------------------------------------------------------------
  40. // PROTRUST signature verification (elements that failed; See dwStatusFlags below)
  41. //--------------------------------------------------------------------------
  42. // PROTRUST_TIME_FLAG - Time of the signer certificate is not valid
  43. // PROTRUST_DIGEST_FLAG - digest of signature did not verify
  44. // PROTRUST_ROOT_FLAG - unable to find a trusted root
  45. // (NOTE. check pRoot to see if a root was found)
  46. // These flags are supplied only to a policy call back. They are not returned
  47. // to the caller of WinVerifyTrust.
  48. #define PROTRUST_TIME_FLAG 0x20000000 // Time of a certificate in chain is not valid
  49. #define PROTRUST_DIGEST_FLAG 0x40000000 //
  50. #define PROTRUST_ROOT_FLAG 0x80000000
  51. //+-------------------------------------------------------------------------
  52. #define REGSTR_PATH_PROTRUST REGSTR_PATH_SERVICES "\\WinTrust\\TrustProviders\\Protected Trust"
  53. #define WIN_PROTECTED_ACTION \
  54. { 0xa692ba40, 0x6da8, 0x11d0, { 0xa7, 0x0, 0x0, 0xa0, 0xc9, 0x3, 0xb8, 0x3d } }
  55. // Policy Information supplied to the call back, Use only what is required to
  56. // determine if the signature is to be trusted.
  57. typedef struct _PROTECTED_POLICY_INFO {
  58. HCRYPTPROV hCryptProv; // The provider used in verfication
  59. DWORD dwEncodingType; // Encoding type of certificate
  60. DWORD dwSignCount; // Signature, may be more then one signature
  61. DWORD dwSigner; // Which signer in signature, may be more then one signer
  62. DWORD dwVerifyFlags; // Search flags used to find certificates in chain
  63. PCCERT_CONTEXT pCertContext; // Signing Certificate found
  64. PCCERT_CONTEXT pRoot; // Root Certificate found
  65. PCCERT_CONTEXTLIST pCertChain; // Chain used to verify certificate
  66. FILETIME sTime; // Valid date for certificates (ie time stamp)
  67. CRYPT_DIGEST_BLOB sDigest; // Digest (unsigned hash) from signature
  68. PCRYPT_ATTRIBUTES pAuthenticatedAttributes; // List of authenticated attributes
  69. PCRYPT_ATTRIBUTES pUnauthenticatedAttributes; // List of unauthenticated attributes
  70. PBYTE pbSignature; // Encoded Signature
  71. DWORD cbSignature; // Size of Encoded Signature
  72. DWORD dwStatusFlags; // Status flags defined in PROTECTED trust model
  73. } PROTECTED_POLICY_INFO, *PPROTECTED_POLICY_INFO;
  74. // PROTECTED Trust Policy is defined as:
  75. typedef HRESULT (WINAPI *_PROTECTED_TRUST_POLICY)(IN HANDLE hClientToken,
  76. IN PPROTECTED_POLICY_INFO pInfo);
  77. // Policy List is defined as:
  78. typedef struct _PROTECTED_TRUST_INFO {
  79. DWORD cbSize; // sizeof(_PROTECTED_TRUST_POLICY_LIST)
  80. DWORD dwVerifyFlags; // Should contain at least PROTRUST_CERT_SIGNATURE_FLAG
  81. DWORD dwCertEncodingType; // Optional, defaults to X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
  82. HCRYPTPROV hCryptProv; // Optional, pass in provider for doing verification
  83. HCERTSTORE hTrustedStore; // Optional, list of trusted roots
  84. HCERTSTORE hCertificateStore; // Optional, additional certs to use in verification
  85. _PROTECTED_TRUST_POLICY pfnPolicy; // Optional, application defined user policy
  86. } PROTECTED_TRUST_INFO, *PPROTECTED_TRUST_INFO;
  87. typedef struct _PROTECTED_TRUST_ACTDATA_CALLER_CONTEXT {
  88. HANDLE hClientToken;
  89. GUID * SubjectType;
  90. WIN_TRUST_SUBJECT Subject;
  91. PROTECTED_TRUST_INFO sTrustInfo;
  92. } PROTECTED_TRUST_ACTDATA_CALLER_CONTEXT, *LPPROTECTED_TRUST_ACTDATA_CALLER_CONTEXT;
  93. // The policy provider must use the following return codes
  94. // Returns S_OK: - valid signature, returns from the trust provider
  95. // S_FALSE: - continue on to the next signature or signer
  96. // ERROR: - aborts trust provider and exists with this error code.
  97. //
  98. //---------------------------------------------------------------------------
  99. /*
  100. Generic Trust Provider
  101. Usage: The generic trust provider is designed to provide a flexible manner for
  102. implementing a policy where the developer can let the provider do as much or
  103. as little of the decision making as required. Verifying is composed of two stages,
  104. the first is to determine if the signature matches the item that was signed. The
  105. second stage is to determine if the certificate used to do the signing was valid.
  106. This second stage is dependent on the policy of the calling application, criteria
  107. like, root certificates, specific signature certicates, certificate extensions can
  108. all be used to determine if the signature is valid.
  109. There are three ways of using the generic trust provider (GTB) to do the verification,
  110. 1) let the GTB verify the digest and verify the certificate.
  111. 2) let the GTB verify the digest and verify the certificate supplying the GTB root
  112. certificates that can be trusted.
  113. 3) supply a policy call back that the GTB calls providing the signature, certificates
  114. and its status for the digest and the certifcate to the policy call back.
  115. METHOD 1) Let the trust provider do the verfication
  116. Fill in a PROTECTED_TRUST_INFO structure. The only fields that must be filled in are
  117. cbSize and dwVerifyFlags. dwVerifyFlags specify how to determine if the signing certificate
  118. and all the issuer certificates are valid (validity flags can be combined).
  119. cbSize = sizeof(PROTECTED_TRUST_INFO);
  120. dwVerifyFlags = zero or more of PROTRUST_CERT_SIGNATURE_FLAG
  121. PROTRUST_CERT_TIME_VALIDITY_FLAG
  122. PROTRUST_TIMESTAMP_SIGNATURE_FLAG
  123. PROTRUST_TRUST_TEST_ROOT.
  124. (where:
  125. PROTRUST_CERT_SIGNATURE_FLAG - verify certificates on signatures
  126. (ie find the issuer certificate and
  127. verify the signature of the certificate).
  128. PROTRUST_CERT_TIME_VALIDITY_FLAG - verify that the certificate is
  129. valid at the current time.
  130. PROTRUST_TIMESTAMP_SIGNATURE_FLAG - verify that the certificate was
  131. valid at the time a time-stamp was
  132. placed on the signature. If there
  133. is no time stamp then use the current time.
  134. PROTRUST_TRUST_TEST_ROOT - Verifying the certifcate chain to the test
  135. root is valid.)
  136. WinVerifyTrust will return:
  137. S_OK - signature verified
  138. TRUST_E_NOSIGNATURE - no signature found
  139. NTE_BAD_SIGNATURE - signature did not verify to digest
  140. CERT_E_UNTRUSTEDROOT - verifyied to an untrusted root
  141. CERT_E_CHAINING - a certificate could not be verified (issuer not found)
  142. CERT_E_EXPIRED - a valid certificate chain could not be found
  143. (ceritifcate or issuer expired)
  144. METHOD 2) Let the trust provider verify to a list of certificates.
  145. Add a store to the PROTECTED_TRUST_INFO structure in addition to the entries
  146. specified in method 1.
  147. hTrustedStore = a store that contains all roots that are to be trusted.
  148. (This store can be opened using CertOpenSystemStore etc.)
  149. cbSize = sizeof(PROTECTED_TRUST_INFO);
  150. dwVerifyFlags = zero or more of PROTRUST_CERT_SIGNATURE_FLAG
  151. PROTRUST_CERT_TIME_VALIDITY_FLAG
  152. PROTRUST_TIMESTAMP_SIGNATURE_FLAG
  153. PROTRUST_TRUST_TEST_ROOT.
  154. (where:
  155. PROTRUST_CERT_SIGNATURE_FLAG - verify certificates on signatures
  156. (ie find the issuer certificate and
  157. verify the signature of the certificate).
  158. PROTRUST_CERT_TIME_VALIDITY_FLAG - verify that the certificate is
  159. valid at the current time.
  160. PROTRUST_TIMESTAMP_SIGNATURE_FLAG - verify that the certificate was
  161. valid at the time a time-stamp was
  162. placed on the signature. If there
  163. is no time stamp then use the current time.
  164. PROTRUST_TRUST_TEST_ROOT - Verifying the certifcate chain to the test
  165. root is valid.)
  166. WinVerifyTrust will return:
  167. S_OK - signature verified
  168. TRUST_E_NOSIGNATURE - no signature found
  169. NTE_BAD_SIGNATURE - signature did not verify to digest
  170. CERT_E_UNTRUSTEDROOT - verifyied to an untrusted root
  171. CERT_E_CHAINING - a certificate could not be verified (issuer not found)
  172. CERT_E_EXPIRED - a valid certificate chain could not be found
  173. (ceritifcate or issuer expired)
  174. METHOD 3) Pass in a policy call back that is called prior to returning from
  175. WinVerifyTrust. The call back is called for every signature found and for
  176. each signer in a signature. When then call back returns S_OK then the WinVerifyTrust
  177. returns. If S_FALSE is returned from the call back then the next signer or signature
  178. is tried. If and error is found then WinVerifyTrust returns this error immediately.
  179. The call back must by of type _PROTECTED_TRUST_POLICY. This function takes a HANDLE
  180. and a PPROTECTED_POLICY_INFO. The handle points to client data that is passed into
  181. WinVerifyTrust, it can contain data, returned elements, status flags etc. The
  182. PPROTECTED_POLICY_INFO points to a structure that contains all the information the
  183. general trust provider found in the signature. The policy call back can use some or
  184. all of this data in determining if the signature is valid.
  185. In addition to method 1 and method 2 a call back procedure is added to the
  186. PROTECTED_TRUST_INFO structure.
  187. pfnPolicy = MyPolicy;
  188. (where:
  189. MyPolicy is a function defined by the caller.)
  190. hTrustedStore = a store that contains all roots that are to be trusted.
  191. (This store can be opened using CertOpenSystemStore etc.)
  192. cbSize = sizeof(PROTECTED_TRUST_INFO);
  193. dwVerifyFlags = zero or more of PROTRUST_CERT_SIGNATURE_FLAG
  194. PROTRUST_CERT_TIME_VALIDITY_FLAG
  195. PROTRUST_TIMESTAMP_SIGNATURE_FLAG
  196. PROTRUST_TRUST_TEST_ROOT.
  197. (where:
  198. PROTRUST_CERT_SIGNATURE_FLAG - verify certificates on signatures
  199. (ie find the issuer certificate and
  200. verify the signature of the certificate).
  201. PROTRUST_CERT_TIME_VALIDITY_FLAG - verify that the certificate is
  202. valid at the current time.
  203. PROTRUST_TIMESTAMP_SIGNATURE_FLAG - verify that the certificate was
  204. valid at the time a time-stamp was
  205. placed on the signature. If there
  206. is no time stamp then use the current time.
  207. PROTRUST_TRUST_TEST_ROOT - Verifying the certifcate chain to the test
  208. root is valid.)
  209. WinVerifyTrust will return:
  210. The return code from the policy module.
  211. Example: of policy callback.
  212. //
  213. // Protest3 - tool for manually calling WinVerifyTrust
  214. //
  215. #include <stdio.h>
  216. #include <windows.h>
  217. #include "wincrypt.h"
  218. #include "signcde.h"
  219. #include "protrust.h"
  220. // Potential Subject ids
  221. GUID guidProtectedTrust = WIN_PROTECTED_ACTION;
  222. GUID guidSubjectPeImage = WIN_TRUST_SUBJTYPE_PE_IMAGE;
  223. GUID guidSubjectJavaClass = WIN_TRUST_SUBJTYPE_JAVA_CLASS;
  224. GUID guidSubjectCabinet = WIN_TRUST_SUBJTYPE_CABINET;
  225. // Which action and subject will be used
  226. GUID* pguidActionID = &guidProtectedTrust;
  227. GUID* pguidSubject = &guidSubjectPeImage;
  228. // Structures used to call WinVerifyTrust
  229. PROTECTED_TRUST_ACTDATA_CALLER_CONTEXT sSetup;
  230. WIN_TRUST_SUBJECT_FILE sSubjectFile;
  231. // Set up my own error codes
  232. #define MY_CODE_NO_ROOT 0x00010000
  233. #define MY_CODE_BAD_DIGEST 0x00100000
  234. #define MY_CODE_BAD_TIME 0x00200000
  235. // Define my structure for use in the Policy call back.
  236. typedef struct _CLIENT_DATA {
  237. DWORD dwStatusFlags; // Verification Status
  238. BOOL dwRealRoot; // Did it verify to the real microsoft root
  239. BOOL dwTestRoot; // Did it verify to the test root
  240. } CLIENT_DATA, *PCLIENT_DATA;
  241. HRESULT WINAPI MyPolicy(IN HANDLE hClientToken,
  242. IN PPROTECTED_POLICY_INFO pInfo)
  243. {
  244. HRESULT hr = S_OK;
  245. PCLIENT_DATA pClient = (PCLIENT_DATA) hClientToken;
  246. if(pInfo->dwStatusFlags & PROTRUST_DIGEST_FLAG) {
  247. // Bad digest
  248. pClient->dwStatusFlags |= MY_CODE_BAD_DIGEST;
  249. return S_FALSE; // Try next one
  250. }
  251. // Check to see if the signing certificate had a valid time
  252. if(pInfo->dwStatusFlags & PROTRUST_TIME_FLAG) {
  253. // time expired on certificate or issuer
  254. pClient->dwStatusFlags |= MY_CODE_BAD_TIME;
  255. return S_FALSE; // Try next one
  256. }
  257. // Check to see we got a root cert. If not then we did
  258. // not verify up to a root.
  259. if(!pInfo->pRoot) {
  260. pClient->dwStatusFlags |= MY_CODE_NO_ROOT;
  261. hr = CERT_E_ISSUERCHAINING;
  262. }
  263. else {
  264. // Test the Cert to see which one it is
  265. hr = SpcIsRootCert(pInfo->pRoot);
  266. if(hr == S_FALSE) { // The certificate is the test root cert
  267. pClient->dwRealRoot = FALSE;
  268. pClient->dwTestRoot = TRUE;
  269. }
  270. else if(hr == S_OK) {
  271. pClient->dwRealRoot = TRUE;
  272. pClient->dwTestRoot = FALSE;
  273. }
  274. }
  275. return hr;
  276. }
  277. // Information defined by me for use in my policy
  278. WCHAR rgwSubjectPath[_MAX_PATH];
  279. BOOL fCheckTimeStamp = FALSE;
  280. BOOL fCheckCurrentTime = FALSE;
  281. BOOL fTestRootOk = FALSE;
  282. void Usage ()
  283. {
  284. printf ( "Usage: CHKTRUST [-options] file-name\n" );
  285. printf ( "Options:\n" );
  286. printf ( " -I : subject type is PE executable image file (default)\n" );
  287. printf ( " -J : subject type is Java class\n" );
  288. printf ( " -C : subject type is Cabinet file\n" );
  289. printf ( " -S : check for a time stamp\n");
  290. printf ( " -T : test root is valid\n");
  291. printf ( " -U : use current time to see if certificates are valid\n");
  292. exit ( 0 );
  293. }
  294. VOID
  295. WINAPI
  296. ParseSwitch (CHAR chSwitch,
  297. int *pArgc,
  298. char **pArgv[])
  299. {
  300. switch (toupper (chSwitch)) {
  301. case '?':
  302. Usage();
  303. break;
  304. case 'I':
  305. pguidSubject = &guidSubjectPeImage;
  306. break;
  307. case 'J':
  308. pguidSubject = &guidSubjectJavaClass;
  309. break;
  310. case 'C':
  311. pguidSubject = &guidSubjectCabinet;
  312. break;
  313. case 'S':
  314. fCheckTimeStamp = TRUE;
  315. break;
  316. case 'T':
  317. fTestRootOk = TRUE;
  318. break;
  319. case 'U':
  320. fCheckCurrentTime = TRUE;
  321. break;
  322. default:
  323. Usage ();
  324. break;
  325. }
  326. }
  327. void _cdecl main ( int argc, char** argv )
  328. {
  329. HCERTSTORE hRoots = NULL;
  330. WCHAR wpath[_MAX_PATH];
  331. char chChar, *pchChar;
  332. if ( argc <= 1 ) Usage ();
  333. while (--argc) {
  334. pchChar = *++argv;
  335. if (*pchChar == '/' || *pchChar == '-') {
  336. while (chChar = *++pchChar) {
  337. ParseSwitch (chChar, &argc, &argv);
  338. }
  339. }
  340. else {
  341. MultiByteToWideChar ( CP_ACP, 0, pchChar, -1, wpath, _MAX_PATH );
  342. sSubjectFile.hFile = INVALID_HANDLE_VALUE;
  343. sSubjectFile.lpPath = &(wpath[0]);
  344. sSetup.SubjectType = pguidSubject;
  345. sSetup.Subject = &sSubjectFile;
  346. }
  347. }
  348. // Make sure we have a file
  349. if ( sSubjectFile.lpPath == NULL )
  350. Usage();
  351. // Setup up client data for policy (application decides what this is)
  352. CLIENT_DATA sClientData;
  353. // Zero out structure
  354. ZeroMemory(&sClientData, sizeof(CLIENT_DATA));
  355. // Set the Client structure to return status codes
  356. sSetup.hClientToken = (HANDLE) &sClientData;
  357. //==================
  358. // Setup the Protrust structure
  359. // Setup the Protected Trust info (Most fields are optional)
  360. // Zero out structure
  361. ZeroMemory(&sSetup.sTrustInfo, sizeof(PROTECTED_TRUST_INFO));
  362. // Set size of structure for extensibility
  363. sSetup.sTrustInfo.cbSize = sizeof(PROTECTED_TRUST_INFO); //
  364. // Check the possible flags for verifying certificates
  365. sSetup.sTrustInfo.dwVerifyFlags = PROTRUST_CERT_SIGNATURE_FLAG;
  366. if(fTestRootOk)
  367. sSetup.sTrustInfo.dwVerifyFlags |= PROTRUST_TRUST_TEST_ROOT;
  368. if(fCheckTimeStamp)
  369. sSetup.sTrustInfo.dwVerifyFlags |= PROTRUST_TIMESTAMP_SIGNATURE_FLAG;
  370. if(fCheckCurrentTime)
  371. sSetup.sTrustInfo.dwVerifyFlags |= PROTRUST_CERT_TIME_VALIDITY_FLAG;
  372. // Set the policy (defined above)
  373. sSetup.sTrustInfo.pfnPolicy = MyPolicy;
  374. // The rest of sSetup.sTrustInfo is the default values
  375. //==================
  376. // Check the file
  377. DWORD r = WinVerifyTrust ( NULL, pguidActionID, &sSetup );
  378. if(sClientData.dwStatusFlags & MY_CODE_NO_ROOT)
  379. printf ("Did not find a root certificate\n");
  380. if(sClientData.dwStatusFlags & MY_CODE_BAD_DIGEST)
  381. printf ("There was no valid signature\n");
  382. if(sClientData.dwStatusFlags & MY_CODE_BAD_TIME)
  383. printf ("The certificate had an invalid time\n");
  384. switch(r) {
  385. case TRUST_E_NOSIGNATURE:
  386. printf ("No signature found\n");
  387. break;
  388. default:
  389. printf ("Result: %0x\n", r );
  390. }
  391. if(hRoots)
  392. CertCloseStore(hRoots, 0);
  393. exit ( r == 0 ? 0 : 1 );
  394. }
  395. */
  396. //---------------------------------------------------------------------------
  397. #ifdef __cplusplus
  398. }
  399. #endif
  400. #endif //_PROTRUST_H_