On Mon, Dec 2, 2024 at 8:09 AM Steve Sakoman via lists.openembedded.org <[email protected]> wrote: > > On Thu, Nov 28, 2024 at 12:15 AM Jia, Hongxu <[email protected]> wrote: > > > > Hi Steve, > > > > I am afraid the issue was caused by CR("^M") in ovmf source code > > > > The source of ovmf use CR (^M) as new line, we should use 'git am --keep-cr > > xxxx.patch' to apply the patch, > > otherwise do_patch failed > > > > But I do not know how you apply the patch to your build or via patchtest > > automatically, do you use git am with option --keep-cr? > > I download the patch from patchworks using the "mbox" button and the > apply it like this: > > $ git am --keep-cr > ~/Downloads/kirkstone-V2-01-13-ovmf-Fix-CVE-2022-36763.patch > Applying: ovmf: Fix CVE-2022-36763 > .git/rebase-apply/patch:56: trailing whitespace. > .git/rebase-apply/patch:60: trailing whitespace. > .git/rebase-apply/patch:65: trailing whitespace. > .git/rebase-apply/patch:81: trailing whitespace. > .git/rebase-apply/patch:95: trailing whitespace. > warning: squelched 27 whitespace errors > warning: 32 lines add whitespace errors. > > $ bitbake ovmf > Loading cache: 100% | > > > > | ETA: --:--:-- > <snip> > NOTE: Executing Tasks > > ERROR: ovmf-edk2-stable202202-r0 do_patch: Applying patch > 'CVE-2022-36763-0001.patch' on target directory > '/home/steve/builds/poky-contrib-kirkstone/build/tmp/work/core2-64-poky-linux/ovmf/edk2-stable202202-r0/git' > CmdError('quilt --quiltrc > /home/steve/builds/poky-contrib-kirkstone/build/tmp/work/core2-64-poky-linux/ovmf/edk2-stable202202-r0/recipe-sysroot-native/etc/quiltrc > push', 0, 'stdout: Applying patch CVE-2022-36763-0001.patch > patching file > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c > Hunk #1 FAILED at 20 (different line endings). > Hunk #2 FAILED at 44 (different line endings). > Hunk #3 FAILED at 144 (different line endings). > Hunk #4 FAILED at 195 (different line endings). > Hunk #5 FAILED at 223 (different line endings). > Hunk #6 FAILED at 248 (different line endings). > Hunk #7 FAILED at 310 (different line endings). > Hunk #8 FAILED at 326 (different line endings). > Hunk #9 FAILED at 443 (different line endings). > Hunk #10 FAILED at 515 (different line endings). > Hunk #11 FAILED at 646 (different line endings). > 11 out of 11 hunks FAILED -- rejects in file > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c > patching file > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf > Hunk #1 FAILED at 37 (different line endings). > Hunk #2 FAILED at 46 (different line endings). > Hunk #3 FAILED at 65 (different line endings). > 3 out of 3 hunks FAILED -- rejects in file > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf > patching file > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c > patching file > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h > patching file > SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c > patching file > SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf > patching file SecurityPkg/SecurityPkg.ci.yaml > Hunk #1 FAILED at 15 (different line endings). > 1 out of 1 hunk FAILED -- rejects in file SecurityPkg/SecurityPkg.ci.yaml > Patch CVE-2022-36763-0001.patch does not apply (enforce with -f) > > stderr: ') > ERROR: Logfile of failure stored in: > /home/steve/builds/poky-contrib-kirkstone/build/tmp/work/core2-64-poky-linux/ovmf/edk2-stable202202-r0/temp/log.do_patch.2851600 > ERROR: Task > (/home/steve/builds/poky-contrib-kirkstone/meta/recipes-core/ovmf/ovmf_git.bb:do_patch) > failed with exit code '1' > NOTE: Tasks Summary: Attempted 1094 tasks of which 1085 didn't need to > be rerun and 1 failed. > Complete CVE report summary created at: > /home/steve/builds/poky-contrib-kirkstone/build/tmp/log/cve/cve-summary > NOTE: Generating JSON CVE summary > Complete CVE JSON report summary created at: > /home/steve/builds/poky-contrib-kirkstone/build/tmp/log/cve/cve-summary.json > > Summary: 1 task failed: > > /home/steve/builds/poky-contrib-kirkstone/meta/recipes-core/ovmf/ovmf_git.bb:do_patch > Summary: There was 1 ERROR message, returning a non-zero exit code. > > Any suggestions?
If you have a public git repo perhaps I could pull the patches directly from there? Steve > > Steve > > > ________________________________ > > From: Steve Sakoman <[email protected]> > > Sent: Wednesday, November 27, 2024 10:50 PM > > To: Jia, Hongxu <[email protected]> > > Cc: [email protected] > > <[email protected]> > > Subject: Re: [kirkstone][PATCH V2 01/13] ovmf: Fix CVE-2022-36763 > > > > CAUTION: This email comes from a non Wind River email account! > > Do not click links or open attachments unless you recognize the sender and > > know the content is safe. > > > > I am getting build time errors with this patch: > > > > ERROR: ovmf-edk2-stable202202-r0 do_patch: Applying patch > > 'CVE-2022-36763-0001.patch' on target directory > > '/home/steve/builds/poky-contrib-kirkstone/build/tmp/work/core2-64-poky-linux/ovmf/edk2-stable202202-r0/git' > > CmdError('quilt --quiltrc > > /home/steve/builds/poky-contrib-kirkstone/build/tmp/work/core2-64-poky-linux/ovmf/edk2-stable202202-r0/recipe-sysroot-native/etc/quiltrc > > push', 0, 'stdout: Applying patch CVE-2022-36763-0001.patch > > patching file > > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c > > Hunk #1 FAILED at 20 (different line endings). > > Hunk #2 FAILED at 44 (different line endings). > > Hunk #3 FAILED at 144 (different line endings). > > Hunk #4 FAILED at 195 (different line endings). > > Hunk #5 FAILED at 223 (different line endings). > > Hunk #6 FAILED at 248 (different line endings). > > Hunk #7 FAILED at 310 (different line endings). > > Hunk #8 FAILED at 326 (different line endings). > > Hunk #9 FAILED at 443 (different line endings). > > Hunk #10 FAILED at 515 (different line endings). > > Hunk #11 FAILED at 646 (different line endings). > > 11 out of 11 hunks FAILED -- rejects in file > > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c > > patching file > > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf > > Hunk #1 FAILED at 37 (different line endings). > > Hunk #2 FAILED at 46 (different line endings). > > Hunk #3 FAILED at 65 (different line endings). > > 3 out of 3 hunks FAILED -- rejects in file > > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf > > patching file > > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c > > patching file > > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h > > patching file > > SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c > > patching file > > SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf > > patching file SecurityPkg/SecurityPkg.ci.yaml > > Hunk #1 FAILED at 15 (different line endings). > > 1 out of 1 hunk FAILED -- rejects in file SecurityPkg/SecurityPkg.ci.yaml > > Patch CVE-2022-36763-0001.patch does not apply (enforce with -f) > > > > Please submit a V2 of this series with the line ending issues fixed. > > > > Thanks! > > > > Steve > > > > On Mon, Nov 25, 2024 at 6:25 PM Hongxu Jia <[email protected]> wrote: > > > > > > From: Soumya Sambu <[email protected]> > > > > > > EDK2 is susceptible to a vulnerability in the Tcg2MeasureGptTable() > > > function, allowing a user to trigger a heap buffer overflow via a local > > > network. Successful exploitation of this vulnerability may result in a > > > compromise of confidentiality, integrity, and/or availability. > > > > > > References: > > > https://nvd.nist.gov/vuln/detail/CVE-2022-36763 > > > > > > Upstream-patches: > > > https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b > > > https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3 > > > https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e > > > > > > Signed-off-by: Soumya Sambu <[email protected]> > > > --- > > > .../ovmf/ovmf/CVE-2022-36763-0001.patch | 985 ++++++++++++++++++ > > > .../ovmf/ovmf/CVE-2022-36763-0002.patch | 889 ++++++++++++++++ > > > .../ovmf/ovmf/CVE-2022-36763-0003.patch | 55 + > > > meta/recipes-core/ovmf/ovmf_git.bb | 3 + > > > 4 files changed, 1932 insertions(+) > > > create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch > > > create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch > > > create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch > > > > > > diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch > > > b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch > > > new file mode 100644 > > > index 0000000000..93cefe7740 > > > --- /dev/null > > > +++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch > > > @@ -0,0 +1,985 @@ > > > +From 224446543206450ddb5830e6abd026d61d3c7f4b Mon Sep 17 00:00:00 2001 > > > +From: "Douglas Flick [MSFT]" <[email protected]> > > > +Date: Fri, 12 Jan 2024 02:16:01 +0800 > > > +Subject: [PATCH] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117 > > > - CVE > > > + 2022-36763 > > > + > > > +This commit contains the patch files and tests for DxeTpm2MeasureBootLib > > > +CVE 2022-36763. > > > + > > > +Cc: Jiewen Yao <[email protected]> > > > + > > > +Signed-off-by: Doug Flick [MSFT] <[email protected]> > > > + > > > +CVE: CVE-2022-36763 > > > + > > > +Upstream-Status: Backport > > > [https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b] > > > + > > > +Signed-off-by: Soumya Sambu <[email protected]> > > > +--- > > > + .../DxeTpm2MeasureBootLib.c | 69 ++-- > > > + .../DxeTpm2MeasureBootLib.inf | 4 +- > > > + .../DxeTpm2MeasureBootLibSanitization.c | 275 ++++++++++++++++ > > > + .../DxeTpm2MeasureBootLibSanitization.h | 113 +++++++ > > > + .../DxeTpm2MeasureBootLibSanitizationTest.c | 303 ++++++++++++++++++ > > > + ...Tpm2MeasureBootLibSanitizationTestHost.inf | 28 ++ > > > + SecurityPkg/SecurityPkg.ci.yaml | 1 + > > > + 7 files changed, 763 insertions(+), 30 deletions(-) > > > + create mode 100644 > > > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c > > > + create mode 100644 > > > SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h > > > + create mode 100644 > > > SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c > > > + create mode 100644 > > > SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf > > > + > > > +diff --git > > > a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c > > > +index 36a256a7af..0475103d6e 100644 > > > +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c > > > ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c > > > +@@ -20,6 +20,8 @@ Copyright (c) 2013 - 2018, Intel Corporation. All > > > rights reserved.<BR> > > > + (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> > > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > > + > > > ++Copyright (c) Microsoft Corporation.<BR> > > > ++SPDX-License-Identifier: BSD-2-Clause-Patent > > > + **/ > > > + > > > + #include <PiDxe.h> > > > +@@ -44,6 +46,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > > > + #include <Library/HobLib.h> > > > + #include <Protocol/CcMeasurement.h> > > > + > > > ++#include "DxeTpm2MeasureBootLibSanitization.h" > > > ++ > > > + typedef struct { > > > + EFI_TCG2_PROTOCOL *Tcg2Protocol; > > > + EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; > > > +@@ -144,10 +148,11 @@ Tcg2MeasureGptTable ( > > > + EFI_TCG2_EVENT *Tcg2Event; > > > + EFI_CC_EVENT *CcEvent; > > > + EFI_GPT_DATA *GptData; > > > +- UINT32 EventSize; > > > ++ UINT32 TcgEventSize; > > > + EFI_TCG2_PROTOCOL *Tcg2Protocol; > > > + EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; > > > + EFI_CC_MR_INDEX MrIndex; > > > ++ UINT32 AllocSize; > > > + > > > + if (mTcg2MeasureGptCount > 0) { > > > + return EFI_SUCCESS; > > > +@@ -195,25 +200,22 @@ Tcg2MeasureGptTable ( > > > + BlockIo->Media->BlockSize, > > > + (UINT8 *)PrimaryHeader > > > + ); > > > +- if (EFI_ERROR (Status)) { > > > +- DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n")); > > > ++ if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader > > > (PrimaryHeader, BlockIo))) { > > > ++ DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or > > > invalid Partition Table Header!\n")); > > > + FreePool (PrimaryHeader); > > > + return EFI_DEVICE_ERROR; > > > + } > > > + > > > + // > > > +- // PrimaryHeader->SizeOfPartitionEntry should not be zero > > > ++ // Read the partition entry. > > > + // > > > +- if (PrimaryHeader->SizeOfPartitionEntry == 0) { > > > +- DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n")); > > > ++ Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, > > > &AllocSize); > > > ++ if (EFI_ERROR (Status)) { > > > + FreePool (PrimaryHeader); > > > + return EFI_BAD_BUFFER_SIZE; > > > + } > > > + > > > +- // > > > +- // Read the partition entry. > > > +- // > > > +- EntryPtr = (UINT8 *)AllocatePool > > > (PrimaryHeader->NumberOfPartitionEntries * > > > PrimaryHeader->SizeOfPartitionEntry); > > > ++ EntryPtr = (UINT8 *)AllocatePool (AllocSize); > > > + if (EntryPtr == NULL) { > > > + FreePool (PrimaryHeader); > > > + return EFI_OUT_OF_RESOURCES; > > > +@@ -223,7 +225,7 @@ Tcg2MeasureGptTable ( > > > + DiskIo, > > > + BlockIo->Media->MediaId, > > > + MultU64x32 (PrimaryHeader->PartitionEntryLBA, > > > BlockIo->Media->BlockSize), > > > +- PrimaryHeader->NumberOfPartitionEntries * > > > PrimaryHeader->SizeOfPartitionEntry, > > > ++ AllocSize, > > > + EntryPtr > > > + ); > > > + if (EFI_ERROR (Status)) { > > > +@@ -248,16 +250,21 @@ Tcg2MeasureGptTable ( > > > + // > > > + // Prepare Data for Measurement (CcProtocol and Tcg2Protocol) > > > + // > > > +- EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof > > > (GptData->Partitions) > > > +- + NumberOfPartition * > > > PrimaryHeader->SizeOfPartitionEntry); > > > +- EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof > > > (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)); > > > ++ Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, > > > NumberOfPartition, &TcgEventSize); > > > ++ if (EFI_ERROR (Status)) { > > > ++ FreePool (PrimaryHeader); > > > ++ FreePool (EntryPtr); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ EventPtr = (UINT8 *)AllocateZeroPool (TcgEventSize); > > > + if (EventPtr == NULL) { > > > + Status = EFI_OUT_OF_RESOURCES; > > > + goto Exit; > > > + } > > > + > > > + Tcg2Event = (EFI_TCG2_EVENT *)EventPtr; > > > +- Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) > > > - sizeof (Tcg2Event->Event); > > > ++ Tcg2Event->Size = TcgEventSize; > > > + Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER); > > > + Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; > > > + Tcg2Event->Header.PCRIndex = 5; > > > +@@ -310,7 +317,7 @@ Tcg2MeasureGptTable ( > > > + CcProtocol, > > > + 0, > > > + > > > (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData, > > > +- (UINT64)EventSize, > > > ++ (UINT64)TcgEventSize - > > > OFFSET_OF (EFI_TCG2_EVENT, Event), > > > + CcEvent > > > + ); > > > + if (!EFI_ERROR (Status)) { > > > +@@ -326,7 +333,7 @@ Tcg2MeasureGptTable ( > > > + Tcg2Protocol, > > > + 0, > > > + (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID > > > *)GptData, > > > +- (UINT64)EventSize, > > > ++ (UINT64)TcgEventSize - OFFSET_OF > > > (EFI_TCG2_EVENT, Event), > > > + Tcg2Event > > > + ); > > > + if (!EFI_ERROR (Status)) { > > > +@@ -443,11 +450,13 @@ Tcg2MeasurePeImage ( > > > + Tcg2Event->Header.PCRIndex = 2; > > > + break; > > > + default: > > > +- DEBUG (( > > > +- DEBUG_ERROR, > > > +- "Tcg2MeasurePeImage: Unknown subsystem type %d", > > > +- ImageType > > > +- )); > > > ++ DEBUG ( > > > ++ ( > > > ++ DEBUG_ERROR, > > > ++ "Tcg2MeasurePeImage: Unknown subsystem type %d", > > > ++ ImageType > > > ++ ) > > > ++ ); > > > + goto Finish; > > > + } > > > + > > > +@@ -515,7 +524,7 @@ Finish: > > > + > > > + @param MeasureBootProtocols Pointer to the located measure boot > > > protocol instances. > > > + > > > +- @retval EFI_SUCCESS Sucessfully locate the measure boot > > > protocol instances (at least one instance). > > > ++ @retval EFI_SUCCESS Successfully locate the measure boot > > > protocol instances (at least one instance). > > > + @retval EFI_UNSUPPORTED Measure boot is not supported. > > > + **/ > > > + EFI_STATUS > > > +@@ -646,12 +655,14 @@ DxeTpm2MeasureBootHandler ( > > > + return EFI_SUCCESS; > > > + } > > > + > > > +- DEBUG (( > > > +- DEBUG_INFO, > > > +- "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n", > > > +- MeasureBootProtocols.Tcg2Protocol, > > > +- MeasureBootProtocols.CcProtocol > > > +- )); > > > ++ DEBUG ( > > > ++ ( > > > ++ DEBUG_INFO, > > > ++ "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n", > > > ++ MeasureBootProtocols.Tcg2Protocol, > > > ++ MeasureBootProtocols.CcProtocol > > > ++ ) > > > ++ ); > > > + > > > + // > > > + // Copy File Device Path > > > +diff --git > > > a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf > > > +index 6dca79a20c..28995f438d 100644 > > > +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf > > > ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf > > > +@@ -37,6 +37,8 @@ > > > + > > > + [Sources] > > > + DxeTpm2MeasureBootLib.c > > > ++ DxeTpm2MeasureBootLibSanitization.c > > > ++ DxeTpm2MeasureBootLibSanitization.h > > > + > > > + [Packages] > > > + MdePkg/MdePkg.dec > > > +@@ -46,6 +48,7 @@ > > > + > > > + [LibraryClasses] > > > + BaseMemoryLib > > > ++ SafeIntLib > > > + DebugLib > > > + MemoryAllocationLib > > > + DevicePathLib > > > +@@ -65,4 +68,3 @@ > > > + gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES > > > + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES > > > + gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES > > > +- > > > +diff --git > > > a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c > > > > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c > > > +new file mode 100644 > > > +index 0000000000..e2309655d3 > > > +--- /dev/null > > > ++++ > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c > > > +@@ -0,0 +1,275 @@ > > > ++/** @file > > > ++ The library instance provides security service of TPM2 measure boot > > > and > > > ++ Confidential Computing (CC) measure boot. > > > ++ > > > ++ Caution: This file requires additional review when modified. > > > ++ This library will have external input - PE/COFF image and GPT > > > partition. > > > ++ This external input must be validated carefully to avoid security > > > issue like > > > ++ buffer overflow, integer overflow. > > > ++ > > > ++ This file will pull out the validation logic from the following > > > functions, in an > > > ++ attempt to validate the untrusted input in the form of unit tests > > > ++ > > > ++ These are those functions: > > > ++ > > > ++ DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF > > > image content > > > ++ read is within the image buffer. > > > ++ > > > ++ Tcg2MeasureGptTable() function will receive untrusted GPT partition > > > table, and parse > > > ++ partition data carefully. > > > ++ > > > ++ Copyright (c) Microsoft Corporation.<BR> > > > ++ SPDX-License-Identifier: BSD-2-Clause-Patent > > > ++**/ > > > ++#include <Uefi.h> > > > ++#include <Uefi/UefiSpec.h> > > > ++#include <Library/SafeIntLib.h> > > > ++#include <Library/UefiLib.h> > > > ++#include <Library/DebugLib.h> > > > ++#include <Library/BaseLib.h> > > > ++#include <IndustryStandard/UefiTcgPlatform.h> > > > ++#include <Protocol/BlockIo.h> > > > ++#include <Library/MemoryAllocationLib.h> > > > ++ > > > ++#include "DxeTpm2MeasureBootLibSanitization.h" > > > ++ > > > ++#define GPT_HEADER_REVISION_V1 0x00010000 > > > ++ > > > ++/** > > > ++ This function will validate the EFI_PARTITION_TABLE_HEADER structure > > > is safe to parse > > > ++ However this function will not attempt to verify the validity of the > > > GPT partition > > > ++ It will check the following: > > > ++ - Signature > > > ++ - Revision > > > ++ - AlternateLBA > > > ++ - FirstUsableLBA > > > ++ - LastUsableLBA > > > ++ - PartitionEntryLBA > > > ++ - NumberOfPartitionEntries > > > ++ - SizeOfPartitionEntry > > > ++ - BlockIo > > > ++ > > > ++ @param[in] PrimaryHeader > > > ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. > > > ++ > > > ++ @param[in] BlockIo > > > ++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The EFI_PARTITION_TABLE_HEADER structure is valid. > > > ++ > > > ++ @retval EFI_INVALID_PARAMETER > > > ++ The EFI_PARTITION_TABLE_HEADER structure is invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++SanitizeEfiPartitionTableHeader ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo > > > ++ ) > > > ++{ > > > ++ // > > > ++ // Verify that the input parameters are safe to use > > > ++ // > > > ++ if (PrimaryHeader == NULL) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ if ((BlockIo == NULL) || (BlockIo->Media == NULL)) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n")); > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ // > > > ++ // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII) > > > ++ // > > > ++ if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // > > > ++ // The version must be GPT_HEADER_REVISION_V1 (0x00010000) > > > ++ // > > > ++ if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // > > > ++ // The HeaderSize must be greater than or equal to 92 and must be > > > less than or equal to the logical block size > > > ++ // > > > ++ if ((PrimaryHeader->Header.HeaderSize < sizeof > > > (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > > > > BlockIo->Media->BlockSize)) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header > > > HeaderSize!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // > > > ++ // The partition entries should all be before the first usable block > > > ++ // > > > ++ if (PrimaryHeader->FirstUsableLBA <= > > > PrimaryHeader->PartitionEntryLBA) { > > > ++ DEBUG ((DEBUG_ERROR, "GPT PartitionEntryLBA is not less than > > > FirstUsableLBA!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // > > > ++ // Check that the PartitionEntryLBA greater than the Max LBA > > > ++ // This will be used later for multiplication > > > ++ // > > > ++ if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, > > > BlockIo->Media->BlockSize)) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header > > > PartitionEntryLBA!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // > > > ++ // Check that the number of partition entries is greater than zero > > > ++ // > > > ++ if (PrimaryHeader->NumberOfPartitionEntries == 0) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header > > > NumberOfPartitionEntries!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // > > > ++ // SizeOfPartitionEntry must be 128, 256, 512... improper size may > > > lead to accessing uninitialized memory > > > ++ // > > > ++ if ((PrimaryHeader->SizeOfPartitionEntry < 128) || > > > ((PrimaryHeader->SizeOfPartitionEntry & > > > (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) { > > > ++ DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry shall be set to a value > > > of 128 x 2^n where n is an integer greater than or equal to zero (e.g., > > > 128, 256, 512, etc.)!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // > > > ++ // This check is to prevent overflow when calculating the allocation > > > size for the partition entries > > > ++ // This check will be used later for multiplication > > > ++ // > > > ++ if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, > > > PrimaryHeader->SizeOfPartitionEntry)) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header > > > NumberOfPartitionEntries!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ return EFI_SUCCESS; > > > ++} > > > ++ > > > ++/** > > > ++ This function will validate that the allocation size from the primary > > > header is sane > > > ++ It will check the following: > > > ++ - AllocationSize does not overflow > > > ++ > > > ++ @param[in] PrimaryHeader > > > ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. > > > ++ > > > ++ @param[out] AllocationSize > > > ++ Pointer to the allocation size. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The allocation size is valid. > > > ++ > > > ++ @retval EFI_OUT_OF_RESOURCES > > > ++ The allocation size is invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++SanitizePrimaryHeaderAllocationSize ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ OUT UINT32 *AllocationSize > > > ++ ) > > > ++{ > > > ++ EFI_STATUS Status; > > > ++ > > > ++ if (PrimaryHeader == NULL) { > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ if (AllocationSize == NULL) { > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ // > > > ++ // Replacing logic: > > > ++ // PrimaryHeader->NumberOfPartitionEntries * > > > PrimaryHeader->SizeOfPartitionEntry; > > > ++ // > > > ++ Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, > > > PrimaryHeader->SizeOfPartitionEntry, AllocationSize); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n")); > > > ++ return EFI_BAD_BUFFER_SIZE; > > > ++ } > > > ++ > > > ++ return EFI_SUCCESS; > > > ++} > > > ++ > > > ++/** > > > ++ This function will validate that the Gpt Event Size calculated from > > > the primary header is sane > > > ++ It will check the following: > > > ++ - EventSize does not overflow > > > ++ > > > ++ Important: This function includes the entire length of the allocated > > > space, including > > > ++ (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing > > > the buffer allocated with this > > > ++ size, the caller must subtract the size of the (sizeof > > > (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) > > > ++ from the size of the buffer before hashing. > > > ++ > > > ++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER > > > structure. > > > ++ @param[in] NumberOfPartition - Number of partitions. > > > ++ @param[out] EventSize - Pointer to the event size. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The event size is valid. > > > ++ > > > ++ @retval EFI_OUT_OF_RESOURCES > > > ++ Overflow would have occurred. > > > ++ > > > ++ @retval EFI_INVALID_PARAMETER > > > ++ One of the passed parameters was invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++SanitizePrimaryHeaderGptEventSize ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ IN UINTN NumberOfPartition, > > > ++ OUT UINT32 *EventSize > > > ++ ) > > > ++{ > > > ++ EFI_STATUS Status; > > > ++ UINT32 SafeNumberOfPartitions; > > > ++ > > > ++ if (PrimaryHeader == NULL) { > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ if (EventSize == NULL) { > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ // > > > ++ // We shouldn't even attempt to perform the multiplication if the > > > number of partitions is greater than the maximum value of UINT32 > > > ++ // > > > ++ Status = SafeUintnToUint32 (NumberOfPartition, > > > &SafeNumberOfPartitions); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n")); > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ // > > > ++ // Replacing logic: > > > ++ // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + > > > NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry); > > > ++ // > > > ++ Status = SafeUint32Mult (SafeNumberOfPartitions, > > > PrimaryHeader->SizeOfPartitionEntry, EventSize); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n")); > > > ++ return EFI_BAD_BUFFER_SIZE; > > > ++ } > > > ++ > > > ++ // > > > ++ // Replacing logic: > > > ++ // *EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event); > > > ++ // > > > ++ Status = SafeUint32Add ( > > > ++ OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF > > > (EFI_GPT_DATA, Partitions), > > > ++ *EventSize, > > > ++ EventSize > > > ++ ); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of > > > GPTData!\n")); > > > ++ return EFI_BAD_BUFFER_SIZE; > > > ++ } > > > ++ > > > ++ return EFI_SUCCESS; > > > ++} > > > +diff --git > > > a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h > > > > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h > > > +new file mode 100644 > > > +index 0000000000..048b738987 > > > +--- /dev/null > > > ++++ > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h > > > +@@ -0,0 +1,113 @@ > > > ++/** @file > > > ++ This file includes the function prototypes for the sanitization > > > functions. > > > ++ > > > ++ These are those functions: > > > ++ > > > ++ DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF > > > image content > > > ++ read is within the image buffer. > > > ++ > > > ++ Tcg2MeasureGptTable() function will receive untrusted GPT partition > > > table, and parse > > > ++ partition data carefully. > > > ++ > > > ++ Copyright (c) Microsoft Corporation.<BR> > > > ++ SPDX-License-Identifier: BSD-2-Clause-Patent > > > ++ > > > ++**/ > > > ++ > > > ++#ifndef DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ > > > ++#define DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ > > > ++ > > > ++#include <Uefi.h> > > > ++#include <Uefi/UefiSpec.h> > > > ++#include <Protocol/BlockIo.h> > > > ++#include <IndustryStandard/UefiTcgPlatform.h> > > > ++#include <Protocol/Tcg2Protocol.h> > > > ++ > > > ++/** > > > ++ This function will validate the EFI_PARTITION_TABLE_HEADER structure > > > is safe to parse > > > ++ However this function will not attempt to verify the validity of the > > > GPT partition > > > ++ It will check the following: > > > ++ - Signature > > > ++ - Revision > > > ++ - AlternateLBA > > > ++ - FirstUsableLBA > > > ++ - LastUsableLBA > > > ++ - PartitionEntryLBA > > > ++ - NumberOfPartitionEntries > > > ++ - SizeOfPartitionEntry > > > ++ - BlockIo > > > ++ > > > ++ @param[in] PrimaryHeader > > > ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. > > > ++ > > > ++ @param[in] BlockIo > > > ++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The EFI_PARTITION_TABLE_HEADER structure is valid. > > > ++ > > > ++ @retval EFI_INVALID_PARAMETER > > > ++ The EFI_PARTITION_TABLE_HEADER structure is invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++SanitizeEfiPartitionTableHeader ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo > > > ++ ); > > > ++ > > > ++/** > > > ++ This function will validate that the allocation size from the primary > > > header is sane > > > ++ It will check the following: > > > ++ - AllocationSize does not overflow > > > ++ > > > ++ @param[in] PrimaryHeader > > > ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. > > > ++ > > > ++ @param[out] AllocationSize > > > ++ Pointer to the allocation size. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The allocation size is valid. > > > ++ > > > ++ @retval EFI_OUT_OF_RESOURCES > > > ++ The allocation size is invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++SanitizePrimaryHeaderAllocationSize ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ OUT UINT32 *AllocationSize > > > ++ ); > > > ++ > > > ++/** > > > ++ This function will validate that the Gpt Event Size calculated from > > > the primary header is sane > > > ++ It will check the following: > > > ++ - EventSize does not overflow > > > ++ > > > ++ Important: This function includes the entire length of the allocated > > > space, including > > > ++ (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing > > > the buffer allocated with this > > > ++ size, the caller must subtract the size of the (sizeof > > > (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) > > > ++ from the size of the buffer before hashing. > > > ++ > > > ++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER > > > structure. > > > ++ @param[in] NumberOfPartition - Number of partitions. > > > ++ @param[out] EventSize - Pointer to the event size. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The event size is valid. > > > ++ > > > ++ @retval EFI_OUT_OF_RESOURCES > > > ++ Overflow would have occurred. > > > ++ > > > ++ @retval EFI_INVALID_PARAMETER > > > ++ One of the passed parameters was invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++SanitizePrimaryHeaderGptEventSize ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ IN UINTN NumberOfPartition, > > > ++ OUT UINT32 *EventSize > > > ++ ); > > > ++ > > > ++#endif // DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ > > > +diff --git > > > a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c > > > > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c > > > +new file mode 100644 > > > +index 0000000000..3eb9763e3c > > > +--- /dev/null > > > ++++ > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c > > > +@@ -0,0 +1,303 @@ > > > ++/** @file > > > ++ This file includes the unit test cases for the > > > DxeTpm2MeasureBootLibSanitizationTest.c. > > > ++ > > > ++ Copyright (c) Microsoft Corporation.<BR> > > > ++ SPDX-License-Identifier: BSD-2-Clause-Patent > > > ++**/ > > > ++ > > > ++#include <Uefi.h> > > > ++#include <Library/UefiLib.h> > > > ++#include <Library/DebugLib.h> > > > ++#include <Library/UnitTestLib.h> > > > ++#include <Protocol/BlockIo.h> > > > ++#include <Library/MemoryAllocationLib.h> > > > ++#include <Library/BaseMemoryLib.h> > > > ++#include <IndustryStandard/UefiTcgPlatform.h> > > > ++#include <Protocol/Tcg2Protocol.h> > > > ++ > > > ++#include "../DxeTpm2MeasureBootLibSanitization.h" > > > ++ > > > ++#define UNIT_TEST_NAME "DxeTpm2MeasureBootLibSanitizationTest" > > > ++#define UNIT_TEST_VERSION "1.0" > > > ++ > > > ++#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION > > > 0x00010000 > > > ++#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1 > > > ++#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128 > > > ++ > > > ++/** > > > ++ This function tests the SanitizeEfiPartitionTableHeader function. > > > ++ It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER > > > ++ structure will not cause undefined or unexpected behavior. > > > ++ > > > ++ In general the TPM should still be able to measure the data, but > > > ++ be the header should be sanitized to prevent any unexpected behavior. > > > ++ > > > ++ @param[in] Context The unit test context. > > > ++ > > > ++ @retval UNIT_TEST_PASSED The test passed. > > > ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. > > > ++**/ > > > ++UNIT_TEST_STATUS > > > ++EFIAPI > > > ++TestSanitizeEfiPartitionTableHeader ( > > > ++ IN UNIT_TEST_CONTEXT Context > > > ++ ) > > > ++{ > > > ++ EFI_STATUS Status; > > > ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; > > > ++ EFI_BLOCK_IO_PROTOCOL BlockIo; > > > ++ EFI_BLOCK_IO_MEDIA BlockMedia; > > > ++ > > > ++ // Generate EFI_BLOCK_IO_MEDIA test data > > > ++ BlockMedia.MediaId = 1; > > > ++ BlockMedia.RemovableMedia = FALSE; > > > ++ BlockMedia.MediaPresent = TRUE; > > > ++ BlockMedia.LogicalPartition = FALSE; > > > ++ BlockMedia.ReadOnly = FALSE; > > > ++ BlockMedia.WriteCaching = FALSE; > > > ++ BlockMedia.BlockSize = 512; > > > ++ BlockMedia.IoAlign = 1; > > > ++ BlockMedia.LastBlock = 0; > > > ++ > > > ++ // Generate EFI_BLOCK_IO_PROTOCOL test data > > > ++ BlockIo.Revision = 1; > > > ++ BlockIo.Media = &BlockMedia; > > > ++ BlockIo.Reset = NULL; > > > ++ BlockIo.ReadBlocks = NULL; > > > ++ BlockIo.WriteBlocks = NULL; > > > ++ BlockIo.FlushBlocks = NULL; > > > ++ > > > ++ // Geneate EFI_PARTITION_TABLE_HEADER test data > > > ++ PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID; > > > ++ PrimaryHeader.Header.Revision = > > > DEFAULT_PRIMARY_TABLE_HEADER_REVISION; > > > ++ PrimaryHeader.Header.HeaderSize = sizeof > > > (EFI_PARTITION_TABLE_HEADER); > > > ++ PrimaryHeader.MyLBA = 1; > > > ++ PrimaryHeader.AlternateLBA = 2; > > > ++ PrimaryHeader.FirstUsableLBA = 3; > > > ++ PrimaryHeader.LastUsableLBA = 4; > > > ++ PrimaryHeader.PartitionEntryLBA = 5; > > > ++ PrimaryHeader.NumberOfPartitionEntries = > > > DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES; > > > ++ PrimaryHeader.SizeOfPartitionEntry = > > > DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; > > > ++ PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid > > > ++ > > > ++ // Calculate the CRC32 of the PrimaryHeader > > > ++ PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, > > > PrimaryHeader.Header.HeaderSize); > > > ++ > > > ++ // Test that a normal PrimaryHeader passes validation > > > ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); > > > ++ UT_ASSERT_NOT_EFI_ERROR (Status); > > > ++ > > > ++ // Test that when number of partition entries is 0, the function > > > returns EFI_DEVICE_ERROR > > > ++ // Should print "Invalid Partition Table Header > > > NumberOfPartitionEntries!"" > > > ++ PrimaryHeader.NumberOfPartitionEntries = 0; > > > ++ Status = > > > SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); > > > ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); > > > ++ PrimaryHeader.NumberOfPartitionEntries = > > > DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; > > > ++ > > > ++ // Test that when the header size is too small, the function returns > > > EFI_DEVICE_ERROR > > > ++ // Should print "Invalid Partition Table Header Size!" > > > ++ PrimaryHeader.Header.HeaderSize = 0; > > > ++ Status = SanitizeEfiPartitionTableHeader > > > (&PrimaryHeader, &BlockIo); > > > ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); > > > ++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); > > > ++ > > > ++ // Test that when the SizeOfPartitionEntry is too small, the function > > > returns EFI_DEVICE_ERROR > > > ++ // should print: "SizeOfPartitionEntry shall be set to a value of 128 > > > x 2^n where n is an integer greater than or equal to zero (e.g., 128, > > > 256, 512, etc.)!" > > > ++ PrimaryHeader.SizeOfPartitionEntry = 1; > > > ++ Status = SanitizeEfiPartitionTableHeader > > > (&PrimaryHeader, &BlockIo); > > > ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); > > > ++ > > > ++ return UNIT_TEST_PASSED; > > > ++} > > > ++ > > > ++/** > > > ++ This function tests the SanitizePrimaryHeaderAllocationSize function. > > > ++ It's intent is to test that the untrusted input from a > > > EFI_PARTITION_TABLE_HEADER > > > ++ structure will not cause an overflow when calculating the allocation > > > size. > > > ++ > > > ++ @param[in] Context The unit test context. > > > ++ > > > ++ @retval UNIT_TEST_PASSED The test passed. > > > ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. > > > ++**/ > > > ++UNIT_TEST_STATUS > > > ++EFIAPI > > > ++TestSanitizePrimaryHeaderAllocationSize ( > > > ++ IN UNIT_TEST_CONTEXT Context > > > ++ ) > > > ++{ > > > ++ UINT32 AllocationSize; > > > ++ > > > ++ EFI_STATUS Status; > > > ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; > > > ++ > > > ++ // Test that a normal PrimaryHeader passes validation > > > ++ PrimaryHeader.NumberOfPartitionEntries = 5; > > > ++ PrimaryHeader.SizeOfPartitionEntry = > > > DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; > > > ++ > > > ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, > > > &AllocationSize); > > > ++ UT_ASSERT_NOT_EFI_ERROR (Status); > > > ++ > > > ++ // Test that the allocation size is correct compared to the existing > > > logic > > > ++ UT_ASSERT_EQUAL (AllocationSize, > > > PrimaryHeader.NumberOfPartitionEntries * > > > PrimaryHeader.SizeOfPartitionEntry); > > > ++ > > > ++ // Test that an overflow is detected > > > ++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; > > > ++ PrimaryHeader.SizeOfPartitionEntry = 5; > > > ++ Status = > > > SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ // Test the inverse > > > ++ PrimaryHeader.NumberOfPartitionEntries = 5; > > > ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; > > > ++ Status = > > > SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ // Test the worst case scenario > > > ++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; > > > ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; > > > ++ Status = > > > SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); > > > ++ > > > ++ return UNIT_TEST_PASSED; > > > ++} > > > ++ > > > ++/** > > > ++ This function tests the SanitizePrimaryHeaderGptEventSize function. > > > ++ It's intent is to test that the untrusted input from a EFI_GPT_DATA > > > structure > > > ++ will not cause an overflow when calculating the event size. > > > ++ > > > ++ @param[in] Context The unit test context. > > > ++ > > > ++ @retval UNIT_TEST_PASSED The test passed. > > > ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. > > > ++**/ > > > ++UNIT_TEST_STATUS > > > ++EFIAPI > > > ++TestSanitizePrimaryHeaderGptEventSize ( > > > ++ IN UNIT_TEST_CONTEXT Context > > > ++ ) > > > ++{ > > > ++ UINT32 EventSize; > > > ++ UINT32 ExistingLogicEventSize; > > > ++ EFI_STATUS Status; > > > ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; > > > ++ UINTN NumberOfPartition; > > > ++ EFI_GPT_DATA *GptData; > > > ++ EFI_TCG2_EVENT *Tcg2Event; > > > ++ > > > ++ Tcg2Event = NULL; > > > ++ GptData = NULL; > > > ++ > > > ++ // Test that a normal PrimaryHeader passes validation > > > ++ PrimaryHeader.NumberOfPartitionEntries = 5; > > > ++ PrimaryHeader.SizeOfPartitionEntry = > > > DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; > > > ++ > > > ++ // set the number of partitions > > > ++ NumberOfPartition = 13; > > > ++ > > > ++ // that the primary event size is correct > > > ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, > > > NumberOfPartition, &EventSize); > > > ++ UT_ASSERT_NOT_EFI_ERROR (Status); > > > ++ > > > ++ // Calculate the existing logic event size > > > ++ ExistingLogicEventSize = (UINT32)(OFFSET_OF (EFI_TCG2_EVENT, Event) + > > > OFFSET_OF (EFI_GPT_DATA, Partitions) > > > ++ + NumberOfPartition * > > > PrimaryHeader.SizeOfPartitionEntry); > > > ++ > > > ++ // Check that the event size is correct > > > ++ UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); > > > ++ > > > ++ // Tests that the primary event size may not overflow > > > ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, > > > MAX_UINT32, &EventSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ // Test that the size of partition entries may not overflow > > > ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; > > > ++ Status = > > > SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, > > > &EventSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); > > > ++ > > > ++ return UNIT_TEST_PASSED; > > > ++} > > > ++ > > > ++// > > > *--------------------------------------------------------------------* > > > ++// * Unit Test Code Main Function > > > ++// > > > *--------------------------------------------------------------------* > > > ++ > > > ++/** > > > ++ This function acts as the entry point for the unit tests. > > > ++ > > > ++ @retval UNIT_TEST_PASSED The test passed. > > > ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. > > > ++ @retval others The test failed. > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++UefiTestMain ( > > > ++ VOID > > > ++ ) > > > ++{ > > > ++ EFI_STATUS Status; > > > ++ UNIT_TEST_FRAMEWORK_HANDLE Framework; > > > ++ UNIT_TEST_SUITE_HANDLE Tcg2MeasureBootLibValidationTestSuite; > > > ++ > > > ++ Framework = NULL; > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME)); > > > ++ > > > ++ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, > > > gEfiCallerBaseName, UNIT_TEST_VERSION); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = > > > %r\n", UNIT_TEST_NAME, Status)); > > > ++ goto EXIT; > > > ++ } > > > ++ > > > ++ Status = CreateUnitTestSuite (&Tcg2MeasureBootLibValidationTestSuite, > > > Framework, "Tcg2MeasureBootLibValidationTestSuite", > > > "Common.Tcg2MeasureBootLibValidation", NULL, NULL); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for > > > Tcg2MeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME)); > > > ++ Status = EFI_OUT_OF_RESOURCES; > > > ++ goto EXIT; > > > ++ } > > > ++ > > > ++ // > > > -----------Suite---------------------------------Description----------------------------Class----------------------------------Test > > > Function------------------------Pre---Clean-Context > > > ++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating > > > EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", > > > TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL); > > > ++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary > > > header gpt event checks for overflow", > > > "Common.Tcg2MeasureBootLibValidation", > > > TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL); > > > ++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary > > > header allocation size checks for overflow", > > > "Common.Tcg2MeasureBootLibValidation", > > > TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL); > > > ++ > > > ++ Status = RunAllTestSuites (Framework); > > > ++ > > > ++EXIT: > > > ++ if (Framework != NULL) { > > > ++ FreeUnitTestFramework (Framework); > > > ++ } > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME)); > > > ++ return Status; > > > ++} > > > ++ > > > ++/// > > > ++/// Avoid ECC error for function name that starts with lower case letter > > > ++/// > > > ++#define DxeTpm2MeasureBootLibUnitTestMain main > > > ++ > > > ++/** > > > ++ Standard POSIX C entry point for host based unit test execution. > > > ++ > > > ++ @param[in] Argc Number of arguments > > > ++ @param[in] Argv Array of pointers to arguments > > > ++ > > > ++ @retval 0 Success > > > ++ @retval other Error > > > ++**/ > > > ++INT32 > > > ++DxeTpm2MeasureBootLibUnitTestMain ( > > > ++ IN INT32 Argc, > > > ++ IN CHAR8 *Argv[] > > > ++ ) > > > ++{ > > > ++ return (INT32)UefiTestMain (); > > > ++} > > > +diff --git > > > a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf > > > > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf > > > +new file mode 100644 > > > +index 0000000000..2999aa2a44 > > > +--- /dev/null > > > ++++ > > > b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf > > > +@@ -0,0 +1,28 @@ > > > ++## @file > > > ++# This file builds the unit tests for DxeTpm2MeasureBootLib > > > ++# > > > ++# Copyright (C) Microsoft Corporation.<BR> > > > ++# SPDX-License-Identifier: BSD-2-Clause-Patent > > > ++## > > > ++ > > > ++[Defines] > > > ++ INF_VERSION = 0x00010006 > > > ++ BASE_NAME = DxeTpm2MeasuredBootLibTest > > > ++ FILE_GUID = 144d757f-d423-484e-9309-a23695fad5bd > > > ++ MODULE_TYPE = HOST_APPLICATION > > > ++ VERSION_STRING = 1.0 > > > ++ ENTRY_POINT = main > > > ++ > > > ++[Sources] > > > ++ DxeTpm2MeasureBootLibSanitizationTest.c > > > ++ ../DxeTpm2MeasureBootLibSanitization.c > > > ++ > > > ++[Packages] > > > ++ MdePkg/MdePkg.dec > > > ++ > > > ++[LibraryClasses] > > > ++ BaseLib > > > ++ DebugLib > > > ++ UnitTestLib > > > ++ PrintLib > > > ++ SafeIntLib > > > +diff --git a/SecurityPkg/SecurityPkg.ci.yaml > > > b/SecurityPkg/SecurityPkg.ci.yaml > > > +index 7912142398..da811fdf93 100644 > > > +--- a/SecurityPkg/SecurityPkg.ci.yaml > > > ++++ b/SecurityPkg/SecurityPkg.ci.yaml > > > +@@ -15,6 +15,7 @@ > > > + ## "<ErrorID>", "<KeyWord>" > > > + ## ] > > > + "ExceptionList": [ > > > ++ "8001", "DxeTpm2MeasureBootLibUnitTestMain", > > > + ], > > > + ## Both file path and directory path are accepted. > > > + "IgnoreFiles": [ > > > +-- > > > +2.40.0 > > > + > > > diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch > > > b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch > > > new file mode 100644 > > > index 0000000000..6c20cc305e > > > --- /dev/null > > > +++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch > > > @@ -0,0 +1,889 @@ > > > +From 4776a1b39ee08fc45c70c1eab5a0195f325000d3 Mon Sep 17 00:00:00 2001 > > > +From: "Douglas Flick [MSFT]" <[email protected]> > > > +Date: Fri, 12 Jan 2024 02:16:02 +0800 > > > +Subject: [PATCH] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117 > > > - CVE > > > + 2022-36763 > > > + > > > +This commit contains the patch files and tests for DxeTpmMeasureBootLib > > > +CVE 2022-36763. > > > + > > > +Cc: Jiewen Yao <[email protected]> > > > + > > > +Signed-off-by: Doug Flick [MSFT] <[email protected]> > > > +Reviewed-by: Jiewen Yao <[email protected]> > > > + > > > +CVE: CVE-2022-36763 > > > + > > > +Upstream-Status: Backport > > > [https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3] > > > + > > > +Signed-off-by: Soumya Sambu <[email protected]> > > > +--- > > > + .../DxeTpmMeasureBootLib.c | 40 ++- > > > + .../DxeTpmMeasureBootLib.inf | 4 +- > > > + .../DxeTpmMeasureBootLibSanitization.c | 241 ++++++++++++++ > > > + .../DxeTpmMeasureBootLibSanitization.h | 114 +++++++ > > > + .../DxeTpmMeasureBootLibSanitizationTest.c | 301 ++++++++++++++++++ > > > + ...eTpmMeasureBootLibSanitizationTestHost.inf | 28 ++ > > > + SecurityPkg/SecurityPkg.ci.yaml | 1 + > > > + 7 files changed, 715 insertions(+), 14 deletions(-) > > > + create mode 100644 > > > SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c > > > + create mode 100644 > > > SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h > > > + create mode 100644 > > > SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c > > > + create mode 100644 > > > SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf > > > + > > > +diff --git > > > a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c > > > +index 220393dd2b..669ab19134 100644 > > > +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c > > > ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c > > > +@@ -18,6 +18,8 @@ > > > + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> > > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > > + > > > ++Copyright (c) Microsoft Corporation.<BR> > > > ++SPDX-License-Identifier: BSD-2-Clause-Patent > > > + **/ > > > + > > > + #include <PiDxe.h> > > > +@@ -40,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > > > + #include <Library/SecurityManagementLib.h> > > > + #include <Library/HobLib.h> > > > + > > > ++#include "DxeTpmMeasureBootLibSanitization.h" > > > ++ > > > + // > > > + // Flag to check GPT partition. It only need be measured once. > > > + // > > > +@@ -136,6 +140,9 @@ TcgMeasureGptTable ( > > > + UINT32 EventSize; > > > + UINT32 EventNumber; > > > + EFI_PHYSICAL_ADDRESS EventLogLastEntry; > > > ++ UINT32 AllocSize; > > > ++ > > > ++ GptData = NULL; > > > + > > > + if (mMeasureGptCount > 0) { > > > + return EFI_SUCCESS; > > > +@@ -166,8 +173,8 @@ TcgMeasureGptTable ( > > > + BlockIo->Media->BlockSize, > > > + (UINT8 *)PrimaryHeader > > > + ); > > > +- if (EFI_ERROR (Status)) { > > > +- DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n")); > > > ++ if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader > > > (PrimaryHeader, BlockIo))) { > > > ++ DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or > > > invalid Partition Table Header!\n")); > > > + FreePool (PrimaryHeader); > > > + return EFI_DEVICE_ERROR; > > > + } > > > +@@ -175,7 +182,13 @@ TcgMeasureGptTable ( > > > + // > > > + // Read the partition entry. > > > + // > > > +- EntryPtr = (UINT8 *)AllocatePool > > > (PrimaryHeader->NumberOfPartitionEntries * > > > PrimaryHeader->SizeOfPartitionEntry); > > > ++ Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, > > > &AllocSize); > > > ++ if (EFI_ERROR (Status)) { > > > ++ FreePool (PrimaryHeader); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ EntryPtr = (UINT8 *)AllocatePool (AllocSize); > > > + if (EntryPtr == NULL) { > > > + FreePool (PrimaryHeader); > > > + return EFI_OUT_OF_RESOURCES; > > > +@@ -185,7 +198,7 @@ TcgMeasureGptTable ( > > > + DiskIo, > > > + BlockIo->Media->MediaId, > > > + MultU64x32 (PrimaryHeader->PartitionEntryLBA, > > > BlockIo->Media->BlockSize), > > > +- PrimaryHeader->NumberOfPartitionEntries * > > > PrimaryHeader->SizeOfPartitionEntry, > > > ++ AllocSize, > > > + EntryPtr > > > + ); > > > + if (EFI_ERROR (Status)) { > > > +@@ -210,9 +223,8 @@ TcgMeasureGptTable ( > > > + // > > > + // Prepare Data for Measurement > > > + // > > > +- EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof > > > (GptData->Partitions) > > > +- + NumberOfPartition * > > > PrimaryHeader->SizeOfPartitionEntry); > > > +- TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize + sizeof > > > (TCG_PCR_EVENT_HDR)); > > > ++ Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, > > > NumberOfPartition, &EventSize); > > > ++ TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize); > > > + if (TcgEvent == NULL) { > > > + FreePool (PrimaryHeader); > > > + FreePool (EntryPtr); > > > +@@ -221,7 +233,7 @@ TcgMeasureGptTable ( > > > + > > > + TcgEvent->PCRIndex = 5; > > > + TcgEvent->EventType = EV_EFI_GPT_EVENT; > > > +- TcgEvent->EventSize = EventSize; > > > ++ TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR); > > > + GptData = (EFI_GPT_DATA *)TcgEvent->Event; > > > + > > > + // > > > +@@ -361,11 +373,13 @@ TcgMeasurePeImage ( > > > + TcgEvent->PCRIndex = 2; > > > + break; > > > + default: > > > +- DEBUG (( > > > +- DEBUG_ERROR, > > > +- "TcgMeasurePeImage: Unknown subsystem type %d", > > > +- ImageType > > > +- )); > > > ++ DEBUG ( > > > ++ ( > > > ++ DEBUG_ERROR, > > > ++ "TcgMeasurePeImage: Unknown subsystem type %d", > > > ++ ImageType > > > ++ ) > > > ++ ); > > > + goto Finish; > > > + } > > > + > > > +diff --git > > > a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf > > > +index ebab6f7c1e..414c654d15 100644 > > > +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf > > > ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf > > > +@@ -32,6 +32,8 @@ > > > + > > > + [Sources] > > > + DxeTpmMeasureBootLib.c > > > ++ DxeTpmMeasureBootLibSanitization.c > > > ++ DxeTpmMeasureBootLibSanitization.h > > > + > > > + [Packages] > > > + MdePkg/MdePkg.dec > > > +@@ -41,6 +43,7 @@ > > > + > > > + [LibraryClasses] > > > + BaseMemoryLib > > > ++ SafeIntLib > > > + DebugLib > > > + MemoryAllocationLib > > > + DevicePathLib > > > +@@ -59,4 +62,3 @@ > > > + gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES > > > + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES > > > + gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES > > > +- > > > +diff --git > > > a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c > > > > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c > > > +new file mode 100644 > > > +index 0000000000..a3fa46f5e6 > > > +--- /dev/null > > > ++++ > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c > > > +@@ -0,0 +1,241 @@ > > > ++/** @file > > > ++ The library instance provides security service of TPM2 measure boot > > > and > > > ++ Confidential Computing (CC) measure boot. > > > ++ > > > ++ Caution: This file requires additional review when modified. > > > ++ This library will have external input - PE/COFF image and GPT > > > partition. > > > ++ This external input must be validated carefully to avoid security > > > issue like > > > ++ buffer overflow, integer overflow. > > > ++ > > > ++ This file will pull out the validation logic from the following > > > functions, in an > > > ++ attempt to validate the untrusted input in the form of unit tests > > > ++ > > > ++ These are those functions: > > > ++ > > > ++ DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF > > > image content > > > ++ read is within the image buffer. > > > ++ > > > ++ Tcg2MeasureGptTable() function will receive untrusted GPT partition > > > table, and parse > > > ++ partition data carefully. > > > ++ > > > ++ Copyright (c) Microsoft Corporation.<BR> > > > ++ SPDX-License-Identifier: BSD-2-Clause-Patent > > > ++**/ > > > ++#include <Uefi.h> > > > ++#include <Uefi/UefiSpec.h> > > > ++#include <Library/SafeIntLib.h> > > > ++#include <Library/UefiLib.h> > > > ++#include <Library/DebugLib.h> > > > ++#include <Library/BaseLib.h> > > > ++#include <IndustryStandard/UefiTcgPlatform.h> > > > ++#include <Protocol/BlockIo.h> > > > ++#include <Library/MemoryAllocationLib.h> > > > ++ > > > ++#include "DxeTpmMeasureBootLibSanitization.h" > > > ++ > > > ++#define GPT_HEADER_REVISION_V1 0x00010000 > > > ++ > > > ++/** > > > ++ This function will validate the EFI_PARTITION_TABLE_HEADER structure > > > is safe to parse > > > ++ However this function will not attempt to verify the validity of the > > > GPT partition > > > ++ It will check the following: > > > ++ - Signature > > > ++ - Revision > > > ++ - AlternateLBA > > > ++ - FirstUsableLBA > > > ++ - LastUsableLBA > > > ++ - PartitionEntryLBA > > > ++ - NumberOfPartitionEntries > > > ++ - SizeOfPartitionEntry > > > ++ - BlockIo > > > ++ > > > ++ @param[in] PrimaryHeader > > > ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. > > > ++ > > > ++ @param[in] BlockIo > > > ++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The EFI_PARTITION_TABLE_HEADER structure is valid. > > > ++ > > > ++ @retval EFI_INVALID_PARAMETER > > > ++ The EFI_PARTITION_TABLE_HEADER structure is invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++SanitizeEfiPartitionTableHeader ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo > > > ++ ) > > > ++{ > > > ++ // Verify that the input parameters are safe to use > > > ++ if (PrimaryHeader == NULL) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ if ((BlockIo == NULL) || (BlockIo->Media == NULL)) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n")); > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII) > > > ++ if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // The version must be GPT_HEADER_REVISION_V1 (0x00010000) > > > ++ if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // The HeaderSize must be greater than or equal to 92 and must be > > > less than or equal to the logical block size > > > ++ if ((PrimaryHeader->Header.HeaderSize < sizeof > > > (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > > > > BlockIo->Media->BlockSize)) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header > > > HeaderSize!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // check that the PartitionEntryLBA greater than the Max LBA > > > ++ // This will be used later for multiplication > > > ++ if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, > > > BlockIo->Media->BlockSize)) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header > > > PartitionEntryLBA!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // Check that the number of partition entries is greater than zero > > > ++ if (PrimaryHeader->NumberOfPartitionEntries == 0) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header > > > NumberOfPartitionEntries!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // SizeOfPartitionEntry must be 128, 256, 512... improper size may > > > lead to accessing uninitialized memory > > > ++ if ((PrimaryHeader->SizeOfPartitionEntry < 128) || > > > ((PrimaryHeader->SizeOfPartitionEntry & > > > (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) { > > > ++ DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry shall be set to a value > > > of 128 x 2^n where n is an integer greater than or equal to zero (e.g., > > > 128, 256, 512, etc.)!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ // This check is to prevent overflow when calculating the allocation > > > size for the partition entries > > > ++ // This check will be used later for multiplication > > > ++ if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, > > > PrimaryHeader->SizeOfPartitionEntry)) { > > > ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header > > > NumberOfPartitionEntries!\n")); > > > ++ return EFI_DEVICE_ERROR; > > > ++ } > > > ++ > > > ++ return EFI_SUCCESS; > > > ++} > > > ++ > > > ++/** > > > ++ This function will validate that the allocation size from the primary > > > header is sane > > > ++ It will check the following: > > > ++ - AllocationSize does not overflow > > > ++ > > > ++ @param[in] PrimaryHeader > > > ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. > > > ++ > > > ++ @param[out] AllocationSize > > > ++ Pointer to the allocation size. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The allocation size is valid. > > > ++ > > > ++ @retval EFI_OUT_OF_RESOURCES > > > ++ The allocation size is invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++SanitizePrimaryHeaderAllocationSize ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ OUT UINT32 *AllocationSize > > > ++ ) > > > ++{ > > > ++ EFI_STATUS Status; > > > ++ > > > ++ if (PrimaryHeader == NULL) { > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ if (AllocationSize == NULL) { > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ // Replacing logic: > > > ++ // PrimaryHeader->NumberOfPartitionEntries * > > > PrimaryHeader->SizeOfPartitionEntry; > > > ++ Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, > > > PrimaryHeader->SizeOfPartitionEntry, AllocationSize); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n")); > > > ++ return EFI_BAD_BUFFER_SIZE; > > > ++ } > > > ++ > > > ++ return EFI_SUCCESS; > > > ++} > > > ++ > > > ++/** > > > ++ This function will validate that the Gpt Event Size calculated from > > > the primary header is sane > > > ++ It will check the following: > > > ++ - EventSize does not overflow > > > ++ > > > ++ Important: This function includes the entire length of the allocated > > > space, including the > > > ++ TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, > > > the caller must subtract > > > ++ the size of the TCG_PCR_EVENT_HDR from the size of the buffer before > > > hashing. > > > ++ > > > ++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER > > > structure. > > > ++ @param[in] NumberOfPartition - Number of partitions. > > > ++ @param[out] EventSize - Pointer to the event size. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The event size is valid. > > > ++ > > > ++ @retval EFI_OUT_OF_RESOURCES > > > ++ Overflow would have occurred. > > > ++ > > > ++ @retval EFI_INVALID_PARAMETER > > > ++ One of the passed parameters was invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++SanitizePrimaryHeaderGptEventSize ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ IN UINTN NumberOfPartition, > > > ++ OUT UINT32 *EventSize > > > ++ ) > > > ++{ > > > ++ EFI_STATUS Status; > > > ++ UINT32 SafeNumberOfPartitions; > > > ++ > > > ++ if (PrimaryHeader == NULL) { > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ if (EventSize == NULL) { > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ // We shouldn't even attempt to perform the multiplication if the > > > number of partitions is greater than the maximum value of UINT32 > > > ++ Status = SafeUintnToUint32 (NumberOfPartition, > > > &SafeNumberOfPartitions); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n")); > > > ++ return EFI_INVALID_PARAMETER; > > > ++ } > > > ++ > > > ++ // Replacing logic: > > > ++ // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + > > > NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry + sizeof > > > (TCG_PCR_EVENT_HDR)); > > > ++ Status = SafeUint32Mult (SafeNumberOfPartitions, > > > PrimaryHeader->SizeOfPartitionEntry, EventSize); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n")); > > > ++ return EFI_BAD_BUFFER_SIZE; > > > ++ } > > > ++ > > > ++ Status = SafeUint32Add ( > > > ++ sizeof (TCG_PCR_EVENT_HDR) + > > > ++ OFFSET_OF (EFI_GPT_DATA, Partitions), > > > ++ *EventSize, > > > ++ EventSize > > > ++ ); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of > > > GPTData!\n")); > > > ++ return EFI_BAD_BUFFER_SIZE; > > > ++ } > > > ++ > > > ++ return EFI_SUCCESS; > > > ++} > > > +diff --git > > > a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h > > > > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h > > > +new file mode 100644 > > > +index 0000000000..0d9d00c281 > > > +--- /dev/null > > > ++++ > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h > > > +@@ -0,0 +1,114 @@ > > > ++/** @file > > > ++ This file includes the function prototypes for the sanitization > > > functions. > > > ++ > > > ++ These are those functions: > > > ++ > > > ++ DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF > > > image content > > > ++ read is within the image buffer. > > > ++ > > > ++ TcgMeasurePeImage() function will accept untrusted PE/COFF image and > > > validate its > > > ++ data structure within this image buffer before use. > > > ++ > > > ++ TcgMeasureGptTable() function will receive untrusted GPT partition > > > table, and parse > > > ++ partition data carefully. > > > ++ > > > ++ Copyright (c) Microsoft Corporation.<BR> > > > ++ SPDX-License-Identifier: BSD-2-Clause-Patent > > > ++ > > > ++**/ > > > ++ > > > ++#ifndef DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ > > > ++#define DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ > > > ++ > > > ++#include <Uefi.h> > > > ++#include <Uefi/UefiSpec.h> > > > ++#include <Protocol/BlockIo.h> > > > ++#include <IndustryStandard/UefiTcgPlatform.h> > > > ++ > > > ++/** > > > ++ This function will validate the EFI_PARTITION_TABLE_HEADER structure > > > is safe to parse > > > ++ However this function will not attempt to verify the validity of the > > > GPT partition > > > ++ It will check the following: > > > ++ - Signature > > > ++ - Revision > > > ++ - AlternateLBA > > > ++ - FirstUsableLBA > > > ++ - LastUsableLBA > > > ++ - PartitionEntryLBA > > > ++ - NumberOfPartitionEntries > > > ++ - SizeOfPartitionEntry > > > ++ - BlockIo > > > ++ > > > ++ @param[in] PrimaryHeader > > > ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. > > > ++ > > > ++ @param[in] BlockIo > > > ++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The EFI_PARTITION_TABLE_HEADER structure is valid. > > > ++ > > > ++ @retval EFI_INVALID_PARAMETER > > > ++ The EFI_PARTITION_TABLE_HEADER structure is invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++SanitizeEfiPartitionTableHeader ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo > > > ++ ); > > > ++ > > > ++/** > > > ++ This function will validate that the allocation size from the primary > > > header is sane > > > ++ It will check the following: > > > ++ - AllocationSize does not overflow > > > ++ > > > ++ @param[in] PrimaryHeader > > > ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. > > > ++ > > > ++ @param[out] AllocationSize > > > ++ Pointer to the allocation size. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The allocation size is valid. > > > ++ > > > ++ @retval EFI_OUT_OF_RESOURCES > > > ++ The allocation size is invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++SanitizePrimaryHeaderAllocationSize ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ OUT UINT32 *AllocationSize > > > ++ ); > > > ++ > > > ++/** > > > ++ This function will validate that the Gpt Event Size calculated from > > > the primary header is sane > > > ++ It will check the following: > > > ++ - EventSize does not overflow > > > ++ > > > ++ Important: This function includes the entire length of the allocated > > > space, including the > > > ++ TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, > > > the caller must subtract > > > ++ the size of the TCG_PCR_EVENT_HDR from the size of the buffer before > > > hashing. > > > ++ > > > ++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER > > > structure. > > > ++ @param[in] NumberOfPartition - Number of partitions. > > > ++ @param[out] EventSize - Pointer to the event size. > > > ++ > > > ++ @retval EFI_SUCCESS > > > ++ The event size is valid. > > > ++ > > > ++ @retval EFI_OUT_OF_RESOURCES > > > ++ Overflow would have occurred. > > > ++ > > > ++ @retval EFI_INVALID_PARAMETER > > > ++ One of the passed parameters was invalid. > > > ++**/ > > > ++EFI_STATUS > > > ++SanitizePrimaryHeaderGptEventSize ( > > > ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, > > > ++ IN UINTN NumberOfPartition, > > > ++ OUT UINT32 *EventSize > > > ++ ); > > > ++ > > > ++#endif // DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ > > > +diff --git > > > a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c > > > > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c > > > +new file mode 100644 > > > +index 0000000000..eeb928cdb0 > > > +--- /dev/null > > > ++++ > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c > > > +@@ -0,0 +1,301 @@ > > > ++/** @file > > > ++This file includes the unit test cases for the > > > DxeTpmMeasureBootLibSanitizationTest.c. > > > ++ > > > ++Copyright (c) Microsoft Corporation.<BR> > > > ++SPDX-License-Identifier: BSD-2-Clause-Patent > > > ++**/ > > > ++ > > > ++#include <Uefi.h> > > > ++#include <Library/UefiLib.h> > > > ++#include <Library/DebugLib.h> > > > ++#include <Library/UnitTestLib.h> > > > ++#include <Protocol/BlockIo.h> > > > ++#include <Library/MemoryAllocationLib.h> > > > ++#include <Library/BaseMemoryLib.h> > > > ++#include <IndustryStandard/UefiTcgPlatform.h> > > > ++ > > > ++#include "../DxeTpmMeasureBootLibSanitization.h" > > > ++ > > > ++#define UNIT_TEST_NAME "DxeTpmMeasureBootLibSanitizationTest" > > > ++#define UNIT_TEST_VERSION "1.0" > > > ++ > > > ++#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION > > > 0x00010000 > > > ++#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1 > > > ++#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128 > > > ++ > > > ++/** > > > ++ This function tests the SanitizeEfiPartitionTableHeader function. > > > ++ It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER > > > ++ structure will not cause undefined or unexpected behavior. > > > ++ > > > ++ In general the TPM should still be able to measure the data, but > > > ++ be the header should be sanitized to prevent any unexpected behavior. > > > ++ > > > ++ @param[in] Context The unit test context. > > > ++ > > > ++ @retval UNIT_TEST_PASSED The test passed. > > > ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. > > > ++**/ > > > ++UNIT_TEST_STATUS > > > ++EFIAPI > > > ++TestSanitizeEfiPartitionTableHeader ( > > > ++ IN UNIT_TEST_CONTEXT Context > > > ++ ) > > > ++{ > > > ++ EFI_STATUS Status; > > > ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; > > > ++ EFI_BLOCK_IO_PROTOCOL BlockIo; > > > ++ EFI_BLOCK_IO_MEDIA BlockMedia; > > > ++ > > > ++ // Generate EFI_BLOCK_IO_MEDIA test data > > > ++ BlockMedia.MediaId = 1; > > > ++ BlockMedia.RemovableMedia = FALSE; > > > ++ BlockMedia.MediaPresent = TRUE; > > > ++ BlockMedia.LogicalPartition = FALSE; > > > ++ BlockMedia.ReadOnly = FALSE; > > > ++ BlockMedia.WriteCaching = FALSE; > > > ++ BlockMedia.BlockSize = 512; > > > ++ BlockMedia.IoAlign = 1; > > > ++ BlockMedia.LastBlock = 0; > > > ++ > > > ++ // Generate EFI_BLOCK_IO_PROTOCOL test data > > > ++ BlockIo.Revision = 1; > > > ++ BlockIo.Media = &BlockMedia; > > > ++ BlockIo.Reset = NULL; > > > ++ BlockIo.ReadBlocks = NULL; > > > ++ BlockIo.WriteBlocks = NULL; > > > ++ BlockIo.FlushBlocks = NULL; > > > ++ > > > ++ // Geneate EFI_PARTITION_TABLE_HEADER test data > > > ++ PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID; > > > ++ PrimaryHeader.Header.Revision = > > > DEFAULT_PRIMARY_TABLE_HEADER_REVISION; > > > ++ PrimaryHeader.Header.HeaderSize = sizeof > > > (EFI_PARTITION_TABLE_HEADER); > > > ++ PrimaryHeader.MyLBA = 1; > > > ++ PrimaryHeader.AlternateLBA = 2; > > > ++ PrimaryHeader.FirstUsableLBA = 3; > > > ++ PrimaryHeader.LastUsableLBA = 4; > > > ++ PrimaryHeader.PartitionEntryLBA = 5; > > > ++ PrimaryHeader.NumberOfPartitionEntries = > > > DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES; > > > ++ PrimaryHeader.SizeOfPartitionEntry = > > > DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; > > > ++ PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid > > > ++ > > > ++ // Calculate the CRC32 of the PrimaryHeader > > > ++ PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, > > > PrimaryHeader.Header.HeaderSize); > > > ++ > > > ++ // Test that a normal PrimaryHeader passes validation > > > ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); > > > ++ UT_ASSERT_NOT_EFI_ERROR (Status); > > > ++ > > > ++ // Test that when number of partition entries is 0, the function > > > returns EFI_DEVICE_ERROR > > > ++ // Should print "Invalid Partition Table Header > > > NumberOfPartitionEntries!"" > > > ++ PrimaryHeader.NumberOfPartitionEntries = 0; > > > ++ Status = > > > SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); > > > ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); > > > ++ PrimaryHeader.NumberOfPartitionEntries = > > > DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; > > > ++ > > > ++ // Test that when the header size is too small, the function returns > > > EFI_DEVICE_ERROR > > > ++ // Should print "Invalid Partition Table Header Size!" > > > ++ PrimaryHeader.Header.HeaderSize = 0; > > > ++ Status = SanitizeEfiPartitionTableHeader > > > (&PrimaryHeader, &BlockIo); > > > ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); > > > ++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); > > > ++ > > > ++ // Test that when the SizeOfPartitionEntry is too small, the function > > > returns EFI_DEVICE_ERROR > > > ++ // should print: "SizeOfPartitionEntry shall be set to a value of 128 > > > x 2^n where n is an integer greater than or equal to zero (e.g., 128, > > > 256, 512, etc.)!" > > > ++ PrimaryHeader.SizeOfPartitionEntry = 1; > > > ++ Status = SanitizeEfiPartitionTableHeader > > > (&PrimaryHeader, &BlockIo); > > > ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); > > > ++ > > > ++ return UNIT_TEST_PASSED; > > > ++} > > > ++ > > > ++/** > > > ++ This function tests the SanitizePrimaryHeaderAllocationSize function. > > > ++ It's intent is to test that the untrusted input from a > > > EFI_PARTITION_TABLE_HEADER > > > ++ structure will not cause an overflow when calculating the allocation > > > size. > > > ++ > > > ++ @param[in] Context The unit test context. > > > ++ > > > ++ @retval UNIT_TEST_PASSED The test passed. > > > ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. > > > ++**/ > > > ++UNIT_TEST_STATUS > > > ++EFIAPI > > > ++TestSanitizePrimaryHeaderAllocationSize ( > > > ++ IN UNIT_TEST_CONTEXT Context > > > ++ ) > > > ++{ > > > ++ UINT32 AllocationSize; > > > ++ > > > ++ EFI_STATUS Status; > > > ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; > > > ++ > > > ++ // Test that a normal PrimaryHeader passes validation > > > ++ PrimaryHeader.NumberOfPartitionEntries = 5; > > > ++ PrimaryHeader.SizeOfPartitionEntry = > > > DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; > > > ++ > > > ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, > > > &AllocationSize); > > > ++ UT_ASSERT_NOT_EFI_ERROR (Status); > > > ++ > > > ++ // Test that the allocation size is correct compared to the existing > > > logic > > > ++ UT_ASSERT_EQUAL (AllocationSize, > > > PrimaryHeader.NumberOfPartitionEntries * > > > PrimaryHeader.SizeOfPartitionEntry); > > > ++ > > > ++ // Test that an overflow is detected > > > ++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; > > > ++ PrimaryHeader.SizeOfPartitionEntry = 5; > > > ++ Status = > > > SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ // Test the inverse > > > ++ PrimaryHeader.NumberOfPartitionEntries = 5; > > > ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; > > > ++ Status = > > > SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ // Test the worst case scenario > > > ++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; > > > ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; > > > ++ Status = > > > SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); > > > ++ > > > ++ return UNIT_TEST_PASSED; > > > ++} > > > ++ > > > ++/** > > > ++ This function tests the SanitizePrimaryHeaderGptEventSize function. > > > ++ It's intent is to test that the untrusted input from a EFI_GPT_DATA > > > structure > > > ++ will not cause an overflow when calculating the event size. > > > ++ > > > ++ @param[in] Context The unit test context. > > > ++ > > > ++ @retval UNIT_TEST_PASSED The test passed. > > > ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. > > > ++**/ > > > ++UNIT_TEST_STATUS > > > ++EFIAPI > > > ++TestSanitizePrimaryHeaderGptEventSize ( > > > ++ IN UNIT_TEST_CONTEXT Context > > > ++ ) > > > ++{ > > > ++ UINT32 EventSize; > > > ++ UINT32 ExistingLogicEventSize; > > > ++ EFI_STATUS Status; > > > ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; > > > ++ UINTN NumberOfPartition; > > > ++ EFI_GPT_DATA *GptData; > > > ++ > > > ++ GptData = NULL; > > > ++ > > > ++ // Test that a normal PrimaryHeader passes validation > > > ++ PrimaryHeader.NumberOfPartitionEntries = 5; > > > ++ PrimaryHeader.SizeOfPartitionEntry = > > > DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; > > > ++ > > > ++ // set the number of partitions > > > ++ NumberOfPartition = 13; > > > ++ > > > ++ // that the primary event size is correct > > > ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, > > > NumberOfPartition, &EventSize); > > > ++ UT_ASSERT_NOT_EFI_ERROR (Status); > > > ++ > > > ++ // Calculate the existing logic event size > > > ++ ExistingLogicEventSize = (UINT32)(sizeof (TCG_PCR_EVENT_HDR) + > > > OFFSET_OF (EFI_GPT_DATA, Partitions) > > > ++ + NumberOfPartition * > > > PrimaryHeader.SizeOfPartitionEntry); > > > ++ > > > ++ // Check that the event size is correct > > > ++ UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); > > > ++ > > > ++ // Tests that the primary event size may not overflow > > > ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, > > > MAX_UINT32, &EventSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ // Test that the size of partition entries may not overflow > > > ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; > > > ++ Status = > > > SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, > > > &EventSize); > > > ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); > > > ++ > > > ++ return UNIT_TEST_PASSED; > > > ++} > > > ++ > > > ++// > > > *--------------------------------------------------------------------* > > > ++// * Unit Test Code Main Function > > > ++// > > > *--------------------------------------------------------------------* > > > ++ > > > ++/** > > > ++ This function acts as the entry point for the unit tests. > > > ++ > > > ++ @param argc - The number of command line arguments > > > ++ @param argv - The command line arguments > > > ++ > > > ++ @return int - The status of the test > > > ++**/ > > > ++EFI_STATUS > > > ++EFIAPI > > > ++UefiTestMain ( > > > ++ VOID > > > ++ ) > > > ++{ > > > ++ EFI_STATUS Status; > > > ++ UNIT_TEST_FRAMEWORK_HANDLE Framework; > > > ++ UNIT_TEST_SUITE_HANDLE TcgMeasureBootLibValidationTestSuite; > > > ++ > > > ++ Framework = NULL; > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME)); > > > ++ > > > ++ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, > > > gEfiCallerBaseName, UNIT_TEST_VERSION); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = > > > %r\n", UNIT_TEST_NAME, Status)); > > > ++ goto EXIT; > > > ++ } > > > ++ > > > ++ Status = CreateUnitTestSuite (&TcgMeasureBootLibValidationTestSuite, > > > Framework, "TcgMeasureBootLibValidationTestSuite", > > > "Common.TcgMeasureBootLibValidation", NULL, NULL); > > > ++ if (EFI_ERROR (Status)) { > > > ++ DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for > > > TcgMeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME)); > > > ++ Status = EFI_OUT_OF_RESOURCES; > > > ++ goto EXIT; > > > ++ } > > > ++ > > > ++ // > > > -----------Suite---------------------------------Description----------------------------Class----------------------------------Test > > > Function------------------------Pre---Clean-Context > > > ++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating > > > EFI Partition Table", "Common.TcgMeasureBootLibValidation", > > > TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL); > > > ++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary > > > header gpt event checks for overflow", > > > "Common.TcgMeasureBootLibValidation", > > > TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL); > > > ++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary > > > header allocation size checks for overflow", > > > "Common.TcgMeasureBootLibValidation", > > > TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL); > > > ++ > > > ++ Status = RunAllTestSuites (Framework); > > > ++ > > > ++EXIT: > > > ++ if (Framework != NULL) { > > > ++ FreeUnitTestFramework (Framework); > > > ++ } > > > ++ > > > ++ DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME)); > > > ++ return Status; > > > ++} > > > ++ > > > ++/// > > > ++/// Avoid ECC error for function name that starts with lower case letter > > > ++/// > > > ++#define DxeTpmMeasureBootLibUnitTestMain main > > > ++ > > > ++/** > > > ++ Standard POSIX C entry point for host based unit test execution. > > > ++ > > > ++ @param[in] Argc Number of arguments > > > ++ @param[in] Argv Array of pointers to arguments > > > ++ > > > ++ @retval 0 Success > > > ++ @retval other Error > > > ++**/ > > > ++INT32 > > > ++DxeTpmMeasureBootLibUnitTestMain ( > > > ++ IN INT32 Argc, > > > ++ IN CHAR8 *Argv[] > > > ++ ) > > > ++{ > > > ++ return (INT32)UefiTestMain (); > > > ++} > > > +diff --git > > > a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf > > > > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf > > > +new file mode 100644 > > > +index 0000000000..47b0811b00 > > > +--- /dev/null > > > ++++ > > > b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf > > > +@@ -0,0 +1,28 @@ > > > ++## @file > > > ++# This file builds the unit tests for DxeTpmMeasureBootLib > > > ++# > > > ++# Copyright (C) Microsoft Corporation.<BR> > > > ++# SPDX-License-Identifier: BSD-2-Clause-Patent > > > ++## > > > ++ > > > ++[Defines] > > > ++ INF_VERSION = 0x00010006 > > > ++ BASE_NAME = DxeTpmMeasuredBootLibTest > > > ++ FILE_GUID = eb01bc38-309c-4d3e-967e-9f078c90772f > > > ++ MODULE_TYPE = HOST_APPLICATION > > > ++ VERSION_STRING = 1.0 > > > ++ ENTRY_POINT = main > > > ++ > > > ++[Sources] > > > ++ DxeTpmMeasureBootLibSanitizationTest.c > > > ++ ../DxeTpmMeasureBootLibSanitization.c > > > ++ > > > ++[Packages] > > > ++ MdePkg/MdePkg.dec > > > ++ > > > ++[LibraryClasses] > > > ++ BaseLib > > > ++ DebugLib > > > ++ UnitTestLib > > > ++ PrintLib > > > ++ SafeIntLib > > > +diff --git a/SecurityPkg/SecurityPkg.ci.yaml > > > b/SecurityPkg/SecurityPkg.ci.yaml > > > +index da811fdf93..0e40eaa0fe 100644 > > > +--- a/SecurityPkg/SecurityPkg.ci.yaml > > > ++++ b/SecurityPkg/SecurityPkg.ci.yaml > > > +@@ -16,6 +16,7 @@ > > > + ## ] > > > + "ExceptionList": [ > > > + "8001", "DxeTpm2MeasureBootLibUnitTestMain", > > > ++ "8001", "DxeTpmMeasureBootLibUnitTestMain" > > > + ], > > > + ## Both file path and directory path are accepted. > > > + "IgnoreFiles": [ > > > +-- > > > +2.40.0 > > > + > > > diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch > > > b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch > > > new file mode 100644 > > > index 0000000000..59bd5c4910 > > > --- /dev/null > > > +++ b/meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch > > > @@ -0,0 +1,55 @@ > > > +From 1ddcb9fc6b4164e882687b031e8beacfcf7df29e Mon Sep 17 00:00:00 2001 > > > +From: "Douglas Flick [MSFT]" <[email protected]> > > > +Date: Fri, 12 Jan 2024 02:16:03 +0800 > > > +Subject: [PATCH] SecurityPkg: : Adding CVE 2022-36763 to > > > SecurityFixes.yaml > > > + > > > +This creates / adds a security file that tracks the security fixes > > > +found in this package and can be used to find the fixes that were > > > +applied. > > > + > > > +Cc: Jiewen Yao <[email protected]> > > > + > > > +Signed-off-by: Doug Flick [MSFT] <[email protected]> > > > +Reviewed-by: Jiewen Yao <[email protected]> > > > + > > > +CVE: CVE-2022-36763 > > > + > > > +Upstream-Status: Backport > > > [https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e] > > > + > > > +Signed-off-by: Soumya Sambu <[email protected]> > > > +--- > > > + SecurityPkg/SecurityFixes.yaml | 22 ++++++++++++++++++++++ > > > + 1 file changed, 22 insertions(+) > > > + create mode 100644 SecurityPkg/SecurityFixes.yaml > > > + > > > +diff --git a/SecurityPkg/SecurityFixes.yaml > > > b/SecurityPkg/SecurityFixes.yaml > > > +new file mode 100644 > > > +index 0000000000..f9e3e7be74 > > > +--- /dev/null > > > ++++ b/SecurityPkg/SecurityFixes.yaml > > > +@@ -0,0 +1,22 @@ > > > ++## @file > > > ++# Security Fixes for SecurityPkg > > > ++# > > > ++# Copyright (c) Microsoft Corporation > > > ++# SPDX-License-Identifier: BSD-2-Clause-Patent > > > ++## > > > ++CVE_2022_36763: > > > ++ commit_titles: > > > ++ - "SecurityPkg: DxeTpm2Measurement: SECURITY PATCH 4117 - CVE > > > 2022-36763" > > > ++ - "SecurityPkg: DxeTpmMeasurement: SECURITY PATCH 4117 - CVE > > > 2022-36763" > > > ++ - "SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml" > > > ++ cve: CVE-2022-36763 > > > ++ date_reported: 2022-10-25 11:31 UTC > > > ++ description: (CVE-2022-36763) - Heap Buffer Overflow in > > > Tcg2MeasureGptTable() > > > ++ note: This patch is related to and supersedes TCBZ2168 > > > ++ files_impacted: > > > ++ - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c > > > ++ - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c > > > ++ links: > > > ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4117 > > > ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=2168 > > > ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=1990 > > > +-- > > > +2.40.0 > > > + > > > diff --git a/meta/recipes-core/ovmf/ovmf_git.bb > > > b/meta/recipes-core/ovmf/ovmf_git.bb > > > index 84e3360a3a..78d86ad879 100644 > > > --- a/meta/recipes-core/ovmf/ovmf_git.bb > > > +++ b/meta/recipes-core/ovmf/ovmf_git.bb > > > @@ -27,6 +27,9 @@ SRC_URI = > > > "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \ > > > file://0006-reproducible.patch \ > > > file://0001-BaseTools-fix-gcc12-warning.patch \ > > > file://0001-BaseTools-fix-gcc12-warning-1.patch \ > > > + file://CVE-2022-36763-0001.patch \ > > > + file://CVE-2022-36763-0002.patch \ > > > + file://CVE-2022-36763-0003.patch \ > > > " > > > > > > PV = "edk2-stable202202" > > > -- > > > 2.25.1 > > > > > >
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#208160): https://lists.openembedded.org/g/openembedded-core/message/208160 Mute This Topic: https://lists.openembedded.org/mt/109784095/21656 Group Owner: [email protected] Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
