]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SecurityPkg / Library / DxeTpmMeasureBootLib / DxeTpmMeasureBootLib.c
CommitLineData
0c18794e 1/** @file\r
b3548d32 2 The library instance provides security service of TPM measure boot.\r
0c18794e 3\r
dc204d5a
JY
4 Caution: This file requires additional review when modified.\r
5 This library will have external input - PE/COFF image and GPT partition.\r
6 This external input must be validated carefully to avoid security issue like\r
7 buffer overflow, integer overflow.\r
8\r
9 DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content\r
10 read is within the image buffer.\r
11\r
12 TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its\r
13 data structure within this image buffer before use.\r
14\r
15 TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse\r
16 partition data carefully.\r
17\r
b3548d32 18Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
289b714b 19SPDX-License-Identifier: BSD-2-Clause-Patent\r
0c18794e 20\r
21**/\r
22\r
23#include <PiDxe.h>\r
24\r
25#include <Protocol/TcgService.h>\r
0c18794e 26#include <Protocol/BlockIo.h>\r
27#include <Protocol/DiskIo.h>\r
2aadc920 28#include <Protocol/FirmwareVolumeBlock.h>\r
29\r
0758c830 30#include <Guid/MeasuredFvHob.h>\r
0c18794e 31\r
32#include <Library/BaseLib.h>\r
33#include <Library/DebugLib.h>\r
34#include <Library/BaseMemoryLib.h>\r
35#include <Library/MemoryAllocationLib.h>\r
36#include <Library/DevicePathLib.h>\r
37#include <Library/UefiBootServicesTableLib.h>\r
38#include <Library/BaseCryptLib.h>\r
39#include <Library/PeCoffLib.h>\r
40#include <Library/SecurityManagementLib.h>\r
2aadc920 41#include <Library/HobLib.h>\r
0c18794e 42\r
43//\r
44// Flag to check GPT partition. It only need be measured once.\r
45//\r
c411b485
MK
46BOOLEAN mMeasureGptTableFlag = FALSE;\r
47UINTN mMeasureGptCount = 0;\r
48VOID *mFileBuffer;\r
49UINTN mTpmImageSize;\r
2aadc920 50//\r
51// Measured FV handle cache\r
52//\r
c411b485
MK
53EFI_HANDLE mCacheMeasuredHandle = NULL;\r
54MEASURED_HOB_DATA *mMeasuredHobData = NULL;\r
0c18794e 55\r
56/**\r
57 Reads contents of a PE/COFF image in memory buffer.\r
58\r
dc204d5a
JY
59 Caution: This function may receive untrusted input.\r
60 PE/COFF image is external input, so this function will make sure the PE/COFF image content\r
61 read is within the image buffer.\r
62\r
0c18794e 63 @param FileHandle Pointer to the file handle to read the PE/COFF image.\r
64 @param FileOffset Offset into the PE/COFF image to begin the read operation.\r
b3548d32 65 @param ReadSize On input, the size in bytes of the requested read operation.\r
0c18794e 66 On output, the number of bytes actually read.\r
67 @param Buffer Output buffer that contains the data read from the PE/COFF image.\r
b3548d32
LG
68\r
69 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size\r
0c18794e 70**/\r
71EFI_STATUS\r
72EFIAPI\r
e0192326 73DxeTpmMeasureBootLibImageRead (\r
c411b485
MK
74 IN VOID *FileHandle,\r
75 IN UINTN FileOffset,\r
76 IN OUT UINTN *ReadSize,\r
77 OUT VOID *Buffer\r
0c18794e 78 )\r
79{\r
c411b485 80 UINTN EndPosition;\r
28186d45 81\r
c411b485 82 if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {\r
28186d45
ED
83 return EFI_INVALID_PARAMETER;\r
84 }\r
85\r
86 if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
87 return EFI_INVALID_PARAMETER;\r
88 }\r
89\r
90 EndPosition = FileOffset + *ReadSize;\r
a00bd8e0
ED
91 if (EndPosition > mTpmImageSize) {\r
92 *ReadSize = (UINT32)(mTpmImageSize - FileOffset);\r
28186d45
ED
93 }\r
94\r
a00bd8e0 95 if (FileOffset >= mTpmImageSize) {\r
28186d45
ED
96 *ReadSize = 0;\r
97 }\r
98\r
c411b485 99 CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);\r
28186d45 100\r
0c18794e 101 return EFI_SUCCESS;\r
102}\r
103\r
104/**\r
105 Measure GPT table data into TPM log.\r
106\r
dc204d5a
JY
107 Caution: This function may receive untrusted input.\r
108 The GPT partition table is external input, so this function should parse partition data carefully.\r
109\r
0c18794e 110 @param TcgProtocol Pointer to the located TCG protocol instance.\r
111 @param GptHandle Handle that GPT partition was installed.\r
112\r
113 @retval EFI_SUCCESS Successfully measure GPT table.\r
114 @retval EFI_UNSUPPORTED Not support GPT table on the given handle.\r
115 @retval EFI_DEVICE_ERROR Can't get GPT table because device error.\r
116 @retval EFI_OUT_OF_RESOURCES No enough resource to measure GPT table.\r
117 @retval other error value\r
118**/\r
119EFI_STATUS\r
120EFIAPI\r
121TcgMeasureGptTable (\r
c411b485
MK
122 IN EFI_TCG_PROTOCOL *TcgProtocol,\r
123 IN EFI_HANDLE GptHandle\r
0c18794e 124 )\r
125{\r
c411b485
MK
126 EFI_STATUS Status;\r
127 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
128 EFI_DISK_IO_PROTOCOL *DiskIo;\r
129 EFI_PARTITION_TABLE_HEADER *PrimaryHeader;\r
130 EFI_PARTITION_ENTRY *PartitionEntry;\r
131 UINT8 *EntryPtr;\r
132 UINTN NumberOfPartition;\r
133 UINT32 Index;\r
134 TCG_PCR_EVENT *TcgEvent;\r
135 EFI_GPT_DATA *GptData;\r
136 UINT32 EventSize;\r
137 UINT32 EventNumber;\r
138 EFI_PHYSICAL_ADDRESS EventLogLastEntry;\r
0c18794e 139\r
140 if (mMeasureGptCount > 0) {\r
141 return EFI_SUCCESS;\r
142 }\r
143\r
c411b485 144 Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
0c18794e 145 if (EFI_ERROR (Status)) {\r
146 return EFI_UNSUPPORTED;\r
147 }\r
c411b485
MK
148\r
149 Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);\r
0c18794e 150 if (EFI_ERROR (Status)) {\r
151 return EFI_UNSUPPORTED;\r
152 }\r
c411b485 153\r
0c18794e 154 //\r
155 // Read the EFI Partition Table Header\r
b3548d32 156 //\r
c411b485 157 PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *)AllocatePool (BlockIo->Media->BlockSize);\r
0c18794e 158 if (PrimaryHeader == NULL) {\r
159 return EFI_OUT_OF_RESOURCES;\r
b3548d32 160 }\r
c411b485 161\r
0c18794e 162 Status = DiskIo->ReadDisk (\r
163 DiskIo,\r
164 BlockIo->Media->MediaId,\r
165 1 * BlockIo->Media->BlockSize,\r
166 BlockIo->Media->BlockSize,\r
167 (UINT8 *)PrimaryHeader\r
168 );\r
169 if (EFI_ERROR (Status)) {\r
e905fbb0 170 DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n"));\r
0c18794e 171 FreePool (PrimaryHeader);\r
172 return EFI_DEVICE_ERROR;\r
b3548d32 173 }\r
c411b485 174\r
0c18794e 175 //\r
176 // Read the partition entry.\r
177 //\r
178 EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);\r
179 if (EntryPtr == NULL) {\r
180 FreePool (PrimaryHeader);\r
181 return EFI_OUT_OF_RESOURCES;\r
182 }\r
c411b485 183\r
0c18794e 184 Status = DiskIo->ReadDisk (\r
185 DiskIo,\r
186 BlockIo->Media->MediaId,\r
c411b485 187 MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
0c18794e 188 PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,\r
189 EntryPtr\r
190 );\r
191 if (EFI_ERROR (Status)) {\r
192 FreePool (PrimaryHeader);\r
193 FreePool (EntryPtr);\r
194 return EFI_DEVICE_ERROR;\r
195 }\r
b3548d32 196\r
0c18794e 197 //\r
198 // Count the valid partition\r
199 //\r
200 PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr;\r
201 NumberOfPartition = 0;\r
202 for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
965268ea 203 if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {\r
b3548d32 204 NumberOfPartition++;\r
0c18794e 205 }\r
c411b485 206\r
2ea3b920 207 PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
0c18794e 208 }\r
209\r
210 //\r
2ea3b920 211 // Prepare Data for Measurement\r
b3548d32
LG
212 //\r
213 EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)\r
c411b485
MK
214 + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
215 TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR));\r
0c18794e 216 if (TcgEvent == NULL) {\r
217 FreePool (PrimaryHeader);\r
218 FreePool (EntryPtr);\r
219 return EFI_OUT_OF_RESOURCES;\r
220 }\r
221\r
c411b485
MK
222 TcgEvent->PCRIndex = 5;\r
223 TcgEvent->EventType = EV_EFI_GPT_EVENT;\r
224 TcgEvent->EventSize = EventSize;\r
225 GptData = (EFI_GPT_DATA *)TcgEvent->Event;\r
0c18794e 226\r
227 //\r
228 // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition\r
b3548d32 229 //\r
c411b485 230 CopyMem ((UINT8 *)GptData, (UINT8 *)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));\r
0c18794e 231 GptData->NumberOfPartitions = NumberOfPartition;\r
232 //\r
233 // Copy the valid partition entry\r
234 //\r
c411b485 235 PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr;\r
0c18794e 236 NumberOfPartition = 0;\r
237 for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
965268ea 238 if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {\r
0c18794e 239 CopyMem (\r
2ea3b920 240 (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry,\r
0c18794e 241 (UINT8 *)PartitionEntry,\r
2ea3b920 242 PrimaryHeader->SizeOfPartitionEntry\r
0c18794e 243 );\r
244 NumberOfPartition++;\r
245 }\r
c411b485
MK
246\r
247 PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
0c18794e 248 }\r
249\r
250 //\r
251 // Measure the GPT data\r
252 //\r
253 EventNumber = 1;\r
c411b485
MK
254 Status = TcgProtocol->HashLogExtendEvent (\r
255 TcgProtocol,\r
256 (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,\r
257 (UINT64)TcgEvent->EventSize,\r
258 TPM_ALG_SHA,\r
259 TcgEvent,\r
260 &EventNumber,\r
261 &EventLogLastEntry\r
262 );\r
0c18794e 263 if (!EFI_ERROR (Status)) {\r
264 mMeasureGptCount++;\r
265 }\r
266\r
267 FreePool (PrimaryHeader);\r
268 FreePool (EntryPtr);\r
269 FreePool (TcgEvent);\r
270\r
271 return Status;\r
272}\r
273\r
274/**\r
275 Measure PE image into TPM log based on the authenticode image hashing in\r
276 PE/COFF Specification 8.0 Appendix A.\r
277\r
dc204d5a
JY
278 Caution: This function may receive untrusted input.\r
279 PE/COFF image is external input, so this function will validate its data structure\r
280 within this image buffer before use.\r
281\r
b3548d32 282 Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in\r
e39d0569
LG
283 its caller function DxeTpmMeasureBootHandler().\r
284\r
0c18794e 285 @param[in] TcgProtocol Pointer to the located TCG protocol instance.\r
286 @param[in] ImageAddress Start address of image buffer.\r
287 @param[in] ImageSize Image size\r
288 @param[in] LinkTimeBase Address that the image is loaded into memory.\r
289 @param[in] ImageType Image subsystem type.\r
290 @param[in] FilePath File path is corresponding to the input image.\r
291\r
292 @retval EFI_SUCCESS Successfully measure image.\r
293 @retval EFI_OUT_OF_RESOURCES No enough resource to measure image.\r
b3548d32 294 @retval EFI_UNSUPPORTED ImageType is unsupported or PE image is mal-format.\r
0c18794e 295 @retval other error value\r
551d8081 296\r
0c18794e 297**/\r
298EFI_STATUS\r
299EFIAPI\r
300TcgMeasurePeImage (\r
301 IN EFI_TCG_PROTOCOL *TcgProtocol,\r
302 IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
303 IN UINTN ImageSize,\r
304 IN UINTN LinkTimeBase,\r
305 IN UINT16 ImageType,\r
306 IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
307 )\r
308{\r
551d8081 309 EFI_STATUS Status;\r
310 TCG_PCR_EVENT *TcgEvent;\r
311 EFI_IMAGE_LOAD_EVENT *ImageLoad;\r
312 UINT32 FilePathSize;\r
313 VOID *Sha1Ctx;\r
314 UINTN CtxSize;\r
315 EFI_IMAGE_DOS_HEADER *DosHdr;\r
316 UINT32 PeCoffHeaderOffset;\r
317 EFI_IMAGE_SECTION_HEADER *Section;\r
318 UINT8 *HashBase;\r
319 UINTN HashSize;\r
320 UINTN SumOfBytesHashed;\r
321 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
322 UINTN Index;\r
323 UINTN Pos;\r
551d8081 324 UINT32 EventSize;\r
325 UINT32 EventNumber;\r
326 EFI_PHYSICAL_ADDRESS EventLogLastEntry;\r
0c18794e 327 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
551d8081 328 UINT32 NumberOfRvaAndSizes;\r
329 BOOLEAN HashStatus;\r
330 UINT32 CertSize;\r
0c18794e 331\r
551d8081 332 Status = EFI_UNSUPPORTED;\r
0c18794e 333 ImageLoad = NULL;\r
334 SectionHeader = NULL;\r
335 Sha1Ctx = NULL;\r
c411b485 336 FilePathSize = (UINT32)GetDevicePathSize (FilePath);\r
0c18794e 337\r
338 //\r
339 // Determine destination PCR by BootPolicy\r
340 //\r
341 EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;\r
c411b485 342 TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));\r
0c18794e 343 if (TcgEvent == NULL) {\r
344 return EFI_OUT_OF_RESOURCES;\r
345 }\r
346\r
347 TcgEvent->EventSize = EventSize;\r
c411b485 348 ImageLoad = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event;\r
0c18794e 349\r
350 switch (ImageType) {\r
351 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
352 TcgEvent->EventType = EV_EFI_BOOT_SERVICES_APPLICATION;\r
353 TcgEvent->PCRIndex = 4;\r
354 break;\r
355 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
356 TcgEvent->EventType = EV_EFI_BOOT_SERVICES_DRIVER;\r
357 TcgEvent->PCRIndex = 2;\r
358 break;\r
359 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
360 TcgEvent->EventType = EV_EFI_RUNTIME_SERVICES_DRIVER;\r
361 TcgEvent->PCRIndex = 2;\r
362 break;\r
363 default:\r
364 DEBUG ((\r
e905fbb0 365 DEBUG_ERROR,\r
0c18794e 366 "TcgMeasurePeImage: Unknown subsystem type %d",\r
367 ImageType\r
368 ));\r
0c18794e 369 goto Finish;\r
370 }\r
371\r
372 ImageLoad->ImageLocationInMemory = ImageAddress;\r
373 ImageLoad->ImageLengthInMemory = ImageSize;\r
374 ImageLoad->ImageLinkTimeAddress = LinkTimeBase;\r
375 ImageLoad->LengthOfDevicePath = FilePathSize;\r
7a1f792d
ED
376 if ((FilePath != NULL) && (FilePathSize != 0)) {\r
377 CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);\r
378 }\r
0c18794e 379\r
380 //\r
381 // Check PE/COFF image\r
382 //\r
c411b485 383 DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;\r
0c18794e 384 PeCoffHeaderOffset = 0;\r
385 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
386 PeCoffHeaderOffset = DosHdr->e_lfanew;\r
387 }\r
551d8081 388\r
c411b485 389 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);\r
551d8081 390 if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
0c18794e 391 goto Finish;\r
392 }\r
393\r
394 //\r
395 // PE/COFF Image Measurement\r
396 //\r
397 // NOTE: The following codes/steps are based upon the authenticode image hashing in\r
398 // PE/COFF Specification 8.0 Appendix A.\r
399 //\r
400 //\r
401\r
402 // 1. Load the image header into memory.\r
403\r
404 // 2. Initialize a SHA hash context.\r
405 CtxSize = Sha1GetContextSize ();\r
406 Sha1Ctx = AllocatePool (CtxSize);\r
407 if (Sha1Ctx == NULL) {\r
408 Status = EFI_OUT_OF_RESOURCES;\r
409 goto Finish;\r
410 }\r
411\r
551d8081 412 HashStatus = Sha1Init (Sha1Ctx);\r
413 if (!HashStatus) {\r
414 goto Finish;\r
415 }\r
0c18794e 416\r
417 //\r
418 // Measuring PE/COFF Image Header;\r
419 // But CheckSum field and SECURITY data directory (certificate) are excluded\r
420 //\r
b3548d32 421\r
0c18794e 422 //\r
423 // 3. Calculate the distance from the base of the image header to the image checksum address.\r
424 // 4. Hash the image header from its base to beginning of the image checksum.\r
425 //\r
c411b485 426 HashBase = (UINT8 *)(UINTN)ImageAddress;\r
f199664c 427 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
0c18794e 428 //\r
429 // Use PE32 offset\r
430 //\r
551d8081 431 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
c411b485 432 HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;\r
0c18794e 433 } else {\r
434 //\r
435 // Use PE32+ offset\r
436 //\r
551d8081 437 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
c411b485 438 HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;\r
0c18794e 439 }\r
440\r
551d8081 441 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
442 if (!HashStatus) {\r
443 goto Finish;\r
b3548d32 444 }\r
0c18794e 445\r
446 //\r
447 // 5. Skip over the image checksum (it occupies a single ULONG).\r
0c18794e 448 //\r
551d8081 449 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
0c18794e 450 //\r
551d8081 451 // 6. Since there is no Cert Directory in optional header, hash everything\r
452 // from the end of the checksum to the end of image header.\r
0c18794e 453 //\r
f199664c 454 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
551d8081 455 //\r
456 // Use PE32 offset.\r
457 //\r
c411b485
MK
458 HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
459 HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
551d8081 460 } else {\r
461 //\r
462 // Use PE32+ offset.\r
463 //\r
c411b485
MK
464 HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
465 HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
551d8081 466 }\r
467\r
468 if (HashSize != 0) {\r
c411b485 469 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
551d8081 470 if (!HashStatus) {\r
471 goto Finish;\r
472 }\r
b3548d32 473 }\r
0c18794e 474 } else {\r
475 //\r
551d8081 476 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
477 //\r
f199664c 478 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
551d8081 479 //\r
480 // Use PE32 offset\r
481 //\r
c411b485
MK
482 HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
483 HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;\r
551d8081 484 } else {\r
485 //\r
486 // Use PE32+ offset\r
b3548d32 487 //\r
c411b485
MK
488 HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
489 HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;\r
551d8081 490 }\r
0c18794e 491\r
551d8081 492 if (HashSize != 0) {\r
c411b485 493 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
551d8081 494 if (!HashStatus) {\r
495 goto Finish;\r
496 }\r
497 }\r
0c18794e 498\r
0c18794e 499 //\r
551d8081 500 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
501 // 9. Hash everything from the end of the Cert Directory to the end of image header.\r
0c18794e 502 //\r
f199664c 503 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
551d8081 504 //\r
505 // Use PE32 offset\r
506 //\r
c411b485
MK
507 HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
508 HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
551d8081 509 } else {\r
510 //\r
511 // Use PE32+ offset\r
512 //\r
c411b485
MK
513 HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
514 HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
551d8081 515 }\r
b3548d32 516\r
551d8081 517 if (HashSize != 0) {\r
c411b485 518 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
551d8081 519 if (!HashStatus) {\r
520 goto Finish;\r
521 }\r
522 }\r
0c18794e 523 }\r
0c18794e 524\r
525 //\r
526 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header\r
527 //\r
f199664c 528 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
0c18794e 529 //\r
530 // Use PE32 offset\r
531 //\r
532 SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders;\r
533 } else {\r
534 //\r
535 // Use PE32+ offset\r
536 //\r
537 SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
538 }\r
539\r
540 //\r
541 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
542 // structures in the image. The 'NumberOfSections' field of the image\r
543 // header indicates how big the table should be. Do not include any\r
544 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
545 //\r
c411b485 546 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);\r
0c18794e 547 if (SectionHeader == NULL) {\r
548 Status = EFI_OUT_OF_RESOURCES;\r
549 goto Finish;\r
550 }\r
551\r
552 //\r
553 // 12. Using the 'PointerToRawData' in the referenced section headers as\r
554 // a key, arrange the elements in the table in ascending order. In other\r
555 // words, sort the section headers according to the disk-file offset of\r
556 // the section.\r
557 //\r
c411b485
MK
558 Section = (EFI_IMAGE_SECTION_HEADER *)(\r
559 (UINT8 *)(UINTN)ImageAddress +\r
560 PeCoffHeaderOffset +\r
561 sizeof (UINT32) +\r
562 sizeof (EFI_IMAGE_FILE_HEADER) +\r
563 Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
564 );\r
0c18794e 565 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
566 Pos = Index;\r
567 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
c411b485 568 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
0c18794e 569 Pos--;\r
570 }\r
c411b485
MK
571\r
572 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
0c18794e 573 Section += 1;\r
574 }\r
575\r
576 //\r
577 // 13. Walk through the sorted table, bring the corresponding section\r
578 // into memory, and hash the entire section (using the 'SizeOfRawData'\r
579 // field in the section header to determine the amount of data to hash).\r
580 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
581 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.\r
582 //\r
583 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
c411b485 584 Section = (EFI_IMAGE_SECTION_HEADER *)&SectionHeader[Index];\r
0c18794e 585 if (Section->SizeOfRawData == 0) {\r
586 continue;\r
587 }\r
c411b485
MK
588\r
589 HashBase = (UINT8 *)(UINTN)ImageAddress + Section->PointerToRawData;\r
590 HashSize = (UINTN)Section->SizeOfRawData;\r
0c18794e 591\r
551d8081 592 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
593 if (!HashStatus) {\r
594 goto Finish;\r
595 }\r
0c18794e 596\r
597 SumOfBytesHashed += HashSize;\r
598 }\r
599\r
600 //\r
601 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
602 // data in the file that needs to be added to the hash. This data begins\r
603 // at file offset SUM_OF_BYTES_HASHED and its length is:\r
604 // FileSize - (CertDirectory->Size)\r
605 //\r
606 if (ImageSize > SumOfBytesHashed) {\r
c411b485 607 HashBase = (UINT8 *)(UINTN)ImageAddress + SumOfBytesHashed;\r
551d8081 608\r
609 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
610 CertSize = 0;\r
0c18794e 611 } else {\r
f199664c 612 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
551d8081 613 //\r
614 // Use PE32 offset.\r
615 //\r
616 CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
617 } else {\r
618 //\r
619 // Use PE32+ offset.\r
620 //\r
621 CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
28186d45 622 }\r
0c18794e 623 }\r
624\r
551d8081 625 if (ImageSize > CertSize + SumOfBytesHashed) {\r
c411b485 626 HashSize = (UINTN)(ImageSize - CertSize - SumOfBytesHashed);\r
551d8081 627\r
628 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
629 if (!HashStatus) {\r
630 goto Finish;\r
631 }\r
632 } else if (ImageSize < CertSize + SumOfBytesHashed) {\r
633 goto Finish;\r
634 }\r
0c18794e 635 }\r
636\r
637 //\r
638 // 17. Finalize the SHA hash.\r
639 //\r
c411b485 640 HashStatus = Sha1Final (Sha1Ctx, (UINT8 *)&TcgEvent->Digest);\r
551d8081 641 if (!HashStatus) {\r
642 goto Finish;\r
643 }\r
0c18794e 644\r
645 //\r
646 // Log the PE data\r
647 //\r
648 EventNumber = 1;\r
c411b485
MK
649 Status = TcgProtocol->HashLogExtendEvent (\r
650 TcgProtocol,\r
651 (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)NULL,\r
652 0,\r
653 TPM_ALG_SHA,\r
654 TcgEvent,\r
655 &EventNumber,\r
656 &EventLogLastEntry\r
657 );\r
772b6011 658 if (Status == EFI_OUT_OF_RESOURCES) {\r
659 //\r
660 // Out of resource here means the image is hashed and its result is extended to PCR.\r
d6b926e7 661 // But the event log can't be saved since log area is full.\r
772b6011 662 // Just return EFI_SUCCESS in order not to block the image load.\r
663 //\r
664 Status = EFI_SUCCESS;\r
665 }\r
0c18794e 666\r
667Finish:\r
668 FreePool (TcgEvent);\r
669\r
670 if (SectionHeader != NULL) {\r
671 FreePool (SectionHeader);\r
672 }\r
673\r
674 if (Sha1Ctx != NULL ) {\r
675 FreePool (Sha1Ctx);\r
676 }\r
c411b485 677\r
0c18794e 678 return Status;\r
679}\r
680\r
681/**\r
b3548d32
LG
682 The security handler is used to abstract platform-specific policy\r
683 from the DXE core response to an attempt to use a file that returns a\r
684 given status for the authentication check from the section extraction protocol.\r
0c18794e 685\r
b3548d32
LG
686 The possible responses in a given SAP implementation may include locking\r
687 flash upon failure to authenticate, attestation logging for all signed drivers,\r
688 and other exception operations. The File parameter allows for possible logging\r
0c18794e 689 within the SAP of the driver.\r
690\r
b3548d32 691 If the file specified by File with an authentication status specified by\r
0c18794e 692 AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.\r
693\r
b3548d32
LG
694 If the file specified by File with an authentication status specified by\r
695 AuthenticationStatus is not safe for the DXE Core to use under any circumstances,\r
0c18794e 696 then EFI_ACCESS_DENIED is returned.\r
697\r
b3548d32
LG
698 If the file specified by File with an authentication status specified by\r
699 AuthenticationStatus is not safe for the DXE Core to use right now, but it\r
700 might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is\r
0c18794e 701 returned.\r
702\r
1755932f
GJ
703 If check image specified by FileBuffer and File is NULL meanwhile, return EFI_ACCESS_DENIED.\r
704\r
5db28a67 705 @param[in] AuthenticationStatus This is the authentication status returned\r
0c18794e 706 from the securitymeasurement services for the\r
707 input file.\r
708 @param[in] File This is a pointer to the device path of the file that is\r
709 being dispatched. This will optionally be used for logging.\r
710 @param[in] FileBuffer File buffer matches the input file device path.\r
711 @param[in] FileSize Size of File buffer matches the input file device path.\r
5db28a67 712 @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.\r
0c18794e 713\r
5db28a67
LG
714 @retval EFI_SUCCESS The file specified by DevicePath and non-NULL\r
715 FileBuffer did authenticate, and the platform policy dictates\r
716 that the DXE Foundation may use the file.\r
717 @retval other error value\r
0c18794e 718**/\r
719EFI_STATUS\r
720EFIAPI\r
721DxeTpmMeasureBootHandler (\r
c411b485
MK
722 IN UINT32 AuthenticationStatus,\r
723 IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,\r
724 IN VOID *FileBuffer,\r
725 IN UINTN FileSize,\r
726 IN BOOLEAN BootPolicy\r
0c18794e 727 )\r
728{\r
2aadc920 729 EFI_TCG_PROTOCOL *TcgProtocol;\r
730 EFI_STATUS Status;\r
731 TCG_EFI_BOOT_SERVICE_CAPABILITY ProtocolCapability;\r
732 UINT32 TCGFeatureFlags;\r
733 EFI_PHYSICAL_ADDRESS EventLogLocation;\r
734 EFI_PHYSICAL_ADDRESS EventLogLastEntry;\r
735 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
736 EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;\r
737 EFI_HANDLE Handle;\r
738 EFI_HANDLE TempHandle;\r
739 BOOLEAN ApplicationRequired;\r
740 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
741 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
742 EFI_PHYSICAL_ADDRESS FvAddress;\r
2aadc920 743 UINT32 Index;\r
0c18794e 744\r
c411b485 745 Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);\r
0c18794e 746 if (EFI_ERROR (Status)) {\r
747 //\r
748 // TCG protocol is not installed. So, TPM is not present.\r
749 // Don't do any measurement, and directly return EFI_SUCCESS.\r
750 //\r
751 return EFI_SUCCESS;\r
752 }\r
753\r
c411b485
MK
754 ProtocolCapability.Size = (UINT8)sizeof (ProtocolCapability);\r
755 Status = TcgProtocol->StatusCheck (\r
756 TcgProtocol,\r
757 &ProtocolCapability,\r
758 &TCGFeatureFlags,\r
759 &EventLogLocation,\r
760 &EventLogLastEntry\r
761 );\r
6f785cfc 762 if (EFI_ERROR (Status) || ProtocolCapability.TPMDeactivatedFlag || (!ProtocolCapability.TPMPresentFlag)) {\r
0c18794e 763 //\r
764 // TPM device doesn't work or activate.\r
765 //\r
766 return EFI_SUCCESS;\r
767 }\r
768\r
769 //\r
770 // Copy File Device Path\r
771 //\r
772 OrigDevicePathNode = DuplicateDevicePath (File);\r
b3548d32 773\r
0c18794e 774 //\r
775 // 1. Check whether this device path support BlockIo protocol.\r
776 // Is so, this device path may be a GPT device path.\r
777 //\r
778 DevicePathNode = OrigDevicePathNode;\r
c411b485 779 Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle);\r
0c18794e 780 if (!EFI_ERROR (Status) && !mMeasureGptTableFlag) {\r
781 //\r
fc70522f 782 // Find the gpt partition on the given devicepath\r
0c18794e 783 //\r
784 DevicePathNode = OrigDevicePathNode;\r
4dbb98ab 785 ASSERT (DevicePathNode != NULL);\r
0c18794e 786 while (!IsDevicePathEnd (DevicePathNode)) {\r
787 //\r
788 // Find the Gpt partition\r
789 //\r
c411b485
MK
790 if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&\r
791 (DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP))\r
792 {\r
0c18794e 793 //\r
794 // Check whether it is a gpt partition or not\r
b3548d32 795 //\r
c411b485
MK
796 if ((((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) &&\r
797 (((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->SignatureType == SIGNATURE_TYPE_GUID))\r
798 {\r
0c18794e 799 //\r
800 // Change the partition device path to its parent device path (disk) and get the handle.\r
801 //\r
802 DevicePathNode->Type = END_DEVICE_PATH_TYPE;\r
803 DevicePathNode->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
804 DevicePathNode = OrigDevicePathNode;\r
c411b485
MK
805 Status = gBS->LocateDevicePath (\r
806 &gEfiDiskIoProtocolGuid,\r
807 &DevicePathNode,\r
808 &Handle\r
809 );\r
0c18794e 810 if (!EFI_ERROR (Status)) {\r
811 //\r
812 // Measure GPT disk.\r
813 //\r
814 Status = TcgMeasureGptTable (TcgProtocol, Handle);\r
815 if (!EFI_ERROR (Status)) {\r
816 //\r
817 // GPT disk check done.\r
818 //\r
819 mMeasureGptTableFlag = TRUE;\r
820 }\r
821 }\r
c411b485 822\r
0c18794e 823 FreePool (OrigDevicePathNode);\r
824 OrigDevicePathNode = DuplicateDevicePath (File);\r
825 ASSERT (OrigDevicePathNode != NULL);\r
826 break;\r
827 }\r
828 }\r
c411b485
MK
829\r
830 DevicePathNode = NextDevicePathNode (DevicePathNode);\r
0c18794e 831 }\r
832 }\r
b3548d32 833\r
0c18794e 834 //\r
835 // 2. Measure PE image.\r
836 //\r
837 ApplicationRequired = FALSE;\r
838\r
839 //\r
2aadc920 840 // Check whether this device path support FVB protocol.\r
0c18794e 841 //\r
842 DevicePathNode = OrigDevicePathNode;\r
c411b485 843 Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &DevicePathNode, &Handle);\r
0c18794e 844 if (!EFI_ERROR (Status)) {\r
845 //\r
846 // Don't check FV image, and directly return EFI_SUCCESS.\r
847 // It can be extended to the specific FV authentication according to the different requirement.\r
848 //\r
849 if (IsDevicePathEnd (DevicePathNode)) {\r
850 return EFI_SUCCESS;\r
851 }\r
c411b485 852\r
0c18794e 853 //\r
0758c830 854 // The PE image from unmeasured Firmware volume need be measured\r
d6b926e7 855 // The PE image from measured Firmware volume will be measured according to policy below.\r
0758c830 856 // If it is driver, do not measure\r
2aadc920 857 // If it is application, still measure.\r
0c18794e 858 //\r
859 ApplicationRequired = TRUE;\r
2aadc920 860\r
c411b485 861 if ((mCacheMeasuredHandle != Handle) && (mMeasuredHobData != NULL)) {\r
2aadc920 862 //\r
863 // Search for Root FV of this PE image\r
864 //\r
865 TempHandle = Handle;\r
866 do {\r
c411b485 867 Status = gBS->HandleProtocol (\r
b3548d32 868 TempHandle,\r
2aadc920 869 &gEfiFirmwareVolumeBlockProtocolGuid,\r
c411b485 870 (VOID **)&FvbProtocol\r
2aadc920 871 );\r
872 TempHandle = FvbProtocol->ParentHandle;\r
c411b485 873 } while (!EFI_ERROR (Status) && FvbProtocol->ParentHandle != NULL);\r
2aadc920 874\r
875 //\r
876 // Search in measured FV Hob\r
877 //\r
c411b485
MK
878 Status = FvbProtocol->GetPhysicalAddress (FvbProtocol, &FvAddress);\r
879 if (EFI_ERROR (Status)) {\r
2aadc920 880 return Status;\r
881 }\r
882\r
2aadc920 883 ApplicationRequired = FALSE;\r
884\r
0758c830 885 for (Index = 0; Index < mMeasuredHobData->Num; Index++) {\r
c411b485 886 if (mMeasuredHobData->MeasuredFvBuf[Index].BlobBase == FvAddress) {\r
2aadc920 887 //\r
888 // Cache measured FV for next measurement\r
889 //\r
890 mCacheMeasuredHandle = Handle;\r
891 ApplicationRequired = TRUE;\r
892 break;\r
893 }\r
894 }\r
895 }\r
0c18794e 896 }\r
2aadc920 897\r
0c18794e 898 //\r
899 // File is not found.\r
900 //\r
901 if (FileBuffer == NULL) {\r
902 Status = EFI_SECURITY_VIOLATION;\r
903 goto Finish;\r
904 }\r
905\r
c411b485
MK
906 mTpmImageSize = FileSize;\r
907 mFileBuffer = FileBuffer;\r
28186d45 908\r
0c18794e 909 //\r
910 // Measure PE Image\r
911 //\r
912 DevicePathNode = OrigDevicePathNode;\r
913 ZeroMem (&ImageContext, sizeof (ImageContext));\r
c411b485
MK
914 ImageContext.Handle = (VOID *)FileBuffer;\r
915 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)DxeTpmMeasureBootLibImageRead;\r
0c18794e 916\r
917 //\r
918 // Get information about the image being loaded\r
919 //\r
920 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
921 if (EFI_ERROR (Status)) {\r
1755932f
GJ
922 //\r
923 // Check for invalid parameters.\r
924 //\r
925 if (File == NULL) {\r
926 return EFI_ACCESS_DENIED;\r
927 }\r
928\r
0c18794e 929 //\r
930 // The information can't be got from the invalid PeImage\r
931 //\r
932 goto Finish;\r
933 }\r
b3548d32 934\r
0c18794e 935 //\r
936 // Measure only application if Application flag is set\r
937 // Measure drivers and applications if Application flag is not set\r
938 //\r
b3548d32 939 if ((!ApplicationRequired) ||\r
c411b485
MK
940 (ApplicationRequired && (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)))\r
941 {\r
0c18794e 942 //\r
943 // Print the image path to be measured.\r
b3548d32 944 //\r
0c18794e 945 DEBUG_CODE_BEGIN ();\r
c411b485
MK
946 CHAR16 *ToText;\r
947 ToText = ConvertDevicePathToText (\r
948 DevicePathNode,\r
949 FALSE,\r
950 TRUE\r
951 );\r
952 if (ToText != NULL) {\r
953 DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));\r
954 FreePool (ToText);\r
955 }\r
956\r
0c18794e 957 DEBUG_CODE_END ();\r
958\r
959 //\r
960 // Measure PE image into TPM log.\r
961 //\r
962 Status = TcgMeasurePeImage (\r
963 TcgProtocol,\r
c411b485 964 (EFI_PHYSICAL_ADDRESS)(UINTN)FileBuffer,\r
b3548d32 965 FileSize,\r
c411b485 966 (UINTN)ImageContext.ImageAddress,\r
b3548d32 967 ImageContext.ImageType,\r
0c18794e 968 DevicePathNode\r
969 );\r
970 }\r
971\r
972 //\r
973 // Done, free the allocated resource.\r
974 //\r
975Finish:\r
5db28a67
LG
976 if (OrigDevicePathNode != NULL) {\r
977 FreePool (OrigDevicePathNode);\r
978 }\r
0c18794e 979\r
980 return Status;\r
981}\r
982\r
983/**\r
984 Register the security handler to provide TPM measure boot service.\r
985\r
986 @param ImageHandle ImageHandle of the loaded driver.\r
987 @param SystemTable Pointer to the EFI System Table.\r
988\r
989 @retval EFI_SUCCESS Register successfully.\r
990 @retval EFI_OUT_OF_RESOURCES No enough memory to register this handler.\r
991**/\r
992EFI_STATUS\r
993EFIAPI\r
994DxeTpmMeasureBootLibConstructor (\r
995 IN EFI_HANDLE ImageHandle,\r
996 IN EFI_SYSTEM_TABLE *SystemTable\r
997 )\r
998{\r
2aadc920 999 EFI_HOB_GUID_TYPE *GuidHob;\r
1000\r
1001 GuidHob = NULL;\r
1002\r
0758c830 1003 GuidHob = GetFirstGuidHob (&gMeasuredFvHobGuid);\r
2aadc920 1004\r
1005 if (GuidHob != NULL) {\r
0758c830 1006 mMeasuredHobData = GET_GUID_HOB_DATA (GuidHob);\r
2aadc920 1007 }\r
1008\r
5db28a67 1009 return RegisterSecurity2Handler (\r
c411b485
MK
1010 DxeTpmMeasureBootHandler,\r
1011 EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
1012 );\r
0c18794e 1013}\r