mirror of https://github.com/acidanthera/audk.git
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>
This commit is contained in:
parent
a4b8944e27
commit
2244465432
|
@ -20,6 +20,8 @@ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||||
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
|
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
|
||||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.<BR>
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include <PiDxe.h>
|
#include <PiDxe.h>
|
||||||
|
@ -44,6 +46,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
#include <Library/HobLib.h>
|
#include <Library/HobLib.h>
|
||||||
#include <Protocol/CcMeasurement.h>
|
#include <Protocol/CcMeasurement.h>
|
||||||
|
|
||||||
|
#include "DxeTpm2MeasureBootLibSanitization.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
EFI_TCG2_PROTOCOL *Tcg2Protocol;
|
EFI_TCG2_PROTOCOL *Tcg2Protocol;
|
||||||
EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
|
EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
|
||||||
|
@ -144,10 +148,11 @@ Tcg2MeasureGptTable (
|
||||||
EFI_TCG2_EVENT *Tcg2Event;
|
EFI_TCG2_EVENT *Tcg2Event;
|
||||||
EFI_CC_EVENT *CcEvent;
|
EFI_CC_EVENT *CcEvent;
|
||||||
EFI_GPT_DATA *GptData;
|
EFI_GPT_DATA *GptData;
|
||||||
UINT32 EventSize;
|
UINT32 TcgEventSize;
|
||||||
EFI_TCG2_PROTOCOL *Tcg2Protocol;
|
EFI_TCG2_PROTOCOL *Tcg2Protocol;
|
||||||
EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
|
EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;
|
||||||
EFI_CC_MR_INDEX MrIndex;
|
EFI_CC_MR_INDEX MrIndex;
|
||||||
|
UINT32 AllocSize;
|
||||||
|
|
||||||
if (mTcg2MeasureGptCount > 0) {
|
if (mTcg2MeasureGptCount > 0) {
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -195,25 +200,22 @@ Tcg2MeasureGptTable (
|
||||||
BlockIo->Media->BlockSize,
|
BlockIo->Media->BlockSize,
|
||||||
(UINT8 *)PrimaryHeader
|
(UINT8 *)PrimaryHeader
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {
|
||||||
DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n"));
|
DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n"));
|
||||||
FreePool (PrimaryHeader);
|
FreePool (PrimaryHeader);
|
||||||
return EFI_DEVICE_ERROR;
|
return EFI_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// PrimaryHeader->SizeOfPartitionEntry should not be zero
|
// Read the partition entry.
|
||||||
//
|
//
|
||||||
if (PrimaryHeader->SizeOfPartitionEntry == 0) {
|
Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);
|
||||||
DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n"));
|
if (EFI_ERROR (Status)) {
|
||||||
FreePool (PrimaryHeader);
|
FreePool (PrimaryHeader);
|
||||||
return EFI_BAD_BUFFER_SIZE;
|
return EFI_BAD_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
EntryPtr = (UINT8 *)AllocatePool (AllocSize);
|
||||||
// Read the partition entry.
|
|
||||||
//
|
|
||||||
EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);
|
|
||||||
if (EntryPtr == NULL) {
|
if (EntryPtr == NULL) {
|
||||||
FreePool (PrimaryHeader);
|
FreePool (PrimaryHeader);
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
@ -223,7 +225,7 @@ Tcg2MeasureGptTable (
|
||||||
DiskIo,
|
DiskIo,
|
||||||
BlockIo->Media->MediaId,
|
BlockIo->Media->MediaId,
|
||||||
MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
|
MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
|
||||||
PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,
|
AllocSize,
|
||||||
EntryPtr
|
EntryPtr
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
|
@ -248,16 +250,21 @@ Tcg2MeasureGptTable (
|
||||||
//
|
//
|
||||||
// Prepare Data for Measurement (CcProtocol and Tcg2Protocol)
|
// Prepare Data for Measurement (CcProtocol and Tcg2Protocol)
|
||||||
//
|
//
|
||||||
EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)
|
Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize);
|
||||||
+ NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);
|
if (EFI_ERROR (Status)) {
|
||||||
EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));
|
FreePool (PrimaryHeader);
|
||||||
|
FreePool (EntryPtr);
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventPtr = (UINT8 *)AllocateZeroPool (TcgEventSize);
|
||||||
if (EventPtr == NULL) {
|
if (EventPtr == NULL) {
|
||||||
Status = EFI_OUT_OF_RESOURCES;
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;
|
Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;
|
||||||
Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);
|
Tcg2Event->Size = TcgEventSize;
|
||||||
Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
|
Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
|
||||||
Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
|
Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
|
||||||
Tcg2Event->Header.PCRIndex = 5;
|
Tcg2Event->Header.PCRIndex = 5;
|
||||||
|
@ -310,7 +317,7 @@ Tcg2MeasureGptTable (
|
||||||
CcProtocol,
|
CcProtocol,
|
||||||
0,
|
0,
|
||||||
(EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
|
(EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
|
||||||
(UINT64)EventSize,
|
(UINT64)TcgEventSize - OFFSET_OF (EFI_TCG2_EVENT, Event),
|
||||||
CcEvent
|
CcEvent
|
||||||
);
|
);
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
|
@ -326,7 +333,7 @@ Tcg2MeasureGptTable (
|
||||||
Tcg2Protocol,
|
Tcg2Protocol,
|
||||||
0,
|
0,
|
||||||
(EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
|
(EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
|
||||||
(UINT64)EventSize,
|
(UINT64)TcgEventSize - OFFSET_OF (EFI_TCG2_EVENT, Event),
|
||||||
Tcg2Event
|
Tcg2Event
|
||||||
);
|
);
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
|
@ -443,11 +450,13 @@ Tcg2MeasurePeImage (
|
||||||
Tcg2Event->Header.PCRIndex = 2;
|
Tcg2Event->Header.PCRIndex = 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG ((
|
DEBUG (
|
||||||
|
(
|
||||||
DEBUG_ERROR,
|
DEBUG_ERROR,
|
||||||
"Tcg2MeasurePeImage: Unknown subsystem type %d",
|
"Tcg2MeasurePeImage: Unknown subsystem type %d",
|
||||||
ImageType
|
ImageType
|
||||||
));
|
)
|
||||||
|
);
|
||||||
goto Finish;
|
goto Finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +524,7 @@ Finish:
|
||||||
|
|
||||||
@param MeasureBootProtocols Pointer to the located measure boot protocol instances.
|
@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.
|
@retval EFI_UNSUPPORTED Measure boot is not supported.
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -646,12 +655,14 @@ DxeTpm2MeasureBootHandler (
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG ((
|
DEBUG (
|
||||||
|
(
|
||||||
DEBUG_INFO,
|
DEBUG_INFO,
|
||||||
"Tcg2Protocol = %p, CcMeasurementProtocol = %p\n",
|
"Tcg2Protocol = %p, CcMeasurementProtocol = %p\n",
|
||||||
MeasureBootProtocols.Tcg2Protocol,
|
MeasureBootProtocols.Tcg2Protocol,
|
||||||
MeasureBootProtocols.CcProtocol
|
MeasureBootProtocols.CcProtocol
|
||||||
));
|
)
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Copy File Device Path
|
// Copy File Device Path
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
|
|
||||||
[Sources]
|
[Sources]
|
||||||
DxeTpm2MeasureBootLib.c
|
DxeTpm2MeasureBootLib.c
|
||||||
|
DxeTpm2MeasureBootLibSanitization.c
|
||||||
|
DxeTpm2MeasureBootLibSanitization.h
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
MdePkg/MdePkg.dec
|
MdePkg/MdePkg.dec
|
||||||
|
@ -46,6 +48,7 @@
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
BaseMemoryLib
|
BaseMemoryLib
|
||||||
|
SafeIntLib
|
||||||
DebugLib
|
DebugLib
|
||||||
MemoryAllocationLib
|
MemoryAllocationLib
|
||||||
DevicePathLib
|
DevicePathLib
|
||||||
|
@ -65,4 +68,3 @@
|
||||||
gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
|
gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES
|
gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES
|
gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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_
|
|
@ -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 ();
|
||||||
|
}
|
|
@ -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
|
|
@ -16,6 +16,7 @@
|
||||||
## ]
|
## ]
|
||||||
"ExceptionList": [
|
"ExceptionList": [
|
||||||
"8005", "gRT",
|
"8005", "gRT",
|
||||||
|
"8001", "DxeTpm2MeasureBootLibUnitTestMain",
|
||||||
],
|
],
|
||||||
## Both file path and directory path are accepted.
|
## Both file path and directory path are accepted.
|
||||||
"IgnoreFiles": [
|
"IgnoreFiles": [
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockPlatformPKProtectionLib.inf
|
SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockPlatformPKProtectionLib.inf
|
||||||
SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf
|
SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf
|
||||||
SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf
|
SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf
|
||||||
|
SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf
|
||||||
|
|
||||||
#
|
#
|
||||||
# Build SecurityPkg HOST_APPLICATION Tests
|
# Build SecurityPkg HOST_APPLICATION Tests
|
||||||
|
|
Loading…
Reference in New Issue