Source code of Windows XP (NT5)
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.

699 lines
23 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: certtrst.cpp
  8. //
  9. // Contents: Microsoft Internet Security Provider
  10. //
  11. // Functions: WintrustCertificateTrust
  12. //
  13. // *** local functions ***
  14. // _WalkChain
  15. // _IsLifetimeSigningCert
  16. //
  17. // History: 07-Jun-1997 pberkman created
  18. //
  19. //--------------------------------------------------------------------------
  20. #include "global.hxx"
  21. //
  22. // support for MS test roots!!!!
  23. //
  24. static BYTE rgbTestRoot[] =
  25. {
  26. # include "certs\\mstest1.h"
  27. };
  28. static BYTE rgbTestRootCorrected[] =
  29. {
  30. # include "certs\\mstest2.h"
  31. };
  32. static BYTE rgbTestRootBeta1[] =
  33. {
  34. # include "certs\\mstestb1.h"
  35. };
  36. #define NTESTROOTS 3
  37. static CERT_PUBLIC_KEY_INFO rgTestRootPublicKeyInfo[NTESTROOTS] =
  38. {
  39. {szOID_RSA_RSA, 0, NULL, sizeof(rgbTestRoot), rgbTestRoot, 0},
  40. {szOID_RSA_RSA, 0, NULL, sizeof(rgbTestRootCorrected), rgbTestRootCorrected, 0},
  41. {szOID_RSA_RSA, 0, NULL, sizeof(rgbTestRootBeta1), rgbTestRootBeta1, 0}
  42. };
  43. BOOL _WalkChain(
  44. CRYPT_PROVIDER_DATA *pProvData,
  45. DWORD idxSigner,
  46. DWORD *pdwError,
  47. BOOL fCounterSigner,
  48. DWORD idxCounterSigner,
  49. BOOL fTimeStamped,
  50. BOOL *pfLifetimeSigning // IN OUT, only accessed for fTimeStamped
  51. );
  52. BOOL WINAPI _IsLifetimeSigningCert(
  53. PCCERT_CONTEXT pCertContext
  54. );
  55. HRESULT WINAPI WintrustCertificateTrust(CRYPT_PROVIDER_DATA *pProvData)
  56. {
  57. if ((_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, fRecallWithState)) &&
  58. (pProvData->fRecallWithState == TRUE))
  59. {
  60. return(S_OK);
  61. }
  62. DWORD dwError;
  63. dwError = S_OK;
  64. if (pProvData->csSigners < 1)
  65. {
  66. pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = TRUST_E_NOSIGNATURE;
  67. return(S_FALSE);
  68. }
  69. //
  70. // loop through all signers
  71. //
  72. for (int i = 0; i < (int)pProvData->csSigners; i++)
  73. {
  74. BOOL fTimeStamped = FALSE;
  75. BOOL fLifetimeSigning = FALSE;
  76. if (pProvData->pasSigners[i].csCertChain < 1)
  77. {
  78. pProvData->pasSigners[i].dwError = TRUST_E_NO_SIGNER_CERT;
  79. pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = TRUST_E_NO_SIGNER_CERT;
  80. continue;
  81. }
  82. // Check if timestamped.
  83. if (0 < pProvData->pasSigners[i].csCounterSigners &&
  84. (pProvData->pasSigners[i].pasCounterSigners[0].dwSignerType &
  85. SGNR_TYPE_TIMESTAMP))
  86. {
  87. fTimeStamped = TRUE;
  88. // See if LifeTime Signing has been enabled
  89. if (pProvData->dwProvFlags & WTD_LIFETIME_SIGNING_FLAG)
  90. {
  91. fLifetimeSigning = TRUE;
  92. }
  93. else
  94. {
  95. // Check if the signer certificate has the LIFETIME_SIGNING
  96. // EKU.
  97. fLifetimeSigning = _IsLifetimeSigningCert(
  98. pProvData->pasSigners[i].pasCertChain[0].pCert);
  99. }
  100. }
  101. _WalkChain(pProvData, i, &dwError, FALSE, 0,
  102. fTimeStamped, &fLifetimeSigning);
  103. for (int i2 = 0; i2 < (int)pProvData->pasSigners[i].csCounterSigners; i2++)
  104. {
  105. if (pProvData->pasSigners[i].pasCounterSigners[i2].csCertChain < 1)
  106. {
  107. pProvData->pasSigners[i].pasCounterSigners[i2].dwError = TRUST_E_NO_SIGNER_CERT;
  108. pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = TRUST_E_COUNTER_SIGNER;
  109. dwError = S_FALSE;
  110. continue;
  111. }
  112. // If lifetime signing has been enabled, use current time instead
  113. // of timestamp time.
  114. if (fLifetimeSigning)
  115. {
  116. memcpy(&pProvData->pasSigners[i].pasCounterSigners[i2].sftVerifyAsOf,
  117. &pProvData->sftSystemTime, sizeof(FILETIME));
  118. }
  119. _WalkChain(pProvData, i, &dwError, TRUE, i2, FALSE, NULL);
  120. }
  121. }
  122. return(dwError);
  123. }
  124. HCERTCHAINENGINE GetChainEngine(
  125. IN CRYPT_PROVIDER_DATA *pProvData
  126. )
  127. {
  128. CERT_CHAIN_ENGINE_CONFIG Config;
  129. HCERTSTORE hStore = NULL;
  130. HCERTCHAINENGINE hChainEngine = NULL;
  131. if (NULL == pProvData->pWintrustData ||
  132. pProvData->pWintrustData->dwUnionChoice != WTD_CHOICE_CERT ||
  133. !_ISINSTRUCT(WINTRUST_CERT_INFO,
  134. pProvData->pWintrustData->pCert->cbStruct, dwFlags) ||
  135. 0 == (pProvData->pWintrustData->pCert->dwFlags &
  136. (WTCI_DONT_OPEN_STORES | WTCI_OPEN_ONLY_ROOT)))
  137. return NULL;
  138. memset(&Config, 0, sizeof(Config));
  139. Config.cbSize = sizeof(Config);
  140. if (NULL == (hStore = CertOpenStore(
  141. CERT_STORE_PROV_MEMORY,
  142. 0, // dwEncodingType
  143. 0, // hCryptProv
  144. 0, // dwFlags
  145. NULL // pvPara
  146. )))
  147. goto OpenMemoryStoreError;
  148. if (pProvData->pWintrustData->pCert->dwFlags & WTCI_DONT_OPEN_STORES)
  149. Config.hRestrictedRoot = hStore;
  150. Config.hRestrictedTrust = hStore;
  151. Config.hRestrictedOther = hStore;
  152. if (!CertCreateCertificateChainEngine(
  153. &Config,
  154. &hChainEngine
  155. ))
  156. goto CreateChainEngineError;
  157. CommonReturn:
  158. CertCloseStore(hStore, 0);
  159. return hChainEngine;
  160. ErrorReturn:
  161. hChainEngine = NULL;
  162. goto CommonReturn;
  163. TRACE_ERROR_EX(DBG_SS, OpenMemoryStoreError)
  164. TRACE_ERROR_EX(DBG_SS, CreateChainEngineError)
  165. }
  166. HCERTSTORE GetChainAdditionalStore(
  167. IN CRYPT_PROVIDER_DATA *pProvData
  168. )
  169. {
  170. HCERTSTORE hStore = NULL;
  171. if (0 == pProvData->chStores)
  172. return NULL;
  173. if (1 < pProvData->chStores) {
  174. if (hStore = CertOpenStore(
  175. CERT_STORE_PROV_COLLECTION,
  176. 0, // dwEncodingType
  177. 0, // hCryptProv
  178. 0, // dwFlags
  179. NULL // pvPara
  180. )) {
  181. DWORD i;
  182. for (i = 0; i < pProvData->chStores; i++)
  183. CertAddStoreToCollection(
  184. hStore,
  185. pProvData->pahStores[i],
  186. CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
  187. 0 // dwPriority
  188. );
  189. }
  190. } else
  191. hStore = CertDuplicateStore(pProvData->pahStores[0]);
  192. #if 0
  193. CertSaveStore(
  194. hStore,
  195. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  196. CERT_STORE_SAVE_AS_STORE,
  197. CERT_STORE_SAVE_TO_FILENAME_A,
  198. (void *) "C:\\temp\\wintrust.sto",
  199. 0 // dwFlags
  200. );
  201. #endif
  202. return hStore;
  203. }
  204. BOOL UpdateCertProvChain(
  205. IN OUT PCRYPT_PROVIDER_DATA pProvData,
  206. IN DWORD idxSigner,
  207. OUT DWORD *pdwError,
  208. IN BOOL fCounterSigner,
  209. IN DWORD idxCounterSigner,
  210. IN PCRYPT_PROVIDER_SGNR pSgnr,
  211. IN PCCERT_CHAIN_CONTEXT pChainContext
  212. )
  213. {
  214. BOOL fTestCert = FALSE;
  215. DWORD dwSgnrError = 0;
  216. DWORD i;
  217. // The chain better have at least the certificate we passed in
  218. assert(0 < pChainContext->cChain &&
  219. 0 < pChainContext->rgpChain[0]->cElement);
  220. for (i = 0; i < pChainContext->cChain; i++) {
  221. DWORD j;
  222. PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[i];
  223. for (j = 0; j < pChain->cElement; j++) {
  224. PCERT_CHAIN_ELEMENT pEle = pChain->rgpElement[j];
  225. DWORD dwEleError = pEle->TrustStatus.dwErrorStatus;
  226. DWORD dwEleInfo = pEle->TrustStatus.dwInfoStatus;
  227. PCRYPT_PROVIDER_CERT pProvCert;
  228. if (0 != i || 0 != j) {
  229. if (!(pProvData->psPfns->pfnAddCert2Chain(
  230. pProvData, idxSigner, fCounterSigner,
  231. idxCounterSigner, pEle->pCertContext)))
  232. {
  233. pProvData->dwError = GetLastError();
  234. dwSgnrError = TRUST_E_SYSTEM_ERROR;
  235. goto CommonReturn;
  236. }
  237. }
  238. //
  239. // else
  240. // Signer cert has already been added
  241. pProvCert = &pSgnr->pasCertChain[pSgnr->csCertChain -1];
  242. //DSIE: 12-Oct-2000 added to get pChainElement.
  243. pProvCert->pChainElement = pEle;
  244. pProvCert->fSelfSigned =
  245. 0 != (dwEleInfo & CERT_TRUST_IS_SELF_SIGNED) &&
  246. 0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID);
  247. pProvCert->fTrustedRoot =
  248. pProvCert->fSelfSigned &&
  249. i == pChainContext->cChain - 1 &&
  250. j == pChain->cElement - 1 &&
  251. 0 == (dwEleError & CERT_TRUST_IS_UNTRUSTED_ROOT);
  252. if (pProvCert->fSelfSigned) {
  253. // Check if one of the "test" roots
  254. DWORD k;
  255. for (k = 0; k < NTESTROOTS; k++)
  256. {
  257. if (CertComparePublicKeyInfo(
  258. pProvData->dwEncoding,
  259. &pProvCert->pCert->pCertInfo->SubjectPublicKeyInfo,
  260. &rgTestRootPublicKeyInfo[k]))
  261. {
  262. pProvCert->fTestCert = TRUE;
  263. fTestCert = TRUE;
  264. if (pProvData->dwRegPolicySettings & WTPF_TRUSTTEST)
  265. pProvCert->fTrustedRoot = TRUE;
  266. break;
  267. }
  268. }
  269. }
  270. // First Element in all but the first simple chain
  271. pProvCert->fTrustListSignerCert = (0 < i && 0 == j);
  272. pProvCert->fIsCyclic = (0 != (dwEleError & CERT_TRUST_IS_CYCLIC));
  273. // Map to IE4Trust confidence
  274. if (0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
  275. pProvCert->dwConfidence |= CERT_CONFIDENCE_SIG;
  276. if (0 == (dwEleError & CERT_TRUST_IS_NOT_TIME_VALID))
  277. pProvCert->dwConfidence |= CERT_CONFIDENCE_TIME;
  278. // On Sep 10, 1998 Trevor/Brian wanted time nesting checks to
  279. // be disabled
  280. // if (0 == (dwEleError & CERT_TRUST_IS_NOT_TIME_NESTED))
  281. pProvCert->dwConfidence |= CERT_CONFIDENCE_TIMENEST;
  282. if (0 != (dwEleInfo & CERT_TRUST_HAS_EXACT_MATCH_ISSUER))
  283. pProvCert->dwConfidence |= CERT_CONFIDENCE_AUTHIDEXT;
  284. if (0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID) &&
  285. 0 != (dwEleInfo & CERT_TRUST_HAS_EXACT_MATCH_ISSUER))
  286. pProvCert->dwConfidence |= CERT_CONFIDENCE_HYGIENE;
  287. if (pEle->pRevocationInfo) {
  288. pProvCert->dwRevokedReason =
  289. pEle->pRevocationInfo->dwRevocationResult;
  290. }
  291. // Update any signature or revocations errors
  292. if (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID) {
  293. pProvCert->dwError = TRUST_E_CERT_SIGNATURE;
  294. assert(pChainContext->TrustStatus.dwErrorStatus &
  295. CERT_TRUST_IS_NOT_SIGNATURE_VALID);
  296. dwSgnrError = TRUST_E_CERT_SIGNATURE;
  297. } else if (dwEleError & CERT_TRUST_IS_REVOKED) {
  298. pProvCert->dwError = CERT_E_REVOKED;
  299. assert(pChainContext->TrustStatus.dwErrorStatus &
  300. CERT_TRUST_IS_REVOKED);
  301. if (0 == dwSgnrError ||
  302. CERT_E_REVOCATION_FAILURE == dwSgnrError)
  303. dwSgnrError = CERT_E_REVOKED;
  304. } else if (dwEleError & CERT_TRUST_IS_OFFLINE_REVOCATION) {
  305. // Ignore NO_CHECK errors
  306. if (pProvData->pWintrustData->fdwRevocationChecks ==
  307. WTD_REVOKE_WHOLECHAIN) {
  308. pProvCert->dwError = CERT_E_REVOCATION_FAILURE;
  309. assert(pChainContext->TrustStatus.dwErrorStatus &
  310. CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
  311. if (0 == dwSgnrError)
  312. dwSgnrError = CERT_E_REVOCATION_FAILURE;
  313. }
  314. }
  315. // If last element in simple chain, check if it was in a
  316. // CTL and update CryptProvData if it was.
  317. if (j == pChain->cElement - 1 && pChain->pTrustListInfo &&
  318. pChain->pTrustListInfo->pCtlContext) {
  319. DWORD dwChainError = pChain->TrustStatus.dwErrorStatus;
  320. // Note, don't need to AddRef since we already hold an
  321. // AddRef on the ChainContext.
  322. pProvCert->pCtlContext = pChain->pTrustListInfo->pCtlContext;
  323. if (dwChainError & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID) {
  324. pProvCert->dwCtlError = TRUST_E_CERT_SIGNATURE;
  325. dwSgnrError = TRUST_E_CERT_SIGNATURE;
  326. } else if (dwChainError & CERT_TRUST_CTL_IS_NOT_TIME_VALID) {
  327. if (0 == (pProvData->dwRegPolicySettings &
  328. WTPF_IGNOREEXPIRATION))
  329. pProvCert->dwCtlError = CERT_E_EXPIRED;
  330. } else if (dwChainError &
  331. CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) {
  332. pProvCert->dwCtlError = CERT_E_WRONG_USAGE;
  333. }
  334. }
  335. if (pProvData->psPfns->pfnCertCheckPolicy) {
  336. if (! (*pProvData->psPfns->pfnCertCheckPolicy)(
  337. pProvData, idxSigner, fCounterSigner, idxCounterSigner))
  338. goto CommonReturn;
  339. }
  340. }
  341. }
  342. CommonReturn:
  343. if (fTestCert) {
  344. if (CERT_TRUST_IS_REVOKED == dwSgnrError ||
  345. CERT_E_REVOCATION_FAILURE == dwSgnrError) {
  346. // No revocation errors for "test" roots
  347. dwSgnrError = 0;
  348. // Loop through certs and remove any revocation error status
  349. for (i = 0; i < pSgnr->csCertChain; i++) {
  350. PCRYPT_PROVIDER_CERT pProvCert = &pSgnr->pasCertChain[i];
  351. pProvCert->dwError = 0;
  352. pProvCert->dwRevokedReason = 0;
  353. }
  354. }
  355. }
  356. if (CERT_E_REVOCATION_FAILURE == dwSgnrError &&
  357. pProvData->pWintrustData->fdwRevocationChecks !=
  358. WTD_REVOKE_WHOLECHAIN)
  359. // Will check during Final Policy
  360. dwSgnrError = 0;
  361. if (dwSgnrError) {
  362. pSgnr->dwError = dwSgnrError;
  363. pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
  364. dwSgnrError;
  365. *pdwError = S_FALSE;
  366. return FALSE;
  367. } else
  368. return TRUE;
  369. }
  370. BOOL _WalkChain(
  371. CRYPT_PROVIDER_DATA *pProvData,
  372. DWORD idxSigner,
  373. DWORD *pdwError,
  374. BOOL fCounterSigner,
  375. DWORD idxCounterSigner,
  376. BOOL fTimeStamped,
  377. BOOL *pfLifetimeSigning // IN OUT, only accessed for fTimeStamped
  378. )
  379. {
  380. BOOL fResult;
  381. DWORD dwCreateChainFlags;
  382. DWORD dwSgnrError = 0;
  383. CRYPT_PROVIDER_SGNR *pSgnr; // not allocated
  384. PCCERT_CONTEXT pCertContext; // not allocated
  385. CERT_CHAIN_PARA ChainPara;
  386. HCERTCHAINENGINE hChainEngine = NULL;
  387. HCERTSTORE hAdditionalStore = NULL;
  388. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  389. LPSTR pszUsage = NULL;
  390. if (fCounterSigner)
  391. pSgnr = &pProvData->pasSigners[idxSigner].pasCounterSigners[
  392. idxCounterSigner];
  393. else
  394. pSgnr = &pProvData->pasSigners[idxSigner];
  395. assert(pSgnr);
  396. //
  397. // at this stage, the last cert in the chain "should be" the signers cert.
  398. // eg: there should only be one cert in the chain from the Signature
  399. // Provider
  400. //
  401. if (1 != pSgnr->csCertChain ||
  402. (NULL == (pCertContext =
  403. pSgnr->pasCertChain[pSgnr->csCertChain - 1].pCert))) {
  404. dwSgnrError = TRUST_E_NO_SIGNER_CERT;
  405. goto NoSignerCertError;
  406. }
  407. memset(&ChainPara, 0, sizeof(ChainPara));
  408. ChainPara.cbSize = sizeof(ChainPara);
  409. if (fCounterSigner && SGNR_TYPE_TIMESTAMP == pSgnr->dwSignerType) {
  410. pszUsage = szOID_PKIX_KP_TIMESTAMP_SIGNING;
  411. } else if(NULL != pProvData->pRequestUsage) {
  412. ChainPara.RequestedUsage = *pProvData->pRequestUsage;
  413. } else {
  414. pszUsage = pProvData->pszUsageOID;
  415. }
  416. if ( (0 == (pProvData->dwProvFlags & WTD_NO_POLICY_USAGE_FLAG)) && pszUsage) {
  417. ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  418. ChainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
  419. ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = &pszUsage;
  420. }
  421. hChainEngine = GetChainEngine(pProvData);
  422. hAdditionalStore = GetChainAdditionalStore(pProvData);
  423. dwCreateChainFlags = 0;
  424. if (pProvData->dwProvFlags & CPD_REVOCATION_CHECK_NONE) {
  425. ;
  426. } else if (pProvData->dwProvFlags & CPD_REVOCATION_CHECK_END_CERT) {
  427. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_END_CERT;
  428. } else if (pProvData->dwProvFlags & CPD_REVOCATION_CHECK_CHAIN) {
  429. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
  430. } else if (pProvData->dwProvFlags &
  431. CPD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT) {
  432. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  433. } else if (pProvData->dwProvFlags & WTD_REVOCATION_CHECK_NONE) {
  434. ;
  435. } else if (pProvData->dwProvFlags & WTD_REVOCATION_CHECK_END_CERT) {
  436. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_END_CERT;
  437. } else if (pProvData->dwProvFlags & WTD_REVOCATION_CHECK_CHAIN) {
  438. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
  439. } else if (pProvData->dwProvFlags &
  440. WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT) {
  441. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  442. } else if (pProvData->pWintrustData->fdwRevocationChecks ==
  443. WTD_REVOKE_WHOLECHAIN) {
  444. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
  445. } else if (fCounterSigner && SGNR_TYPE_TIMESTAMP == pSgnr->dwSignerType) {
  446. if (0 == (pProvData->dwRegPolicySettings & WTPF_IGNOREREVOCATIONONTS))
  447. // On 4-12-01 changed from END_CERT to EXCLUDE_ROOT
  448. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  449. } else if (0 == (pProvData->dwRegPolicySettings & WTPF_IGNOREREVOKATION))
  450. // On 4-12-01 changed from END_CERT to EXCLUDE_ROOT
  451. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  452. if (!(pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_CERT ||
  453. pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_SIGNER))
  454. // Certificate was obtained from either the message store, or one
  455. // of our known stores
  456. dwCreateChainFlags |= CERT_CHAIN_CACHE_END_CERT;
  457. // else
  458. // Can't implicitly cache a context passed to us
  459. #if 0
  460. {
  461. HCERTSTORE hDebugStore;
  462. if (hDebugStore = CertOpenSystemStoreA(0, "wintrust")) {
  463. CertAddCertificateContextToStore(
  464. hDebugStore,
  465. pCertContext,
  466. CERT_STORE_ADD_ALWAYS,
  467. NULL
  468. );
  469. CertCloseStore(hDebugStore, 0);
  470. }
  471. }
  472. #endif
  473. FILETIME fileTime;
  474. memset(&fileTime, 0, sizeof(fileTime));
  475. if (fTimeStamped && *pfLifetimeSigning)
  476. dwCreateChainFlags |= CERT_CHAIN_TIMESTAMP_TIME;
  477. if (!CertGetCertificateChain (
  478. hChainEngine,
  479. pCertContext,
  480. (memcmp(&pSgnr->sftVerifyAsOf, &fileTime, sizeof(fileTime)) == 0) ?
  481. NULL : &pSgnr->sftVerifyAsOf,
  482. hAdditionalStore,
  483. &ChainPara,
  484. dwCreateChainFlags,
  485. NULL, // pvReserved,
  486. &pChainContext
  487. )) {
  488. pProvData->dwError = GetLastError();
  489. dwSgnrError = TRUST_E_SYSTEM_ERROR;
  490. goto GetChainError;
  491. }
  492. if (fTimeStamped && !*pfLifetimeSigning) {
  493. // See if resultant application policy has the LIFETIME_SIGNING OID
  494. PCERT_ENHKEY_USAGE pAppUsage =
  495. pChainContext->rgpChain[0]->rgpElement[0]->pApplicationUsage;
  496. if (pAppUsage) {
  497. DWORD i;
  498. for (i = 0; i < pAppUsage->cUsageIdentifier; i++) {
  499. if (0 == strcmp(pAppUsage->rgpszUsageIdentifier[i],
  500. szOID_KP_LIFETIME_SIGNING)) {
  501. *pfLifetimeSigning = TRUE;
  502. break;
  503. }
  504. }
  505. }
  506. if (*pfLifetimeSigning) {
  507. CertFreeCertificateChain(pChainContext);
  508. pChainContext = NULL;
  509. dwCreateChainFlags |= CERT_CHAIN_TIMESTAMP_TIME;
  510. if (!CertGetCertificateChain (
  511. hChainEngine,
  512. pCertContext,
  513. (memcmp(&pSgnr->sftVerifyAsOf, &fileTime, sizeof(fileTime)) == 0) ?
  514. NULL : &pSgnr->sftVerifyAsOf,
  515. hAdditionalStore,
  516. &ChainPara,
  517. dwCreateChainFlags,
  518. NULL, // pvReserved,
  519. &pChainContext
  520. )) {
  521. pProvData->dwError = GetLastError();
  522. dwSgnrError = TRUST_E_SYSTEM_ERROR;
  523. goto GetChainError;
  524. }
  525. }
  526. }
  527. pSgnr->pChainContext = pChainContext;
  528. if (pProvData->dwProvFlags & WTD_NO_IE4_CHAIN_FLAG) {
  529. pProvData->dwProvFlags |= CPD_USE_NT5_CHAIN_FLAG;
  530. fResult = TRUE;
  531. } else
  532. fResult = UpdateCertProvChain(
  533. pProvData,
  534. idxSigner,
  535. pdwError,
  536. fCounterSigner,
  537. idxCounterSigner,
  538. pSgnr,
  539. pChainContext
  540. );
  541. CommonReturn:
  542. if (hChainEngine)
  543. CertFreeCertificateChainEngine(hChainEngine);
  544. if (hAdditionalStore)
  545. CertCloseStore(hAdditionalStore, 0);
  546. return fResult;
  547. ErrorReturn:
  548. pSgnr->dwError = dwSgnrError;
  549. pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
  550. dwSgnrError;
  551. *pdwError = S_FALSE;
  552. fResult = FALSE;
  553. goto CommonReturn;
  554. TRACE_ERROR_EX(DBG_SS, NoSignerCertError)
  555. TRACE_ERROR_EX(DBG_SS, GetChainError)
  556. }
  557. BOOL WINAPI _IsLifetimeSigningCert(
  558. PCCERT_CONTEXT pCertContext
  559. )
  560. {
  561. DWORD cbSize;
  562. PCERT_ENHKEY_USAGE pCertEKU;
  563. //
  564. // see if the certificate has the proper enhanced key usage OID
  565. //
  566. cbSize = 0;
  567. CertGetEnhancedKeyUsage(pCertContext,
  568. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  569. NULL,
  570. &cbSize);
  571. if (cbSize == 0)
  572. {
  573. return(FALSE);
  574. }
  575. if (!(pCertEKU = (PCERT_ENHKEY_USAGE)new BYTE[cbSize]))
  576. {
  577. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  578. return(FALSE);
  579. }
  580. if (!(CertGetEnhancedKeyUsage(pCertContext,
  581. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  582. pCertEKU,
  583. &cbSize)))
  584. {
  585. delete pCertEKU;
  586. return(FALSE);
  587. }
  588. for (int i = 0; i < (int)pCertEKU->cUsageIdentifier; i++)
  589. {
  590. if (strcmp(pCertEKU->rgpszUsageIdentifier[i], szOID_KP_LIFETIME_SIGNING) == 0)
  591. {
  592. delete pCertEKU;
  593. return(TRUE);
  594. }
  595. }
  596. delete pCertEKU;
  597. return(FALSE);
  598. }