[edk2] [PATCH V2] SecurityPkg\Tcg2Pei: FV measure performance enhancement

Zhang, Chao B posted 1 patch 6 years, 6 months ago
Failed in applying to current master (apply log)
.../Include/Ppi/FirmwareVolumeInfoPrehashedFV.h    |  70 ++++++
SecurityPkg/SecurityPkg.dec                        |   7 +-
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c                  | 245 +++++++++++++++------
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf                |   2 +
4 files changed, 250 insertions(+), 74 deletions(-)
create mode 100644 SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
[edk2] [PATCH V2] SecurityPkg\Tcg2Pei: FV measure performance enhancement
Posted by Zhang, Chao B 6 years, 6 months ago
1. Leverage Pre-Hashed FV PPI to reduce duplicated hash
2. Only measure BFV at the beginning. Other FVs are measured in FVinfo callback with nested
   FV check. https://bugzilla.tianocore.org/show_bug.cgi?id=662

Cc: Long Qin <qin.long@intel.com>
Cc: Yao Jiewen <jiewen.yao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
---
 .../Include/Ppi/FirmwareVolumeInfoPrehashedFV.h    |  70 ++++++
 SecurityPkg/SecurityPkg.dec                        |   7 +-
 SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c                  | 245 +++++++++++++++------
 SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf                |   2 +
 4 files changed, 250 insertions(+), 74 deletions(-)
 create mode 100644 SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h

