]> git.proxmox.com Git - mirror_edk2.git/commitdiff
SecurityPkg/FvReportPei: implement a common FV verifier and reporter
authorJian J Wang <jian.j.wang@intel.com>
Fri, 10 May 2019 02:19:36 +0000 (10:19 +0800)
committerJian J Wang <jian.j.wang@intel.com>
Wed, 26 Jun 2019 13:18:43 +0000 (21:18 +0800)
https://bugzilla.tianocore.org/show_bug.cgi?id=1617

This driver implements a common checker, verifier and reporter which is
independent of hardware based root-of-trust.

Usually the hardware based root-of-trust will not verify all BIOS but
part of it. For example, Boot Guard will only verify IBB segment. The IBB
needs to verify other part of BIOS, i.e. other FVs to transfer control to
from IBB. This driver plays the role in IBB to verify FVs not covered by
hardware root-of-trust to make sure integrity of the chain of trust.

To be hardware/platform independent, PPI

  gEdkiiPeiFirmwareVolumeInfoStoredHashFvPpiGuid

is introduced for platform to pass digest information to this driver.
This PPI should include all information needed to verify required FVs in
required boot mode.

struct _EDKII_PEI_FIRMWARE_VOLUME_INFO_STORED_HASH_FV_PPI {
  FV_HASH_INFO            HashInfo;
  UINTN                   FvNumber;
  HASHED_FV_INFO          FvInfo[1];
};

To avoid TOCTOU issue, all FVs to be verified will be copied to memory
before hash calculation. That also means this driver has to be run after
permanent memory has been discovered.

For a measured boot, this driver will install

  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid

to report digest of each FV to TCG driver.

