TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeTpm2MeasureBootLibSanitizationTest.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>
17
18#include "../DxeTpm2MeasureBootLibSanitization.h"
19
20#define UNIT_TEST_NAME "DxeTpm2MeasureBootLibSanitizationTest"
21#define UNIT_TEST_VERSION "1.0"
22
23#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION 0x00010000
24#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1
25#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128
26
41EFIAPI
43 IN UNIT_TEST_CONTEXT Context
44 )
45{
46 EFI_STATUS Status;
47 EFI_PARTITION_TABLE_HEADER PrimaryHeader;
49 EFI_BLOCK_IO_MEDIA BlockMedia;
50
51 // Generate EFI_BLOCK_IO_MEDIA test data
52 BlockMedia.MediaId = 1;
53 BlockMedia.RemovableMedia = FALSE;
54 BlockMedia.MediaPresent = TRUE;
55 BlockMedia.LogicalPartition = FALSE;
56 BlockMedia.ReadOnly = FALSE;
57 BlockMedia.WriteCaching = FALSE;
58 BlockMedia.BlockSize = 512;
59 BlockMedia.IoAlign = 1;
60 BlockMedia.LastBlock = 0;
61
62 // Generate EFI_BLOCK_IO_PROTOCOL test data
63 BlockIo.Revision = 1;
64 BlockIo.Media = &BlockMedia;
65 BlockIo.Reset = NULL;
66 BlockIo.ReadBlocks = NULL;
67 BlockIo.WriteBlocks = NULL;
68 BlockIo.FlushBlocks = NULL;
69
70 // Geneate EFI_PARTITION_TABLE_HEADER test data
71 PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID;
72 PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION;
73 PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
74 PrimaryHeader.MyLBA = 1;
75 PrimaryHeader.PartitionEntryLBA = 2;
76 PrimaryHeader.AlternateLBA = 3;
77 PrimaryHeader.FirstUsableLBA = 4;
78 PrimaryHeader.LastUsableLBA = 5;
79 PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES;
80 PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
81 PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid
82
83 // Calculate the CRC32 of the PrimaryHeader
84 PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize);
85
86 // Test that a normal PrimaryHeader passes validation
87 Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
89
90 // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR
91 // Should print "Invalid Partition Table Header NumberOfPartitionEntries!""
92 PrimaryHeader.NumberOfPartitionEntries = 0;
93 Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
94 UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
95 PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
96
97 // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR
98 // Should print "Invalid Partition Table Header Size!"
99 PrimaryHeader.Header.HeaderSize = 0;
100 Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
101 UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
102 PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
103
104 // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR
105 // 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.)!"
106 PrimaryHeader.SizeOfPartitionEntry = 1;
107 Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo);
108 UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR);
109
110 DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
111
112 return UNIT_TEST_PASSED;
113}
114
126EFIAPI
128 IN UNIT_TEST_CONTEXT Context
129 )
130{
131 UINT32 AllocationSize;
132
133 EFI_STATUS Status;
134 EFI_PARTITION_TABLE_HEADER PrimaryHeader;
135
136 // Test that a normal PrimaryHeader passes validation
137 PrimaryHeader.NumberOfPartitionEntries = 5;
138 PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
139
140 Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
142
143 // Test that the allocation size is correct compared to the existing logic
144 UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry);
145
146 // Test that an overflow is detected
147 PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
148 PrimaryHeader.SizeOfPartitionEntry = 5;
149 Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
150 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
151
152 // Test the inverse
153 PrimaryHeader.NumberOfPartitionEntries = 5;
154 PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
155 Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
156 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
157
158 // Test the worst case scenario
159 PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32;
160 PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
161 Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize);
162 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
163
164 DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
165
166 return UNIT_TEST_PASSED;
167}
168
180EFIAPI
182 IN UNIT_TEST_CONTEXT Context
183 )
184{
185 UINT32 EventSize;
186 UINT32 ExistingLogicEventSize;
187 EFI_STATUS Status;
188 EFI_PARTITION_TABLE_HEADER PrimaryHeader;
189 UINTN NumberOfPartition;
190
191 // Test that a normal PrimaryHeader passes validation
192 PrimaryHeader.NumberOfPartitionEntries = 5;
193 PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
194
195 // set the number of partitions
196 NumberOfPartition = 13;
197
198 // that the primary event size is correct
199 Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
201
202 // Calculate the existing logic event size
203 ExistingLogicEventSize = (UINT32)(OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF (EFI_GPT_DATA, Partitions)
204 + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry);
205
206 // Check that the event size is correct
207 UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize);
208
209 // Tests that the primary event size may not overflow
210 Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize);
211 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
212
213 // Test that the size of partition entries may not overflow
214 PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32;
215 Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize);
216 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
217
218 DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
219
220 return UNIT_TEST_PASSED;
221}
222
235EFIAPI
237 IN UNIT_TEST_CONTEXT Context
238 )
239{
240 UINT32 EventSize;
241 UINTN ExistingLogicEventSize;
242 UINT32 FilePathSize;
243 EFI_STATUS Status;
244
245 FilePathSize = 255;
246
247 // Test that a normal PE image passes validation
248 Status = Tpm2SanitizePeImageEventSize (FilePathSize, &EventSize);
250
251 // Test that the event size is correct compared to the existing logic
252 ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize;
253 ExistingLogicEventSize += OFFSET_OF (EFI_TCG2_EVENT, Event);
254
255 if (EventSize != ExistingLogicEventSize) {
256 UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize);
257 return UNIT_TEST_ERROR_TEST_FAILED;
258 }
259
260 // Test that the event size may not overflow
261 Status = Tpm2SanitizePeImageEventSize (MAX_UINT32, &EventSize);
262 UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
263
264 DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
265
266 return UNIT_TEST_PASSED;
267}
268
269// *--------------------------------------------------------------------*
270// * Unit Test Code Main Function
271// *--------------------------------------------------------------------*
272
281EFIAPI
283 VOID
284 )
285{
286 EFI_STATUS Status;
287 UNIT_TEST_FRAMEWORK_HANDLE Framework;
288 UNIT_TEST_SUITE_HANDLE Tcg2MeasureBootLibValidationTestSuite;
289
290 Framework = NULL;
291
292 DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME));
293
294 Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
295 if (EFI_ERROR (Status)) {
296 DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status));
297 goto EXIT;
298 }
299
300 Status = CreateUnitTestSuite (&Tcg2MeasureBootLibValidationTestSuite, Framework, "Tcg2MeasureBootLibValidationTestSuite", "Common.Tcg2MeasureBootLibValidation", NULL, NULL);
301 if (EFI_ERROR (Status)) {
302 DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for Tcg2MeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME));
303 Status = EFI_OUT_OF_RESOURCES;
304 goto EXIT;
305 }
306
307 // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context
308 AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
309 AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
310 AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
311 AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL);
312
313 Status = RunAllTestSuites (Framework);
314
315EXIT:
316 if (Framework != NULL) {
317 FreeUnitTestFramework (Framework);
318 }
319
320 DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME));
321 return Status;
322}
323
327#define DxeTpm2MeasureBootLibUnitTestMain main
328
338INT32
340 IN INT32 Argc,
341 IN CHAR8 *Argv[]
342 )
343{
344 return (INT32)UefiTestMain ();
345}
UINT64 UINTN
UINT32 EFIAPI CalculateCrc32(IN VOID *Buffer, IN UINTN Length)
Definition: CheckSum.c:600
EFI_STATUS EFIAPI Tpm2SanitizeEfiPartitionTableHeader(IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo)
EFI_STATUS EFIAPI Tpm2SanitizePrimaryHeaderAllocationSize(IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, OUT UINT32 *AllocationSize)
EFI_STATUS Tpm2SanitizePeImageEventSize(IN UINT32 FilePathSize, OUT UINT32 *EventSize)
EFI_STATUS Tpm2SanitizePrimaryHeaderGptEventSize(IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN UINTN NumberOfPartition, OUT UINT32 *EventSize)
EFI_STATUS EFIAPI UefiTestMain(VOID)
UNIT_TEST_STATUS EFIAPI TestSanitizePeImageEventSize(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestSanitizeEfiPartitionTableHeader(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestSanitizePrimaryHeaderAllocationSize(IN UNIT_TEST_CONTEXT Context)
#define DxeTpm2MeasureBootLibUnitTestMain
UNIT_TEST_STATUS EFIAPI TestSanitizePrimaryHeaderGptEventSize(IN UNIT_TEST_CONTEXT Context)
#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
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
#define EFI_PTAB_HEADER_ID
Definition: UefiGpt.h:20
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