Tcg2Pei.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. /** @file
  2. Initialize TPM2 device and measure FVs before handing off control to DXE.
  3. Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
  4. Copyright (c) 2017, Microsoft Corporation. All rights reserved. <BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <PiPei.h>
  8. #include <IndustryStandard/UefiTcgPlatform.h>
  9. #include <Ppi/FirmwareVolumeInfo.h>
  10. #include <Ppi/FirmwareVolumeInfo2.h>
  11. #include <Ppi/TpmInitialized.h>
  12. #include <Ppi/FirmwareVolume.h>
  13. #include <Ppi/EndOfPeiPhase.h>
  14. #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
  15. #include <Ppi/FirmwareVolumeInfoPrehashedFV.h>
  16. #include <Guid/TcgEventHob.h>
  17. #include <Guid/MeasuredFvHob.h>
  18. #include <Guid/TpmInstance.h>
  19. #include <Library/DebugLib.h>
  20. #include <Library/BaseMemoryLib.h>
  21. #include <Library/PeiServicesLib.h>
  22. #include <Library/PeimEntryPoint.h>
  23. #include <Library/Tpm2CommandLib.h>
  24. #include <Library/Tpm2DeviceLib.h>
  25. #include <Library/HashLib.h>
  26. #include <Library/HobLib.h>
  27. #include <Library/PcdLib.h>
  28. #include <Library/PeiServicesTablePointerLib.h>
  29. #include <Protocol/Tcg2Protocol.h>
  30. #include <Library/PerformanceLib.h>
  31. #include <Library/MemoryAllocationLib.h>
  32. #include <Library/ReportStatusCodeLib.h>
  33. #include <Library/ResetSystemLib.h>
  34. #define PERF_ID_TCG2_PEI 0x3080
  35. typedef struct {
  36. EFI_GUID *EventGuid;
  37. EFI_TCG2_EVENT_LOG_FORMAT LogFormat;
  38. } TCG2_EVENT_INFO_STRUCT;
  39. TCG2_EVENT_INFO_STRUCT mTcg2EventInfo[] = {
  40. {&gTcgEventEntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2},
  41. {&gTcgEvent2EntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2},
  42. };
  43. BOOLEAN mImageInMemory = FALSE;
  44. EFI_PEI_FILE_HANDLE mFileHandle;
  45. EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = {
  46. EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
  47. &gPeiTpmInitializedPpiGuid,
  48. NULL
  49. };
  50. EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = {
  51. EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
  52. &gPeiTpmInitializationDonePpiGuid,
  53. NULL
  54. };
  55. //
  56. // Number of firmware blobs to grow by each time we run out of room
  57. //
  58. #define FIRMWARE_BLOB_GROWTH_STEP 4
  59. EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;
  60. UINT32 mMeasuredMaxBaseFvIndex = 0;
  61. UINT32 mMeasuredBaseFvIndex = 0;
  62. EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;
  63. UINT32 mMeasuredMaxChildFvIndex = 0;
  64. UINT32 mMeasuredChildFvIndex = 0;
  65. /**
  66. Measure and record the Firmware Volume Information once FvInfoPPI install.
  67. @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
  68. @param[in] NotifyDescriptor Address of the notification descriptor data structure.
  69. @param[in] Ppi Address of the PPI that was installed.
  70. @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
  71. @return Others Fail to measure FV.
  72. **/
  73. EFI_STATUS
  74. EFIAPI
  75. FirmwareVolumeInfoPpiNotifyCallback (
  76. IN EFI_PEI_SERVICES **PeiServices,
  77. IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
  78. IN VOID *Ppi
  79. );
  80. /**
  81. Record all measured Firmware Volume Information into a Guid Hob
  82. @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
  83. @param[in] NotifyDescriptor Address of the notification descriptor data structure.
  84. @param[in] Ppi Address of the PPI that was installed.
  85. @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
  86. @return Others Fail to measure FV.
  87. **/
  88. EFI_STATUS
  89. EFIAPI
  90. EndofPeiSignalNotifyCallBack (
  91. IN EFI_PEI_SERVICES **PeiServices,
  92. IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
  93. IN VOID *Ppi
  94. );
  95. EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
  96. {
  97. EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
  98. &gEfiPeiFirmwareVolumeInfoPpiGuid,
  99. FirmwareVolumeInfoPpiNotifyCallback
  100. },
  101. {
  102. EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
  103. &gEfiPeiFirmwareVolumeInfo2PpiGuid,
  104. FirmwareVolumeInfoPpiNotifyCallback
  105. },
  106. {
  107. (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  108. &gEfiEndOfPeiSignalPpiGuid,
  109. EndofPeiSignalNotifyCallBack
  110. }
  111. };
  112. /**
  113. Record all measured Firmware Volume Information into a Guid Hob
  114. Guid Hob payload layout is
  115. UINT32 *************************** FIRMWARE_BLOB number
  116. EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
  117. @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
  118. @param[in] NotifyDescriptor Address of the notification descriptor data structure.
  119. @param[in] Ppi Address of the PPI that was installed.
  120. @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
  121. @return Others Fail to measure FV.
  122. **/
  123. EFI_STATUS
  124. EFIAPI
  125. EndofPeiSignalNotifyCallBack (
  126. IN EFI_PEI_SERVICES **PeiServices,
  127. IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
  128. IN VOID *Ppi
  129. )
  130. {
  131. MEASURED_HOB_DATA *MeasuredHobData;
  132. MeasuredHobData = NULL;
  133. PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid);
  134. //
  135. // Create a Guid hob to save all measured Fv
  136. //
  137. MeasuredHobData = BuildGuidHob(
  138. &gMeasuredFvHobGuid,
  139. sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)
  140. );
  141. if (MeasuredHobData != NULL){
  142. //
  143. // Save measured FV info enty number
  144. //
  145. MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;
  146. //
  147. // Save measured base Fv info
  148. //
  149. CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));
  150. //
  151. // Save measured child Fv info
  152. //
  153. CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));
  154. }
  155. PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid);
  156. return EFI_SUCCESS;
  157. }
  158. /**
  159. Make sure that the current PCR allocations, the TPM supported PCRs,
  160. and the PcdTpm2HashMask are all in agreement.
  161. **/
  162. VOID
  163. SyncPcrAllocationsAndPcrMask (
  164. VOID
  165. )
  166. {
  167. EFI_STATUS Status;
  168. EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap;
  169. UINT32 TpmActivePcrBanks;
  170. UINT32 NewTpmActivePcrBanks;
  171. UINT32 Tpm2PcrMask;
  172. UINT32 NewTpm2PcrMask;
  173. DEBUG ((EFI_D_ERROR, "SyncPcrAllocationsAndPcrMask!\n"));
  174. //
  175. // Determine the current TPM support and the Platform PCR mask.
  176. //
  177. Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &TpmActivePcrBanks);
  178. ASSERT_EFI_ERROR (Status);
  179. Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
  180. if (Tpm2PcrMask == 0) {
  181. //
  182. // if PcdTPm2HashMask is zero, use ActivePcr setting
  183. //
  184. PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
  185. Tpm2PcrMask = TpmActivePcrBanks;
  186. }
  187. //
  188. // Find the intersection of Pcd support and TPM support.
  189. // If banks are missing from the TPM support that are in the PCD, update the PCD.
  190. // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.
  191. //
  192. //
  193. // If there are active PCR banks that are not supported by the Platform mask,
  194. // update the TPM allocations and reboot the machine.
  195. //
  196. if ((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) {
  197. NewTpmActivePcrBanks = TpmActivePcrBanks & Tpm2PcrMask;
  198. DEBUG ((EFI_D_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));
  199. if (NewTpmActivePcrBanks == 0) {
  200. DEBUG ((EFI_D_ERROR, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
  201. ASSERT (FALSE);
  202. } else {
  203. Status = Tpm2PcrAllocateBanks (NULL, (UINT32)TpmHashAlgorithmBitmap, NewTpmActivePcrBanks);
  204. if (EFI_ERROR (Status)) {
  205. //
  206. // We can't do much here, but we hope that this doesn't happen.
  207. //
  208. DEBUG ((EFI_D_ERROR, "%a - Failed to reallocate PCRs!\n", __FUNCTION__));
  209. ASSERT_EFI_ERROR (Status);
  210. }
  211. //
  212. // Need reset system, since we just called Tpm2PcrAllocateBanks().
  213. //
  214. ResetCold();
  215. }
  216. }
  217. //
  218. // If there are any PCRs that claim support in the Platform mask that are
  219. // not supported by the TPM, update the mask.
  220. //
  221. if ((Tpm2PcrMask & TpmHashAlgorithmBitmap) != Tpm2PcrMask) {
  222. NewTpm2PcrMask = Tpm2PcrMask & TpmHashAlgorithmBitmap;
  223. DEBUG ((EFI_D_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask));
  224. if (NewTpm2PcrMask == 0) {
  225. DEBUG ((EFI_D_ERROR, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
  226. ASSERT (FALSE);
  227. }
  228. Status = PcdSet32S (PcdTpm2HashMask, NewTpm2PcrMask);
  229. ASSERT_EFI_ERROR (Status);
  230. }
  231. }
  232. /**
  233. Add a new entry to the Event Log.
  234. @param[in] DigestList A list of digest.
  235. @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
  236. @param[in] NewEventData Pointer to the new event data.
  237. @retval EFI_SUCCESS The new event log entry was added.
  238. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
  239. **/
  240. EFI_STATUS
  241. LogHashEvent (
  242. IN TPML_DIGEST_VALUES *DigestList,
  243. IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,
  244. IN UINT8 *NewEventData
  245. )
  246. {
  247. VOID *HobData;
  248. EFI_STATUS Status;
  249. UINTN Index;
  250. EFI_STATUS RetStatus;
  251. UINT32 SupportedEventLogs;
  252. TCG_PCR_EVENT2 *TcgPcrEvent2;
  253. UINT8 *DigestBuffer;
  254. SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
  255. RetStatus = EFI_SUCCESS;
  256. for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) {
  257. if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) {
  258. DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat));
  259. switch (mTcg2EventInfo[Index].LogFormat) {
  260. case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:
  261. Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);
  262. if (!EFI_ERROR (Status)) {
  263. HobData = BuildGuidHob (
  264. &gTcgEventEntryHobGuid,
  265. sizeof (*NewEventHdr) + NewEventHdr->EventSize
  266. );
  267. if (HobData == NULL) {
  268. RetStatus = EFI_OUT_OF_RESOURCES;
  269. break;
  270. }
  271. CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
  272. HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));
  273. CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
  274. }
  275. break;
  276. case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2:
  277. //
  278. // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation
  279. // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.
  280. //
  281. HobData = BuildGuidHob (
  282. &gTcgEvent2EntryHobGuid,
  283. sizeof(TcgPcrEvent2->PCRIndex) + sizeof(TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2->EventSize) + NewEventHdr->EventSize
  284. );
  285. if (HobData == NULL) {
  286. RetStatus = EFI_OUT_OF_RESOURCES;
  287. break;
  288. }
  289. TcgPcrEvent2 = HobData;
  290. TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex;
  291. TcgPcrEvent2->EventType = NewEventHdr->EventType;
  292. DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;
  293. DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList, PcdGet32 (PcdTpm2HashMask));
  294. CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(TcgPcrEvent2->EventSize));
  295. DigestBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize);
  296. CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize);
  297. break;
  298. }
  299. }
  300. }
  301. return RetStatus;
  302. }
  303. /**
  304. Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
  305. and build a GUIDed HOB recording the event which will be passed to the DXE phase and
  306. added into the Event Log.
  307. @param[in] Flags Bitmap providing additional information.
  308. @param[in] HashData Physical address of the start of the data buffer
  309. to be hashed, extended, and logged.
  310. @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
  311. @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
  312. @param[in] NewEventData Pointer to the new event data.
  313. @retval EFI_SUCCESS Operation completed successfully.
  314. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
  315. @retval EFI_DEVICE_ERROR The command was unsuccessful.
  316. **/
  317. EFI_STATUS
  318. HashLogExtendEvent (
  319. IN UINT64 Flags,
  320. IN UINT8 *HashData,
  321. IN UINTN HashDataLen,
  322. IN TCG_PCR_EVENT_HDR *NewEventHdr,
  323. IN UINT8 *NewEventData
  324. )
  325. {
  326. EFI_STATUS Status;
  327. TPML_DIGEST_VALUES DigestList;
  328. if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
  329. return EFI_DEVICE_ERROR;
  330. }
  331. Status = HashAndExtend (
  332. NewEventHdr->PCRIndex,
  333. HashData,
  334. HashDataLen,
  335. &DigestList
  336. );
  337. if (!EFI_ERROR (Status)) {
  338. if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) {
  339. Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
  340. }
  341. }
  342. if (Status == EFI_DEVICE_ERROR) {
  343. DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
  344. BuildGuidHob (&gTpmErrorHobGuid,0);
  345. REPORT_STATUS_CODE (
  346. EFI_ERROR_CODE | EFI_ERROR_MINOR,
  347. (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
  348. );
  349. }
  350. return Status;
  351. }
  352. /**
  353. Measure CRTM version.
  354. @retval EFI_SUCCESS Operation completed successfully.
  355. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
  356. @retval EFI_DEVICE_ERROR The command was unsuccessful.
  357. **/
  358. EFI_STATUS
  359. MeasureCRTMVersion (
  360. VOID
  361. )
  362. {
  363. TCG_PCR_EVENT_HDR TcgEventHdr;
  364. //
  365. // Use FirmwareVersion string to represent CRTM version.
  366. // OEMs should get real CRTM version string and measure it.
  367. //
  368. TcgEventHdr.PCRIndex = 0;
  369. TcgEventHdr.EventType = EV_S_CRTM_VERSION;
  370. TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
  371. return HashLogExtendEvent (
  372. 0,
  373. (UINT8*)PcdGetPtr (PcdFirmwareVersionString),
  374. TcgEventHdr.EventSize,
  375. &TcgEventHdr,
  376. (UINT8*)PcdGetPtr (PcdFirmwareVersionString)
  377. );
  378. }
  379. /**
  380. Measure FV image.
  381. Add it into the measured FV list after the FV is measured successfully.
  382. @param[in] FvBase Base address of FV image.
  383. @param[in] FvLength Length of FV image.
  384. @retval EFI_SUCCESS Fv image is measured successfully
  385. or it has been already measured.
  386. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
  387. @retval EFI_DEVICE_ERROR The command was unsuccessful.
  388. **/
  389. EFI_STATUS
  390. MeasureFvImage (
  391. IN EFI_PHYSICAL_ADDRESS FvBase,
  392. IN UINT64 FvLength
  393. )
  394. {
  395. UINT32 Index;
  396. EFI_STATUS Status;
  397. EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
  398. TCG_PCR_EVENT_HDR TcgEventHdr;
  399. UINT32 Instance;
  400. UINT32 Tpm2HashMask;
  401. TPML_DIGEST_VALUES DigestList;
  402. UINT32 DigestCount;
  403. EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
  404. EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI *PrehashedFvPpi;
  405. HASH_INFO *PreHashInfo;
  406. UINT32 HashAlgoMask;
  407. //
  408. // Check Excluded FV list
  409. //
  410. Instance = 0;
  411. do {
  412. Status = PeiServicesLocatePpi(
  413. &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
  414. Instance,
  415. NULL,
  416. (VOID**)&MeasurementExcludedFvPpi
  417. );
  418. if (!EFI_ERROR(Status)) {
  419. for (Index = 0; Index < MeasurementExcludedFvPpi->Count; Index ++) {
  420. if (MeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase
  421. && MeasurementExcludedFvPpi->Fv[Index].FvLength == FvLength) {
  422. DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
  423. DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
  424. return EFI_SUCCESS;
  425. }
  426. }
  427. Instance++;
  428. }
  429. } while (!EFI_ERROR(Status));
  430. //
  431. // Check measured FV list
  432. //
  433. for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
  434. if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase && mMeasuredBaseFvInfo[Index].BlobLength == FvLength) {
  435. DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase));
  436. DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength));
  437. return EFI_SUCCESS;
  438. }
  439. }
  440. //
  441. // Check pre-hashed FV list
  442. //
  443. Instance = 0;
  444. Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);
  445. do {
  446. Status = PeiServicesLocatePpi (
  447. &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid,
  448. Instance,
  449. NULL,
  450. (VOID**)&PrehashedFvPpi
  451. );
  452. if (!EFI_ERROR(Status) && PrehashedFvPpi->FvBase == FvBase && PrehashedFvPpi->FvLength == FvLength) {
  453. ZeroMem (&DigestList, sizeof(TPML_DIGEST_VALUES));
  454. //
  455. // The FV is prehashed, check against TPM hash mask
  456. //
  457. PreHashInfo = (HASH_INFO *)(PrehashedFvPpi + 1);
  458. for (Index = 0, DigestCount = 0; Index < PrehashedFvPpi->Count; Index++) {
  459. DEBUG((DEBUG_INFO, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo->HashAlgoId));
  460. HashAlgoMask = GetHashMaskFromAlgo(PreHashInfo->HashAlgoId);
  461. if ((Tpm2HashMask & HashAlgoMask) != 0 ) {
  462. //
  463. // Hash is required, copy it to DigestList
  464. //
  465. WriteUnaligned16(&(DigestList.digests[DigestCount].hashAlg), PreHashInfo->HashAlgoId);
  466. CopyMem (
  467. &DigestList.digests[DigestCount].digest,
  468. PreHashInfo + 1,
  469. PreHashInfo->HashSize
  470. );
  471. DigestCount++;
  472. //
  473. // Clean the corresponding Hash Algo mask bit
  474. //
  475. Tpm2HashMask &= ~HashAlgoMask;
  476. }
  477. PreHashInfo = (HASH_INFO *)((UINT8 *)(PreHashInfo + 1) + PreHashInfo->HashSize);
  478. }
  479. WriteUnaligned32(&DigestList.count, DigestCount);
  480. break;
  481. }
  482. Instance++;
  483. } while (!EFI_ERROR(Status));
  484. //
  485. // Init the log event for FV measurement
  486. //
  487. FvBlob.BlobBase = FvBase;
  488. FvBlob.BlobLength = FvLength;
  489. TcgEventHdr.PCRIndex = 0;
  490. TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
  491. TcgEventHdr.EventSize = sizeof (FvBlob);
  492. if (Tpm2HashMask == 0) {
  493. //
  494. // FV pre-hash algos comply with current TPM hash requirement
  495. // Skip hashing step in measure, only extend DigestList to PCR and log event
  496. //
  497. Status = Tpm2PcrExtend(
  498. 0,
  499. &DigestList
  500. );
  501. if (!EFI_ERROR(Status)) {
  502. Status = LogHashEvent (&DigestList, &TcgEventHdr, (UINT8*) &FvBlob);
  503. DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
  504. DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
  505. } else if (Status == EFI_DEVICE_ERROR) {
  506. BuildGuidHob (&gTpmErrorHobGuid,0);
  507. REPORT_STATUS_CODE (
  508. EFI_ERROR_CODE | EFI_ERROR_MINOR,
  509. (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
  510. );
  511. }
  512. } else {
  513. //
  514. // Hash the FV, extend digest to the TPM and log TCG event
  515. //
  516. Status = HashLogExtendEvent (
  517. 0,
  518. (UINT8*) (UINTN) FvBlob.BlobBase,
  519. (UINTN) FvBlob.BlobLength,
  520. &TcgEventHdr,
  521. (UINT8*) &FvBlob
  522. );
  523. DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
  524. DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
  525. }
  526. if (EFI_ERROR(Status)) {
  527. DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));
  528. return Status;
  529. }
  530. //
  531. // Add new FV into the measured FV list.
  532. //
  533. if (mMeasuredBaseFvIndex >= mMeasuredMaxBaseFvIndex) {
  534. mMeasuredBaseFvInfo = ReallocatePool (
  535. sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxBaseFvIndex,
  536. sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
  537. mMeasuredBaseFvInfo
  538. );
  539. ASSERT (mMeasuredBaseFvInfo != NULL);
  540. mMeasuredMaxBaseFvIndex = mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
  541. }
  542. mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;
  543. mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
  544. mMeasuredBaseFvIndex++;
  545. return Status;
  546. }
  547. /**
  548. Measure main BIOS.
  549. @retval EFI_SUCCESS Operation completed successfully.
  550. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
  551. @retval EFI_DEVICE_ERROR The command was unsuccessful.
  552. **/
  553. EFI_STATUS
  554. MeasureMainBios (
  555. VOID
  556. )
  557. {
  558. EFI_STATUS Status;
  559. EFI_PEI_FV_HANDLE VolumeHandle;
  560. EFI_FV_INFO VolumeInfo;
  561. EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
  562. PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
  563. //
  564. // Only measure BFV at the very beginning. Other parts of Static Core Root of
  565. // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
  566. // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
  567. // reported by platform will be installed with Fv Info Ppi
  568. // This firmware volume measure policy can be modified/enhanced by special
  569. // platform for special CRTM TPM measuring.
  570. //
  571. Status = PeiServicesFfsFindNextVolume (0, &VolumeHandle);
  572. ASSERT_EFI_ERROR (Status);
  573. //
  574. // Measure and record the firmware volume that is dispatched by PeiCore
  575. //
  576. Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
  577. ASSERT_EFI_ERROR (Status);
  578. //
  579. // Locate the corresponding FV_PPI according to founded FV's format guid
  580. //
  581. Status = PeiServicesLocatePpi (
  582. &VolumeInfo.FvFormat,
  583. 0,
  584. NULL,
  585. (VOID**)&FvPpi
  586. );
  587. ASSERT_EFI_ERROR (Status);
  588. Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
  589. PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
  590. return Status;
  591. }
  592. /**
  593. Measure and record the Firmware Volume Information once FvInfoPPI install.
  594. @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
  595. @param[in] NotifyDescriptor Address of the notification descriptor data structure.
  596. @param[in] Ppi Address of the PPI that was installed.
  597. @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
  598. @return Others Fail to measure FV.
  599. **/
  600. EFI_STATUS
  601. EFIAPI
  602. FirmwareVolumeInfoPpiNotifyCallback (
  603. IN EFI_PEI_SERVICES **PeiServices,
  604. IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
  605. IN VOID *Ppi
  606. )
  607. {
  608. EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;
  609. EFI_STATUS Status;
  610. EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
  611. UINTN Index;
  612. Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;
  613. //
  614. // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
  615. //
  616. Status = PeiServicesLocatePpi (
  617. &Fv->FvFormat,
  618. 0,
  619. NULL,
  620. (VOID**)&FvPpi
  621. );
  622. if (EFI_ERROR (Status)) {
  623. return EFI_SUCCESS;
  624. }
  625. //
  626. // This is an FV from an FFS file, and the parent FV must have already been measured,
  627. // No need to measure twice, so just record the FV and return
  628. //
  629. if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {
  630. if (mMeasuredChildFvIndex >= mMeasuredMaxChildFvIndex) {
  631. mMeasuredChildFvInfo = ReallocatePool (
  632. sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxChildFvIndex,
  633. sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP),
  634. mMeasuredChildFvInfo
  635. );
  636. ASSERT (mMeasuredChildFvInfo != NULL);
  637. mMeasuredMaxChildFvIndex = mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP;
  638. }
  639. //
  640. // Check whether FV is in the measured child FV list.
  641. //
  642. for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {
  643. if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) {
  644. return EFI_SUCCESS;
  645. }
  646. }
  647. mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;
  648. mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
  649. mMeasuredChildFvIndex++;
  650. return EFI_SUCCESS;
  651. }
  652. return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);
  653. }
  654. /**
  655. Do measurement after memory is ready.
  656. @param[in] PeiServices Describes the list of possible PEI Services.
  657. @retval EFI_SUCCESS Operation completed successfully.
  658. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
  659. @retval EFI_DEVICE_ERROR The command was unsuccessful.
  660. **/
  661. EFI_STATUS
  662. PeimEntryMP (
  663. IN EFI_PEI_SERVICES **PeiServices
  664. )
  665. {
  666. EFI_STATUS Status;
  667. if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {
  668. Status = MeasureCRTMVersion ();
  669. }
  670. Status = MeasureMainBios ();
  671. if (EFI_ERROR(Status)) {
  672. return Status;
  673. }
  674. //
  675. // Post callbacks:
  676. // for the FvInfoPpi services to measure and record
  677. // the additional Fvs to TPM
  678. //
  679. Status = PeiServicesNotifyPpi (&mNotifyList[0]);
  680. ASSERT_EFI_ERROR (Status);
  681. return Status;
  682. }
  683. /**
  684. Measure and log Separator event with error, and extend the measurement result into a specific PCR.
  685. @param[in] PCRIndex PCR index.
  686. @retval EFI_SUCCESS Operation completed successfully.
  687. @retval EFI_DEVICE_ERROR The operation was unsuccessful.
  688. **/
  689. EFI_STATUS
  690. MeasureSeparatorEventWithError (
  691. IN TPM_PCRINDEX PCRIndex
  692. )
  693. {
  694. TCG_PCR_EVENT_HDR TcgEvent;
  695. UINT32 EventData;
  696. //
  697. // Use EventData 0x1 to indicate there is error.
  698. //
  699. EventData = 0x1;
  700. TcgEvent.PCRIndex = PCRIndex;
  701. TcgEvent.EventType = EV_SEPARATOR;
  702. TcgEvent.EventSize = (UINT32)sizeof (EventData);
  703. return HashLogExtendEvent(0,(UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent,(UINT8 *)&EventData);
  704. }
  705. /**
  706. Entry point of this module.
  707. @param[in] FileHandle Handle of the file being invoked.
  708. @param[in] PeiServices Describes the list of possible PEI Services.
  709. @return Status.
  710. **/
  711. EFI_STATUS
  712. EFIAPI
  713. PeimEntryMA (
  714. IN EFI_PEI_FILE_HANDLE FileHandle,
  715. IN CONST EFI_PEI_SERVICES **PeiServices
  716. )
  717. {
  718. EFI_STATUS Status;
  719. EFI_STATUS Status2;
  720. EFI_BOOT_MODE BootMode;
  721. TPM_PCRINDEX PcrIndex;
  722. BOOLEAN S3ErrorReport;
  723. if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
  724. CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
  725. DEBUG ((DEBUG_INFO, "No TPM2 instance required!\n"));
  726. return EFI_UNSUPPORTED;
  727. }
  728. if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
  729. DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));
  730. return EFI_DEVICE_ERROR;
  731. }
  732. Status = PeiServicesGetBootMode (&BootMode);
  733. ASSERT_EFI_ERROR (Status);
  734. //
  735. // In S3 path, skip shadow logic. no measurement is required
  736. //
  737. if (BootMode != BOOT_ON_S3_RESUME) {
  738. Status = (**PeiServices).RegisterForShadow(FileHandle);
  739. if (Status == EFI_ALREADY_STARTED) {
  740. mImageInMemory = TRUE;
  741. mFileHandle = FileHandle;
  742. } else if (Status == EFI_NOT_FOUND) {
  743. ASSERT_EFI_ERROR (Status);
  744. }
  745. }
  746. if (!mImageInMemory) {
  747. //
  748. // Initialize TPM device
  749. //
  750. Status = Tpm2RequestUseTpm ();
  751. if (EFI_ERROR (Status)) {
  752. DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n"));
  753. goto Done;
  754. }
  755. S3ErrorReport = FALSE;
  756. if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {
  757. if (BootMode == BOOT_ON_S3_RESUME) {
  758. Status = Tpm2Startup (TPM_SU_STATE);
  759. if (EFI_ERROR (Status) ) {
  760. Status = Tpm2Startup (TPM_SU_CLEAR);
  761. if (!EFI_ERROR(Status)) {
  762. S3ErrorReport = TRUE;
  763. }
  764. }
  765. } else {
  766. Status = Tpm2Startup (TPM_SU_CLEAR);
  767. }
  768. if (EFI_ERROR (Status) ) {
  769. goto Done;
  770. }
  771. }
  772. //
  773. // Update Tpm2HashMask according to PCR bank.
  774. //
  775. SyncPcrAllocationsAndPcrMask ();
  776. if (S3ErrorReport) {
  777. //
  778. // The system firmware that resumes from S3 MUST deal with a
  779. // TPM2_Startup error appropriately.
  780. // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
  781. // configuring the device securely by taking actions like extending a
  782. // separator with an error digest (0x01) into PCRs 0 through 7.
  783. //
  784. for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
  785. Status = MeasureSeparatorEventWithError (PcrIndex);
  786. if (EFI_ERROR (Status)) {
  787. DEBUG ((EFI_D_ERROR, "Separator Event with Error not Measured. Error!\n"));
  788. }
  789. }
  790. }
  791. //
  792. // TpmSelfTest is optional on S3 path, skip it to save S3 time
  793. //
  794. if (BootMode != BOOT_ON_S3_RESUME) {
  795. if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {
  796. Status = Tpm2SelfTest (NO);
  797. if (EFI_ERROR (Status)) {
  798. goto Done;
  799. }
  800. }
  801. }
  802. //
  803. // Only intall TpmInitializedPpi on success
  804. //
  805. Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
  806. ASSERT_EFI_ERROR (Status);
  807. }
  808. if (mImageInMemory) {
  809. Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
  810. return Status;
  811. }
  812. Done:
  813. if (EFI_ERROR (Status)) {
  814. DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n"));
  815. BuildGuidHob (&gTpmErrorHobGuid,0);
  816. REPORT_STATUS_CODE (
  817. EFI_ERROR_CODE | EFI_ERROR_MINOR,
  818. (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
  819. );
  820. }
  821. //
  822. // Always intall TpmInitializationDonePpi no matter success or fail.
  823. // Other driver can know TPM initialization state by TpmInitializedPpi.
  824. //
  825. Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
  826. ASSERT_EFI_ERROR (Status2);
  827. return Status;
  828. }