diff mbox series

[kirkstone,01/11] ovmf: Fix CVE-2022-36763

Message ID 20240711045541.2155076-1-soumya.sambu@windriver.com
State Changes Requested
Delegated to: Steve Sakoman
Headers show
Series [kirkstone,01/11] ovmf: Fix CVE-2022-36763 | expand

Commit Message

ssambu July 11, 2024, 4:55 a.m. UTC
From: Soumya Sambu <soumya.sambu@windriver.com>

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 <soumya.sambu@windriver.com>
---
 .../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

Comments

Steve Sakoman July 11, 2024, 6:34 p.m. UTC | #1
There appear to be line ending issues with all of the patches in this series:

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)

Steve

On Wed, Jul 10, 2024 at 9:56 PM Soumya via lists.openembedded.org
<soumya.sambu=windriver.com@lists.openembedded.org> wrote:
>
> From: Soumya Sambu <soumya.sambu@windriver.com>
>
> 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 <soumya.sambu@windriver.com>
> ---
>  .../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]" <doug.edk2@gmail.com>
> +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 <jiewen.yao@intel.com>
> +
> +Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> +
> +CVE: CVE-2022-36763
> +
> +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b]
> +
> +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
> +---
> + .../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]" <doug.edk2@gmail.com>
> +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 <jiewen.yao@intel.com>
> +
> +Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> +Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
> +
> +CVE: CVE-2022-36763
> +
> +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3]
> +
> +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
> +---
> + .../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]" <doug.edk2@gmail.com>
> +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 <jiewen.yao@intel.com>
> +
> +Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> +Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
> +
> +CVE: CVE-2022-36763
> +
> +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e]
> +
> +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
> +---
> + 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.40.0
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#201751): https://lists.openembedded.org/g/openembedded-core/message/201751
> Mute This Topic: https://lists.openembedded.org/mt/107157592/3620601
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
ssambu July 11, 2024, 6:46 p.m. UTC | #2
Hi Steve,

Kindly apply patch using: git am --keep-cr <patch> to retain the line endings.

Regards,
Soumya
________________________________
From: Steve Sakoman <steve@sakoman.com>
Sent: Friday, July 12, 2024 12:04 AM
To: Sambu, Soumya <Soumya.Sambu@windriver.com>
Cc: openembedded-core@lists.openembedded.org <openembedded-core@lists.openembedded.org>
Subject: Re: [OE-core][kirkstone][PATCH 01/11] 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.

There appear to be line ending issues with all of the patches in this series:

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)

Steve

On Wed, Jul 10, 2024 at 9:56 PM Soumya via lists.openembedded.org
<soumya.sambu=windriver.com@lists.openembedded.org> wrote:
>
> From: Soumya Sambu <soumya.sambu@windriver.com>
>
> 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 <soumya.sambu@windriver.com>
> ---
>  .../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]" <doug.edk2@gmail.com>
> +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 <jiewen.yao@intel.com>
> +
> +Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> +
> +CVE: CVE-2022-36763
> +
> +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b]
> +
> +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
> +---
> + .../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]" <doug.edk2@gmail.com>
> +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 <jiewen.yao@intel.com>
> +
> +Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> +Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
> +
> +CVE: CVE-2022-36763
> +
> +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3]
> +
> +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
> +---
> + .../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]" <doug.edk2@gmail.com>
> +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 <jiewen.yao@intel.com>
> +
> +Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> +Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
> +
> +CVE: CVE-2022-36763
> +
> +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e]
> +
> +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
> +---
> + 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.40.0
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#201751): https://lists.openembedded.org/g/openembedded-core/message/201751
> Mute This Topic: https://lists.openembedded.org/mt/107157592/3620601
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Steve Sakoman July 11, 2024, 7:04 p.m. UTC | #3
On Thu, Jul 11, 2024 at 11:46 AM Sambu, Soumya
<Soumya.Sambu@windriver.com> wrote:
>
> Hi Steve,
>
> Kindly apply patch using: git am --keep-cr <patch> to retain the line endings.

This does not fix the issue.  To confirm, please try applying your
patches to kirkstone head from the mailing list or patchworks and then
build ovmf.

Steve
>
> Regards,
> Soumya
> ________________________________
> From: Steve Sakoman <steve@sakoman.com>
> Sent: Friday, July 12, 2024 12:04 AM
> To: Sambu, Soumya <Soumya.Sambu@windriver.com>
> Cc: openembedded-core@lists.openembedded.org <openembedded-core@lists.openembedded.org>
> Subject: Re: [OE-core][kirkstone][PATCH 01/11] 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.
>
> There appear to be line ending issues with all of the patches in this series:
>
> 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)
>
> Steve
>
> On Wed, Jul 10, 2024 at 9:56 PM Soumya via lists.openembedded.org
> <soumya.sambu=windriver.com@lists.openembedded.org> wrote:
> >
> > From: Soumya Sambu <soumya.sambu@windriver.com>
> >
> > 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 <soumya.sambu@windriver.com>
> > ---
> >  .../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]" <doug.edk2@gmail.com>
> > +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 <jiewen.yao@intel.com>
> > +
> > +Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> > +
> > +CVE: CVE-2022-36763
> > +
> > +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b]
> > +
> > +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
> > +---
> > + .../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]" <doug.edk2@gmail.com>
> > +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 <jiewen.yao@intel.com>
> > +
> > +Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> > +Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
> > +
> > +CVE: CVE-2022-36763
> > +
> > +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3]
> > +
> > +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
> > +---
> > + .../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]" <doug.edk2@gmail.com>
> > +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 <jiewen.yao@intel.com>
> > +
> > +Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> > +Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
> > +
> > +CVE: CVE-2022-36763
> > +
> > +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e]
> > +
> > +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
> > +---
> > + 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.40.0
> >
> >
> > -=-=-=-=-=-=-=-=-=-=-=-
> > Links: You receive all messages sent to this group.
> > View/Reply Online (#201751): https://lists.openembedded.org/g/openembedded-core/message/201751
> > Mute This Topic: https://lists.openembedded.org/mt/107157592/3620601
> > Group Owner: openembedded-core+owner@lists.openembedded.org
> > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com]
> > -=-=-=-=-=-=-=-=-=-=-=-
> >
diff mbox series

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]" <doug.edk2@gmail.com>
+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 <jiewen.yao@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+
+CVE: CVE-2022-36763
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/224446543206450ddb5830e6abd026d61d3c7f4b]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../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]" <doug.edk2@gmail.com>
+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 <jiewen.yao@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
+
+CVE: CVE-2022-36763
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4776a1b39ee08fc45c70c1eab5a0195f325000d3]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ .../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]" <doug.edk2@gmail.com>
+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 <jiewen.yao@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
+
+CVE: CVE-2022-36763
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1ddcb9fc6b4164e882687b031e8beacfcf7df29e]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ 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"