X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=SecurityPkg%2FLibrary%2FDxeTpmMeasureBootLib%2FDxeTpmMeasureBootLib.c;h=f3e486eadc7a97bb9d129c0ec7b40c63abe9296d;hp=f0039c80483af7c1e56ca2958b1ba94ce75c6d6f;hb=6dbdb1914d293d9abd378bf4f035d6f38809eaf3;hpb=28186d45660c92b8d98b8b19b5f8e6ff71ea5fba diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c index f0039c8048..f3e486eadc 100644 --- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c @@ -1,6 +1,20 @@ /** @file The library instance provides security service of TPM 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. + + DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content + read is within the image buffer. + + TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its + data structure within this image buffer before use. + + TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse + partition data carefully. + Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -15,10 +29,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include -#include #include #include #include +#include + +#include #include #include @@ -29,6 +45,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include // // Flag to check GPT partition. It only need be measured once. @@ -38,10 +55,19 @@ EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} UINTN mMeasureGptCount = 0; VOID *mFileBuffer; UINTN mImageSize; +// +// Measured FV handle cache +// +EFI_HANDLE mCacheMeasuredHandle = NULL; +UINT32 *mGuidHobData = 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. @@ -52,7 +78,7 @@ UINTN mImageSize; **/ EFI_STATUS EFIAPI -ImageRead ( +DxeTpmMeasureBootLibImageRead ( IN VOID *FileHandle, IN UINTN FileOffset, IN OUT UINTN *ReadSize, @@ -86,6 +112,9 @@ ImageRead ( /** 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 TcgProtocol Pointer to the located TCG protocol instance. @param GptHandle Handle that GPT partition was installed. @@ -177,15 +206,15 @@ TcgMeasureGptTable ( if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) { NumberOfPartition++; } - PartitionEntry++; + PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry); } // - // Parepare Data for Measurement + // Prepare Data for Measurement // EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); - TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT)); + TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR)); if (TcgEvent == NULL) { FreePool (PrimaryHeader); FreePool (EntryPtr); @@ -210,13 +239,13 @@ TcgMeasureGptTable ( for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) { CopyMem ( - (UINT8 *)&GptData->Partitions + NumberOfPartition * sizeof (EFI_PARTITION_ENTRY), + (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry, (UINT8 *)PartitionEntry, - sizeof (EFI_PARTITION_ENTRY) + PrimaryHeader->SizeOfPartitionEntry ); NumberOfPartition++; } - PartitionEntry++; + PartitionEntry =(EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry); } // @@ -247,6 +276,10 @@ TcgMeasureGptTable ( 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] TcgProtocol Pointer to the located TCG protocol instance. @param[in] ImageAddress Start address of image buffer. @param[in] ImageSize Image size @@ -256,7 +289,9 @@ TcgMeasureGptTable ( @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 @@ -269,27 +304,31 @@ TcgMeasurePeImage ( IN EFI_DEVICE_PATH_PROTOCOL *FilePath ) { - EFI_STATUS Status; - TCG_PCR_EVENT *TcgEvent; - EFI_IMAGE_LOAD_EVENT *ImageLoad; - UINT32 FilePathSize; - VOID *Sha1Ctx; - UINTN CtxSize; - EFI_IMAGE_DOS_HEADER *DosHdr; - UINT32 PeCoffHeaderOffset; - EFI_IMAGE_SECTION_HEADER *Section; - UINT8 *HashBase; - UINTN HashSize; - UINTN SumOfBytesHashed; - EFI_IMAGE_SECTION_HEADER *SectionHeader; - UINTN Index, Pos; - UINT16 Magic; - UINT32 EventSize; - UINT32 EventNumber; - EFI_PHYSICAL_ADDRESS EventLogLastEntry; + EFI_STATUS Status; + TCG_PCR_EVENT *TcgEvent; + EFI_IMAGE_LOAD_EVENT *ImageLoad; + UINT32 FilePathSize; + VOID *Sha1Ctx; + UINTN CtxSize; + EFI_IMAGE_DOS_HEADER *DosHdr; + UINT32 PeCoffHeaderOffset; + EFI_IMAGE_SECTION_HEADER *Section; + UINT8 *HashBase; + UINTN HashSize; + UINTN SumOfBytesHashed; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINTN Index; + UINTN Pos; + UINT16 Magic; + UINT32 EventSize; + UINT32 EventNumber; + EFI_PHYSICAL_ADDRESS EventLogLastEntry; EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + UINT32 NumberOfRvaAndSizes; + BOOLEAN HashStatus; + UINT32 CertSize; - Status = EFI_SUCCESS; + Status = EFI_UNSUPPORTED; ImageLoad = NULL; SectionHeader = NULL; Sha1Ctx = NULL; @@ -326,7 +365,6 @@ TcgMeasurePeImage ( "TcgMeasurePeImage: Unknown subsystem type %d", ImageType )); - Status = EFI_UNSUPPORTED; goto Finish; } @@ -344,8 +382,9 @@ TcgMeasurePeImage ( if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { PeCoffHeaderOffset = DosHdr->e_lfanew; } - if (((EFI_TE_IMAGE_HEADER *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset))->Signature - == EFI_TE_IMAGE_HEADER_SIGNATURE) { + + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset); + if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { goto Finish; } @@ -367,14 +406,29 @@ TcgMeasurePeImage ( goto Finish; } - Sha1Init (Sha1Ctx); + HashStatus = Sha1Init (Sha1Ctx); + if (!HashStatus) { + goto Finish; + } // // Measuring PE/COFF Image Header; // But CheckSum field and SECURITY data directory (certificate) are excluded // - Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset); - Magic = Hdr.Pe32->OptionalHeader.Magic; + if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value + // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the + // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC + // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else { + // + // Get the magic value from the PE/COFF Optional Header + // + Magic = Hdr.Pe32->OptionalHeader.Magic; + } // // 3. Calculate the distance from the base of the image header to the image checksum address. @@ -385,58 +439,99 @@ TcgMeasurePeImage ( // // Use PE32 offset // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase); } else { // // Use PE32+ offset // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase); } - Sha1Update (Sha1Ctx, HashBase, HashSize); + HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize); + if (!HashStatus) { + goto Finish; + } // // 5. Skip over the image checksum (it occupies a single ULONG). - // 6. Get the address of the beginning of the Cert Directory. - // 7. Hash everything from the end of the checksum to the start of the Cert Directory. // - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) { // - // Use PE32 offset + // 6. Since there is no Cert Directory in optional header, hash everything + // from the end of the checksum to the end of image header. // - HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32); - HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset. + // + HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress); + } else { + // + // Use PE32+ offset. + // + HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress); + } + + if (HashSize != 0) { + HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize); + if (!HashStatus) { + goto Finish; + } + } } else { // - // Use PE32+ offset - // - HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32); - HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); - } + // 7. Hash everything from the end of the checksum to the start of the Cert Directory. + // + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); + } else { + // + // Use PE32+ offset + // + HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); + } - Sha1Update (Sha1Ctx, HashBase, HashSize); + if (HashSize != 0) { + HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize); + if (!HashStatus) { + goto Finish; + } + } - // - // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.) - // 9. Hash everything from the end of the Cert Directory to the end of image header. - // - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // Use PE32 offset - // - HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; - HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - - (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) ImageAddress); - } else { // - // Use PE32+ offset + // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.) + // 9. Hash everything from the end of the Cert Directory to the end of image header. // - HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; - HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - - (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) ImageAddress); + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; + HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress); + } else { + // + // Use PE32+ offset + // + HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; + HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress); + } + + if (HashSize != 0) { + HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize); + if (!HashStatus) { + goto Finish; + } + } } - - Sha1Update (Sha1Ctx, HashBase, HashSize); // // 10. Set the SUM_OF_BYTES_HASHED to the size of the header @@ -459,7 +554,7 @@ TcgMeasurePeImage ( // header indicates how big the table should be. Do not include any // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero. // - SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections); if (SectionHeader == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Finish; @@ -503,7 +598,10 @@ TcgMeasurePeImage ( HashBase = (UINT8 *) (UINTN) ImageAddress + Section->PointerToRawData; HashSize = (UINTN) Section->SizeOfRawData; - Sha1Update (Sha1Ctx, HashBase, HashSize); + HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize); + if (!HashStatus) { + goto Finish; + } SumOfBytesHashed += HashSize; } @@ -516,37 +614,42 @@ TcgMeasurePeImage ( // if (ImageSize > SumOfBytesHashed) { HashBase = (UINT8 *) (UINTN) ImageAddress + SumOfBytesHashed; - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - if (ImageSize - SumOfBytesHashed < Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size) { - Status = EFI_INVALID_PARAMETER; - goto Finish; - } - // - // Use PE32 offset - // - HashSize = (UINTN)(ImageSize - - Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - - SumOfBytesHashed); + + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) { + CertSize = 0; } else { - if (ImageSize - SumOfBytesHashed < Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size) { - Status = EFI_INVALID_PARAMETER; - goto Finish; + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset. + // + CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size; + } else { + // + // Use PE32+ offset. + // + CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size; } - // - // Use PE32+ offset - // - HashSize = (UINTN)(ImageSize - - Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - - SumOfBytesHashed); } - Sha1Update (Sha1Ctx, HashBase, HashSize); + if (ImageSize > CertSize + SumOfBytesHashed) { + HashSize = (UINTN) (ImageSize - CertSize - SumOfBytesHashed); + + HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize); + if (!HashStatus) { + goto Finish; + } + } else if (ImageSize < CertSize + SumOfBytesHashed) { + goto Finish; + } } // // 17. Finalize the SHA hash. // - Sha1Final (Sha1Ctx, (UINT8 *)&TcgEvent->Digest); + HashStatus = Sha1Final (Sha1Ctx, (UINT8 *) &TcgEvent->Digest); + if (!HashStatus) { + goto Finish; + } // // Log the PE data @@ -599,51 +702,46 @@ Finish: might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is returned. - @param[in, out] AuthenticationStatus This is the authentication status returned + @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 File did authenticate, and the - platform policy dictates that the DXE Core may use File. - @retval EFI_INVALID_PARAMETER File is NULL. - @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and - the platform policy dictates that File should be placed - in the untrusted state. A file may be promoted from - the untrusted to the trusted state at a future time - with a call to the Trust() DXE Service. - @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and - the platform policy dictates that File should not be - used for any purpose. - + @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 DxeTpmMeasureBootHandler ( - IN OUT UINT32 AuthenticationStatus, + IN UINT32 AuthenticationStatus, IN CONST EFI_DEVICE_PATH_PROTOCOL *File, - IN VOID *FileBuffer OPTIONAL, - IN UINTN FileSize OPTIONAL + IN VOID *FileBuffer, + IN UINTN FileSize, + IN BOOLEAN BootPolicy ) { - EFI_TCG_PROTOCOL *TcgProtocol; - EFI_STATUS Status; - TCG_EFI_BOOT_SERVICE_CAPABILITY ProtocolCapability; - UINT32 TCGFeatureFlags; - EFI_PHYSICAL_ADDRESS EventLogLocation; - EFI_PHYSICAL_ADDRESS EventLogLastEntry; - EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; - EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode; - EFI_HANDLE Handle; - BOOLEAN ApplicationRequired; - PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; - - if (File == NULL) { - return EFI_INVALID_PARAMETER; - } + EFI_TCG_PROTOCOL *TcgProtocol; + EFI_STATUS Status; + TCG_EFI_BOOT_SERVICE_CAPABILITY ProtocolCapability; + UINT32 TCGFeatureFlags; + EFI_PHYSICAL_ADDRESS EventLogLocation; + EFI_PHYSICAL_ADDRESS EventLogLastEntry; + 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; + EFI_PLATFORM_FIRMWARE_BLOB *TrustedFvBuf; + UINT32 Index; Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol); if (EFI_ERROR (Status)) { @@ -673,7 +771,6 @@ DxeTpmMeasureBootHandler ( // Copy File Device Path // OrigDevicePathNode = DuplicateDevicePath (File); - ASSERT (OrigDevicePathNode != NULL); // // 1. Check whether this device path support BlockIo protocol. @@ -686,6 +783,7 @@ DxeTpmMeasureBootHandler ( // Find the gpt partion on the given devicepath // DevicePathNode = OrigDevicePathNode; + ASSERT (DevicePathNode != NULL); while (!IsDevicePathEnd (DevicePathNode)) { // // Find the Gpt partition @@ -737,10 +835,10 @@ DxeTpmMeasureBootHandler ( ApplicationRequired = FALSE; // - // Check whether this device path support FV2 protocol. + // Check whether this device path support FVB protocol. // DevicePathNode = OrigDevicePathNode; - Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePathNode, &Handle); + Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &DevicePathNode, &Handle); if (!EFI_ERROR (Status)) { // // Don't check FV image, and directly return EFI_SUCCESS. @@ -750,13 +848,51 @@ DxeTpmMeasureBootHandler ( return EFI_SUCCESS; } // - // The image from Firmware image will not be mearsured. - // Current policy doesn't measure PeImage from Firmware if it is driver - // If the got PeImage is application, it will be still be measured. + // The PE image from untrusted Firmware volume need be measured + // The PE image from trusted Firmware volume will be mearsured according to policy below. + // if it is driver, do not measure + // If it is application, still measure. // ApplicationRequired = TRUE; + + if (mCacheMeasuredHandle != Handle && mGuidHobData != 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; + } + + TrustedFvBuf = (EFI_PLATFORM_FIRMWARE_BLOB *)(mGuidHobData + 1); + ApplicationRequired = FALSE; + + for (Index = 0; Index < *mGuidHobData; Index++) { + if(TrustedFvBuf[Index].BlobBase == FvAddress) { + // + // Cache measured FV for next measurement + // + mCacheMeasuredHandle = Handle; + ApplicationRequired = TRUE; + break; + } + } + } } - + // // File is not found. // @@ -774,7 +910,7 @@ DxeTpmMeasureBootHandler ( DevicePathNode = OrigDevicePathNode; ZeroMem (&ImageContext, sizeof (ImageContext)); ImageContext.Handle = (VOID *) FileBuffer; - ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) ImageRead; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeTpmMeasureBootLibImageRead; // // Get information about the image being loaded @@ -833,7 +969,9 @@ DxeTpmMeasureBootHandler ( // Done, free the allocated resource. // Finish: - FreePool (OrigDevicePathNode); + if (OrigDevicePathNode != NULL) { + FreePool (OrigDevicePathNode); + } return Status; } @@ -854,7 +992,17 @@ DxeTpmMeasureBootLibConstructor ( IN EFI_SYSTEM_TABLE *SystemTable ) { - return RegisterSecurityHandler ( + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = NULL; + + GuidHob = GetFirstGuidHob (&gTrustedFvHobGuid); + + if (GuidHob != NULL) { + mGuidHobData = GET_GUID_HOB_DATA (GuidHob); + } + + return RegisterSecurity2Handler ( DxeTpmMeasureBootHandler, EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED );