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 (#207934):
https://lists.openembedded.org/g/openembedded-core/message/207934
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]]
-=-=-=-=-=-=-=-=-=-=-=-