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.

722 lines
24 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. // Following is in ..\softpub\callui.cpp
  205. extern
  206. HRESULT _CheckTrustedCodeHash(CRYPT_PROVIDER_DATA *pProvData);
  207. BOOL UpdateCertProvChain(
  208. IN OUT PCRYPT_PROVIDER_DATA pProvData,
  209. IN DWORD idxSigner,
  210. OUT DWORD *pdwError,
  211. IN BOOL fCounterSigner,
  212. IN DWORD idxCounterSigner,
  213. IN PCRYPT_PROVIDER_SGNR pSgnr,
  214. IN PCCERT_CHAIN_CONTEXT pChainContext
  215. )
  216. {
  217. BOOL fTestCert = FALSE;
  218. DWORD dwSgnrError = 0;
  219. DWORD i;
  220. // The chain better have at least the certificate we passed in
  221. assert(0 < pChainContext->cChain &&
  222. 0 < pChainContext->rgpChain[0]->cElement);
  223. for (i = 0; i < pChainContext->cChain; i++) {
  224. DWORD j;
  225. PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[i];
  226. for (j = 0; j < pChain->cElement; j++) {
  227. PCERT_CHAIN_ELEMENT pEle = pChain->rgpElement[j];
  228. DWORD dwEleError = pEle->TrustStatus.dwErrorStatus;
  229. DWORD dwEleInfo = pEle->TrustStatus.dwInfoStatus;
  230. PCRYPT_PROVIDER_CERT pProvCert;
  231. if (0 != i || 0 != j) {
  232. if (!(pProvData->psPfns->pfnAddCert2Chain(
  233. pProvData, idxSigner, fCounterSigner,
  234. idxCounterSigner, pEle->pCertContext)))
  235. {
  236. pProvData->dwError = GetLastError();
  237. dwSgnrError = TRUST_E_SYSTEM_ERROR;
  238. goto CommonReturn;
  239. }
  240. }
  241. //
  242. // else
  243. // Signer cert has already been added
  244. pProvCert = &pSgnr->pasCertChain[pSgnr->csCertChain -1];
  245. //DSIE: 12-Oct-2000 added to get pChainElement.
  246. pProvCert->pChainElement = pEle;
  247. pProvCert->fSelfSigned =
  248. 0 != (dwEleInfo & CERT_TRUST_IS_SELF_SIGNED) &&
  249. 0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID);
  250. pProvCert->fTrustedRoot =
  251. pProvCert->fSelfSigned &&
  252. i == pChainContext->cChain - 1 &&
  253. j == pChain->cElement - 1 &&
  254. 0 == (dwEleError & CERT_TRUST_IS_UNTRUSTED_ROOT);
  255. if (pProvCert->fSelfSigned) {
  256. // Check if one of the "test" roots
  257. DWORD k;
  258. for (k = 0; k < NTESTROOTS; k++)
  259. {
  260. if (CertComparePublicKeyInfo(
  261. pProvData->dwEncoding,
  262. &pProvCert->pCert->pCertInfo->SubjectPublicKeyInfo,
  263. &rgTestRootPublicKeyInfo[k]))
  264. {
  265. pProvCert->fTestCert = TRUE;
  266. fTestCert = TRUE;
  267. if (pProvData->dwRegPolicySettings & WTPF_TRUSTTEST)
  268. pProvCert->fTrustedRoot = TRUE;
  269. break;
  270. }
  271. }
  272. }
  273. // First Element in all but the first simple chain
  274. pProvCert->fTrustListSignerCert = (0 < i && 0 == j);
  275. pProvCert->fIsCyclic = (0 != (dwEleError & CERT_TRUST_IS_CYCLIC));
  276. // Map to IE4Trust confidence
  277. if (0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
  278. pProvCert->dwConfidence |= CERT_CONFIDENCE_SIG;
  279. if (0 == (dwEleError & CERT_TRUST_IS_NOT_TIME_VALID))
  280. pProvCert->dwConfidence |= CERT_CONFIDENCE_TIME;
  281. // On Sep 10, 1998 Trevor/Brian wanted time nesting checks to
  282. // be disabled
  283. // if (0 == (dwEleError & CERT_TRUST_IS_NOT_TIME_NESTED))
  284. pProvCert->dwConfidence |= CERT_CONFIDENCE_TIMENEST;
  285. if (0 != (dwEleInfo & CERT_TRUST_HAS_EXACT_MATCH_ISSUER))
  286. pProvCert->dwConfidence |= CERT_CONFIDENCE_AUTHIDEXT;
  287. if (0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID) &&
  288. 0 != (dwEleInfo & CERT_TRUST_HAS_EXACT_MATCH_ISSUER))
  289. pProvCert->dwConfidence |= CERT_CONFIDENCE_HYGIENE;
  290. if (pEle->pRevocationInfo) {
  291. pProvCert->dwRevokedReason =
  292. pEle->pRevocationInfo->dwRevocationResult;
  293. }
  294. // Update any signature or revocations errors
  295. if (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID) {
  296. pProvCert->dwError = TRUST_E_CERT_SIGNATURE;
  297. assert(pChainContext->TrustStatus.dwErrorStatus &
  298. CERT_TRUST_IS_NOT_SIGNATURE_VALID);
  299. dwSgnrError = TRUST_E_CERT_SIGNATURE;
  300. } else if (dwEleError & CERT_TRUST_IS_REVOKED) {
  301. pProvCert->dwError = CERT_E_REVOKED;
  302. assert(pChainContext->TrustStatus.dwErrorStatus &
  303. CERT_TRUST_IS_REVOKED);
  304. if (0 == dwSgnrError ||
  305. CERT_E_REVOCATION_FAILURE == dwSgnrError)
  306. dwSgnrError = CERT_E_REVOKED;
  307. #if 0
  308. // On 8-April-2002 removed the following. Revocation checking
  309. // is no longer done for partial chains.
  310. //
  311. // Also, this was only set for WTD_REVOKE_WHOLECHAIN.
  312. } else if (dwEleError & CERT_TRUST_IS_OFFLINE_REVOCATION) {
  313. // Ignore NO_CHECK errors
  314. if (pProvData->pWintrustData->fdwRevocationChecks ==
  315. WTD_REVOKE_WHOLECHAIN) {
  316. pProvCert->dwError = CERT_E_REVOCATION_FAILURE;
  317. assert(pChainContext->TrustStatus.dwErrorStatus &
  318. CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
  319. if (0 == dwSgnrError)
  320. dwSgnrError = CERT_E_REVOCATION_FAILURE;
  321. }
  322. #endif
  323. }
  324. // If last element in simple chain, check if it was in a
  325. // CTL and update CryptProvData if it was.
  326. if (j == pChain->cElement - 1 && pChain->pTrustListInfo &&
  327. pChain->pTrustListInfo->pCtlContext) {
  328. DWORD dwChainError = pChain->TrustStatus.dwErrorStatus;
  329. // Note, don't need to AddRef since we already hold an
  330. // AddRef on the ChainContext.
  331. pProvCert->pCtlContext = pChain->pTrustListInfo->pCtlContext;
  332. if (dwChainError & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID) {
  333. pProvCert->dwCtlError = TRUST_E_CERT_SIGNATURE;
  334. dwSgnrError = TRUST_E_CERT_SIGNATURE;
  335. } else if (dwChainError & CERT_TRUST_CTL_IS_NOT_TIME_VALID) {
  336. if (0 == (pProvData->dwRegPolicySettings &
  337. WTPF_IGNOREEXPIRATION))
  338. pProvCert->dwCtlError = CERT_E_EXPIRED;
  339. } else if (dwChainError &
  340. CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) {
  341. pProvCert->dwCtlError = CERT_E_WRONG_USAGE;
  342. }
  343. }
  344. if (pProvData->psPfns->pfnCertCheckPolicy) {
  345. if (! (*pProvData->psPfns->pfnCertCheckPolicy)(
  346. pProvData, idxSigner, fCounterSigner, idxCounterSigner))
  347. goto CommonReturn;
  348. }
  349. }
  350. }
  351. CommonReturn:
  352. if (fTestCert) {
  353. if (CERT_TRUST_IS_REVOKED == dwSgnrError ||
  354. CERT_E_REVOCATION_FAILURE == dwSgnrError) {
  355. // No revocation errors for "test" roots
  356. dwSgnrError = 0;
  357. // Loop through certs and remove any revocation error status
  358. for (i = 0; i < pSgnr->csCertChain; i++) {
  359. PCRYPT_PROVIDER_CERT pProvCert = &pSgnr->pasCertChain[i];
  360. pProvCert->dwError = 0;
  361. pProvCert->dwRevokedReason = 0;
  362. }
  363. }
  364. }
  365. if (CERT_E_REVOCATION_FAILURE == dwSgnrError &&
  366. pProvData->pWintrustData->fdwRevocationChecks !=
  367. WTD_REVOKE_WHOLECHAIN)
  368. // Will check during Final Policy
  369. dwSgnrError = 0;
  370. if (CERT_E_REVOKED == dwSgnrError) {
  371. if (S_OK == _CheckTrustedCodeHash(pProvData)) {
  372. // The code was explicitly trusted.
  373. dwSgnrError = 0;
  374. }
  375. }
  376. if (dwSgnrError) {
  377. pSgnr->dwError = dwSgnrError;
  378. pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
  379. dwSgnrError;
  380. *pdwError = S_FALSE;
  381. return FALSE;
  382. } else
  383. return TRUE;
  384. }
  385. BOOL _WalkChain(
  386. CRYPT_PROVIDER_DATA *pProvData,
  387. DWORD idxSigner,
  388. DWORD *pdwError,
  389. BOOL fCounterSigner,
  390. DWORD idxCounterSigner,
  391. BOOL fTimeStamped,
  392. BOOL *pfLifetimeSigning // IN OUT, only accessed for fTimeStamped
  393. )
  394. {
  395. BOOL fResult;
  396. DWORD dwCreateChainFlags;
  397. DWORD dwSgnrError = 0;
  398. CRYPT_PROVIDER_SGNR *pSgnr; // not allocated
  399. PCCERT_CONTEXT pCertContext; // not allocated
  400. CERT_CHAIN_PARA ChainPara;
  401. HCERTCHAINENGINE hChainEngine = NULL;
  402. HCERTSTORE hAdditionalStore = NULL;
  403. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  404. LPSTR pszUsage = NULL;
  405. if (fCounterSigner)
  406. pSgnr = &pProvData->pasSigners[idxSigner].pasCounterSigners[
  407. idxCounterSigner];
  408. else
  409. pSgnr = &pProvData->pasSigners[idxSigner];
  410. assert(pSgnr);
  411. //
  412. // at this stage, the last cert in the chain "should be" the signers cert.
  413. // eg: there should only be one cert in the chain from the Signature
  414. // Provider
  415. //
  416. if (1 != pSgnr->csCertChain ||
  417. (NULL == (pCertContext =
  418. pSgnr->pasCertChain[pSgnr->csCertChain - 1].pCert))) {
  419. dwSgnrError = TRUST_E_NO_SIGNER_CERT;
  420. goto NoSignerCertError;
  421. }
  422. memset(&ChainPara, 0, sizeof(ChainPara));
  423. ChainPara.cbSize = sizeof(ChainPara);
  424. if (fCounterSigner && SGNR_TYPE_TIMESTAMP == pSgnr->dwSignerType) {
  425. pszUsage = szOID_PKIX_KP_TIMESTAMP_SIGNING;
  426. } else if(NULL != pProvData->pRequestUsage) {
  427. ChainPara.RequestedUsage = *pProvData->pRequestUsage;
  428. } else {
  429. pszUsage = pProvData->pszUsageOID;
  430. }
  431. if ( (0 == (pProvData->dwProvFlags & WTD_NO_POLICY_USAGE_FLAG)) && pszUsage) {
  432. ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  433. ChainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
  434. ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = &pszUsage;
  435. }
  436. hChainEngine = GetChainEngine(pProvData);
  437. hAdditionalStore = GetChainAdditionalStore(pProvData);
  438. dwCreateChainFlags = 0;
  439. if (pProvData->dwProvFlags & CPD_REVOCATION_CHECK_NONE) {
  440. ;
  441. } else if (pProvData->dwProvFlags & CPD_REVOCATION_CHECK_END_CERT) {
  442. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_END_CERT;
  443. } else if (pProvData->dwProvFlags & CPD_REVOCATION_CHECK_CHAIN) {
  444. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
  445. } else if (pProvData->dwProvFlags &
  446. CPD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT) {
  447. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  448. } else if (pProvData->dwProvFlags & WTD_REVOCATION_CHECK_NONE) {
  449. ;
  450. } else if (pProvData->dwProvFlags & WTD_REVOCATION_CHECK_END_CERT) {
  451. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_END_CERT;
  452. } else if (pProvData->dwProvFlags & WTD_REVOCATION_CHECK_CHAIN) {
  453. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
  454. } else if (pProvData->dwProvFlags &
  455. WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT) {
  456. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  457. } else if (pProvData->pWintrustData->fdwRevocationChecks ==
  458. WTD_REVOKE_WHOLECHAIN) {
  459. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
  460. } else if (fCounterSigner && SGNR_TYPE_TIMESTAMP == pSgnr->dwSignerType) {
  461. if (0 == (pProvData->dwRegPolicySettings & WTPF_IGNOREREVOCATIONONTS))
  462. // On 4-12-01 changed from END_CERT to EXCLUDE_ROOT
  463. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  464. } else if (0 == (pProvData->dwRegPolicySettings & WTPF_IGNOREREVOKATION))
  465. // On 4-12-01 changed from END_CERT to EXCLUDE_ROOT
  466. dwCreateChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  467. if (!(pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_CERT ||
  468. pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_SIGNER))
  469. // Certificate was obtained from either the message store, or one
  470. // of our known stores
  471. dwCreateChainFlags |= CERT_CHAIN_CACHE_END_CERT;
  472. // else
  473. // Can't implicitly cache a context passed to us
  474. if (pProvData->dwProvFlags & WTD_CACHE_ONLY_URL_RETRIEVAL)
  475. {
  476. dwCreateChainFlags |= CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL |
  477. CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
  478. }
  479. #if 0
  480. {
  481. HCERTSTORE hDebugStore;
  482. if (hDebugStore = CertOpenSystemStoreA(0, "wintrust")) {
  483. CertAddCertificateContextToStore(
  484. hDebugStore,
  485. pCertContext,
  486. CERT_STORE_ADD_ALWAYS,
  487. NULL
  488. );
  489. CertCloseStore(hDebugStore, 0);
  490. }
  491. }
  492. #endif
  493. FILETIME fileTime;
  494. memset(&fileTime, 0, sizeof(fileTime));
  495. if (fTimeStamped && *pfLifetimeSigning)
  496. dwCreateChainFlags |= CERT_CHAIN_TIMESTAMP_TIME;
  497. if (!CertGetCertificateChain (
  498. hChainEngine,
  499. pCertContext,
  500. (memcmp(&pSgnr->sftVerifyAsOf, &fileTime, sizeof(fileTime)) == 0) ?
  501. NULL : &pSgnr->sftVerifyAsOf,
  502. hAdditionalStore,
  503. &ChainPara,
  504. dwCreateChainFlags,
  505. NULL, // pvReserved,
  506. &pChainContext
  507. )) {
  508. pProvData->dwError = GetLastError();
  509. dwSgnrError = TRUST_E_SYSTEM_ERROR;
  510. goto GetChainError;
  511. }
  512. if (fTimeStamped && !*pfLifetimeSigning) {
  513. // See if resultant application policy has the LIFETIME_SIGNING OID
  514. PCERT_ENHKEY_USAGE pAppUsage =
  515. pChainContext->rgpChain[0]->rgpElement[0]->pApplicationUsage;
  516. if (pAppUsage) {
  517. DWORD i;
  518. for (i = 0; i < pAppUsage->cUsageIdentifier; i++) {
  519. if (0 == strcmp(pAppUsage->rgpszUsageIdentifier[i],
  520. szOID_KP_LIFETIME_SIGNING)) {
  521. *pfLifetimeSigning = TRUE;
  522. break;
  523. }
  524. }
  525. }
  526. if (*pfLifetimeSigning) {
  527. CertFreeCertificateChain(pChainContext);
  528. pChainContext = NULL;
  529. dwCreateChainFlags |= CERT_CHAIN_TIMESTAMP_TIME;
  530. if (!CertGetCertificateChain (
  531. hChainEngine,
  532. pCertContext,
  533. (memcmp(&pSgnr->sftVerifyAsOf, &fileTime, sizeof(fileTime)) == 0) ?
  534. NULL : &pSgnr->sftVerifyAsOf,
  535. hAdditionalStore,
  536. &ChainPara,
  537. dwCreateChainFlags,
  538. NULL, // pvReserved,
  539. &pChainContext
  540. )) {
  541. pProvData->dwError = GetLastError();
  542. dwSgnrError = TRUST_E_SYSTEM_ERROR;
  543. goto GetChainError;
  544. }
  545. }
  546. }
  547. pSgnr->pChainContext = pChainContext;
  548. if (pProvData->dwProvFlags & WTD_NO_IE4_CHAIN_FLAG) {
  549. pProvData->dwProvFlags |= CPD_USE_NT5_CHAIN_FLAG;
  550. fResult = TRUE;
  551. } else
  552. fResult = UpdateCertProvChain(
  553. pProvData,
  554. idxSigner,
  555. pdwError,
  556. fCounterSigner,
  557. idxCounterSigner,
  558. pSgnr,
  559. pChainContext
  560. );
  561. CommonReturn:
  562. if (hChainEngine)
  563. CertFreeCertificateChainEngine(hChainEngine);
  564. if (hAdditionalStore)
  565. CertCloseStore(hAdditionalStore, 0);
  566. return fResult;
  567. ErrorReturn:
  568. pSgnr->dwError = dwSgnrError;
  569. pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
  570. dwSgnrError;
  571. *pdwError = S_FALSE;
  572. fResult = FALSE;
  573. goto CommonReturn;
  574. TRACE_ERROR_EX(DBG_SS, NoSignerCertError)
  575. TRACE_ERROR_EX(DBG_SS, GetChainError)
  576. }
  577. BOOL WINAPI _IsLifetimeSigningCert(
  578. PCCERT_CONTEXT pCertContext
  579. )
  580. {
  581. DWORD cbSize;
  582. PCERT_ENHKEY_USAGE pCertEKU;
  583. //
  584. // see if the certificate has the proper enhanced key usage OID
  585. //
  586. cbSize = 0;
  587. CertGetEnhancedKeyUsage(pCertContext,
  588. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  589. NULL,
  590. &cbSize);
  591. if (cbSize == 0)
  592. {
  593. return(FALSE);
  594. }
  595. if (!(pCertEKU = (PCERT_ENHKEY_USAGE)new BYTE[cbSize]))
  596. {
  597. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  598. return(FALSE);
  599. }
  600. if (!(CertGetEnhancedKeyUsage(pCertContext,
  601. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  602. pCertEKU,
  603. &cbSize)))
  604. {
  605. delete pCertEKU;
  606. return(FALSE);
  607. }
  608. for (int i = 0; i < (int)pCertEKU->cUsageIdentifier; i++)
  609. {
  610. if (strcmp(pCertEKU->rgpszUsageIdentifier[i], szOID_KP_LIFETIME_SIGNING) == 0)
  611. {
  612. delete pCertEKU;
  613. return(TRUE);
  614. }
  615. }
  616. delete pCertEKU;
  617. return(FALSE);
  618. }