From nobody Sun Feb 8 14:56:38 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+89754+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+89754+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1652686976; cv=none; d=zohomail.com; s=zohoarc; b=au6rVHQBigLH2OvU7vz6MQo+i5nWzBn8HKsg79oQLe+nXVao8aKKuwHnvOiL7b3t9bmTu8ltnlPoPiF3czYuAkSmQvTK9o+MWc8jEXnz6Q4IOy0j1s9NcuUbtWYhzsE83ibpvr0CFYnvV+RDXgwRh6jLyxv15W0FZ1NeTWxt1p0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1652686976; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=n1pNA62oh8gw9S8hUuugGF0kD9p10AWK7ul01B17Xt4=; b=OKgzUR9hRRBkgNF6JxjA9KpFB4QlnjNp3LKNEY1KLuHEvR2qsppayHTbHunegcDVEwuJOY9Xl/xZJCZ6RJak2sQLvonZMQisAU+3UpQB3l6VeniNeyQJ3KfTymO90YMcsiIr1SGtc3FNcIp/w83kwuS3y1Ivz+xEW8RPbfh0XgU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+89754+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1652686976867535.9498061492483; Mon, 16 May 2022 00:42:56 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id nwVaYY1788612xnrAHcMWdP1; Mon, 16 May 2022 00:42:56 -0700 X-Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web08.26035.1652686973757576480 for ; Mon, 16 May 2022 00:42:55 -0700 X-IronPort-AV: E=McAfee;i="6400,9594,10348"; a="252830429" X-IronPort-AV: E=Sophos;i="5.91,229,1647327600"; d="scan'208";a="252830429" X-Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2022 00:42:51 -0700 X-IronPort-AV: E=Sophos;i="5.91,229,1647327600"; d="scan'208";a="699418974" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.249.170.79]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2022 00:42:45 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky , Ken Lu , Sami Mujawar , Gerd Hoffmann Subject: [edk2-devel] [PATCH V4 4/9] OvmfPkg: Introduce SecMeasurementLib Date: Mon, 16 May 2022 15:42:18 +0800 Message-Id: <71ee1a1ede4e8ef742ab611323f2fa42e0468cd6.1652686674.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: 3Qv6J4OTyyvU0Qsewmc4OklQx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1652686976; bh=0CBgTbauTk6a7lS7wRi9XSFUWGl+fZcq98gQeFNlgwM=; h=Cc:Date:From:Reply-To:Subject:To; b=sNstPxlpwXKXOJDt01Laqt204ayJ7o67/+T+7NChz/icGluR+m2clie0S3BxPjHqe8Q fFgSrq533TaqfGXfoYvoMw55pcMWwEQZFp3dUPIK43NIuEiWvxjFesAHb29kV0PQEuWaz ZLvpy1zy0qc5KnoJneEcpOMhKd7lY9ZNeCo= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1652686977604100001 Content-Type: text/plain; charset="utf-8" RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3853 SecMeasurementLib is designed to do the measurement in SEC phase. In current stage there are 2 functions introduced: - MeasureHobList: Measure the Hoblist passed from the VMM. - MeasureFvImage: Measure the FV image. SecMeasurementLibTdx is the TDX version of the library. Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Cc: Ken Lu Cc: Sami Mujawar Cc: Gerd Hoffmann Reviewed-by: Jiewen Yao Signed-off-by: Min Xu --- OvmfPkg/Include/Library/SecMeasurementLib.h | 46 +++ .../SecMeasurementLib/SecMeasurementLibTdx.c | 340 ++++++++++++++++++ .../SecMeasurementLibTdx.inf | 30 ++ OvmfPkg/OvmfPkg.dec | 4 + 4 files changed, 420 insertions(+) create mode 100644 OvmfPkg/Include/Library/SecMeasurementLib.h create mode 100644 OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.c create mode 100644 OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.= inf diff --git a/OvmfPkg/Include/Library/SecMeasurementLib.h b/OvmfPkg/Include/= Library/SecMeasurementLib.h new file mode 100644 index 000000000000..ca7a7dc3a9b2 --- /dev/null +++ b/OvmfPkg/Include/Library/SecMeasurementLib.h @@ -0,0 +1,46 @@ +/** @file + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SEC_MEASUREMENT_LIB_H_ +#define SEC_MEASUREMENT_LIB_H_ + +/** + 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. + + @param[in] FvBase Base address of FV image. + @param[in] FvLength Length of FV image. + @param[in] PcrIndex Index of PCR + + @retval EFI_SUCCESS Fv image is measured successfully + or it has been already measured. + @retval Others Other errors as indicated +**/ +EFI_STATUS +EFIAPI +MeasureFvImage ( + IN EFI_PHYSICAL_ADDRESS FvBase, + IN UINT64 FvLength, + IN UINT8 PcrIndex + ); + +#endif diff --git a/OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.c b/Ovm= fPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.c new file mode 100644 index 000000000000..274fda1e563e --- /dev/null +++ b/OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.c @@ -0,0 +1,340 @@ +/** @file +* +* Copyright (c) 2021, Intel Corporation. All rights reserved.
+* SPDX-License-Identifier: BSD-2-Clause-Patent +* +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(1) + +typedef struct { + UINT32 count; + TPMI_ALG_HASH hashAlg; + BYTE sha384[SHA384_DIGEST_SIZE]; +} TDX_DIGEST_VALUE; + +#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; + +#define FV_HANDOFF_TABLE_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)" +typedef struct { + UINT8 BlobDescriptionSize; + UINT8 BlobDescription[sizeof (FV_HANDOFF_TABLE_DESC)]; + EFI_PHYSICAL_ADDRESS BlobBase; + UINT64 BlobLength; +} FV_HANDOFF_TABLE_POINTERS2; + +#pragma pack() + +#define INVALID_PCR2MR_INDEX 0xFF + +/** + RTMR[0] =3D> PCR[1,7] + RTMR[1] =3D> PCR[2,3,4,5] + RTMR[2] =3D> PCR[8~15] + RTMR[3] =3D> NA + Note: + PCR[0] is mapped to MRTD and should not appear here. + PCR[6] is reserved for OEM. It is not used. +**/ +UINT8 +GetMappedRtmrIndex ( + UINT32 PCRIndex + ) +{ + UINT8 RtmrIndex; + + if ((PCRIndex =3D=3D 6) || (PCRIndex =3D=3D 0) || (PCRIndex > 15)) { + DEBUG ((DEBUG_ERROR, "Invalid PCRIndex(%d) map to MR Index.\n", PCRInd= ex)); + ASSERT (FALSE); + return INVALID_PCR2MR_INDEX; + } + + RtmrIndex =3D 0; + if ((PCRIndex =3D=3D 1) || (PCRIndex =3D=3D 7)) { + RtmrIndex =3D 0; + } else if ((PCRIndex >=3D 2) && (PCRIndex < 6)) { + RtmrIndex =3D 1; + } else if ((PCRIndex >=3D 8) && (PCRIndex <=3D 15)) { + RtmrIndex =3D 2; + } + + return RtmrIndex; +} + +/** + Tpm measure and log data, and extend the measurement result into a speci= fic PCR. + + @param[in] PcrIndex PCR Index. + @param[in] EventType Event type. + @param[in] EventLog Measurement event log. + @param[in] LogLen Event log length in bytes. + @param[in] HashData The start of the data buffer to be hashed, = extended. + @param[in] HashDataLen The length, in bytes, of the buffer referen= ced by HashData + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_UNSUPPORTED TPM device not available. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. +**/ +EFI_STATUS +EFIAPI +TdxMeasureAndLogData ( + IN UINT32 PcrIndex, + IN UINT32 EventType, + IN VOID *EventLog, + IN UINT32 LogLen, + IN VOID *HashData, + IN UINT64 HashDataLen + ) +{ + EFI_STATUS Status; + UINT32 RtmrIndex; + VOID *EventHobData; + TCG_PCR_EVENT2 *TcgPcrEvent2; + UINT8 *DigestBuffer; + TDX_DIGEST_VALUE *TdxDigest; + TPML_DIGEST_VALUES DigestList; + UINT8 *Ptr; + + RtmrIndex =3D GetMappedRtmrIndex (PcrIndex); + if (RtmrIndex =3D=3D INVALID_PCR2MR_INDEX) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_INFO, "Creating TdTcg2PcrEvent PCR[%d]/RTMR[%d] EventType = 0x%x\n", PcrIndex, RtmrIndex, EventType)); + + Status =3D HashAndExtend ( + RtmrIndex, + (VOID *)HashData, + HashDataLen, + &DigestList + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Failed to HashAndExtend. %r\n", Status)); + return Status; + } + + // + // Use TDX_DIGEST_VALUE in the GUID HOB DataLength calculation + // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary + // which is limited to a SHA384 digest list + // + EventHobData =3D BuildGuidHob ( + &gCcEventEntryHobGuid, + sizeof (TcgPcrEvent2->PCRIndex) + sizeof (TcgPcrEvent2-= >EventType) + + sizeof (TDX_DIGEST_VALUE) + + sizeof (TcgPcrEvent2->EventSize) + LogLen + ); + + if (EventHobData =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Ptr =3D (UINT8 *)EventHobData; + // + // Initialize PcrEvent data now + // + RtmrIndex++; + CopyMem (Ptr, &RtmrIndex, sizeof (UINT32)); + Ptr +=3D sizeof (UINT32); + CopyMem (Ptr, &EventType, sizeof (TCG_EVENTTYPE)); + Ptr +=3D sizeof (TCG_EVENTTYPE); + + DigestBuffer =3D Ptr; + + TdxDigest =3D (TDX_DIGEST_VALUE *)DigestBuffer; + TdxDigest->count =3D 1; + TdxDigest->hashAlg =3D TPM_ALG_SHA384; + CopyMem ( + TdxDigest->sha384, + DigestList.digests[0].digest.sha384, + SHA384_DIGEST_SIZE + ); + + Ptr +=3D sizeof (TDX_DIGEST_VALUE); + + CopyMem (Ptr, &LogLen, sizeof (UINT32)); + Ptr +=3D sizeof (UINT32); + CopyMem (Ptr, EventLog, LogLen); + Ptr +=3D LogLen; + + Status =3D EFI_SUCCESS; + return Status; +} + +/** + 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 =3D (UINT8 *)VmmHobList; + + // + // Parse the HOB list until end of list. + // + while (!END_OF_HOB_LIST (Hob)) { + Hob.Raw =3D GET_NEXT_HOB (Hob); + } + + // + // Init the log event for HOB measurement + // + + HandoffTables.TableDescriptionSize =3D sizeof (HandoffTables.TableDescri= ption); + CopyMem (HandoffTables.TableDescription, HANDOFF_TABLE_DESC, sizeof (Han= doffTables.TableDescription)); + HandoffTables.NumberOfTables =3D 1; + CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), &gUefiOvmfPkgTokenS= paceGuid); + HandoffTables.TableEntry[0].VendorTable =3D (VOID *)VmmHobList; + + Status =3D TdxMeasureAndLogData ( + 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. + + Causion: The FV is untrusted input. + + @param[in] FvBase Base address of FV image. + @param[in] FvLength Length of FV image. + + @return FvName pointer + @retval NULL FvName is NOT found +**/ +VOID * +GetFvName ( + IN EFI_PHYSICAL_ADDRESS FvBase, + IN UINT64 FvLength + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; + + if (FvBase >=3D MAX_ADDRESS) { + return NULL; + } + + if (FvLength >=3D MAX_ADDRESS - FvBase) { + return NULL; + } + + if (FvLength < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) { + return NULL; + } + + FvHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase; + if (FvHeader->ExtHeaderOffset < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) { + return NULL; + } + + if (FvHeader->ExtHeaderOffset + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER) = > FvLength) { + return NULL; + } + + FvExtHeader =3D (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(UINTN)(FvBase + FvHea= der->ExtHeaderOffset); + + return &FvExtHeader->FvName; +} + +/** + Measure FV image. + + @param[in] FvBase Base address of FV image. + @param[in] FvLength Length of FV image. + @param[in] PcrIndex Index of PCR + + @retval EFI_SUCCESS Fv image is measured successfully + or it has been already measured. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + +**/ +EFI_STATUS +EFIAPI +MeasureFvImage ( + IN EFI_PHYSICAL_ADDRESS FvBase, + IN UINT64 FvLength, + IN UINT8 PcrIndex + ) +{ + EFI_STATUS Status; + FV_HANDOFF_TABLE_POINTERS2 FvBlob2; + VOID *FvName; + + // + // Init the log event for FV measurement + // + FvBlob2.BlobDescriptionSize =3D sizeof (FvBlob2.BlobDescription); + CopyMem (FvBlob2.BlobDescription, FV_HANDOFF_TABLE_DESC, sizeof (FvBlob2= .BlobDescription)); + FvName =3D GetFvName (FvBase, FvLength); + if (FvName !=3D NULL) { + AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDes= cription), "Fv(%g)", FvName); + } + + FvBlob2.BlobBase =3D FvBase; + FvBlob2.BlobLength =3D FvLength; + + Status =3D TdxMeasureAndLogData ( + 1, // PCRIndex + EV_EFI_PLATFORM_FIRMWARE_BLOB2, // EventType + (VOID *)&FvBlob2, // EventData + sizeof (FvBlob2), // EventSize + (UINT8 *)(UINTN)FvBase, // HashData + (UINTN)(FvLength) // HashDataLen + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x= %x\n", FvBase)); + ASSERT (FALSE); + } + + return Status; +} diff --git a/OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.inf b/O= vmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.inf new file mode 100644 index 000000000000..6215df5af8fc --- /dev/null +++ b/OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.inf @@ -0,0 +1,30 @@ +#/** @file +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D SecMeasurementLibTdx + FILE_GUID =3D 3e3fc69d-e834-40e9-96ed-e1e721f41883 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D SecMeasurementLib + +[Sources] + SecMeasurementLibTdx.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + CryptoPkg/CryptoPkg.dec + SecurityPkg/SecurityPkg.dec + +[Guids] + gCcEventEntryHobGuid + gUefiOvmfPkgTokenSpaceGuid + +[LibraryClasses] + HashLib diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 8c2048051bea..1dd86af55b91 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -125,6 +125,10 @@ # PeilessStartupLib|Include/Library/PeilessStartupLib.h =20 + ## @libraryclass SecMeasurementLib + # + SecMeasurementLib|Include/Library/SecMeasurementLib.h + [Guids] gUefiOvmfPkgTokenSpaceGuid =3D {0x93bb96af, 0xb9f2, 0x4eb8, {= 0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}} gEfiXenInfoGuid =3D {0xd3b46f3b, 0xd441, 0x1244, {= 0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}} --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#89754): https://edk2.groups.io/g/devel/message/89754 Mute This Topic: https://groups.io/mt/91135112/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-