From nobody Sun Feb 8 17:03:26 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+88988+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+88988+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1650240024; cv=none; d=zohomail.com; s=zohoarc; b=Npk6+d3ciDXGBH3RfbclxwbNQAGC1bl36XQiGgjV30rDKxcKEZtYqdxVL2EjJXtKg/wLSlipZU9DMPsSDTlV8ZSTuZPBKm6AC5rVsT3iwh+/YgDQzZmyG2PN0oJxwtikKucZdbNR+p2nI+f8PNrKyv9lFTc+Li4N+z6V3NClbh0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1650240024; 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=kmG2dK0EmuDGXq6FfSgwN/Q+Nk97wbe5IpCtdeJNw1Y=; b=hWEH4gHIXvFAP0NYHwAK4h4/TkcXDfFumjr9rJ8vkZ/rbhcMYYuTbPRdDqRrr88QeMHNQQW5ntyK3ZHu/t7YlUE+2bAZ2N81zUpO6cM3qt6fEuhpR9R/SjgnZE0TZBE26M0vH9/NGmsohhiYpJwhXkcLx1bX8ByBV0eBUInAbDc= 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+88988+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 1650240024380339.50011672892094; Sun, 17 Apr 2022 17:00:24 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id Y5AzYY1788612xIQ3ocVWveA; Sun, 17 Apr 2022 17:00:24 -0700 X-Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mx.groups.io with SMTP id smtpd.web10.34422.1650240016423357250 for ; Sun, 17 Apr 2022 17:00:23 -0700 X-IronPort-AV: E=McAfee;i="6400,9594,10320"; a="349872481" X-IronPort-AV: E=Sophos;i="5.90,267,1643702400"; d="scan'208";a="349872481" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Apr 2022 17:00:22 -0700 X-IronPort-AV: E=Sophos;i="5.90,267,1643702400"; d="scan'208";a="575329376" X-Received: from cuixin-mobl.ccr.corp.intel.com (HELO mxu9-mobl1.ccr.corp.intel.com) ([10.249.170.67]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Apr 2022 17:00:20 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jiewen Yao , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Tom Lendacky , Gerd Hoffmann Subject: [edk2-devel] [PATCH V3 5/9] OvmfPkg/IntelTdx: Measure Td HobList and Configuration FV Date: Mon, 18 Apr 2022 07:59:56 +0800 Message-Id: <1992c4538efeb3cd3d2e53bd02f2dd24663e9825.1650239544.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: HZarJN1tloJT5RReLksWOgYmx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1650240024; bh=bhCw6oKjHHkdJvozNBPAlafJNadReXMeJ7rPih8Z8VY=; h=Cc:Date:From:Reply-To:Subject:To; b=U5iDaxVRAP2YrbNQiLWk4JqTC56az05la2kLydOfAg4xO08kTcgPccRmlDyhD0oACEi G3S+Vqb7laST8DWhPe1vK2m6KupFTl0dM8BALA8hIhs3y+vaLh2fi/EKCbsHUt3eURw1W U4tYVr42YG2QrU2w7l1Y7GWRltGEmhzwBcc= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1650240025176100022 Content-Type: text/plain; charset="utf-8" RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3853 TdHobList and Configuration FV are external data provided by Host VMM. These are not trusted in Td guest. So they should be validated , measured and extended to Td RTMR registers. In the meantime 2 EFI_CC_EVENT_HOB are created. These 2 GUIDed HOBs carry the hash value of TdHobList and Configuration FV. In DXE phase EFI_CC_EVENT can be created based on these 2 GUIDed HOBs. Cc: Ard Biesheuvel Cc: Jiewen Yao Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Cc: Gerd Hoffmann Signed-off-by: Min Xu --- OvmfPkg/IntelTdx/IntelTdxX64.dsc | 4 + OvmfPkg/Library/PeilessStartupLib/IntelTdx.c | 163 ++++++++++++++++++ .../PeilessStartupLib/PeilessStartup.c | 31 ++++ .../PeilessStartupInternal.h | 17 ++ .../PeilessStartupLib/PeilessStartupLib.inf | 8 +- 5 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 OvmfPkg/Library/PeilessStartupLib/IntelTdx.c diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX6= 4.dsc index 245155d41b30..e6cd10a120a8 100644 --- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc +++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc @@ -520,6 +520,10 @@ OvmfPkg/IntelTdx/Sec/SecMain.inf { NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompre= ssLib.inf + SecMeasurementLib|OvmfPkg/Library/SecMeasurementLib/SecMeasurementLi= bTdx.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SecCryptLib.inf + HashLib|SecurityPkg/Library/HashLibTdx/HashLibTdx.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384= .inf } =20 # diff --git a/OvmfPkg/Library/PeilessStartupLib/IntelTdx.c b/OvmfPkg/Library= /PeilessStartupLib/IntelTdx.c new file mode 100644 index 000000000000..d240d3b7719f --- /dev/null +++ b/OvmfPkg/Library/PeilessStartupLib/IntelTdx.c @@ -0,0 +1,163 @@ +/** @file + Copyright (c) 2022, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include "PeilessStartupInternal.h" + +/** + Check padding data all bit should be 1. + + @param[in] Buffer - A pointer to buffer header + @param[in] BufferSize - Buffer size + + @retval TRUE - The padding data is valid. + @retval TRUE - The padding data is invalid. + +**/ +BOOLEAN +CheckPaddingData ( + IN UINT8 *Buffer, + IN UINT32 BufferSize + ) +{ + UINT32 index; + + for (index =3D 0; index < BufferSize; index++) { + if (Buffer[index] !=3D 0xFF) { + return FALSE; + } + } + + return TRUE; +} + +/** + Check the integrity of CFV data. + + @param[in] TdxCfvBase - A pointer to CFV header + @param[in] TdxCfvSize - CFV data size + + @retval TRUE - The CFV data is valid. + @retval FALSE - The CFV data is invalid. + +**/ +BOOLEAN +EFIAPI +TdxValidateCfv ( + IN UINT8 *TdxCfvBase, + IN UINT32 TdxCfvSize + ) +{ + UINT16 Checksum; + UINTN VariableBase; + UINT32 VariableOffset; + UINT32 VariableOffsetBeforeAlign; + EFI_FIRMWARE_VOLUME_HEADER *CfvFvHeader; + VARIABLE_STORE_HEADER *CfvVariableStoreHeader; + AUTHENTICATED_VARIABLE_HEADER *VariableHeader; + + static EFI_GUID FvHdrGUID =3D EFI_SYSTEM_NV_DATA_FV_GUID; + static EFI_GUID VarStoreHdrGUID =3D EFI_AUTHENTICATED_VARIABLE_GUID; + + VariableOffset =3D 0; + + if (TdxCfvBase =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "TDX CFV: CFV pointer is NULL\n")); + return FALSE; + } + + // + // Verify the header zerovetor, filesystemguid, + // revision, signature, attributes, fvlength, checksum + // HeaderLength cannot be an odd number + // + CfvFvHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)TdxCfvBase; + + if ((!IsZeroBuffer (CfvFvHeader->ZeroVector, 16)) || + (!CompareGuid (&FvHdrGUID, &CfvFvHeader->FileSystemGuid)) || + (CfvFvHeader->Signature !=3D EFI_FVH_SIGNATURE) || + (CfvFvHeader->Attributes !=3D 0x4feff) || + (CfvFvHeader->Revision !=3D EFI_FVH_REVISION) || + (CfvFvHeader->FvLength !=3D TdxCfvSize) + ) + { + DEBUG ((DEBUG_ERROR, "TDX CFV: Basic FV headers were invalid\n")); + return FALSE; + } + + // + // Verify the header checksum + // + Checksum =3D CalculateSum16 ((VOID *)CfvFvHeader, CfvFvHeader->HeaderLen= gth); + + if (Checksum !=3D 0) { + DEBUG ((DEBUG_ERROR, "TDX CFV: FV checksum was invalid\n")); + return FALSE; + } + + // + // Verify the header signature, size, format, state + // + CfvVariableStoreHeader =3D (VARIABLE_STORE_HEADER *)(TdxCfvBase + CfvFvH= eader->HeaderLength); + if ((!CompareGuid (&VarStoreHdrGUID, &CfvVariableStoreHeader->Signature)= ) || + (CfvVariableStoreHeader->Format !=3D VARIABLE_STORE_FORMATTED) || + (CfvVariableStoreHeader->State !=3D VARIABLE_STORE_HEALTHY) || + (CfvVariableStoreHeader->Size > (CfvFvHeader->FvLength - CfvFvHeader= ->HeaderLength)) || + (CfvVariableStoreHeader->Size < sizeof (VARIABLE_STORE_HEADER)) + ) + { + DEBUG ((DEBUG_ERROR, "TDX CFV: Variable Store header was invalid\n")); + return FALSE; + } + + // + // Verify the header startId, state + // Verify data to the end + // + VariableBase =3D (UINTN)TdxCfvBase + CfvFvHeader->HeaderLength + sizeof = (VARIABLE_STORE_HEADER); + while (VariableOffset < (CfvVariableStoreHeader->Size - sizeof (VARIABL= E_STORE_HEADER))) { + VariableHeader =3D (AUTHENTICATED_VARIABLE_HEADER *)(VariableBase + Va= riableOffset); + if (VariableHeader->StartId !=3D VARIABLE_DATA) { + if (!CheckPaddingData ((UINT8 *)VariableHeader, CfvVariableStoreHead= er->Size - sizeof (VARIABLE_STORE_HEADER) - VariableOffset)) { + DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n")); + return FALSE; + } + + VariableOffset =3D CfvVariableStoreHeader->Size - sizeof (VARIABLE_S= TORE_HEADER); + } else { + if (!((VariableHeader->State =3D=3D VAR_IN_DELETED_TRANSITION) || + (VariableHeader->State =3D=3D VAR_DELETED) || + (VariableHeader->State =3D=3D VAR_HEADER_VALID_ONLY) || + (VariableHeader->State =3D=3D VAR_ADDED))) + { + DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n")); + return FALSE; + } + + VariableOffset +=3D sizeof (AUTHENTICATED_VARIABLE_HEADER) + Variabl= eHeader->NameSize + VariableHeader->DataSize; + // Verify VariableOffset should be less than or equal CfvVariableSto= reHeader->Size - sizeof(VARIABLE_STORE_HEADER) + if (VariableOffset > (CfvVariableStoreHeader->Size - sizeof (VARIABL= E_STORE_HEADER))) { + DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n")); + return FALSE; + } + + VariableOffsetBeforeAlign =3D VariableOffset; + // 4 byte align + VariableOffset =3D (VariableOffset + 3) & (UINTN)(~3); + + if (!CheckPaddingData ((UINT8 *)(VariableBase + VariableOffsetBefore= Align), VariableOffset - VariableOffsetBeforeAlign)) { + DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n")); + return FALSE; + } + } + } + + return TRUE; +} diff --git a/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c b/OvmfPkg/L= ibrary/PeilessStartupLib/PeilessStartup.c index 126eb74048f4..54236b956c52 100644 --- a/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c +++ b/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "PeilessStartupInternal.h" =20 #define GET_GPAW_INIT_STATE(INFO) ((UINT8) ((INFO) & 0x3f)) @@ -133,11 +134,13 @@ PeilessStartup ( UINT32 DxeCodeSize; TD_RETURN_DATA TdReturnData; VOID *VmmHobList; + UINT8 *CfvBase; =20 Status =3D EFI_SUCCESS; BootFv =3D NULL; VmmHobList =3D NULL; SecCoreData =3D (EFI_SEC_PEI_HAND_OFF *)Context; + CfvBase =3D (UINT8 *)(UINTN)FixedPcdGet32 (PcdCfvBase); =20 ZeroMem (&PlatformInfoHob, sizeof (PlatformInfoHob)); =20 @@ -167,6 +170,34 @@ PeilessStartup ( =20 DEBUG ((DEBUG_INFO, "HobList: %p\n", GetHobList ())); =20 + if (TdIsEnabled ()) { + // + // Measure HobList + // + Status =3D MeasureHobList (VmmHobList); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + CpuDeadLoop (); + } + + // + // Validate Tdx CFV + // + if (!TdxValidateCfv (CfvBase, FixedPcdGet32 (PcdCfvRawDataSize))) { + ASSERT (FALSE); + CpuDeadLoop (); + } + + // + // Measure Tdx CFV + // + Status =3D MeasureFvImage ((EFI_PHYSICAL_ADDRESS)(UINTN)CfvBase, Fixed= PcdGet32 (PcdCfvRawDataSize), 1); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + CpuDeadLoop (); + } + } + // // Initialize the Platform // diff --git a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h b/O= vmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h index 23e9e0be53f1..dd79b8a06b44 100644 --- a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h +++ b/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h @@ -52,4 +52,21 @@ EFIAPI ConstructSecHobList ( ); =20 +/** + Check the integrity of CFV data. + + @param[in] TdxCfvBase - A pointer to CFV header + @param[in] TdxCfvSize - CFV data size + + @retval TRUE - The CFV data is valid. + @retval FALSE - The CFV data is invalid. + +**/ +BOOLEAN +EFIAPI +TdxValidateCfv ( + IN UINT8 *TdxCfvBase, + IN UINT32 TdxCfvSize + ); + #endif diff --git a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf b/Ovmf= Pkg/Library/PeilessStartupLib/PeilessStartupLib.inf index 8791984586a4..c5d291f02bcd 100644 --- a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf +++ b/OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf @@ -29,8 +29,7 @@ PeilessStartup.c Hob.c DxeLoad.c - -[Sources.X64] + IntelTdx.c X64/VirtualMemory.c =20 [Packages] @@ -39,6 +38,8 @@ UefiCpuPkg/UefiCpuPkg.dec OvmfPkg/OvmfPkg.dec EmbeddedPkg/EmbeddedPkg.dec + CryptoPkg/CryptoPkg.dec + SecurityPkg/SecurityPkg.dec =20 [LibraryClasses] BaseLib @@ -56,6 +57,8 @@ PrePiLib QemuFwCfgLib PlatformInitLib + HashLib + SecMeasurementLib =20 [Guids] gEfiHobMemoryAllocModuleGuid @@ -63,6 +66,7 @@ gUefiOvmfPkgPlatformInfoGuid gEfiMemoryTypeInformationGuid gPcdDataBaseHobGuid + gCcEventEntryHobGuid =20 [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdCfvBase --=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 (#88988): https://edk2.groups.io/g/devel/message/88988 Mute This Topic: https://groups.io/mt/90531017/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-