diff --git a/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h b/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
new file mode 100644
index 0000000..2273357
--- /dev/null
+++ b/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
@@ -0,0 +1,70 @@
+/** @file
+PPI to describe all hash digests for a given FV
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+/**
+PPI to describe all hash digests for a given FV
+
+Copyright (c) 2017, Microsoft Corporation
+
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_H__
+#define __PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_H__
+
+#define EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI_GUID \
+ { 0x3ce1e631, 0x7008, 0x477c, { 0xad, 0xa7, 0x5d, 0xcf, 0xc7, 0xc1, 0x49, 0x4b } }
+
+//
+// HashAlgoId is TPM_ALG_ID in Tpm20.h
+//
+typedef struct _HASH_INFO {
+  UINT16                                     HashAlgoId;
+  UINT16                                     HashSize;
+  //UINT8                                    Hash[];
+} HASH_INFO;
+
+//
+// This PPI indicates a FV is already hashed, platform should ensure 1:1 mapping between pre-hashed PPI and FV.
+// The Count field in PPI is followed by Count number of FV hash info entries, which can be extended to PCR and logged to TCG event log directly by TCG modules.
+//
+typedef struct {
+  UINT32                                     FvBase;
+  UINT32                                     FvLength;
+  UINT32                                     Count;
+  //HASH_INFO                                HashInfo[];
+} EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI;
+
+extern EFI_GUID gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid;
+
+#endif
+
diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index 7a900dc..45d95c5 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -7,6 +7,7 @@
 #
 # Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
 # (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR>
+# Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
 # This program and the accompanying materials are licensed and made available under
 # the terms and conditions of the BSD License which accompanies this distribution.
 # The full text of the license may be found at
@@ -222,6 +223,9 @@
   ## Include/Ppi/FirmwareVolumeInfoMeasurementExcluded.h
   gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid = { 0x6e056ff9, 0xc695, 0x4364, { 0x9e, 0x2c, 0x61, 0x26, 0xf5, 0xce, 0xea, 0xae } }
 
+  ## Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
+  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid = { 0x3ce1e631, 0x7008, 0x477c, { 0xad, 0xa7, 0x5d, 0xcf, 0xc7, 0xc1, 0x49, 0x4b } }
+
 #
 # [Error.gEfiSecurityPkgTokenSpaceGuid]
 #   0x80000001 | Invalid value provided.
@@ -452,9 +456,10 @@
 
 [PcdsDynamic, PcdsDynamicEx]
 
-  ## This PCD indicates Hash mask for TPM 2.0.<BR><BR>
+  ## This PCD indicates Hash mask for TPM 2.0. Bit definition strictly follows TCG Algorithm Registry.<BR><BR>
   #  If this bit is set, that means this algorithm is needed to extend to PCR.<BR>
   #  If this bit is clear, that means this algorithm is NOT needed to extend to PCR.<BR>
+  #  If all the bits are clear, that means hash algorithm is determined by current Active PCR Banks.<BR>
   #    BIT0  -  SHA1.<BR>
   #    BIT1  -  SHA256.<BR>
   #    BIT2  -  SHA384.<BR>
diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
index 69adad4..a7ae335 100644
--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
+++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
@@ -2,6 +2,7 @@
   Initialize TPM2 device and measure FVs before handing off control to DXE.
 
 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
 This program and the accompanying materials 
 are licensed and made available under the terms and conditions of the BSD License 
 which accompanies this distribution.  The full text of the license may be found at 
@@ -22,6 +23,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Ppi/FirmwareVolume.h>
 #include <Ppi/EndOfPeiPhase.h>
 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
+#include <Ppi/FirmwareVolumeInfoPrehashedFV.h>
 
 #include <Guid/TcgEventHob.h>
 #include <Guid/MeasuredFvHob.h>
@@ -133,7 +135,6 @@ EFI_PEI_NOTIFY_DESCRIPTOR           mNotifyList[] = {
   }
 };
 
-EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;
 
 /**
   Record all measured Firmware Volum Information into a Guid Hob
@@ -215,6 +216,13 @@ SyncPcrAllocationsAndPcrMask (
   ASSERT_EFI_ERROR (Status);
 
   Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
+  if (Tpm2PcrMask == 0) {
+    //
+    // if PcdTPm2HashMask is zero, use ActivePcr setting
+    //
+    PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
+    Tpm2PcrMask = TpmActivePcrBanks;
+  }
 
   //
   // Find the intersection of Pcd support and TPM support.
@@ -455,53 +463,152 @@ MeasureFvImage (
   IN UINT64                         FvLength
   )
 {
-  UINT32                            Index;
-  EFI_STATUS                        Status;
-  EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;
-  TCG_PCR_EVENT_HDR                 TcgEventHdr;
-
-  //
-  // Check if it is in Excluded FV list
-  //
-  if (mMeasurementExcludedFvPpi != NULL) {
-    for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
-      if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
-        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
-        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
-        return EFI_SUCCESS;
+  UINT32                                                Index;
+  EFI_STATUS                                            Status;
+  EFI_PLATFORM_FIRMWARE_BLOB                            FvBlob;
+  TCG_PCR_EVENT_HDR                                     TcgEventHdr;
+  UINT32                                                Instance;
+  UINT32                                                Tpm2HashMask;
+  TPML_DIGEST_VALUES                                    DigestList;
+  UINT32                                                DigestCount;
+  EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
+  EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI       *PrehashedFvPpi;
+  HASH_INFO                                             *PreHashInfo;
+  UINT32                                                HashAlgoMask;
+
+  //
+  // Check Excluded FV list
+  //
+  Instance = 0;
+  do {
+    Status = PeiServicesLocatePpi(
+                 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
+                 Instance,
+                 NULL,
+                 (VOID**)&MeasurementExcludedFvPpi
+                 );
+    if (!EFI_ERROR(Status)) {
+      for (Index = 0; Index < MeasurementExcludedFvPpi->Count; Index ++) {
+        if (MeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase
+         && MeasurementExcludedFvPpi->Fv[Index].FvLength == FvLength) {
+          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
+          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
+          return EFI_SUCCESS;
+        }
       }
+
+      Instance++;
     }
-  }
+  } while (!EFI_ERROR(Status));
 
   //
-  // Check whether FV is in the measured FV list.
+  // Check measured FV list
   //
   for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
-    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
+    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase && mMeasuredBaseFvInfo[Index].BlobLength == FvLength) {
+      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase));
+      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength));
       return EFI_SUCCESS;
     }
   }
-  
+
   //
-  // Measure and record the FV to the TPM
+  // Check pre-hashed FV list
   //
-  FvBlob.BlobBase   = FvBase;
-  FvBlob.BlobLength = FvLength;
+  Instance     = 0;
+  Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);
+  do {
+    Status = PeiServicesLocatePpi (
+               &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid,
+               Instance,
+               NULL,
+               (VOID**)&PrehashedFvPpi
+               );
+    if (!EFI_ERROR(Status) && PrehashedFvPpi->FvBase == FvBase && PrehashedFvPpi->FvLength == FvLength) {
+      ZeroMem (&DigestList, sizeof(TPML_DIGEST_VALUES));
+
+      //
+      // The FV is prehashed, check against TPM hash mask
+      //
+      PreHashInfo = (HASH_INFO *)(PrehashedFvPpi + 1);
+      for (Index = 0, DigestCount = 0; Index < PrehashedFvPpi->Count; Index++) {
+        DEBUG((DEBUG_INFO, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo->HashAlgoId));
+        HashAlgoMask = GetHashMaskFromAlgo(PreHashInfo->HashAlgoId);
+        if ((Tpm2HashMask & HashAlgoMask) != 0 ) {
+          //
+          // Hash is required, copy it to DigestList
+          //
+          WriteUnaligned16(&(DigestList.digests[DigestCount].hashAlg), PreHashInfo->HashAlgoId);
+          CopyMem (
+            &DigestList.digests[DigestCount].digest,
+            PreHashInfo + 1,
+            PreHashInfo->HashSize
+            );
+          DigestCount++;
+          //
+          // Clean the corresponding Hash Algo mask bit
+          //
+          Tpm2HashMask &= ~HashAlgoMask;
+        }
+        PreHashInfo = (HASH_INFO *)((UINT8 *)(PreHashInfo + 1) + PreHashInfo->HashSize);
+      }
+
+      WriteUnaligned32(&DigestList.count, DigestCount);
 
-  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
-  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
+      break;
+    }
+    Instance++;
+  } while (!EFI_ERROR(Status));
 
-  TcgEventHdr.PCRIndex = 0;
+  //
+  // Init the log event for FV measurement
+  //
+  FvBlob.BlobBase       = FvBase;
+  FvBlob.BlobLength     = FvLength;
+  TcgEventHdr.PCRIndex  = 0;
   TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
   TcgEventHdr.EventSize = sizeof (FvBlob);
 
-  Status = HashLogExtendEvent (
-             0,
-             (UINT8*) (UINTN) FvBlob.BlobBase,
-             (UINTN) FvBlob.BlobLength,
-             &TcgEventHdr,
-             (UINT8*) &FvBlob
-             );
+  if (Tpm2HashMask == 0) {
+    //
+    // FV pre-hash algos comply with current TPM hash requirement
+    // Skip hashing step in measure, only extend DigestList to PCR and log event
+    //
+    Status = Tpm2PcrExtend(
+               0,
+               &DigestList
+               );
+
+    if (!EFI_ERROR(Status)) {
+       Status = LogHashEvent (&DigestList, &TcgEventHdr, (UINT8*) &FvBlob);
+       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
+       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
+    } else if (Status == EFI_DEVICE_ERROR) {
+      BuildGuidHob (&gTpmErrorHobGuid,0);
+      REPORT_STATUS_CODE (
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,
+        (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
+        );
+    }
+  } else {
+    //
+    // Hash the FV, extend digest to the TPM and log TCG event
+    //
+    Status = HashLogExtendEvent (
+               0,
+               (UINT8*) (UINTN) FvBlob.BlobBase,
+               (UINTN) FvBlob.BlobLength,
+               &TcgEventHdr,
+               (UINT8*) &FvBlob
+               );
+    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
+    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
+  }
+
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));
+    return Status;
+  }
 
   //
   // Add new FV into the measured FV list.
@@ -530,47 +637,44 @@ MeasureMainBios (
   )
 {
   EFI_STATUS                        Status;
-  UINT32                            FvInstances;
   EFI_PEI_FV_HANDLE                 VolumeHandle;
   EFI_FV_INFO                       VolumeInfo;
   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
 
   PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
-  FvInstances    = 0;
-  while (TRUE) {
-    //
-    // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
-    // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
-    // platform for special CRTM TPM measuring.
-    //
-    Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
-    if (EFI_ERROR (Status)) {
-      break;
-    }
-  
-    //
-    // Measure and record the firmware volume that is dispatched by PeiCore
-    //
-    Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
-    ASSERT_EFI_ERROR (Status);
-    //
-    // Locate the corresponding FV_PPI according to founded FV's format guid
-    //
-    Status = PeiServicesLocatePpi (
-               &VolumeInfo.FvFormat, 
-               0, 
-               NULL,
-               (VOID**)&FvPpi
-               );
-    if (!EFI_ERROR (Status)) {
-      MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
-    }
 
-    FvInstances++;
-  }
+  //
+  // Only measure BFV at the very beginning. Other parts of Static Core Root of
+  // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
+  // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
+  // reported by platform will be installed with Fv Info Ppi
+  // This firmware volume measure policy can be modified/enhanced by special
+  // platform for special CRTM TPM measuring.
+  //
+  Status = PeiServicesFfsFindNextVolume (0, &VolumeHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Measure and record the firmware volume that is dispatched by PeiCore
+  //
+  Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Locate the corresponding FV_PPI according to founded FV's format guid
+  //
+  Status = PeiServicesLocatePpi (
+             &VolumeInfo.FvFormat,
+             0,
+             NULL,
+             (VOID**)&FvPpi
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
+
   PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
 
-  return EFI_SUCCESS;
+  return Status;
 }
 
 /**
@@ -655,14 +759,6 @@ PeimEntryMP (
 {
   EFI_STATUS                        Status;
 
-  Status = PeiServicesLocatePpi (
-               &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, 
-               0, 
-               NULL,
-               (VOID**)&mMeasurementExcludedFvPpi
-               );
-  // Do not check status, because it is optional
-
   mMeasuredBaseFvInfo  = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
   ASSERT (mMeasuredBaseFvInfo != NULL);
   mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
@@ -673,6 +769,9 @@ PeimEntryMP (
   }
 
   Status = MeasureMainBios ();
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
 
   //
   // Post callbacks:
diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
index 1b79ee4..f7b8544 100644
--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
+++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
@@ -9,6 +9,7 @@
 #  This module will initialize TPM device, measure reported FVs and BIOS version.
 #
 # Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
 # This program and the accompanying materials
 # are licensed and made available under the terms and conditions of the BSD License
 # which accompanies this distribution. The full text of the license may be found at
@@ -75,6 +76,7 @@
   gPeiTpmInitializedPpiGuid                                            ## SOMETIMES_PRODUCES
   gPeiTpmInitializationDonePpiGuid                                     ## PRODUCES
   gEfiEndOfPeiSignalPpiGuid                                            ## SOMETIMES_CONSUMES     ## NOTIFY
+  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid                        ## SOMETIMES_CONSUMES
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString              ## SOMETIMES_CONSUMES
-- 
1.9.5.msysgit.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH V2] SecurityPkg\Tcg2Pei: FV measure performance enhancement
Posted by Long, Qin 6 years, 6 months ago
Reviewed-by: Long Qin <qin.long@intel.com>


Best Regards & Thanks,
LONG, Qin

-----Original Message-----
From: Zhang, Chao B 
Sent: Friday, October 13, 2017 3:26 PM
To: edk2-devel@lists.01.org
Cc: Long, Qin <qin.long@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; sean.brogan@microsoft.com; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: [PATCH V2] SecurityPkg\Tcg2Pei: FV measure performance enhancement

1. Leverage Pre-Hashed FV PPI to reduce duplicated hash 2. Only measure BFV at the beginning. Other FVs are measured in FVinfo callback with nested
   FV check. https://bugzilla.tianocore.org/show_bug.cgi?id=662

Cc: Long Qin <qin.long@intel.com>
Cc: Yao Jiewen <jiewen.yao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
---
 .../Include/Ppi/FirmwareVolumeInfoPrehashedFV.h    |  70 ++++++
 SecurityPkg/SecurityPkg.dec                        |   7 +-
 SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c                  | 245 +++++++++++++++------
 SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf                |   2 +
 4 files changed, 250 insertions(+), 74 deletions(-)  create mode 100644 SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h

diff --git a/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h b/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
new file mode 100644
index 0000000..2273357
--- /dev/null
+++ b/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
@@ -0,0 +1,70 @@
+/** @file
+PPI to describe all hash digests for a given FV
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR> This 
+program and the accompanying materials are licensed and made available 
+under the terms and conditions of the BSD License which accompanies 
+this distribution.  The full text of the license may be found at 
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+/**
+PPI to describe all hash digests for a given FV
+
+Copyright (c) 2017, Microsoft Corporation
+
+All rights reserved.
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright 
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright 
+notice, this list of conditions and the following disclaimer in the 
+documentation  and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_H__
+#define __PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_H__
+
+#define EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI_GUID \  { 
+0x3ce1e631, 0x7008, 0x477c, { 0xad, 0xa7, 0x5d, 0xcf, 0xc7, 0xc1, 0x49, 
+0x4b } }
+
+//
+// HashAlgoId is TPM_ALG_ID in Tpm20.h
+//
+typedef struct _HASH_INFO {
+  UINT16                                     HashAlgoId;
+  UINT16                                     HashSize;
+  //UINT8                                    Hash[];
+} HASH_INFO;
+
+//
+// This PPI indicates a FV is already hashed, platform should ensure 1:1 mapping between pre-hashed PPI and FV.
+// The Count field in PPI is followed by Count number of FV hash info entries, which can be extended to PCR and logged to TCG event log directly by TCG modules.
+//
+typedef struct {
+  UINT32                                     FvBase;
+  UINT32                                     FvLength;
+  UINT32                                     Count;
+  //HASH_INFO                                HashInfo[];
+} EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI;
+
+extern EFI_GUID gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid;
+
+#endif
+
diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec index 7a900dc..45d95c5 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -7,6 +7,7 @@
 #
 # Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>  # (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR>
+# Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
 # This program and the accompanying materials are licensed and made available under  # the terms and conditions of the BSD License which accompanies this distribution.
 # The full text of the license may be found at @@ -222,6 +223,9 @@
   ## Include/Ppi/FirmwareVolumeInfoMeasurementExcluded.h
   gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid = { 0x6e056ff9, 0xc695, 0x4364, { 0x9e, 0x2c, 0x61, 0x26, 0xf5, 0xce, 0xea, 0xae } }
 
+  ## Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
+  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid = { 0x3ce1e631, 0x7008, 
+ 0x477c, { 0xad, 0xa7, 0x5d, 0xcf, 0xc7, 0xc1, 0x49, 0x4b } }
+
 #
 # [Error.gEfiSecurityPkgTokenSpaceGuid]
 #   0x80000001 | Invalid value provided.
@@ -452,9 +456,10 @@
 
 [PcdsDynamic, PcdsDynamicEx]
 
-  ## This PCD indicates Hash mask for TPM 2.0.<BR><BR>
+  ## This PCD indicates Hash mask for TPM 2.0. Bit definition strictly 
+ follows TCG Algorithm Registry.<BR><BR>
   #  If this bit is set, that means this algorithm is needed to extend to PCR.<BR>
   #  If this bit is clear, that means this algorithm is NOT needed to extend to PCR.<BR>
+  #  If all the bits are clear, that means hash algorithm is determined 
+ by current Active PCR Banks.<BR>
   #    BIT0  -  SHA1.<BR>
   #    BIT1  -  SHA256.<BR>
   #    BIT2  -  SHA384.<BR>
diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
index 69adad4..a7ae335 100644
--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
+++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
@@ -2,6 +2,7 @@
   Initialize TPM2 device and measure FVs before handing off control to DXE.
 
 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
 This program and the accompanying materials  are licensed and made available under the terms and conditions of the BSD License  which accompanies this distribution.  The full text of the license may be found at @@ -22,6 +23,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Ppi/FirmwareVolume.h>
 #include <Ppi/EndOfPeiPhase.h>
 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
+#include <Ppi/FirmwareVolumeInfoPrehashedFV.h>
 
 #include <Guid/TcgEventHob.h>
 #include <Guid/MeasuredFvHob.h>
@@ -133,7 +135,6 @@ EFI_PEI_NOTIFY_DESCRIPTOR           mNotifyList[] = {
   }
 };
 
-EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;
 
 /**
   Record all measured Firmware Volum Information into a Guid Hob @@ -215,6 +216,13 @@ SyncPcrAllocationsAndPcrMask (
   ASSERT_EFI_ERROR (Status);
 
   Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
+  if (Tpm2PcrMask == 0) {
+    //
+    // if PcdTPm2HashMask is zero, use ActivePcr setting
+    //
+    PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
+    Tpm2PcrMask = TpmActivePcrBanks;
+  }
 
   //
   // Find the intersection of Pcd support and TPM support.
@@ -455,53 +463,152 @@ MeasureFvImage (
   IN UINT64                         FvLength
   )
 {
-  UINT32                            Index;
-  EFI_STATUS                        Status;
-  EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;
-  TCG_PCR_EVENT_HDR                 TcgEventHdr;
-
-  //
-  // Check if it is in Excluded FV list
-  //
-  if (mMeasurementExcludedFvPpi != NULL) {
-    for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
-      if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
-        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
-        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
-        return EFI_SUCCESS;
+  UINT32                                                Index;
+  EFI_STATUS                                            Status;
+  EFI_PLATFORM_FIRMWARE_BLOB                            FvBlob;
+  TCG_PCR_EVENT_HDR                                     TcgEventHdr;
+  UINT32                                                Instance;
+  UINT32                                                Tpm2HashMask;
+  TPML_DIGEST_VALUES                                    DigestList;
+  UINT32                                                DigestCount;
+  EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
+  EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI       *PrehashedFvPpi;
+  HASH_INFO                                             *PreHashInfo;
+  UINT32                                                HashAlgoMask;
+
+  //
+  // Check Excluded FV list
+  //
+  Instance = 0;
+  do {
+    Status = PeiServicesLocatePpi(
+                 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
+                 Instance,
+                 NULL,
+                 (VOID**)&MeasurementExcludedFvPpi
+                 );
+    if (!EFI_ERROR(Status)) {
+      for (Index = 0; Index < MeasurementExcludedFvPpi->Count; Index ++) {
+        if (MeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase
+         && MeasurementExcludedFvPpi->Fv[Index].FvLength == FvLength) {
+          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
+          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
+          return EFI_SUCCESS;
+        }
       }
+
+      Instance++;
     }
-  }
+  } while (!EFI_ERROR(Status));
 
   //
-  // Check whether FV is in the measured FV list.
+  // Check measured FV list
   //
   for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
-    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
+    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase && mMeasuredBaseFvInfo[Index].BlobLength == FvLength) {
+      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase));
+      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei 
+ has the size: 0x%x\n", FvLength));
       return EFI_SUCCESS;
     }
   }
-  
+
   //
-  // Measure and record the FV to the TPM
+  // Check pre-hashed FV list
   //
-  FvBlob.BlobBase   = FvBase;
-  FvBlob.BlobLength = FvLength;
+  Instance     = 0;
+  Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);  do {
+    Status = PeiServicesLocatePpi (
+               &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid,
+               Instance,
+               NULL,
+               (VOID**)&PrehashedFvPpi
+               );
+    if (!EFI_ERROR(Status) && PrehashedFvPpi->FvBase == FvBase && PrehashedFvPpi->FvLength == FvLength) {
+      ZeroMem (&DigestList, sizeof(TPML_DIGEST_VALUES));
+
+      //
+      // The FV is prehashed, check against TPM hash mask
+      //
+      PreHashInfo = (HASH_INFO *)(PrehashedFvPpi + 1);
+      for (Index = 0, DigestCount = 0; Index < PrehashedFvPpi->Count; Index++) {
+        DEBUG((DEBUG_INFO, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo->HashAlgoId));
+        HashAlgoMask = GetHashMaskFromAlgo(PreHashInfo->HashAlgoId);
+        if ((Tpm2HashMask & HashAlgoMask) != 0 ) {
+          //
+          // Hash is required, copy it to DigestList
+          //
+          WriteUnaligned16(&(DigestList.digests[DigestCount].hashAlg), PreHashInfo->HashAlgoId);
+          CopyMem (
+            &DigestList.digests[DigestCount].digest,
+            PreHashInfo + 1,
+            PreHashInfo->HashSize
+            );
+          DigestCount++;
+          //
+          // Clean the corresponding Hash Algo mask bit
+          //
+          Tpm2HashMask &= ~HashAlgoMask;
+        }
+        PreHashInfo = (HASH_INFO *)((UINT8 *)(PreHashInfo + 1) + PreHashInfo->HashSize);
+      }
+
+      WriteUnaligned32(&DigestList.count, DigestCount);
 
-  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
-  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
+      break;
+    }
+    Instance++;
+  } while (!EFI_ERROR(Status));
 
-  TcgEventHdr.PCRIndex = 0;
+  //
+  // Init the log event for FV measurement  //
+  FvBlob.BlobBase       = FvBase;
+  FvBlob.BlobLength     = FvLength;
+  TcgEventHdr.PCRIndex  = 0;
   TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
   TcgEventHdr.EventSize = sizeof (FvBlob);
 
-  Status = HashLogExtendEvent (
-             0,
-             (UINT8*) (UINTN) FvBlob.BlobBase,
-             (UINTN) FvBlob.BlobLength,
-             &TcgEventHdr,
-             (UINT8*) &FvBlob
-             );
+  if (Tpm2HashMask == 0) {
+    //
+    // FV pre-hash algos comply with current TPM hash requirement
+    // Skip hashing step in measure, only extend DigestList to PCR and log event
+    //
+    Status = Tpm2PcrExtend(
+               0,
+               &DigestList
+               );
+
+    if (!EFI_ERROR(Status)) {
+       Status = LogHashEvent (&DigestList, &TcgEventHdr, (UINT8*) &FvBlob);
+       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
+       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
+    } else if (Status == EFI_DEVICE_ERROR) {
+      BuildGuidHob (&gTpmErrorHobGuid,0);
+      REPORT_STATUS_CODE (
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,
+        (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
+        );
+    }
+  } else {
+    //
+    // Hash the FV, extend digest to the TPM and log TCG event
+    //
+    Status = HashLogExtendEvent (
+               0,
+               (UINT8*) (UINTN) FvBlob.BlobBase,
+               (UINTN) FvBlob.BlobLength,
+               &TcgEventHdr,
+               (UINT8*) &FvBlob
+               );
+    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
+    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the 
+ size: 0x%x\n", FvBlob.BlobLength));  }
+
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));
+    return Status;
+  }
 
   //
   // Add new FV into the measured FV list.
@@ -530,47 +637,44 @@ MeasureMainBios (
   )
 {
   EFI_STATUS                        Status;
-  UINT32                            FvInstances;
   EFI_PEI_FV_HANDLE                 VolumeHandle;
   EFI_FV_INFO                       VolumeInfo;
   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
 
   PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
-  FvInstances    = 0;
-  while (TRUE) {
-    //
-    // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
-    // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
-    // platform for special CRTM TPM measuring.
-    //
-    Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
-    if (EFI_ERROR (Status)) {
-      break;
-    }
-  
-    //
-    // Measure and record the firmware volume that is dispatched by PeiCore
-    //
-    Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
-    ASSERT_EFI_ERROR (Status);
-    //
-    // Locate the corresponding FV_PPI according to founded FV's format guid
-    //
-    Status = PeiServicesLocatePpi (
-               &VolumeInfo.FvFormat, 
-               0, 
-               NULL,
-               (VOID**)&FvPpi
-               );
-    if (!EFI_ERROR (Status)) {
-      MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
-    }
 
-    FvInstances++;
-  }
+  //
+  // Only measure BFV at the very beginning. Other parts of Static Core 
+ Root of  // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
+  // BFV is processed without installing FV Info Ppi. Other FVs either 
+ inside BFV or  // reported by platform will be installed with Fv Info 
+ Ppi  // This firmware volume measure policy can be modified/enhanced 
+ by special  // platform for special CRTM TPM measuring.
+  //
+  Status = PeiServicesFfsFindNextVolume (0, &VolumeHandle);  
+ ASSERT_EFI_ERROR (Status);
+
+  //
+  // Measure and record the firmware volume that is dispatched by 
+ PeiCore  //  Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, 
+ &VolumeInfo);  ASSERT_EFI_ERROR (Status);  //  // Locate the 
+ corresponding FV_PPI according to founded FV's format guid  //  Status 
+ = PeiServicesLocatePpi (
+             &VolumeInfo.FvFormat,
+             0,
+             NULL,
+             (VOID**)&FvPpi
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) 
+ VolumeInfo.FvStart, VolumeInfo.FvSize);
+
   PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
 
-  return EFI_SUCCESS;
+  return Status;
 }
 
 /**
@@ -655,14 +759,6 @@ PeimEntryMP (
 {
   EFI_STATUS                        Status;
 
-  Status = PeiServicesLocatePpi (
-               &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, 
-               0, 
-               NULL,
-               (VOID**)&mMeasurementExcludedFvPpi
-               );
-  // Do not check status, because it is optional
-
   mMeasuredBaseFvInfo  = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
   ASSERT (mMeasuredBaseFvInfo != NULL);
   mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported)); @@ -673,6 +769,9 @@ PeimEntryMP (
   }
 
   Status = MeasureMainBios ();
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
 
   //
   // Post callbacks:
diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
index 1b79ee4..f7b8544 100644
--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
+++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
@@ -9,6 +9,7 @@
 #  This module will initialize TPM device, measure reported FVs and BIOS version.
 #
 # Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
 # This program and the accompanying materials  # are licensed and made available under the terms and conditions of the BSD License  # which accompanies this distribution. The full text of the license may be found at @@ -75,6 +76,7 @@
   gPeiTpmInitializedPpiGuid                                            ## SOMETIMES_PRODUCES
   gPeiTpmInitializationDonePpiGuid                                     ## PRODUCES
   gEfiEndOfPeiSignalPpiGuid                                            ## SOMETIMES_CONSUMES     ## NOTIFY
+  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid                        ## SOMETIMES_CONSUMES
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString              ## SOMETIMES_CONSUMES
--
1.9.5.msysgit.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH V2] SecurityPkg\Tcg2Pei: FV measure performance enhancement
Posted by Yao, Jiewen 6 years, 6 months ago
Thank you Chao!

I have 2 minor suggestion.
1) I know you did lots of unit test.
Would you please share the information to all of us?

2) I found the pre-hash/tpm-mask mismatch case might be misunderstood.
Would you please add some comment in the ppi header file to describe the expectation clearly?

With comment update for 2) and unit test description for 1), reviewed-by jiewen.yao@intel.com

thank you!
Yao, Jiewen


> 在 2017年10月13日,下午3:26,Zhang, Chao B <chao.b.zhang@intel.com> 写道:
> 
> 1. Leverage Pre-Hashed FV PPI to reduce duplicated hash
> 2. Only measure BFV at the beginning. Other FVs are measured in FVinfo callback with nested
>   FV check. https://bugzilla.tianocore.org/show_bug.cgi?id=662
> 
> Cc: Long Qin <qin.long@intel.com>
> Cc: Yao Jiewen <jiewen.yao@intel.com>
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
> ---
> .../Include/Ppi/FirmwareVolumeInfoPrehashedFV.h    |  70 ++++++
> SecurityPkg/SecurityPkg.dec                        |   7 +-
> SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c                  | 245 +++++++++++++++------
> SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf                |   2 +
> 4 files changed, 250 insertions(+), 74 deletions(-)
> create mode 100644 SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
> 
> diff --git a/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h b/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
> new file mode 100644
> index 0000000..2273357
> --- /dev/null
> +++ b/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
> @@ -0,0 +1,70 @@
> +/** @file
> +PPI to describe all hash digests for a given FV
> +
> +Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD License
> +which accompanies this distribution.  The full text of the license may be found at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +/**
> +PPI to describe all hash digests for a given FV
> +
> +Copyright (c) 2017, Microsoft Corporation
> +
> +All rights reserved.
> +Redistribution and use in source and binary forms, with or without
> +modification, are permitted provided that the following conditions are met:
> +1. Redistributions of source code must retain the above copyright notice,
> +this list of conditions and the following disclaimer.
> +2. Redistributions in binary form must reproduce the above copyright notice,
> +this list of conditions and the following disclaimer in the documentation
> + and/or other materials provided with the distribution.
> +
> +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
> +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
> +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
> +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
> +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
> +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +**/
> +
> +#ifndef __PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_H__
> +#define __PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_H__
> +
> +#define EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI_GUID \
> + { 0x3ce1e631, 0x7008, 0x477c, { 0xad, 0xa7, 0x5d, 0xcf, 0xc7, 0xc1, 0x49, 0x4b } }
> +
> +//
> +// HashAlgoId is TPM_ALG_ID in Tpm20.h
> +//
> +typedef struct _HASH_INFO {
> +  UINT16                                     HashAlgoId;
> +  UINT16                                     HashSize;
> +  //UINT8                                    Hash[];
> +} HASH_INFO;
> +
> +//
> +// This PPI indicates a FV is already hashed, platform should ensure 1:1 mapping between pre-hashed PPI and FV.
> +// The Count field in PPI is followed by Count number of FV hash info entries, which can be extended to PCR and logged to TCG event log directly by TCG modules.
> +//
> +typedef struct {
> +  UINT32                                     FvBase;
> +  UINT32                                     FvLength;
> +  UINT32                                     Count;
> +  //HASH_INFO                                HashInfo[];
> +} EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI;
> +
> +extern EFI_GUID gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid;
> +
> +#endif
> +
> diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
> index 7a900dc..45d95c5 100644
> --- a/SecurityPkg/SecurityPkg.dec
> +++ b/SecurityPkg/SecurityPkg.dec
> @@ -7,6 +7,7 @@
> #
> # Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
> # (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR>
> +# Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
> # This program and the accompanying materials are licensed and made available under
> # the terms and conditions of the BSD License which accompanies this distribution.
> # The full text of the license may be found at
> @@ -222,6 +223,9 @@
>   ## Include/Ppi/FirmwareVolumeInfoMeasurementExcluded.h
>   gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid = { 0x6e056ff9, 0xc695, 0x4364, { 0x9e, 0x2c, 0x61, 0x26, 0xf5, 0xce, 0xea, 0xae } }
> 
> +  ## Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
> +  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid = { 0x3ce1e631, 0x7008, 0x477c, { 0xad, 0xa7, 0x5d, 0xcf, 0xc7, 0xc1, 0x49, 0x4b } }
> +
> #
> # [Error.gEfiSecurityPkgTokenSpaceGuid]
> #   0x80000001 | Invalid value provided.
> @@ -452,9 +456,10 @@
> 
> [PcdsDynamic, PcdsDynamicEx]
> 
> -  ## This PCD indicates Hash mask for TPM 2.0.<BR><BR>
> +  ## This PCD indicates Hash mask for TPM 2.0. Bit definition strictly follows TCG Algorithm Registry.<BR><BR>
>   #  If this bit is set, that means this algorithm is needed to extend to PCR.<BR>
>   #  If this bit is clear, that means this algorithm is NOT needed to extend to PCR.<BR>
> +  #  If all the bits are clear, that means hash algorithm is determined by current Active PCR Banks.<BR>
>   #    BIT0  -  SHA1.<BR>
>   #    BIT1  -  SHA256.<BR>
>   #    BIT2  -  SHA384.<BR>
> diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
> index 69adad4..a7ae335 100644
> --- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
> +++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
> @@ -2,6 +2,7 @@
>   Initialize TPM2 device and measure FVs before handing off control to DXE.
> 
> Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
> This program and the accompanying materials 
> are licensed and made available under the terms and conditions of the BSD License 
> which accompanies this distribution.  The full text of the license may be found at 
> @@ -22,6 +23,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> #include <Ppi/FirmwareVolume.h>
> #include <Ppi/EndOfPeiPhase.h>
> #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
> +#include <Ppi/FirmwareVolumeInfoPrehashedFV.h>
> 
> #include <Guid/TcgEventHob.h>
> #include <Guid/MeasuredFvHob.h>
> @@ -133,7 +135,6 @@ EFI_PEI_NOTIFY_DESCRIPTOR           mNotifyList[] = {
>   }
> };
> 
> -EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;
> 
> /**
>   Record all measured Firmware Volum Information into a Guid Hob
> @@ -215,6 +216,13 @@ SyncPcrAllocationsAndPcrMask (
>   ASSERT_EFI_ERROR (Status);
> 
>   Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
> +  if (Tpm2PcrMask == 0) {
> +    //
> +    // if PcdTPm2HashMask is zero, use ActivePcr setting
> +    //
> +    PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
> +    Tpm2PcrMask = TpmActivePcrBanks;
> +  }
> 
>   //
>   // Find the intersection of Pcd support and TPM support.
> @@ -455,53 +463,152 @@ MeasureFvImage (
>   IN UINT64                         FvLength
>   )
> {
> -  UINT32                            Index;
> -  EFI_STATUS                        Status;
> -  EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;
> -  TCG_PCR_EVENT_HDR                 TcgEventHdr;
> -
> -  //
> -  // Check if it is in Excluded FV list
> -  //
> -  if (mMeasurementExcludedFvPpi != NULL) {
> -    for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
> -      if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
> -        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
> -        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
> -        return EFI_SUCCESS;
> +  UINT32                                                Index;
> +  EFI_STATUS                                            Status;
> +  EFI_PLATFORM_FIRMWARE_BLOB                            FvBlob;
> +  TCG_PCR_EVENT_HDR                                     TcgEventHdr;
> +  UINT32                                                Instance;
> +  UINT32                                                Tpm2HashMask;
> +  TPML_DIGEST_VALUES                                    DigestList;
> +  UINT32                                                DigestCount;
> +  EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
> +  EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI       *PrehashedFvPpi;
> +  HASH_INFO                                             *PreHashInfo;
> +  UINT32                                                HashAlgoMask;
> +
> +  //
> +  // Check Excluded FV list
> +  //
> +  Instance = 0;
> +  do {
> +    Status = PeiServicesLocatePpi(
> +                 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
> +                 Instance,
> +                 NULL,
> +                 (VOID**)&MeasurementExcludedFvPpi
> +                 );
> +    if (!EFI_ERROR(Status)) {
> +      for (Index = 0; Index < MeasurementExcludedFvPpi->Count; Index ++) {
> +        if (MeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase
> +         && MeasurementExcludedFvPpi->Fv[Index].FvLength == FvLength) {
> +          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
> +          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
> +          return EFI_SUCCESS;
> +        }
>       }
> +
> +      Instance++;
>     }
> -  }
> +  } while (!EFI_ERROR(Status));
> 
>   //
> -  // Check whether FV is in the measured FV list.
> +  // Check measured FV list
>   //
>   for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
> -    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
> +    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase && mMeasuredBaseFvInfo[Index].BlobLength == FvLength) {
> +      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase));
> +      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength));
>       return EFI_SUCCESS;
>     }
>   }
> -  
> +
>   //
> -  // Measure and record the FV to the TPM
> +  // Check pre-hashed FV list
>   //
> -  FvBlob.BlobBase   = FvBase;
> -  FvBlob.BlobLength = FvLength;
> +  Instance     = 0;
> +  Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);
> +  do {
> +    Status = PeiServicesLocatePpi (
> +               &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid,
> +               Instance,
> +               NULL,
> +               (VOID**)&PrehashedFvPpi
> +               );
> +    if (!EFI_ERROR(Status) && PrehashedFvPpi->FvBase == FvBase && PrehashedFvPpi->FvLength == FvLength) {
> +      ZeroMem (&DigestList, sizeof(TPML_DIGEST_VALUES));
> +
> +      //
> +      // The FV is prehashed, check against TPM hash mask
> +      //
> +      PreHashInfo = (HASH_INFO *)(PrehashedFvPpi + 1);
> +      for (Index = 0, DigestCount = 0; Index < PrehashedFvPpi->Count; Index++) {
> +        DEBUG((DEBUG_INFO, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo->HashAlgoId));
> +        HashAlgoMask = GetHashMaskFromAlgo(PreHashInfo->HashAlgoId);
> +        if ((Tpm2HashMask & HashAlgoMask) != 0 ) {
> +          //
> +          // Hash is required, copy it to DigestList
> +          //
> +          WriteUnaligned16(&(DigestList.digests[DigestCount].hashAlg), PreHashInfo->HashAlgoId);
> +          CopyMem (
> +            &DigestList.digests[DigestCount].digest,
> +            PreHashInfo + 1,
> +            PreHashInfo->HashSize
> +            );
> +          DigestCount++;
> +          //
> +          // Clean the corresponding Hash Algo mask bit
> +          //
> +          Tpm2HashMask &= ~HashAlgoMask;
> +        }
> +        PreHashInfo = (HASH_INFO *)((UINT8 *)(PreHashInfo + 1) + PreHashInfo->HashSize);
> +      }
> +
> +      WriteUnaligned32(&DigestList.count, DigestCount);
> 
> -  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
> -  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
> +      break;
> +    }
> +    Instance++;
> +  } while (!EFI_ERROR(Status));
> 
> -  TcgEventHdr.PCRIndex = 0;
> +  //
> +  // Init the log event for FV measurement
> +  //
> +  FvBlob.BlobBase       = FvBase;
> +  FvBlob.BlobLength     = FvLength;
> +  TcgEventHdr.PCRIndex  = 0;
>   TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
>   TcgEventHdr.EventSize = sizeof (FvBlob);
> 
> -  Status = HashLogExtendEvent (
> -             0,
> -             (UINT8*) (UINTN) FvBlob.BlobBase,
> -             (UINTN) FvBlob.BlobLength,
> -             &TcgEventHdr,
> -             (UINT8*) &FvBlob
> -             );
> +  if (Tpm2HashMask == 0) {
> +    //
> +    // FV pre-hash algos comply with current TPM hash requirement
> +    // Skip hashing step in measure, only extend DigestList to PCR and log event
> +    //
> +    Status = Tpm2PcrExtend(
> +               0,
> +               &DigestList
> +               );
> +
> +    if (!EFI_ERROR(Status)) {
> +       Status = LogHashEvent (&DigestList, &TcgEventHdr, (UINT8*) &FvBlob);
> +       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
> +       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
> +    } else if (Status == EFI_DEVICE_ERROR) {
> +      BuildGuidHob (&gTpmErrorHobGuid,0);
> +      REPORT_STATUS_CODE (
> +        EFI_ERROR_CODE | EFI_ERROR_MINOR,
> +        (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
> +        );
> +    }
> +  } else {
> +    //
> +    // Hash the FV, extend digest to the TPM and log TCG event
> +    //
> +    Status = HashLogExtendEvent (
> +               0,
> +               (UINT8*) (UINTN) FvBlob.BlobBase,
> +               (UINTN) FvBlob.BlobLength,
> +               &TcgEventHdr,
> +               (UINT8*) &FvBlob
> +               );
> +    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
> +    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
> +  }
> +
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));
> +    return Status;
> +  }
> 
>   //
>   // Add new FV into the measured FV list.
> @@ -530,47 +637,44 @@ MeasureMainBios (
>   )
> {
>   EFI_STATUS                        Status;
> -  UINT32                            FvInstances;
>   EFI_PEI_FV_HANDLE                 VolumeHandle;
>   EFI_FV_INFO                       VolumeInfo;
>   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
> 
>   PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
> -  FvInstances    = 0;
> -  while (TRUE) {
> -    //
> -    // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
> -    // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
> -    // platform for special CRTM TPM measuring.
> -    //
> -    Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
> -    if (EFI_ERROR (Status)) {
> -      break;
> -    }
> -  
> -    //
> -    // Measure and record the firmware volume that is dispatched by PeiCore
> -    //
> -    Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
> -    ASSERT_EFI_ERROR (Status);
> -    //
> -    // Locate the corresponding FV_PPI according to founded FV's format guid
> -    //
> -    Status = PeiServicesLocatePpi (
> -               &VolumeInfo.FvFormat, 
> -               0, 
> -               NULL,
> -               (VOID**)&FvPpi
> -               );
> -    if (!EFI_ERROR (Status)) {
> -      MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
> -    }
> 
> -    FvInstances++;
> -  }
> +  //
> +  // Only measure BFV at the very beginning. Other parts of Static Core Root of
> +  // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
> +  // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
> +  // reported by platform will be installed with Fv Info Ppi
> +  // This firmware volume measure policy can be modified/enhanced by special
> +  // platform for special CRTM TPM measuring.
> +  //
> +  Status = PeiServicesFfsFindNextVolume (0, &VolumeHandle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Measure and record the firmware volume that is dispatched by PeiCore
> +  //
> +  Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
> +  ASSERT_EFI_ERROR (Status);
> +  //
> +  // Locate the corresponding FV_PPI according to founded FV's format guid
> +  //
> +  Status = PeiServicesLocatePpi (
> +             &VolumeInfo.FvFormat,
> +             0,
> +             NULL,
> +             (VOID**)&FvPpi
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
> +
>   PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
> 
> -  return EFI_SUCCESS;
> +  return Status;
> }
> 
> /**
> @@ -655,14 +759,6 @@ PeimEntryMP (
> {
>   EFI_STATUS                        Status;
> 
> -  Status = PeiServicesLocatePpi (
> -               &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, 
> -               0, 
> -               NULL,
> -               (VOID**)&mMeasurementExcludedFvPpi
> -               );
> -  // Do not check status, because it is optional
> -
>   mMeasuredBaseFvInfo  = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
>   ASSERT (mMeasuredBaseFvInfo != NULL);
>   mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
> @@ -673,6 +769,9 @@ PeimEntryMP (
>   }
> 
>   Status = MeasureMainBios ();
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> 
>   //
>   // Post callbacks:
> diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
> index 1b79ee4..f7b8544 100644
> --- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
> +++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
> @@ -9,6 +9,7 @@
> #  This module will initialize TPM device, measure reported FVs and BIOS version.
> #
> # Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
> # This program and the accompanying materials
> # are licensed and made available under the terms and conditions of the BSD License
> # which accompanies this distribution. The full text of the license may be found at
> @@ -75,6 +76,7 @@
>   gPeiTpmInitializedPpiGuid                                            ## SOMETIMES_PRODUCES
>   gPeiTpmInitializationDonePpiGuid                                     ## PRODUCES
>   gEfiEndOfPeiSignalPpiGuid                                            ## SOMETIMES_CONSUMES     ## NOTIFY
> +  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid                        ## SOMETIMES_CONSUMES
> 
> [Pcd]
>   gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString              ## SOMETIMES_CONSUMES
> -- 
> 1.9.5.msysgit.1
> 
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH V2] SecurityPkg\Tcg2Pei: FV measure performance enhancement
Posted by Zhang, Chao B 6 years, 6 months ago
Hi Jiewen & Qin:
     Thank you very much for all the comments. I will update PPI comments with clear wording.
     Here are all the information of white box test. The test matrix covered different algorithms combinations for Pre-hash data & Hash required for TPM. 
     All the results were expected.

      Image Pre-hash Setting	PcdTPMHashMask	     Test Result
               NONE	                                      SHA256	                     CPU calculates hash. No Pre-Hash can be found in Tcg2 Event Log
                SHA1	                                      SHA256                             CPU calculates hash. No Pre-Hash can be found in Tcg2 Event Log
         SHA1+SHA256	                       SHA256	                     Specific SHA256 produced by Pre-Hash found in TCG2 Event Log
         SHA1+SHA256	                  SHA1+SHA256              	      Specific SHA1+SHA256 produced by Pre-Hash found in TCG2 Event Log
               SHA256                                  SHA1+SHA256	                     CPU calculates Hash. No Pre-Hash can be found in Tcg2 Event Log
    SHA1+SHA256+SHA384	   SHA1+SHA256	                     Specific SHA1+SHA256 produced by Pre-Hash found in TCG2 Event Log
    
   Test case also verified PCR Extend Op Failure when using pre-hash data. TPM2 device was made invisible after failure. It complies with TCG PFP spec 00.21

-----Original Message-----
From: Yao, Jiewen 
Sent: Friday, October 13, 2017 4:55 PM
To: Zhang, Chao B <chao.b.zhang@intel.com>
Cc: edk2-devel@lists.01.org; Long, Qin <qin.long@intel.com>; sean.brogan@microsoft.com; Yao, Jiewen <jiewen.yao@intel.com>
Subject: Re: [PATCH V2] SecurityPkg\Tcg2Pei: FV measure performance enhancement

Thank you Chao!

I have 2 minor suggestion.
1) I know you did lots of unit test.
Would you please share the information to all of us?

2) I found the pre-hash/tpm-mask mismatch case might be misunderstood.
Would you please add some comment in the ppi header file to describe the expectation clearly?

With comment update for 2) and unit test description for 1), reviewed-by jiewen.yao@intel.com

thank you!
Yao, Jiewen


> 在 2017年10月13日,下午3:26,Zhang, Chao B <chao.b.zhang@intel.com> 写道:
> 
> 1. Leverage Pre-Hashed FV PPI to reduce duplicated hash 2. Only 
> measure BFV at the beginning. Other FVs are measured in FVinfo callback with nested
>   FV check. https://bugzilla.tianocore.org/show_bug.cgi?id=662
> 
> Cc: Long Qin <qin.long@intel.com>
> Cc: Yao Jiewen <jiewen.yao@intel.com>
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
> ---
> .../Include/Ppi/FirmwareVolumeInfoPrehashedFV.h    |  70 ++++++
> SecurityPkg/SecurityPkg.dec                        |   7 +-
> SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c                  | 245 +++++++++++++++------
> SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf                |   2 +
> 4 files changed, 250 insertions(+), 74 deletions(-) create mode 100644 
> SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
> 
> diff --git a/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h 
> b/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
> new file mode 100644
> index 0000000..2273357
> --- /dev/null
> +++ b/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
> @@ -0,0 +1,70 @@
> +/** @file
> +PPI to describe all hash digests for a given FV
> +
> +Copyright (c) 2017, Intel Corporation. All rights reserved.<BR> This 
> +program and the accompanying materials are licensed and made 
> +available under the terms and conditions of the BSD License which 
> +accompanies this distribution.  The full text of the license may be 
> +found at http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +/**
> +PPI to describe all hash digests for a given FV
> +
> +Copyright (c) 2017, Microsoft Corporation
> +
> +All rights reserved.
> +Redistribution and use in source and binary forms, with or without 
> +modification, are permitted provided that the following conditions are met:
> +1. Redistributions of source code must retain the above copyright 
> +notice, this list of conditions and the following disclaimer.
> +2. Redistributions in binary form must reproduce the above copyright 
> +notice, this list of conditions and the following disclaimer in the 
> +documentation  and/or other materials provided with the distribution.
> +
> +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
> +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
> +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 
> +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
> +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
> +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
> +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
> +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
> +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +**/
> +
> +#ifndef __PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_H__
> +#define __PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_H__
> +
> +#define EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI_GUID \  { 
> +0x3ce1e631, 0x7008, 0x477c, { 0xad, 0xa7, 0x5d, 0xcf, 0xc7, 0xc1, 
> +0x49, 0x4b } }
> +
> +//
> +// HashAlgoId is TPM_ALG_ID in Tpm20.h // typedef struct _HASH_INFO {
> +  UINT16                                     HashAlgoId;
> +  UINT16                                     HashSize;
> +  //UINT8                                    Hash[];
> +} HASH_INFO;
> +
> +//
> +// This PPI indicates a FV is already hashed, platform should ensure 1:1 mapping between pre-hashed PPI and FV.
> +// The Count field in PPI is followed by Count number of FV hash info entries, which can be extended to PCR and logged to TCG event log directly by TCG modules.
> +//
> +typedef struct {
> +  UINT32                                     FvBase;
> +  UINT32                                     FvLength;
> +  UINT32                                     Count;
> +  //HASH_INFO                                HashInfo[];
> +} EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI;
> +
> +extern EFI_GUID gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid;
> +
> +#endif
> +
> diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
> index 7a900dc..45d95c5 100644
> --- a/SecurityPkg/SecurityPkg.dec
> +++ b/SecurityPkg/SecurityPkg.dec
> @@ -7,6 +7,7 @@
> #
> # Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
> # (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR>
> +# Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
> # This program and the accompanying materials are licensed and made available under
> # the terms and conditions of the BSD License which accompanies this distribution.
> # The full text of the license may be found at
> @@ -222,6 +223,9 @@
>   ## Include/Ppi/FirmwareVolumeInfoMeasurementExcluded.h
>   gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid = { 0x6e056ff9, 0xc695, 0x4364, { 0x9e, 0x2c, 0x61, 0x26, 0xf5, 0xce, 0xea, 0xae } }
> 
> +  ## Include/Ppi/FirmwareVolumeInfoPrehashedFV.h
> +  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid = { 0x3ce1e631, 0x7008, 0x477c, { 0xad, 0xa7, 0x5d, 0xcf, 0xc7, 0xc1, 0x49, 0x4b } }
> +
> #
> # [Error.gEfiSecurityPkgTokenSpaceGuid]
> #   0x80000001 | Invalid value provided.
> @@ -452,9 +456,10 @@
> 
> [PcdsDynamic, PcdsDynamicEx]
> 
> -  ## This PCD indicates Hash mask for TPM 2.0.<BR><BR>
> +  ## This PCD indicates Hash mask for TPM 2.0. Bit definition strictly follows TCG Algorithm Registry.<BR><BR>
>   #  If this bit is set, that means this algorithm is needed to extend to PCR.<BR>
>   #  If this bit is clear, that means this algorithm is NOT needed to extend to PCR.<BR>
> +  #  If all the bits are clear, that means hash algorithm is determined by current Active PCR Banks.<BR>
>   #    BIT0  -  SHA1.<BR>
>   #    BIT1  -  SHA256.<BR>
>   #    BIT2  -  SHA384.<BR>
> diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
> index 69adad4..a7ae335 100644
> --- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
> +++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
> @@ -2,6 +2,7 @@
>   Initialize TPM2 device and measure FVs before handing off control to DXE.
> 
> Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
> This program and the accompanying materials 
> are licensed and made available under the terms and conditions of the BSD License 
> which accompanies this distribution.  The full text of the license may be found at 
> @@ -22,6 +23,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> #include <Ppi/FirmwareVolume.h>
> #include <Ppi/EndOfPeiPhase.h>
> #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
> +#include <Ppi/FirmwareVolumeInfoPrehashedFV.h>
> 
> #include <Guid/TcgEventHob.h>
> #include <Guid/MeasuredFvHob.h>
> @@ -133,7 +135,6 @@ EFI_PEI_NOTIFY_DESCRIPTOR           mNotifyList[] = {
>   }
> };
> 
> -EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;
> 
> /**
>   Record all measured Firmware Volum Information into a Guid Hob
> @@ -215,6 +216,13 @@ SyncPcrAllocationsAndPcrMask (
>   ASSERT_EFI_ERROR (Status);
> 
>   Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
> +  if (Tpm2PcrMask == 0) {
> +    //
> +    // if PcdTPm2HashMask is zero, use ActivePcr setting
> +    //
> +    PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
> +    Tpm2PcrMask = TpmActivePcrBanks;
> +  }
> 
>   //
>   // Find the intersection of Pcd support and TPM support.
> @@ -455,53 +463,152 @@ MeasureFvImage (
>   IN UINT64                         FvLength
>   )
> {
> -  UINT32                            Index;
> -  EFI_STATUS                        Status;
> -  EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;
> -  TCG_PCR_EVENT_HDR                 TcgEventHdr;
> -
> -  //
> -  // Check if it is in Excluded FV list
> -  //
> -  if (mMeasurementExcludedFvPpi != NULL) {
> -    for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
> -      if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
> -        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
> -        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
> -        return EFI_SUCCESS;
> +  UINT32                                                Index;
> +  EFI_STATUS                                            Status;
> +  EFI_PLATFORM_FIRMWARE_BLOB                            FvBlob;
> +  TCG_PCR_EVENT_HDR                                     TcgEventHdr;
> +  UINT32                                                Instance;
> +  UINT32                                                Tpm2HashMask;
> +  TPML_DIGEST_VALUES                                    DigestList;
> +  UINT32                                                DigestCount;
> +  EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
> +  EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI       *PrehashedFvPpi;
> +  HASH_INFO                                             *PreHashInfo;
> +  UINT32                                                HashAlgoMask;
> +
> +  //
> +  // Check Excluded FV list
> +  //
> +  Instance = 0;
> +  do {
> +    Status = PeiServicesLocatePpi(
> +                 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
> +                 Instance,
> +                 NULL,
> +                 (VOID**)&MeasurementExcludedFvPpi
> +                 );
> +    if (!EFI_ERROR(Status)) {
> +      for (Index = 0; Index < MeasurementExcludedFvPpi->Count; Index ++) {
> +        if (MeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase
> +         && MeasurementExcludedFvPpi->Fv[Index].FvLength == FvLength) {
> +          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
> +          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
> +          return EFI_SUCCESS;
> +        }
>       }
> +
> +      Instance++;
>     }
> -  }
> +  } while (!EFI_ERROR(Status));
> 
>   //
> -  // Check whether FV is in the measured FV list.
> +  // Check measured FV list
>   //
>   for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
> -    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
> +    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase && mMeasuredBaseFvInfo[Index].BlobLength == FvLength) {
> +      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase));
> +      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength));
>       return EFI_SUCCESS;
>     }
>   }
> -  
> +
>   //
> -  // Measure and record the FV to the TPM
> +  // Check pre-hashed FV list
>   //
> -  FvBlob.BlobBase   = FvBase;
> -  FvBlob.BlobLength = FvLength;
> +  Instance     = 0;
> +  Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);
> +  do {
> +    Status = PeiServicesLocatePpi (
> +               &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid,
> +               Instance,
> +               NULL,
> +               (VOID**)&PrehashedFvPpi
> +               );
> +    if (!EFI_ERROR(Status) && PrehashedFvPpi->FvBase == FvBase && PrehashedFvPpi->FvLength == FvLength) {
> +      ZeroMem (&DigestList, sizeof(TPML_DIGEST_VALUES));
> +
> +      //
> +      // The FV is prehashed, check against TPM hash mask
> +      //
> +      PreHashInfo = (HASH_INFO *)(PrehashedFvPpi + 1);
> +      for (Index = 0, DigestCount = 0; Index < PrehashedFvPpi->Count; Index++) {
> +        DEBUG((DEBUG_INFO, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo->HashAlgoId));
> +        HashAlgoMask = GetHashMaskFromAlgo(PreHashInfo->HashAlgoId);
> +        if ((Tpm2HashMask & HashAlgoMask) != 0 ) {
> +          //
> +          // Hash is required, copy it to DigestList
> +          //
> +          WriteUnaligned16(&(DigestList.digests[DigestCount].hashAlg), PreHashInfo->HashAlgoId);
> +          CopyMem (
> +            &DigestList.digests[DigestCount].digest,
> +            PreHashInfo + 1,
> +            PreHashInfo->HashSize
> +            );
> +          DigestCount++;
> +          //
> +          // Clean the corresponding Hash Algo mask bit
> +          //
> +          Tpm2HashMask &= ~HashAlgoMask;
> +        }
> +        PreHashInfo = (HASH_INFO *)((UINT8 *)(PreHashInfo + 1) + PreHashInfo->HashSize);
> +      }
> +
> +      WriteUnaligned32(&DigestList.count, DigestCount);
> 
> -  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
> -  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
> +      break;
> +    }
> +    Instance++;
> +  } while (!EFI_ERROR(Status));
> 
> -  TcgEventHdr.PCRIndex = 0;
> +  //
> +  // Init the log event for FV measurement
> +  //
> +  FvBlob.BlobBase       = FvBase;
> +  FvBlob.BlobLength     = FvLength;
> +  TcgEventHdr.PCRIndex  = 0;
>   TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
>   TcgEventHdr.EventSize = sizeof (FvBlob);
> 
> -  Status = HashLogExtendEvent (
> -             0,
> -             (UINT8*) (UINTN) FvBlob.BlobBase,
> -             (UINTN) FvBlob.BlobLength,
> -             &TcgEventHdr,
> -             (UINT8*) &FvBlob
> -             );
> +  if (Tpm2HashMask == 0) {
> +    //
> +    // FV pre-hash algos comply with current TPM hash requirement
> +    // Skip hashing step in measure, only extend DigestList to PCR and log event
> +    //
> +    Status = Tpm2PcrExtend(
> +               0,
> +               &DigestList
> +               );
> +
> +    if (!EFI_ERROR(Status)) {
> +       Status = LogHashEvent (&DigestList, &TcgEventHdr, (UINT8*) &FvBlob);
> +       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
> +       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
> +    } else if (Status == EFI_DEVICE_ERROR) {
> +      BuildGuidHob (&gTpmErrorHobGuid,0);
> +      REPORT_STATUS_CODE (
> +        EFI_ERROR_CODE | EFI_ERROR_MINOR,
> +        (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
> +        );
> +    }
> +  } else {
> +    //
> +    // Hash the FV, extend digest to the TPM and log TCG event
> +    //
> +    Status = HashLogExtendEvent (
> +               0,
> +               (UINT8*) (UINTN) FvBlob.BlobBase,
> +               (UINTN) FvBlob.BlobLength,
> +               &TcgEventHdr,
> +               (UINT8*) &FvBlob
> +               );
> +    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
> +    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
> +  }
> +
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));
> +    return Status;
> +  }
> 
>   //
>   // Add new FV into the measured FV list.
> @@ -530,47 +637,44 @@ MeasureMainBios (
>   )
> {
>   EFI_STATUS                        Status;
> -  UINT32                            FvInstances;
>   EFI_PEI_FV_HANDLE                 VolumeHandle;
>   EFI_FV_INFO                       VolumeInfo;
>   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
> 
>   PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
> -  FvInstances    = 0;
> -  while (TRUE) {
> -    //
> -    // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
> -    // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
> -    // platform for special CRTM TPM measuring.
> -    //
> -    Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
> -    if (EFI_ERROR (Status)) {
> -      break;
> -    }
> -  
> -    //
> -    // Measure and record the firmware volume that is dispatched by PeiCore
> -    //
> -    Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
> -    ASSERT_EFI_ERROR (Status);
> -    //
> -    // Locate the corresponding FV_PPI according to founded FV's format guid
> -    //
> -    Status = PeiServicesLocatePpi (
> -               &VolumeInfo.FvFormat, 
> -               0, 
> -               NULL,
> -               (VOID**)&FvPpi
> -               );
> -    if (!EFI_ERROR (Status)) {
> -      MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
> -    }
> 
> -    FvInstances++;
> -  }
> +  //
> +  // Only measure BFV at the very beginning. Other parts of Static Core Root of
> +  // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.
> +  // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or
> +  // reported by platform will be installed with Fv Info Ppi
> +  // This firmware volume measure policy can be modified/enhanced by special
> +  // platform for special CRTM TPM measuring.
> +  //
> +  Status = PeiServicesFfsFindNextVolume (0, &VolumeHandle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Measure and record the firmware volume that is dispatched by PeiCore
> +  //
> +  Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
> +  ASSERT_EFI_ERROR (Status);
> +  //
> +  // Locate the corresponding FV_PPI according to founded FV's format guid
> +  //
> +  Status = PeiServicesLocatePpi (
> +             &VolumeInfo.FvFormat,
> +             0,
> +             NULL,
> +             (VOID**)&FvPpi
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
> +
>   PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
> 
> -  return EFI_SUCCESS;
> +  return Status;
> }
> 
> /**
> @@ -655,14 +759,6 @@ PeimEntryMP (
> {
>   EFI_STATUS                        Status;
> 
> -  Status = PeiServicesLocatePpi (
> -               &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, 
> -               0, 
> -               NULL,
> -               (VOID**)&mMeasurementExcludedFvPpi
> -               );
> -  // Do not check status, because it is optional
> -
>   mMeasuredBaseFvInfo  = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
>   ASSERT (mMeasuredBaseFvInfo != NULL);
>   mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
> @@ -673,6 +769,9 @@ PeimEntryMP (
>   }
> 
>   Status = MeasureMainBios ();
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> 
>   //
>   // Post callbacks:
> diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
> index 1b79ee4..f7b8544 100644
> --- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
> +++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
> @@ -9,6 +9,7 @@
> #  This module will initialize TPM device, measure reported FVs and BIOS version.
> #
> # Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
> # This program and the accompanying materials
> # are licensed and made available under the terms and conditions of the BSD License
> # which accompanies this distribution. The full text of the license may be found at
> @@ -75,6 +76,7 @@
>   gPeiTpmInitializedPpiGuid                                            ## SOMETIMES_PRODUCES
>   gPeiTpmInitializationDonePpiGuid                                     ## PRODUCES
>   gEfiEndOfPeiSignalPpiGuid                                            ## SOMETIMES_CONSUMES     ## NOTIFY
> +  gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid                        ## SOMETIMES_CONSUMES
> 
> [Pcd]
>   gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString              ## SOMETIMES_CONSUMES
> -- 
> 1.9.5.msysgit.1
> 
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel