edk2/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch

1067 lines
40 KiB
Diff
Raw Normal View History

* Wed Feb 14 2024 Jon Maloy <jmaloy@redhat.com> - 20220126gitbb1bba3d77-11 - edk2-SecurityPkg-Change-use-of-EFI_D_-to-DEBUG_.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-Change-OPTIONAL-keyword-usage-style.patch [RHEL-21154 RHEL-21156] - edk2-MdePkg-Introduce-CcMeasurementProtocol-for-CC-Guest-.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpm2.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpmM.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-418.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-DxeTpm2MeasureBootLib-SEC-PATCH-4118-2.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-DxeTpmMeasureBootLib-SEC-PATCH-4117-2.patch [RHEL-21154 RHEL-21156] - edk2-SecurityPkg-Updating-SecurityFixes.yaml-after-symbol.patch [RHEL-21154 RHEL-21156] - edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch [RHEL-21840 RHEL-21842] - edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch [RHEL-21840 RHEL-21842] - edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch [RHEL-21840 RHEL-21842] - edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch [RHEL-21840 RHEL-21842] - Resolves: RHEL-21154 (CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8]) - Resolves: RHEL-21156 (CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8]) - Resolves: RHEL-21840 (CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8]) - Resolves: RHEL-21842 (CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8])
2024-02-14 16:57:41 +00:00
From dd30c6c8f2a47b46d514eb413c8c96aedc951297 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Wed, 17 Jan 2024 12:20:52 -0500
Subject: [PATCH 06/17] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117
- CVE 2022-36763
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
RH-Jira: RHEL-21154 RHEL-21156
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Commit: [6/13] d8e42e23d4215506de05ed540644545a4dd65f44 (jmaloy/jons_fork)
JIRA: https://issues.redhat.com/browse/RHEL-21154
CVE: CVE-2022-36763
Upstream: Merged
Conflicts: Only cosmetic conflicts.
commit 224446543206450ddb5830e6abd026d61d3c7f4b
Author: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Date: Fri Jan 12 02:16:01 2024 +0800
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>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
.../DxeTpm2MeasureBootLib.c | 81 ++---
.../DxeTpm2MeasureBootLib.inf | 4 +-
.../DxeTpm2MeasureBootLibSanitization.c | 275 ++++++++++++++++
.../DxeTpm2MeasureBootLibSanitization.h | 113 +++++++
.../DxeTpm2MeasureBootLibSanitizationTest.c | 303 ++++++++++++++++++
...Tpm2MeasureBootLibSanitizationTestHost.inf | 28 ++
SecurityPkg/SecurityPkg.ci.yaml | 2 +
SecurityPkg/Test/SecurityPkgHostTest.dsc | 47 +++
8 files changed, 815 insertions(+), 38 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
create mode 100644 SecurityPkg/Test/SecurityPkgHostTest.dsc
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
index 7abacdbc0a..476c8d543f 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;
@@ -192,25 +197,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;
@@ -218,8 +220,8 @@ Tcg2MeasureGptTable (
Status = DiskIo->ReadDisk (
DiskIo,
BlockIo->Media->MediaId,
- MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
- PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,
+ MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
+ AllocSize,
EntryPtr
);
if (EFI_ERROR (Status)) {
@@ -243,23 +245,22 @@ 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;
- if (Tcg2Event == NULL) {
- FreePool (PrimaryHeader);
- FreePool (EntryPtr);
- return EFI_OUT_OF_RESOURCES;
- }
-
- Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event);
- Tcg2Event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER);
+ Tcg2Event->Size = TcgEventSize;
+ Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
Tcg2Event->Header.PCRIndex = 5;
Tcg2Event->Header.EventType = EV_EFI_GPT_EVENT;
@@ -310,7 +311,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 +327,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)) {
@@ -442,11 +443,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;
}
@@ -514,7 +517,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
@@ -644,12 +647,16 @@ DxeTpm2MeasureBootHandler (
DEBUG ((DEBUG_INFO, "None of Tcg2Protocol/CcMeasurementProtocol is installed.\n"));
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 d7b9e1f4e2..aa8496d6d9 100644
--- a/SecurityPkg/SecurityPkg.ci.yaml
+++ b/SecurityPkg/SecurityPkg.ci.yaml
@@ -15,6 +15,8 @@
## "<ErrorID>", "<KeyWord>"
## ]
"ExceptionList": [
+ "8005", "gRT",
+ "8001", "DxeTpm2MeasureBootLibUnitTestMain",
],
## Both file path and directory path are accepted.
"IgnoreFiles": [
diff --git a/SecurityPkg/Test/SecurityPkgHostTest.dsc b/SecurityPkg/Test/SecurityPkgHostTest.dsc
new file mode 100644
index 0000000000..788c1ab6fe
--- /dev/null
+++ b/SecurityPkg/Test/SecurityPkgHostTest.dsc
@@ -0,0 +1,47 @@
+## @file
+# SecurityPkg DSC file used to build host-based unit tests.
+#
+# Copyright (C) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = SecurityPkgHostTest
+ PLATFORM_GUID = 9D78A9B4-00CD-477E-A5BF-90CC793EEFB0
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/SecurityPkg/HostTest
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+
+[LibraryClasses]
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+
+[Components]
+ SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiRuntimeServicesTableLib.inf
+ SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockPlatformPKProtectionLib.inf
+ SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf
+ SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf
+ SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf
+
+ #
+ # Build SecurityPkg HOST_APPLICATION Tests
+ #
+ SecurityPkg/Library/SecureBootVariableLib/UnitTest/SecureBootVariableLibUnitTest.inf {
+ <LibraryClasses>
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
+ UefiRuntimeServicesTableLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiRuntimeServicesTableLib.inf
+ PlatformPKProtectionLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockPlatformPKProtectionLib.inf
+ UefiLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf
+ }
+ SecurityPkg/Library/SecureBootVariableLib/GoogleTest/SecureBootVariableLibGoogleTest.inf {
+ <LibraryClasses>
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf
+ PlatformPKProtectionLib|SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf
+ UefiLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.inf
+ }
--
2.41.0