summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/IntelTdx
diff options
context:
space:
mode:
authorMin M Xu <min.m.xu@intel.com>2023-02-03 11:31:40 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-02-04 03:38:15 +0000
commitf41acc651feec13fac8bea305da5ef0523508a53 (patch)
tree21d2a778d76ba828c16d4fc090f1259b285b5a25 /OvmfPkg/IntelTdx
parentd59279f8ce640caad9e372184a962fad5c578310 (diff)
downloadedk2-f41acc651feec13fac8bea305da5ef0523508a53.tar.gz
edk2-f41acc651feec13fac8bea305da5ef0523508a53.tar.bz2
edk2-f41acc651feec13fac8bea305da5ef0523508a53.zip
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 <erdemaktas@google.com> Cc: James Bottomley <jejb@linux.ibm.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Michael Roth <michael.roth@amd.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Signed-off-by: Min Xu <min.m.xu@intel.com>
Diffstat (limited to 'OvmfPkg/IntelTdx')
-rw-r--r--OvmfPkg/IntelTdx/IntelTdxX64.dsc1
-rw-r--r--OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c123
-rw-r--r--OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf1
-rw-r--r--OvmfPkg/IntelTdx/TdxHelperLib/TdxMeasurementHob.c173
4 files changed, 297 insertions, 1 deletions
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 @@
<LibraryClasses>
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 <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Tdx.h>
+#include <IndustryStandard/IntelTdx.h>
+#include <IndustryStandard/Tpm20.h>
+#include <Library/TdxLib.h>
+#include <Pi/PrePiHob.h>
+#include <WorkArea.h>
+#include <ConfidentialComputingGuestAttr.h>
+#include <Library/TdxHelperLib.h>
+
+/**
+ 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
@@ -28,6 +53,58 @@ TdxHelperProcessTdHob (
}
/**
+ * 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
it is consumed, it should be measured and extended.
@@ -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.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Tpm20.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/HobLib.h>
+#include <Library/PrintLib.h>
+#include <WorkArea.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()
+
+/**
+ * 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;
+}