]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SecurityPkg / Library / DxeTpm2MeasureBootLib / DxeTpm2MeasureBootLib.c
CommitLineData
c1d93242 1/** @file\r
a124cd4e
MX
2 The library instance provides security service of TPM2 measure boot and\r
3 Confidential Computing (CC) measure boot.\r
c1d93242
JY
4\r
5 Caution: This file requires additional review when modified.\r
6 This library will have external input - PE/COFF image and GPT partition.\r
7 This external input must be validated carefully to avoid security issue like\r
8 buffer overflow, integer overflow.\r
9\r
10 DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content\r
11 read is within the image buffer.\r
12\r
1abfa4ce 13 Tcg2MeasurePeImage() function will accept untrusted PE/COFF image and validate its\r
c1d93242
JY
14 data structure within this image buffer before use.\r
15\r
1abfa4ce 16 Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse\r
c1d93242
JY
17 partition data carefully.\r
18\r
b3548d32 19Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>\r
6aaac383 20(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
289b714b 21SPDX-License-Identifier: BSD-2-Clause-Patent\r
c1d93242
JY
22\r
23**/\r
24\r
25#include <PiDxe.h>\r
26\r
1abfa4ce 27#include <Protocol/Tcg2Protocol.h>\r
c1d93242
JY
28#include <Protocol/BlockIo.h>\r
29#include <Protocol/DiskIo.h>\r
30#include <Protocol/DevicePathToText.h>\r
31#include <Protocol/FirmwareVolumeBlock.h>\r
32\r
33#include <Guid/MeasuredFvHob.h>\r
34\r
35#include <Library/BaseLib.h>\r
36#include <Library/DebugLib.h>\r
37#include <Library/BaseMemoryLib.h>\r
38#include <Library/MemoryAllocationLib.h>\r
39#include <Library/DevicePathLib.h>\r
40#include <Library/UefiBootServicesTableLib.h>\r
41#include <Library/BaseCryptLib.h>\r
42#include <Library/PeCoffLib.h>\r
43#include <Library/SecurityManagementLib.h>\r
44#include <Library/HobLib.h>\r
a124cd4e
MX
45#include <Protocol/CcMeasurement.h>\r
46\r
47typedef struct {\r
48 EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
49 EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;\r
50} MEASURE_BOOT_PROTOCOLS;\r
c1d93242
JY
51\r
52//\r
53// Flag to check GPT partition. It only need be measured once.\r
54//\r
c411b485
MK
55BOOLEAN mTcg2MeasureGptTableFlag = FALSE;\r
56UINTN mTcg2MeasureGptCount = 0;\r
57VOID *mTcg2FileBuffer;\r
58UINTN mTcg2ImageSize;\r
c1d93242
JY
59//\r
60// Measured FV handle cache\r
61//\r
c411b485
MK
62EFI_HANDLE mTcg2CacheMeasuredHandle = NULL;\r
63MEASURED_HOB_DATA *mTcg2MeasuredHobData = NULL;\r
c1d93242
JY
64\r
65/**\r
66 Reads contents of a PE/COFF image in memory buffer.\r
67\r
68 Caution: This function may receive untrusted input.\r
69 PE/COFF image is external input, so this function will make sure the PE/COFF image content\r
70 read is within the image buffer.\r
71\r
72 @param FileHandle Pointer to the file handle to read the PE/COFF image.\r
73 @param FileOffset Offset into the PE/COFF image to begin the read operation.\r
b3548d32 74 @param ReadSize On input, the size in bytes of the requested read operation.\r
c1d93242
JY
75 On output, the number of bytes actually read.\r
76 @param Buffer Output buffer that contains the data read from the PE/COFF image.\r
b3548d32
LG
77\r
78 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size\r
c1d93242
JY
79**/\r
80EFI_STATUS\r
81EFIAPI\r
82DxeTpm2MeasureBootLibImageRead (\r
c411b485
MK
83 IN VOID *FileHandle,\r
84 IN UINTN FileOffset,\r
85 IN OUT UINTN *ReadSize,\r
86 OUT VOID *Buffer\r
c1d93242
JY
87 )\r
88{\r
c411b485 89 UINTN EndPosition;\r
c1d93242 90\r
c411b485 91 if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {\r
c1d93242
JY
92 return EFI_INVALID_PARAMETER;\r
93 }\r
94\r
95 if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
96 return EFI_INVALID_PARAMETER;\r
97 }\r
98\r
99 EndPosition = FileOffset + *ReadSize;\r
1abfa4ce
JY
100 if (EndPosition > mTcg2ImageSize) {\r
101 *ReadSize = (UINT32)(mTcg2ImageSize - FileOffset);\r
c1d93242
JY
102 }\r
103\r
1abfa4ce 104 if (FileOffset >= mTcg2ImageSize) {\r
c1d93242
JY
105 *ReadSize = 0;\r
106 }\r
107\r
c411b485 108 CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);\r
c1d93242
JY
109\r
110 return EFI_SUCCESS;\r
111}\r
112\r
113/**\r
114 Measure GPT table data into TPM log.\r
115\r
116 Caution: This function may receive untrusted input.\r
117 The GPT partition table is external input, so this function should parse partition data carefully.\r
118\r
a124cd4e 119 @param MeasureBootProtocols Pointer to the located MeasureBoot protocol instances (i.e. TCG2/CC protocol).\r
c1d93242
JY
120 @param GptHandle Handle that GPT partition was installed.\r
121\r
122 @retval EFI_SUCCESS Successfully measure GPT table.\r
123 @retval EFI_UNSUPPORTED Not support GPT table on the given handle.\r
124 @retval EFI_DEVICE_ERROR Can't get GPT table because device error.\r
125 @retval EFI_OUT_OF_RESOURCES No enough resource to measure GPT table.\r
126 @retval other error value\r
127**/\r
128EFI_STATUS\r
129EFIAPI\r
1abfa4ce 130Tcg2MeasureGptTable (\r
a124cd4e
MX
131 IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols,\r
132 IN EFI_HANDLE GptHandle\r
c1d93242
JY
133 )\r
134{\r
a124cd4e
MX
135 EFI_STATUS Status;\r
136 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
137 EFI_DISK_IO_PROTOCOL *DiskIo;\r
138 EFI_PARTITION_TABLE_HEADER *PrimaryHeader;\r
139 EFI_PARTITION_ENTRY *PartitionEntry;\r
140 UINT8 *EntryPtr;\r
141 UINTN NumberOfPartition;\r
142 UINT32 Index;\r
143 UINT8 *EventPtr;\r
144 EFI_TCG2_EVENT *Tcg2Event;\r
145 EFI_CC_EVENT *CcEvent;\r
146 EFI_GPT_DATA *GptData;\r
147 UINT32 EventSize;\r
148 EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
149 EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;\r
150 EFI_CC_MR_INDEX MrIndex;\r
c1d93242 151\r
1abfa4ce 152 if (mTcg2MeasureGptCount > 0) {\r
c1d93242
JY
153 return EFI_SUCCESS;\r
154 }\r
155\r
a124cd4e
MX
156 PrimaryHeader = NULL;\r
157 EntryPtr = NULL;\r
158 EventPtr = NULL;\r
159\r
160 Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;\r
161 CcProtocol = MeasureBootProtocols->CcProtocol;\r
162\r
163 if ((Tcg2Protocol == NULL) && (CcProtocol == NULL)) {\r
164 ASSERT (FALSE);\r
165 return EFI_UNSUPPORTED;\r
166 }\r
167\r
168 if (sizeof (EFI_CC_EVENT) != sizeof (EFI_TCG2_EVENT)) {\r
169 ASSERT (FALSE);\r
170 return EFI_UNSUPPORTED;\r
171 }\r
172\r
c411b485 173 Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
c1d93242
JY
174 if (EFI_ERROR (Status)) {\r
175 return EFI_UNSUPPORTED;\r
176 }\r
c411b485
MK
177\r
178 Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);\r
c1d93242
JY
179 if (EFI_ERROR (Status)) {\r
180 return EFI_UNSUPPORTED;\r
181 }\r
c411b485 182\r
c1d93242
JY
183 //\r
184 // Read the EFI Partition Table Header\r
b3548d32 185 //\r
c411b485 186 PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *)AllocatePool (BlockIo->Media->BlockSize);\r
c1d93242
JY
187 if (PrimaryHeader == NULL) {\r
188 return EFI_OUT_OF_RESOURCES;\r
b3548d32 189 }\r
c411b485 190\r
c1d93242
JY
191 Status = DiskIo->ReadDisk (\r
192 DiskIo,\r
193 BlockIo->Media->MediaId,\r
194 1 * BlockIo->Media->BlockSize,\r
195 BlockIo->Media->BlockSize,\r
196 (UINT8 *)PrimaryHeader\r
197 );\r
198 if (EFI_ERROR (Status)) {\r
e905fbb0 199 DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n"));\r
c1d93242
JY
200 FreePool (PrimaryHeader);\r
201 return EFI_DEVICE_ERROR;\r
b3548d32 202 }\r
c411b485 203\r
a124cd4e
MX
204 //\r
205 // PrimaryHeader->SizeOfPartitionEntry should not be zero\r
206 //\r
207 if (PrimaryHeader->SizeOfPartitionEntry == 0) {\r
208 DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n"));\r
209 FreePool (PrimaryHeader);\r
210 return EFI_BAD_BUFFER_SIZE;\r
211 }\r
212\r
c1d93242
JY
213 //\r
214 // Read the partition entry.\r
215 //\r
216 EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);\r
217 if (EntryPtr == NULL) {\r
218 FreePool (PrimaryHeader);\r
219 return EFI_OUT_OF_RESOURCES;\r
220 }\r
c411b485 221\r
c1d93242
JY
222 Status = DiskIo->ReadDisk (\r
223 DiskIo,\r
224 BlockIo->Media->MediaId,\r
c411b485 225 MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
c1d93242
JY
226 PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,\r
227 EntryPtr\r
228 );\r
229 if (EFI_ERROR (Status)) {\r
230 FreePool (PrimaryHeader);\r
231 FreePool (EntryPtr);\r
232 return EFI_DEVICE_ERROR;\r
233 }\r
b3548d32 234\r
c1d93242
JY
235 //\r
236 // Count the valid partition\r
237 //\r
238 PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr;\r
239 NumberOfPartition = 0;\r
240 for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
965268ea 241 if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {\r
b3548d32 242 NumberOfPartition++;\r
c1d93242 243 }\r
c411b485 244\r
c1d93242
JY
245 PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
246 }\r
247\r
248 //\r
a124cd4e 249 // Prepare Data for Measurement (CcProtocol and Tcg2Protocol)\r
b3548d32
LG
250 //\r
251 EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)\r
c411b485 252 + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
a124cd4e
MX
253 EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));\r
254 if (EventPtr == NULL) {\r
255 Status = EFI_OUT_OF_RESOURCES;\r
256 goto Exit;\r
c1d93242
JY
257 }\r
258\r
a124cd4e 259 Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;\r
c411b485
MK
260 Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);\r
261 Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);\r
1abfa4ce
JY
262 Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;\r
263 Tcg2Event->Header.PCRIndex = 5;\r
264 Tcg2Event->Header.EventType = EV_EFI_GPT_EVENT;\r
c411b485 265 GptData = (EFI_GPT_DATA *)Tcg2Event->Event;\r
c1d93242
JY
266\r
267 //\r
268 // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition\r
b3548d32 269 //\r
c411b485 270 CopyMem ((UINT8 *)GptData, (UINT8 *)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));\r
c1d93242
JY
271 GptData->NumberOfPartitions = NumberOfPartition;\r
272 //\r
273 // Copy the valid partition entry\r
274 //\r
c411b485 275 PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr;\r
c1d93242
JY
276 NumberOfPartition = 0;\r
277 for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
965268ea 278 if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {\r
c1d93242
JY
279 CopyMem (\r
280 (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry,\r
281 (UINT8 *)PartitionEntry,\r
282 PrimaryHeader->SizeOfPartitionEntry\r
283 );\r
284 NumberOfPartition++;\r
285 }\r
c411b485
MK
286\r
287 PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
c1d93242
JY
288 }\r
289\r
290 //\r
a124cd4e
MX
291 // Only one of TCG2_PROTOCOL or CC_MEASUREMENT_PROTOCOL is exposed.\r
292 // So Measure the GPT data with one of the protocol.\r
c1d93242 293 //\r
a124cd4e
MX
294 if (CcProtocol != NULL) {\r
295 //\r
296 // EFI_CC_EVENT share the same data structure with EFI_TCG2_EVENT\r
297 // except the MrIndex and PCRIndex in Header.\r
298 // Tcg2Event has been created and initialized before. So only the MrIndex need\r
299 // be adjusted.\r
300 //\r
301 Status = CcProtocol->MapPcrToMrIndex (CcProtocol, Tcg2Event->Header.PCRIndex, &MrIndex);\r
302 if (EFI_ERROR (Status)) {\r
303 DEBUG ((DEBUG_ERROR, "Cannot map PcrIndex(%d) to MrIndex\n", Tcg2Event->Header.PCRIndex));\r
304 goto Exit;\r
305 }\r
306\r
307 CcEvent = (EFI_CC_EVENT *)EventPtr;\r
308 CcEvent->Header.MrIndex = MrIndex;\r
309 Status = CcProtocol->HashLogExtendEvent (\r
310 CcProtocol,\r
311 0,\r
312 (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,\r
313 (UINT64)EventSize,\r
314 CcEvent\r
315 );\r
316 if (!EFI_ERROR (Status)) {\r
317 mTcg2MeasureGptCount++;\r
318 }\r
319\r
320 DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Cc MeasureGptTable - %r\n", Status));\r
321 } else if (Tcg2Protocol != NULL) {\r
322 //\r
323 // If Tcg2Protocol is installed, then Measure GPT data with this protocol.\r
324 //\r
325 Status = Tcg2Protocol->HashLogExtendEvent (\r
326 Tcg2Protocol,\r
327 0,\r
328 (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,\r
329 (UINT64)EventSize,\r
330 Tcg2Event\r
331 );\r
332 if (!EFI_ERROR (Status)) {\r
333 mTcg2MeasureGptCount++;\r
334 }\r
335\r
336 DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2 MeasureGptTable - %r\n", Status));\r
c1d93242
JY
337 }\r
338\r
a124cd4e
MX
339Exit:\r
340 if (PrimaryHeader != NULL) {\r
341 FreePool (PrimaryHeader);\r
342 }\r
343\r
344 if (EntryPtr != NULL) {\r
345 FreePool (EntryPtr);\r
346 }\r
347\r
348 if (EventPtr != NULL) {\r
349 FreePool (EventPtr);\r
350 }\r
c1d93242
JY
351\r
352 return Status;\r
353}\r
354\r
355/**\r
356 Measure PE image into TPM log based on the authenticode image hashing in\r
357 PE/COFF Specification 8.0 Appendix A.\r
358\r
359 Caution: This function may receive untrusted input.\r
360 PE/COFF image is external input, so this function will validate its data structure\r
361 within this image buffer before use.\r
362\r
a124cd4e
MX
363 @param[in] MeasureBootProtocols Pointer to the located MeasureBoot protocol instances.\r
364 @param[in] ImageAddress Start address of image buffer.\r
365 @param[in] ImageSize Image size\r
366 @param[in] LinkTimeBase Address that the image is loaded into memory.\r
367 @param[in] ImageType Image subsystem type.\r
368 @param[in] FilePath File path is corresponding to the input image.\r
c1d93242
JY
369\r
370 @retval EFI_SUCCESS Successfully measure image.\r
371 @retval EFI_OUT_OF_RESOURCES No enough resource to measure image.\r
b3548d32 372 @retval EFI_UNSUPPORTED ImageType is unsupported or PE image is mal-format.\r
c1d93242
JY
373 @retval other error value\r
374\r
375**/\r
376EFI_STATUS\r
377EFIAPI\r
1abfa4ce 378Tcg2MeasurePeImage (\r
a124cd4e 379 IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols,\r
c1d93242
JY
380 IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
381 IN UINTN ImageSize,\r
382 IN UINTN LinkTimeBase,\r
383 IN UINT16 ImageType,\r
384 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
385 )\r
386{\r
a124cd4e
MX
387 EFI_STATUS Status;\r
388 EFI_TCG2_EVENT *Tcg2Event;\r
389 EFI_IMAGE_LOAD_EVENT *ImageLoad;\r
390 UINT32 FilePathSize;\r
391 UINT32 EventSize;\r
392 EFI_CC_EVENT *CcEvent;\r
393 EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;\r
394 EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
395 UINT8 *EventPtr;\r
396 EFI_CC_MR_INDEX MrIndex;\r
397\r
398 Status = EFI_UNSUPPORTED;\r
399 ImageLoad = NULL;\r
400 EventPtr = NULL;\r
401\r
402 Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;\r
403 CcProtocol = MeasureBootProtocols->CcProtocol;\r
404\r
405 if ((Tcg2Protocol == NULL) && (CcProtocol == NULL)) {\r
406 ASSERT (FALSE);\r
407 return EFI_UNSUPPORTED;\r
408 }\r
409\r
410 if (sizeof (EFI_CC_EVENT) != sizeof (EFI_TCG2_EVENT)) {\r
411 ASSERT (FALSE);\r
412 return EFI_UNSUPPORTED;\r
413 }\r
414\r
c411b485 415 FilePathSize = (UINT32)GetDevicePathSize (FilePath);\r
c1d93242
JY
416\r
417 //\r
418 // Determine destination PCR by BootPolicy\r
419 //\r
420 EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;\r
a124cd4e
MX
421 EventPtr = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));\r
422 if (EventPtr == NULL) {\r
c1d93242
JY
423 return EFI_OUT_OF_RESOURCES;\r
424 }\r
425\r
a124cd4e 426 Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;\r
c411b485
MK
427 Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);\r
428 Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);\r
1abfa4ce 429 Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;\r
c411b485 430 ImageLoad = (EFI_IMAGE_LOAD_EVENT *)Tcg2Event->Event;\r
c1d93242
JY
431\r
432 switch (ImageType) {\r
433 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
1abfa4ce
JY
434 Tcg2Event->Header.EventType = EV_EFI_BOOT_SERVICES_APPLICATION;\r
435 Tcg2Event->Header.PCRIndex = 4;\r
c1d93242
JY
436 break;\r
437 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
1abfa4ce
JY
438 Tcg2Event->Header.EventType = EV_EFI_BOOT_SERVICES_DRIVER;\r
439 Tcg2Event->Header.PCRIndex = 2;\r
c1d93242
JY
440 break;\r
441 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
1abfa4ce
JY
442 Tcg2Event->Header.EventType = EV_EFI_RUNTIME_SERVICES_DRIVER;\r
443 Tcg2Event->Header.PCRIndex = 2;\r
c1d93242
JY
444 break;\r
445 default:\r
446 DEBUG ((\r
e905fbb0 447 DEBUG_ERROR,\r
1abfa4ce 448 "Tcg2MeasurePeImage: Unknown subsystem type %d",\r
c1d93242
JY
449 ImageType\r
450 ));\r
451 goto Finish;\r
452 }\r
453\r
454 ImageLoad->ImageLocationInMemory = ImageAddress;\r
455 ImageLoad->ImageLengthInMemory = ImageSize;\r
456 ImageLoad->ImageLinkTimeAddress = LinkTimeBase;\r
457 ImageLoad->LengthOfDevicePath = FilePathSize;\r
7a1f792d
ED
458 if ((FilePath != NULL) && (FilePathSize != 0)) {\r
459 CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);\r
460 }\r
c1d93242
JY
461\r
462 //\r
463 // Log the PE data\r
464 //\r
a124cd4e
MX
465 if (CcProtocol != NULL) {\r
466 Status = CcProtocol->MapPcrToMrIndex (CcProtocol, Tcg2Event->Header.PCRIndex, &MrIndex);\r
467 if (EFI_ERROR (Status)) {\r
468 DEBUG ((DEBUG_ERROR, "Cannot map PcrIndex(%d) to MrIndex\n", Tcg2Event->Header.PCRIndex));\r
469 goto Finish;\r
470 }\r
471\r
472 CcEvent = (EFI_CC_EVENT *)EventPtr;\r
473 CcEvent->Header.MrIndex = MrIndex;\r
474\r
475 Status = CcProtocol->HashLogExtendEvent (\r
476 CcProtocol,\r
c411b485
MK
477 PE_COFF_IMAGE,\r
478 ImageAddress,\r
479 ImageSize,\r
a124cd4e 480 CcEvent\r
c411b485 481 );\r
a124cd4e
MX
482 DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Cc MeasurePeImage - %r\n", Status));\r
483 } else if (Tcg2Protocol != NULL) {\r
484 Status = Tcg2Protocol->HashLogExtendEvent (\r
485 Tcg2Protocol,\r
486 PE_COFF_IMAGE,\r
487 ImageAddress,\r
488 ImageSize,\r
489 Tcg2Event\r
490 );\r
491 DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2 MeasurePeImage - %r\n", Status));\r
492 }\r
493\r
c1d93242
JY
494 if (Status == EFI_VOLUME_FULL) {\r
495 //\r
496 // Volume full here means the image is hashed and its result is extended to PCR.\r
d6b926e7 497 // But the event log can't be saved since log area is full.\r
c1d93242
JY
498 // Just return EFI_SUCCESS in order not to block the image load.\r
499 //\r
500 Status = EFI_SUCCESS;\r
501 }\r
502\r
503Finish:\r
a124cd4e
MX
504 if (EventPtr != NULL) {\r
505 FreePool (EventPtr);\r
506 }\r
c1d93242
JY
507\r
508 return Status;\r
509}\r
510\r
a124cd4e
MX
511/**\r
512 Get the measure boot protocols.\r
513\r
514 There are 2 measure boot, TCG2 protocol based and Cc measurement protocol based.\r
515\r
516 @param MeasureBootProtocols Pointer to the located measure boot protocol instances.\r
517\r
518 @retval EFI_SUCCESS Sucessfully locate the measure boot protocol instances (at least one instance).\r
519 @retval EFI_UNSUPPORTED Measure boot is not supported.\r
520**/\r
521EFI_STATUS\r
522EFIAPI\r
523GetMeasureBootProtocols (\r
524 MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols\r
525 )\r
526{\r
527 EFI_STATUS Status;\r
528 EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
529 EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;\r
530 EFI_TCG2_BOOT_SERVICE_CAPABILITY Tcg2ProtocolCapability;\r
531 EFI_CC_BOOT_SERVICE_CAPABILITY CcProtocolCapability;\r
532\r
533 CcProtocol = NULL;\r
534 Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **)&CcProtocol);\r
535 if (EFI_ERROR (Status)) {\r
536 //\r
537 // Cc Measurement protocol is not installed.\r
538 //\r
539 DEBUG ((DEBUG_VERBOSE, "CcMeasurementProtocol is not installed. - %r\n", Status));\r
540 } else {\r
541 ZeroMem (&CcProtocolCapability, sizeof (CcProtocolCapability));\r
542 CcProtocolCapability.Size = sizeof (CcProtocolCapability);\r
543 Status = CcProtocol->GetCapability (CcProtocol, &CcProtocolCapability);\r
544 if (EFI_ERROR (Status) || (CcProtocolCapability.CcType.Type == EFI_CC_TYPE_NONE)) {\r
545 DEBUG ((DEBUG_ERROR, " CcProtocol->GetCapability returns : %x, %r\n", CcProtocolCapability.CcType.Type, Status));\r
546 CcProtocol = NULL;\r
547 }\r
548 }\r
549\r
550 Tcg2Protocol = NULL;\r
551 Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);\r
552 if (EFI_ERROR (Status)) {\r
553 //\r
554 // Tcg2 protocol is not installed. So, TPM2 is not present.\r
555 //\r
556 DEBUG ((DEBUG_VERBOSE, "Tcg2Protocol is not installed. - %r\n", Status));\r
557 } else {\r
558 Tcg2ProtocolCapability.Size = (UINT8)sizeof (Tcg2ProtocolCapability);\r
559 Status = Tcg2Protocol->GetCapability (Tcg2Protocol, &Tcg2ProtocolCapability);\r
560 if (EFI_ERROR (Status) || (!Tcg2ProtocolCapability.TPMPresentFlag)) {\r
561 //\r
562 // TPM device doesn't work or activate.\r
563 //\r
564 DEBUG ((DEBUG_ERROR, "TPMPresentFlag=FALSE %r\n", Status));\r
565 Tcg2Protocol = NULL;\r
566 }\r
567 }\r
568\r
569 MeasureBootProtocols->Tcg2Protocol = Tcg2Protocol;\r
570 MeasureBootProtocols->CcProtocol = CcProtocol;\r
571\r
572 return (Tcg2Protocol == NULL && CcProtocol == NULL) ? EFI_UNSUPPORTED : EFI_SUCCESS;\r
573}\r
574\r
c1d93242 575/**\r
b3548d32
LG
576 The security handler is used to abstract platform-specific policy\r
577 from the DXE core response to an attempt to use a file that returns a\r
578 given status for the authentication check from the section extraction protocol.\r
c1d93242 579\r
b3548d32
LG
580 The possible responses in a given SAP implementation may include locking\r
581 flash upon failure to authenticate, attestation logging for all signed drivers,\r
582 and other exception operations. The File parameter allows for possible logging\r
c1d93242
JY
583 within the SAP of the driver.\r
584\r
b3548d32 585 If the file specified by File with an authentication status specified by\r
c1d93242
JY
586 AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.\r
587\r
b3548d32
LG
588 If the file specified by File with an authentication status specified by\r
589 AuthenticationStatus is not safe for the DXE Core to use under any circumstances,\r
c1d93242
JY
590 then EFI_ACCESS_DENIED is returned.\r
591\r
b3548d32
LG
592 If the file specified by File with an authentication status specified by\r
593 AuthenticationStatus is not safe for the DXE Core to use right now, but it\r
594 might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is\r
c1d93242
JY
595 returned.\r
596\r
1755932f
GJ
597 If check image specified by FileBuffer and File is NULL meanwhile, return EFI_ACCESS_DENIED.\r
598\r
c1d93242
JY
599 @param[in] AuthenticationStatus This is the authentication status returned\r
600 from the securitymeasurement services for the\r
601 input file.\r
602 @param[in] File This is a pointer to the device path of the file that is\r
603 being dispatched. This will optionally be used for logging.\r
604 @param[in] FileBuffer File buffer matches the input file device path.\r
605 @param[in] FileSize Size of File buffer matches the input file device path.\r
606 @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.\r
607\r
608 @retval EFI_SUCCESS The file specified by DevicePath and non-NULL\r
609 FileBuffer did authenticate, and the platform policy dictates\r
610 that the DXE Foundation may use the file.\r
611 @retval other error value\r
612**/\r
613EFI_STATUS\r
614EFIAPI\r
615DxeTpm2MeasureBootHandler (\r
c411b485
MK
616 IN UINT32 AuthenticationStatus,\r
617 IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,\r
618 IN VOID *FileBuffer,\r
619 IN UINTN FileSize,\r
620 IN BOOLEAN BootPolicy\r
c1d93242
JY
621 )\r
622{\r
a124cd4e 623 MEASURE_BOOT_PROTOCOLS MeasureBootProtocols;\r
c1d93242 624 EFI_STATUS Status;\r
c1d93242
JY
625 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
626 EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;\r
627 EFI_HANDLE Handle;\r
628 EFI_HANDLE TempHandle;\r
629 BOOLEAN ApplicationRequired;\r
630 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
631 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
632 EFI_PHYSICAL_ADDRESS FvAddress;\r
633 UINT32 Index;\r
4b026f0d 634\r
a124cd4e
MX
635 MeasureBootProtocols.Tcg2Protocol = NULL;\r
636 MeasureBootProtocols.CcProtocol = NULL;\r
637\r
638 Status = GetMeasureBootProtocols (&MeasureBootProtocols);\r
639\r
c1d93242
JY
640 if (EFI_ERROR (Status)) {\r
641 //\r
a124cd4e 642 // None of Measured boot protocols (Tcg2, Cc) is installed.\r
c1d93242
JY
643 // Don't do any measurement, and directly return EFI_SUCCESS.\r
644 //\r
a124cd4e 645 DEBUG ((DEBUG_INFO, "None of Tcg2Protocol/CcMeasurementProtocol is installed.\n"));\r
c1d93242
JY
646 return EFI_SUCCESS;\r
647 }\r
648\r
a124cd4e
MX
649 DEBUG ((\r
650 DEBUG_INFO,\r
651 "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n",\r
652 MeasureBootProtocols.Tcg2Protocol,\r
653 MeasureBootProtocols.CcProtocol\r
654 ));\r
c1d93242
JY
655\r
656 //\r
657 // Copy File Device Path\r
658 //\r
659 OrigDevicePathNode = DuplicateDevicePath (File);\r
b3548d32 660\r
c1d93242
JY
661 //\r
662 // 1. Check whether this device path support BlockIo protocol.\r
663 // Is so, this device path may be a GPT device path.\r
664 //\r
665 DevicePathNode = OrigDevicePathNode;\r
c411b485 666 Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle);\r
1abfa4ce 667 if (!EFI_ERROR (Status) && !mTcg2MeasureGptTableFlag) {\r
c1d93242 668 //\r
fc70522f 669 // Find the gpt partition on the given devicepath\r
c1d93242
JY
670 //\r
671 DevicePathNode = OrigDevicePathNode;\r
672 ASSERT (DevicePathNode != NULL);\r
673 while (!IsDevicePathEnd (DevicePathNode)) {\r
674 //\r
675 // Find the Gpt partition\r
676 //\r
c411b485
MK
677 if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&\r
678 (DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP))\r
679 {\r
c1d93242
JY
680 //\r
681 // Check whether it is a gpt partition or not\r
b3548d32 682 //\r
c411b485
MK
683 if ((((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) &&\r
684 (((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->SignatureType == SIGNATURE_TYPE_GUID))\r
685 {\r
c1d93242
JY
686 //\r
687 // Change the partition device path to its parent device path (disk) and get the handle.\r
688 //\r
689 DevicePathNode->Type = END_DEVICE_PATH_TYPE;\r
690 DevicePathNode->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
691 DevicePathNode = OrigDevicePathNode;\r
c411b485
MK
692 Status = gBS->LocateDevicePath (\r
693 &gEfiDiskIoProtocolGuid,\r
694 &DevicePathNode,\r
695 &Handle\r
696 );\r
c1d93242
JY
697 if (!EFI_ERROR (Status)) {\r
698 //\r
699 // Measure GPT disk.\r
700 //\r
a124cd4e
MX
701 Status = Tcg2MeasureGptTable (&MeasureBootProtocols, Handle);\r
702\r
c1d93242
JY
703 if (!EFI_ERROR (Status)) {\r
704 //\r
705 // GPT disk check done.\r
706 //\r
1abfa4ce 707 mTcg2MeasureGptTableFlag = TRUE;\r
c1d93242
JY
708 }\r
709 }\r
c411b485 710\r
c1d93242
JY
711 FreePool (OrigDevicePathNode);\r
712 OrigDevicePathNode = DuplicateDevicePath (File);\r
713 ASSERT (OrigDevicePathNode != NULL);\r
714 break;\r
715 }\r
716 }\r
c411b485
MK
717\r
718 DevicePathNode = NextDevicePathNode (DevicePathNode);\r
c1d93242
JY
719 }\r
720 }\r
b3548d32 721\r
c1d93242
JY
722 //\r
723 // 2. Measure PE image.\r
724 //\r
725 ApplicationRequired = FALSE;\r
726\r
727 //\r
728 // Check whether this device path support FVB protocol.\r
729 //\r
730 DevicePathNode = OrigDevicePathNode;\r
c411b485 731 Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &DevicePathNode, &Handle);\r
c1d93242
JY
732 if (!EFI_ERROR (Status)) {\r
733 //\r
734 // Don't check FV image, and directly return EFI_SUCCESS.\r
735 // It can be extended to the specific FV authentication according to the different requirement.\r
736 //\r
737 if (IsDevicePathEnd (DevicePathNode)) {\r
738 return EFI_SUCCESS;\r
739 }\r
c411b485 740\r
c1d93242
JY
741 //\r
742 // The PE image from unmeasured Firmware volume need be measured\r
d6b926e7 743 // The PE image from measured Firmware volume will be measured according to policy below.\r
c1d93242
JY
744 // If it is driver, do not measure\r
745 // If it is application, still measure.\r
746 //\r
747 ApplicationRequired = TRUE;\r
748\r
c411b485 749 if ((mTcg2CacheMeasuredHandle != Handle) && (mTcg2MeasuredHobData != NULL)) {\r
c1d93242
JY
750 //\r
751 // Search for Root FV of this PE image\r
752 //\r
753 TempHandle = Handle;\r
754 do {\r
c411b485 755 Status = gBS->HandleProtocol (\r
b3548d32 756 TempHandle,\r
c1d93242 757 &gEfiFirmwareVolumeBlockProtocolGuid,\r
c411b485 758 (VOID **)&FvbProtocol\r
c1d93242
JY
759 );\r
760 TempHandle = FvbProtocol->ParentHandle;\r
c411b485 761 } while (!EFI_ERROR (Status) && FvbProtocol->ParentHandle != NULL);\r
c1d93242
JY
762\r
763 //\r
764 // Search in measured FV Hob\r
765 //\r
c411b485
MK
766 Status = FvbProtocol->GetPhysicalAddress (FvbProtocol, &FvAddress);\r
767 if (EFI_ERROR (Status)) {\r
c1d93242
JY
768 return Status;\r
769 }\r
770\r
771 ApplicationRequired = FALSE;\r
772\r
1abfa4ce 773 for (Index = 0; Index < mTcg2MeasuredHobData->Num; Index++) {\r
c411b485 774 if (mTcg2MeasuredHobData->MeasuredFvBuf[Index].BlobBase == FvAddress) {\r
c1d93242
JY
775 //\r
776 // Cache measured FV for next measurement\r
777 //\r
1abfa4ce 778 mTcg2CacheMeasuredHandle = Handle;\r
c411b485 779 ApplicationRequired = TRUE;\r
c1d93242
JY
780 break;\r
781 }\r
782 }\r
783 }\r
784 }\r
785\r
786 //\r
787 // File is not found.\r
788 //\r
789 if (FileBuffer == NULL) {\r
790 Status = EFI_SECURITY_VIOLATION;\r
791 goto Finish;\r
792 }\r
793\r
1abfa4ce
JY
794 mTcg2ImageSize = FileSize;\r
795 mTcg2FileBuffer = FileBuffer;\r
c1d93242
JY
796\r
797 //\r
798 // Measure PE Image\r
799 //\r
800 DevicePathNode = OrigDevicePathNode;\r
801 ZeroMem (&ImageContext, sizeof (ImageContext));\r
c411b485
MK
802 ImageContext.Handle = (VOID *)FileBuffer;\r
803 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)DxeTpm2MeasureBootLibImageRead;\r
c1d93242
JY
804\r
805 //\r
806 // Get information about the image being loaded\r
807 //\r
808 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
809 if (EFI_ERROR (Status)) {\r
1755932f
GJ
810 //\r
811 // Check for invalid parameters.\r
812 //\r
813 if (File == NULL) {\r
814 Status = EFI_ACCESS_DENIED;\r
815 }\r
816\r
c1d93242
JY
817 //\r
818 // The information can't be got from the invalid PeImage\r
819 //\r
820 goto Finish;\r
821 }\r
b3548d32 822\r
c1d93242
JY
823 //\r
824 // Measure only application if Application flag is set\r
825 // Measure drivers and applications if Application flag is not set\r
826 //\r
b3548d32 827 if ((!ApplicationRequired) ||\r
c411b485
MK
828 (ApplicationRequired && (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)))\r
829 {\r
c1d93242
JY
830 //\r
831 // Print the image path to be measured.\r
b3548d32 832 //\r
c1d93242 833 DEBUG_CODE_BEGIN ();\r
c411b485
MK
834 CHAR16 *ToText;\r
835 ToText = ConvertDevicePathToText (\r
836 DevicePathNode,\r
837 FALSE,\r
838 TRUE\r
839 );\r
840 if (ToText != NULL) {\r
841 DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));\r
842 FreePool (ToText);\r
843 }\r
844\r
c1d93242
JY
845 DEBUG_CODE_END ();\r
846\r
847 //\r
848 // Measure PE image into TPM log.\r
849 //\r
1abfa4ce 850 Status = Tcg2MeasurePeImage (\r
a124cd4e 851 &MeasureBootProtocols,\r
c411b485 852 (EFI_PHYSICAL_ADDRESS)(UINTN)FileBuffer,\r
b3548d32 853 FileSize,\r
c411b485 854 (UINTN)ImageContext.ImageAddress,\r
b3548d32 855 ImageContext.ImageType,\r
c1d93242
JY
856 DevicePathNode\r
857 );\r
c1d93242
JY
858 }\r
859\r
860 //\r
861 // Done, free the allocated resource.\r
862 //\r
863Finish:\r
864 if (OrigDevicePathNode != NULL) {\r
865 FreePool (OrigDevicePathNode);\r
866 }\r
867\r
e905fbb0 868 DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - %r\n", Status));\r
c1d93242
JY
869\r
870 return Status;\r
871}\r
872\r
873/**\r
874 Register the security handler to provide TPM measure boot service.\r
875\r
876 @param ImageHandle ImageHandle of the loaded driver.\r
877 @param SystemTable Pointer to the EFI System Table.\r
878\r
879 @retval EFI_SUCCESS Register successfully.\r
880 @retval EFI_OUT_OF_RESOURCES No enough memory to register this handler.\r
881**/\r
882EFI_STATUS\r
883EFIAPI\r
884DxeTpm2MeasureBootLibConstructor (\r
885 IN EFI_HANDLE ImageHandle,\r
886 IN EFI_SYSTEM_TABLE *SystemTable\r
887 )\r
888{\r
889 EFI_HOB_GUID_TYPE *GuidHob;\r
890\r
891 GuidHob = NULL;\r
892\r
893 GuidHob = GetFirstGuidHob (&gMeasuredFvHobGuid);\r
894\r
895 if (GuidHob != NULL) {\r
1abfa4ce 896 mTcg2MeasuredHobData = GET_GUID_HOB_DATA (GuidHob);\r
c1d93242
JY
897 }\r
898\r
899 return RegisterSecurity2Handler (\r
c411b485
MK
900 DxeTpm2MeasureBootHandler,\r
901 EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
902 );\r
c1d93242 903}\r