]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: Introduce SecMeasurementLib
authorMin Xu <min.m.xu@intel.com>
Mon, 16 May 2022 07:42:18 +0000 (15:42 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 3 Jun 2022 11:41:36 +0000 (11:41 +0000)
RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3853

SecMeasurementLib is designed to do the measurement in SEC phase. In
current stage there are 2 functions introduced:
 - MeasureHobList: Measure the Hoblist passed from the VMM.
 - MeasureFvImage: Measure the FV image.

SecMeasurementLibTdx is the TDX version of the library.

Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Ken Lu <ken.lu@intel.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
OvmfPkg/Include/Library/SecMeasurementLib.h [new file with mode: 0644]
OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.c [new file with mode: 0644]
OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.inf [new file with mode: 0644]
OvmfPkg/OvmfPkg.dec

diff --git a/OvmfPkg/Include/Library/SecMeasurementLib.h b/OvmfPkg/Include/Library/SecMeasurementLib.h
new file mode 100644 (file)
index 0000000..ca7a7dc
--- /dev/null
@@ -0,0 +1,46 @@
+/** @file\r
+\r
+  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef SEC_MEASUREMENT_LIB_H_\r
+#define SEC_MEASUREMENT_LIB_H_\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
+  @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 Others                Other errors as indicated\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
+#endif\r
diff --git a/OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.c b/OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.c
new file mode 100644 (file)
index 0000000..274fda1
--- /dev/null
@@ -0,0 +1,340 @@
+/** @file\r
+*\r
+*  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+*  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+*\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Guid/CcEventHob.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HashLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <IndustryStandard/Tpm20.h>\r
+#include <Protocol/CcMeasurement.h>\r
+#include <Library/SecMeasurementLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  UINT32           count;\r
+  TPMI_ALG_HASH    hashAlg;\r
+  BYTE             sha384[SHA384_DIGEST_SIZE];\r
+} TDX_DIGEST_VALUE;\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
+#define INVALID_PCR2MR_INDEX  0xFF\r
+\r
+/**\r
+    RTMR[0]  => PCR[1,7]\r
+    RTMR[1]  => PCR[2,3,4,5]\r
+    RTMR[2]  => PCR[8~15]\r
+    RTMR[3]  => NA\r
+  Note:\r
+    PCR[0] is mapped to MRTD and should not appear here.\r
+    PCR[6] is reserved for OEM. It is not used.\r
+**/\r
+UINT8\r
+GetMappedRtmrIndex (\r
+  UINT32  PCRIndex\r
+  )\r
+{\r
+  UINT8  RtmrIndex;\r
+\r
+  if ((PCRIndex == 6) || (PCRIndex == 0) || (PCRIndex > 15)) {\r
+    DEBUG ((DEBUG_ERROR, "Invalid PCRIndex(%d) map to MR Index.\n", PCRIndex));\r
+    ASSERT (FALSE);\r
+    return INVALID_PCR2MR_INDEX;\r
+  }\r
+\r
+  RtmrIndex = 0;\r
+  if ((PCRIndex == 1) || (PCRIndex == 7)) {\r
+    RtmrIndex = 0;\r
+  } else if ((PCRIndex >= 2) && (PCRIndex < 6)) {\r
+    RtmrIndex = 1;\r
+  } else if ((PCRIndex >= 8) && (PCRIndex <= 15)) {\r
+    RtmrIndex = 2;\r
+  }\r
+\r
+  return RtmrIndex;\r
+}\r
+\r
+/**\r
+  Tpm measure and log data, and extend the measurement result into a specific PCR.\r
+\r
+  @param[in]  PcrIndex         PCR Index.\r
+  @param[in]  EventType        Event type.\r
+  @param[in]  EventLog         Measurement event log.\r
+  @param[in]  LogLen           Event log length in bytes.\r
+  @param[in]  HashData         The start of the data buffer to be hashed, extended.\r
+  @param[in]  HashDataLen      The length, in bytes, of the buffer referenced by HashData\r
+  @retval EFI_SUCCESS               Operation completed successfully.\r
+  @retval EFI_UNSUPPORTED       TPM device not available.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TdxMeasureAndLogData (\r
+  IN UINT32  PcrIndex,\r
+  IN UINT32  EventType,\r
+  IN VOID    *EventLog,\r
+  IN UINT32  LogLen,\r
+  IN VOID    *HashData,\r
+  IN UINT64  HashDataLen\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  UINT32              RtmrIndex;\r
+  VOID                *EventHobData;\r
+  TCG_PCR_EVENT2      *TcgPcrEvent2;\r
+  UINT8               *DigestBuffer;\r
+  TDX_DIGEST_VALUE    *TdxDigest;\r
+  TPML_DIGEST_VALUES  DigestList;\r
+  UINT8               *Ptr;\r
+\r
+  RtmrIndex = GetMappedRtmrIndex (PcrIndex);\r
+  if (RtmrIndex == INVALID_PCR2MR_INDEX) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "Creating TdTcg2PcrEvent PCR[%d]/RTMR[%d] EventType 0x%x\n", PcrIndex, RtmrIndex, EventType));\r
+\r
+  Status = HashAndExtend (\r
+             RtmrIndex,\r
+             (VOID *)HashData,\r
+             HashDataLen,\r
+             &DigestList\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_INFO, "Failed to HashAndExtend. %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Use TDX_DIGEST_VALUE in the GUID HOB DataLength calculation\r
+  // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary\r
+  // which is limited to a SHA384 digest list\r
+  //\r
+  EventHobData = BuildGuidHob (\r
+                   &gCcEventEntryHobGuid,\r
+                   sizeof (TcgPcrEvent2->PCRIndex) + sizeof (TcgPcrEvent2->EventType) +\r
+                   sizeof (TDX_DIGEST_VALUE) +\r
+                   sizeof (TcgPcrEvent2->EventSize) + LogLen\r
+                   );\r
+\r
+  if (EventHobData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ptr = (UINT8 *)EventHobData;\r
+  //\r
+  // Initialize PcrEvent data now\r
+  //\r
+  RtmrIndex++;\r
+  CopyMem (Ptr, &RtmrIndex, sizeof (UINT32));\r
+  Ptr += sizeof (UINT32);\r
+  CopyMem (Ptr, &EventType, sizeof (TCG_EVENTTYPE));\r
+  Ptr += sizeof (TCG_EVENTTYPE);\r
+\r
+  DigestBuffer = Ptr;\r
+\r
+  TdxDigest          = (TDX_DIGEST_VALUE *)DigestBuffer;\r
+  TdxDigest->count   = 1;\r
+  TdxDigest->hashAlg = TPM_ALG_SHA384;\r
+  CopyMem (\r
+    TdxDigest->sha384,\r
+    DigestList.digests[0].digest.sha384,\r
+    SHA384_DIGEST_SIZE\r
+    );\r
+\r
+  Ptr += sizeof (TDX_DIGEST_VALUE);\r
+\r
+  CopyMem (Ptr, &LogLen, sizeof (UINT32));\r
+  Ptr += sizeof (UINT32);\r
+  CopyMem (Ptr, EventLog, LogLen);\r
+  Ptr += LogLen;\r
+\r
+  Status = EFI_SUCCESS;\r
+  return Status;\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 = TdxMeasureAndLogData (\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 = TdxMeasureAndLogData (\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
diff --git a/OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.inf b/OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.inf
new file mode 100644 (file)
index 0000000..6215df5
--- /dev/null
@@ -0,0 +1,30 @@
+#/** @file\r
+#\r
+#  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SecMeasurementLibTdx\r
+  FILE_GUID                      = 3e3fc69d-e834-40e9-96ed-e1e721f41883\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = SecMeasurementLib\r
+\r
+[Sources]\r
+  SecMeasurementLibTdx.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[Guids]\r
+  gCcEventEntryHobGuid\r
+  gUefiOvmfPkgTokenSpaceGuid\r
+\r
+[LibraryClasses]\r
+  HashLib\r
index 8c2048051bea2887035bee33c01036b9ca682b96..1dd86af55b912106721285e6005e9fa1a436f038 100644 (file)
   #\r
   PeilessStartupLib|Include/Library/PeilessStartupLib.h\r
 \r
+  ##  @libraryclass  SecMeasurementLib\r
+  #\r
+  SecMeasurementLib|Include/Library/SecMeasurementLib.h\r
+\r
 [Guids]\r
   gUefiOvmfPkgTokenSpaceGuid            = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}\r
   gEfiXenInfoGuid                       = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}\r