2 The library instance provides security service of TPM measure boot.
4 Caution: This file requires additional review when modified.
5 This library will have external input - PE/COFF image and GPT partition.
6 This external input must be validated carefully to avoid security issue like
7 buffer overflow, integer overflow.
9 DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content
10 read is within the image buffer.
12 TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its
13 data structure within this image buffer before use.
15 TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse
16 partition data carefully.
18 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
19 This program and the accompanying materials
20 are licensed and made available under the terms and conditions of the BSD License
21 which accompanies this distribution. The full text of the license may be found at
22 http://opensource.org/licenses/bsd-license.php
24 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
25 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
31 #include <Protocol/TcgService.h>
32 #include <Protocol/BlockIo.h>
33 #include <Protocol/DiskIo.h>
34 #include <Protocol/DevicePathToText.h>
35 #include <Protocol/FirmwareVolumeBlock.h>
37 #include <Guid/MeasuredFvHob.h>
39 #include <Library/BaseLib.h>
40 #include <Library/DebugLib.h>
41 #include <Library/BaseMemoryLib.h>
42 #include <Library/MemoryAllocationLib.h>
43 #include <Library/DevicePathLib.h>
44 #include <Library/UefiBootServicesTableLib.h>
45 #include <Library/BaseCryptLib.h>
46 #include <Library/PeCoffLib.h>
47 #include <Library/SecurityManagementLib.h>
48 #include <Library/HobLib.h>
51 // Flag to check GPT partition. It only need be measured once.
53 BOOLEAN mMeasureGptTableFlag
= FALSE
;
54 EFI_GUID mZeroGuid
= {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
55 UINTN mMeasureGptCount
= 0;
59 // Measured FV handle cache
61 EFI_HANDLE mCacheMeasuredHandle
= NULL
;
62 MEASURED_HOB_DATA
*mMeasuredHobData
= NULL
;
65 Reads contents of a PE/COFF image in memory buffer.
67 Caution: This function may receive untrusted input.
68 PE/COFF image is external input, so this function will make sure the PE/COFF image content
69 read is within the image buffer.
71 @param FileHandle Pointer to the file handle to read the PE/COFF image.
72 @param FileOffset Offset into the PE/COFF image to begin the read operation.
73 @param ReadSize On input, the size in bytes of the requested read operation.
74 On output, the number of bytes actually read.
75 @param Buffer Output buffer that contains the data read from the PE/COFF image.
77 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
81 DxeTpmMeasureBootLibImageRead (
84 IN OUT UINTN
*ReadSize
,
90 if (FileHandle
== NULL
|| ReadSize
== NULL
|| Buffer
== NULL
) {
91 return EFI_INVALID_PARAMETER
;
94 if (MAX_ADDRESS
- FileOffset
< *ReadSize
) {
95 return EFI_INVALID_PARAMETER
;
98 EndPosition
= FileOffset
+ *ReadSize
;
99 if (EndPosition
> mImageSize
) {
100 *ReadSize
= (UINT32
)(mImageSize
- FileOffset
);
103 if (FileOffset
>= mImageSize
) {
107 CopyMem (Buffer
, (UINT8
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
113 Measure GPT table data into TPM log.
115 Caution: This function may receive untrusted input.
116 The GPT partition table is external input, so this function should parse partition data carefully.
118 @param TcgProtocol Pointer to the located TCG protocol instance.
119 @param GptHandle Handle that GPT partition was installed.
121 @retval EFI_SUCCESS Successfully measure GPT table.
122 @retval EFI_UNSUPPORTED Not support GPT table on the given handle.
123 @retval EFI_DEVICE_ERROR Can't get GPT table because device error.
124 @retval EFI_OUT_OF_RESOURCES No enough resource to measure GPT table.
125 @retval other error value
130 IN EFI_TCG_PROTOCOL
*TcgProtocol
,
131 IN EFI_HANDLE GptHandle
135 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
136 EFI_DISK_IO_PROTOCOL
*DiskIo
;
137 EFI_PARTITION_TABLE_HEADER
*PrimaryHeader
;
138 EFI_PARTITION_ENTRY
*PartitionEntry
;
140 UINTN NumberOfPartition
;
142 TCG_PCR_EVENT
*TcgEvent
;
143 EFI_GPT_DATA
*GptData
;
146 EFI_PHYSICAL_ADDRESS EventLogLastEntry
;
148 if (mMeasureGptCount
> 0) {
152 Status
= gBS
->HandleProtocol (GptHandle
, &gEfiBlockIoProtocolGuid
, (VOID
**)&BlockIo
);
153 if (EFI_ERROR (Status
)) {
154 return EFI_UNSUPPORTED
;
156 Status
= gBS
->HandleProtocol (GptHandle
, &gEfiDiskIoProtocolGuid
, (VOID
**)&DiskIo
);
157 if (EFI_ERROR (Status
)) {
158 return EFI_UNSUPPORTED
;
161 // Read the EFI Partition Table Header
163 PrimaryHeader
= (EFI_PARTITION_TABLE_HEADER
*) AllocatePool (BlockIo
->Media
->BlockSize
);
164 if (PrimaryHeader
== NULL
) {
165 return EFI_OUT_OF_RESOURCES
;
167 Status
= DiskIo
->ReadDisk (
169 BlockIo
->Media
->MediaId
,
170 1 * BlockIo
->Media
->BlockSize
,
171 BlockIo
->Media
->BlockSize
,
172 (UINT8
*)PrimaryHeader
174 if (EFI_ERROR (Status
)) {
175 DEBUG ((EFI_D_ERROR
, "Failed to Read Partition Table Header!\n"));
176 FreePool (PrimaryHeader
);
177 return EFI_DEVICE_ERROR
;
180 // Read the partition entry.
182 EntryPtr
= (UINT8
*)AllocatePool (PrimaryHeader
->NumberOfPartitionEntries
* PrimaryHeader
->SizeOfPartitionEntry
);
183 if (EntryPtr
== NULL
) {
184 FreePool (PrimaryHeader
);
185 return EFI_OUT_OF_RESOURCES
;
187 Status
= DiskIo
->ReadDisk (
189 BlockIo
->Media
->MediaId
,
190 MultU64x32(PrimaryHeader
->PartitionEntryLBA
, BlockIo
->Media
->BlockSize
),
191 PrimaryHeader
->NumberOfPartitionEntries
* PrimaryHeader
->SizeOfPartitionEntry
,
194 if (EFI_ERROR (Status
)) {
195 FreePool (PrimaryHeader
);
197 return EFI_DEVICE_ERROR
;
201 // Count the valid partition
203 PartitionEntry
= (EFI_PARTITION_ENTRY
*)EntryPtr
;
204 NumberOfPartition
= 0;
205 for (Index
= 0; Index
< PrimaryHeader
->NumberOfPartitionEntries
; Index
++) {
206 if (!CompareGuid (&PartitionEntry
->PartitionTypeGUID
, &mZeroGuid
)) {
209 PartitionEntry
= (EFI_PARTITION_ENTRY
*)((UINT8
*)PartitionEntry
+ PrimaryHeader
->SizeOfPartitionEntry
);
213 // Prepare Data for Measurement
215 EventSize
= (UINT32
)(sizeof (EFI_GPT_DATA
) - sizeof (GptData
->Partitions
)
216 + NumberOfPartition
* PrimaryHeader
->SizeOfPartitionEntry
);
217 TcgEvent
= (TCG_PCR_EVENT
*) AllocateZeroPool (EventSize
+ sizeof (TCG_PCR_EVENT_HDR
));
218 if (TcgEvent
== NULL
) {
219 FreePool (PrimaryHeader
);
221 return EFI_OUT_OF_RESOURCES
;
224 TcgEvent
->PCRIndex
= 5;
225 TcgEvent
->EventType
= EV_EFI_GPT_EVENT
;
226 TcgEvent
->EventSize
= EventSize
;
227 GptData
= (EFI_GPT_DATA
*) TcgEvent
->Event
;
230 // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition
232 CopyMem ((UINT8
*)GptData
, (UINT8
*)PrimaryHeader
, sizeof (EFI_PARTITION_TABLE_HEADER
));
233 GptData
->NumberOfPartitions
= NumberOfPartition
;
235 // Copy the valid partition entry
237 PartitionEntry
= (EFI_PARTITION_ENTRY
*)EntryPtr
;
238 NumberOfPartition
= 0;
239 for (Index
= 0; Index
< PrimaryHeader
->NumberOfPartitionEntries
; Index
++) {
240 if (!CompareGuid (&PartitionEntry
->PartitionTypeGUID
, &mZeroGuid
)) {
242 (UINT8
*)&GptData
->Partitions
+ NumberOfPartition
* PrimaryHeader
->SizeOfPartitionEntry
,
243 (UINT8
*)PartitionEntry
,
244 PrimaryHeader
->SizeOfPartitionEntry
248 PartitionEntry
=(EFI_PARTITION_ENTRY
*)((UINT8
*)PartitionEntry
+ PrimaryHeader
->SizeOfPartitionEntry
);
252 // Measure the GPT data
255 Status
= TcgProtocol
->HashLogExtendEvent (
257 (EFI_PHYSICAL_ADDRESS
) (UINTN
) (VOID
*) GptData
,
258 (UINT64
) TcgEvent
->EventSize
,
264 if (!EFI_ERROR (Status
)) {
268 FreePool (PrimaryHeader
);
276 Measure PE image into TPM log based on the authenticode image hashing in
277 PE/COFF Specification 8.0 Appendix A.
279 Caution: This function may receive untrusted input.
280 PE/COFF image is external input, so this function will validate its data structure
281 within this image buffer before use.
283 @param[in] TcgProtocol Pointer to the located TCG protocol instance.
284 @param[in] ImageAddress Start address of image buffer.
285 @param[in] ImageSize Image size
286 @param[in] LinkTimeBase Address that the image is loaded into memory.
287 @param[in] ImageType Image subsystem type.
288 @param[in] FilePath File path is corresponding to the input image.
290 @retval EFI_SUCCESS Successfully measure image.
291 @retval EFI_OUT_OF_RESOURCES No enough resource to measure image.
292 @retval EFI_UNSUPPORTED ImageType is unsupported or PE image is mal-format.
293 @retval other error value
299 IN EFI_TCG_PROTOCOL
*TcgProtocol
,
300 IN EFI_PHYSICAL_ADDRESS ImageAddress
,
302 IN UINTN LinkTimeBase
,
304 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
308 TCG_PCR_EVENT
*TcgEvent
;
309 EFI_IMAGE_LOAD_EVENT
*ImageLoad
;
313 EFI_IMAGE_DOS_HEADER
*DosHdr
;
314 UINT32 PeCoffHeaderOffset
;
315 EFI_IMAGE_SECTION_HEADER
*Section
;
318 UINTN SumOfBytesHashed
;
319 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
325 EFI_PHYSICAL_ADDRESS EventLogLastEntry
;
326 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
327 UINT32 NumberOfRvaAndSizes
;
331 Status
= EFI_UNSUPPORTED
;
333 SectionHeader
= NULL
;
335 FilePathSize
= (UINT32
) GetDevicePathSize (FilePath
);
338 // Determine destination PCR by BootPolicy
340 EventSize
= sizeof (*ImageLoad
) - sizeof (ImageLoad
->DevicePath
) + FilePathSize
;
341 TcgEvent
= AllocateZeroPool (EventSize
+ sizeof (TCG_PCR_EVENT
));
342 if (TcgEvent
== NULL
) {
343 return EFI_OUT_OF_RESOURCES
;
346 TcgEvent
->EventSize
= EventSize
;
347 ImageLoad
= (EFI_IMAGE_LOAD_EVENT
*) TcgEvent
->Event
;
350 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
351 TcgEvent
->EventType
= EV_EFI_BOOT_SERVICES_APPLICATION
;
352 TcgEvent
->PCRIndex
= 4;
354 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
355 TcgEvent
->EventType
= EV_EFI_BOOT_SERVICES_DRIVER
;
356 TcgEvent
->PCRIndex
= 2;
358 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
359 TcgEvent
->EventType
= EV_EFI_RUNTIME_SERVICES_DRIVER
;
360 TcgEvent
->PCRIndex
= 2;
365 "TcgMeasurePeImage: Unknown subsystem type %d",
371 ImageLoad
->ImageLocationInMemory
= ImageAddress
;
372 ImageLoad
->ImageLengthInMemory
= ImageSize
;
373 ImageLoad
->ImageLinkTimeAddress
= LinkTimeBase
;
374 ImageLoad
->LengthOfDevicePath
= FilePathSize
;
375 CopyMem (ImageLoad
->DevicePath
, FilePath
, FilePathSize
);
378 // Check PE/COFF image
380 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
381 PeCoffHeaderOffset
= 0;
382 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
383 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
386 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
387 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
392 // PE/COFF Image Measurement
394 // NOTE: The following codes/steps are based upon the authenticode image hashing in
395 // PE/COFF Specification 8.0 Appendix A.
399 // 1. Load the image header into memory.
401 // 2. Initialize a SHA hash context.
402 CtxSize
= Sha1GetContextSize ();
403 Sha1Ctx
= AllocatePool (CtxSize
);
404 if (Sha1Ctx
== NULL
) {
405 Status
= EFI_OUT_OF_RESOURCES
;
409 HashStatus
= Sha1Init (Sha1Ctx
);
415 // Measuring PE/COFF Image Header;
416 // But CheckSum field and SECURITY data directory (certificate) are excluded
418 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
420 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
421 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
422 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
423 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
425 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
428 // Get the magic value from the PE/COFF Optional Header
430 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
434 // 3. Calculate the distance from the base of the image header to the image checksum address.
435 // 4. Hash the image header from its base to beginning of the image checksum.
437 HashBase
= (UINT8
*) (UINTN
) ImageAddress
;
438 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
442 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
443 HashSize
= (UINTN
) ((UINT8
*)(&Hdr
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
448 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
449 HashSize
= (UINTN
) ((UINT8
*)(&Hdr
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
452 HashStatus
= Sha1Update (Sha1Ctx
, HashBase
, HashSize
);
458 // 5. Skip over the image checksum (it occupies a single ULONG).
460 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
462 // 6. Since there is no Cert Directory in optional header, hash everything
463 // from the end of the checksum to the end of image header.
465 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
469 HashBase
= (UINT8
*) &Hdr
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
470 HashSize
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- ImageAddress
);
475 HashBase
= (UINT8
*) &Hdr
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
476 HashSize
= Hdr
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- ImageAddress
);
480 HashStatus
= Sha1Update (Sha1Ctx
, HashBase
, HashSize
);
487 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
489 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
493 HashBase
= (UINT8
*) &Hdr
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
494 HashSize
= (UINTN
) ((UINT8
*)(&Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
499 HashBase
= (UINT8
*) &Hdr
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
500 HashSize
= (UINTN
) ((UINT8
*)(&Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
504 HashStatus
= Sha1Update (Sha1Ctx
, HashBase
, HashSize
);
511 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
512 // 9. Hash everything from the end of the Cert Directory to the end of image header.
514 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
518 HashBase
= (UINT8
*) &Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
519 HashSize
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- ImageAddress
);
524 HashBase
= (UINT8
*) &Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
525 HashSize
= Hdr
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) (HashBase
- ImageAddress
);
529 HashStatus
= Sha1Update (Sha1Ctx
, HashBase
, HashSize
);
537 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header
539 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
543 SumOfBytesHashed
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
;
548 SumOfBytesHashed
= Hdr
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
552 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
553 // structures in the image. The 'NumberOfSections' field of the image
554 // header indicates how big the table should be. Do not include any
555 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
557 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * Hdr
.Pe32
->FileHeader
.NumberOfSections
);
558 if (SectionHeader
== NULL
) {
559 Status
= EFI_OUT_OF_RESOURCES
;
564 // 12. Using the 'PointerToRawData' in the referenced section headers as
565 // a key, arrange the elements in the table in ascending order. In other
566 // words, sort the section headers according to the disk-file offset of
569 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
570 (UINT8
*) (UINTN
) ImageAddress
+
573 sizeof(EFI_IMAGE_FILE_HEADER
) +
574 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
576 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
578 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
579 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof(EFI_IMAGE_SECTION_HEADER
));
582 CopyMem (&SectionHeader
[Pos
], Section
, sizeof(EFI_IMAGE_SECTION_HEADER
));
587 // 13. Walk through the sorted table, bring the corresponding section
588 // into memory, and hash the entire section (using the 'SizeOfRawData'
589 // field in the section header to determine the amount of data to hash).
590 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
591 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
593 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
594 Section
= (EFI_IMAGE_SECTION_HEADER
*) &SectionHeader
[Index
];
595 if (Section
->SizeOfRawData
== 0) {
598 HashBase
= (UINT8
*) (UINTN
) ImageAddress
+ Section
->PointerToRawData
;
599 HashSize
= (UINTN
) Section
->SizeOfRawData
;
601 HashStatus
= Sha1Update (Sha1Ctx
, HashBase
, HashSize
);
606 SumOfBytesHashed
+= HashSize
;
610 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
611 // data in the file that needs to be added to the hash. This data begins
612 // at file offset SUM_OF_BYTES_HASHED and its length is:
613 // FileSize - (CertDirectory->Size)
615 if (ImageSize
> SumOfBytesHashed
) {
616 HashBase
= (UINT8
*) (UINTN
) ImageAddress
+ SumOfBytesHashed
;
618 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
) {
621 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
625 CertSize
= Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
630 CertSize
= Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
634 if (ImageSize
> CertSize
+ SumOfBytesHashed
) {
635 HashSize
= (UINTN
) (ImageSize
- CertSize
- SumOfBytesHashed
);
637 HashStatus
= Sha1Update (Sha1Ctx
, HashBase
, HashSize
);
641 } else if (ImageSize
< CertSize
+ SumOfBytesHashed
) {
647 // 17. Finalize the SHA hash.
649 HashStatus
= Sha1Final (Sha1Ctx
, (UINT8
*) &TcgEvent
->Digest
);
658 Status
= TcgProtocol
->HashLogExtendEvent (
660 (EFI_PHYSICAL_ADDRESS
) (UINTN
) (VOID
*) NULL
,
671 if (SectionHeader
!= NULL
) {
672 FreePool (SectionHeader
);
675 if (Sha1Ctx
!= NULL
) {
682 The security handler is used to abstract platform-specific policy
683 from the DXE core response to an attempt to use a file that returns a
684 given status for the authentication check from the section extraction protocol.
686 The possible responses in a given SAP implementation may include locking
687 flash upon failure to authenticate, attestation logging for all signed drivers,
688 and other exception operations. The File parameter allows for possible logging
689 within the SAP of the driver.
691 If File is NULL, then EFI_INVALID_PARAMETER is returned.
693 If the file specified by File with an authentication status specified by
694 AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.
696 If the file specified by File with an authentication status specified by
697 AuthenticationStatus is not safe for the DXE Core to use under any circumstances,
698 then EFI_ACCESS_DENIED is returned.
700 If the file specified by File with an authentication status specified by
701 AuthenticationStatus is not safe for the DXE Core to use right now, but it
702 might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is
705 @param[in] AuthenticationStatus This is the authentication status returned
706 from the securitymeasurement services for the
708 @param[in] File This is a pointer to the device path of the file that is
709 being dispatched. This will optionally be used for logging.
710 @param[in] FileBuffer File buffer matches the input file device path.
711 @param[in] FileSize Size of File buffer matches the input file device path.
712 @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.
714 @retval EFI_SUCCESS The file specified by DevicePath and non-NULL
715 FileBuffer did authenticate, and the platform policy dictates
716 that the DXE Foundation may use the file.
717 @retval other error value
721 DxeTpmMeasureBootHandler (
722 IN UINT32 AuthenticationStatus
,
723 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File
,
726 IN BOOLEAN BootPolicy
729 EFI_TCG_PROTOCOL
*TcgProtocol
;
731 TCG_EFI_BOOT_SERVICE_CAPABILITY ProtocolCapability
;
732 UINT32 TCGFeatureFlags
;
733 EFI_PHYSICAL_ADDRESS EventLogLocation
;
734 EFI_PHYSICAL_ADDRESS EventLogLastEntry
;
735 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
736 EFI_DEVICE_PATH_PROTOCOL
*OrigDevicePathNode
;
738 EFI_HANDLE TempHandle
;
739 BOOLEAN ApplicationRequired
;
740 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
741 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
;
742 EFI_PHYSICAL_ADDRESS FvAddress
;
745 Status
= gBS
->LocateProtocol (&gEfiTcgProtocolGuid
, NULL
, (VOID
**) &TcgProtocol
);
746 if (EFI_ERROR (Status
)) {
748 // TCG protocol is not installed. So, TPM is not present.
749 // Don't do any measurement, and directly return EFI_SUCCESS.
754 ProtocolCapability
.Size
= (UINT8
) sizeof (ProtocolCapability
);
755 Status
= TcgProtocol
->StatusCheck (
762 if (EFI_ERROR (Status
) || ProtocolCapability
.TPMDeactivatedFlag
) {
764 // TPM device doesn't work or activate.
770 // Copy File Device Path
772 OrigDevicePathNode
= DuplicateDevicePath (File
);
775 // 1. Check whether this device path support BlockIo protocol.
776 // Is so, this device path may be a GPT device path.
778 DevicePathNode
= OrigDevicePathNode
;
779 Status
= gBS
->LocateDevicePath (&gEfiBlockIoProtocolGuid
, &DevicePathNode
, &Handle
);
780 if (!EFI_ERROR (Status
) && !mMeasureGptTableFlag
) {
782 // Find the gpt partion on the given devicepath
784 DevicePathNode
= OrigDevicePathNode
;
785 ASSERT (DevicePathNode
!= NULL
);
786 while (!IsDevicePathEnd (DevicePathNode
)) {
788 // Find the Gpt partition
790 if (DevicePathType (DevicePathNode
) == MEDIA_DEVICE_PATH
&&
791 DevicePathSubType (DevicePathNode
) == MEDIA_HARDDRIVE_DP
) {
793 // Check whether it is a gpt partition or not
795 if (((HARDDRIVE_DEVICE_PATH
*) DevicePathNode
)->MBRType
== MBR_TYPE_EFI_PARTITION_TABLE_HEADER
&&
796 ((HARDDRIVE_DEVICE_PATH
*) DevicePathNode
)->SignatureType
== SIGNATURE_TYPE_GUID
) {
799 // Change the partition device path to its parent device path (disk) and get the handle.
801 DevicePathNode
->Type
= END_DEVICE_PATH_TYPE
;
802 DevicePathNode
->SubType
= END_ENTIRE_DEVICE_PATH_SUBTYPE
;
803 DevicePathNode
= OrigDevicePathNode
;
804 Status
= gBS
->LocateDevicePath (
805 &gEfiDiskIoProtocolGuid
,
809 if (!EFI_ERROR (Status
)) {
813 Status
= TcgMeasureGptTable (TcgProtocol
, Handle
);
814 if (!EFI_ERROR (Status
)) {
816 // GPT disk check done.
818 mMeasureGptTableFlag
= TRUE
;
821 FreePool (OrigDevicePathNode
);
822 OrigDevicePathNode
= DuplicateDevicePath (File
);
823 ASSERT (OrigDevicePathNode
!= NULL
);
827 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
832 // 2. Measure PE image.
834 ApplicationRequired
= FALSE
;
837 // Check whether this device path support FVB protocol.
839 DevicePathNode
= OrigDevicePathNode
;
840 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid
, &DevicePathNode
, &Handle
);
841 if (!EFI_ERROR (Status
)) {
843 // Don't check FV image, and directly return EFI_SUCCESS.
844 // It can be extended to the specific FV authentication according to the different requirement.
846 if (IsDevicePathEnd (DevicePathNode
)) {
850 // The PE image from unmeasured Firmware volume need be measured
851 // The PE image from measured Firmware volume will be mearsured according to policy below.
852 // If it is driver, do not measure
853 // If it is application, still measure.
855 ApplicationRequired
= TRUE
;
857 if (mCacheMeasuredHandle
!= Handle
&& mMeasuredHobData
!= NULL
) {
859 // Search for Root FV of this PE image
863 Status
= gBS
->HandleProtocol(
865 &gEfiFirmwareVolumeBlockProtocolGuid
,
868 TempHandle
= FvbProtocol
->ParentHandle
;
869 } while (!EFI_ERROR(Status
) && FvbProtocol
->ParentHandle
!= NULL
);
872 // Search in measured FV Hob
874 Status
= FvbProtocol
->GetPhysicalAddress(FvbProtocol
, &FvAddress
);
875 if (EFI_ERROR(Status
)){
879 ApplicationRequired
= FALSE
;
881 for (Index
= 0; Index
< mMeasuredHobData
->Num
; Index
++) {
882 if(mMeasuredHobData
->MeasuredFvBuf
[Index
].BlobBase
== FvAddress
) {
884 // Cache measured FV for next measurement
886 mCacheMeasuredHandle
= Handle
;
887 ApplicationRequired
= TRUE
;
895 // File is not found.
897 if (FileBuffer
== NULL
) {
898 Status
= EFI_SECURITY_VIOLATION
;
902 mImageSize
= FileSize
;
903 mFileBuffer
= FileBuffer
;
908 DevicePathNode
= OrigDevicePathNode
;
909 ZeroMem (&ImageContext
, sizeof (ImageContext
));
910 ImageContext
.Handle
= (VOID
*) FileBuffer
;
911 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) DxeTpmMeasureBootLibImageRead
;
914 // Get information about the image being loaded
916 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
917 if (EFI_ERROR (Status
)) {
919 // The information can't be got from the invalid PeImage
925 // Measure only application if Application flag is set
926 // Measure drivers and applications if Application flag is not set
928 if ((!ApplicationRequired
) ||
929 (ApplicationRequired
&& ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
)) {
931 // Print the image path to be measured.
935 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*DevPathToText
;
936 Status
= gBS
->LocateProtocol (
937 &gEfiDevicePathToTextProtocolGuid
,
939 (VOID
**) &DevPathToText
941 if (!EFI_ERROR (Status
)) {
942 ToText
= DevPathToText
->ConvertDevicePathToText (
947 if (ToText
!= NULL
) {
948 DEBUG ((DEBUG_INFO
, "The measured image path is %s.\n", ToText
));
954 // Measure PE image into TPM log.
956 Status
= TcgMeasurePeImage (
958 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FileBuffer
,
960 (UINTN
) ImageContext
.ImageAddress
,
961 ImageContext
.ImageType
,
967 // Done, free the allocated resource.
970 if (OrigDevicePathNode
!= NULL
) {
971 FreePool (OrigDevicePathNode
);
978 Register the security handler to provide TPM measure boot service.
980 @param ImageHandle ImageHandle of the loaded driver.
981 @param SystemTable Pointer to the EFI System Table.
983 @retval EFI_SUCCESS Register successfully.
984 @retval EFI_OUT_OF_RESOURCES No enough memory to register this handler.
988 DxeTpmMeasureBootLibConstructor (
989 IN EFI_HANDLE ImageHandle
,
990 IN EFI_SYSTEM_TABLE
*SystemTable
993 EFI_HOB_GUID_TYPE
*GuidHob
;
997 GuidHob
= GetFirstGuidHob (&gMeasuredFvHobGuid
);
999 if (GuidHob
!= NULL
) {
1000 mMeasuredHobData
= GET_GUID_HOB_DATA (GuidHob
);
1003 return RegisterSecurity2Handler (
1004 DxeTpmMeasureBootHandler
,
1005 EFI_AUTH_OPERATION_MEASURE_IMAGE
| EFI_AUTH_OPERATION_IMAGE_REQUIRED