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.

1762 lines
58 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001 - 2001
  6. //
  7. // File: wxptrust.cpp
  8. //
  9. // Contents: Windows XP version of the Outlook WinVerify Trust Provider
  10. //
  11. // Functions: WXP_CertTrustDllMain
  12. // CertTrustInit
  13. // CertTrustCertPolicy - shouldn't be called
  14. // CertTrustFinalPolicy
  15. // CertTrustCleanup - shouldn't be called
  16. //
  17. // CertModifyCertificatesToTrust
  18. // FModifyTrust
  19. // FreeWVTHandle
  20. // HrDoTrustWork
  21. // FormatValidityFailures
  22. //
  23. // History: 11-Feb-2001 philh created (rewrite to use chain APIs)
  24. //
  25. //--------------------------------------------------------------------------
  26. #include "pch.hxx"
  27. #include <wintrust.h>
  28. #include "demand.h"
  29. #include <stdio.h>
  30. // The following should be moved to cryptdlg.h
  31. #define CERT_VALIDITY_POLICY_FAILURE 0x00001000
  32. #define CERT_VALIDITY_BASIC_CONSTRAINTS_FAILURE 0x00002000
  33. const char SzPolicyKey[] =
  34. "SOFTWARE\\Microsoft\\Cryptography\\" szCERT_CERTIFICATE_ACTION_VERIFY;
  35. const char SzPolicyData[] = "PolicyFlags";
  36. const char SzUrlRetrievalTimeoutData[] = "UrlRetrievalTimeout"; // milliseconds
  37. #define EXPLICIT_TRUST_NONE 0
  38. #define EXPLICIT_TRUST_YES 1
  39. #define EXPLICIT_TRUST_NO 2
  40. #define MAX_HASH_LEN 20
  41. #define MIN_HASH_LEN 16
  42. // ExplictTrust is encoded as a SEQUENCE OF Attribues. We are only
  43. // interested in encoding one attribute with one value. We will only change
  44. // the last byte. It contains the trust value. It can be: 0-NONE, 1-YES, 2-NO.
  45. const BYTE rgbEncodedExplictTrust[] = {
  46. 0x30, 0x13, // SEQUENCE OF
  47. 0x30, 0x11, // SEQUENCE
  48. 0x06, 0x0a, // OID: 1.3.6.1.4.1.311.10.4.1
  49. 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0A, 0x04, 0x01,
  50. 0x31, 0x03, // SET OF
  51. 0x02, 0x01, 0x00 // INTEGER: 0-NONE, 1-YES, 2-NO
  52. };
  53. HINSTANCE g_hCertTrustInst;
  54. HCERTSTORE g_hStoreTrustedPeople;
  55. HCERTSTORE g_hStoreDisallowed;
  56. // Cached Chain. We remember the last built chain context and try to re-use.
  57. // Outlook calls us 2 or 3 times to build a chain for the same certificate
  58. // context.
  59. CRITICAL_SECTION g_CachedChainCriticalSection;
  60. DWORD g_dwCachedCreateChainFlags;
  61. PCCERT_CHAIN_CONTEXT g_pCachedChainContext;
  62. FILETIME g_ftCachedChain;
  63. #define CACHED_CHAIN_SECONDS_DURATION 30
  64. BOOL
  65. WINAPI
  66. WXP_CertTrustDllMain(
  67. HINSTANCE hInst,
  68. ULONG ulReason,
  69. LPVOID
  70. )
  71. {
  72. BOOL fResult = TRUE;
  73. switch (ulReason) {
  74. case DLL_PROCESS_ATTACH:
  75. g_hCertTrustInst = hInst;
  76. __try {
  77. InitializeCriticalSection(&g_CachedChainCriticalSection);
  78. } __except(EXCEPTION_EXECUTE_HANDLER) {
  79. SetLastError(GetExceptionCode());
  80. fResult = FALSE;
  81. }
  82. break;
  83. case DLL_PROCESS_DETACH:
  84. if (g_hStoreTrustedPeople)
  85. CertCloseStore(g_hStoreTrustedPeople, 0);
  86. if (g_hStoreDisallowed)
  87. CertCloseStore(g_hStoreDisallowed, 0);
  88. if (g_pCachedChainContext)
  89. CertFreeCertificateChain(g_pCachedChainContext);
  90. DeleteCriticalSection(&g_CachedChainCriticalSection);
  91. break;
  92. case DLL_THREAD_DETACH:
  93. default:
  94. break;
  95. }
  96. return fResult;
  97. }
  98. HCERTSTORE
  99. I_OpenCachedHKCUStore(
  100. IN OUT HCERTSTORE *phStoreCache,
  101. IN LPCWSTR pwszStore
  102. )
  103. {
  104. HCERTSTORE hStore;
  105. hStore = *phStoreCache;
  106. if (NULL == hStore) {
  107. hStore = CertOpenStore(
  108. CERT_STORE_PROV_SYSTEM_W,
  109. 0,
  110. NULL,
  111. CERT_SYSTEM_STORE_CURRENT_USER |
  112. CERT_STORE_MAXIMUM_ALLOWED_FLAG |
  113. CERT_STORE_SHARE_CONTEXT_FLAG,
  114. (const void *) pwszStore
  115. );
  116. if (hStore) {
  117. HCERTSTORE hPrevStore;
  118. CertControlStore(
  119. hStore,
  120. 0, // dwFlags
  121. CERT_STORE_CTRL_AUTO_RESYNC,
  122. NULL // pvCtrlPara
  123. );
  124. hPrevStore = InterlockedCompareExchangePointer(
  125. phStoreCache, hStore, NULL);
  126. if (hPrevStore) {
  127. CertCloseStore(hStore, 0);
  128. hStore = hPrevStore;
  129. }
  130. }
  131. }
  132. if (hStore)
  133. hStore = CertDuplicateStore(hStore);
  134. return hStore;
  135. }
  136. HCERTSTORE
  137. I_OpenTrustedPeopleStore()
  138. {
  139. return I_OpenCachedHKCUStore(&g_hStoreTrustedPeople, L"TrustedPeople");
  140. }
  141. HCERTSTORE
  142. I_OpenDisallowedStore()
  143. {
  144. return I_OpenCachedHKCUStore(&g_hStoreDisallowed, L"Disallowed");
  145. }
  146. // We use signature hash. For untrusted, this will find certificates with
  147. // altered signature content.
  148. PCCERT_CONTEXT
  149. I_FindCertificateInOtherStore(
  150. IN HCERTSTORE hOtherStore,
  151. IN PCCERT_CONTEXT pCert
  152. )
  153. {
  154. BYTE rgbHash[MAX_HASH_LEN];
  155. CRYPT_DATA_BLOB HashBlob;
  156. HashBlob.pbData = rgbHash;
  157. HashBlob.cbData = MAX_HASH_LEN;
  158. if (!CertGetCertificateContextProperty(
  159. pCert,
  160. CERT_SIGNATURE_HASH_PROP_ID,
  161. rgbHash,
  162. &HashBlob.cbData
  163. ) || MIN_HASH_LEN > HashBlob.cbData)
  164. return NULL;
  165. return CertFindCertificateInStore(
  166. hOtherStore,
  167. 0, // dwCertEncodingType
  168. 0, // dwFindFlags
  169. CERT_FIND_SIGNATURE_HASH,
  170. (const void *) &HashBlob,
  171. NULL //pPrevCertContext
  172. );
  173. }
  174. // Returns:
  175. // +1 - Cert was successfully deleted
  176. // 0 - Cert wasn't found
  177. // -1 - Delete failed (GetLastError() for failure reason)
  178. //
  179. LONG
  180. I_DeleteCertificateFromOtherStore(
  181. IN HCERTSTORE hOtherStore,
  182. IN PCCERT_CONTEXT pCert
  183. )
  184. {
  185. LONG lDelete;
  186. PCCERT_CONTEXT pOtherCert;
  187. BYTE rgbHash[MAX_HASH_LEN];
  188. CRYPT_DATA_BLOB HashBlob;
  189. HashBlob.pbData = rgbHash;
  190. HashBlob.cbData = MAX_HASH_LEN;
  191. if (!CertGetCertificateContextProperty(
  192. pCert,
  193. CERT_SIGNATURE_HASH_PROP_ID,
  194. rgbHash,
  195. &HashBlob.cbData
  196. ) || MIN_HASH_LEN > HashBlob.cbData)
  197. return 0;
  198. // Note, there is a possibility that multiple certs can have
  199. // the same signature hash. For example, the signature algorithm
  200. // parameters may have been altered. Change empty NULL : {0x05, 0x00} to
  201. // empty OCTET : {0x04, 0x00}.
  202. lDelete = 0;
  203. pOtherCert = NULL;
  204. while (pOtherCert = CertFindCertificateInStore(
  205. hOtherStore,
  206. 0, // dwCertEncodingType
  207. 0, // dwFindFlags
  208. CERT_FIND_SIGNATURE_HASH,
  209. (const void *) &HashBlob,
  210. pOtherCert
  211. )) {
  212. CertDuplicateCertificateContext(pOtherCert);
  213. if (CertDeleteCertificateFromStore(pOtherCert)) {
  214. if (0 == lDelete)
  215. lDelete = 1;
  216. } else
  217. lDelete = -1;
  218. }
  219. return lDelete;
  220. }
  221. HRESULT
  222. I_CheckExplicitTrust(
  223. IN PCCERT_CONTEXT pCert,
  224. IN LPFILETIME pftCurrent,
  225. OUT BYTE *pbExplicitTrust
  226. )
  227. {
  228. HRESULT hr;
  229. BYTE bExplicitTrust = EXPLICIT_TRUST_NONE;
  230. HCERTSTORE hStoreDisallowed = NULL;
  231. HCERTSTORE hStoreTrustedPeople = NULL;
  232. PCCERT_CONTEXT pFindCert = NULL;
  233. hStoreDisallowed = I_OpenDisallowedStore();
  234. if (NULL == hStoreDisallowed)
  235. goto OpenDisallowedStoreError;
  236. pFindCert = I_FindCertificateInOtherStore(hStoreDisallowed, pCert);
  237. if (pFindCert) {
  238. bExplicitTrust = EXPLICIT_TRUST_NO;
  239. goto SuccessReturn;
  240. }
  241. hStoreTrustedPeople = I_OpenTrustedPeopleStore();
  242. if (NULL == hStoreTrustedPeople)
  243. goto SuccessReturn;
  244. pFindCert = I_FindCertificateInOtherStore(hStoreTrustedPeople, pCert);
  245. if (pFindCert) {
  246. // Must be time valid to trust
  247. if (0 == CertVerifyTimeValidity(pftCurrent, pCert->pCertInfo))
  248. bExplicitTrust = EXPLICIT_TRUST_YES;
  249. else
  250. // Remove the expired cert. Just in case there are
  251. // altered certificates having the same signature hash, do
  252. // the following delete.
  253. I_DeleteCertificateFromOtherStore(hStoreTrustedPeople, pFindCert);
  254. }
  255. SuccessReturn:
  256. hr = S_OK;
  257. CommonReturn:
  258. if (pFindCert)
  259. CertFreeCertificateContext(pFindCert);
  260. if (hStoreDisallowed)
  261. CertCloseStore(hStoreDisallowed, 0);
  262. if (hStoreTrustedPeople)
  263. CertCloseStore(hStoreTrustedPeople, 0);
  264. *pbExplicitTrust = bExplicitTrust;
  265. return hr;
  266. OpenDisallowedStoreError:
  267. // Most likely unable to access
  268. hr = E_ACCESSDENIED;
  269. goto CommonReturn;
  270. }
  271. //+-------------------------------------------------------------------------
  272. // Subtract two filetimes and return the number of seconds.
  273. //
  274. // The second filetime is subtracted from the first. If the first filetime
  275. // is before the second, then, 0 seconds is returned.
  276. //
  277. // Filetime is in units of 100 nanoseconds. Each second has
  278. // 10**7 100 nanoseconds.
  279. //--------------------------------------------------------------------------
  280. __inline
  281. DWORD
  282. WINAPI
  283. I_SubtractFileTimes(
  284. IN LPFILETIME pftFirst,
  285. IN LPFILETIME pftSecond
  286. )
  287. {
  288. DWORDLONG qwDiff;
  289. if (0 >= CompareFileTime(pftFirst, pftSecond))
  290. return 0;
  291. qwDiff = *(((DWORDLONG UNALIGNED *) pftFirst)) -
  292. *(((DWORDLONG UNALIGNED *) pftSecond));
  293. return (DWORD) (qwDiff / 10000000i64);
  294. }
  295. PCCERT_CHAIN_CONTEXT
  296. I_CheckCachedChain(
  297. IN PCCERT_CONTEXT pCert,
  298. IN DWORD dwCreateChainFlags
  299. )
  300. {
  301. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  302. FILETIME ftCurrent;
  303. EnterCriticalSection(&g_CachedChainCriticalSection);
  304. if (NULL == g_pCachedChainContext)
  305. goto CommonReturn;
  306. if (g_pCachedChainContext->rgpChain[0]->rgpElement[0]->pCertContext !=
  307. pCert)
  308. goto CommonReturn;
  309. if (dwCreateChainFlags == g_dwCachedCreateChainFlags)
  310. ;
  311. else {
  312. if ((dwCreateChainFlags & g_dwCachedCreateChainFlags) !=
  313. dwCreateChainFlags)
  314. goto CommonReturn;
  315. if (g_pCachedChainContext->TrustStatus.dwErrorStatus &
  316. (CERT_TRUST_IS_REVOKED | CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
  317. goto CommonReturn;
  318. }
  319. GetSystemTimeAsFileTime(&ftCurrent);
  320. if (CACHED_CHAIN_SECONDS_DURATION <
  321. I_SubtractFileTimes(&ftCurrent, &g_ftCachedChain)) {
  322. CertFreeCertificateChain(g_pCachedChainContext);
  323. g_pCachedChainContext = NULL;
  324. goto CommonReturn;
  325. }
  326. pChainContext = CertDuplicateCertificateChain(g_pCachedChainContext);
  327. CommonReturn:
  328. LeaveCriticalSection(&g_CachedChainCriticalSection);
  329. return pChainContext;
  330. }
  331. void
  332. I_SetCachedChain(
  333. IN PCCERT_CHAIN_CONTEXT pChainContext,
  334. IN DWORD dwCreateChainFlags
  335. )
  336. {
  337. if (pChainContext->TrustStatus.dwErrorStatus &
  338. (CERT_TRUST_IS_NOT_SIGNATURE_VALID |
  339. CERT_TRUST_IS_PARTIAL_CHAIN))
  340. return;
  341. EnterCriticalSection(&g_CachedChainCriticalSection);
  342. if (g_pCachedChainContext)
  343. CertFreeCertificateChain(g_pCachedChainContext);
  344. g_pCachedChainContext = CertDuplicateCertificateChain(pChainContext);
  345. g_dwCachedCreateChainFlags = dwCreateChainFlags;
  346. GetSystemTimeAsFileTime(&g_ftCachedChain);
  347. LeaveCriticalSection(&g_CachedChainCriticalSection);
  348. }
  349. // Assumption: the message store is included in the rghstoreCAs array.
  350. // Will ignore the rghstoreRoots and rghstoreTrust store arrays. These
  351. // certs should already be opened and cached in the chain engine.
  352. HCERTSTORE
  353. I_GetChainAdditionalStore(
  354. IN PCERT_VERIFY_CERTIFICATE_TRUST pCertTrust
  355. )
  356. {
  357. if (0 == pCertTrust->cStores)
  358. return NULL;
  359. if (1 < pCertTrust->cStores) {
  360. HCERTSTORE hCollectionStore;
  361. if (hCollectionStore = CertOpenStore(
  362. CERT_STORE_PROV_COLLECTION,
  363. 0, // dwEncodingType
  364. 0, // hCryptProv
  365. 0, // dwFlags
  366. NULL // pvPara
  367. )) {
  368. DWORD i;
  369. for (i = 0; i < pCertTrust->cStores; i++)
  370. CertAddStoreToCollection(
  371. hCollectionStore,
  372. pCertTrust->rghstoreCAs[i],
  373. CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
  374. 0 // dwPriority
  375. );
  376. }
  377. return hCollectionStore;
  378. } else
  379. return CertDuplicateStore(pCertTrust->rghstoreCAs[0]);
  380. }
  381. HRESULT
  382. I_BuildChain(
  383. IN PCERT_VERIFY_CERTIFICATE_TRUST pCertTrust,
  384. IN LPFILETIME pftCurrent,
  385. IN DWORD dwPolicy,
  386. IN DWORD dwUrlRetrievalTimeout,
  387. OUT PCCERT_CHAIN_CONTEXT* ppChainContext
  388. )
  389. {
  390. HRESULT hr;
  391. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  392. DWORD dwCreateChainFlags = 0;
  393. CERT_CHAIN_PARA ChainPara;
  394. HCERTSTORE hAdditionalStore = NULL;
  395. HCRYPTDEFAULTCONTEXT hDefaultContext = NULL;
  396. // Update the revocation flags to be used for chain building
  397. if (pCertTrust->dwFlags & CRYPTDLG_REVOCATION_ONLINE) {
  398. // Allow full online revocation checking
  399. dwCreateChainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN;
  400. } else if (pCertTrust->dwFlags & CRYPTDLG_REVOCATION_CACHE) {
  401. // Allow local revocation checks only, do not hit the network.
  402. dwCreateChainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN |
  403. CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
  404. } else if (pCertTrust->dwFlags & CRYPTDLG_REVOCATION_NONE) {
  405. ;
  406. } else if (dwPolicy & ACTION_REVOCATION_DEFAULT_ONLINE) {
  407. // Allow full online revocation checking
  408. dwCreateChainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN;
  409. } else if (dwPolicy & ACTION_REVOCATION_DEFAULT_CACHE) {
  410. // Allow local revocation checks only, do not hit the network
  411. dwCreateChainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN |
  412. CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
  413. }
  414. // Enable LRU caching of the end certificate. Also, set an upper limit
  415. // for all CRL URL fetches.
  416. dwCreateChainFlags |= CERT_CHAIN_CACHE_END_CERT |
  417. CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT;
  418. pChainContext = I_CheckCachedChain(
  419. pCertTrust->pccert,
  420. dwCreateChainFlags
  421. );
  422. if (NULL != pChainContext)
  423. goto SuccessReturn;
  424. if (pCertTrust->hprov != NULL) {
  425. // Set the default crypt provider so we can make sure that ours is used
  426. if (!CryptInstallDefaultContext(pCertTrust->hprov,
  427. CRYPT_DEFAULT_CONTEXT_CERT_SIGN_OID,
  428. szOID_OIWSEC_md5RSA, 0, NULL, &hDefaultContext))
  429. goto InstallDefaultContextError;
  430. }
  431. memset(&ChainPara, 0, sizeof(ChainPara));
  432. ChainPara.cbSize = sizeof(ChainPara);
  433. if (pCertTrust->pszUsageOid && '\0' != pCertTrust->pszUsageOid[0]) {
  434. ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  435. ChainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
  436. ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier =
  437. &pCertTrust->pszUsageOid;
  438. }
  439. ChainPara.dwUrlRetrievalTimeout = dwUrlRetrievalTimeout;
  440. hAdditionalStore = I_GetChainAdditionalStore(pCertTrust);
  441. if (!CertGetCertificateChain (
  442. HCCE_CURRENT_USER,
  443. pCertTrust->pccert,
  444. pftCurrent,
  445. hAdditionalStore,
  446. &ChainPara,
  447. dwCreateChainFlags,
  448. NULL, // pvReserved,
  449. &pChainContext
  450. ))
  451. goto GetChainError;
  452. I_SetCachedChain(pChainContext, dwCreateChainFlags);
  453. SuccessReturn:
  454. hr = S_OK;
  455. CommonReturn:
  456. if (hDefaultContext)
  457. CryptUninstallDefaultContext(hDefaultContext, 0, NULL);
  458. if (hAdditionalStore)
  459. CertCloseStore(hAdditionalStore, 0);
  460. *ppChainContext = pChainContext;
  461. return hr;
  462. GetChainError:
  463. InstallDefaultContextError:
  464. pChainContext = NULL;
  465. hr = TRUST_E_SYSTEM_ERROR;
  466. goto CommonReturn;
  467. }
  468. DWORD
  469. I_MapValidityErrorsToTrustError(
  470. IN DWORD dwErrors
  471. )
  472. {
  473. DWORD dwTrustError = S_OK;
  474. // Look at them in decreasing order of importance
  475. if (dwErrors) {
  476. if (dwErrors & CERT_VALIDITY_EXPLICITLY_DISTRUSTED) {
  477. dwTrustError = TRUST_E_EXPLICIT_DISTRUST;
  478. } else if (dwErrors & CERT_VALIDITY_SIGNATURE_FAILS) {
  479. dwTrustError = TRUST_E_CERT_SIGNATURE;
  480. } else if (dwErrors & CERT_VALIDITY_NO_ISSUER_CERT_FOUND) {
  481. dwTrustError = CERT_E_CHAINING;
  482. } else if (dwErrors & CERT_VALIDITY_NO_TRUST_DATA) {
  483. dwTrustError = CERT_E_UNTRUSTEDROOT;
  484. } else if (dwErrors & CERT_VALIDITY_CERTIFICATE_REVOKED) {
  485. dwTrustError = CERT_E_REVOKED;
  486. } else if (dwErrors & CERT_VALIDITY_EXTENDED_USAGE_FAILURE) {
  487. dwTrustError = CERT_E_WRONG_USAGE;
  488. } else if (dwErrors &
  489. (CERT_VALIDITY_BEFORE_START | CERT_VALIDITY_AFTER_END)) {
  490. dwTrustError = CERT_E_EXPIRED;
  491. } else if (dwErrors & CERT_VALIDITY_NAME_CONSTRAINTS_FAILURE) {
  492. dwTrustError = CERT_E_INVALID_NAME;
  493. } else if (dwErrors & CERT_VALIDITY_POLICY_FAILURE) {
  494. dwTrustError = CERT_E_INVALID_POLICY;
  495. } else if (dwErrors & CERT_VALIDITY_BASIC_CONSTRAINTS_FAILURE) {
  496. dwTrustError = TRUST_E_BASIC_CONSTRAINTS;
  497. } else if (dwErrors & CERT_VALIDITY_NO_CRL_FOUND) {
  498. dwTrustError = CERT_E_REVOCATION_FAILURE;
  499. } else if (dwErrors & (CERT_VALIDITY_ISSUER_INVALID |
  500. CERT_VALIDITY_ISSUER_DISTRUST)) {
  501. dwTrustError = CERT_E_UNTRUSTEDROOT;
  502. } else {
  503. dwTrustError = TRUST_E_FAIL;
  504. }
  505. }
  506. return dwTrustError;
  507. }
  508. HRESULT
  509. I_UpdateCertProvFromExplicitTrust(
  510. IN OUT PCRYPT_PROVIDER_DATA pProvData,
  511. IN PCCERT_CONTEXT pCert,
  512. IN DWORD dwAllErrors
  513. )
  514. {
  515. CRYPT_PROVIDER_SGNR Sgnr;
  516. PCRYPT_PROVIDER_SGNR pSgnr;
  517. PCRYPT_PROVIDER_CERT pProvCert;
  518. memset(&Sgnr, 0, sizeof(Sgnr));
  519. Sgnr.cbStruct = sizeof(Sgnr);
  520. if (!pProvData->psPfns->pfnAddSgnr2Chain(
  521. pProvData,
  522. FALSE, // fCounterSigner
  523. 0, // idwSigner
  524. &Sgnr
  525. ))
  526. return TRUST_E_SYSTEM_ERROR;
  527. if (!pProvData->psPfns->pfnAddCert2Chain(
  528. pProvData,
  529. 0, // idxSigner
  530. FALSE, // fCounterSigner
  531. 0, // idxCounterSigner
  532. pCert
  533. ))
  534. return TRUST_E_SYSTEM_ERROR;
  535. pSgnr = WTHelperGetProvSignerFromChain(
  536. pProvData,
  537. 0, // idxSigner
  538. FALSE, // fCounterSigner
  539. 0 // idxCounterSigner
  540. );
  541. if (NULL == pSgnr)
  542. return TRUST_E_SYSTEM_ERROR;
  543. pProvCert = WTHelperGetProvCertFromChain(
  544. pSgnr,
  545. 0 // idxCert
  546. );
  547. if (NULL == pProvCert)
  548. return TRUST_E_SYSTEM_ERROR;
  549. pSgnr->dwError = pProvCert->dwError =
  550. I_MapValidityErrorsToTrustError(dwAllErrors);
  551. // Map to IE4Trust confidence
  552. pProvCert->dwConfidence |=
  553. CERT_CONFIDENCE_SIG |
  554. CERT_CONFIDENCE_TIMENEST |
  555. CERT_CONFIDENCE_AUTHIDEXT |
  556. CERT_CONFIDENCE_HYGIENE
  557. ;
  558. if (!(dwAllErrors &
  559. (CERT_VALIDITY_BEFORE_START | CERT_VALIDITY_AFTER_END)))
  560. pProvCert->dwConfidence |= CERT_CONFIDENCE_TIME;
  561. return S_OK;
  562. }
  563. HRESULT
  564. I_UpdateCertProvChain(
  565. IN OUT PCRYPT_PROVIDER_DATA pProvData,
  566. IN PCCERT_CHAIN_CONTEXT pChainContext,
  567. IN DWORD cTrustCert,
  568. IN DWORD rgdwErrors[],
  569. IN DWORD dwAllErrors
  570. )
  571. {
  572. CRYPT_PROVIDER_SGNR Sgnr;
  573. PCRYPT_PROVIDER_SGNR pSgnr;
  574. DWORD iTrustCert;
  575. DWORD i;
  576. memset(&Sgnr, 0, sizeof(Sgnr));
  577. Sgnr.cbStruct = sizeof(Sgnr);
  578. if (!pProvData->psPfns->pfnAddSgnr2Chain(
  579. pProvData,
  580. FALSE, // fCounterSigner
  581. 0, // idwSigner
  582. &Sgnr
  583. ))
  584. return TRUST_E_SYSTEM_ERROR;
  585. pSgnr = WTHelperGetProvSignerFromChain(
  586. pProvData,
  587. 0, // idxSigner
  588. FALSE, // fCounterSigner
  589. 0 // idxCounterSigner
  590. );
  591. if (NULL == pSgnr)
  592. return TRUST_E_SYSTEM_ERROR;
  593. pSgnr->pChainContext = CertDuplicateCertificateChain(pChainContext);
  594. pSgnr->dwError = I_MapValidityErrorsToTrustError(dwAllErrors);
  595. iTrustCert = 0;
  596. for (i = 0; i < pChainContext->cChain; i++) {
  597. DWORD j;
  598. PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[i];
  599. for (j = 0; j < pChain->cElement; j++) {
  600. PCERT_CHAIN_ELEMENT pEle = pChain->rgpElement[j];
  601. DWORD dwEleError = pEle->TrustStatus.dwErrorStatus;
  602. DWORD dwEleInfo = pEle->TrustStatus.dwInfoStatus;
  603. PCRYPT_PROVIDER_CERT pProvCert;
  604. if (iTrustCert >= cTrustCert)
  605. return TRUST_E_SYSTEM_ERROR;
  606. if (!pProvData->psPfns->pfnAddCert2Chain(
  607. pProvData,
  608. 0, // idxSigner
  609. FALSE, // fCounterSigner
  610. 0, // idxCounterSigner
  611. pEle->pCertContext
  612. ))
  613. return TRUST_E_SYSTEM_ERROR;
  614. pProvCert = WTHelperGetProvCertFromChain(
  615. pSgnr,
  616. iTrustCert
  617. );
  618. if (NULL == pProvCert)
  619. return TRUST_E_SYSTEM_ERROR;
  620. //DSIE: 12-Oct-2000 added pChainElement to CRYPT_PROVIDER_CERT.
  621. if (WVT_ISINSTRUCT(CRYPT_PROVIDER_CERT, pProvCert->cbStruct,
  622. pChainElement))
  623. pProvCert->pChainElement = pEle;
  624. pProvCert->fSelfSigned =
  625. 0 != (dwEleInfo & CERT_TRUST_IS_SELF_SIGNED) &&
  626. 0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID);
  627. pProvCert->fTrustedRoot =
  628. pProvCert->fSelfSigned &&
  629. i == pChainContext->cChain - 1 &&
  630. j == pChain->cElement - 1 &&
  631. 0 == (dwEleError & CERT_TRUST_IS_UNTRUSTED_ROOT);
  632. // First Element in all but the first simple chain
  633. pProvCert->fTrustListSignerCert = (0 < i && 0 == j);
  634. pProvCert->fIsCyclic = (0 != (dwEleError & CERT_TRUST_IS_CYCLIC));
  635. // Map to IE4Trust confidence
  636. if (0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
  637. pProvCert->dwConfidence |= CERT_CONFIDENCE_SIG;
  638. if (0 == (dwEleError & CERT_TRUST_IS_NOT_TIME_VALID))
  639. pProvCert->dwConfidence |= CERT_CONFIDENCE_TIME;
  640. // On Sep 10, 1998 Trevor/Brian wanted time nesting checks to
  641. // be disabled
  642. // if (0 == (dwEleError & CERT_TRUST_IS_NOT_TIME_NESTED))
  643. pProvCert->dwConfidence |= CERT_CONFIDENCE_TIMENEST;
  644. if (0 != (dwEleInfo & CERT_TRUST_HAS_EXACT_MATCH_ISSUER))
  645. pProvCert->dwConfidence |= CERT_CONFIDENCE_AUTHIDEXT;
  646. if (0 == (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID) &&
  647. 0 != (dwEleInfo & CERT_TRUST_HAS_EXACT_MATCH_ISSUER))
  648. pProvCert->dwConfidence |= CERT_CONFIDENCE_HYGIENE;
  649. if (pEle->pRevocationInfo) {
  650. pProvCert->dwRevokedReason =
  651. pEle->pRevocationInfo->dwRevocationResult;
  652. }
  653. pProvCert->dwError = I_MapValidityErrorsToTrustError(
  654. rgdwErrors[iTrustCert]);
  655. // If last element in simple chain, check if it was in a
  656. // CTL and update CryptProvData if it was.
  657. if (j == pChain->cElement - 1 && pChain->pTrustListInfo &&
  658. pChain->pTrustListInfo->pCtlContext) {
  659. DWORD dwChainError = pChain->TrustStatus.dwErrorStatus;
  660. // Note, don't need to AddRef since we already hold an
  661. // AddRef on the ChainContext.
  662. pProvCert->pCtlContext = pChain->pTrustListInfo->pCtlContext;
  663. if (dwChainError & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID) {
  664. pProvCert->dwCtlError = TRUST_E_CERT_SIGNATURE;
  665. } else if (dwChainError & CERT_TRUST_CTL_IS_NOT_TIME_VALID) {
  666. pProvCert->dwCtlError = CERT_E_EXPIRED;
  667. } else if (dwChainError &
  668. CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) {
  669. pProvCert->dwCtlError = CERT_E_WRONG_USAGE;
  670. }
  671. }
  672. iTrustCert++;
  673. }
  674. }
  675. return S_OK;
  676. }
  677. HRESULT
  678. CertTrustFinalPolicy(
  679. IN OUT PCRYPT_PROVIDER_DATA pProvData
  680. )
  681. {
  682. HRESULT hr;
  683. PCERT_VERIFY_CERTIFICATE_TRUST pCertTrust;
  684. DWORD dwPolicy = 0;
  685. DWORD dwUrlRetrievalTimeout = 0;
  686. FILETIME ftCurrent;
  687. BYTE bExplicitTrust = EXPLICIT_TRUST_NONE;
  688. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  689. DWORD cTrustCert = 0;
  690. PCCERT_CONTEXT *rgpTrustCert = NULL;
  691. DWORD *rgdwErrors = NULL;
  692. DATA_BLOB *rgBlobTrustInfo = NULL;
  693. DWORD dwAllErrors = 0;
  694. // Verify we are called by a version of WVT having all of the fields we will
  695. // be using.
  696. if (!WVT_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, dwFinalError))
  697. return E_INVALIDARG;
  698. // Continue checking that we have everything we need.
  699. if (pProvData->pWintrustData->pBlob->cbStruct <
  700. sizeof(WINTRUST_BLOB_INFO))
  701. goto InvalidProvData;
  702. pCertTrust = (PCERT_VERIFY_CERTIFICATE_TRUST)
  703. pProvData->pWintrustData->pBlob->pbMemObject;
  704. if ((pCertTrust == NULL) ||
  705. (pCertTrust->cbSize < sizeof(*pCertTrust)))
  706. goto InvalidProvData;
  707. // If present, retrieve policy flags and URL retrieval timeout from
  708. // the registry
  709. {
  710. HKEY hKeyPolicy;
  711. if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_LOCAL_MACHINE, SzPolicyKey,
  712. 0, KEY_READ, &hKeyPolicy)) {
  713. DWORD dwType;
  714. DWORD cbSize;
  715. cbSize = sizeof(dwPolicy);
  716. if (ERROR_SUCCESS != RegQueryValueExA(hKeyPolicy, SzPolicyData,
  717. 0, &dwType, (LPBYTE) &dwPolicy, &cbSize)
  718. ||
  719. REG_DWORD != dwType)
  720. dwPolicy = 0;
  721. cbSize = sizeof(dwUrlRetrievalTimeout);
  722. if (ERROR_SUCCESS != RegQueryValueExA(
  723. hKeyPolicy, SzUrlRetrievalTimeoutData,
  724. 0, &dwType, (LPBYTE) &dwUrlRetrievalTimeout, &cbSize)
  725. ||
  726. REG_DWORD != dwType)
  727. dwUrlRetrievalTimeout = 0;
  728. RegCloseKey(hKeyPolicy);
  729. }
  730. }
  731. // Get current time to be used
  732. GetSystemTimeAsFileTime(&ftCurrent);
  733. hr = I_CheckExplicitTrust(
  734. pCertTrust->pccert,
  735. &ftCurrent,
  736. &bExplicitTrust
  737. );
  738. if (S_OK != hr)
  739. goto CheckExplicitTrustError;
  740. if (EXPLICIT_TRUST_NONE != bExplicitTrust) {
  741. // No need to build the chain, the trust decision has already been
  742. // made
  743. cTrustCert = 1;
  744. } else {
  745. DWORD i;
  746. hr = I_BuildChain(
  747. pCertTrust,
  748. &ftCurrent,
  749. dwPolicy,
  750. dwUrlRetrievalTimeout,
  751. &pChainContext
  752. );
  753. if (S_OK != hr)
  754. goto BuildChainError;
  755. cTrustCert = 0;
  756. for (i = 0; i < pChainContext->cChain; i++)
  757. cTrustCert += pChainContext->rgpChain[i]->cElement;
  758. if (0 == cTrustCert)
  759. goto InvalidChainContext;
  760. }
  761. // Allocate the memory to contain the errors for each cert in the chain
  762. rgdwErrors = (DWORD *) LocalAlloc(
  763. LMEM_FIXED | LMEM_ZEROINIT, cTrustCert * sizeof(DWORD));
  764. if (NULL == rgdwErrors)
  765. goto OutOfMemory;
  766. // If the caller requests the chain certs and/or the encoded trust
  767. // information, then, allocate the arrays
  768. if (pCertTrust->prgChain) {
  769. rgpTrustCert = (PCCERT_CONTEXT *) LocalAlloc(
  770. LMEM_FIXED | LMEM_ZEROINIT, cTrustCert * sizeof(PCCERT_CONTEXT));
  771. if (NULL == rgpTrustCert)
  772. goto OutOfMemory;
  773. }
  774. if (pCertTrust->prgpbTrustInfo) {
  775. rgBlobTrustInfo = (DATA_BLOB *) LocalAlloc(
  776. LMEM_FIXED | LMEM_ZEROINIT, cTrustCert * sizeof(DATA_BLOB));
  777. if (NULL == rgBlobTrustInfo)
  778. goto OutOfMemory;
  779. }
  780. if (EXPLICIT_TRUST_NONE != bExplicitTrust) {
  781. // We have a single cert without a chain
  782. if (rgpTrustCert)
  783. rgpTrustCert[0] =
  784. CertDuplicateCertificateContext(pCertTrust->pccert);
  785. if (rgBlobTrustInfo) {
  786. // Update the returned encoded trust info
  787. const DWORD cb = sizeof(rgbEncodedExplictTrust);
  788. BYTE *pb;
  789. pb = (BYTE *) LocalAlloc(LMEM_FIXED, cb);
  790. if (NULL == pb)
  791. goto OutOfMemory;
  792. memcpy(pb, rgbEncodedExplictTrust, cb);
  793. pb[cb-1] = bExplicitTrust;
  794. rgBlobTrustInfo[0].cbData = cb;
  795. rgBlobTrustInfo[0].pbData = pb;
  796. }
  797. if (EXPLICIT_TRUST_YES != bExplicitTrust) {
  798. LONG lValidity;
  799. dwAllErrors |= CERT_VALIDITY_EXPLICITLY_DISTRUSTED;
  800. lValidity = CertVerifyTimeValidity(&ftCurrent,
  801. pCertTrust->pccert->pCertInfo);
  802. if (0 > lValidity)
  803. dwAllErrors |= CERT_VALIDITY_BEFORE_START;
  804. else if (0 < lValidity)
  805. dwAllErrors |= CERT_VALIDITY_AFTER_END;
  806. }
  807. dwAllErrors &= ~pCertTrust->dwIgnoreErr;
  808. rgdwErrors[0] = dwAllErrors;
  809. if (WTD_STATEACTION_VERIFY == pProvData->pWintrustData->dwStateAction) {
  810. hr = I_UpdateCertProvFromExplicitTrust(
  811. pProvData,
  812. pCertTrust->pccert,
  813. dwAllErrors
  814. );
  815. if (S_OK != hr)
  816. goto UpdateCertProvFromExplicitTrustError;
  817. }
  818. } else {
  819. DWORD i;
  820. DWORD iTrustCert = 0;
  821. // Get the cert trust info from the chain context elements
  822. for (i = 0; i < pChainContext->cChain; i++) {
  823. DWORD j;
  824. PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[i];
  825. DWORD dwChainError = pChain->TrustStatus.dwErrorStatus;
  826. for (j = 0; j < pChain->cElement; j++) {
  827. PCERT_CHAIN_ELEMENT pEle = pChain->rgpElement[j];
  828. DWORD dwEleError = pEle->TrustStatus.dwErrorStatus;
  829. DWORD dwErrors = 0;
  830. if (iTrustCert >= cTrustCert)
  831. goto InvalidChainContext;
  832. if (0 != dwEleError) {
  833. if (dwEleError & CERT_TRUST_IS_NOT_TIME_VALID) {
  834. // Check if after or before
  835. if (0 > CertVerifyTimeValidity(&ftCurrent,
  836. pEle->pCertContext->pCertInfo))
  837. dwErrors |= CERT_VALIDITY_BEFORE_START;
  838. else
  839. dwErrors |= CERT_VALIDITY_AFTER_END;
  840. }
  841. if (dwEleError & CERT_TRUST_IS_NOT_SIGNATURE_VALID)
  842. dwErrors |= CERT_VALIDITY_SIGNATURE_FAILS;
  843. if (dwEleError & CERT_TRUST_IS_REVOKED) {
  844. dwErrors |= CERT_VALIDITY_CERTIFICATE_REVOKED;
  845. } else if (dwEleError & CERT_TRUST_IS_OFFLINE_REVOCATION)
  846. dwErrors |= CERT_VALIDITY_NO_CRL_FOUND;
  847. if (dwEleError & CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
  848. dwErrors |= CERT_VALIDITY_EXTENDED_USAGE_FAILURE;
  849. if (dwEleError &
  850. (CERT_TRUST_INVALID_POLICY_CONSTRAINTS |
  851. CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY))
  852. // We added POLICY_FAILURE on 02-13-01
  853. dwErrors |= CERT_VALIDITY_POLICY_FAILURE |
  854. CERT_VALIDITY_OTHER_EXTENSION_FAILURE;
  855. if (dwEleError & CERT_TRUST_INVALID_BASIC_CONSTRAINTS) {
  856. BOOL fEnableBasicConstraints = TRUE;
  857. if (dwPolicy & POLICY_IGNORE_NON_CRITICAL_BC) {
  858. // Disable if we don't have a critical extension
  859. PCERT_EXTENSION pExt;
  860. pExt = CertFindExtension(
  861. szOID_BASIC_CONSTRAINTS2,
  862. pEle->pCertContext->pCertInfo->cExtension,
  863. pEle->pCertContext->pCertInfo->rgExtension
  864. );
  865. if (NULL == pExt || !pExt->fCritical)
  866. fEnableBasicConstraints = FALSE;
  867. }
  868. if (fEnableBasicConstraints)
  869. // We added BASIC_CONSTRAINTS_FAILURE on 02-13-01
  870. dwErrors |=
  871. CERT_VALIDITY_BASIC_CONSTRAINTS_FAILURE |
  872. CERT_VALIDITY_OTHER_EXTENSION_FAILURE;
  873. }
  874. if (dwEleError & CERT_TRUST_INVALID_EXTENSION)
  875. dwErrors |= CERT_VALIDITY_OTHER_EXTENSION_FAILURE;
  876. if (dwEleError &
  877. (CERT_TRUST_INVALID_NAME_CONSTRAINTS |
  878. CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT |
  879. CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT |
  880. CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT |
  881. CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT))
  882. dwErrors |= CERT_VALIDITY_NAME_CONSTRAINTS_FAILURE |
  883. CERT_VALIDITY_OTHER_EXTENSION_FAILURE;
  884. }
  885. if (0 == j) {
  886. // End cert
  887. if (dwChainError & CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY)
  888. // We added POLICY_FAILURE on 02-13-01
  889. dwErrors |= CERT_VALIDITY_POLICY_FAILURE |
  890. CERT_VALIDITY_OTHER_EXTENSION_FAILURE;
  891. }
  892. if (iTrustCert == cTrustCert - 1) {
  893. // Top cert. Should be the root.
  894. if (dwChainError & (CERT_TRUST_IS_PARTIAL_CHAIN |
  895. CERT_TRUST_IS_CYCLIC))
  896. dwErrors |= CERT_VALIDITY_NO_ISSUER_CERT_FOUND |
  897. CERT_VALIDITY_NO_TRUST_DATA;
  898. else if (dwEleError & CERT_TRUST_IS_UNTRUSTED_ROOT)
  899. dwErrors |= CERT_VALIDITY_NO_TRUST_DATA;
  900. else if (NULL != rgBlobTrustInfo)
  901. rgBlobTrustInfo[iTrustCert].pbData = (BYTE *) 1;
  902. }
  903. dwErrors &= ~pCertTrust->dwIgnoreErr;
  904. dwAllErrors |= dwErrors;
  905. rgdwErrors[iTrustCert] = dwErrors;
  906. if (rgpTrustCert)
  907. rgpTrustCert[iTrustCert] =
  908. CertDuplicateCertificateContext(pEle->pCertContext);
  909. iTrustCert++;
  910. }
  911. // CTL chain errors
  912. if (dwChainError &
  913. (CERT_TRUST_CTL_IS_NOT_TIME_VALID |
  914. CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID |
  915. CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE)) {
  916. if (dwChainError & CERT_TRUST_CTL_IS_NOT_TIME_VALID)
  917. dwAllErrors |= CERT_VALIDITY_AFTER_END;
  918. if (dwChainError & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID)
  919. dwAllErrors |= CERT_VALIDITY_SIGNATURE_FAILS;
  920. if (dwChainError & CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE)
  921. dwAllErrors |= CERT_VALIDITY_EXTENDED_USAGE_FAILURE;
  922. dwAllErrors &= ~pCertTrust->dwIgnoreErr;
  923. }
  924. }
  925. if (dwAllErrors) {
  926. // If the issuer has errors, set an issuer error on the subject
  927. for (iTrustCert = cTrustCert - 1; iTrustCert > 0; iTrustCert--) {
  928. if (rgdwErrors[iTrustCert] & CERT_VALIDITY_MASK_VALIDITY)
  929. rgdwErrors[iTrustCert - 1] |= CERT_VALIDITY_ISSUER_INVALID;
  930. if (rgdwErrors[iTrustCert] & CERT_VALIDITY_MASK_TRUST)
  931. rgdwErrors[iTrustCert - 1] |= CERT_VALIDITY_ISSUER_DISTRUST;
  932. rgdwErrors[iTrustCert - 1] &= ~pCertTrust->dwIgnoreErr;
  933. dwAllErrors |= rgdwErrors[iTrustCert - 1];
  934. }
  935. }
  936. if (WTD_STATEACTION_VERIFY == pProvData->pWintrustData->dwStateAction) {
  937. hr = I_UpdateCertProvChain(
  938. pProvData,
  939. pChainContext,
  940. cTrustCert,
  941. rgdwErrors,
  942. dwAllErrors
  943. );
  944. if (S_OK != hr)
  945. goto UpdateCertProvChainError;
  946. }
  947. }
  948. pProvData->dwFinalError = I_MapValidityErrorsToTrustError(dwAllErrors);
  949. switch (pProvData->dwFinalError) {
  950. // For backwards compatibility, only the following HRESULTs are
  951. // returned.
  952. case S_OK:
  953. // case TRUST_E_CERT_SIGNATURE:
  954. // case CERT_E_REVOKED:
  955. // case CERT_E_REVOCATION_FAILURE:
  956. hr = pProvData->dwFinalError;
  957. break;
  958. default:
  959. hr = S_FALSE;
  960. }
  961. // Update the returned cert trust info
  962. if (NULL != pCertTrust->pdwErrors) {
  963. *pCertTrust->pdwErrors = dwAllErrors;
  964. }
  965. if (NULL != pCertTrust->pcChain) {
  966. *pCertTrust->pcChain = cTrustCert;
  967. }
  968. if (NULL != pCertTrust->prgChain) {
  969. *pCertTrust->prgChain = rgpTrustCert;
  970. rgpTrustCert = NULL;
  971. }
  972. if (NULL != pCertTrust->prgdwErrors) {
  973. *pCertTrust->prgdwErrors = rgdwErrors;
  974. rgdwErrors = NULL;
  975. }
  976. if (NULL != pCertTrust->prgpbTrustInfo) {
  977. *pCertTrust->prgpbTrustInfo = rgBlobTrustInfo;
  978. rgBlobTrustInfo = NULL;
  979. }
  980. CommonReturn:
  981. if (pChainContext)
  982. CertFreeCertificateChain(pChainContext);
  983. if (NULL != rgpTrustCert) {
  984. DWORD i;
  985. for (i = 0; i < cTrustCert; i++) {
  986. if (NULL != rgpTrustCert[i])
  987. CertFreeCertificateContext(rgpTrustCert[i]);
  988. }
  989. LocalFree(rgpTrustCert);
  990. }
  991. if (NULL != rgBlobTrustInfo) {
  992. DWORD i;
  993. for (i = 0; i < cTrustCert; i++) {
  994. if (0 < rgBlobTrustInfo[i].cbData)
  995. LocalFree(rgBlobTrustInfo[i].pbData);
  996. }
  997. LocalFree(rgBlobTrustInfo);
  998. }
  999. if (NULL != rgdwErrors)
  1000. LocalFree(rgdwErrors);
  1001. return hr;
  1002. CheckExplicitTrustError:
  1003. BuildChainError:
  1004. UpdateCertProvFromExplicitTrustError:
  1005. UpdateCertProvChainError:
  1006. ErrorReturn:
  1007. if (SUCCEEDED(hr))
  1008. hr = TRUST_E_SYSTEM_ERROR;
  1009. goto CommonReturn;
  1010. InvalidProvData:
  1011. hr = E_INVALIDARG;
  1012. goto ErrorReturn;
  1013. OutOfMemory:
  1014. hr = E_OUTOFMEMORY;
  1015. goto ErrorReturn;
  1016. InvalidChainContext:
  1017. hr = TRUST_E_SYSTEM_ERROR;
  1018. goto ErrorReturn;
  1019. }
  1020. HRESULT
  1021. CertTrustInit(
  1022. IN OUT PCRYPT_PROVIDER_DATA pProvData
  1023. )
  1024. {
  1025. // Verify we are called by a version of WVT having all of the fields we will
  1026. // be using.
  1027. if (!WVT_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, dwFinalError))
  1028. return E_INVALIDARG;
  1029. // We are going to do all of our stuff in the pfFinalPolicy
  1030. // callback. NULL all of the remaining provider callbacks to
  1031. // inhibit them from being called.
  1032. if (!WVT_ISINSTRUCT(CRYPT_PROVIDER_FUNCTIONS,
  1033. pProvData->psPfns->cbStruct, pfnCleanupPolicy))
  1034. return E_INVALIDARG;
  1035. pProvData->psPfns->pfnObjectTrust = NULL;
  1036. pProvData->psPfns->pfnSignatureTrust = NULL;
  1037. pProvData->psPfns->pfnCertificateTrust = NULL;
  1038. pProvData->psPfns->pfnFinalPolicy = CertTrustFinalPolicy;
  1039. pProvData->psPfns->pfnCertCheckPolicy = NULL;
  1040. pProvData->psPfns->pfnTestFinalPolicy = NULL;
  1041. pProvData->psPfns->pfnCleanupPolicy = NULL;
  1042. return S_OK;
  1043. }
  1044. // The following function should never be called.
  1045. BOOL
  1046. CertTrustCertPolicy(PCRYPT_PROVIDER_DATA, DWORD, BOOL, DWORD)
  1047. {
  1048. return FALSE;
  1049. }
  1050. // The following function should never be called.
  1051. HRESULT
  1052. CertTrustCleanup(PCRYPT_PROVIDER_DATA)
  1053. {
  1054. return TRUST_E_FAIL;
  1055. }
  1056. // In WXP this API was changed not to use CTLs. Instead, the "TrustedPeople" and
  1057. // "Disallowed" certificate stores are used.
  1058. HRESULT CertModifyCertificatesToTrust(int cCertsToModify, PCTL_MODIFY_REQUEST rgCertMods,
  1059. LPCSTR szPurpose, HWND hwnd, HCERTSTORE hcertstorTrust,
  1060. PCCERT_CONTEXT pccertSigner)
  1061. {
  1062. HRESULT hr = S_OK;
  1063. HCERTSTORE hStoreDisallowed = NULL;
  1064. HCERTSTORE hStoreTrustedPeople = NULL;
  1065. int i;
  1066. hStoreDisallowed = I_OpenDisallowedStore();
  1067. if (NULL == hStoreDisallowed)
  1068. goto OpenDisallowedStoreError;
  1069. hStoreTrustedPeople = I_OpenTrustedPeopleStore();
  1070. if (NULL == hStoreTrustedPeople)
  1071. goto OpenTrustedPeopleStoreError;
  1072. for (i = 0; i < cCertsToModify; i++) {
  1073. PCCERT_CONTEXT pCert = rgCertMods[i].pccert;
  1074. DWORD dwError = S_OK;
  1075. switch(rgCertMods[i].dwOperation) {
  1076. case CTL_MODIFY_REQUEST_ADD_NOT_TRUSTED:
  1077. if (0 > I_DeleteCertificateFromOtherStore(
  1078. hStoreTrustedPeople, pCert))
  1079. dwError = GetLastError();
  1080. if (!CertAddCertificateContextToStore(
  1081. hStoreDisallowed,
  1082. pCert,
  1083. CERT_STORE_ADD_USE_EXISTING,
  1084. NULL
  1085. ))
  1086. dwError = GetLastError();
  1087. break;
  1088. case CTL_MODIFY_REQUEST_REMOVE:
  1089. if (0 > I_DeleteCertificateFromOtherStore(
  1090. hStoreDisallowed, pCert))
  1091. dwError = GetLastError();
  1092. if (0 > I_DeleteCertificateFromOtherStore(
  1093. hStoreTrustedPeople, pCert))
  1094. dwError = GetLastError();
  1095. break;
  1096. case CTL_MODIFY_REQUEST_ADD_TRUSTED:
  1097. if (0 > I_DeleteCertificateFromOtherStore(
  1098. hStoreDisallowed, pCert))
  1099. dwError = GetLastError();
  1100. if (!CertAddCertificateContextToStore(
  1101. hStoreTrustedPeople,
  1102. pCert,
  1103. CERT_STORE_ADD_USE_EXISTING,
  1104. NULL
  1105. ))
  1106. dwError = GetLastError();
  1107. break;
  1108. default:
  1109. dwError = E_INVALIDARG;
  1110. }
  1111. dwError = HRESULT_FROM_WIN32(dwError);
  1112. rgCertMods[i].dwError = dwError;
  1113. if (FAILED(dwError))
  1114. hr = S_FALSE;
  1115. }
  1116. CommonReturn:
  1117. if (hStoreDisallowed)
  1118. CertCloseStore(hStoreDisallowed, 0);
  1119. if (hStoreTrustedPeople)
  1120. CertCloseStore(hStoreTrustedPeople, 0);
  1121. return hr;
  1122. OpenDisallowedStoreError:
  1123. OpenTrustedPeopleStoreError:
  1124. // Most likely unable to access
  1125. hr = E_ACCESSDENIED;
  1126. goto CommonReturn;
  1127. }
  1128. BOOL FModifyTrust(HWND hwnd, PCCERT_CONTEXT pccert, DWORD dwNewTrust,
  1129. LPSTR szPurpose)
  1130. {
  1131. HRESULT hr;
  1132. CTL_MODIFY_REQUEST certmod;
  1133. certmod.pccert = pccert;
  1134. certmod.dwOperation = dwNewTrust;
  1135. hr = CertModifyCertificatesToTrust(1, &certmod, szPurpose, hwnd, NULL, NULL);
  1136. return (hr == S_OK) && (certmod.dwError == 0);
  1137. }
  1138. void FreeWVTHandle(HANDLE hWVTState) {
  1139. if (hWVTState) {
  1140. HRESULT hr;
  1141. WINTRUST_DATA data = {0};
  1142. data.cbStruct = sizeof(WINTRUST_DATA);
  1143. data.pPolicyCallbackData = NULL;
  1144. data.pSIPClientData = NULL;
  1145. data.dwUIChoice = WTD_UI_NONE;
  1146. data.fdwRevocationChecks = WTD_REVOKE_NONE;
  1147. data.dwUnionChoice = WTD_CHOICE_BLOB;
  1148. data.pBlob = NULL; // &blob;
  1149. data.dwStateAction = WTD_STATEACTION_CLOSE;
  1150. data.hWVTStateData = hWVTState;
  1151. hr = WinVerifyTrust(NULL, (GUID *)&GuidCertValidate, &data);
  1152. }
  1153. }
  1154. HRESULT HrDoTrustWork(PCCERT_CONTEXT pccertToCheck, DWORD dwControl,
  1155. DWORD dwValidityMask,
  1156. DWORD /*cPurposes*/, LPSTR * rgszPurposes, HCRYPTPROV hprov,
  1157. DWORD cRoots, HCERTSTORE * rgRoots,
  1158. DWORD cCAs, HCERTSTORE * rgCAs,
  1159. DWORD cTrust, HCERTSTORE * rgTrust,
  1160. PFNTRUSTHELPER pfn, DWORD lCustData,
  1161. PCCertFrame * /*ppcf*/, DWORD * pcNodes,
  1162. PCCertFrame * rgpcfResult,
  1163. HANDLE * phReturnStateData) // optional: return WinVerifyTrust state handle here
  1164. {
  1165. DWORD cbData;
  1166. DWORD cCerts = 0;
  1167. WINTRUST_BLOB_INFO blob = {0};
  1168. WINTRUST_DATA data = {0};
  1169. DWORD dwErrors;
  1170. BOOL f;
  1171. HRESULT hr;
  1172. int i;
  1173. DWORD j;
  1174. PCCERT_CONTEXT * rgCerts = NULL;
  1175. DWORD * rgdwErrors = NULL;
  1176. DATA_BLOB * rgblobTrust = NULL;
  1177. CERT_VERIFY_CERTIFICATE_TRUST trust;
  1178. UNALIGNED CRYPT_ATTR_BLOB *pVal = NULL;
  1179. FILETIME ftCurrent;
  1180. data.cbStruct = sizeof(WINTRUST_DATA);
  1181. data.pPolicyCallbackData = NULL;
  1182. data.pSIPClientData = NULL;
  1183. data.dwUIChoice = WTD_UI_NONE;
  1184. data.fdwRevocationChecks = WTD_REVOKE_NONE;
  1185. data.dwUnionChoice = WTD_CHOICE_BLOB;
  1186. data.pBlob = &blob;
  1187. if (phReturnStateData) {
  1188. data.dwStateAction = WTD_STATEACTION_VERIFY;
  1189. }
  1190. blob.cbStruct = sizeof(WINTRUST_BLOB_INFO);
  1191. blob.pcwszDisplayName = NULL;
  1192. blob.cbMemObject = sizeof(trust);
  1193. blob.pbMemObject = (LPBYTE) &trust;
  1194. trust.cbSize = sizeof(trust);
  1195. trust.pccert = pccertToCheck;
  1196. trust.dwFlags = (CERT_TRUST_DO_FULL_SEARCH |
  1197. CERT_TRUST_PERMIT_MISSING_CRLS |
  1198. CERT_TRUST_DO_FULL_TRUST | dwControl);
  1199. trust.dwIgnoreErr = dwValidityMask;
  1200. trust.pdwErrors = &dwErrors;
  1201. // Assert(cPurposes == 1);
  1202. if (rgszPurposes != NULL) {
  1203. trust.pszUsageOid = rgszPurposes[0];
  1204. }
  1205. else {
  1206. trust.pszUsageOid = NULL;
  1207. }
  1208. trust.hprov = hprov;
  1209. trust.cRootStores = cRoots;
  1210. trust.rghstoreRoots = rgRoots;
  1211. trust.cStores = cCAs;
  1212. trust.rghstoreCAs = rgCAs;
  1213. trust.cTrustStores = cTrust;
  1214. trust.rghstoreTrust = rgTrust;
  1215. trust.lCustData = lCustData;
  1216. trust.pfnTrustHelper = pfn;
  1217. trust.pcChain = &cCerts;
  1218. trust.prgChain = &rgCerts;
  1219. trust.prgdwErrors = &rgdwErrors;
  1220. trust.prgpbTrustInfo = &rgblobTrust;
  1221. hr = WinVerifyTrust(NULL, (GUID *) &GuidCertValidate, &data);
  1222. if ((TRUST_E_CERT_SIGNATURE == hr) ||
  1223. (CERT_E_REVOKED == hr) ||
  1224. (CERT_E_REVOCATION_FAILURE == hr)) {
  1225. hr = S_OK;
  1226. }
  1227. else if (FAILED(hr)) {
  1228. return hr;
  1229. }
  1230. if (cCerts == 0) {
  1231. return(E_INVALIDARG);
  1232. }
  1233. if (phReturnStateData) {
  1234. *phReturnStateData = data.hWVTStateData; // Caller must use WinVerifyTrust to free
  1235. }
  1236. GetSystemTimeAsFileTime(&ftCurrent);
  1237. //Assert( cCerts <= 20);
  1238. *pcNodes = cCerts;
  1239. for (i=cCerts-1; i >= 0; i--) {
  1240. rgpcfResult[i] = new CCertFrame(rgCerts[i]);
  1241. if(!rgpcfResult[i])
  1242. {
  1243. hr=E_OUTOFMEMORY;
  1244. goto ExitHere;
  1245. }
  1246. rgpcfResult[i]->m_dwFlags = rgdwErrors[i];
  1247. if (rgszPurposes == NULL) {
  1248. continue;
  1249. }
  1250. rgpcfResult[i]->m_cTrust = 1;
  1251. rgpcfResult[i]->m_rgTrust = new STrustDesc[1];
  1252. memset(rgpcfResult[i]->m_rgTrust, 0, sizeof(STrustDesc));
  1253. if (0 == i)
  1254. rgpcfResult[i]->m_fLeaf = TRUE;
  1255. else
  1256. rgpcfResult[i]->m_fLeaf = FALSE;
  1257. if (0 == CertVerifyTimeValidity(&ftCurrent, rgCerts[i]->pCertInfo))
  1258. rgpcfResult[i]->m_fExpired = FALSE;
  1259. else
  1260. rgpcfResult[i]->m_fExpired = TRUE;
  1261. //
  1262. // We are going to fill in the trust information which we use
  1263. // to fill in the fields of the dialog box.
  1264. //
  1265. // Start with the question of the cert being self signed
  1266. //
  1267. rgpcfResult[i]->m_fSelfSign = WTHelperCertIsSelfSigned(X509_ASN_ENCODING, rgCerts[i]->pCertInfo);
  1268. //
  1269. // We may or may not have trust data information returned, we now
  1270. // build up the trust info for a single cert
  1271. //
  1272. // If we don't have any explicit data, then we just chain the data
  1273. // down from the next level up.
  1274. //
  1275. if (rgblobTrust[i].cbData == 0) {
  1276. // chain:
  1277. rgpcfResult[i]->m_rgTrust[0].fExplicitTrust = FALSE;
  1278. rgpcfResult[i]->m_rgTrust[0].fExplicitDistrust = FALSE;
  1279. //
  1280. // We return a special code to say that we found it in the root store
  1281. //
  1282. rgpcfResult[i]->m_rgTrust[0].fRootStore = rgpcfResult[i]->m_fRootStore =
  1283. (rgblobTrust[i].pbData == (LPBYTE) 1);
  1284. if (i != (int) (cCerts-1)) {
  1285. rgpcfResult[i]->m_rgTrust[0].fTrust = rgpcfResult[i+1]->m_rgTrust[0].fTrust;
  1286. rgpcfResult[i]->m_rgTrust[0].fDistrust= rgpcfResult[i+1]->m_rgTrust[0].fDistrust;
  1287. } else {
  1288. // Oops -- there is no level up one, so just make some
  1289. // good defaults
  1290. //
  1291. rgpcfResult[i]->m_rgTrust[0].fTrust = rgpcfResult[i]->m_fRootStore;
  1292. rgpcfResult[i]->m_rgTrust[0].fDistrust= FALSE;
  1293. }
  1294. }
  1295. else {
  1296. // Explicit trust is contained in the last byte
  1297. if (EXPLICIT_TRUST_YES ==
  1298. rgblobTrust[i].pbData[rgblobTrust[i].cbData - 1]) {
  1299. rgpcfResult[i]->m_rgTrust[0].fExplicitTrust = TRUE;
  1300. rgpcfResult[i]->m_rgTrust[0].fTrust = TRUE;
  1301. } else {
  1302. rgpcfResult[i]->m_rgTrust[0].fExplicitDistrust = TRUE;
  1303. rgpcfResult[i]->m_rgTrust[0].fDistrust= TRUE;
  1304. }
  1305. }
  1306. }
  1307. //
  1308. // Clean up all returned values
  1309. //
  1310. ExitHere:
  1311. if (rgCerts != NULL) {
  1312. //bobn If the loop has been broken because "new" failed, free what we allocated so far...
  1313. for ((hr==E_OUTOFMEMORY?i++:i=0); i< (int) cCerts; i++) {
  1314. CertFreeCertificateContext(rgCerts[i]);
  1315. }
  1316. LocalFree(rgCerts);
  1317. }
  1318. if (rgdwErrors != NULL) LocalFree(rgdwErrors);
  1319. if (rgblobTrust != NULL) {
  1320. for (i=0; i<(int) cCerts; i++) {
  1321. if (rgblobTrust[i].cbData > 0) {
  1322. LocalFree(rgblobTrust[i].pbData);
  1323. }
  1324. }
  1325. LocalFree(rgblobTrust);
  1326. }
  1327. return hr;
  1328. }
  1329. LPWSTR FormatValidityFailures(DWORD dwFlags)
  1330. {
  1331. DWORD cch = 0;
  1332. LPWSTR pwsz = NULL;
  1333. LPWSTR pwszT;
  1334. WCHAR rgwch[200];
  1335. if (dwFlags == 0) {
  1336. return NULL;
  1337. }
  1338. cch = 100;
  1339. pwsz = (LPWSTR) malloc(cch*sizeof(WCHAR));
  1340. if (pwsz == NULL) {
  1341. return NULL;
  1342. }
  1343. if (dwFlags & CERT_VALIDITY_BEFORE_START) {
  1344. LoadString(g_hCertTrustInst, IDS_WHY_NOT_YET, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1345. StrCpyNW(pwsz, rgwch, cch);
  1346. } else {
  1347. StrCpyNW(pwsz, L"",cch);
  1348. }
  1349. if (dwFlags & CERT_VALIDITY_AFTER_END) {
  1350. LoadString(g_hCertTrustInst, IDS_WHY_EXPIRED, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1351. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1352. cch += 200;
  1353. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1354. if (pwszT == NULL) {
  1355. free(pwsz);
  1356. return NULL;
  1357. }
  1358. pwsz = pwszT;
  1359. }
  1360. if (wcslen(pwsz) > 0)
  1361. StrCatBuffW(pwsz, wszCRLF, cch);
  1362. StrCatBuffW(pwsz, rgwch, cch);
  1363. }
  1364. if (dwFlags & CERT_VALIDITY_SIGNATURE_FAILS) {
  1365. LoadString(g_hCertTrustInst, IDS_WHY_CERT_SIG, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1366. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1367. cch += 200;
  1368. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1369. if (pwszT == NULL) {
  1370. free(pwsz);
  1371. return NULL;
  1372. }
  1373. pwsz = pwszT;
  1374. }
  1375. if (wcslen(pwsz) > 0)
  1376. StrCatBuffW(pwsz, wszCRLF, cch);
  1377. StrCatBuffW(pwsz, rgwch, cch);
  1378. }
  1379. if (dwFlags & CERT_VALIDITY_NO_ISSUER_CERT_FOUND) {
  1380. LoadString(g_hCertTrustInst, IDS_WHY_NO_PARENT, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1381. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1382. cch += 200;
  1383. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1384. if (pwszT == NULL) {
  1385. free(pwsz);
  1386. return NULL;
  1387. }
  1388. pwsz = pwszT;
  1389. }
  1390. if (wcslen(pwsz) > 0)
  1391. StrCatBuffW(pwsz, wszCRLF, cch);
  1392. StrCatBuffW(pwsz, rgwch, cch);
  1393. }
  1394. if (dwFlags & CERT_VALIDITY_NO_CRL_FOUND) {
  1395. LoadString(g_hCertTrustInst, IDS_WHY_NO_CRL, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1396. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1397. cch += 200;
  1398. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1399. if (pwszT == NULL) {
  1400. free(pwsz);
  1401. return NULL;
  1402. }
  1403. pwsz = pwszT;
  1404. }
  1405. if (wcslen(pwsz) > 0)
  1406. StrCatBuffW(pwsz, wszCRLF, cch);
  1407. StrCatBuffW(pwsz, rgwch, cch);
  1408. }
  1409. if (dwFlags & CERT_VALIDITY_CERTIFICATE_REVOKED) {
  1410. LoadString(g_hCertTrustInst, IDS_WHY_REVOKED, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1411. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1412. cch += 200;
  1413. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1414. if (pwszT == NULL) {
  1415. free(pwsz);
  1416. return NULL;
  1417. }
  1418. pwsz = pwszT;
  1419. }
  1420. if (wcslen(pwsz) > 0)
  1421. StrCatBuffW(pwsz, wszCRLF, cch);
  1422. StrCatBuffW(pwsz, rgwch, cch);
  1423. }
  1424. if (dwFlags & CERT_VALIDITY_CRL_OUT_OF_DATE) {
  1425. LoadString(g_hCertTrustInst, IDS_WHY_CRL_EXPIRED, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1426. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1427. cch += 200;
  1428. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1429. if (pwszT == NULL) {
  1430. free(pwsz);
  1431. return NULL;
  1432. }
  1433. pwsz = pwszT;
  1434. }
  1435. if (wcslen(pwsz) > 0)
  1436. StrCatBuffW(pwsz, wszCRLF, cch);
  1437. StrCatBuffW(pwsz, rgwch, cch);
  1438. }
  1439. if (dwFlags & CERT_VALIDITY_EXTENDED_USAGE_FAILURE) {
  1440. LoadString(g_hCertTrustInst, IDS_WHY_EXTEND_USE, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1441. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1442. cch += 200;
  1443. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1444. if (pwszT == NULL) {
  1445. free(pwsz);
  1446. return NULL;
  1447. }
  1448. pwsz = pwszT;
  1449. }
  1450. if (wcslen(pwsz) > 0)
  1451. StrCatBuffW(pwsz, wszCRLF, cch);
  1452. StrCatBuffW(pwsz, rgwch, cch);
  1453. }
  1454. if (dwFlags & CERT_VALIDITY_NAME_CONSTRAINTS_FAILURE) {
  1455. LoadString(g_hCertTrustInst, IDS_WHY_NAME_CONST, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1456. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1457. cch += 200;
  1458. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1459. if (pwszT == NULL) {
  1460. free(pwsz);
  1461. return NULL;
  1462. }
  1463. pwsz = pwszT;
  1464. }
  1465. if (wcslen(pwsz) > 0)
  1466. StrCatBuffW(pwsz, wszCRLF, cch);
  1467. StrCatBuffW(pwsz, rgwch, cch);
  1468. }
  1469. if (dwFlags & CERT_VALIDITY_POLICY_FAILURE) {
  1470. LoadString(g_hCertTrustInst, IDS_WHY_POLICY, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1471. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1472. cch += 200;
  1473. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1474. if (pwszT == NULL) {
  1475. free(pwsz);
  1476. return NULL;
  1477. }
  1478. pwsz = pwszT;
  1479. }
  1480. if (wcslen(pwsz) > 0)
  1481. StrCatBuffW(pwsz, wszCRLF, cch);
  1482. StrCatBuffW(pwsz, rgwch, cch);
  1483. }
  1484. if (dwFlags & CERT_VALIDITY_BASIC_CONSTRAINTS_FAILURE) {
  1485. LoadString(g_hCertTrustInst, IDS_WHY_BASIC_CONS, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1486. if (wcslen(pwsz) + wcslen(rgwch) + 2 > cch) {
  1487. cch += 200;
  1488. pwszT = (LPWSTR) realloc(pwsz, cch*sizeof(WCHAR));
  1489. if (pwszT == NULL) {
  1490. free(pwsz);
  1491. return NULL;
  1492. }
  1493. pwsz = pwszT;
  1494. }
  1495. if (wcslen(pwsz) > 0)
  1496. StrCatBuffW(pwsz, wszCRLF, cch);
  1497. StrCatBuffW(pwsz, rgwch, cch);
  1498. }
  1499. return pwsz;
  1500. }