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.

663 lines
20 KiB

  1. //+-------------------------------------------------------------------------
  2. // Microsoft Windows
  3. //
  4. // Copyright (C) Microsoft Corporation, 2001 - 2001
  5. //
  6. // File: vercat.cpp
  7. //
  8. // Contents: Minimal Cryptographic functions to verify hashes in the
  9. // system catalogs.
  10. //
  11. // Functions: MinCryptVerifyHashInSystemCatalogs
  12. //
  13. // History: 23-Jan-01 philh created
  14. //--------------------------------------------------------------------------
  15. #include "global.hxx"
  16. #include <softpub.h>
  17. #include <mscat.h>
  18. // #define szOID_CTL "1.3.6.1.4.1.311.10.1"
  19. const BYTE rgbOID_CTL[] =
  20. {0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0A, 0x01};
  21. // #define SPC_INDIRECT_DATA_OBJID "1.3.6.1.4.1.311.2.1.4"
  22. static const BYTE rgbSPC_INDIRECT_DATA_OBJID[] =
  23. {0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04};
  24. const CRYPT_DER_BLOB IndirectDataEncodedOIDBlob = {
  25. sizeof(rgbSPC_INDIRECT_DATA_OBJID),
  26. (BYTE *) rgbSPC_INDIRECT_DATA_OBJID
  27. };
  28. #define MAX_CAT_FILE_CNT 10
  29. #define MAX_CAT_ATTR_CNT 10
  30. #define MAX_CAT_EXT_CNT 10
  31. typedef struct _MAP_CAT_INFO {
  32. LONG lErr;
  33. CRYPT_DATA_BLOB FileBlob;
  34. CRYPT_DER_BLOB CTLSubjectsValueBlob;
  35. CRYPT_DER_BLOB CTLExtsValueBlob;
  36. CRYPT_DER_BLOB SignerAuthAttrsValueBlob;
  37. } MAP_CAT_INFO, *PMAP_CAT_INFO;
  38. #define MAP_CAT_IDX_MASK 0x0000FFFF
  39. #define MAP_CAT_MULTIPLE_FLAG 0x00010000
  40. LONG
  41. WINAPI
  42. I_GetAndMapSystemCatalogs(
  43. IN ALG_ID HashAlgId,
  44. IN DWORD cHash,
  45. IN CRYPT_HASH_BLOB rgHashBlob[],
  46. OUT LONG rglHashMapCatIdx[],
  47. OUT DWORD *pcMapCatInfo,
  48. OUT MAP_CAT_INFO rgMapCatInfo[MAX_CAT_FILE_CNT]
  49. )
  50. {
  51. LONG lErr;
  52. HCATADMIN hCatAdmin = NULL;
  53. const GUID guidCatRoot = DRIVER_ACTION_VERIFY;
  54. DWORD cMapCatInfo = 0;
  55. DWORD cCatInfo = 0;
  56. CATALOG_INFO rgCatInfo[MAX_CAT_FILE_CNT];
  57. LONG rglMapCatIdx[MAX_CAT_FILE_CNT];
  58. DWORD iHash;
  59. if (!(CryptCATAdminAcquireContext(&hCatAdmin, &guidCatRoot, 0)))
  60. goto CryptCATAdminAcquireContextError;
  61. for (iHash = 0; iHash < cHash; iHash++) {
  62. HCATINFO hCatInfo = NULL;
  63. // Set index to indicate no catalog file
  64. rglHashMapCatIdx[iHash] = -1;
  65. while (hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin,
  66. rgHashBlob[iHash].pbData, rgHashBlob[iHash].cbData,
  67. 0, &hCatInfo)) {
  68. CATALOG_INFO CatInfo;
  69. LONG lMapCatIdx;
  70. DWORD iCatInfo;
  71. memset(&CatInfo, 0, sizeof(CATALOG_INFO));
  72. CatInfo.cbStruct = sizeof(CATALOG_INFO);
  73. if (!(CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0)))
  74. continue;
  75. // Ensure we have a NULL terminated string
  76. CatInfo.wszCatalogFile[
  77. sizeof(CatInfo.wszCatalogFile)/sizeof(WCHAR) - 1] = L'\0';
  78. // Check if we already encountered this catalog file
  79. for (iCatInfo = 0; iCatInfo < cCatInfo; iCatInfo++) {
  80. if (0 == _wcsicmp(CatInfo.wszCatalogFile,
  81. rgCatInfo[iCatInfo].wszCatalogFile))
  82. break;
  83. }
  84. if (iCatInfo >= cCatInfo) {
  85. // Attempt to map this new catalog file
  86. if (cCatInfo >= MAX_CAT_FILE_CNT)
  87. continue;
  88. wcscpy(rgCatInfo[cCatInfo].wszCatalogFile,
  89. CatInfo.wszCatalogFile);
  90. memset(&rgMapCatInfo[cMapCatInfo], 0, sizeof(MAP_CAT_INFO));
  91. if (ERROR_SUCCESS == I_MinCryptMapFile(
  92. MINCRYPT_FILE_NAME,
  93. (const VOID *) CatInfo.wszCatalogFile,
  94. &rgMapCatInfo[cMapCatInfo].FileBlob
  95. ))
  96. rglMapCatIdx[cCatInfo] = cMapCatInfo++;
  97. else
  98. rglMapCatIdx[cCatInfo] = -1;
  99. cCatInfo++;
  100. assert(iCatInfo < cCatInfo);
  101. }
  102. lMapCatIdx = rglMapCatIdx[iCatInfo];
  103. if (0 > rglHashMapCatIdx[iHash])
  104. rglHashMapCatIdx[iHash] = lMapCatIdx;
  105. else if (0 <= lMapCatIdx)
  106. rglHashMapCatIdx[iHash] |= MAP_CAT_MULTIPLE_FLAG;
  107. }
  108. }
  109. lErr = ERROR_SUCCESS;
  110. CommonReturn:
  111. *pcMapCatInfo = cMapCatInfo;
  112. if (hCatAdmin)
  113. CryptCATAdminReleaseContext(hCatAdmin, 0);
  114. return lErr;
  115. CryptCATAdminAcquireContextError:
  116. lErr = GetLastError();
  117. if (ERROR_SUCCESS == lErr)
  118. lErr = E_UNEXPECTED;
  119. goto CommonReturn;
  120. }
  121. VOID
  122. WINAPI
  123. I_VerifyMappedCatalog(
  124. IN OUT PMAP_CAT_INFO pMapCatInfo
  125. )
  126. {
  127. LONG lErr;
  128. CRYPT_DER_BLOB rgVerSignedDataBlob[MINCRYPT_VER_SIGNED_DATA_BLOB_CNT];
  129. CRYPT_DER_BLOB rgCTLBlob[MINASN1_CTL_BLOB_CNT];
  130. __try {
  131. lErr = MinCryptVerifySignedData(
  132. pMapCatInfo->FileBlob.pbData,
  133. pMapCatInfo->FileBlob.cbData,
  134. rgVerSignedDataBlob
  135. );
  136. if (ERROR_SUCCESS != lErr)
  137. goto ErrorReturn;
  138. // The data content should be a CTL
  139. if (sizeof(rgbOID_CTL) !=
  140. rgVerSignedDataBlob[
  141. MINCRYPT_VER_SIGNED_DATA_CONTENT_OID_IDX].cbData
  142. ||
  143. 0 != memcmp(rgbOID_CTL,
  144. rgVerSignedDataBlob[
  145. MINCRYPT_VER_SIGNED_DATA_CONTENT_OID_IDX].pbData,
  146. sizeof(rgbOID_CTL)))
  147. goto NotCTLOID;
  148. if (0 >= MinAsn1ParseCTL(
  149. &rgVerSignedDataBlob[MINCRYPT_VER_SIGNED_DATA_CONTENT_DATA_IDX],
  150. rgCTLBlob
  151. ))
  152. goto ParseCTLError;
  153. pMapCatInfo->CTLSubjectsValueBlob =
  154. rgCTLBlob[MINASN1_CTL_SUBJECTS_IDX];
  155. pMapCatInfo->CTLExtsValueBlob =
  156. rgCTLBlob[MINASN1_CTL_EXTS_IDX];
  157. pMapCatInfo->SignerAuthAttrsValueBlob =
  158. rgVerSignedDataBlob[MINCRYPT_VER_SIGNED_DATA_AUTH_ATTRS_IDX];
  159. } __except(EXCEPTION_EXECUTE_HANDLER) {
  160. lErr = GetExceptionCode();
  161. if (ERROR_SUCCESS == lErr)
  162. lErr = E_UNEXPECTED;
  163. goto ErrorReturn;
  164. }
  165. lErr = ERROR_SUCCESS;
  166. CommonReturn:
  167. pMapCatInfo->lErr = lErr;
  168. return;
  169. ErrorReturn:
  170. goto CommonReturn;
  171. NotCTLOID:
  172. ParseCTLError:
  173. lErr = CRYPT_E_BAD_MSG;
  174. goto ErrorReturn;
  175. }
  176. VOID
  177. WINAPI
  178. I_VerifyMappedSystemCatalogs(
  179. IN DWORD cMapCatInfo,
  180. IN OUT MAP_CAT_INFO rgMapCatInfo[MAX_CAT_FILE_CNT]
  181. )
  182. {
  183. DWORD i;
  184. for (i = 0; i < cMapCatInfo; i++)
  185. I_VerifyMappedCatalog(&rgMapCatInfo[i]);
  186. }
  187. LONG
  188. WINAPI
  189. I_FindHashInCTLSubjects(
  190. IN ALG_ID HashAlgId,
  191. IN PCRYPT_HASH_BLOB pHashBlob,
  192. IN PCRYPT_DER_BLOB pCTLSubjectsValueBlob,
  193. OUT PCRYPT_DER_BLOB pCTLSubjectAttrsValueBlob
  194. )
  195. {
  196. DWORD cbEncoded;
  197. const BYTE *pbEncoded;
  198. // Advance past the outer tag and length
  199. if (0 >= MinAsn1ExtractContent(
  200. pCTLSubjectsValueBlob->pbData,
  201. pCTLSubjectsValueBlob->cbData,
  202. &cbEncoded,
  203. &pbEncoded
  204. ))
  205. goto NoOrInvalidSubjects;
  206. while (cbEncoded) {
  207. // Loop through the encoded subjects until we have a hash match
  208. // with the digest octets in the IndirectData attribute.
  209. LONG cbSubject;
  210. CRYPT_DER_BLOB rgCTLSubjectBlob[MINASN1_CTL_SUBJECT_BLOB_CNT];
  211. DWORD cAttr;
  212. CRYPT_DER_BLOB rgrgAttrBlob[MAX_CAT_ATTR_CNT][MINASN1_ATTR_BLOB_CNT];
  213. cbSubject = MinAsn1ParseCTLSubject(
  214. pbEncoded,
  215. cbEncoded,
  216. rgCTLSubjectBlob
  217. );
  218. if (0 >= cbSubject)
  219. goto InvalidSubject;
  220. cAttr = MAX_CAT_ATTR_CNT;
  221. if (0 < MinAsn1ParseAttributes(
  222. &rgCTLSubjectBlob[MINASN1_CTL_SUBJECT_ATTRS_IDX],
  223. &cAttr,
  224. rgrgAttrBlob
  225. )) {
  226. PCRYPT_DER_BLOB rgIndirectDataAttrBlob;
  227. CRYPT_DER_BLOB rgIndirectDataBlob[MINASN1_INDIRECT_DATA_BLOB_CNT];
  228. rgIndirectDataAttrBlob = MinAsn1FindAttribute(
  229. (PCRYPT_DER_BLOB) &IndirectDataEncodedOIDBlob,
  230. cAttr,
  231. rgrgAttrBlob
  232. );
  233. if (rgIndirectDataAttrBlob &&
  234. 0 < MinAsn1ParseIndirectData(
  235. &rgIndirectDataAttrBlob[MINASN1_ATTR_VALUE_IDX],
  236. rgIndirectDataBlob)) {
  237. if (pHashBlob->cbData ==
  238. rgIndirectDataBlob[
  239. MINASN1_INDIRECT_DATA_DIGEST_IDX].cbData
  240. &&
  241. 0 == memcmp(pHashBlob->pbData,
  242. rgIndirectDataBlob[
  243. MINASN1_INDIRECT_DATA_DIGEST_IDX].pbData,
  244. pHashBlob->cbData)) {
  245. *pCTLSubjectAttrsValueBlob =
  246. rgCTLSubjectBlob[MINASN1_CTL_SUBJECT_ATTRS_IDX];
  247. return ERROR_SUCCESS;
  248. }
  249. }
  250. }
  251. pbEncoded += cbSubject;
  252. cbEncoded -= cbSubject;
  253. }
  254. NoOrInvalidSubjects:
  255. InvalidSubject:
  256. pCTLSubjectAttrsValueBlob->pbData = NULL;
  257. pCTLSubjectAttrsValueBlob->cbData = 0;
  258. return ERROR_FILE_NOT_FOUND;
  259. }
  260. LONG
  261. WINAPI
  262. I_FindHashInMappedSystemCatalogs(
  263. IN ALG_ID HashAlgId,
  264. IN PCRYPT_HASH_BLOB pHashBlob,
  265. IN DWORD cMapCatInfo,
  266. IN MAP_CAT_INFO rgMapCatInfo[MAX_CAT_FILE_CNT],
  267. IN OUT LONG *plMapCatIdx,
  268. OUT PCRYPT_DER_BLOB pCTLSubjectAttrsValueBlob
  269. )
  270. {
  271. LONG lErr;
  272. LONG lMapCatIdx = *plMapCatIdx;
  273. BOOL fMultiple = FALSE;
  274. if (0 > lMapCatIdx)
  275. goto NotInCatalog;
  276. if (lMapCatIdx & MAP_CAT_MULTIPLE_FLAG)
  277. fMultiple = TRUE;
  278. else
  279. fMultiple = FALSE;
  280. lMapCatIdx &= MAP_CAT_IDX_MASK;
  281. assert((DWORD) lMapCatIdx < cMapCatInfo);
  282. if (ERROR_SUCCESS == rgMapCatInfo[lMapCatIdx].lErr
  283. &&
  284. ERROR_SUCCESS == I_FindHashInCTLSubjects(
  285. HashAlgId,
  286. pHashBlob,
  287. &rgMapCatInfo[lMapCatIdx].CTLSubjectsValueBlob,
  288. pCTLSubjectAttrsValueBlob
  289. ))
  290. goto SuccessReturn;
  291. if (fMultiple) {
  292. DWORD i;
  293. for (i = 0; i < cMapCatInfo; i++) {
  294. if ((DWORD) lMapCatIdx == i)
  295. continue;
  296. if (ERROR_SUCCESS == rgMapCatInfo[i].lErr
  297. &&
  298. ERROR_SUCCESS == I_FindHashInCTLSubjects(
  299. HashAlgId,
  300. pHashBlob,
  301. &rgMapCatInfo[i].CTLSubjectsValueBlob,
  302. pCTLSubjectAttrsValueBlob
  303. )) {
  304. lMapCatIdx = i;
  305. goto SuccessReturn;
  306. }
  307. }
  308. }
  309. NotInCatalog:
  310. lErr = ERROR_FILE_NOT_FOUND;
  311. lMapCatIdx = -1;
  312. pCTLSubjectAttrsValueBlob->pbData = NULL;
  313. pCTLSubjectAttrsValueBlob->cbData = 0;
  314. goto CommonReturn;
  315. SuccessReturn:
  316. lErr = ERROR_SUCCESS;
  317. CommonReturn:
  318. *plMapCatIdx = lMapCatIdx;
  319. return lErr;
  320. }
  321. VOID
  322. WINAPI
  323. I_GetHashAttributes(
  324. IN OPTIONAL DWORD cAttrOID,
  325. IN OPTIONAL CRYPT_DER_BLOB rgAttrEncodedOIDBlob[],
  326. IN PCRYPT_DER_BLOB pCTLSubjectAttrsValueBlob,
  327. IN PCRYPT_DER_BLOB pCTLExtsValueBlob,
  328. IN PCRYPT_DER_BLOB pSignerAuthAttrsValueBlob,
  329. IN OUT OPTIONAL CRYPT_DER_BLOB rgAttrValueBlob[],
  330. IN OUT LONG *plRemainExtra,
  331. IN OUT BYTE **ppbExtra
  332. )
  333. {
  334. DWORD cSubjectAttr;
  335. CRYPT_DER_BLOB rgrgSubjectAttrBlob[MAX_CAT_ATTR_CNT][MINASN1_ATTR_BLOB_CNT];
  336. DWORD cExt;
  337. CRYPT_DER_BLOB rgrgExtBlob[MAX_CAT_EXT_CNT][MINASN1_EXT_BLOB_CNT];
  338. DWORD cSignerAttr;
  339. CRYPT_DER_BLOB rgrgSignerAttrBlob[MAX_CAT_ATTR_CNT][MINASN1_ATTR_BLOB_CNT];
  340. DWORD i;
  341. LONG lRemainExtra = *plRemainExtra;
  342. BYTE *pbExtra = *ppbExtra;
  343. // Parse the attributes and extensions
  344. cSubjectAttr = MAX_CAT_ATTR_CNT;
  345. if (0 >= MinAsn1ParseAttributes(
  346. pCTLSubjectAttrsValueBlob,
  347. &cSubjectAttr,
  348. rgrgSubjectAttrBlob))
  349. cSubjectAttr = 0;
  350. cExt = MAX_CAT_EXT_CNT;
  351. if (0 >= MinAsn1ParseExtensions(
  352. pCTLExtsValueBlob,
  353. &cExt,
  354. rgrgExtBlob))
  355. cExt = 0;
  356. cSignerAttr = MAX_CAT_ATTR_CNT;
  357. if (0 >= MinAsn1ParseAttributes(
  358. pSignerAuthAttrsValueBlob,
  359. &cSignerAttr,
  360. rgrgSignerAttrBlob))
  361. cSignerAttr = 0;
  362. for (i = 0; i < cAttrOID; i++) {
  363. PCRYPT_DER_BLOB rgFindAttrBlob;
  364. PCRYPT_DER_BLOB rgFindExtBlob;
  365. PCRYPT_DER_BLOB pFindAttrValue;
  366. if (rgFindAttrBlob = MinAsn1FindAttribute(
  367. &rgAttrEncodedOIDBlob[i],
  368. cSubjectAttr,
  369. rgrgSubjectAttrBlob
  370. ))
  371. pFindAttrValue = &rgFindAttrBlob[MINASN1_ATTR_VALUE_IDX];
  372. else if (rgFindExtBlob = MinAsn1FindExtension(
  373. &rgAttrEncodedOIDBlob[i],
  374. cExt,
  375. rgrgExtBlob
  376. ))
  377. pFindAttrValue = &rgFindExtBlob[MINASN1_EXT_VALUE_IDX];
  378. else if (rgFindAttrBlob = MinAsn1FindAttribute(
  379. &rgAttrEncodedOIDBlob[i],
  380. cSignerAttr,
  381. rgrgSignerAttrBlob
  382. ))
  383. pFindAttrValue = &rgFindAttrBlob[MINASN1_ATTR_VALUE_IDX];
  384. else
  385. pFindAttrValue = NULL;
  386. if (pFindAttrValue && 0 != pFindAttrValue->cbData) {
  387. const BYTE *pbFindValue = pFindAttrValue->pbData;
  388. DWORD cbFindValue = pFindAttrValue->cbData;
  389. lRemainExtra -= cbFindValue;
  390. if (0 <= lRemainExtra) {
  391. rgAttrValueBlob[i].pbData = pbExtra;
  392. rgAttrValueBlob[i].cbData = cbFindValue;
  393. memcpy(pbExtra, pbFindValue, cbFindValue);
  394. pbExtra += cbFindValue;
  395. }
  396. }
  397. }
  398. *plRemainExtra = lRemainExtra;
  399. *ppbExtra = pbExtra;
  400. }
  401. //+-------------------------------------------------------------------------
  402. // Verifies the hashes in the system catalogs.
  403. //
  404. // Iterates through the hashes and attempts to find the system catalog
  405. // containing it. If found, the system catalog file is verified as a
  406. // PKCS #7 Signed Data message with its signer cert verified up to a baked
  407. // in root.
  408. //
  409. // The following mscat32.dll APIs are called to find the system catalog file:
  410. // CryptCATAdminAcquireContext
  411. // CryptCATAdminReleaseContext
  412. // CryptCATAdminEnumCatalogFromHash
  413. // CryptCATAdminReleaseCatalogContext
  414. // CryptCATCatalogInfoFromContext
  415. //
  416. // If the hash was successfully verified, rglErr[] is set to ERROR_SUCCESS.
  417. // Otherwise, rglErr[] is set to a nonzero error code.
  418. //
  419. // The caller can request one or more catalog subject attribute,
  420. // extension or signer authenticated attribute values to be returned for
  421. // each hash. The still encoded values are returned in the
  422. // caller allocated memory. The beginning of this returned memory will
  423. // be set to a 2 dimensional array of attribute value blobs pointing to these
  424. // encoded values (CRYPT_DER_BLOB rgrgAttrValueBlob[cHash][cAttrOID]).
  425. // The caller should make every attempt to allow for a
  426. // single pass call. The necessary memory size is:
  427. // (cHash * cAttrOID * sizeof(CRYPT_DER_BLOB)) +
  428. // total length of encoded attribute values.
  429. //
  430. // *pcbAttr will be updated with the number of bytes required to contain
  431. // the attribute blobs and values. If the input memory is insufficient,
  432. // ERROR_INSUFFICIENT_BUFFER will be returned if no other error.
  433. //
  434. // For a multi-valued attribute, only the first value is returned.
  435. //
  436. // If the function succeeds, the return value is ERROR_SUCCESS. This may
  437. // be returned for unsuccessful rglErr[] values. Otherwise,
  438. // a nonzero error code is returned.
  439. //--------------------------------------------------------------------------
  440. LONG
  441. WINAPI
  442. MinCryptVerifyHashInSystemCatalogs(
  443. IN ALG_ID HashAlgId,
  444. IN DWORD cHash,
  445. IN CRYPT_HASH_BLOB rgHashBlob[],
  446. OUT LONG rglErr[],
  447. IN OPTIONAL DWORD cAttrOID,
  448. IN OPTIONAL CRYPT_DER_BLOB rgAttrEncodedOIDBlob[],
  449. // CRYPT_DER_BLOB rgrgAttrValueBlob[cHash][cAttrOID] header is at beginning
  450. // with the bytes pointed to immediately following
  451. OUT OPTIONAL CRYPT_DER_BLOB *rgrgAttrValueBlob,
  452. IN OUT OPTIONAL DWORD *pcbAttr
  453. )
  454. {
  455. LONG lErr;
  456. DWORD cMapCatInfo = 0;
  457. MAP_CAT_INFO rgMapCatInfo[MAX_CAT_FILE_CNT];
  458. DWORD iMapCat;
  459. //**********************************************************************
  460. // WARNING!!!!
  461. //
  462. // The following function calls into other DLLs such as, kernel32.dll
  463. // and wintrust.dll to find and map the system catalog files. The input
  464. // array of hashes must be protected!!
  465. //
  466. // After returning we won't be calling into other DLLs until
  467. // UnmapViewOfFile is called in CommonReturn.
  468. //
  469. //**********************************************************************
  470. // Note, rglErr[] is overloaded and also used to contain the indices
  471. // into rgMapCatInfo for each corresponding hash.
  472. lErr = I_GetAndMapSystemCatalogs(
  473. HashAlgId,
  474. cHash,
  475. rgHashBlob,
  476. rglErr,
  477. &cMapCatInfo,
  478. rgMapCatInfo
  479. );
  480. if (ERROR_SUCCESS != lErr)
  481. goto ErrorReturn;
  482. __try {
  483. DWORD cbAttr = 0;
  484. LONG lRemainExtra = 0;
  485. BYTE *pbExtra = NULL;
  486. DWORD iHash;
  487. if (0 != cAttrOID && 0 != cHash) {
  488. if (rgrgAttrValueBlob)
  489. cbAttr = *pcbAttr;
  490. lRemainExtra = cbAttr - sizeof(CRYPT_DER_BLOB) * cAttrOID * cHash;
  491. if (0 <= lRemainExtra) {
  492. memset(rgrgAttrValueBlob, 0,
  493. sizeof(CRYPT_DER_BLOB) * cAttrOID * cHash);
  494. pbExtra = (BYTE *) &rgrgAttrValueBlob[cAttrOID * cHash];
  495. }
  496. }
  497. I_VerifyMappedSystemCatalogs(
  498. cMapCatInfo,
  499. rgMapCatInfo
  500. );
  501. for (iHash = 0; iHash < cHash; iHash++) {
  502. LONG lMapCatIdx = rglErr[iHash];
  503. CRYPT_DER_BLOB CTLSubjectAttrsValueBlob;
  504. rglErr[iHash] = I_FindHashInMappedSystemCatalogs(
  505. HashAlgId,
  506. &rgHashBlob[iHash],
  507. cMapCatInfo,
  508. rgMapCatInfo,
  509. &lMapCatIdx,
  510. &CTLSubjectAttrsValueBlob
  511. );
  512. if (0 != cAttrOID && ERROR_SUCCESS == rglErr[iHash]) {
  513. assert(0 <= lMapCatIdx && (DWORD) lMapCatIdx < cMapCatInfo);
  514. I_GetHashAttributes(
  515. cAttrOID,
  516. rgAttrEncodedOIDBlob,
  517. &CTLSubjectAttrsValueBlob,
  518. &rgMapCatInfo[lMapCatIdx].CTLExtsValueBlob,
  519. &rgMapCatInfo[lMapCatIdx].SignerAuthAttrsValueBlob,
  520. 0 <= lRemainExtra ?
  521. &rgrgAttrValueBlob[cAttrOID * iHash] : NULL,
  522. &lRemainExtra,
  523. &pbExtra
  524. );
  525. }
  526. }
  527. if (0 != cAttrOID && 0 != cHash) {
  528. if (0 <= lRemainExtra)
  529. *pcbAttr = cbAttr - (DWORD) lRemainExtra;
  530. else {
  531. *pcbAttr = cbAttr + (DWORD) -lRemainExtra;
  532. goto InsufficientBuffer;
  533. }
  534. }
  535. } __except(EXCEPTION_EXECUTE_HANDLER) {
  536. lErr = GetExceptionCode();
  537. if (ERROR_SUCCESS == lErr)
  538. lErr = E_UNEXPECTED;
  539. goto ErrorReturn;
  540. }
  541. lErr = ERROR_SUCCESS;
  542. CommonReturn:
  543. //**********************************************************************
  544. // WARNING!!!!
  545. //
  546. // UnmapViewOfFile is in another DLL, kernel32.dll.
  547. // lErr and the return error for each hash in rglErr[] must be protected.
  548. //
  549. //**********************************************************************
  550. for (iMapCat = 0; iMapCat < cMapCatInfo; iMapCat++)
  551. UnmapViewOfFile(rgMapCatInfo[iMapCat].FileBlob.pbData);
  552. return lErr;
  553. ErrorReturn:
  554. assert(ERROR_SUCCESS != lErr);
  555. if (ERROR_INSUFFICIENT_BUFFER == lErr)
  556. // This error can only be set when we determine that the attribute
  557. // buffer isn't big enough.
  558. lErr = E_UNEXPECTED;
  559. goto CommonReturn;
  560. InsufficientBuffer:
  561. lErr = ERROR_INSUFFICIENT_BUFFER;
  562. // Don't goto ErrorReturn. It explicitly checks that noone else can
  563. // set this error
  564. goto CommonReturn;
  565. }