diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c index 1afd60ce66eb..e6aaed27ceba 100644 --- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c @@ -502,6 +502,38 @@ NorFlashRead ( return EFI_SUCCESS; } +STATIC +EFI_STATUS +NorFlashWriteSingleBlockWithErase ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + + // Read NOR Flash data into shadow buffer + Status = NorFlashReadBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer); + if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } + + // Put the data at the appropriate location inside the buffer area + CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes); + + // Write the modified buffer back to the NorFlash + Status = NorFlashWriteBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer); + if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + /* Write a full or portion of a block. It must not span block boundaries; that is, Offset + *NumBytes <= Instance->BlockSize. @@ -520,6 +552,8 @@ NorFlashWriteSingleBlock ( UINTN BlockSize; UINTN BlockAddress; UINT8 *OrigData; + UINTN Start, End; + UINT32 Index, Count; DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer)); @@ -548,14 +582,37 @@ NorFlashWriteSingleBlock ( return EFI_BAD_BUFFER_SIZE; } - // Pick P30_MAX_BUFFER_SIZE_IN_BYTES (== 128 bytes) as a good start for word - // operations as opposed to erasing the block and writing the data regardless - // if an erase is really needed. It looks like most individual NV variable - // writes are smaller than 128 bytes. - // To avoid pathological cases were a 2 byte write is disregarded because it - // occurs right at a 128 byte buffered write alignment boundary, permit up to - // twice the max buffer size, and perform two writes if needed. - if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) { + // Pick 4 * P30_MAX_BUFFER_SIZE_IN_BYTES (== 512 bytes) as a good + // start for word operations as opposed to erasing the block and + // writing the data regardless if an erase is really needed. + // + // Many NV variable updates are small enough for a a single + // P30_MAX_BUFFER_SIZE_IN_BYTES block write. In case the update is + // larger than a single block, or the update crosses a + // P30_MAX_BUFFER_SIZE_IN_BYTES boundary (as shown in the diagram + // below), or both, we might have to write two or more blocks. + // + // 0 128 256 + // [----------------|----------------] + // ^ ^ ^ ^ + // | | | | + // | | | End, the next "word" boundary beyond + // | | | the (logical) update + // | | | + // | | (Offset & BOUNDARY_OF_32_WORDS) + NumBytes; + // | | i.e., the relative offset inside (or just past) + // | | the *double-word* such that it is the + // | | *exclusive* end of the (logical) update. + // | | + // | Offset & BOUNDARY_OF_32_WORDS; i.e., Offset within the "word"; + // | this is where the (logical) update is supposed to start + // | + // Start = Offset & ~BOUNDARY_OF_32_WORDS; i.e., Offset truncated to "word" boundary + + Start = Offset & ~BOUNDARY_OF_32_WORDS; + End = ALIGN_VALUE (Offset + *NumBytes, P30_MAX_BUFFER_SIZE_IN_BYTES); + + if ((End - Start) <= (4 * P30_MAX_BUFFER_SIZE_IN_BYTES)) { // Check to see if we need to erase before programming the data into NOR. // If the destination bits are only changing from 1s to 0s we can just write. // After a block is erased all bits in the block is set to 1. @@ -565,8 +622,8 @@ NorFlashWriteSingleBlock ( Status = NorFlashRead ( Instance, Lba, - Offset & ~BOUNDARY_OF_32_WORDS, - (*NumBytes | BOUNDARY_OF_32_WORDS) + 1, + Start, + End - Start, Instance->ShadowBuffer ); if (EFI_ERROR (Status)) { @@ -581,8 +638,15 @@ NorFlashWriteSingleBlock ( // contents, while checking whether the old version had any bits cleared // that we want to set. In that case, we will need to erase the block first. for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) { - if (~OrigData[CurOffset] & Buffer[CurOffset]) { - goto DoErase; + if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) { + Status = NorFlashWriteSingleBlockWithErase ( + Instance, + Lba, + Offset, + NumBytes, + Buffer + ); + return Status; } OrigData[CurOffset] = Buffer[CurOffset]; @@ -599,53 +663,34 @@ NorFlashWriteSingleBlock ( goto Exit; } - Status = NorFlashWriteBuffer ( - Instance, - BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS), - P30_MAX_BUFFER_SIZE_IN_BYTES, - Instance->ShadowBuffer - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - - if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) > P30_MAX_BUFFER_SIZE_IN_BYTES) { - BlockAddress += P30_MAX_BUFFER_SIZE_IN_BYTES; - + Count = (End - Start) / P30_MAX_BUFFER_SIZE_IN_BYTES; + for (Index = 0; Index < Count; Index++) { Status = NorFlashWriteBuffer ( Instance, - BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS), + BlockAddress + Start + Index * P30_MAX_BUFFER_SIZE_IN_BYTES, P30_MAX_BUFFER_SIZE_IN_BYTES, - Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES + Instance->ShadowBuffer + Index * P30_MAX_BUFFER_SIZE_IN_BYTES ); + if (EFI_ERROR (Status)) { + goto Exit; + } } - -Exit: - // Put device back into Read Array mode - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); - + } else { + Status = NorFlashWriteSingleBlockWithErase ( + Instance, + Lba, + Offset, + NumBytes, + Buffer + ); return Status; } -DoErase: - // Read NOR Flash data into shadow buffer - Status = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); - if (EFI_ERROR (Status)) { - // Return one of the pre-approved error statuses - return EFI_DEVICE_ERROR; - } - - // Put the data at the appropriate location inside the buffer area - CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes); - - // Write the modified buffer back to the NorFlash - Status = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); - if (EFI_ERROR (Status)) { - // Return one of the pre-approved error statuses - return EFI_DEVICE_ERROR; - } +Exit: + // Put device back into Read Array mode + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); - return EFI_SUCCESS; + return Status; } EFI_STATUS diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h index b7f5d208b236..455eafacc2cf 100644 --- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h @@ -61,7 +61,7 @@ #define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128) #define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4)) #define MAX_BUFFERED_PROG_ITERATIONS 10000000 -#define BOUNDARY_OF_32_WORDS 0x7F +#define BOUNDARY_OF_32_WORDS ((UINTN)0x7F) // CFI Addresses #define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10 diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c index 8fcd999ac6df..c8b5e0be1379 100644 --- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c @@ -302,6 +302,11 @@ ValidateFvHeader ( break; } + if (VarHeader->State == 0xff) { + DEBUG ((DEBUG_INFO, "%a: end of var list (unwritten state)\n", __func__)); + break; + } + VarName = NULL; switch (VarHeader->State) { // usage: State = VAR_HEADER_VALID_ONLY diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c index 714cc8e03e80..73719f3b96ed 100644 --- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c @@ -200,7 +200,7 @@ Tcg2MeasureGptTable ( BlockIo->Media->BlockSize, (UINT8 *)PrimaryHeader ); - if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { + if (EFI_ERROR (Status) || EFI_ERROR (Tpm2SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n")); FreePool (PrimaryHeader); return EFI_DEVICE_ERROR; @@ -209,7 +209,7 @@ Tcg2MeasureGptTable ( // // Read the partition entry. // - Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); + Status = Tpm2SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); if (EFI_ERROR (Status)) { FreePool (PrimaryHeader); return EFI_BAD_BUFFER_SIZE; @@ -250,7 +250,7 @@ Tcg2MeasureGptTable ( // // Prepare Data for Measurement (CcProtocol and Tcg2Protocol) // - Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize); + Status = Tpm2SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize); if (EFI_ERROR (Status)) { FreePool (PrimaryHeader); FreePool (EntryPtr); @@ -420,7 +420,7 @@ Tcg2MeasurePeImage ( } FilePathSize = (UINT32)GetDevicePathSize (FilePath); - Status = SanitizePeImageEventSize (FilePathSize, &EventSize); + Status = Tpm2SanitizePeImageEventSize (FilePathSize, &EventSize); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c index 2a4d52c6d5cf..809a3bfd892e 100644 --- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c @@ -63,7 +63,7 @@ **/ EFI_STATUS EFIAPI -SanitizeEfiPartitionTableHeader ( +Tpm2SanitizeEfiPartitionTableHeader ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo ) @@ -169,7 +169,7 @@ SanitizeEfiPartitionTableHeader ( **/ EFI_STATUS EFIAPI -SanitizePrimaryHeaderAllocationSize ( +Tpm2SanitizePrimaryHeaderAllocationSize ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, OUT UINT32 *AllocationSize ) @@ -221,7 +221,7 @@ SanitizePrimaryHeaderAllocationSize ( One of the passed parameters was invalid. **/ EFI_STATUS -SanitizePrimaryHeaderGptEventSize ( +Tpm2SanitizePrimaryHeaderGptEventSize ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN UINTN NumberOfPartition, OUT UINT32 *EventSize @@ -292,7 +292,7 @@ SanitizePrimaryHeaderGptEventSize ( One of the passed parameters was invalid. **/ EFI_STATUS -SanitizePeImageEventSize ( +Tpm2SanitizePeImageEventSize ( IN UINT32 FilePathSize, OUT UINT32 *EventSize ) diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h index 8f72ba42401f..8526bc7537d5 100644 --- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h @@ -54,7 +54,7 @@ **/ EFI_STATUS EFIAPI -SanitizeEfiPartitionTableHeader ( +Tpm2SanitizeEfiPartitionTableHeader ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo ); @@ -78,7 +78,7 @@ SanitizeEfiPartitionTableHeader ( **/ EFI_STATUS EFIAPI -SanitizePrimaryHeaderAllocationSize ( +Tpm2SanitizePrimaryHeaderAllocationSize ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, OUT UINT32 *AllocationSize ); @@ -107,7 +107,7 @@ SanitizePrimaryHeaderAllocationSize ( One of the passed parameters was invalid. **/ EFI_STATUS -SanitizePrimaryHeaderGptEventSize ( +Tpm2SanitizePrimaryHeaderGptEventSize ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN UINTN NumberOfPartition, OUT UINT32 *EventSize @@ -131,7 +131,7 @@ SanitizePrimaryHeaderGptEventSize ( One of the passed parameters was invalid. **/ EFI_STATUS -SanitizePeImageEventSize ( +Tpm2SanitizePeImageEventSize ( IN UINT32 FilePathSize, OUT UINT32 *EventSize ); diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c index 820e99aeb9b4..50a68e1076ad 100644 --- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c @@ -84,27 +84,27 @@ TestSanitizeEfiPartitionTableHeader ( PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize); // Test that a normal PrimaryHeader passes validation - Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + Status = Tpm2SanitizeEfiPartitionTableHeader (&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); + Status = Tpm2SanitizeEfiPartitionTableHeader (&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); + Status = Tpm2SanitizeEfiPartitionTableHeader (&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); + Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); @@ -137,7 +137,7 @@ TestSanitizePrimaryHeaderAllocationSize ( PrimaryHeader.NumberOfPartitionEntries = 5; PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; - Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); UT_ASSERT_NOT_EFI_ERROR (Status); // Test that the allocation size is correct compared to the existing logic @@ -146,19 +146,19 @@ TestSanitizePrimaryHeaderAllocationSize ( // Test that an overflow is detected PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; PrimaryHeader.SizeOfPartitionEntry = 5; - Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); // Test the inverse PrimaryHeader.NumberOfPartitionEntries = 5; PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; - Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + Status = Tpm2SanitizePrimaryHeaderAllocationSize (&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); + Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); @@ -196,7 +196,7 @@ TestSanitizePrimaryHeaderGptEventSize ( NumberOfPartition = 13; // that the primary event size is correct - Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); + Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); UT_ASSERT_NOT_EFI_ERROR (Status); // Calculate the existing logic event size @@ -207,12 +207,12 @@ TestSanitizePrimaryHeaderGptEventSize ( UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); // Tests that the primary event size may not overflow - Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); + Status = Tpm2SanitizePrimaryHeaderGptEventSize (&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); + Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); @@ -245,7 +245,7 @@ TestSanitizePeImageEventSize ( FilePathSize = 255; // Test that a normal PE image passes validation - Status = SanitizePeImageEventSize (FilePathSize, &EventSize); + Status = Tpm2SanitizePeImageEventSize (FilePathSize, &EventSize); UT_ASSERT_EQUAL (Status, EFI_SUCCESS); // Test that the event size is correct compared to the existing logic @@ -258,7 +258,7 @@ TestSanitizePeImageEventSize ( } // Test that the event size may not overflow - Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize); + Status = Tpm2SanitizePeImageEventSize (MAX_UINT32, &EventSize); UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c index a9fc440a091e..ac855b8fbbf4 100644 --- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c @@ -174,7 +174,7 @@ TcgMeasureGptTable ( BlockIo->Media->BlockSize, (UINT8 *)PrimaryHeader ); - if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { + if (EFI_ERROR (Status) || EFI_ERROR (TpmSanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n")); FreePool (PrimaryHeader); return EFI_DEVICE_ERROR; @@ -183,7 +183,7 @@ TcgMeasureGptTable ( // // Read the partition entry. // - Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); + Status = TpmSanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); if (EFI_ERROR (Status)) { FreePool (PrimaryHeader); return EFI_DEVICE_ERROR; @@ -224,7 +224,7 @@ TcgMeasureGptTable ( // // Prepare Data for Measurement // - Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize); + Status = TpmSanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize); TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize); if (TcgEvent == NULL) { FreePool (PrimaryHeader); @@ -351,7 +351,7 @@ TcgMeasurePeImage ( // Determine destination PCR by BootPolicy // - Status = SanitizePeImageEventSize (FilePathSize, &EventSize); + Status = TpmSanitizePeImageEventSize (FilePathSize, &EventSize); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c index c989851cec2d..070e4a2c1cab 100644 --- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c @@ -1,5 +1,5 @@ /** @file - The library instance provides security service of TPM2 measure boot and + The library instance provides security service of TPM measure boot and Confidential Computing (CC) measure boot. Caution: This file requires additional review when modified. @@ -63,7 +63,7 @@ **/ EFI_STATUS EFIAPI -SanitizeEfiPartitionTableHeader ( +TpmSanitizeEfiPartitionTableHeader ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo ) @@ -145,7 +145,7 @@ SanitizeEfiPartitionTableHeader ( **/ EFI_STATUS EFIAPI -SanitizePrimaryHeaderAllocationSize ( +TpmSanitizePrimaryHeaderAllocationSize ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, OUT UINT32 *AllocationSize ) @@ -194,7 +194,7 @@ SanitizePrimaryHeaderAllocationSize ( One of the passed parameters was invalid. **/ EFI_STATUS -SanitizePrimaryHeaderGptEventSize ( +TpmSanitizePrimaryHeaderGptEventSize ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN UINTN NumberOfPartition, OUT UINT32 *EventSize @@ -258,7 +258,7 @@ SanitizePrimaryHeaderGptEventSize ( One of the passed parameters was invalid. **/ EFI_STATUS -SanitizePeImageEventSize ( +TpmSanitizePeImageEventSize ( IN UINT32 FilePathSize, OUT UINT32 *EventSize ) diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h index 2248495813b5..db6e9c3752d6 100644 --- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h @@ -53,7 +53,7 @@ **/ EFI_STATUS EFIAPI -SanitizeEfiPartitionTableHeader ( +TpmSanitizeEfiPartitionTableHeader ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo ); @@ -77,7 +77,7 @@ SanitizeEfiPartitionTableHeader ( **/ EFI_STATUS EFIAPI -SanitizePrimaryHeaderAllocationSize ( +TpmSanitizePrimaryHeaderAllocationSize ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, OUT UINT32 *AllocationSize ); @@ -105,7 +105,7 @@ SanitizePrimaryHeaderAllocationSize ( One of the passed parameters was invalid. **/ EFI_STATUS -SanitizePrimaryHeaderGptEventSize ( +TpmSanitizePrimaryHeaderGptEventSize ( IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN UINTN NumberOfPartition, OUT UINT32 *EventSize @@ -129,7 +129,7 @@ SanitizePrimaryHeaderGptEventSize ( One of the passed parameters was invalid. **/ EFI_STATUS -SanitizePeImageEventSize ( +TpmSanitizePeImageEventSize ( IN UINT32 FilePathSize, OUT UINT32 *EventSize ); diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c index c41498be4521..de1740af41b3 100644 --- a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c @@ -83,27 +83,27 @@ TestSanitizeEfiPartitionTableHeader ( PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize); // Test that a normal PrimaryHeader passes validation - Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + Status = TpmSanitizeEfiPartitionTableHeader (&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); + Status = TpmSanitizeEfiPartitionTableHeader (&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); + Status = TpmSanitizeEfiPartitionTableHeader (&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); + Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); @@ -136,7 +136,7 @@ TestSanitizePrimaryHeaderAllocationSize ( PrimaryHeader.NumberOfPartitionEntries = 5; PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; - Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); UT_ASSERT_NOT_EFI_ERROR (Status); // Test that the allocation size is correct compared to the existing logic @@ -145,19 +145,19 @@ TestSanitizePrimaryHeaderAllocationSize ( // Test that an overflow is detected PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; PrimaryHeader.SizeOfPartitionEntry = 5; - Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); // Test the inverse PrimaryHeader.NumberOfPartitionEntries = 5; PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; - Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + Status = TpmSanitizePrimaryHeaderAllocationSize (&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); + Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); @@ -195,7 +195,7 @@ TestSanitizePrimaryHeaderGptEventSize ( NumberOfPartition = 13; // that the primary event size is correct - Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); + Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); UT_ASSERT_NOT_EFI_ERROR (Status); // Calculate the existing logic event size @@ -206,12 +206,12 @@ TestSanitizePrimaryHeaderGptEventSize ( UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); // Tests that the primary event size may not overflow - Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); + Status = TpmSanitizePrimaryHeaderGptEventSize (&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); + Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); @@ -269,7 +269,7 @@ TestSanitizePeImageEventSize ( FilePathSize = 255; // Test that a normal PE image passes validation - Status = SanitizePeImageEventSize (FilePathSize, &EventSize); + Status = TpmSanitizePeImageEventSize (FilePathSize, &EventSize); if (EFI_ERROR (Status)) { UT_LOG_ERROR ("SanitizePeImageEventSize failed with %r\n", Status); goto Exit; @@ -285,7 +285,7 @@ TestSanitizePeImageEventSize ( } // Test that the event size may not overflow - Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize); + Status = TpmSanitizePeImageEventSize (MAX_UINT32, &EventSize); if (Status != EFI_BAD_BUFFER_SIZE) { UT_LOG_ERROR ("SanitizePeImageEventSize succeded when it was supposed to fail with %r\n", Status); goto Exit; diff --git a/SecurityPkg/SecurityFixes.yaml b/SecurityPkg/SecurityFixes.yaml index 833fb827a96c..b4006b42b89e 100644 --- a/SecurityPkg/SecurityFixes.yaml +++ b/SecurityPkg/SecurityFixes.yaml @@ -9,28 +9,34 @@ CVE_2022_36763: - "SecurityPkg: DxeTpm2Measurement: SECURITY PATCH 4117 - CVE 2022-36763" - "SecurityPkg: DxeTpmMeasurement: SECURITY PATCH 4117 - CVE 2022-36763" - "SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml" + - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117/4118 symbol rename" + - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117/4118 symbol rename" + - "SecurityPkg: : Updating SecurityFixes.yaml after symbol rename" cve: CVE-2022-36763 date_reported: 2022-10-25 11:31 UTC description: (CVE-2022-36763) - Heap Buffer Overflow in Tcg2MeasureGptTable() note: This patch is related to and supersedes TCBZ2168 files_impacted: - - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c - - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c + - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c + - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c links: - - https://bugzilla.tianocore.org/show_bug.cgi?id=4117 - - https://bugzilla.tianocore.org/show_bug.cgi?id=2168 - - https://bugzilla.tianocore.org/show_bug.cgi?id=1990 + - https://bugzilla.tianocore.org/show_bug.cgi?id=4117 + - https://bugzilla.tianocore.org/show_bug.cgi?id=2168 + - https://bugzilla.tianocore.org/show_bug.cgi?id=1990 CVE_2022_36764: commit_titles: - - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764" - - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764" - - "SecurityPkg: : Adding CVE 2022-36764 to SecurityFixes.yaml" + - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764" + - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764" + - "SecurityPkg: : Adding CVE 2022-36764 to SecurityFixes.yaml" + - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117/4118 symbol rename" + - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117/4118 symbol rename" + - "SecurityPkg: : Updating SecurityFixes.yaml after symbol rename" cve: CVE-2022-36764 date_reported: 2022-10-25 12:23 UTC description: Heap Buffer Overflow in Tcg2MeasurePeImage() note: files_impacted: - - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c - - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c + - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c + - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c links: - - https://bugzilla.tianocore.org/show_bug.cgi?id=4118 + - https://bugzilla.tianocore.org/show_bug.cgi?id=4118