]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/IntelTdx: Measure Td HobList and Configuration FV
authorMin Xu <min.m.xu@intel.com>
Mon, 16 May 2022 07:42:19 +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

TdHobList and Configuration FV are external data provided by Host VMM.
These are not trusted in Td guest. So they should be validated , measured
and extended to Td RTMR registers. In the meantime 2 EFI_CC_EVENT_HOB are
created. These 2 GUIDed HOBs carry the hash value of TdHobList and
Configuration FV. In DXE phase EFI_CC_EVENT can be created based on these
2 GUIDed HOBs.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
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: 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/Library/PeilessStartupLib/IntelTdx.c [new file with mode: 0644]
OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c
OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h
OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf

index dd8d446f4a5617833ca622ec12ff9f3e5169084f..c51da39874a52838c125b7b163e3fdb32d97a489 100644 (file)
   OvmfPkg/IntelTdx/Sec/SecMain.inf {\r
     <LibraryClasses>\r
       NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf\r
+      SecMeasurementLib|OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.inf\r
+      BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SecCryptLib.inf\r
+      HashLib|SecurityPkg/Library/HashLibTdx/HashLibTdx.inf\r
+      NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf\r
   }\r
 \r
   #\r
diff --git a/OvmfPkg/Library/PeilessStartupLib/IntelTdx.c b/OvmfPkg/Library/PeilessStartupLib/IntelTdx.c
new file mode 100644 (file)
index 0000000..d240d3b
--- /dev/null
@@ -0,0 +1,163 @@
+/** @file\r
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Guid/VariableFormat.h>\r
+#include <Guid/SystemNvDataGuid.h>\r
+#include "PeilessStartupInternal.h"\r
+\r
+/**\r
+  Check padding data all bit should be 1.\r
+\r
+  @param[in] Buffer     - A pointer to buffer header\r
+  @param[in] BufferSize - Buffer size\r
+\r
+  @retval  TRUE   - The padding data is valid.\r
+  @retval  TRUE  - The padding data is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+CheckPaddingData (\r
+  IN UINT8   *Buffer,\r
+  IN UINT32  BufferSize\r
+  )\r
+{\r
+  UINT32  index;\r
+\r
+  for (index = 0; index < BufferSize; index++) {\r
+    if (Buffer[index] != 0xFF) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Check the integrity of CFV data.\r
+\r
+  @param[in] TdxCfvBase - A pointer to CFV header\r
+  @param[in] TdxCfvSize - CFV data size\r
+\r
+  @retval  TRUE   - The CFV data is valid.\r
+  @retval  FALSE  - The CFV data is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TdxValidateCfv (\r
+  IN UINT8   *TdxCfvBase,\r
+  IN UINT32  TdxCfvSize\r
+  )\r
+{\r
+  UINT16                         Checksum;\r
+  UINTN                          VariableBase;\r
+  UINT32                         VariableOffset;\r
+  UINT32                         VariableOffsetBeforeAlign;\r
+  EFI_FIRMWARE_VOLUME_HEADER     *CfvFvHeader;\r
+  VARIABLE_STORE_HEADER          *CfvVariableStoreHeader;\r
+  AUTHENTICATED_VARIABLE_HEADER  *VariableHeader;\r
+\r
+  static EFI_GUID  FvHdrGUID       = EFI_SYSTEM_NV_DATA_FV_GUID;\r
+  static EFI_GUID  VarStoreHdrGUID = EFI_AUTHENTICATED_VARIABLE_GUID;\r
+\r
+  VariableOffset = 0;\r
+\r
+  if (TdxCfvBase == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "TDX CFV: CFV pointer is NULL\n"));\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Verify the header zerovetor, filesystemguid,\r
+  // revision, signature, attributes, fvlength, checksum\r
+  // HeaderLength cannot be an odd number\r
+  //\r
+  CfvFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)TdxCfvBase;\r
+\r
+  if ((!IsZeroBuffer (CfvFvHeader->ZeroVector, 16)) ||\r
+      (!CompareGuid (&FvHdrGUID, &CfvFvHeader->FileSystemGuid)) ||\r
+      (CfvFvHeader->Signature != EFI_FVH_SIGNATURE) ||\r
+      (CfvFvHeader->Attributes != 0x4feff) ||\r
+      (CfvFvHeader->Revision != EFI_FVH_REVISION) ||\r
+      (CfvFvHeader->FvLength != TdxCfvSize)\r
+      )\r
+  {\r
+    DEBUG ((DEBUG_ERROR, "TDX CFV: Basic FV headers were invalid\n"));\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Verify the header checksum\r
+  //\r
+  Checksum = CalculateSum16 ((VOID *)CfvFvHeader, CfvFvHeader->HeaderLength);\r
+\r
+  if (Checksum != 0) {\r
+    DEBUG ((DEBUG_ERROR, "TDX CFV: FV checksum was invalid\n"));\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Verify the header signature, size, format, state\r
+  //\r
+  CfvVariableStoreHeader = (VARIABLE_STORE_HEADER *)(TdxCfvBase + CfvFvHeader->HeaderLength);\r
+  if ((!CompareGuid (&VarStoreHdrGUID, &CfvVariableStoreHeader->Signature)) ||\r
+      (CfvVariableStoreHeader->Format != VARIABLE_STORE_FORMATTED) ||\r
+      (CfvVariableStoreHeader->State != VARIABLE_STORE_HEALTHY) ||\r
+      (CfvVariableStoreHeader->Size > (CfvFvHeader->FvLength - CfvFvHeader->HeaderLength)) ||\r
+      (CfvVariableStoreHeader->Size < sizeof (VARIABLE_STORE_HEADER))\r
+      )\r
+  {\r
+    DEBUG ((DEBUG_ERROR, "TDX CFV: Variable Store header was invalid\n"));\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Verify the header startId, state\r
+  // Verify data to the end\r
+  //\r
+  VariableBase = (UINTN)TdxCfvBase + CfvFvHeader->HeaderLength + sizeof (VARIABLE_STORE_HEADER);\r
+  while (VariableOffset  < (CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) {\r
+    VariableHeader = (AUTHENTICATED_VARIABLE_HEADER *)(VariableBase + VariableOffset);\r
+    if (VariableHeader->StartId != VARIABLE_DATA) {\r
+      if (!CheckPaddingData ((UINT8 *)VariableHeader, CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - VariableOffset)) {\r
+        DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
+        return FALSE;\r
+      }\r
+\r
+      VariableOffset = CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
+    } else {\r
+      if (!((VariableHeader->State == VAR_IN_DELETED_TRANSITION) ||\r
+            (VariableHeader->State == VAR_DELETED) ||\r
+            (VariableHeader->State == VAR_HEADER_VALID_ONLY) ||\r
+            (VariableHeader->State == VAR_ADDED)))\r
+      {\r
+        DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
+        return FALSE;\r
+      }\r
+\r
+      VariableOffset += sizeof (AUTHENTICATED_VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize;\r
+      // Verify VariableOffset should be less than or equal CfvVariableStoreHeader->Size - sizeof(VARIABLE_STORE_HEADER)\r
+      if (VariableOffset > (CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) {\r
+        DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
+        return FALSE;\r
+      }\r
+\r
+      VariableOffsetBeforeAlign = VariableOffset;\r
+      // 4 byte align\r
+      VariableOffset = (VariableOffset  + 3) & (UINTN)(~3);\r
+\r
+      if (!CheckPaddingData ((UINT8 *)(VariableBase + VariableOffsetBeforeAlign), VariableOffset - VariableOffsetBeforeAlign)) {\r
+        DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
+        return FALSE;\r
+      }\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
index 126eb74048f48b201f46d10d9074b6833139b5ca..54236b956c52547092f121da4e165482ac85f374 100644 (file)
@@ -20,6 +20,7 @@
 #include <ConfidentialComputingGuestAttr.h>\r
 #include <Guid/MemoryTypeInformation.h>\r
 #include <OvmfPlatforms.h>\r
+#include <Library/SecMeasurementLib.h>\r
 #include "PeilessStartupInternal.h"\r
 \r
 #define GET_GPAW_INIT_STATE(INFO)  ((UINT8) ((INFO) & 0x3f))\r
@@ -133,11 +134,13 @@ PeilessStartup (
   UINT32                      DxeCodeSize;\r
   TD_RETURN_DATA              TdReturnData;\r
   VOID                        *VmmHobList;\r
+  UINT8                       *CfvBase;\r
 \r
   Status      = EFI_SUCCESS;\r
   BootFv      = NULL;\r
   VmmHobList  = NULL;\r
   SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;\r
+  CfvBase     = (UINT8 *)(UINTN)FixedPcdGet32 (PcdCfvBase);\r
 \r
   ZeroMem (&PlatformInfoHob, sizeof (PlatformInfoHob));\r
 \r
@@ -167,6 +170,34 @@ PeilessStartup (
 \r
   DEBUG ((DEBUG_INFO, "HobList: %p\n", GetHobList ()));\r
 \r
+  if (TdIsEnabled ()) {\r
+    //\r
+    // Measure HobList\r
+    //\r
+    Status = MeasureHobList (VmmHobList);\r
+    if (EFI_ERROR (Status)) {\r
+      ASSERT (FALSE);\r
+      CpuDeadLoop ();\r
+    }\r
+\r
+    //\r
+    // Validate Tdx CFV\r
+    //\r
+    if (!TdxValidateCfv (CfvBase, FixedPcdGet32 (PcdCfvRawDataSize))) {\r
+      ASSERT (FALSE);\r
+      CpuDeadLoop ();\r
+    }\r
+\r
+    //\r
+    // Measure Tdx CFV\r
+    //\r
+    Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS)(UINTN)CfvBase, FixedPcdGet32 (PcdCfvRawDataSize), 1);\r
+    if (EFI_ERROR (Status)) {\r
+      ASSERT (FALSE);\r
+      CpuDeadLoop ();\r
+    }\r
+  }\r
+\r
   //\r
   // Initialize the Platform\r
   //\r
index 23e9e0be53f13e4bf48e36490fc4832b56e10a3a..dd79b8a06b44fa250bb4d525a6acb35ea79b9223 100644 (file)
@@ -52,4 +52,21 @@ EFIAPI
 ConstructSecHobList (\r
   );\r
 \r
+/**\r
+  Check the integrity of CFV data.\r
+\r
+  @param[in] TdxCfvBase - A pointer to CFV header\r
+  @param[in] TdxCfvSize - CFV data size\r
+\r
+  @retval  TRUE   - The CFV data is valid.\r
+  @retval  FALSE  - The CFV data is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TdxValidateCfv (\r
+  IN UINT8   *TdxCfvBase,\r
+  IN UINT32  TdxCfvSize\r
+  );\r
+\r
 #endif\r
index 8791984586a4cd9a18d333d014da1750cad49fec..c5d291f02bcd9808d6ba9097ebe1717ba946a592 100644 (file)
@@ -29,8 +29,7 @@
   PeilessStartup.c\r
   Hob.c\r
   DxeLoad.c\r
-\r
-[Sources.X64]\r
+  IntelTdx.c\r
   X64/VirtualMemory.c\r
 \r
 [Packages]\r
@@ -39,6 +38,8 @@
   UefiCpuPkg/UefiCpuPkg.dec\r
   OvmfPkg/OvmfPkg.dec\r
   EmbeddedPkg/EmbeddedPkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
 \r
 [LibraryClasses]\r
   BaseLib\r
@@ -56,6 +57,8 @@
   PrePiLib\r
   QemuFwCfgLib\r
   PlatformInitLib\r
+  HashLib\r
+  SecMeasurementLib\r
 \r
 [Guids]\r
   gEfiHobMemoryAllocModuleGuid\r
@@ -63,6 +66,7 @@
   gUefiOvmfPkgPlatformInfoGuid\r
   gEfiMemoryTypeInformationGuid\r
   gPcdDataBaseHobGuid\r
+  gCcEventEntryHobGuid\r
 \r
 [Pcd]\r
   gUefiOvmfPkgTokenSpaceGuid.PcdCfvBase\r