123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716 |
- /** @file
- The library instance provides security service of TPM2 measure boot.
- Caution: This file requires additional review when modified.
- This library will have external input - PE/COFF image and GPT partition.
- This external input must be validated carefully to avoid security issue like
- buffer overflow, integer overflow.
- DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content
- read is within the image buffer.
- Tcg2MeasurePeImage() function will accept untrusted PE/COFF image and validate its
- data structure within this image buffer before use.
- Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse
- partition data carefully.
- Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <PiDxe.h>
- #include <Protocol/Tcg2Protocol.h>
- #include <Protocol/BlockIo.h>
- #include <Protocol/DiskIo.h>
- #include <Protocol/DevicePathToText.h>
- #include <Protocol/FirmwareVolumeBlock.h>
- #include <Guid/MeasuredFvHob.h>
- #include <Library/BaseLib.h>
- #include <Library/DebugLib.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/DevicePathLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/BaseCryptLib.h>
- #include <Library/PeCoffLib.h>
- #include <Library/SecurityManagementLib.h>
- #include <Library/HobLib.h>
- //
- // Flag to check GPT partition. It only need be measured once.
- //
- BOOLEAN mTcg2MeasureGptTableFlag = FALSE;
- UINTN mTcg2MeasureGptCount = 0;
- VOID *mTcg2FileBuffer;
- UINTN mTcg2ImageSize;
- //
- // Measured FV handle cache
- //
- EFI_HANDLE mTcg2CacheMeasuredHandle = NULL;
- MEASURED_HOB_DATA *mTcg2MeasuredHobData = NULL;
- /**
- Reads contents of a PE/COFF image in memory buffer.
- Caution: This function may receive untrusted input.
- PE/COFF image is external input, so this function will make sure the PE/COFF image content
- read is within the image buffer.
- @param FileHandle Pointer to the file handle to read the PE/COFF image.
- @param FileOffset Offset into the PE/COFF image to begin the read operation.
- @param ReadSize On input, the size in bytes of the requested read operation.
- On output, the number of bytes actually read.
- @param Buffer Output buffer that contains the data read from the PE/COFF image.
- @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
- **/
- EFI_STATUS
- EFIAPI
- DxeTpm2MeasureBootLibImageRead (
- IN VOID *FileHandle,
- IN UINTN FileOffset,
- IN OUT UINTN *ReadSize,
- OUT VOID *Buffer
- )
- {
- UINTN EndPosition;
- if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if (MAX_ADDRESS - FileOffset < *ReadSize) {
- return EFI_INVALID_PARAMETER;
- }
- EndPosition = FileOffset + *ReadSize;
- if (EndPosition > mTcg2ImageSize) {
- *ReadSize = (UINT32)(mTcg2ImageSize - FileOffset);
- }
- if (FileOffset >= mTcg2ImageSize) {
- *ReadSize = 0;
- }
- CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);
- return EFI_SUCCESS;
- }
- /**
- Measure GPT table data into TPM log.
- Caution: This function may receive untrusted input.
- The GPT partition table is external input, so this function should parse partition data carefully.
- @param Tcg2Protocol Pointer to the located TCG2 protocol instance.
- @param GptHandle Handle that GPT partition was installed.
- @retval EFI_SUCCESS Successfully measure GPT table.
- @retval EFI_UNSUPPORTED Not support GPT table on the given handle.
- @retval EFI_DEVICE_ERROR Can't get GPT table because device error.
- @retval EFI_OUT_OF_RESOURCES No enough resource to measure GPT table.
- @retval other error value
- **/
- EFI_STATUS
- EFIAPI
- Tcg2MeasureGptTable (
- IN EFI_TCG2_PROTOCOL *Tcg2Protocol,
- IN EFI_HANDLE GptHandle
- )
- {
- EFI_STATUS Status;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- EFI_DISK_IO_PROTOCOL *DiskIo;
- EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
- EFI_PARTITION_ENTRY *PartitionEntry;
- UINT8 *EntryPtr;
- UINTN NumberOfPartition;
- UINT32 Index;
- EFI_TCG2_EVENT *Tcg2Event;
- EFI_GPT_DATA *GptData;
- UINT32 EventSize;
- if (mTcg2MeasureGptCount > 0) {
- return EFI_SUCCESS;
- }
- Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
- Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
- //
- // Read the EFI Partition Table Header
- //
- PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *)AllocatePool (BlockIo->Media->BlockSize);
- if (PrimaryHeader == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Status = DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- 1 * BlockIo->Media->BlockSize,
- BlockIo->Media->BlockSize,
- (UINT8 *)PrimaryHeader
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n"));
- FreePool (PrimaryHeader);
- return EFI_DEVICE_ERROR;
- }
- //
- // Read the partition entry.
- //
- EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);
- if (EntryPtr == NULL) {
- FreePool (PrimaryHeader);
- return EFI_OUT_OF_RESOURCES;
- }
- Status = DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
- PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,
- EntryPtr
- );
- if (EFI_ERROR (Status)) {
- FreePool (PrimaryHeader);
- FreePool (EntryPtr);
- return EFI_DEVICE_ERROR;
- }
- //
- // Count the valid partition
- //
- PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr;
- NumberOfPartition = 0;
- for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
- if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {
- NumberOfPartition++;
- }
- PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);
- }
- //
- // Prepare Data for Measurement
- //
- EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)
- + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);
- Tcg2Event = (EFI_TCG2_EVENT *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));
- if (Tcg2Event == NULL) {
- FreePool (PrimaryHeader);
- FreePool (EntryPtr);
- return EFI_OUT_OF_RESOURCES;
- }
- Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);
- Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
- Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
- Tcg2Event->Header.PCRIndex = 5;
- Tcg2Event->Header.EventType = EV_EFI_GPT_EVENT;
- GptData = (EFI_GPT_DATA *)Tcg2Event->Event;
- //
- // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition
- //
- CopyMem ((UINT8 *)GptData, (UINT8 *)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
- GptData->NumberOfPartitions = NumberOfPartition;
- //
- // Copy the valid partition entry
- //
- PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr;
- NumberOfPartition = 0;
- for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
- if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {
- CopyMem (
- (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry,
- (UINT8 *)PartitionEntry,
- PrimaryHeader->SizeOfPartitionEntry
- );
- NumberOfPartition++;
- }
- PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);
- }
- //
- // Measure the GPT data
- //
- Status = Tcg2Protocol->HashLogExtendEvent (
- Tcg2Protocol,
- 0,
- (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
- (UINT64)EventSize,
- Tcg2Event
- );
- if (!EFI_ERROR (Status)) {
- mTcg2MeasureGptCount++;
- }
- FreePool (PrimaryHeader);
- FreePool (EntryPtr);
- FreePool (Tcg2Event);
- return Status;
- }
- /**
- Measure PE image into TPM log based on the authenticode image hashing in
- PE/COFF Specification 8.0 Appendix A.
- Caution: This function may receive untrusted input.
- PE/COFF image is external input, so this function will validate its data structure
- within this image buffer before use.
- @param[in] Tcg2Protocol Pointer to the located TCG2 protocol instance.
- @param[in] ImageAddress Start address of image buffer.
- @param[in] ImageSize Image size
- @param[in] LinkTimeBase Address that the image is loaded into memory.
- @param[in] ImageType Image subsystem type.
- @param[in] FilePath File path is corresponding to the input image.
- @retval EFI_SUCCESS Successfully measure image.
- @retval EFI_OUT_OF_RESOURCES No enough resource to measure image.
- @retval EFI_UNSUPPORTED ImageType is unsupported or PE image is mal-format.
- @retval other error value
- **/
- EFI_STATUS
- EFIAPI
- Tcg2MeasurePeImage (
- IN EFI_TCG2_PROTOCOL *Tcg2Protocol,
- IN EFI_PHYSICAL_ADDRESS ImageAddress,
- IN UINTN ImageSize,
- IN UINTN LinkTimeBase,
- IN UINT16 ImageType,
- IN EFI_DEVICE_PATH_PROTOCOL *FilePath
- )
- {
- EFI_STATUS Status;
- EFI_TCG2_EVENT *Tcg2Event;
- EFI_IMAGE_LOAD_EVENT *ImageLoad;
- UINT32 FilePathSize;
- UINT32 EventSize;
- Status = EFI_UNSUPPORTED;
- ImageLoad = NULL;
- FilePathSize = (UINT32)GetDevicePathSize (FilePath);
- //
- // Determine destination PCR by BootPolicy
- //
- EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
- Tcg2Event = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));
- if (Tcg2Event == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);
- Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
- Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
- ImageLoad = (EFI_IMAGE_LOAD_EVENT *)Tcg2Event->Event;
- switch (ImageType) {
- case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
- Tcg2Event->Header.EventType = EV_EFI_BOOT_SERVICES_APPLICATION;
- Tcg2Event->Header.PCRIndex = 4;
- break;
- case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
- Tcg2Event->Header.EventType = EV_EFI_BOOT_SERVICES_DRIVER;
- Tcg2Event->Header.PCRIndex = 2;
- break;
- case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
- Tcg2Event->Header.EventType = EV_EFI_RUNTIME_SERVICES_DRIVER;
- Tcg2Event->Header.PCRIndex = 2;
- break;
- default:
- DEBUG ((
- DEBUG_ERROR,
- "Tcg2MeasurePeImage: Unknown subsystem type %d",
- ImageType
- ));
- goto Finish;
- }
- ImageLoad->ImageLocationInMemory = ImageAddress;
- ImageLoad->ImageLengthInMemory = ImageSize;
- ImageLoad->ImageLinkTimeAddress = LinkTimeBase;
- ImageLoad->LengthOfDevicePath = FilePathSize;
- if ((FilePath != NULL) && (FilePathSize != 0)) {
- CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);
- }
- //
- // Log the PE data
- //
- Status = Tcg2Protocol->HashLogExtendEvent (
- Tcg2Protocol,
- PE_COFF_IMAGE,
- ImageAddress,
- ImageSize,
- Tcg2Event
- );
- if (Status == EFI_VOLUME_FULL) {
- //
- // Volume full here means the image is hashed and its result is extended to PCR.
- // But the event log can't be saved since log area is full.
- // Just return EFI_SUCCESS in order not to block the image load.
- //
- Status = EFI_SUCCESS;
- }
- Finish:
- FreePool (Tcg2Event);
- return Status;
- }
- /**
- The security handler is used to abstract platform-specific policy
- from the DXE core response to an attempt to use a file that returns a
- given status for the authentication check from the section extraction protocol.
- The possible responses in a given SAP implementation may include locking
- flash upon failure to authenticate, attestation logging for all signed drivers,
- and other exception operations. The File parameter allows for possible logging
- within the SAP of the driver.
- If the file specified by File with an authentication status specified by
- AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.
- If the file specified by File with an authentication status specified by
- AuthenticationStatus is not safe for the DXE Core to use under any circumstances,
- then EFI_ACCESS_DENIED is returned.
- If the file specified by File with an authentication status specified by
- AuthenticationStatus is not safe for the DXE Core to use right now, but it
- might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is
- returned.
- If check image specified by FileBuffer and File is NULL meanwhile, return EFI_ACCESS_DENIED.
- @param[in] AuthenticationStatus This is the authentication status returned
- from the securitymeasurement services for the
- input file.
- @param[in] File This is a pointer to the device path of the file that is
- being dispatched. This will optionally be used for logging.
- @param[in] FileBuffer File buffer matches the input file device path.
- @param[in] FileSize Size of File buffer matches the input file device path.
- @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.
- @retval EFI_SUCCESS The file specified by DevicePath and non-NULL
- FileBuffer did authenticate, and the platform policy dictates
- that the DXE Foundation may use the file.
- @retval other error value
- **/
- EFI_STATUS
- EFIAPI
- DxeTpm2MeasureBootHandler (
- IN UINT32 AuthenticationStatus,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,
- IN VOID *FileBuffer,
- IN UINTN FileSize,
- IN BOOLEAN BootPolicy
- )
- {
- EFI_TCG2_PROTOCOL *Tcg2Protocol;
- EFI_STATUS Status;
- EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability;
- EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
- EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;
- EFI_HANDLE Handle;
- EFI_HANDLE TempHandle;
- BOOLEAN ApplicationRequired;
- PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
- EFI_PHYSICAL_ADDRESS FvAddress;
- UINT32 Index;
- Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);
- if (EFI_ERROR (Status)) {
- //
- // Tcg2 protocol is not installed. So, TPM2 is not present.
- // Don't do any measurement, and directly return EFI_SUCCESS.
- //
- DEBUG ((DEBUG_VERBOSE, "DxeTpm2MeasureBootHandler - Tcg2 - %r\n", Status));
- return EFI_SUCCESS;
- }
- ProtocolCapability.Size = (UINT8)sizeof (ProtocolCapability);
- Status = Tcg2Protocol->GetCapability (
- Tcg2Protocol,
- &ProtocolCapability
- );
- if (EFI_ERROR (Status) || (!ProtocolCapability.TPMPresentFlag)) {
- //
- // TPM device doesn't work or activate.
- //
- DEBUG ((DEBUG_ERROR, "DxeTpm2MeasureBootHandler (%r) - TPMPresentFlag - %x\n", Status, ProtocolCapability.TPMPresentFlag));
- return EFI_SUCCESS;
- }
- //
- // Copy File Device Path
- //
- OrigDevicePathNode = DuplicateDevicePath (File);
- //
- // 1. Check whether this device path support BlockIo protocol.
- // Is so, this device path may be a GPT device path.
- //
- DevicePathNode = OrigDevicePathNode;
- Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle);
- if (!EFI_ERROR (Status) && !mTcg2MeasureGptTableFlag) {
- //
- // Find the gpt partition on the given devicepath
- //
- DevicePathNode = OrigDevicePathNode;
- ASSERT (DevicePathNode != NULL);
- while (!IsDevicePathEnd (DevicePathNode)) {
- //
- // Find the Gpt partition
- //
- if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&
- (DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP))
- {
- //
- // Check whether it is a gpt partition or not
- //
- if ((((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) &&
- (((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->SignatureType == SIGNATURE_TYPE_GUID))
- {
- //
- // Change the partition device path to its parent device path (disk) and get the handle.
- //
- DevicePathNode->Type = END_DEVICE_PATH_TYPE;
- DevicePathNode->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
- DevicePathNode = OrigDevicePathNode;
- Status = gBS->LocateDevicePath (
- &gEfiDiskIoProtocolGuid,
- &DevicePathNode,
- &Handle
- );
- if (!EFI_ERROR (Status)) {
- //
- // Measure GPT disk.
- //
- Status = Tcg2MeasureGptTable (Tcg2Protocol, Handle);
- DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasureGptTable - %r\n", Status));
- if (!EFI_ERROR (Status)) {
- //
- // GPT disk check done.
- //
- mTcg2MeasureGptTableFlag = TRUE;
- }
- }
- FreePool (OrigDevicePathNode);
- OrigDevicePathNode = DuplicateDevicePath (File);
- ASSERT (OrigDevicePathNode != NULL);
- break;
- }
- }
- DevicePathNode = NextDevicePathNode (DevicePathNode);
- }
- }
- //
- // 2. Measure PE image.
- //
- ApplicationRequired = FALSE;
- //
- // Check whether this device path support FVB protocol.
- //
- DevicePathNode = OrigDevicePathNode;
- Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &DevicePathNode, &Handle);
- if (!EFI_ERROR (Status)) {
- //
- // Don't check FV image, and directly return EFI_SUCCESS.
- // It can be extended to the specific FV authentication according to the different requirement.
- //
- if (IsDevicePathEnd (DevicePathNode)) {
- return EFI_SUCCESS;
- }
- //
- // The PE image from unmeasured Firmware volume need be measured
- // The PE image from measured Firmware volume will be measured according to policy below.
- // If it is driver, do not measure
- // If it is application, still measure.
- //
- ApplicationRequired = TRUE;
- if ((mTcg2CacheMeasuredHandle != Handle) && (mTcg2MeasuredHobData != NULL)) {
- //
- // Search for Root FV of this PE image
- //
- TempHandle = Handle;
- do {
- Status = gBS->HandleProtocol (
- TempHandle,
- &gEfiFirmwareVolumeBlockProtocolGuid,
- (VOID **)&FvbProtocol
- );
- TempHandle = FvbProtocol->ParentHandle;
- } while (!EFI_ERROR (Status) && FvbProtocol->ParentHandle != NULL);
- //
- // Search in measured FV Hob
- //
- Status = FvbProtocol->GetPhysicalAddress (FvbProtocol, &FvAddress);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- ApplicationRequired = FALSE;
- for (Index = 0; Index < mTcg2MeasuredHobData->Num; Index++) {
- if (mTcg2MeasuredHobData->MeasuredFvBuf[Index].BlobBase == FvAddress) {
- //
- // Cache measured FV for next measurement
- //
- mTcg2CacheMeasuredHandle = Handle;
- ApplicationRequired = TRUE;
- break;
- }
- }
- }
- }
- //
- // File is not found.
- //
- if (FileBuffer == NULL) {
- Status = EFI_SECURITY_VIOLATION;
- goto Finish;
- }
- mTcg2ImageSize = FileSize;
- mTcg2FileBuffer = FileBuffer;
- //
- // Measure PE Image
- //
- DevicePathNode = OrigDevicePathNode;
- ZeroMem (&ImageContext, sizeof (ImageContext));
- ImageContext.Handle = (VOID *)FileBuffer;
- ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)DxeTpm2MeasureBootLibImageRead;
- //
- // Get information about the image being loaded
- //
- Status = PeCoffLoaderGetImageInfo (&ImageContext);
- if (EFI_ERROR (Status)) {
- //
- // Check for invalid parameters.
- //
- if (File == NULL) {
- Status = EFI_ACCESS_DENIED;
- }
- //
- // The information can't be got from the invalid PeImage
- //
- goto Finish;
- }
- //
- // Measure only application if Application flag is set
- // Measure drivers and applications if Application flag is not set
- //
- if ((!ApplicationRequired) ||
- (ApplicationRequired && (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)))
- {
- //
- // Print the image path to be measured.
- //
- DEBUG_CODE_BEGIN ();
- CHAR16 *ToText;
- ToText = ConvertDevicePathToText (
- DevicePathNode,
- FALSE,
- TRUE
- );
- if (ToText != NULL) {
- DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));
- FreePool (ToText);
- }
- DEBUG_CODE_END ();
- //
- // Measure PE image into TPM log.
- //
- Status = Tcg2MeasurePeImage (
- Tcg2Protocol,
- (EFI_PHYSICAL_ADDRESS)(UINTN)FileBuffer,
- FileSize,
- (UINTN)ImageContext.ImageAddress,
- ImageContext.ImageType,
- DevicePathNode
- );
- DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasurePeImage - %r\n", Status));
- }
- //
- // Done, free the allocated resource.
- //
- Finish:
- if (OrigDevicePathNode != NULL) {
- FreePool (OrigDevicePathNode);
- }
- DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - %r\n", Status));
- return Status;
- }
- /**
- Register the security handler to provide TPM measure boot service.
- @param ImageHandle ImageHandle of the loaded driver.
- @param SystemTable Pointer to the EFI System Table.
- @retval EFI_SUCCESS Register successfully.
- @retval EFI_OUT_OF_RESOURCES No enough memory to register this handler.
- **/
- EFI_STATUS
- EFIAPI
- DxeTpm2MeasureBootLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_HOB_GUID_TYPE *GuidHob;
- GuidHob = NULL;
- GuidHob = GetFirstGuidHob (&gMeasuredFvHobGuid);
- if (GuidHob != NULL) {
- mTcg2MeasuredHobData = GET_GUID_HOB_DATA (GuidHob);
- }
- return RegisterSecurity2Handler (
- DxeTpm2MeasureBootHandler,
- EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
- );
- }
|