From f41acc651feec13fac8bea305da5ef0523508a53 Mon Sep 17 00:00:00 2001 From: Min M Xu Date: Fri, 3 Feb 2023 11:31:40 +0800 Subject: OvmfPkg: Refactor MeasureHobList BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4243 MeasureHobList once was implemented in PeilessStartupLib and it does measurement and logging for TdHob in one go, using TpmMeasureAndLogData(). But it doesn't work in SEC. This patch splits MeasureHobList into 2 functions and implement them in SecTdxHelperLib. - TdxHelperMeasureTdHob - TdxHelperBuildGuidHobForTdxMeasurement TdxHelperMeasureTdHob measures the TdHob and stores the hash value in WorkArea. TdxHelperBuildGuidHobForTdxMeasurement builds GuidHob for the measurement based on the hash value in WorkArea. After these 2 functions are introduced, PeilessStartupLib should also be updated: - Call these 2 functions instead of the MeasureHobList - Delete the duplicated codes in PeilessStartupLib Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Gerd Hoffmann Cc: Tom Lendacky Cc: Michael Roth Acked-by: Gerd Hoffmann Reviewed-by: Jiewen Yao Signed-off-by: Min Xu --- OvmfPkg/IntelTdx/IntelTdxX64.dsc | 1 + OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c | 123 ++++++++++++++- OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf | 1 + OvmfPkg/IntelTdx/TdxHelperLib/TdxMeasurementHob.c | 173 +++++++++++++++++++++ OvmfPkg/Library/PeilessStartupLib/IntelTdx.c | 71 --------- OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c | 12 +- .../PeilessStartupLib/PeilessStartupInternal.h | 15 -- 7 files changed, 308 insertions(+), 88 deletions(-) create mode 100644 OvmfPkg/IntelTdx/TdxHelperLib/TdxMeasurementHob.c (limited to 'OvmfPkg') diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX64.dsc index 0f1e970fbb..920f1c6080 100644 --- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc +++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc @@ -549,6 +549,7 @@ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf TpmMeasurementLib|SecurityPkg/Library/SecTpmMeasurementLib/SecTpmMeasurementLibTdx.inf + NULL|OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SecCryptLib.inf HashLib|SecurityPkg/Library/HashLibTdx/HashLibTdx.inf NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf diff --git a/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c b/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c index ef958b3359..6ca6f01aff 100644 --- a/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c +++ b/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c @@ -8,6 +8,31 @@ **/ #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Build the GuidHob for tdx measurements which were done in SEC phase. + The measurement values are stored in WorkArea. + + @retval EFI_SUCCESS The GuidHob is built successfully + @retval Others Other errors as indicated +**/ +EFI_STATUS +InternalBuildGuidHobForTdxMeasurement ( + VOID + ); /** In Tdx guest, some information need to be passed from host VMM to guest @@ -27,6 +52,58 @@ TdxHelperProcessTdHob ( return EFI_UNSUPPORTED; } +/** + * Calculate the sha384 of input Data and extend it to RTMR register. + * + * @param RtmrIndex Index of the RTMR register + * @param DataToHash Data to be hashed + * @param DataToHashLen Length of the data + * @param Digest Hash value of the input data + * @param DigestLen Length of the hash value + * + * @retval EFI_SUCCESS Successfully hash and extend to RTMR + * @retval Others Other errors as indicated + */ +STATIC +EFI_STATUS +HashAndExtendToRtmr ( + IN UINT32 RtmrIndex, + IN VOID *DataToHash, + IN UINTN DataToHashLen, + OUT UINT8 *Digest, + IN UINTN DigestLen + ) +{ + EFI_STATUS Status; + + if ((DataToHash == NULL) || (DataToHashLen == 0)) { + return EFI_INVALID_PARAMETER; + } + + if ((Digest == NULL) || (DigestLen != SHA384_DIGEST_SIZE)) { + return EFI_INVALID_PARAMETER; + } + + // + // Calculate the sha384 of the data + // + if (!Sha384HashAll (DataToHash, DataToHashLen, Digest)) { + return EFI_ABORTED; + } + + // + // Extend to RTMR + // + Status = TdExtendRtmr ( + (UINT32 *)Digest, + SHA384_DIGEST_SIZE, + (UINT8)RtmrIndex + ); + + ASSERT (!EFI_ERROR (Status)); + return Status; +} + /** In Tdx guest, TdHob is passed from host VMM to guest firmware and it contains the information of the memory resource. From the security perspective before @@ -41,7 +118,47 @@ TdxHelperMeasureTdHob ( VOID ) { - return EFI_UNSUPPORTED; + EFI_PEI_HOB_POINTERS Hob; + EFI_STATUS Status; + UINT8 Digest[SHA384_DIGEST_SIZE]; + OVMF_WORK_AREA *WorkArea; + VOID *TdHob; + + TdHob = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase); + Hob.Raw = (UINT8 *)TdHob; + + // + // Walk thru the TdHob list until end of list. + // + while (!END_OF_HOB_LIST (Hob)) { + Hob.Raw = GET_NEXT_HOB (Hob); + } + + Status = HashAndExtendToRtmr ( + 0, + (UINT8 *)TdHob, + (UINTN)((UINT8 *)Hob.Raw - (UINT8 *)TdHob), + Digest, + SHA384_DIGEST_SIZE + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // This function is called in SEC phase and at that moment the Hob service + // is not available. So the TdHob measurement value is stored in workarea. + // + WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase); + if (WorkArea == NULL) { + return EFI_DEVICE_ERROR; + } + + WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.MeasurementsBitmap |= TDX_MEASUREMENT_TDHOB_BITMASK; + CopyMem (WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.TdHobHashValue, Digest, SHA384_DIGEST_SIZE); + + return EFI_SUCCESS; } /** @@ -74,5 +191,9 @@ TdxHelperBuildGuidHobForTdxMeasurement ( VOID ) { + #ifdef TDX_PEI_LESS_BOOT + return InternalBuildGuidHobForTdxMeasurement (); + #else return EFI_UNSUPPORTED; + #endif } diff --git a/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf b/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf index 3c6b96f775..d17b84c01f 100644 --- a/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf +++ b/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf @@ -24,6 +24,7 @@ [Sources] SecTdxHelper.c + TdxMeasurementHob.c [Packages] CryptoPkg/CryptoPkg.dec diff --git a/OvmfPkg/IntelTdx/TdxHelperLib/TdxMeasurementHob.c b/OvmfPkg/IntelTdx/TdxHelperLib/TdxMeasurementHob.c new file mode 100644 index 0000000000..6cbc7600ad --- /dev/null +++ b/OvmfPkg/IntelTdx/TdxHelperLib/TdxMeasurementHob.c @@ -0,0 +1,173 @@ +/** @file + Build GuidHob for tdx measurement. + + Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(1) + +#define HANDOFF_TABLE_DESC "TdxTable" +typedef struct { + UINT8 TableDescriptionSize; + UINT8 TableDescription[sizeof (HANDOFF_TABLE_DESC)]; + UINT64 NumberOfTables; + EFI_CONFIGURATION_TABLE TableEntry[1]; +} TDX_HANDOFF_TABLE_POINTERS2; + +#pragma pack() + +/** + * Build GuidHob for Tdx measurement. + * + * Tdx measurement includes the measurement of TdHob and CFV. They're measured + * and extended to RTMR registers in SEC phase. Because at that moment the Hob + * service are not available. So the values of the measurement are saved in + * workarea and will be built into GuidHob after the Hob service is ready. + * + * @param RtmrIndex RTMR index + * @param EventType Event type + * @param EventData Event data + * @param EventSize Size of event data + * @param HashValue Hash value + * @param HashSize Size of hash + * + * @retval EFI_SUCCESS Successfully build the GuidHobs + * @retval Others Other error as indicated + */ +STATIC +EFI_STATUS +BuildTdxMeasurementGuidHob ( + UINT32 RtmrIndex, + UINT32 EventType, + UINT8 *EventData, + UINT32 EventSize, + UINT8 *HashValue, + UINT32 HashSize + ) +{ + VOID *EventHobData; + UINT8 *Ptr; + TPML_DIGEST_VALUES *TdxDigest; + + if (HashSize != SHA384_DIGEST_SIZE) { + return EFI_INVALID_PARAMETER; + } + + #define TDX_DIGEST_VALUE_LEN (sizeof (UINT32) + sizeof (TPMI_ALG_HASH) + SHA384_DIGEST_SIZE) + + EventHobData = BuildGuidHob ( + &gCcEventEntryHobGuid, + sizeof (TCG_PCRINDEX) + sizeof (TCG_EVENTTYPE) + + TDX_DIGEST_VALUE_LEN + + sizeof (UINT32) + EventSize + ); + + if (EventHobData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Ptr = (UINT8 *)EventHobData; + + // + // There are 2 types of measurement registers in TDX: MRTD and RTMR[0-3]. + // According to UEFI Spec 2.10 Section 38.4.1, RTMR[0-3] is mapped to MrIndex[1-4]. + // So RtmrIndex must be increased by 1 before the event log is created. + // + RtmrIndex++; + CopyMem (Ptr, &RtmrIndex, sizeof (UINT32)); + Ptr += sizeof (UINT32); + + CopyMem (Ptr, &EventType, sizeof (TCG_EVENTTYPE)); + Ptr += sizeof (TCG_EVENTTYPE); + + TdxDigest = (TPML_DIGEST_VALUES *)Ptr; + TdxDigest->count = 1; + TdxDigest->digests[0].hashAlg = TPM_ALG_SHA384; + CopyMem ( + TdxDigest->digests[0].digest.sha384, + HashValue, + SHA384_DIGEST_SIZE + ); + Ptr += TDX_DIGEST_VALUE_LEN; + + CopyMem (Ptr, &EventSize, sizeof (UINT32)); + Ptr += sizeof (UINT32); + + CopyMem (Ptr, (VOID *)EventData, EventSize); + Ptr += EventSize; + + return EFI_SUCCESS; +} + +/** + Build the GuidHob for tdx measurements which were done in SEC phase. + The measurement values are stored in WorkArea. + + @retval EFI_SUCCESS The GuidHob is built successfully + @retval Others Other errors as indicated +**/ +EFI_STATUS +InternalBuildGuidHobForTdxMeasurement ( + VOID + ) +{ + EFI_STATUS Status; + OVMF_WORK_AREA *WorkArea; + VOID *TdHobList; + TDX_HANDOFF_TABLE_POINTERS2 HandoffTables; + UINT8 *HashValue; + + if (!TdIsEnabled ()) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase); + if (WorkArea == NULL) { + return EFI_ABORTED; + } + + Status = EFI_SUCCESS; + + // + // Build the GuidHob for TdHob measurement + // + TdHobList = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase); + if (WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.MeasurementsBitmap & TDX_MEASUREMENT_TDHOB_BITMASK) { + HashValue = WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.TdHobHashValue; + HandoffTables.TableDescriptionSize = sizeof (HandoffTables.TableDescription); + CopyMem (HandoffTables.TableDescription, HANDOFF_TABLE_DESC, sizeof (HandoffTables.TableDescription)); + HandoffTables.NumberOfTables = 1; + CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), &gUefiOvmfPkgTokenSpaceGuid); + HandoffTables.TableEntry[0].VendorTable = TdHobList; + + Status = BuildTdxMeasurementGuidHob ( + 0, // RtmrIndex + EV_EFI_HANDOFF_TABLES2, // EventType + (UINT8 *)(UINTN)&HandoffTables, // EventData + sizeof (HandoffTables), // EventSize + HashValue, // HashValue + SHA384_DIGEST_SIZE // HashSize + ); + } + + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Library/PeilessStartupLib/IntelTdx.c b/OvmfPkg/Library/PeilessStartupLib/IntelTdx.c index 4e8dca3d77..ae0ffcc95d 100644 --- a/OvmfPkg/Library/PeilessStartupLib/IntelTdx.c +++ b/OvmfPkg/Library/PeilessStartupLib/IntelTdx.c @@ -16,80 +16,9 @@ #include "PeilessStartupInternal.h" -#pragma pack(1) - -#define HANDOFF_TABLE_DESC "TdxTable" -typedef struct { - UINT8 TableDescriptionSize; - UINT8 TableDescription[sizeof (HANDOFF_TABLE_DESC)]; - UINT64 NumberOfTables; - EFI_CONFIGURATION_TABLE TableEntry[1]; -} TDX_HANDOFF_TABLE_POINTERS2; - -#pragma pack() - #define FV_HANDOFF_TABLE_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)" typedef PLATFORM_FIRMWARE_BLOB2_STRUCT CFV_HANDOFF_TABLE_POINTERS2; -/** - Measure the Hoblist passed from the VMM. - - @param[in] VmmHobList The Hoblist pass the firmware - - @retval EFI_SUCCESS Fv image is measured successfully - or it has been already measured. - @retval Others Other errors as indicated -**/ -EFI_STATUS -EFIAPI -MeasureHobList ( - IN CONST VOID *VmmHobList - ) -{ - EFI_PEI_HOB_POINTERS Hob; - TDX_HANDOFF_TABLE_POINTERS2 HandoffTables; - EFI_STATUS Status; - - if (!TdIsEnabled ()) { - ASSERT (FALSE); - return EFI_UNSUPPORTED; - } - - Hob.Raw = (UINT8 *)VmmHobList; - - // - // Parse the HOB list until end of list. - // - while (!END_OF_HOB_LIST (Hob)) { - Hob.Raw = GET_NEXT_HOB (Hob); - } - - // - // Init the log event for HOB measurement - // - - HandoffTables.TableDescriptionSize = sizeof (HandoffTables.TableDescription); - CopyMem (HandoffTables.TableDescription, HANDOFF_TABLE_DESC, sizeof (HandoffTables.TableDescription)); - HandoffTables.NumberOfTables = 1; - CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), &gUefiOvmfPkgTokenSpaceGuid); - HandoffTables.TableEntry[0].VendorTable = (VOID *)VmmHobList; - - Status = TpmMeasureAndLogData ( - 1, // PCRIndex - EV_EFI_HANDOFF_TABLES2, // EventType - (VOID *)&HandoffTables, // EventData - sizeof (HandoffTables), // EventSize - (UINT8 *)(UINTN)VmmHobList, // HashData - (UINTN)((UINT8 *)Hob.Raw - (UINT8 *)VmmHobList) // HashDataLen - ); - - if (EFI_ERROR (Status)) { - ASSERT (FALSE); - } - - return Status; -} - /** Get the FvName from the FV header. diff --git a/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c b/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c index 928120d183..4efbc14d59 100644 --- a/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c +++ b/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -179,7 +180,16 @@ PeilessStartup ( // // Measure HobList // - Status = MeasureHobList (VmmHobList); + Status = TdxHelperMeasureTdHob (); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + CpuDeadLoop (); + } + + // + // Build GuidHob for tdx measurement + // + Status = TdxHelperBuildGuidHobForTdxMeasurement (); if (EFI_ERROR (Status)) { ASSERT (FALSE); CpuDeadLoop (); diff --git a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h b/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h index f56bc3578e..a2d2c1c914 100644 --- a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h +++ b/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h @@ -58,21 +58,6 @@ EFIAPI ConstructSecHobList ( ); -/** - Measure the Hoblist passed from the VMM. - - @param[in] VmmHobList The Hoblist pass the firmware - - @retval EFI_SUCCESS Fv image is measured successfully - or it has been already measured. - @retval Others Other errors as indicated -**/ -EFI_STATUS -EFIAPI -MeasureHobList ( - IN CONST VOID *VmmHobList - ); - /** Measure FV image. -- cgit v1.2.3