]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/commitdiff
ovmf: Fix CVE-2022-36763
authorSoumya Sambu <soumya.sambu@windriver.com>
Fri, 28 Jun 2024 08:37:27 +0000 (08:37 +0000)
committerHongxu Jia <hongxu.jia@windriver.com>
Wed, 4 Dec 2024 03:30:09 +0000 (11:30 +0800)
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>
meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0001.patch [new file with mode: 0644]
meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0002.patch [new file with mode: 0644]
meta/recipes-core/ovmf/ovmf/CVE-2022-36763-0003.patch [new file with mode: 0644]
meta/recipes-core/ovmf/ovmf_git.bb

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 (file)
index 0000000..93cefe7
--- /dev/null
@@ -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>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
++Copyright (c) Microsoft Corporation.<BR>\r
++SPDX-License-Identifier: BSD-2-Clause-Patent\r
+ **/\r
\r
+ #include <PiDxe.h>\r
+@@ -44,6 +46,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
+ #include <Library/HobLib.h>\r
+ #include <Protocol/CcMeasurement.h>\r
\r
++#include "DxeTpm2MeasureBootLibSanitization.h"\r
++\r
+ typedef struct {\r
+   EFI_TCG2_PROTOCOL              *Tcg2Protocol;\r
+   EFI_CC_MEASUREMENT_PROTOCOL    *CcProtocol;\r
+@@ -144,10 +148,11 @@ Tcg2MeasureGptTable (
+   EFI_TCG2_EVENT               *Tcg2Event;\r
+   EFI_CC_EVENT                 *CcEvent;\r
+   EFI_GPT_DATA                 *GptData;\r
+-  UINT32                       EventSize;\r
++  UINT32                       TcgEventSize;\r
+   EFI_TCG2_PROTOCOL            *Tcg2Protocol;\r
+   EFI_CC_MEASUREMENT_PROTOCOL  *CcProtocol;\r
+   EFI_CC_MR_INDEX              MrIndex;\r
++  UINT32                       AllocSize;\r
\r
+   if (mTcg2MeasureGptCount > 0) {\r
+     return EFI_SUCCESS;\r
+@@ -195,25 +200,22 @@ Tcg2MeasureGptTable (
+                      BlockIo->Media->BlockSize,\r
+                      (UINT8 *)PrimaryHeader\r
+                      );\r
+-  if (EFI_ERROR (Status)) {\r
+-    DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n"));\r
++  if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {\r
++    DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n"));\r
+     FreePool (PrimaryHeader);\r
+     return EFI_DEVICE_ERROR;\r
+   }\r
\r
+   //\r
+-  // PrimaryHeader->SizeOfPartitionEntry should not be zero\r
++  // Read the partition entry.\r
+   //\r
+-  if (PrimaryHeader->SizeOfPartitionEntry == 0) {\r
+-    DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n"));\r
++  Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);\r
++  if (EFI_ERROR (Status)) {\r
+     FreePool (PrimaryHeader);\r
+     return EFI_BAD_BUFFER_SIZE;\r
+   }\r
\r
+-  //\r
+-  // Read the partition entry.\r
+-  //\r
+-  EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);\r
++  EntryPtr = (UINT8 *)AllocatePool (AllocSize);\r
+   if (EntryPtr == NULL) {\r
+     FreePool (PrimaryHeader);\r
+     return EFI_OUT_OF_RESOURCES;\r
+@@ -223,7 +225,7 @@ Tcg2MeasureGptTable (
+                      DiskIo,\r
+                      BlockIo->Media->MediaId,\r
+                      MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
+-                     PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,\r
++                     AllocSize,\r
+                      EntryPtr\r
+                      );\r
+   if (EFI_ERROR (Status)) {\r
+@@ -248,16 +250,21 @@ Tcg2MeasureGptTable (
+   //\r
+   // Prepare Data for Measurement (CcProtocol and Tcg2Protocol)\r
+   //\r
+-  EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)\r
+-                       + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
+-  EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));\r
++  Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize);\r
++  if (EFI_ERROR (Status)) {\r
++    FreePool (PrimaryHeader);\r
++    FreePool (EntryPtr);\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  EventPtr = (UINT8 *)AllocateZeroPool (TcgEventSize);\r
+   if (EventPtr == NULL) {\r
+     Status = EFI_OUT_OF_RESOURCES;\r
+     goto Exit;\r
+   }\r
\r
+   Tcg2Event                       = (EFI_TCG2_EVENT *)EventPtr;\r
+-  Tcg2Event->Size                 = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);\r
++  Tcg2Event->Size                 = TcgEventSize;\r
+   Tcg2Event->Header.HeaderSize    = sizeof (EFI_TCG2_EVENT_HEADER);\r
+   Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;\r
+   Tcg2Event->Header.PCRIndex      = 5;\r
+@@ -310,7 +317,7 @@ Tcg2MeasureGptTable (
+                                             CcProtocol,\r
+                                             0,\r
+                                             (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,\r
+-                                            (UINT64)EventSize,\r
++                                            (UINT64)TcgEventSize - OFFSET_OF (EFI_TCG2_EVENT, Event),\r
+                                             CcEvent\r
+                                             );\r
+     if (!EFI_ERROR (Status)) {\r
+@@ -326,7 +333,7 @@ Tcg2MeasureGptTable (
+                              Tcg2Protocol,\r
+                              0,\r
+                              (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,\r
+-                             (UINT64)EventSize,\r
++                             (UINT64)TcgEventSize -  OFFSET_OF (EFI_TCG2_EVENT, Event),\r
+                              Tcg2Event\r
+                              );\r
+     if (!EFI_ERROR (Status)) {\r
+@@ -443,11 +450,13 @@ Tcg2MeasurePeImage (
+       Tcg2Event->Header.PCRIndex  = 2;\r
+       break;\r
+     default:\r
+-      DEBUG ((\r
+-        DEBUG_ERROR,\r
+-        "Tcg2MeasurePeImage: Unknown subsystem type %d",\r
+-        ImageType\r
+-        ));\r
++      DEBUG (\r
++        (\r
++         DEBUG_ERROR,\r
++         "Tcg2MeasurePeImage: Unknown subsystem type %d",\r
++         ImageType\r
++        )\r
++        );\r
+       goto Finish;\r
+   }\r
\r
+@@ -515,7 +524,7 @@ Finish:
\r
+   @param  MeasureBootProtocols  Pointer to the located measure boot protocol instances.\r
\r
+-  @retval EFI_SUCCESS           Sucessfully locate the measure boot protocol instances (at least one instance).\r
++  @retval EFI_SUCCESS           Successfully locate the measure boot protocol instances (at least one instance).\r
+   @retval EFI_UNSUPPORTED       Measure boot is not supported.\r
+ **/\r
+ EFI_STATUS\r
+@@ -646,12 +655,14 @@ DxeTpm2MeasureBootHandler (
+     return EFI_SUCCESS;\r
+   }\r
\r
+-  DEBUG ((\r
+-    DEBUG_INFO,\r
+-    "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n",\r
+-    MeasureBootProtocols.Tcg2Protocol,\r
+-    MeasureBootProtocols.CcProtocol\r
+-    ));\r
++  DEBUG (\r
++    (\r
++     DEBUG_INFO,\r
++     "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n",\r
++     MeasureBootProtocols.Tcg2Protocol,\r
++     MeasureBootProtocols.CcProtocol\r
++    )\r
++    );\r
\r
+   //\r
+   // Copy File Device Path\r
+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 @@
\r
+ [Sources]\r
+   DxeTpm2MeasureBootLib.c\r
++  DxeTpm2MeasureBootLibSanitization.c\r
++  DxeTpm2MeasureBootLibSanitization.h\r
\r
+ [Packages]\r
+   MdePkg/MdePkg.dec\r
+@@ -46,6 +48,7 @@
\r
+ [LibraryClasses]\r
+   BaseMemoryLib\r
++  SafeIntLib\r
+   DebugLib\r
+   MemoryAllocationLib\r
+   DevicePathLib\r
+@@ -65,4 +68,3 @@
+   gEfiFirmwareVolumeBlockProtocolGuid   ## SOMETIMES_CONSUMES\r
+   gEfiBlockIoProtocolGuid               ## SOMETIMES_CONSUMES\r
+   gEfiDiskIoProtocolGuid                ## SOMETIMES_CONSUMES\r
+-\r
+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\r
++  The library instance provides security service of TPM2 measure boot and\r
++  Confidential Computing (CC) measure boot.\r
++\r
++  Caution: This file requires additional review when modified.\r
++  This library will have external input - PE/COFF image and GPT partition.\r
++  This external input must be validated carefully to avoid security issue like\r
++  buffer overflow, integer overflow.\r
++\r
++  This file will pull out the validation logic from the following functions, in an\r
++  attempt to validate the untrusted input in the form of unit tests\r
++\r
++  These are those functions:\r
++\r
++  DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content\r
++  read is within the image buffer.\r
++\r
++  Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse\r
++  partition data carefully.\r
++\r
++  Copyright (c) Microsoft Corporation.<BR>\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++#include <Uefi.h>\r
++#include <Uefi/UefiSpec.h>\r
++#include <Library/SafeIntLib.h>\r
++#include <Library/UefiLib.h>\r
++#include <Library/DebugLib.h>\r
++#include <Library/BaseLib.h>\r
++#include <IndustryStandard/UefiTcgPlatform.h>\r
++#include <Protocol/BlockIo.h>\r
++#include <Library/MemoryAllocationLib.h>\r
++\r
++#include "DxeTpm2MeasureBootLibSanitization.h"\r
++\r
++#define GPT_HEADER_REVISION_V1  0x00010000\r
++\r
++/**\r
++  This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse\r
++  However this function will not attempt to verify the validity of the GPT partition\r
++  It will check the following:\r
++    - Signature\r
++    - Revision\r
++    - AlternateLBA\r
++    - FirstUsableLBA\r
++    - LastUsableLBA\r
++    - PartitionEntryLBA\r
++    - NumberOfPartitionEntries\r
++    - SizeOfPartitionEntry\r
++    - BlockIo\r
++\r
++  @param[in] PrimaryHeader\r
++    Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++\r
++  @param[in] BlockIo\r
++    Pointer to the EFI_BLOCK_IO_PROTOCOL structure.\r
++\r
++  @retval EFI_SUCCESS\r
++    The EFI_PARTITION_TABLE_HEADER structure is valid.\r
++\r
++  @retval EFI_INVALID_PARAMETER\r
++    The EFI_PARTITION_TABLE_HEADER structure is invalid.\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++SanitizeEfiPartitionTableHeader (\r
++  IN CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  IN CONST EFI_BLOCK_IO_PROTOCOL       *BlockIo\r
++  )\r
++{\r
++  //\r
++  // Verify that the input parameters are safe to use\r
++  //\r
++  if (PrimaryHeader == NULL) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n"));\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if ((BlockIo == NULL) || (BlockIo->Media == NULL)) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n"));\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  //\r
++  // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII)\r
++  //\r
++  if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  //\r
++  // The version must be GPT_HEADER_REVISION_V1 (0x00010000)\r
++  //\r
++  if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  //\r
++  // The HeaderSize must be greater than or equal to 92 and must be less than or equal to the logical block size\r
++  //\r
++  if ((PrimaryHeader->Header.HeaderSize < sizeof (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > BlockIo->Media->BlockSize)) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header HeaderSize!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  //\r
++  // The partition entries should all be before the first usable block\r
++  //\r
++  if (PrimaryHeader->FirstUsableLBA <= PrimaryHeader->PartitionEntryLBA) {\r
++    DEBUG ((DEBUG_ERROR, "GPT PartitionEntryLBA is not less than FirstUsableLBA!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  //\r
++  // Check that the PartitionEntryLBA greater than the Max LBA\r
++  // This will be used later for multiplication\r
++  //\r
++  if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, BlockIo->Media->BlockSize)) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header PartitionEntryLBA!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  //\r
++  // Check that the number of partition entries is greater than zero\r
++  //\r
++  if (PrimaryHeader->NumberOfPartitionEntries == 0) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  //\r
++  // SizeOfPartitionEntry must be 128, 256, 512... improper size may lead to accessing uninitialized memory\r
++  //\r
++  if ((PrimaryHeader->SizeOfPartitionEntry < 128) || ((PrimaryHeader->SizeOfPartitionEntry & (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) {\r
++    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"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  //\r
++  // This check is to prevent overflow when calculating the allocation size for the partition entries\r
++  // This check will be used later for multiplication\r
++  //\r
++  if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, PrimaryHeader->SizeOfPartitionEntry)) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++/**\r
++  This function will validate that the allocation size from the primary header is sane\r
++  It will check the following:\r
++    - AllocationSize does not overflow\r
++\r
++  @param[in] PrimaryHeader\r
++    Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++\r
++  @param[out] AllocationSize\r
++    Pointer to the allocation size.\r
++\r
++  @retval EFI_SUCCESS\r
++    The allocation size is valid.\r
++\r
++  @retval EFI_OUT_OF_RESOURCES\r
++    The allocation size is invalid.\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++SanitizePrimaryHeaderAllocationSize (\r
++  IN CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  OUT UINT32                           *AllocationSize\r
++  )\r
++{\r
++  EFI_STATUS  Status;\r
++\r
++  if (PrimaryHeader == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if (AllocationSize == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  //\r
++  // Replacing logic:\r
++  // PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry;\r
++  //\r
++  Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry, AllocationSize);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n"));\r
++    return EFI_BAD_BUFFER_SIZE;\r
++  }\r
++\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++/**\r
++  This function will validate that the Gpt Event Size calculated from the primary header is sane\r
++  It will check the following:\r
++    - EventSize does not overflow\r
++\r
++  Important: This function includes the entire length of the allocated space, including\r
++  (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing the buffer allocated with this\r
++  size, the caller must subtract the size of the (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event))\r
++  from the size of the buffer before hashing.\r
++\r
++  @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++  @param[in] NumberOfPartition - Number of partitions.\r
++  @param[out] EventSize - Pointer to the event size.\r
++\r
++  @retval EFI_SUCCESS\r
++    The event size is valid.\r
++\r
++  @retval EFI_OUT_OF_RESOURCES\r
++    Overflow would have occurred.\r
++\r
++  @retval EFI_INVALID_PARAMETER\r
++    One of the passed parameters was invalid.\r
++**/\r
++EFI_STATUS\r
++SanitizePrimaryHeaderGptEventSize (\r
++  IN  CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  IN  UINTN                             NumberOfPartition,\r
++  OUT UINT32                            *EventSize\r
++  )\r
++{\r
++  EFI_STATUS  Status;\r
++  UINT32      SafeNumberOfPartitions;\r
++\r
++  if (PrimaryHeader == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if (EventSize == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  //\r
++  // We shouldn't even attempt to perform the multiplication if the number of partitions is greater than the maximum value of UINT32\r
++  //\r
++  Status = SafeUintnToUint32 (NumberOfPartition, &SafeNumberOfPartitions);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n"));\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  //\r
++  // Replacing logic:\r
++  // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry);\r
++  //\r
++  Status = SafeUint32Mult (SafeNumberOfPartitions, PrimaryHeader->SizeOfPartitionEntry, EventSize);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n"));\r
++    return EFI_BAD_BUFFER_SIZE;\r
++  }\r
++\r
++  //\r
++  // Replacing logic:\r
++  // *EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);\r
++  //\r
++  Status = SafeUint32Add (\r
++             OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF (EFI_GPT_DATA, Partitions),\r
++             *EventSize,\r
++             EventSize\r
++             );\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of GPTData!\n"));\r
++    return EFI_BAD_BUFFER_SIZE;\r
++  }\r
++\r
++  return EFI_SUCCESS;\r
++}\r
+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\r
++  This file includes the function prototypes for the sanitization functions.\r
++\r
++  These are those functions:\r
++\r
++  DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content\r
++  read is within the image buffer.\r
++\r
++  Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse\r
++  partition data carefully.\r
++\r
++  Copyright (c) Microsoft Corporation.<BR>\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++\r
++**/\r
++\r
++#ifndef DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_\r
++#define DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_\r
++\r
++#include <Uefi.h>\r
++#include <Uefi/UefiSpec.h>\r
++#include <Protocol/BlockIo.h>\r
++#include <IndustryStandard/UefiTcgPlatform.h>\r
++#include <Protocol/Tcg2Protocol.h>\r
++\r
++/**\r
++  This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse\r
++  However this function will not attempt to verify the validity of the GPT partition\r
++  It will check the following:\r
++    - Signature\r
++    - Revision\r
++    - AlternateLBA\r
++    - FirstUsableLBA\r
++    - LastUsableLBA\r
++    - PartitionEntryLBA\r
++    - NumberOfPartitionEntries\r
++    - SizeOfPartitionEntry\r
++    - BlockIo\r
++\r
++  @param[in] PrimaryHeader\r
++    Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++\r
++  @param[in] BlockIo\r
++    Pointer to the EFI_BLOCK_IO_PROTOCOL structure.\r
++\r
++  @retval EFI_SUCCESS\r
++    The EFI_PARTITION_TABLE_HEADER structure is valid.\r
++\r
++  @retval EFI_INVALID_PARAMETER\r
++    The EFI_PARTITION_TABLE_HEADER structure is invalid.\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++SanitizeEfiPartitionTableHeader (\r
++  IN CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  IN CONST EFI_BLOCK_IO_PROTOCOL       *BlockIo\r
++  );\r
++\r
++/**\r
++  This function will validate that the allocation size from the primary header is sane\r
++  It will check the following:\r
++    - AllocationSize does not overflow\r
++\r
++  @param[in] PrimaryHeader\r
++    Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++\r
++  @param[out] AllocationSize\r
++    Pointer to the allocation size.\r
++\r
++  @retval EFI_SUCCESS\r
++    The allocation size is valid.\r
++\r
++  @retval EFI_OUT_OF_RESOURCES\r
++    The allocation size is invalid.\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++SanitizePrimaryHeaderAllocationSize (\r
++  IN CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  OUT UINT32                           *AllocationSize\r
++  );\r
++\r
++/**\r
++  This function will validate that the Gpt Event Size calculated from the primary header is sane\r
++  It will check the following:\r
++    - EventSize does not overflow\r
++\r
++  Important: This function includes the entire length of the allocated space, including\r
++  (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing the buffer allocated with this\r
++  size, the caller must subtract the size of the (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event))\r
++  from the size of the buffer before hashing.\r
++\r
++  @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++  @param[in] NumberOfPartition - Number of partitions.\r
++  @param[out] EventSize - Pointer to the event size.\r
++\r
++  @retval EFI_SUCCESS\r
++    The event size is valid.\r
++\r
++  @retval EFI_OUT_OF_RESOURCES\r
++    Overflow would have occurred.\r
++\r
++  @retval EFI_INVALID_PARAMETER\r
++    One of the passed parameters was invalid.\r
++**/\r
++EFI_STATUS\r
++SanitizePrimaryHeaderGptEventSize (\r
++  IN  CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  IN  UINTN                             NumberOfPartition,\r
++  OUT UINT32                            *EventSize\r
++  );\r
++\r
++#endif // DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_\r
+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\r
++  This file includes the unit test cases for the DxeTpm2MeasureBootLibSanitizationTest.c.\r
++\r
++  Copyright (c) Microsoft Corporation.<BR>\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++\r
++#include <Uefi.h>\r
++#include <Library/UefiLib.h>\r
++#include <Library/DebugLib.h>\r
++#include <Library/UnitTestLib.h>\r
++#include <Protocol/BlockIo.h>\r
++#include <Library/MemoryAllocationLib.h>\r
++#include <Library/BaseMemoryLib.h>\r
++#include <IndustryStandard/UefiTcgPlatform.h>\r
++#include <Protocol/Tcg2Protocol.h>\r
++\r
++#include "../DxeTpm2MeasureBootLibSanitization.h"\r
++\r
++#define UNIT_TEST_NAME     "DxeTpm2MeasureBootLibSanitizationTest"\r
++#define UNIT_TEST_VERSION  "1.0"\r
++\r
++#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION                     0x00010000\r
++#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES  1\r
++#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY      128\r
++\r
++/**\r
++  This function tests the SanitizeEfiPartitionTableHeader function.\r
++  It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER\r
++  structure will not cause undefined or unexpected behavior.\r
++\r
++  In general the TPM should still be able to measure the data, but\r
++  be the header should be sanitized to prevent any unexpected behavior.\r
++\r
++  @param[in] Context  The unit test context.\r
++\r
++  @retval UNIT_TEST_PASSED  The test passed.\r
++  @retval UNIT_TEST_ERROR_TEST_FAILED  The test failed.\r
++**/\r
++UNIT_TEST_STATUS\r
++EFIAPI\r
++TestSanitizeEfiPartitionTableHeader (\r
++  IN UNIT_TEST_CONTEXT  Context\r
++  )\r
++{\r
++  EFI_STATUS                  Status;\r
++  EFI_PARTITION_TABLE_HEADER  PrimaryHeader;\r
++  EFI_BLOCK_IO_PROTOCOL       BlockIo;\r
++  EFI_BLOCK_IO_MEDIA          BlockMedia;\r
++\r
++  // Generate EFI_BLOCK_IO_MEDIA test data\r
++  BlockMedia.MediaId          = 1;\r
++  BlockMedia.RemovableMedia   = FALSE;\r
++  BlockMedia.MediaPresent     = TRUE;\r
++  BlockMedia.LogicalPartition = FALSE;\r
++  BlockMedia.ReadOnly         = FALSE;\r
++  BlockMedia.WriteCaching     = FALSE;\r
++  BlockMedia.BlockSize        = 512;\r
++  BlockMedia.IoAlign          = 1;\r
++  BlockMedia.LastBlock        = 0;\r
++\r
++  // Generate EFI_BLOCK_IO_PROTOCOL test data\r
++  BlockIo.Revision    = 1;\r
++  BlockIo.Media       = &BlockMedia;\r
++  BlockIo.Reset       = NULL;\r
++  BlockIo.ReadBlocks  = NULL;\r
++  BlockIo.WriteBlocks = NULL;\r
++  BlockIo.FlushBlocks = NULL;\r
++\r
++  // Geneate EFI_PARTITION_TABLE_HEADER test data\r
++  PrimaryHeader.Header.Signature         = EFI_PTAB_HEADER_ID;\r
++  PrimaryHeader.Header.Revision          = DEFAULT_PRIMARY_TABLE_HEADER_REVISION;\r
++  PrimaryHeader.Header.HeaderSize        = sizeof (EFI_PARTITION_TABLE_HEADER);\r
++  PrimaryHeader.MyLBA                    = 1;\r
++  PrimaryHeader.AlternateLBA             = 2;\r
++  PrimaryHeader.FirstUsableLBA           = 3;\r
++  PrimaryHeader.LastUsableLBA            = 4;\r
++  PrimaryHeader.PartitionEntryLBA        = 5;\r
++  PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES;\r
++  PrimaryHeader.SizeOfPartitionEntry     = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;\r
++  PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid\r
++\r
++  // Calculate the CRC32 of the PrimaryHeader\r
++  PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize);\r
++\r
++  // Test that a normal PrimaryHeader passes validation\r
++  Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);\r
++  UT_ASSERT_NOT_EFI_ERROR (Status);\r
++\r
++  // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR\r
++  // Should print "Invalid Partition Table Header NumberOfPartitionEntries!""\r
++  PrimaryHeader.NumberOfPartitionEntries = 0;\r
++  Status                                 = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);\r
++  UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);\r
++  PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;\r
++\r
++  // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR\r
++  // Should print "Invalid Partition Table Header Size!"\r
++  PrimaryHeader.Header.HeaderSize = 0;\r
++  Status                          = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);\r
++  UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);\r
++  PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);\r
++\r
++  // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR\r
++  // 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.)!"\r
++  PrimaryHeader.SizeOfPartitionEntry = 1;\r
++  Status                             = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);\r
++  UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));\r
++\r
++  return UNIT_TEST_PASSED;\r
++}\r
++\r
++/**\r
++  This function tests the SanitizePrimaryHeaderAllocationSize function.\r
++  It's intent is to test that the untrusted input from a EFI_PARTITION_TABLE_HEADER\r
++  structure will not cause an overflow when calculating the allocation size.\r
++\r
++  @param[in] Context  The unit test context.\r
++\r
++  @retval UNIT_TEST_PASSED  The test passed.\r
++  @retval UNIT_TEST_ERROR_TEST_FAILED  The test failed.\r
++**/\r
++UNIT_TEST_STATUS\r
++EFIAPI\r
++TestSanitizePrimaryHeaderAllocationSize (\r
++  IN UNIT_TEST_CONTEXT  Context\r
++  )\r
++{\r
++  UINT32  AllocationSize;\r
++\r
++  EFI_STATUS                  Status;\r
++  EFI_PARTITION_TABLE_HEADER  PrimaryHeader;\r
++\r
++  // Test that a normal PrimaryHeader passes validation\r
++  PrimaryHeader.NumberOfPartitionEntries = 5;\r
++  PrimaryHeader.SizeOfPartitionEntry     = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;\r
++\r
++  Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);\r
++  UT_ASSERT_NOT_EFI_ERROR (Status);\r
++\r
++  // Test that the allocation size is correct compared to the existing logic\r
++  UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry);\r
++\r
++  // Test that an overflow is detected\r
++  PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;\r
++  PrimaryHeader.SizeOfPartitionEntry     = 5;\r
++  Status                                 = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  // Test the inverse\r
++  PrimaryHeader.NumberOfPartitionEntries = 5;\r
++  PrimaryHeader.SizeOfPartitionEntry     = MAX_UINT32;\r
++  Status                                 = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  // Test the worst case scenario\r
++  PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;\r
++  PrimaryHeader.SizeOfPartitionEntry     = MAX_UINT32;\r
++  Status                                 = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));\r
++\r
++  return UNIT_TEST_PASSED;\r
++}\r
++\r
++/**\r
++  This function tests the SanitizePrimaryHeaderGptEventSize function.\r
++  It's intent is to test that the untrusted input from a EFI_GPT_DATA structure\r
++  will not cause an overflow when calculating the event size.\r
++\r
++  @param[in] Context  The unit test context.\r
++\r
++  @retval UNIT_TEST_PASSED  The test passed.\r
++  @retval UNIT_TEST_ERROR_TEST_FAILED  The test failed.\r
++**/\r
++UNIT_TEST_STATUS\r
++EFIAPI\r
++TestSanitizePrimaryHeaderGptEventSize (\r
++  IN UNIT_TEST_CONTEXT  Context\r
++  )\r
++{\r
++  UINT32                      EventSize;\r
++  UINT32                      ExistingLogicEventSize;\r
++  EFI_STATUS                  Status;\r
++  EFI_PARTITION_TABLE_HEADER  PrimaryHeader;\r
++  UINTN                       NumberOfPartition;\r
++  EFI_GPT_DATA                *GptData;\r
++  EFI_TCG2_EVENT              *Tcg2Event;\r
++\r
++  Tcg2Event = NULL;\r
++  GptData   = NULL;\r
++\r
++  // Test that a normal PrimaryHeader passes validation\r
++  PrimaryHeader.NumberOfPartitionEntries = 5;\r
++  PrimaryHeader.SizeOfPartitionEntry     = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;\r
++\r
++  // set the number of partitions\r
++  NumberOfPartition = 13;\r
++\r
++  // that the primary event size is correct\r
++  Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);\r
++  UT_ASSERT_NOT_EFI_ERROR (Status);\r
++\r
++  // Calculate the existing logic event size\r
++  ExistingLogicEventSize = (UINT32)(OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF (EFI_GPT_DATA, Partitions)\r
++                                    + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry);\r
++\r
++  // Check that the event size is correct\r
++  UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize);\r
++\r
++  // Tests that the primary event size may not overflow\r
++  Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  // Test that the size of partition entries may not overflow\r
++  PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;\r
++  Status                             = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));\r
++\r
++  return UNIT_TEST_PASSED;\r
++}\r
++\r
++// *--------------------------------------------------------------------*\r
++// *  Unit Test Code Main Function\r
++// *--------------------------------------------------------------------*\r
++\r
++/**\r
++  This function acts as the entry point for the unit tests.\r
++\r
++  @retval UNIT_TEST_PASSED  The test passed.\r
++  @retval UNIT_TEST_ERROR_TEST_FAILED  The test failed.\r
++  @retval others The test failed.\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++UefiTestMain (\r
++  VOID\r
++  )\r
++{\r
++  EFI_STATUS                  Status;\r
++  UNIT_TEST_FRAMEWORK_HANDLE  Framework;\r
++  UNIT_TEST_SUITE_HANDLE      Tcg2MeasureBootLibValidationTestSuite;\r
++\r
++  Framework = NULL;\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME));\r
++\r
++  Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status));\r
++    goto EXIT;\r
++  }\r
++\r
++  Status = CreateUnitTestSuite (&Tcg2MeasureBootLibValidationTestSuite, Framework, "Tcg2MeasureBootLibValidationTestSuite", "Common.Tcg2MeasureBootLibValidation", NULL, NULL);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for Tcg2MeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME));\r
++    Status = EFI_OUT_OF_RESOURCES;\r
++    goto EXIT;\r
++  }\r
++\r
++  // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context\r
++  AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);\r
++  AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);\r
++  AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);\r
++\r
++  Status = RunAllTestSuites (Framework);\r
++\r
++EXIT:\r
++  if (Framework != NULL) {\r
++    FreeUnitTestFramework (Framework);\r
++  }\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME));\r
++  return Status;\r
++}\r
++\r
++///\r
++/// Avoid ECC error for function name that starts with lower case letter\r
++///\r
++#define DxeTpm2MeasureBootLibUnitTestMain  main\r
++\r
++/**\r
++  Standard POSIX C entry point for host based unit test execution.\r
++\r
++  @param[in] Argc  Number of arguments\r
++  @param[in] Argv  Array of pointers to arguments\r
++\r
++  @retval 0      Success\r
++  @retval other  Error\r
++**/\r
++INT32\r
++DxeTpm2MeasureBootLibUnitTestMain (\r
++  IN INT32  Argc,\r
++  IN CHAR8  *Argv[]\r
++  )\r
++{\r
++  return (INT32)UefiTestMain ();\r
++}\r
+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\r
++# This file builds the unit tests for DxeTpm2MeasureBootLib\r
++#\r
++# Copyright (C) Microsoft Corporation.<BR>\r
++# SPDX-License-Identifier: BSD-2-Clause-Patent\r
++##\r
++\r
++[Defines]\r
++  INF_VERSION                    = 0x00010006\r
++  BASE_NAME                      = DxeTpm2MeasuredBootLibTest\r
++  FILE_GUID                      = 144d757f-d423-484e-9309-a23695fad5bd\r
++  MODULE_TYPE                    = HOST_APPLICATION\r
++  VERSION_STRING                 = 1.0\r
++  ENTRY_POINT                    = main\r
++\r
++[Sources]\r
++  DxeTpm2MeasureBootLibSanitizationTest.c\r
++  ../DxeTpm2MeasureBootLibSanitization.c\r
++\r
++[Packages]\r
++  MdePkg/MdePkg.dec\r
++\r
++[LibraryClasses]\r
++  BaseLib\r
++  DebugLib\r
++  UnitTestLib\r
++  PrintLib\r
++  SafeIntLib\r
+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>"\r
+         ## ]\r
+         "ExceptionList": [\r
++            "8001", "DxeTpm2MeasureBootLibUnitTestMain",\r
+         ],\r
+         ## Both file path and directory path are accepted.\r
+         "IgnoreFiles": [\r
+-- 
+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 (file)
index 0000000..6c20cc3
--- /dev/null
@@ -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>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
++Copyright (c) Microsoft Corporation.<BR>\r
++SPDX-License-Identifier: BSD-2-Clause-Patent\r
+ **/\r
\r
+ #include <PiDxe.h>\r
+@@ -40,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
+ #include <Library/SecurityManagementLib.h>\r
+ #include <Library/HobLib.h>\r
\r
++#include "DxeTpmMeasureBootLibSanitization.h"\r
++\r
+ //\r
+ // Flag to check GPT partition. It only need be measured once.\r
+ //\r
+@@ -136,6 +140,9 @@ TcgMeasureGptTable (
+   UINT32                      EventSize;\r
+   UINT32                      EventNumber;\r
+   EFI_PHYSICAL_ADDRESS        EventLogLastEntry;\r
++  UINT32                      AllocSize;\r
++\r
++  GptData = NULL;\r
\r
+   if (mMeasureGptCount > 0) {\r
+     return EFI_SUCCESS;\r
+@@ -166,8 +173,8 @@ TcgMeasureGptTable (
+                      BlockIo->Media->BlockSize,\r
+                      (UINT8 *)PrimaryHeader\r
+                      );\r
+-  if (EFI_ERROR (Status)) {\r
+-    DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n"));\r
++  if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {\r
++    DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n"));\r
+     FreePool (PrimaryHeader);\r
+     return EFI_DEVICE_ERROR;\r
+   }\r
+@@ -175,7 +182,13 @@ TcgMeasureGptTable (
+   //\r
+   // Read the partition entry.\r
+   //\r
+-  EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);\r
++  Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);\r
++  if (EFI_ERROR (Status)) {\r
++    FreePool (PrimaryHeader);\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  EntryPtr = (UINT8 *)AllocatePool (AllocSize);\r
+   if (EntryPtr == NULL) {\r
+     FreePool (PrimaryHeader);\r
+     return EFI_OUT_OF_RESOURCES;\r
+@@ -185,7 +198,7 @@ TcgMeasureGptTable (
+                      DiskIo,\r
+                      BlockIo->Media->MediaId,\r
+                      MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
+-                     PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,\r
++                     AllocSize,\r
+                      EntryPtr\r
+                      );\r
+   if (EFI_ERROR (Status)) {\r
+@@ -210,9 +223,8 @@ TcgMeasureGptTable (
+   //\r
+   // Prepare Data for Measurement\r
+   //\r
+-  EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)\r
+-                       + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
+-  TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR));\r
++  Status   = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize);\r
++  TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize);\r
+   if (TcgEvent == NULL) {\r
+     FreePool (PrimaryHeader);\r
+     FreePool (EntryPtr);\r
+@@ -221,7 +233,7 @@ TcgMeasureGptTable (
\r
+   TcgEvent->PCRIndex  = 5;\r
+   TcgEvent->EventType = EV_EFI_GPT_EVENT;\r
+-  TcgEvent->EventSize = EventSize;\r
++  TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);\r
+   GptData             = (EFI_GPT_DATA *)TcgEvent->Event;\r
\r
+   //\r
+@@ -361,11 +373,13 @@ TcgMeasurePeImage (
+       TcgEvent->PCRIndex  = 2;\r
+       break;\r
+     default:\r
+-      DEBUG ((\r
+-        DEBUG_ERROR,\r
+-        "TcgMeasurePeImage: Unknown subsystem type %d",\r
+-        ImageType\r
+-        ));\r
++      DEBUG (\r
++        (\r
++         DEBUG_ERROR,\r
++         "TcgMeasurePeImage: Unknown subsystem type %d",\r
++         ImageType\r
++        )\r
++        );\r
+       goto Finish;\r
+   }\r
\r
+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 @@
\r
+ [Sources]\r
+   DxeTpmMeasureBootLib.c\r
++  DxeTpmMeasureBootLibSanitization.c\r
++  DxeTpmMeasureBootLibSanitization.h\r
\r
+ [Packages]\r
+   MdePkg/MdePkg.dec\r
+@@ -41,6 +43,7 @@
\r
+ [LibraryClasses]\r
+   BaseMemoryLib\r
++  SafeIntLib\r
+   DebugLib\r
+   MemoryAllocationLib\r
+   DevicePathLib\r
+@@ -59,4 +62,3 @@
+   gEfiFirmwareVolumeBlockProtocolGuid   ## SOMETIMES_CONSUMES\r
+   gEfiBlockIoProtocolGuid               ## SOMETIMES_CONSUMES\r
+   gEfiDiskIoProtocolGuid                ## SOMETIMES_CONSUMES\r
+-\r
+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\r
++  The library instance provides security service of TPM2 measure boot and\r
++  Confidential Computing (CC) measure boot.\r
++\r
++  Caution: This file requires additional review when modified.\r
++  This library will have external input - PE/COFF image and GPT partition.\r
++  This external input must be validated carefully to avoid security issue like\r
++  buffer overflow, integer overflow.\r
++\r
++  This file will pull out the validation logic from the following functions, in an\r
++  attempt to validate the untrusted input in the form of unit tests\r
++\r
++  These are those functions:\r
++\r
++  DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content\r
++  read is within the image buffer.\r
++\r
++  Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse\r
++  partition data carefully.\r
++\r
++  Copyright (c) Microsoft Corporation.<BR>\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++#include <Uefi.h>\r
++#include <Uefi/UefiSpec.h>\r
++#include <Library/SafeIntLib.h>\r
++#include <Library/UefiLib.h>\r
++#include <Library/DebugLib.h>\r
++#include <Library/BaseLib.h>\r
++#include <IndustryStandard/UefiTcgPlatform.h>\r
++#include <Protocol/BlockIo.h>\r
++#include <Library/MemoryAllocationLib.h>\r
++\r
++#include "DxeTpmMeasureBootLibSanitization.h"\r
++\r
++#define GPT_HEADER_REVISION_V1  0x00010000\r
++\r
++/**\r
++  This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse\r
++  However this function will not attempt to verify the validity of the GPT partition\r
++  It will check the following:\r
++    - Signature\r
++    - Revision\r
++    - AlternateLBA\r
++    - FirstUsableLBA\r
++    - LastUsableLBA\r
++    - PartitionEntryLBA\r
++    - NumberOfPartitionEntries\r
++    - SizeOfPartitionEntry\r
++    - BlockIo\r
++\r
++  @param[in] PrimaryHeader\r
++    Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++\r
++  @param[in] BlockIo\r
++    Pointer to the EFI_BLOCK_IO_PROTOCOL structure.\r
++\r
++  @retval EFI_SUCCESS\r
++    The EFI_PARTITION_TABLE_HEADER structure is valid.\r
++\r
++  @retval EFI_INVALID_PARAMETER\r
++    The EFI_PARTITION_TABLE_HEADER structure is invalid.\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++SanitizeEfiPartitionTableHeader (\r
++  IN CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  IN CONST EFI_BLOCK_IO_PROTOCOL       *BlockIo\r
++  )\r
++{\r
++  // Verify that the input parameters are safe to use\r
++  if (PrimaryHeader == NULL) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n"));\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if ((BlockIo == NULL) || (BlockIo->Media == NULL)) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n"));\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII)\r
++  if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  // The version must be GPT_HEADER_REVISION_V1 (0x00010000)\r
++  if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  // The HeaderSize must be greater than or equal to 92 and must be less than or equal to the logical block size\r
++  if ((PrimaryHeader->Header.HeaderSize < sizeof (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > BlockIo->Media->BlockSize)) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header HeaderSize!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  // check that the PartitionEntryLBA greater than the Max LBA\r
++  // This will be used later for multiplication\r
++  if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, BlockIo->Media->BlockSize)) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header PartitionEntryLBA!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  // Check that the number of partition entries is greater than zero\r
++  if (PrimaryHeader->NumberOfPartitionEntries == 0) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  // SizeOfPartitionEntry must be 128, 256, 512... improper size may lead to accessing uninitialized memory\r
++  if ((PrimaryHeader->SizeOfPartitionEntry < 128) || ((PrimaryHeader->SizeOfPartitionEntry & (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) {\r
++    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"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  // This check is to prevent overflow when calculating the allocation size for the partition entries\r
++  // This check will be used later for multiplication\r
++  if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, PrimaryHeader->SizeOfPartitionEntry)) {\r
++    DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n"));\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++/**\r
++  This function will validate that the allocation size from the primary header is sane\r
++  It will check the following:\r
++    - AllocationSize does not overflow\r
++\r
++  @param[in] PrimaryHeader\r
++    Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++\r
++  @param[out] AllocationSize\r
++    Pointer to the allocation size.\r
++\r
++  @retval EFI_SUCCESS\r
++    The allocation size is valid.\r
++\r
++  @retval EFI_OUT_OF_RESOURCES\r
++    The allocation size is invalid.\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++SanitizePrimaryHeaderAllocationSize (\r
++  IN CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  OUT UINT32                           *AllocationSize\r
++  )\r
++{\r
++  EFI_STATUS  Status;\r
++\r
++  if (PrimaryHeader == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if (AllocationSize == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  // Replacing logic:\r
++  // PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry;\r
++  Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry, AllocationSize);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n"));\r
++    return EFI_BAD_BUFFER_SIZE;\r
++  }\r
++\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++/**\r
++  This function will validate that the Gpt Event Size calculated from the primary header is sane\r
++  It will check the following:\r
++    - EventSize does not overflow\r
++\r
++  Important: This function includes the entire length of the allocated space, including the\r
++  TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, the caller must subtract\r
++  the size of the TCG_PCR_EVENT_HDR from the size of the buffer before hashing.\r
++\r
++  @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++  @param[in] NumberOfPartition - Number of partitions.\r
++  @param[out] EventSize - Pointer to the event size.\r
++\r
++  @retval EFI_SUCCESS\r
++    The event size is valid.\r
++\r
++  @retval EFI_OUT_OF_RESOURCES\r
++    Overflow would have occurred.\r
++\r
++  @retval EFI_INVALID_PARAMETER\r
++    One of the passed parameters was invalid.\r
++**/\r
++EFI_STATUS\r
++SanitizePrimaryHeaderGptEventSize (\r
++  IN  CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  IN  UINTN                             NumberOfPartition,\r
++  OUT UINT32                            *EventSize\r
++  )\r
++{\r
++  EFI_STATUS  Status;\r
++  UINT32      SafeNumberOfPartitions;\r
++\r
++  if (PrimaryHeader == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if (EventSize == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  // We shouldn't even attempt to perform the multiplication if the number of partitions is greater than the maximum value of UINT32\r
++  Status = SafeUintnToUint32 (NumberOfPartition, &SafeNumberOfPartitions);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n"));\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  // Replacing logic:\r
++  // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry + sizeof (TCG_PCR_EVENT_HDR));\r
++  Status = SafeUint32Mult (SafeNumberOfPartitions, PrimaryHeader->SizeOfPartitionEntry, EventSize);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n"));\r
++    return EFI_BAD_BUFFER_SIZE;\r
++  }\r
++\r
++  Status = SafeUint32Add (\r
++             sizeof (TCG_PCR_EVENT_HDR) +\r
++             OFFSET_OF (EFI_GPT_DATA, Partitions),\r
++             *EventSize,\r
++             EventSize\r
++             );\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of GPTData!\n"));\r
++    return EFI_BAD_BUFFER_SIZE;\r
++  }\r
++\r
++  return EFI_SUCCESS;\r
++}\r
+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\r
++  This file includes the function prototypes for the sanitization functions.\r
++\r
++  These are those functions:\r
++\r
++  DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content\r
++  read is within the image buffer.\r
++\r
++  TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its\r
++  data structure within this image buffer before use.\r
++\r
++  TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse\r
++  partition data carefully.\r
++\r
++  Copyright (c) Microsoft Corporation.<BR>\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++\r
++**/\r
++\r
++#ifndef DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_\r
++#define DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_\r
++\r
++#include <Uefi.h>\r
++#include <Uefi/UefiSpec.h>\r
++#include <Protocol/BlockIo.h>\r
++#include <IndustryStandard/UefiTcgPlatform.h>\r
++\r
++/**\r
++  This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse\r
++  However this function will not attempt to verify the validity of the GPT partition\r
++  It will check the following:\r
++    - Signature\r
++    - Revision\r
++    - AlternateLBA\r
++    - FirstUsableLBA\r
++    - LastUsableLBA\r
++    - PartitionEntryLBA\r
++    - NumberOfPartitionEntries\r
++    - SizeOfPartitionEntry\r
++    - BlockIo\r
++\r
++  @param[in] PrimaryHeader\r
++    Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++\r
++  @param[in] BlockIo\r
++    Pointer to the EFI_BLOCK_IO_PROTOCOL structure.\r
++\r
++  @retval EFI_SUCCESS\r
++    The EFI_PARTITION_TABLE_HEADER structure is valid.\r
++\r
++  @retval EFI_INVALID_PARAMETER\r
++    The EFI_PARTITION_TABLE_HEADER structure is invalid.\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++SanitizeEfiPartitionTableHeader (\r
++  IN CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  IN CONST EFI_BLOCK_IO_PROTOCOL       *BlockIo\r
++  );\r
++\r
++/**\r
++  This function will validate that the allocation size from the primary header is sane\r
++  It will check the following:\r
++    - AllocationSize does not overflow\r
++\r
++  @param[in] PrimaryHeader\r
++    Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++\r
++  @param[out] AllocationSize\r
++    Pointer to the allocation size.\r
++\r
++  @retval EFI_SUCCESS\r
++    The allocation size is valid.\r
++\r
++  @retval EFI_OUT_OF_RESOURCES\r
++    The allocation size is invalid.\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++SanitizePrimaryHeaderAllocationSize (\r
++  IN CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  OUT UINT32                           *AllocationSize\r
++  );\r
++\r
++/**\r
++  This function will validate that the Gpt Event Size calculated from the primary header is sane\r
++  It will check the following:\r
++    - EventSize does not overflow\r
++\r
++  Important: This function includes the entire length of the allocated space, including the\r
++  TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, the caller must subtract\r
++  the size of the TCG_PCR_EVENT_HDR from the size of the buffer before hashing.\r
++\r
++  @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure.\r
++  @param[in] NumberOfPartition - Number of partitions.\r
++  @param[out] EventSize - Pointer to the event size.\r
++\r
++  @retval EFI_SUCCESS\r
++    The event size is valid.\r
++\r
++  @retval EFI_OUT_OF_RESOURCES\r
++    Overflow would have occurred.\r
++\r
++  @retval EFI_INVALID_PARAMETER\r
++    One of the passed parameters was invalid.\r
++**/\r
++EFI_STATUS\r
++SanitizePrimaryHeaderGptEventSize (\r
++  IN  CONST EFI_PARTITION_TABLE_HEADER  *PrimaryHeader,\r
++  IN  UINTN                             NumberOfPartition,\r
++  OUT UINT32                            *EventSize\r
++  );\r
++\r
++#endif // DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_\r
+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\r
++This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c.\r
++\r
++Copyright (c) Microsoft Corporation.<BR>\r
++SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++\r
++#include <Uefi.h>\r
++#include <Library/UefiLib.h>\r
++#include <Library/DebugLib.h>\r
++#include <Library/UnitTestLib.h>\r
++#include <Protocol/BlockIo.h>\r
++#include <Library/MemoryAllocationLib.h>\r
++#include <Library/BaseMemoryLib.h>\r
++#include <IndustryStandard/UefiTcgPlatform.h>\r
++\r
++#include "../DxeTpmMeasureBootLibSanitization.h"\r
++\r
++#define UNIT_TEST_NAME     "DxeTpmMeasureBootLibSanitizationTest"\r
++#define UNIT_TEST_VERSION  "1.0"\r
++\r
++#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION                     0x00010000\r
++#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES  1\r
++#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY      128\r
++\r
++/**\r
++  This function tests the SanitizeEfiPartitionTableHeader function.\r
++  It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER\r
++  structure will not cause undefined or unexpected behavior.\r
++\r
++  In general the TPM should still be able to measure the data, but\r
++  be the header should be sanitized to prevent any unexpected behavior.\r
++\r
++  @param[in] Context  The unit test context.\r
++\r
++  @retval UNIT_TEST_PASSED  The test passed.\r
++  @retval UNIT_TEST_ERROR_TEST_FAILED  The test failed.\r
++**/\r
++UNIT_TEST_STATUS\r
++EFIAPI\r
++TestSanitizeEfiPartitionTableHeader (\r
++  IN UNIT_TEST_CONTEXT  Context\r
++  )\r
++{\r
++  EFI_STATUS                  Status;\r
++  EFI_PARTITION_TABLE_HEADER  PrimaryHeader;\r
++  EFI_BLOCK_IO_PROTOCOL       BlockIo;\r
++  EFI_BLOCK_IO_MEDIA          BlockMedia;\r
++\r
++  // Generate EFI_BLOCK_IO_MEDIA test data\r
++  BlockMedia.MediaId          = 1;\r
++  BlockMedia.RemovableMedia   = FALSE;\r
++  BlockMedia.MediaPresent     = TRUE;\r
++  BlockMedia.LogicalPartition = FALSE;\r
++  BlockMedia.ReadOnly         = FALSE;\r
++  BlockMedia.WriteCaching     = FALSE;\r
++  BlockMedia.BlockSize        = 512;\r
++  BlockMedia.IoAlign          = 1;\r
++  BlockMedia.LastBlock        = 0;\r
++\r
++  // Generate EFI_BLOCK_IO_PROTOCOL test data\r
++  BlockIo.Revision    = 1;\r
++  BlockIo.Media       = &BlockMedia;\r
++  BlockIo.Reset       = NULL;\r
++  BlockIo.ReadBlocks  = NULL;\r
++  BlockIo.WriteBlocks = NULL;\r
++  BlockIo.FlushBlocks = NULL;\r
++\r
++  // Geneate EFI_PARTITION_TABLE_HEADER test data\r
++  PrimaryHeader.Header.Signature         = EFI_PTAB_HEADER_ID;\r
++  PrimaryHeader.Header.Revision          = DEFAULT_PRIMARY_TABLE_HEADER_REVISION;\r
++  PrimaryHeader.Header.HeaderSize        = sizeof (EFI_PARTITION_TABLE_HEADER);\r
++  PrimaryHeader.MyLBA                    = 1;\r
++  PrimaryHeader.AlternateLBA             = 2;\r
++  PrimaryHeader.FirstUsableLBA           = 3;\r
++  PrimaryHeader.LastUsableLBA            = 4;\r
++  PrimaryHeader.PartitionEntryLBA        = 5;\r
++  PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES;\r
++  PrimaryHeader.SizeOfPartitionEntry     = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;\r
++  PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid\r
++\r
++  // Calculate the CRC32 of the PrimaryHeader\r
++  PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize);\r
++\r
++  // Test that a normal PrimaryHeader passes validation\r
++  Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);\r
++  UT_ASSERT_NOT_EFI_ERROR (Status);\r
++\r
++  // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR\r
++  // Should print "Invalid Partition Table Header NumberOfPartitionEntries!""\r
++  PrimaryHeader.NumberOfPartitionEntries = 0;\r
++  Status                                 = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);\r
++  UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);\r
++  PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;\r
++\r
++  // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR\r
++  // Should print "Invalid Partition Table Header Size!"\r
++  PrimaryHeader.Header.HeaderSize = 0;\r
++  Status                          = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);\r
++  UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);\r
++  PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);\r
++\r
++  // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR\r
++  // 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.)!"\r
++  PrimaryHeader.SizeOfPartitionEntry = 1;\r
++  Status                             = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);\r
++  UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));\r
++\r
++  return UNIT_TEST_PASSED;\r
++}\r
++\r
++/**\r
++  This function tests the SanitizePrimaryHeaderAllocationSize function.\r
++  It's intent is to test that the untrusted input from a EFI_PARTITION_TABLE_HEADER\r
++  structure will not cause an overflow when calculating the allocation size.\r
++\r
++  @param[in] Context  The unit test context.\r
++\r
++  @retval UNIT_TEST_PASSED  The test passed.\r
++  @retval UNIT_TEST_ERROR_TEST_FAILED  The test failed.\r
++**/\r
++UNIT_TEST_STATUS\r
++EFIAPI\r
++TestSanitizePrimaryHeaderAllocationSize (\r
++  IN UNIT_TEST_CONTEXT  Context\r
++  )\r
++{\r
++  UINT32  AllocationSize;\r
++\r
++  EFI_STATUS                  Status;\r
++  EFI_PARTITION_TABLE_HEADER  PrimaryHeader;\r
++\r
++  // Test that a normal PrimaryHeader passes validation\r
++  PrimaryHeader.NumberOfPartitionEntries = 5;\r
++  PrimaryHeader.SizeOfPartitionEntry     = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;\r
++\r
++  Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);\r
++  UT_ASSERT_NOT_EFI_ERROR (Status);\r
++\r
++  // Test that the allocation size is correct compared to the existing logic\r
++  UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry);\r
++\r
++  // Test that an overflow is detected\r
++  PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;\r
++  PrimaryHeader.SizeOfPartitionEntry     = 5;\r
++  Status                                 = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  // Test the inverse\r
++  PrimaryHeader.NumberOfPartitionEntries = 5;\r
++  PrimaryHeader.SizeOfPartitionEntry     = MAX_UINT32;\r
++  Status                                 = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  // Test the worst case scenario\r
++  PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;\r
++  PrimaryHeader.SizeOfPartitionEntry     = MAX_UINT32;\r
++  Status                                 = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));\r
++\r
++  return UNIT_TEST_PASSED;\r
++}\r
++\r
++/**\r
++  This function tests the SanitizePrimaryHeaderGptEventSize function.\r
++  It's intent is to test that the untrusted input from a EFI_GPT_DATA structure\r
++  will not cause an overflow when calculating the event size.\r
++\r
++  @param[in] Context  The unit test context.\r
++\r
++  @retval UNIT_TEST_PASSED  The test passed.\r
++  @retval UNIT_TEST_ERROR_TEST_FAILED  The test failed.\r
++**/\r
++UNIT_TEST_STATUS\r
++EFIAPI\r
++TestSanitizePrimaryHeaderGptEventSize (\r
++  IN UNIT_TEST_CONTEXT  Context\r
++  )\r
++{\r
++  UINT32                      EventSize;\r
++  UINT32                      ExistingLogicEventSize;\r
++  EFI_STATUS                  Status;\r
++  EFI_PARTITION_TABLE_HEADER  PrimaryHeader;\r
++  UINTN                       NumberOfPartition;\r
++  EFI_GPT_DATA                *GptData;\r
++\r
++  GptData = NULL;\r
++\r
++  // Test that a normal PrimaryHeader passes validation\r
++  PrimaryHeader.NumberOfPartitionEntries = 5;\r
++  PrimaryHeader.SizeOfPartitionEntry     = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;\r
++\r
++  // set the number of partitions\r
++  NumberOfPartition = 13;\r
++\r
++  // that the primary event size is correct\r
++  Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);\r
++  UT_ASSERT_NOT_EFI_ERROR (Status);\r
++\r
++  // Calculate the existing logic event size\r
++  ExistingLogicEventSize = (UINT32)(sizeof (TCG_PCR_EVENT_HDR) + OFFSET_OF (EFI_GPT_DATA, Partitions)\r
++                                    + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry);\r
++\r
++  // Check that the event size is correct\r
++  UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize);\r
++\r
++  // Tests that the primary event size may not overflow\r
++  Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  // Test that the size of partition entries may not overflow\r
++  PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;\r
++  Status                             = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);\r
++  UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));\r
++\r
++  return UNIT_TEST_PASSED;\r
++}\r
++\r
++// *--------------------------------------------------------------------*\r
++// *  Unit Test Code Main Function\r
++// *--------------------------------------------------------------------*\r
++\r
++/**\r
++  This function acts as the entry point for the unit tests.\r
++\r
++  @param argc - The number of command line arguments\r
++  @param argv - The command line arguments\r
++\r
++  @return int - The status of the test\r
++**/\r
++EFI_STATUS\r
++EFIAPI\r
++UefiTestMain (\r
++  VOID\r
++  )\r
++{\r
++  EFI_STATUS                  Status;\r
++  UNIT_TEST_FRAMEWORK_HANDLE  Framework;\r
++  UNIT_TEST_SUITE_HANDLE      TcgMeasureBootLibValidationTestSuite;\r
++\r
++  Framework = NULL;\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME));\r
++\r
++  Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status));\r
++    goto EXIT;\r
++  }\r
++\r
++  Status = CreateUnitTestSuite (&TcgMeasureBootLibValidationTestSuite, Framework, "TcgMeasureBootLibValidationTestSuite", "Common.TcgMeasureBootLibValidation", NULL, NULL);\r
++  if (EFI_ERROR (Status)) {\r
++    DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for TcgMeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME));\r
++    Status = EFI_OUT_OF_RESOURCES;\r
++    goto EXIT;\r
++  }\r
++\r
++  // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context\r
++  AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.TcgMeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);\r
++  AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);\r
++  AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);\r
++\r
++  Status = RunAllTestSuites (Framework);\r
++\r
++EXIT:\r
++  if (Framework != NULL) {\r
++    FreeUnitTestFramework (Framework);\r
++  }\r
++\r
++  DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME));\r
++  return Status;\r
++}\r
++\r
++///\r
++/// Avoid ECC error for function name that starts with lower case letter\r
++///\r
++#define DxeTpmMeasureBootLibUnitTestMain  main\r
++\r
++/**\r
++  Standard POSIX C entry point for host based unit test execution.\r
++\r
++  @param[in] Argc  Number of arguments\r
++  @param[in] Argv  Array of pointers to arguments\r
++\r
++  @retval 0      Success\r
++  @retval other  Error\r
++**/\r
++INT32\r
++DxeTpmMeasureBootLibUnitTestMain (\r
++  IN INT32  Argc,\r
++  IN CHAR8  *Argv[]\r
++  )\r
++{\r
++  return (INT32)UefiTestMain ();\r
++}\r
+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\r
++# This file builds the unit tests for DxeTpmMeasureBootLib\r
++#\r
++# Copyright (C) Microsoft Corporation.<BR>\r
++# SPDX-License-Identifier: BSD-2-Clause-Patent\r
++##\r
++\r
++[Defines]\r
++  INF_VERSION                    = 0x00010006\r
++  BASE_NAME                      = DxeTpmMeasuredBootLibTest\r
++  FILE_GUID                      = eb01bc38-309c-4d3e-967e-9f078c90772f\r
++  MODULE_TYPE                    = HOST_APPLICATION\r
++  VERSION_STRING                 = 1.0\r
++  ENTRY_POINT                    = main\r
++\r
++[Sources]\r
++  DxeTpmMeasureBootLibSanitizationTest.c\r
++  ../DxeTpmMeasureBootLibSanitization.c\r
++\r
++[Packages]\r
++  MdePkg/MdePkg.dec\r
++\r
++[LibraryClasses]\r
++  BaseLib\r
++  DebugLib\r
++  UnitTestLib\r
++  PrintLib\r
++  SafeIntLib\r
+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 @@
+         ## ]\r
+         "ExceptionList": [\r
+             "8001", "DxeTpm2MeasureBootLibUnitTestMain",\r
++            "8001", "DxeTpmMeasureBootLibUnitTestMain"\r
+         ],\r
+         ## Both file path and directory path are accepted.\r
+         "IgnoreFiles": [\r
+-- 
+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 (file)
index 0000000..59bd5c4
--- /dev/null
@@ -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\r
++# Security Fixes for SecurityPkg\r
++#\r
++# Copyright (c) Microsoft Corporation\r
++# SPDX-License-Identifier: BSD-2-Clause-Patent\r
++##\r
++CVE_2022_36763:\r
++  commit_titles:\r
++    - "SecurityPkg: DxeTpm2Measurement: SECURITY PATCH 4117 - CVE 2022-36763"\r
++    - "SecurityPkg: DxeTpmMeasurement: SECURITY PATCH 4117 - CVE 2022-36763"\r
++    - "SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml"\r
++  cve: CVE-2022-36763\r
++  date_reported: 2022-10-25 11:31 UTC\r
++  description: (CVE-2022-36763) - Heap Buffer Overflow in Tcg2MeasureGptTable()\r
++  note: This patch is related to and supersedes TCBZ2168\r
++  files_impacted:\r
++  - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c\r
++  - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c\r
++  links:\r
++  - https://bugzilla.tianocore.org/show_bug.cgi?id=4117\r
++  - https://bugzilla.tianocore.org/show_bug.cgi?id=2168\r
++  - https://bugzilla.tianocore.org/show_bug.cgi?id=1990\r
+-- 
+2.40.0
+
index 84e3360a3af69cdd053a6db094ba428149b4a322..78d86ad8793dcffcd18277590cbd88a78f477ede 100644 (file)
@@ -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"