From mboxrd@z Thu Jan 1 00:00:00 1970 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 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=evhO6pIA; spf=pass (domain: intel.com, ip: 192.55.52.43, mailfrom: min.m.xu@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650240023; x=1681776023; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Ii2R6AAGFiVU95agH6wyJlLBYzvbkSvyCBhBSFhs9zQ=; b=evhO6pIAei+MOwrBn6cFdp8q5VkJmcz5YU/DUICekaNRugu/F9CYZbw1 9pA4CzqFsoflDUFcrLxuPgqQCejdlm9mXDo5OpLfmmc8t4J6LCE+zYWkw zgviALcXA33gu9iKbEADKUx7jMnxG/2pHcXnuPhjgaiJ5M5G1YHh/+kUB ACBL/VCgYF0H1GAf6LPpmZyoxkTebjkqblxqgBs/L0EX5UIqkbvp+rupy mle3d3pYKC9ZOimS4fjyH+Ylifc/I6GyrxCArIE0rB7ijs64R8WxQWnrK 2onnK/+CGBAXf9ND4iX5bv/ZZ/nwk6z2DbmDFL1nj1nJLzfCIESpj4trK Q==; 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" 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" 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: [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> X-Mailer: git-send-email 2.29.2.windows.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3853 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/IntelTdxX64.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/LzmaCustomDecompressLib.inf + SecMeasurementLib|OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SecCryptLib.inf + HashLib|SecurityPkg/Library/HashLibTdx/HashLibTdx.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf } # 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 = 0; index < BufferSize; index++) { + if (Buffer[index] != 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 = EFI_SYSTEM_NV_DATA_FV_GUID; + static EFI_GUID VarStoreHdrGUID = EFI_AUTHENTICATED_VARIABLE_GUID; + + VariableOffset = 0; + + if (TdxCfvBase == 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 = (EFI_FIRMWARE_VOLUME_HEADER *)TdxCfvBase; + + if ((!IsZeroBuffer (CfvFvHeader->ZeroVector, 16)) || + (!CompareGuid (&FvHdrGUID, &CfvFvHeader->FileSystemGuid)) || + (CfvFvHeader->Signature != EFI_FVH_SIGNATURE) || + (CfvFvHeader->Attributes != 0x4feff) || + (CfvFvHeader->Revision != EFI_FVH_REVISION) || + (CfvFvHeader->FvLength != TdxCfvSize) + ) + { + DEBUG ((DEBUG_ERROR, "TDX CFV: Basic FV headers were invalid\n")); + return FALSE; + } + + // + // Verify the header checksum + // + Checksum = CalculateSum16 ((VOID *)CfvFvHeader, CfvFvHeader->HeaderLength); + + if (Checksum != 0) { + DEBUG ((DEBUG_ERROR, "TDX CFV: FV checksum was invalid\n")); + return FALSE; + } + + // + // Verify the header signature, size, format, state + // + CfvVariableStoreHeader = (VARIABLE_STORE_HEADER *)(TdxCfvBase + CfvFvHeader->HeaderLength); + if ((!CompareGuid (&VarStoreHdrGUID, &CfvVariableStoreHeader->Signature)) || + (CfvVariableStoreHeader->Format != VARIABLE_STORE_FORMATTED) || + (CfvVariableStoreHeader->State != 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 = (UINTN)TdxCfvBase + CfvFvHeader->HeaderLength + sizeof (VARIABLE_STORE_HEADER); + while (VariableOffset < (CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) { + VariableHeader = (AUTHENTICATED_VARIABLE_HEADER *)(VariableBase + VariableOffset); + if (VariableHeader->StartId != VARIABLE_DATA) { + if (!CheckPaddingData ((UINT8 *)VariableHeader, CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - VariableOffset)) { + DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n")); + return FALSE; + } + + VariableOffset = CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER); + } else { + if (!((VariableHeader->State == VAR_IN_DELETED_TRANSITION) || + (VariableHeader->State == VAR_DELETED) || + (VariableHeader->State == VAR_HEADER_VALID_ONLY) || + (VariableHeader->State == VAR_ADDED))) + { + DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n")); + return FALSE; + } + + VariableOffset += sizeof (AUTHENTICATED_VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize; + // Verify VariableOffset should be less than or equal CfvVariableStoreHeader->Size - sizeof(VARIABLE_STORE_HEADER) + if (VariableOffset > (CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) { + DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n")); + return FALSE; + } + + VariableOffsetBeforeAlign = VariableOffset; + // 4 byte align + VariableOffset = (VariableOffset + 3) & (UINTN)(~3); + + if (!CheckPaddingData ((UINT8 *)(VariableBase + VariableOffsetBeforeAlign), 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/Library/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" #define GET_GPAW_INIT_STATE(INFO) ((UINT8) ((INFO) & 0x3f)) @@ -133,11 +134,13 @@ PeilessStartup ( UINT32 DxeCodeSize; TD_RETURN_DATA TdReturnData; VOID *VmmHobList; + UINT8 *CfvBase; Status = EFI_SUCCESS; BootFv = NULL; VmmHobList = NULL; SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context; + CfvBase = (UINT8 *)(UINTN)FixedPcdGet32 (PcdCfvBase); ZeroMem (&PlatformInfoHob, sizeof (PlatformInfoHob)); @@ -167,6 +170,34 @@ PeilessStartup ( DEBUG ((DEBUG_INFO, "HobList: %p\n", GetHobList ())); + if (TdIsEnabled ()) { + // + // Measure HobList + // + Status = MeasureHobList (VmmHobList); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + CpuDeadLoop (); + } + + // + // Validate Tdx CFV + // + if (!TdxValidateCfv (CfvBase, FixedPcdGet32 (PcdCfvRawDataSize))) { + ASSERT (FALSE); + CpuDeadLoop (); + } + + // + // Measure Tdx CFV + // + Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS)(UINTN)CfvBase, FixedPcdGet32 (PcdCfvRawDataSize), 1); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + CpuDeadLoop (); + } + } + // // Initialize the Platform // diff --git a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h b/OvmfPkg/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 ( ); +/** + 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/OvmfPkg/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 [Packages] @@ -39,6 +38,8 @@ UefiCpuPkg/UefiCpuPkg.dec OvmfPkg/OvmfPkg.dec EmbeddedPkg/EmbeddedPkg.dec + CryptoPkg/CryptoPkg.dec + SecurityPkg/SecurityPkg.dec [LibraryClasses] BaseLib @@ -56,6 +57,8 @@ PrePiLib QemuFwCfgLib PlatformInitLib + HashLib + SecMeasurementLib [Guids] gEfiHobMemoryAllocModuleGuid @@ -63,6 +66,7 @@ gUefiOvmfPkgPlatformInfoGuid gEfiMemoryTypeInformationGuid gPcdDataBaseHobGuid + gCcEventEntryHobGuid [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdCfvBase -- 2.29.2.windows.2