TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeTpmMeasureBootLibSanitizationTest.c
Go to the documentation of this file.
1
8#include <Uefi.h>
9#include <Library/UefiLib.h>
10#include <Library/DebugLib.h>
11#include <Library/UnitTestLib.h>
12#include <Protocol/BlockIo.h>
16
17#include "../DxeTpmMeasureBootLibSanitization.h"
18
19#define UNIT_TEST_NAME "DxeTpmMeasureBootLibSanitizationTest"
20#define UNIT_TEST_VERSION "1.0"
21
22#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION 0x00010000
23#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1
24#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128
25
40EFIAPI
42 IN UNIT_TEST_CONTEXT Context
43 )
44{
45 EFI_STATUS Status;
46 EFI_PARTITION_TABLE_HEADER PrimaryHeader;
48 EFI_BLOCK_IO_MEDIA BlockMedia;
49
50 // Generate EFI_BLOCK_IO_MEDIA test data
51 BlockMedia.MediaId = 1;
52 BlockMedia.RemovableMedia = FALSE;
53 BlockMedia.MediaPresent = TRUE;
54 BlockMedia.LogicalPartition = FALSE;
55 BlockMedia.ReadOnly = FALSE;
56 BlockMedia.WriteCaching = FALSE;
57 BlockMedia.BlockSize = 512;
58 BlockMedia.IoAlign = 1;
59 BlockMedia.LastBlock = 0;
60
61 // Generate EFI_BLOCK_IO_PROTOCOL test data
62 BlockIo.Revision = 1;
63 BlockIo.Media = &BlockMedia;
64 BlockIo.Reset = NULL;
65 BlockIo.ReadBlocks = NULL;
66 BlockIo.WriteBlocks = NULL;
67 BlockIo.FlushBlocks = NULL;
68
69 // Geneate EFI_PARTITION_TABLE_HEADER test data
70 PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID;
71 PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION;
72 PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
73 PrimaryHeader.MyLBA = 1;
74 PrimaryHeader.AlternateLBA = 2;
75 PrimaryHeader.FirstUsableLBA = 3;
76 PrimaryHeader.LastUsableLBA = 4;
77 PrimaryHeader.PartitionEntryLBA = 5;
78 PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES;
79 PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
80 PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid
81
82 // Calculate the CRC32 of the PrimaryHeader
83 PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize);
84
85 // Test that a normal PrimaryHeader passes validation
86 Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
88
89 // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR
90 // Should print "Invalid Partition Table Header NumberOfPartitionEntries!""
91 PrimaryHeader.NumberOfPartitionEntries = 0;
92 Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
93 UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
94 PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
95
96 // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR
97 // Should print "Invalid Partition Table Header Size!"
98 PrimaryHeader.Header.HeaderSize = 0;
99 Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
100 UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
101 PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
102
103 // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR
104 // 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.)!"
105 PrimaryHeader.SizeOfPartitionEntry = 1;
106 Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
107 UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
108
109 DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
110
111 return UNIT_TEST_PASSED;
112}
113
125EFIAPI
127 IN UNIT_TEST_CONTEXT Context
128 )
129{
130 UINT32 AllocationSize;
131
132 EFI_STATUS Status;
133 EFI_PARTITION_TABLE_HEADER PrimaryHeader;
134
135 // Test that a normal PrimaryHeader passes validation
136 PrimaryHeader.NumberOfPartitionEntries = 5;
137 PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
138
139 Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
141
142 // Test that the allocation size is correct compared to the existing logic
143 UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry);
144
145 // Test that an overflow is detected
146 PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
147 PrimaryHeader.SizeOfPartitionEntry = 5;
148 Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
149 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
150
151 // Test the inverse
152 PrimaryHeader.NumberOfPartitionEntries = 5;
153 PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
154 Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
155 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
156
157 // Test the worst case scenario
158 PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
159 PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
160 Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
161 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
162
163 DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
164
165 return UNIT_TEST_PASSED;
166}
167
179EFIAPI
181 IN UNIT_TEST_CONTEXT Context
182 )
183{
184 UINT32 EventSize;
185 UINT32 ExistingLogicEventSize;
186 EFI_STATUS Status;
187 EFI_PARTITION_TABLE_HEADER PrimaryHeader;
188 UINTN NumberOfPartition;
189
190 // Test that a normal PrimaryHeader passes validation
191 PrimaryHeader.NumberOfPartitionEntries = 5;
192 PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
193
194 // set the number of partitions
195 NumberOfPartition = 13;
196
197 // that the primary event size is correct
198 Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
200
201 // Calculate the existing logic event size
202 ExistingLogicEventSize = (UINT32)(sizeof (TCG_PCR_EVENT_HDR) + OFFSET_OF (EFI_GPT_DATA, Partitions)
203 + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry);
204
205 // Check that the event size is correct
206 UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize);
207
208 // Tests that the primary event size may not overflow
209 Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize);
210 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
211
212 // Test that the size of partition entries may not overflow
213 PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
214 Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
215 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
216
217 DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
218
219 return UNIT_TEST_PASSED;
220}
221
234EFIAPI
236 IN UNIT_TEST_CONTEXT Context
237 )
238{
239 UINT32 EventSize;
240 UINTN ExistingLogicEventSize;
241 UINT32 FilePathSize;
242 EFI_STATUS Status;
243 EFI_DEVICE_PATH_PROTOCOL DevicePath;
244 EFI_IMAGE_LOAD_EVENT *ImageLoadEvent;
245 UNIT_TEST_STATUS TestStatus;
246
247 TestStatus = UNIT_TEST_ERROR_TEST_FAILED;
248
249 // Generate EFI_DEVICE_PATH_PROTOCOL test data
250 DevicePath.Type = 0;
251 DevicePath.SubType = 0;
252 DevicePath.Length[0] = 0;
253 DevicePath.Length[1] = 0;
254
255 // Generate EFI_IMAGE_LOAD_EVENT test data
256 ImageLoadEvent = AllocateZeroPool (sizeof (EFI_IMAGE_LOAD_EVENT) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
257 if (ImageLoadEvent == NULL) {
258 DEBUG ((DEBUG_ERROR, "%a: AllocateZeroPool failed\n", __func__));
259 goto Exit;
260 }
261
262 // Populate EFI_IMAGE_LOAD_EVENT54 test data
263 ImageLoadEvent->ImageLocationInMemory = (EFI_PHYSICAL_ADDRESS)0x12345678;
264 ImageLoadEvent->ImageLengthInMemory = 0x1000;
265 ImageLoadEvent->ImageLinkTimeAddress = (UINTN)ImageLoadEvent;
266 ImageLoadEvent->LengthOfDevicePath = sizeof (EFI_DEVICE_PATH_PROTOCOL);
267 CopyMem (ImageLoadEvent->DevicePath, &DevicePath, sizeof (EFI_DEVICE_PATH_PROTOCOL));
268
269 FilePathSize = 255;
270
271 // Test that a normal PE image passes validation
272 Status = TpmSanitizePeImageEventSize (FilePathSize, &EventSize);
273 if (EFI_ERROR (Status)) {
274 UT_LOG_ERROR ("SanitizePeImageEventSize failed with %r\n", Status);
275 goto Exit;
276 }
277
278 // Test that the event size is correct compared to the existing logic
279 ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize;
280 ExistingLogicEventSize += sizeof (TCG_PCR_EVENT_HDR);
281
282 if (EventSize != ExistingLogicEventSize) {
283 UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize);
284 goto Exit;
285 }
286
287 // Test that the event size may not overflow
288 Status = TpmSanitizePeImageEventSize (MAX_UINT32, &EventSize);
289 if (Status != EFI_BAD_BUFFER_SIZE) {
290 UT_LOG_ERROR ("SanitizePeImageEventSize succeded when it was supposed to fail with %r\n", Status);
291 goto Exit;
292 }
293
294 TestStatus = UNIT_TEST_PASSED;
295Exit:
296
297 if (ImageLoadEvent != NULL) {
298 FreePool (ImageLoadEvent);
299 }
300
301 if (TestStatus == UNIT_TEST_ERROR_TEST_FAILED) {
302 DEBUG ((DEBUG_ERROR, "%a: Test failed\n", __func__));
303 } else {
304 DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
305 }
306
307 return TestStatus;
308}
309
310// *--------------------------------------------------------------------*
311// * Unit Test Code Main Function
312// *--------------------------------------------------------------------*
313
323EFIAPI
325 VOID
326 )
327{
328 EFI_STATUS Status;
329 UNIT_TEST_FRAMEWORK_HANDLE Framework;
330 UNIT_TEST_SUITE_HANDLE TcgMeasureBootLibValidationTestSuite;
331
332 Framework = NULL;
333
334 DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME));
335
336 Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
337 if (EFI_ERROR (Status)) {
338 DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status));
339 goto EXIT;
340 }
341
342 Status = CreateUnitTestSuite (&TcgMeasureBootLibValidationTestSuite, Framework, "TcgMeasureBootLibValidationTestSuite", "Common.TcgMeasureBootLibValidation", NULL, NULL);
343 if (EFI_ERROR (Status)) {
344 DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for TcgMeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME));
345 Status = EFI_OUT_OF_RESOURCES;
346 goto EXIT;
347 }
348
349 // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context
350 AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.TcgMeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
351 AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
352 AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
353 AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL);
354
355 Status = RunAllTestSuites (Framework);
356
357EXIT:
358 if (Framework != NULL) {
359 FreeUnitTestFramework (Framework);
360 }
361
362 DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME));
363 return Status;
364}
365
369#define DxeTpmMeasureBootLibUnitTestMain main
370
380INT32
382 IN INT32 Argc,
383 IN CHAR8 *Argv[]
384 )
385{
386 return (INT32)UefiTestMain ();
387}
UINT64 UINTN
UINT32 EFIAPI CalculateCrc32(IN VOID *Buffer, IN UINTN Length)
Definition: CheckSum.c:600
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_STATUS EFIAPI TpmSanitizePrimaryHeaderAllocationSize(IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, OUT UINT32 *AllocationSize)
EFI_STATUS TpmSanitizePrimaryHeaderGptEventSize(IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN UINTN NumberOfPartition, OUT UINT32 *EventSize)
EFI_STATUS EFIAPI TpmSanitizeEfiPartitionTableHeader(IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo)
EFI_STATUS TpmSanitizePeImageEventSize(IN UINT32 FilePathSize, OUT UINT32 *EventSize)
EFI_STATUS EFIAPI UefiTestMain(VOID)
UNIT_TEST_STATUS EFIAPI TestSanitizePeImageEventSize(IN UNIT_TEST_CONTEXT Context)
#define DxeTpmMeasureBootLibUnitTestMain
UNIT_TEST_STATUS EFIAPI TestSanitizeEfiPartitionTableHeader(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestSanitizePrimaryHeaderAllocationSize(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestSanitizePrimaryHeaderGptEventSize(IN UNIT_TEST_CONTEXT Context)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID EFIAPI Exit(IN EFI_STATUS Status)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_PTAB_HEADER_ID
Definition: UefiGpt.h:20
struct tdTCG_PCR_EVENT_HDR TCG_PCR_EVENT_HDR
EFI_STATUS EFIAPI RunAllTestSuites(IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle)
Definition: RunTests.c:145
#define UT_LOG_ERROR(Format,...)
Definition: UnitTestLib.h:791
VOID * UNIT_TEST_CONTEXT
Definition: UnitTestLib.h:54
#define UT_ASSERT_EQUAL(ValueA, ValueB)
Definition: UnitTestLib.h:375
EFI_STATUS EFIAPI CreateUnitTestSuite(OUT UNIT_TEST_SUITE_HANDLE *SuiteHandle, IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle, IN CHAR8 *Title, IN CHAR8 *Name, IN UNIT_TEST_SUITE_SETUP Setup OPTIONAL, IN UNIT_TEST_SUITE_TEARDOWN Teardown OPTIONAL)
Definition: UnitTestLib.c:326
EFI_STATUS EFIAPI FreeUnitTestFramework(IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle)
Definition: UnitTestLib.c:150
EFI_STATUS EFIAPI AddTestCase(IN UNIT_TEST_SUITE_HANDLE SuiteHandle, IN CHAR8 *Description, IN CHAR8 *Name, IN UNIT_TEST_FUNCTION Function, IN UNIT_TEST_PREREQUISITE Prerequisite OPTIONAL, IN UNIT_TEST_CLEANUP CleanUp OPTIONAL, IN UNIT_TEST_CONTEXT Context OPTIONAL)
Definition: UnitTestLib.c:426
EFI_STATUS EFIAPI InitUnitTestFramework(OUT UNIT_TEST_FRAMEWORK_HANDLE *FrameworkHandle, IN CHAR8 *Title, IN CHAR8 *ShortTitle, IN CHAR8 *VersionString)
Definition: UnitTestLib.c:204
UINT32 UNIT_TEST_STATUS
Definition: UnitTestLib.h:16
#define UT_ASSERT_NOT_EFI_ERROR(Status)
Definition: UnitTestLib.h:414
EFI_BLOCK_IO_MEDIA * Media
Definition: BlockIo.h:224
BOOLEAN RemovableMedia
Definition: BlockIo.h:137
BOOLEAN LogicalPartition
Definition: BlockIo.h:150
UINT32 BlockSize
Definition: BlockIo.h:167
EFI_LBA LastBlock
Definition: BlockIo.h:178
BOOLEAN WriteCaching
Definition: BlockIo.h:161
BOOLEAN MediaPresent
Definition: BlockIo.h:144
BOOLEAN ReadOnly
Definition: BlockIo.h:156
EFI_TABLE_HEADER Header
Definition: UefiGpt.h:36
UINT32 PartitionEntryArrayCRC32
Definition: UefiGpt.h:80
UINT32 NumberOfPartitionEntries
Definition: UefiGpt.h:66