For a verified boot, this driver will verify the final hash value
(calculated from the concatenation of each FV's hash) for indicated
FVs against the hash got from platform/hardware.

If pass, it will build EFI_HOB_TYPE_FV (consumed by DXE core) and/or
install gEfiPeiFirmwareVolumeInfoPpiGuid (consumed by PEI core), and
then report status code PcdStatusCodeFvVerificationPass.

If fail, it just report status code PcdStatusCodeFvVerificationFail
and go to dead loop if status report returns.

The platform can register customized handler to process pass and fail
cases differently.

Currently, this driver only supports hash (sha256/384/512) verification
for the performance consideration.

Cc: Chao Zhang <chao.b.zhang@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: "Hernandez Beltran, Jorge" <jorge.hernandez.beltran@intel.com>
Cc: Harry Han <harry.han@intel.com>
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Chao Zhang <chao.b.zhang@intel.com>
SecurityPkg/FvReportPei/FvReportPei.c [new file with mode: 0644]
SecurityPkg/FvReportPei/FvReportPei.h [new file with mode: 0644]
SecurityPkg/FvReportPei/FvReportPei.inf [new file with mode: 0644]
SecurityPkg/FvReportPei/FvReportPei.uni [new file with mode: 0644]
SecurityPkg/FvReportPei/FvReportPeiPeiExtra.uni [new file with mode: 0644]

diff --git a/SecurityPkg/FvReportPei/FvReportPei.c b/SecurityPkg/FvReportPei/FvReportPei.c
new file mode 100644 (file)
index 0000000..c3cf221
--- /dev/null
@@ -0,0 +1,424 @@
+/** @file\r
+  This driver verifies and reports OBB FVs.\r
+\r
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "FvReportPei.h"\r
+\r
+STATIC CONST HASH_ALG_INFO mHashAlgInfo[] = {\r
+  {TPM_ALG_SHA256, SHA256_DIGEST_SIZE, Sha256Init, Sha256Update, Sha256Final, Sha256HashAll}, // 000B\r
+  {TPM_ALG_SHA384, SHA384_DIGEST_SIZE, Sha384Init, Sha384Update, Sha384Final, Sha384HashAll}, // 000C\r
+  {TPM_ALG_SHA512, SHA512_DIGEST_SIZE, Sha512Init, Sha512Update, Sha512Final, Sha512HashAll}, // 000D\r
+};\r
+\r
+/**\r
+  Find hash algorithm information from mHashAlgInfo according to given ID.\r
+\r
+  @param[in]  HashAlgoId          Hash algorithm type id.\r
+\r
+  @retval Pointer to HASH_ALG_INFO if given hash algorithm is supported.\r
+  @retval NULL if given algorithm is not supported.\r
+**/\r
+STATIC\r
+CONST\r
+HASH_ALG_INFO *\r
+FindHashAlgInfo (\r
+  IN UINT16         HashAlgId\r
+  )\r
+{\r
+  UINTN             Index;\r
+\r
+  for (Index = 0; Index < ARRAY_SIZE (mHashAlgInfo); ++Index) {\r
+    if (mHashAlgInfo[Index].HashAlgId == HashAlgId) {\r
+      return &mHashAlgInfo[Index];\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Install a EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI instance so that\r
+  TCG driver may use to extend PCRs.\r
+\r
+  @param[in]  FvBuffer            Buffer containing the whole FV.\r
+  @param[in]  FvLength            Length of the FV.\r
+  @param[in]  HashAlgoId          Hash algorithm type id.\r
+  @param[in]  HashSize            Hash size.\r
+  @param[in]  HashValue           Hash value buffer.\r
+**/\r
+STATIC\r
+VOID\r
+InstallPreHashFvPpi (\r
+  IN VOID           *FvBuffer,\r
+  IN UINTN          FvLength,\r
+  IN UINT16         HashAlgoId,\r
+  IN UINT16         HashSize,\r
+  IN UINT8          *HashValue\r
+  )\r
+{\r
+  EFI_STATUS                                        Status;\r
+  EFI_PEI_PPI_DESCRIPTOR                            *FvInfoPpiDescriptor;\r
+  EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI   *PreHashedFvPpi;\r
+  UINTN                                             PpiSize;\r
+  HASH_INFO                                         *HashInfo;\r
+\r
+  PpiSize = sizeof (EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI)\r
+            + sizeof (sizeof (HASH_INFO))\r
+            + HashSize;\r
+\r
+  PreHashedFvPpi = AllocatePool (PpiSize);\r
+  ASSERT (PreHashedFvPpi != NULL);\r
+\r
+  PreHashedFvPpi->FvBase    = (UINT32)(UINTN)FvBuffer;\r
+  PreHashedFvPpi->FvLength  = (UINT32)FvLength;\r
+  PreHashedFvPpi->Count     = 1;\r
+\r
+  HashInfo = HASH_INFO_PTR (PreHashedFvPpi);\r
+  HashInfo->HashAlgoId = HashAlgoId;\r
+  HashInfo->HashSize = HashSize;\r
+  CopyMem (HASH_VALUE_PTR (HashInfo), HashValue, HashSize);\r
+\r
+  FvInfoPpiDescriptor = AllocatePool (sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
+  ASSERT (FvInfoPpiDescriptor != NULL);\r
+\r
+  FvInfoPpiDescriptor->Guid  = &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid;\r
+  FvInfoPpiDescriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;\r
+  FvInfoPpiDescriptor->Ppi   = (VOID *) PreHashedFvPpi;\r
+\r
+  Status = PeiServicesInstallPpi (FvInfoPpiDescriptor);\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Calculate and verify hash value for given FV.\r
+\r
+  @param[in]  HashInfo            Hash information of the FV.\r
+  @param[in]  FvInfo              Information of FV used for verification.\r
+  @param[in]  FvNumber            Length of the FV.\r
+  @param[in]  BootMode            Length of the FV.\r
+\r
+  @retval EFI_SUCCESS           The given FV is integrate.\r
+  @retval EFI_VOLUME_CORRUPTED  The given FV is corrupted (hash mismatch).\r
+  @retval EFI_UNSUPPORTED       The hash algorithm is not supported.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+VerifyHashedFv (\r
+  IN FV_HASH_INFO         *HashInfo,\r
+  IN HASHED_FV_INFO       *FvInfo,\r
+  IN UINTN                FvNumber,\r
+  IN EFI_BOOT_MODE        BootMode\r
+  )\r
+{\r
+  UINTN                 FvIndex;\r
+  CONST HASH_ALG_INFO   *AlgInfo;\r
+  UINT8                 *HashValue;\r
+  UINT8                 *FvHashValue;\r
+  VOID                  *FvBuffer;\r
+  EFI_STATUS            Status;\r
+\r
+  if (HashInfo == NULL ||\r
+      HashInfo->HashSize == 0 ||\r
+      HashInfo->HashAlgoId == TPM_ALG_NULL) {\r
+    DEBUG ((DEBUG_INFO, "Bypass FV hash verification\r\n"));\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  AlgInfo = FindHashAlgInfo (HashInfo->HashAlgoId);\r
+  if (AlgInfo == NULL || AlgInfo->HashSize != HashInfo->HashSize) {\r
+    DEBUG ((DEBUG_ERROR, "Unsupported or wrong hash algorithm: %04X (size=%d)\r\n",\r
+            HashInfo->HashAlgoId, HashInfo->HashSize));\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  ASSERT (FvInfo != NULL);\r
+  ASSERT (FvNumber > 0);\r
+\r
+  //\r
+  // We need a hash value for each FV as well as one for all FVs.\r
+  //\r
+  HashValue = AllocateZeroPool (AlgInfo->HashSize * (FvNumber + 1));\r
+  ASSERT (HashValue != NULL);\r
+\r
+  //\r
+  // Calcuate hash value for each FV first.\r
+  //\r
+  FvHashValue = HashValue;\r
+  for (FvIndex = 0; FvIndex < FvNumber; ++FvIndex) {\r
+    //\r
+    // FV must be meant for verified boot and/or measured boot.\r
+    //\r
+    ASSERT ((FvInfo[FvIndex].Flag & HASHED_FV_FLAG_VERIFIED_BOOT) != 0 ||\r
+            (FvInfo[FvIndex].Flag & HASHED_FV_FLAG_MEASURED_BOOT) != 0);\r
+\r
+    //\r
+    // Skip any FV not meant for current boot mode.\r
+    //\r
+    if ((FvInfo[FvIndex].Flag & HASHED_FV_FLAG_SKIP_BOOT_MODE (BootMode)) != 0) {\r
+      DEBUG ((DEBUG_INFO, "Skip FV[%016lX] for boot mode[%d]\r\n",\r
+              FvInfo[FvIndex].Base, BootMode));\r
+      continue;\r
+    }\r
+\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "Pre-hashed[alg=%04X,size=%d,flag=%016lX] FV: 0x%016lX (%08lX) (Flag=%016lX)\r\n",\r
+      HashInfo->HashAlgoId,\r
+      HashInfo->HashSize,\r
+      HashInfo->HashFlag,\r
+      FvInfo[FvIndex].Base,\r
+      FvInfo[FvIndex].Length,\r
+      FvInfo[FvIndex].Flag\r
+      ));\r
+\r
+    //\r
+    // Copy FV to permanent memory to avoid potential TOC/TOU.\r
+    //\r
+    FvBuffer = AllocatePages (EFI_SIZE_TO_PAGES((UINTN)FvInfo[FvIndex].Length));\r
+    ASSERT (FvBuffer != NULL);\r
+    CopyMem (FvBuffer, (CONST VOID *)(UINTN)FvInfo[FvIndex].Base, (UINTN)FvInfo[FvIndex].Length);\r
+\r
+    if (!AlgInfo->HashAll (FvBuffer, (UINTN)FvInfo[FvIndex].Length, FvHashValue)) {\r
+      Status = EFI_ABORTED;\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // Report the FV measurement.\r
+    //\r
+    if ((FvInfo[FvIndex].Flag & HASHED_FV_FLAG_MEASURED_BOOT) != 0) {\r
+      InstallPreHashFvPpi (\r
+        FvBuffer,\r
+        (UINTN)FvInfo[FvIndex].Length,\r
+        HashInfo->HashAlgoId,\r
+        HashInfo->HashSize,\r
+        FvHashValue\r
+        );\r
+    }\r
+\r
+    //\r
+    // Don't keep the hash value of current FV if we don't need to verify it.\r
+    //\r
+    if ((FvInfo[FvIndex].Flag & HASHED_FV_FLAG_VERIFIED_BOOT) != 0) {\r
+      FvHashValue += AlgInfo->HashSize;\r
+    }\r
+\r
+    //\r
+    // Use memory copy of the FV from now on.\r
+    //\r
+    FvInfo[FvIndex].Base = (UINT64)(UINTN)FvBuffer;\r
+  }\r
+\r
+  //\r
+  // Check final hash for all FVs.\r
+  //\r
+  if (FvHashValue == HashValue ||\r
+      (AlgInfo->HashAll (HashValue, FvHashValue - HashValue, FvHashValue) &&\r
+       CompareMem (HashInfo->Hash, FvHashValue, AlgInfo->HashSize) == 0)) {\r
+    Status = EFI_SUCCESS;\r
+  } else {\r
+    Status = EFI_VOLUME_CORRUPTED;\r
+  }\r
+\r
+Done:\r
+  FreePool (HashValue);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Report FV to PEI and/or DXE core for dispatch.\r
+\r
+  @param[in] FvInfo     Information of a FV.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+ReportHashedFv (\r
+  IN HASHED_FV_INFO       *FvInfo\r
+  )\r
+{\r
+  CONST EFI_GUID    *FvFormat;\r
+\r
+  if ((FvInfo->Flag & HASHED_FV_FLAG_REPORT_FV_HOB) != 0) {\r
+    //\r
+    // Require DXE core to process this FV.\r
+    //\r
+    BuildFvHob (\r
+      (EFI_PHYSICAL_ADDRESS)FvInfo->Base,\r
+      FvInfo->Length\r
+      );\r
+    DEBUG ((DEBUG_INFO, "Reported FV HOB: %016lX (%08lX)\r\n", FvInfo->Base, FvInfo->Length));\r
+  }\r
+\r
+  if ((FvInfo->Flag & HASHED_FV_FLAG_REPORT_FV_INFO_PPI) != 0) {\r
+    //\r
+    // Require PEI core to process this FV.\r
+    //\r
+    FvFormat = &((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvInfo->Base)->FileSystemGuid;\r
+    PeiServicesInstallFvInfoPpi (\r
+      FvFormat,\r
+      (VOID *)(UINTN)FvInfo->Base,\r
+      (UINT32)FvInfo->Length,\r
+      NULL,\r
+      NULL\r
+      );\r
+    DEBUG ((DEBUG_INFO, "Reported FV PPI: %016lX (%08lX)\r\n", FvInfo->Base, FvInfo->Length));\r
+  }\r
+}\r
+\r
+/**\r
+  Verify and report pre-hashed FVs.\r
+\r
+  Doing this must be at post-memory to make sure there's enough memory to hold\r
+  all FVs to be verified. This is necessary for mitigating TOCTOU issue.\r
+\r
+  This function will never return if the verification is failed.\r
+\r
+  @param[in] StoredHashFvPpi  Pointer to PPI containing hash information.\r
+  @param[in] BootMode         Current boot mode.\r
+\r
+  @retval Pointer to structure containning valid hash information for current boot mode.\r
+  @retval NULL if there's no hash associated with current boot mode.\r
+**/\r
+STATIC\r
+FV_HASH_INFO *\r
+GetHashInfo (\r
+  IN EDKII_PEI_FIRMWARE_VOLUME_INFO_STORED_HASH_FV_PPI  *StoredHashFvPpi,\r
+  IN EFI_BOOT_MODE                                      BootMode\r
+  )\r
+{\r
+  FV_HASH_INFO            *HashInfo;\r
+\r
+  if ((StoredHashFvPpi->HashInfo.HashFlag & FV_HASH_FLAG_BOOT_MODE (BootMode)) != 0) {\r
+    HashInfo = &StoredHashFvPpi->HashInfo;\r
+  } else {\r
+    HashInfo = NULL;\r
+  }\r
+\r
+  return HashInfo;\r
+}\r
+\r
+/**\r
+  Verify and report pre-hashed FVs.\r
+\r
+  Doing this must be at post-memory to make sure there's enough memory to hold\r
+  all FVs to be verified. This is necessary for mitigating TOCTOU issue.\r
+\r
+  This function will never return if the verification is failed.\r
+\r
+  @param[in] PeiServices      General purpose services available to every PEIM.\r
+  @param[in] BootMode         Current boot mode.\r
+\r
+  @retval EFI_SUCCESS         The function completed successfully.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+CheckStoredHashFv (\r
+  IN CONST EFI_PEI_SERVICES           **PeiServices,\r
+  IN EFI_BOOT_MODE                    BootMode\r
+  )\r
+{\r
+  EFI_STATUS                                            Status;\r
+  EDKII_PEI_FIRMWARE_VOLUME_INFO_STORED_HASH_FV_PPI     *StoredHashFvPpi;\r
+  FV_HASH_INFO                                          *HashInfo;\r
+  UINTN                                                 FvIndex;\r
+\r
+  //\r
+  // Check pre-hashed FV list\r
+  //\r
+  StoredHashFvPpi = NULL;\r
+  Status = PeiServicesLocatePpi (\r
+             &gEdkiiPeiFirmwareVolumeInfoStoredHashFvPpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID**)&StoredHashFvPpi\r
+             );\r
+  if (!EFI_ERROR(Status) && StoredHashFvPpi != NULL && StoredHashFvPpi->FvNumber > 0) {\r
+\r
+    HashInfo = GetHashInfo (StoredHashFvPpi, BootMode);\r
+    Status = VerifyHashedFv (HashInfo, StoredHashFvPpi->FvInfo,\r
+                             StoredHashFvPpi->FvNumber, BootMode);\r
+    if (!EFI_ERROR (Status)) {\r
+\r
+      //\r
+      // Report the FVs to PEI core and/or DXE core.\r
+      //\r
+      for (FvIndex = 0; FvIndex < StoredHashFvPpi->FvNumber; ++FvIndex) {\r
+        if ((StoredHashFvPpi->FvInfo[FvIndex].Flag\r
+             & HASHED_FV_FLAG_SKIP_BOOT_MODE (BootMode)) == 0) {\r
+          ReportHashedFv (&StoredHashFvPpi->FvInfo[FvIndex]);\r
+        }\r
+      }\r
+\r
+      REPORT_STATUS_CODE (\r
+        EFI_PROGRESS_CODE,\r
+        PcdGet32 (PcdStatusCodeFvVerificationPass)\r
+        );\r
+\r
+    } else {\r
+\r
+      DEBUG ((DEBUG_ERROR, "ERROR: Failed to verify OBB FVs (%r)\r\n", Status));\r
+\r
+      REPORT_STATUS_CODE_EX (\r
+        EFI_PROGRESS_CODE,\r
+        PcdGet32 (PcdStatusCodeFvVerificationFail),\r
+        0,\r
+        NULL,\r
+        &gEdkiiPeiFirmwareVolumeInfoStoredHashFvPpiGuid,\r
+        StoredHashFvPpi,\r
+        sizeof (*StoredHashFvPpi)\r
+        );\r
+\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+    }\r
+\r
+  } else {\r
+\r
+    DEBUG ((DEBUG_ERROR, "ERROR: No/invalid StoredHashFvPpi located\r\n"));\r
+\r
+    ASSERT_EFI_ERROR (Status);\r
+    ASSERT (StoredHashFvPpi != NULL && StoredHashFvPpi->FvNumber > 0);\r
+\r
+    Status = EFI_NOT_FOUND;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Main entry for FvReport PEIM.\r
+\r
+  @param[in]  FileHandle              Handle of the file being invoked.\r
+  @param[in]  PeiServices             Pointer to PEI Services table.\r
+\r
+  @retval EFI_SUCCESS  If all FVs reported by StoredHashFvPpi are verified.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FvReportEntryPoint (\r
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  EFI_BOOT_MODE        BootMode;\r
+\r
+  Status = PeiServicesGetBootMode (&BootMode);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = CheckStoredHashFv (PeiServices, BootMode);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Never pass control to left part of BIOS if any error.\r
+    //\r
+    CpuDeadLoop ();\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/SecurityPkg/FvReportPei/FvReportPei.h b/SecurityPkg/FvReportPei/FvReportPei.h
new file mode 100644 (file)
index 0000000..aa35d2d
--- /dev/null
@@ -0,0 +1,122 @@
+/** @file\r
+  Definitions for OBB FVs verification.\r
+\r
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef __FV_REPORT_PEI_H__\r
+#define __FV_REPORT_PEI_H__\r
+\r
+#include <PiPei.h>\r
+\r
+#include <IndustryStandard/Tpm20.h>\r
+\r
+#include <Ppi/FirmwareVolumeInfoStoredHashFv.h>\r
+\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseCryptLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+\r
+#define HASH_INFO_PTR(PreHashedFvPpi)  \\r
+  (HASH_INFO *)((UINT8 *)(PreHashedFvPpi) + sizeof (EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI))\r
+\r
+#define HASH_VALUE_PTR(HashInfo)   \\r
+  (VOID *)((UINT8 *)(HashInfo) + sizeof (HASH_INFO))\r
+\r
+/**\r
+  Computes the message digest of a input data buffer.\r
+\r
+  This function performs message digest of a given data buffer, and places\r
+  the digest value into the specified memory.\r
+\r
+  If this interface is not supported, then return FALSE.\r
+\r
+  @param[in]   Data        Pointer to the buffer containing the data to be hashed.\r
+  @param[in]   DataSize    Size of Data buffer in bytes.\r
+  @param[out]  HashValue   Pointer to a buffer that receives digest value.\r
+\r
+  @retval TRUE   The digest computation succeeded.\r
+  @retval FALSE  The digest computation failed.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_ALL_METHOD) (\r
+  IN   CONST VOID  *Data,\r
+  IN   UINTN       DataSize,\r
+  OUT  UINT8       *HashValue\r
+  );\r
+\r
+/**\r
+  Initializes user-supplied memory as hash context for subsequent use.\r
+\r
+  @param[out]  HashContext  Pointer to hash context being initialized.\r
+\r
+  @retval TRUE   Hash context initialization succeeded.\r
+  @retval FALSE  Hash context initialization failed.\r
+  @retval FALSE  This interface is not supported.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_INIT_METHOD) (\r
+  OUT  VOID  *HashContext\r
+  );\r
+\r
+/**\r
+  Digests the input data and updates hash context.\r
+\r
+  @param[in, out]  HashContext  Pointer to the hash context.\r
+  @param[in]       Data         Pointer to the buffer containing the data to be hashed.\r
+  @param[in]       DataSize     Size of Data buffer in bytes.\r
+\r
+  @retval TRUE   Hash data digest succeeded.\r
+  @retval FALSE  Hash data digest failed.\r
+  @retval FALSE  This interface is not supported.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_UPDATE_METHOD) (\r
+  IN OUT  VOID        *HashContext,\r
+  IN      CONST VOID  *Data,\r
+  IN      UINTN       DataSize\r
+  );\r
+\r
+/**\r
+  Completes computation of the hash digest value.\r
+\r
+  @param[in, out]  HashContext  Pointer to the hash context.\r
+  @param[out]      HashValue    Pointer to a buffer that receives the hash digest\r
+                                value.\r
+\r
+  @retval TRUE   Hash digest computation succeeded.\r
+  @retval FALSE  Hash digest computation failed.\r
+  @retval FALSE  This interface is not supported.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_FINAL_METHOD) (\r
+  IN OUT  VOID   *HashContext,\r
+  OUT     UINT8  *HashValue\r
+  );\r
+\r
+typedef struct {\r
+  UINT16              HashAlgId;\r
+  UINTN               HashSize;\r
+  HASH_INIT_METHOD    HashInit;\r
+  HASH_UPDATE_METHOD  HashUpdate;\r
+  HASH_FINAL_METHOD   HashFinal;\r
+  HASH_ALL_METHOD     HashAll;\r
+} HASH_ALG_INFO;\r
+\r
+#endif //__FV_REPORT_PEI_H__\r
+\r
diff --git a/SecurityPkg/FvReportPei/FvReportPei.inf b/SecurityPkg/FvReportPei/FvReportPei.inf
new file mode 100644 (file)
index 0000000..4084068
--- /dev/null
@@ -0,0 +1,58 @@
+## @file\r
+# FV Report/Verify PEI Driver.\r
+#\r
+# Copyright (c) 2019, 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                      = FvReportPei\r
+  MODULE_UNI_FILE                = FvReportPei.uni\r
+  FILE_GUID                      = 72405B40-38DA-4ABA-9283-CA8321C23E63\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = FvReportEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  FvReportPei.c\r
+  FvReportPei.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+  PeimEntryPoint\r
+  PeiServicesLib\r
+  BaseLib\r
+  DebugLib\r
+  BaseMemoryLib\r
+  PcdLib\r
+  HobLib\r
+  MemoryAllocationLib\r
+  BaseCryptLib\r
+  ReportStatusCodeLib\r
+\r
+[Ppis]\r
+  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid   ## PRODUCES\r
+  gEdkiiPeiFirmwareVolumeInfoStoredHashFvPpiGuid  ## CONSUMES\r
+\r
+[Pcd]\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationPass\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationFail\r
+\r
+[Depex]\r
+  gEdkiiPeiFirmwareVolumeInfoStoredHashFvPpiGuid AND gEfiPeiMemoryDiscoveredPpiGuid\r
+\r
+[UserExtensions.TianoCore."ExtraFiles"]\r
+  FvReportPeiPeiExtra.uni\r
diff --git a/SecurityPkg/FvReportPei/FvReportPei.uni b/SecurityPkg/FvReportPei/FvReportPei.uni
new file mode 100644 (file)
index 0000000..bad4340
--- /dev/null
@@ -0,0 +1,14 @@
+// /** @file\r
+// FV Verify/Report PEI Driver.\r
+//\r
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+// SPDX-License-Identifier: BSD-2-Clause-Patent\r
+//\r
+// **/\r
+\r
+\r
+#string STR_MODULE_ABSTRACT             #language en-US "This module verifies and reports FVs."\r
+\r
+#string STR_MODULE_DESCRIPTION          #language en-US "This module verifies FVs' digest passed through gEdkiiPeiFirmwareVolumeInfoStoredHashFvPpiGuid, "\r
+                                                        "and installs gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid, gEfiPeiFirmwareVolumeInfoPpiGuid and/or FV HOB if passed."\r
+\r
diff --git a/SecurityPkg/FvReportPei/FvReportPeiPeiExtra.uni b/SecurityPkg/FvReportPei/FvReportPeiPeiExtra.uni
new file mode 100644 (file)
index 0000000..6214bbd
--- /dev/null
@@ -0,0 +1,12 @@
+// /** @file\r
+// FV Verify/Report PEI Driver.\r
+//\r
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+// SPDX-License-Identifier: BSD-2-Clause-Patent\r
+//\r
+// **/\r
+\r
+#string STR_PROPERTIES_MODULE_NAME\r
+#language en-US "FV Verify/Report PEI Driver"\r
+\r
+\r