]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/PeilessStartupLib/IntelTdx.c
OvmfPkg: Implement MeasureHobList/MeasureFvImage
[mirror_edk2.git] / OvmfPkg / Library / PeilessStartupLib / IntelTdx.c
index d240d3b7719fe046c9f2b6cd892b4ffa5e0f430f..484fd21057c8f4a67258c05a63297fc571a51e0b 100644 (file)
@@ -9,8 +9,34 @@
 #include <Library/DebugLib.h>\r
 #include <Guid/VariableFormat.h>\r
 #include <Guid/SystemNvDataGuid.h>\r
+#include <IndustryStandard/Tpm20.h>\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/TpmMeasurementLib.h>\r
+\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
+#define FV_HANDOFF_TABLE_DESC  "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"\r
+typedef struct {\r
+  UINT8                   BlobDescriptionSize;\r
+  UINT8                   BlobDescription[sizeof (FV_HANDOFF_TABLE_DESC)];\r
+  EFI_PHYSICAL_ADDRESS    BlobBase;\r
+  UINT64                  BlobLength;\r
+} FV_HANDOFF_TABLE_POINTERS2;\r
+\r
+#pragma pack()\r
+\r
 /**\r
   Check padding data all bit should be 1.\r
 \r
@@ -161,3 +187,163 @@ TdxValidateCfv (
 \r
   return TRUE;\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
+  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
+  Causion: The FV is untrusted input.\r
+\r
+  @param[in]  FvBase            Base address of FV image.\r
+  @param[in]  FvLength          Length of FV image.\r
+\r
+  @return FvName pointer\r
+  @retval NULL   FvName is NOT found\r
+**/\r
+VOID *\r
+GetFvName (\r
+  IN EFI_PHYSICAL_ADDRESS  FvBase,\r
+  IN UINT64                FvLength\r
+  )\r
+{\r
+  EFI_FIRMWARE_VOLUME_HEADER      *FvHeader;\r
+  EFI_FIRMWARE_VOLUME_EXT_HEADER  *FvExtHeader;\r
+\r
+  if (FvBase >= MAX_ADDRESS) {\r
+    return NULL;\r
+  }\r
+\r
+  if (FvLength >= MAX_ADDRESS - FvBase) {\r
+    return NULL;\r
+  }\r
+\r
+  if (FvLength < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {\r
+    return NULL;\r
+  }\r
+\r
+  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;\r
+  if (FvHeader->ExtHeaderOffset < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {\r
+    return NULL;\r
+  }\r
+\r
+  if (FvHeader->ExtHeaderOffset + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER) > FvLength) {\r
+    return NULL;\r
+  }\r
+\r
+  FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(UINTN)(FvBase + FvHeader->ExtHeaderOffset);\r
+\r
+  return &FvExtHeader->FvName;\r
+}\r
+\r
+/**\r
+  Measure FV image.\r
+\r
+  @param[in]  FvBase            Base address of FV image.\r
+  @param[in]  FvLength          Length of FV image.\r
+  @param[in]  PcrIndex          Index of PCR\r
+\r
+  @retval EFI_SUCCESS           Fv image is measured successfully\r
+                                or it has been already measured.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.\r
+  @retval EFI_DEVICE_ERROR      The command was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MeasureFvImage (\r
+  IN EFI_PHYSICAL_ADDRESS  FvBase,\r
+  IN UINT64                FvLength,\r
+  IN UINT8                 PcrIndex\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  FV_HANDOFF_TABLE_POINTERS2  FvBlob2;\r
+  VOID                        *FvName;\r
+\r
+  //\r
+  // Init the log event for FV measurement\r
+  //\r
+  FvBlob2.BlobDescriptionSize = sizeof (FvBlob2.BlobDescription);\r
+  CopyMem (FvBlob2.BlobDescription, FV_HANDOFF_TABLE_DESC, sizeof (FvBlob2.BlobDescription));\r
+  FvName = GetFvName (FvBase, FvLength);\r
+  if (FvName != NULL) {\r
+    AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDescription), "Fv(%g)", FvName);\r
+  }\r
+\r
+  FvBlob2.BlobBase   = FvBase;\r
+  FvBlob2.BlobLength = FvLength;\r
+\r
+  Status = TpmMeasureAndLogData (\r
+             1,                              // PCRIndex\r
+             EV_EFI_PLATFORM_FIRMWARE_BLOB2, // EventType\r
+             (VOID *)&FvBlob2,               // EventData\r
+             sizeof (FvBlob2),               // EventSize\r
+             (UINT8 *)(UINTN)FvBase,         // HashData\r
+             (UINTN)(FvLength)               // HashDataLen\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return Status;\r
+}\r