]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/PeilessStartupLib/IntelTdx.c
OvmfPkg/IntelTdx: Measure Td HobList and Configuration FV
[mirror_edk2.git] / OvmfPkg / Library / PeilessStartupLib / IntelTdx.c
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