]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: Refactor MeasureHobList
authorMin M Xu <min.m.xu@intel.com>
Fri, 3 Feb 2023 03:31:40 +0000 (11:31 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Sat, 4 Feb 2023 03:38:15 +0000 (03:38 +0000)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4243

MeasureHobList once was implemented in PeilessStartupLib and it does
measurement and logging for TdHob in one go, using TpmMeasureAndLogData().
But it doesn't work in SEC.

This patch splits MeasureHobList into 2 functions and implement them in
SecTdxHelperLib.
 - TdxHelperMeasureTdHob
 - TdxHelperBuildGuidHobForTdxMeasurement

TdxHelperMeasureTdHob measures the TdHob and stores the hash value in
WorkArea. TdxHelperBuildGuidHobForTdxMeasurement builds GuidHob for the
measurement based on the hash value in WorkArea.

After these 2 functions are introduced, PeilessStartupLib should also be
updated:
 - Call these 2 functions instead of the MeasureHobList
 - Delete the duplicated codes in PeilessStartupLib

Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Michael Roth <michael.roth@amd.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
OvmfPkg/IntelTdx/IntelTdxX64.dsc
OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c
OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf
OvmfPkg/IntelTdx/TdxHelperLib/TdxMeasurementHob.c [new file with mode: 0644]
OvmfPkg/Library/PeilessStartupLib/IntelTdx.c
OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c
OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h

index 0f1e970fbbb3f0deadac88ca7eaa84c438695f92..920f1c6080d40269f999249f5fdd3e0e205317f6 100644 (file)
     <LibraryClasses>\r
       NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf\r
       TpmMeasurementLib|SecurityPkg/Library/SecTpmMeasurementLib/SecTpmMeasurementLibTdx.inf\r
+      NULL|OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf\r
       BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SecCryptLib.inf\r
       HashLib|SecurityPkg/Library/HashLibTdx/HashLibTdx.inf\r
       NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf\r
index ef958b33594034a102c24895c80b367558b610e9..6ca6f01aff579ccd4621cdcaebff644a0b1050d7 100644 (file)
@@ -8,6 +8,31 @@
 **/\r
 \r
 #include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseCryptLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <IndustryStandard/Tdx.h>\r
+#include <IndustryStandard/IntelTdx.h>\r
+#include <IndustryStandard/Tpm20.h>\r
+#include <Library/TdxLib.h>\r
+#include <Pi/PrePiHob.h>\r
+#include <WorkArea.h>\r
+#include <ConfidentialComputingGuestAttr.h>\r
+#include <Library/TdxHelperLib.h>\r
+\r
+/**\r
+  Build the GuidHob for tdx measurements which were done in SEC phase.\r
+  The measurement values are stored in WorkArea.\r
+\r
+  @retval EFI_SUCCESS  The GuidHob is built successfully\r
+  @retval Others       Other errors as indicated\r
+**/\r
+EFI_STATUS\r
+InternalBuildGuidHobForTdxMeasurement (\r
+  VOID\r
+  );\r
 \r
 /**\r
   In Tdx guest, some information need to be passed from host VMM to guest\r
@@ -27,6 +52,58 @@ TdxHelperProcessTdHob (
   return EFI_UNSUPPORTED;\r
 }\r
 \r
+/**\r
+ * Calculate the sha384 of input Data and extend it to RTMR register.\r
+ *\r
+ * @param RtmrIndex       Index of the RTMR register\r
+ * @param DataToHash      Data to be hashed\r
+ * @param DataToHashLen   Length of the data\r
+ * @param Digest          Hash value of the input data\r
+ * @param DigestLen       Length of the hash value\r
+ *\r
+ * @retval EFI_SUCCESS    Successfully hash and extend to RTMR\r
+ * @retval Others         Other errors as indicated\r
+ */\r
+STATIC\r
+EFI_STATUS\r
+HashAndExtendToRtmr (\r
+  IN UINT32  RtmrIndex,\r
+  IN VOID    *DataToHash,\r
+  IN UINTN   DataToHashLen,\r
+  OUT UINT8  *Digest,\r
+  IN  UINTN  DigestLen\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  if ((DataToHash == NULL) || (DataToHashLen == 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Digest == NULL) || (DigestLen != SHA384_DIGEST_SIZE)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Calculate the sha384 of the data\r
+  //\r
+  if (!Sha384HashAll (DataToHash, DataToHashLen, Digest)) {\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  //\r
+  // Extend to RTMR\r
+  //\r
+  Status = TdExtendRtmr (\r
+             (UINT32 *)Digest,\r
+             SHA384_DIGEST_SIZE,\r
+             (UINT8)RtmrIndex\r
+             );\r
+\r
+  ASSERT (!EFI_ERROR (Status));\r
+  return Status;\r
+}\r
+\r
 /**\r
   In Tdx guest, TdHob is passed from host VMM to guest firmware and it contains\r
   the information of the memory resource. From the security perspective before\r
@@ -41,7 +118,47 @@ TdxHelperMeasureTdHob (
   VOID\r
   )\r
 {\r
-  return EFI_UNSUPPORTED;\r
+  EFI_PEI_HOB_POINTERS  Hob;\r
+  EFI_STATUS            Status;\r
+  UINT8                 Digest[SHA384_DIGEST_SIZE];\r
+  OVMF_WORK_AREA        *WorkArea;\r
+  VOID                  *TdHob;\r
+\r
+  TdHob   = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase);\r
+  Hob.Raw = (UINT8 *)TdHob;\r
+\r
+  //\r
+  // Walk thru the TdHob list until end of list.\r
+  //\r
+  while (!END_OF_HOB_LIST (Hob)) {\r
+    Hob.Raw = GET_NEXT_HOB (Hob);\r
+  }\r
+\r
+  Status = HashAndExtendToRtmr (\r
+             0,\r
+             (UINT8 *)TdHob,\r
+             (UINTN)((UINT8 *)Hob.Raw - (UINT8 *)TdHob),\r
+             Digest,\r
+             SHA384_DIGEST_SIZE\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // This function is called in SEC phase and at that moment the Hob service\r
+  // is not available. So the TdHob measurement value is stored in workarea.\r
+  //\r
+  WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase);\r
+  if (WorkArea == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.MeasurementsBitmap |= TDX_MEASUREMENT_TDHOB_BITMASK;\r
+  CopyMem (WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.TdHobHashValue, Digest, SHA384_DIGEST_SIZE);\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -74,5 +191,9 @@ TdxHelperBuildGuidHobForTdxMeasurement (
   VOID\r
   )\r
 {\r
+ #ifdef TDX_PEI_LESS_BOOT\r
+  return InternalBuildGuidHobForTdxMeasurement ();\r
+ #else\r
   return EFI_UNSUPPORTED;\r
+ #endif\r
 }\r
index 3c6b96f7759a7d95030e8136af7d03be0e67e263..d17b84c01f202abd9860e093d57917d04b6dbce0 100644 (file)
@@ -24,6 +24,7 @@
 \r
 [Sources]\r
   SecTdxHelper.c\r
+  TdxMeasurementHob.c\r
 \r
 [Packages]\r
   CryptoPkg/CryptoPkg.dec\r
diff --git a/OvmfPkg/IntelTdx/TdxHelperLib/TdxMeasurementHob.c b/OvmfPkg/IntelTdx/TdxHelperLib/TdxMeasurementHob.c
new file mode 100644 (file)
index 0000000..6cbc760
--- /dev/null
@@ -0,0 +1,173 @@
+/** @file\r
+  Build GuidHob for tdx measurement.\r
+\r
+  Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <IndustryStandard/Tpm20.h>\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <WorkArea.h>\r
+\r
+#pragma pack(1)\r
+\r
+#define HANDOFF_TABLE_DESC  "TdxTable"\r
+typedef struct {\r
+  UINT8                      TableDescriptionSize;\r
+  UINT8                      TableDescription[sizeof (HANDOFF_TABLE_DESC)];\r
+  UINT64                     NumberOfTables;\r
+  EFI_CONFIGURATION_TABLE    TableEntry[1];\r
+} TDX_HANDOFF_TABLE_POINTERS2;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+ * Build GuidHob for Tdx measurement.\r
+ *\r
+ * Tdx measurement includes the measurement of TdHob and CFV. They're measured\r
+ * and extended to RTMR registers in SEC phase. Because at that moment the Hob\r
+ * service are not available. So the values of the measurement are saved in\r
+ * workarea and will be built into GuidHob after the Hob service is ready.\r
+ *\r
+ * @param RtmrIndex     RTMR index\r
+ * @param EventType     Event type\r
+ * @param EventData     Event data\r
+ * @param EventSize     Size of event data\r
+ * @param HashValue     Hash value\r
+ * @param HashSize      Size of hash\r
+ *\r
+ * @retval EFI_SUCCESS  Successfully build the GuidHobs\r
+ * @retval Others       Other error as indicated\r
+ */\r
+STATIC\r
+EFI_STATUS\r
+BuildTdxMeasurementGuidHob (\r
+  UINT32  RtmrIndex,\r
+  UINT32  EventType,\r
+  UINT8   *EventData,\r
+  UINT32  EventSize,\r
+  UINT8   *HashValue,\r
+  UINT32  HashSize\r
+  )\r
+{\r
+  VOID                *EventHobData;\r
+  UINT8               *Ptr;\r
+  TPML_DIGEST_VALUES  *TdxDigest;\r
+\r
+  if (HashSize != SHA384_DIGEST_SIZE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  #define TDX_DIGEST_VALUE_LEN  (sizeof (UINT32) + sizeof (TPMI_ALG_HASH) + SHA384_DIGEST_SIZE)\r
+\r
+  EventHobData = BuildGuidHob (\r
+                   &gCcEventEntryHobGuid,\r
+                   sizeof (TCG_PCRINDEX) + sizeof (TCG_EVENTTYPE) +\r
+                   TDX_DIGEST_VALUE_LEN +\r
+                   sizeof (UINT32) + EventSize\r
+                   );\r
+\r
+  if (EventHobData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ptr = (UINT8 *)EventHobData;\r
+\r
+  //\r
+  // There are 2 types of measurement registers in TDX: MRTD and RTMR[0-3].\r
+  // According to UEFI Spec 2.10 Section 38.4.1, RTMR[0-3] is mapped to MrIndex[1-4].\r
+  // So RtmrIndex must be increased by 1 before the event log is created.\r
+  //\r
+  RtmrIndex++;\r
+  CopyMem (Ptr, &RtmrIndex, sizeof (UINT32));\r
+  Ptr += sizeof (UINT32);\r
+\r
+  CopyMem (Ptr, &EventType, sizeof (TCG_EVENTTYPE));\r
+  Ptr += sizeof (TCG_EVENTTYPE);\r
+\r
+  TdxDigest                     = (TPML_DIGEST_VALUES *)Ptr;\r
+  TdxDigest->count              = 1;\r
+  TdxDigest->digests[0].hashAlg = TPM_ALG_SHA384;\r
+  CopyMem (\r
+    TdxDigest->digests[0].digest.sha384,\r
+    HashValue,\r
+    SHA384_DIGEST_SIZE\r
+    );\r
+  Ptr += TDX_DIGEST_VALUE_LEN;\r
+\r
+  CopyMem (Ptr, &EventSize, sizeof (UINT32));\r
+  Ptr += sizeof (UINT32);\r
+\r
+  CopyMem (Ptr, (VOID *)EventData, EventSize);\r
+  Ptr += EventSize;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Build the GuidHob for tdx measurements which were done in SEC phase.\r
+  The measurement values are stored in WorkArea.\r
+\r
+  @retval EFI_SUCCESS  The GuidHob is built successfully\r
+  @retval Others       Other errors as indicated\r
+**/\r
+EFI_STATUS\r
+InternalBuildGuidHobForTdxMeasurement (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  OVMF_WORK_AREA               *WorkArea;\r
+  VOID                         *TdHobList;\r
+  TDX_HANDOFF_TABLE_POINTERS2  HandoffTables;\r
+  UINT8                        *HashValue;\r
+\r
+  if (!TdIsEnabled ()) {\r
+    ASSERT (FALSE);\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase);\r
+  if (WorkArea == NULL) {\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Build the GuidHob for TdHob measurement\r
+  //\r
+  TdHobList = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase);\r
+  if (WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.MeasurementsBitmap & TDX_MEASUREMENT_TDHOB_BITMASK) {\r
+    HashValue                          = WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.TdHobHashValue;\r
+    HandoffTables.TableDescriptionSize = sizeof (HandoffTables.TableDescription);\r
+    CopyMem (HandoffTables.TableDescription, HANDOFF_TABLE_DESC, sizeof (HandoffTables.TableDescription));\r
+    HandoffTables.NumberOfTables = 1;\r
+    CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), &gUefiOvmfPkgTokenSpaceGuid);\r
+    HandoffTables.TableEntry[0].VendorTable = TdHobList;\r
+\r
+    Status = BuildTdxMeasurementGuidHob (\r
+               0,                               // RtmrIndex\r
+               EV_EFI_HANDOFF_TABLES2,          // EventType\r
+               (UINT8 *)(UINTN)&HandoffTables,  // EventData\r
+               sizeof (HandoffTables),          // EventSize\r
+               HashValue,                       // HashValue\r
+               SHA384_DIGEST_SIZE               // HashSize\r
+               );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (FALSE);\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
index 4e8dca3d77125cdae64e95399818c51cf8918d45..ae0ffcc95da506c99bd4e0746381938896faadb0 100644 (file)
 \r
 #include "PeilessStartupInternal.h"\r
 \r
-#pragma pack(1)\r
-\r
-#define HANDOFF_TABLE_DESC  "TdxTable"\r
-typedef struct {\r
-  UINT8                      TableDescriptionSize;\r
-  UINT8                      TableDescription[sizeof (HANDOFF_TABLE_DESC)];\r
-  UINT64                     NumberOfTables;\r
-  EFI_CONFIGURATION_TABLE    TableEntry[1];\r
-} TDX_HANDOFF_TABLE_POINTERS2;\r
-\r
-#pragma pack()\r
-\r
 #define FV_HANDOFF_TABLE_DESC  "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"\r
 typedef PLATFORM_FIRMWARE_BLOB2_STRUCT CFV_HANDOFF_TABLE_POINTERS2;\r
 \r
-/**\r
-  Measure the Hoblist passed from the VMM.\r
-\r
-  @param[in] VmmHobList    The Hoblist pass the firmware\r
-\r
-  @retval EFI_SUCCESS           Fv image is measured successfully\r
-                                or it has been already measured.\r
-  @retval Others                Other errors as indicated\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MeasureHobList (\r
-  IN CONST VOID  *VmmHobList\r
-  )\r
-{\r
-  EFI_PEI_HOB_POINTERS         Hob;\r
-  TDX_HANDOFF_TABLE_POINTERS2  HandoffTables;\r
-  EFI_STATUS                   Status;\r
-\r
-  if (!TdIsEnabled ()) {\r
-    ASSERT (FALSE);\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  Hob.Raw = (UINT8 *)VmmHobList;\r
-\r
-  //\r
-  // Parse the HOB list until end of list.\r
-  //\r
-  while (!END_OF_HOB_LIST (Hob)) {\r
-    Hob.Raw = GET_NEXT_HOB (Hob);\r
-  }\r
-\r
-  //\r
-  // Init the log event for HOB measurement\r
-  //\r
-\r
-  HandoffTables.TableDescriptionSize = sizeof (HandoffTables.TableDescription);\r
-  CopyMem (HandoffTables.TableDescription, HANDOFF_TABLE_DESC, sizeof (HandoffTables.TableDescription));\r
-  HandoffTables.NumberOfTables = 1;\r
-  CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), &gUefiOvmfPkgTokenSpaceGuid);\r
-  HandoffTables.TableEntry[0].VendorTable = (VOID *)VmmHobList;\r
-\r
-  Status = TpmMeasureAndLogData (\r
-             1,                                              // PCRIndex\r
-             EV_EFI_HANDOFF_TABLES2,                         // EventType\r
-             (VOID *)&HandoffTables,                         // EventData\r
-             sizeof (HandoffTables),                         // EventSize\r
-             (UINT8 *)(UINTN)VmmHobList,                     // HashData\r
-             (UINTN)((UINT8 *)Hob.Raw - (UINT8 *)VmmHobList) // HashDataLen\r
-             );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    ASSERT (FALSE);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
 /**\r
   Get the FvName from the FV header.\r
 \r
index 928120d183ba56d1175bf34625234041df4ea47e..4efbc14d5921bb396f8ee0ea40df5326975e51de 100644 (file)
@@ -17,6 +17,7 @@
 #include <Library/PrePiLib.h>\r
 #include <Library/PeilessStartupLib.h>\r
 #include <Library/PlatformInitLib.h>\r
+#include <Library/TdxHelperLib.h>\r
 #include <ConfidentialComputingGuestAttr.h>\r
 #include <Guid/MemoryTypeInformation.h>\r
 #include <OvmfPlatforms.h>\r
@@ -179,7 +180,16 @@ PeilessStartup (
     //\r
     // Measure HobList\r
     //\r
-    Status = MeasureHobList (VmmHobList);\r
+    Status = TdxHelperMeasureTdHob ();\r
+    if (EFI_ERROR (Status)) {\r
+      ASSERT (FALSE);\r
+      CpuDeadLoop ();\r
+    }\r
+\r
+    //\r
+    // Build GuidHob for tdx measurement\r
+    //\r
+    Status = TdxHelperBuildGuidHobForTdxMeasurement ();\r
     if (EFI_ERROR (Status)) {\r
       ASSERT (FALSE);\r
       CpuDeadLoop ();\r
index f56bc3578e5e6518f3d838656dacfed4d0171cad..a2d2c1c9145bacf2499a0530ca382a6726150313 100644 (file)
@@ -58,21 +58,6 @@ EFIAPI
 ConstructSecHobList (\r
   );\r
 \r
-/**\r
-  Measure the Hoblist passed from the VMM.\r
-\r
-  @param[in] VmmHobList    The Hoblist pass the firmware\r
-\r
-  @retval EFI_SUCCESS           Fv image is measured successfully\r
-                                or it has been already measured.\r
-  @retval Others                Other errors as indicated\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MeasureHobList (\r
-  IN CONST VOID  *VmmHobList\r
-  );\r
-\r
 /**\r
   Measure FV image.\r
 \r