* [PATCH v4 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM [not found] <cover.1639466246.git.longlong.yang@intel.com> @ 2021-12-14 7:18 ` Longlong Yang 2021-12-20 5:16 ` Ni, Ray 0 siblings, 1 reply; 2+ messages in thread From: Longlong Yang @ 2021-12-14 7:18 UTC (permalink / raw) To: devel Cc: Longlong Yang, Eric Dong, Ray Ni, Rahul Kumar, Jiewen Yao, Min M Xu, Qi Zhang REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3683 TCG specification says BIOS should extend measurement of microcode to TPM. However, reference BIOS is not doing this. BIOS shall extend measurement of microcode to TPM. Cc: Eric Dong <eric.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Min M Xu <min.m.xu@intel.com> Cc: Qi Zhang <qi1.zhang@intel.com> Signed-off-by: Longlong Yang <longlong.yang@intel.com> --- .../MicrocodeMeasurementDxe.c | 281 ++++++++++++++++++ .../MicrocodeMeasurementDxe.inf | 56 ++++ .../MicrocodeMeasurementDxe.uni | 15 + .../MicrocodeMeasurementDxeExtra.uni | 12 + UefiCpuPkg/UefiCpuPkg.dsc | 1 + 5 files changed, 365 insertions(+) create mode 100644 UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c create mode 100644 UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf create mode 100644 UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni create mode 100644 UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c new file mode 100644 index 000000000000..762ca159ff0e --- /dev/null +++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c @@ -0,0 +1,281 @@ +/** @file + This driver measures microcode patches to TPM. + + This driver consumes gEdkiiMicrocodePatchHobGuid, packs all unique microcode patch found in gEdkiiMicrocodePatchHobGuid to a binary blob, and measures the binary blob to TPM. + + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <IndustryStandard/UefiTcgPlatform.h> +#include <Guid/EventGroup.h> +#include <Guid/MicrocodePatchHob.h> +#include <Library/DebugLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/HobLib.h> +#include <Library/MicrocodeLib.h> +#include <Library/TpmMeasurementLib.h> + +#define CPU_MICROCODE_MEASUREMENT_DESCRIPTION "Microcode Measurement" +#define CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN sizeof (CPU_MICROCODE_MEASUREMENT_DESCRIPTION) + +#pragma pack(1) +typedef struct { + UINT8 Description[CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN]; + UINTN NumberOfMicrocodePatchesMeasured; + UINTN SizeOfMicrocodePatchesMeasured; +} CPU_MICROCODE_MEASUREMENT_EVENT_LOG; +#pragma pack() + +/** + Helping function. + + The function is called by QuickSort to compare the order of offsets of + two microcode patches in RAM relative to their base address. Elements + will be in ascending order. + + @param[in] Offset1 The pointer to the offset of first microcode patch. + @param[in] Offset2 The pointer to the offset of second microcode patch. + + @retval 1 The offset of first microcode patch is bigger than that of the second. + @retval -1 The offset of first microcode patch is smaller than that of the second. + @retval 0 The offset of first microcode patch equals to that of the second. +**/ +INTN +EFIAPI +MicrocodePatchOffsetCompareFunction ( + IN CONST VOID *Offset1, + IN CONST VOID *Offset2 + ) +{ + if (*(UINT64 *)(Offset1) > *(UINT64 *)(Offset2)) { + return 1; + } else if (*(UINT64 *)(Offset1) < *(UINT64 *)(Offset2)) { + return -1; + } else { + return 0; + } +} + +/** + This function remove duplicate and invalid offsets in Offsets. + + This function remove duplicate and invalid offsets in Offsets. Invalid offset means MAX_UINT64 in Offsets. + + @param[in] Offsets Microcode offset list. + @param[in, out] Count On call as the count of raw microcode offset list; On return as count of the clean microcode offset list. + **/ +VOID +RemoveDuplicateAndInvalidOffset ( + IN UINT64 *Offsets, + IN OUT UINTN *Count + ) +{ + UINTN Index; + UINTN NewCount; + UINT64 LastOffset; + UINT64 QuickSortBuffer; + + // + // The order matters when packing all applied microcode patches to a single binary blob. + // Therefore it is a must to do sorting before packing. + // NOTE: Since microcode patches are sorted by their addresses in memory, the order of + // addresses in memory of all the microcode patches before sorting is required to be the + // same in every boot flow. If any future updates made this assumption untenable, then + // there needs a new solution to measure microcode patches. + // + QuickSort ( + Offsets, + *Count, + sizeof (UINT64), + MicrocodePatchOffsetCompareFunction, + (VOID *)&QuickSortBuffer + ); + + NewCount = 0; + LastOffset = MAX_UINT64; + for (Index = 0; Index < *Count; Index++) { + // + // When MAX_UINT64 element is met, all following elements are MAX_UINT64. + // + if (Offsets[Index] == MAX_UINT64) { + break; + } + + // + // Remove duplicated offsets + // + if (Offsets[Index] != LastOffset) { + LastOffset = Offsets[Index]; + Offsets[NewCount] = Offsets[Index]; + NewCount++; + } + } + + *Count = NewCount; +} + +/** + Callback function. + + Called after signaling of the Ready to Boot Event. Measure microcode patches binary blob with event type EV_CPU_MICROCODE to PCR[1] in TPM. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +MeasureMicrocodePatches ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINT32 PCRIndex; + UINT32 EventType; + CPU_MICROCODE_MEASUREMENT_EVENT_LOG EventLog; + UINT32 EventLogSize; + EFI_HOB_GUID_TYPE *GuidHob; + EDKII_MICROCODE_PATCH_HOB *MicrocodePatchHob; + UINT64 *Offsets; + UINTN Count; + UINTN Index; + UINTN TotalMicrocodeSize; + UINT8 *MicrocodePatchesBlob; + + PCRIndex = 1; + EventType = EV_CPU_MICROCODE; + AsciiStrCpyS ( + (CHAR8 *)(EventLog.Description), + CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN, + CPU_MICROCODE_MEASUREMENT_DESCRIPTION + ); + EventLog.NumberOfMicrocodePatchesMeasured = 0; + EventLog.SizeOfMicrocodePatchesMeasured = 0; + EventLogSize = sizeof (CPU_MICROCODE_MEASUREMENT_EVENT_LOG); + Offsets = NULL; + TotalMicrocodeSize = 0; + Count = 0; + + GuidHob = GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid); + if (NULL == GuidHob) { + DEBUG ((DEBUG_ERROR, "ERROR: GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid) failed.\n")); + return; + } + + MicrocodePatchHob = GET_GUID_HOB_DATA (GuidHob); + DEBUG ( + (DEBUG_INFO, + "INFO: Got MicrocodePatchHob with microcode patches starting address:0x%x, microcode patches region size:0x%x, processor count:0x%x\n", + MicrocodePatchHob->MicrocodePatchAddress, MicrocodePatchHob->MicrocodePatchRegionSize, + MicrocodePatchHob->ProcessorCount) + ); + + Offsets = AllocateCopyPool ( + MicrocodePatchHob->ProcessorCount * sizeof (UINT64), + MicrocodePatchHob->ProcessorSpecificPatchOffset + ); + Count = MicrocodePatchHob->ProcessorCount; + + RemoveDuplicateAndInvalidOffset (Offsets, &Count); + + if (0 == Count) { + DEBUG ((DEBUG_INFO, "INFO: No microcode patch is ever applied, skip the measurement of microcode!\n")); + FreePool (Offsets); + return; + } + + for (Index = 0; Index < Count; Index++) { + TotalMicrocodeSize += + GetMicrocodeLength ((CPU_MICROCODE_HEADER *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + Offsets[Index]))); + } + + EventLog.NumberOfMicrocodePatchesMeasured = Count; + EventLog.SizeOfMicrocodePatchesMeasured = TotalMicrocodeSize; + + MicrocodePatchesBlob = AllocateZeroPool (TotalMicrocodeSize); + if (NULL == MicrocodePatchesBlob) { + DEBUG ((DEBUG_ERROR, "ERROR: AllocateZeroPool to MicrocodePatchesBlob failed!\n")); + FreePool (Offsets); + return; + } + + TotalMicrocodeSize = 0; + for (Index = 0; Index < Count; Index++) { + CopyMem ( + (VOID *)(MicrocodePatchesBlob + TotalMicrocodeSize), + (VOID *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + Offsets[Index])), + (UINTN)(GetMicrocodeLength ( + (CPU_MICROCODE_HEADER *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + + Offsets[Index])) + )) + ); + TotalMicrocodeSize += + GetMicrocodeLength ((CPU_MICROCODE_HEADER *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + Offsets[Index]))); + } + + Status = TpmMeasureAndLogData ( + PCRIndex, // PCRIndex + EventType, // EventType + &EventLog, // EventLog + EventLogSize, // LogLen + MicrocodePatchesBlob, // HashData + TotalMicrocodeSize // HashDataLen + ); + if (!EFI_ERROR (Status)) { + gBS->CloseEvent (Event); + DEBUG ( + (DEBUG_INFO, + "INFO: %d Microcode patches are successfully extended to TPM! The total size measured to TPM is 0x%x\n", + Count, + TotalMicrocodeSize) + ); + } else { + DEBUG ((DEBUG_ERROR, "ERROR: TpmMeasureAndLogData failed with status %a!\n", Status)); + } + + FreePool (Offsets); + FreePool (MicrocodePatchesBlob); + return; +} + +/** + + Driver to produce microcode measurement. + + Driver to produce microcode measurement. Which install a callback function on ready to boot event. + + @param ImageHandle Module's image handle + @param SystemTable Pointer of EFI_SYSTEM_TABLE + + @return EFI_SUCCESS This function always complete successfully. + +**/ +EFI_STATUS +EFIAPI +MicrocodeMeasurementDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_EVENT Event; + + // + // Measure Microcode patches + // + EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + MeasureMicrocodePatches, + NULL, + &Event + ); + + return EFI_SUCCESS; +} diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf new file mode 100644 index 000000000000..649fb9403fd2 --- /dev/null +++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf @@ -0,0 +1,56 @@ +## @file +# This driver measures microcode patches to TPM. +# +# This driver consumes gEdkiiMicrocodePatchHobGuid, packs all unique +# microcode patch found in gEdkiiMicrocodePatchHobGuid to a binary blob, +# and measures the binary blob to TPM. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MicrocodeMeasurementDxe + MODULE_UNI_FILE = MicrocodeMeasurementDxe.uni + FILE_GUID = 0A32A803-ACDF-4C89-8293-91011548CD91 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = MicrocodeMeasurementDriverEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MicrocodeMeasurementDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + UefiDriverEntryPoint + DebugLib + HobLib + MicrocodeLib + TpmMeasurementLib + +[Guids] + gEdkiiMicrocodePatchHobGuid ## CONSUMES ## HOB + +[UserExtensions.TianoCore."ExtraFiles"] + MicrocodeMeasurementDxeExtra.uni + +[Depex] + TRUE diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni new file mode 100644 index 000000000000..5a21e955fbbf --- /dev/null +++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni @@ -0,0 +1,15 @@ +// /** @file +// This driver measures microcode patches to TPM. +// +// This driver consumes gEdkiiMicrocodePatchHobGuid, packs all uniquemicrocode patch found in gEdkiiMicrocodePatchHobGuid to a binary blob, and measures the binary blob to TPM. +// +// Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "This driver measures Microcode Patches to TPM." + +#string STR_MODULE_DESCRIPTION #language en-US "This driver consumes gEdkiiMicrocodePatchHobGuid, packs all microcode patch found in gEdkiiMicrocodePatchHobGuid to a binary blob, and measure the binary blob to TPM." diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni new file mode 100644 index 000000000000..6990cee8c6fd --- /dev/null +++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni @@ -0,0 +1,12 @@ +// /** @file +// MicrocodeMeasurementDxe Localized Strings and Content +// +// Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Microcode Patches Measurement DXE Driver" diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index 870b45284087..d1d61dd6a03b 100644 --- a/UefiCpuPkg/UefiCpuPkg.dsc +++ b/UefiCpuPkg/UefiCpuPkg.dsc @@ -119,6 +119,7 @@ UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf + UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf [Components.IA32, Components.X64] UefiCpuPkg/CpuDxe/CpuDxe.inf -- 2.31.1.windows.1 ^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v4 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM 2021-12-14 7:18 ` [PATCH v4 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM Longlong Yang @ 2021-12-20 5:16 ` Ni, Ray 0 siblings, 0 replies; 2+ messages in thread From: Ni, Ray @ 2021-12-20 5:16 UTC (permalink / raw) To: Yang, Longlong, devel@edk2.groups.io Cc: Dong, Eric, Kumar, Rahul1, Yao, Jiewen, Xu, Min M, Zhang, Qi1 Reviewed-by: Ray Ni <ray.ni@intel.com> -----Original Message----- From: Yang, Longlong <longlong.yang@intel.com> Sent: Tuesday, December 14, 2021 3:19 PM To: devel@edk2.groups.io Cc: Yang, Longlong <longlong.yang@intel.com>; Dong, Eric <eric.dong@intel.com>; Ni, Ray <ray.ni@intel.com>; Kumar, Rahul1 <rahul1.kumar@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Xu, Min M <min.m.xu@intel.com>; Zhang, Qi1 <qi1.zhang@intel.com> Subject: [PATCH v4 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3683 TCG specification says BIOS should extend measurement of microcode to TPM. However, reference BIOS is not doing this. BIOS shall extend measurement of microcode to TPM. Cc: Eric Dong <eric.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Min M Xu <min.m.xu@intel.com> Cc: Qi Zhang <qi1.zhang@intel.com> Signed-off-by: Longlong Yang <longlong.yang@intel.com> --- .../MicrocodeMeasurementDxe.c | 281 ++++++++++++++++++ .../MicrocodeMeasurementDxe.inf | 56 ++++ .../MicrocodeMeasurementDxe.uni | 15 + .../MicrocodeMeasurementDxeExtra.uni | 12 + UefiCpuPkg/UefiCpuPkg.dsc | 1 + 5 files changed, 365 insertions(+) create mode 100644 UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c create mode 100644 UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf create mode 100644 UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni create mode 100644 UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c new file mode 100644 index 000000000000..762ca159ff0e --- /dev/null +++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c @@ -0,0 +1,281 @@ +/** @file + This driver measures microcode patches to TPM. + + This driver consumes gEdkiiMicrocodePatchHobGuid, packs all unique microcode patch found in gEdkiiMicrocodePatchHobGuid to a binary blob, and measures the binary blob to TPM. + + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <IndustryStandard/UefiTcgPlatform.h> +#include <Guid/EventGroup.h> +#include <Guid/MicrocodePatchHob.h> +#include <Library/DebugLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/HobLib.h> +#include <Library/MicrocodeLib.h> +#include <Library/TpmMeasurementLib.h> + +#define CPU_MICROCODE_MEASUREMENT_DESCRIPTION "Microcode Measurement" +#define CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN sizeof (CPU_MICROCODE_MEASUREMENT_DESCRIPTION) + +#pragma pack(1) +typedef struct { + UINT8 Description[CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN]; + UINTN NumberOfMicrocodePatchesMeasured; + UINTN SizeOfMicrocodePatchesMeasured; +} CPU_MICROCODE_MEASUREMENT_EVENT_LOG; +#pragma pack() + +/** + Helping function. + + The function is called by QuickSort to compare the order of offsets of + two microcode patches in RAM relative to their base address. Elements + will be in ascending order. + + @param[in] Offset1 The pointer to the offset of first microcode patch. + @param[in] Offset2 The pointer to the offset of second microcode patch. + + @retval 1 The offset of first microcode patch is bigger than that of the second. + @retval -1 The offset of first microcode patch is smaller than that of the second. + @retval 0 The offset of first microcode patch equals to that of the second. +**/ +INTN +EFIAPI +MicrocodePatchOffsetCompareFunction ( + IN CONST VOID *Offset1, + IN CONST VOID *Offset2 + ) +{ + if (*(UINT64 *)(Offset1) > *(UINT64 *)(Offset2)) { + return 1; + } else if (*(UINT64 *)(Offset1) < *(UINT64 *)(Offset2)) { + return -1; + } else { + return 0; + } +} + +/** + This function remove duplicate and invalid offsets in Offsets. + + This function remove duplicate and invalid offsets in Offsets. Invalid offset means MAX_UINT64 in Offsets. + + @param[in] Offsets Microcode offset list. + @param[in, out] Count On call as the count of raw microcode offset list; On return as count of the clean microcode offset list. + **/ +VOID +RemoveDuplicateAndInvalidOffset ( + IN UINT64 *Offsets, + IN OUT UINTN *Count + ) +{ + UINTN Index; + UINTN NewCount; + UINT64 LastOffset; + UINT64 QuickSortBuffer; + + // + // The order matters when packing all applied microcode patches to a single binary blob. + // Therefore it is a must to do sorting before packing. + // NOTE: Since microcode patches are sorted by their addresses in memory, the order of + // addresses in memory of all the microcode patches before sorting is required to be the + // same in every boot flow. If any future updates made this assumption untenable, then + // there needs a new solution to measure microcode patches. + // + QuickSort ( + Offsets, + *Count, + sizeof (UINT64), + MicrocodePatchOffsetCompareFunction, + (VOID *)&QuickSortBuffer + ); + + NewCount = 0; + LastOffset = MAX_UINT64; + for (Index = 0; Index < *Count; Index++) { + // + // When MAX_UINT64 element is met, all following elements are MAX_UINT64. + // + if (Offsets[Index] == MAX_UINT64) { + break; + } + + // + // Remove duplicated offsets + // + if (Offsets[Index] != LastOffset) { + LastOffset = Offsets[Index]; + Offsets[NewCount] = Offsets[Index]; + NewCount++; + } + } + + *Count = NewCount; +} + +/** + Callback function. + + Called after signaling of the Ready to Boot Event. Measure microcode patches binary blob with event type EV_CPU_MICROCODE to PCR[1] in TPM. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +MeasureMicrocodePatches ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINT32 PCRIndex; + UINT32 EventType; + CPU_MICROCODE_MEASUREMENT_EVENT_LOG EventLog; + UINT32 EventLogSize; + EFI_HOB_GUID_TYPE *GuidHob; + EDKII_MICROCODE_PATCH_HOB *MicrocodePatchHob; + UINT64 *Offsets; + UINTN Count; + UINTN Index; + UINTN TotalMicrocodeSize; + UINT8 *MicrocodePatchesBlob; + + PCRIndex = 1; + EventType = EV_CPU_MICROCODE; + AsciiStrCpyS ( + (CHAR8 *)(EventLog.Description), + CPU_MICROCODE_MEASUREMENT_EVENT_LOG_DESCRIPTION_LEN, + CPU_MICROCODE_MEASUREMENT_DESCRIPTION + ); + EventLog.NumberOfMicrocodePatchesMeasured = 0; + EventLog.SizeOfMicrocodePatchesMeasured = 0; + EventLogSize = sizeof (CPU_MICROCODE_MEASUREMENT_EVENT_LOG); + Offsets = NULL; + TotalMicrocodeSize = 0; + Count = 0; + + GuidHob = GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid); + if (NULL == GuidHob) { + DEBUG ((DEBUG_ERROR, "ERROR: GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid) failed.\n")); + return; + } + + MicrocodePatchHob = GET_GUID_HOB_DATA (GuidHob); + DEBUG ( + (DEBUG_INFO, + "INFO: Got MicrocodePatchHob with microcode patches starting address:0x%x, microcode patches region size:0x%x, processor count:0x%x\n", + MicrocodePatchHob->MicrocodePatchAddress, MicrocodePatchHob->MicrocodePatchRegionSize, + MicrocodePatchHob->ProcessorCount) + ); + + Offsets = AllocateCopyPool ( + MicrocodePatchHob->ProcessorCount * sizeof (UINT64), + MicrocodePatchHob->ProcessorSpecificPatchOffset + ); + Count = MicrocodePatchHob->ProcessorCount; + + RemoveDuplicateAndInvalidOffset (Offsets, &Count); + + if (0 == Count) { + DEBUG ((DEBUG_INFO, "INFO: No microcode patch is ever applied, skip the measurement of microcode!\n")); + FreePool (Offsets); + return; + } + + for (Index = 0; Index < Count; Index++) { + TotalMicrocodeSize += + GetMicrocodeLength ((CPU_MICROCODE_HEADER *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + Offsets[Index]))); + } + + EventLog.NumberOfMicrocodePatchesMeasured = Count; + EventLog.SizeOfMicrocodePatchesMeasured = TotalMicrocodeSize; + + MicrocodePatchesBlob = AllocateZeroPool (TotalMicrocodeSize); + if (NULL == MicrocodePatchesBlob) { + DEBUG ((DEBUG_ERROR, "ERROR: AllocateZeroPool to MicrocodePatchesBlob failed!\n")); + FreePool (Offsets); + return; + } + + TotalMicrocodeSize = 0; + for (Index = 0; Index < Count; Index++) { + CopyMem ( + (VOID *)(MicrocodePatchesBlob + TotalMicrocodeSize), + (VOID *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + Offsets[Index])), + (UINTN)(GetMicrocodeLength ( + (CPU_MICROCODE_HEADER *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + + Offsets[Index])) + )) + ); + TotalMicrocodeSize += + GetMicrocodeLength ((CPU_MICROCODE_HEADER *)((UINTN)(MicrocodePatchHob->MicrocodePatchAddress + Offsets[Index]))); + } + + Status = TpmMeasureAndLogData ( + PCRIndex, // PCRIndex + EventType, // EventType + &EventLog, // EventLog + EventLogSize, // LogLen + MicrocodePatchesBlob, // HashData + TotalMicrocodeSize // HashDataLen + ); + if (!EFI_ERROR (Status)) { + gBS->CloseEvent (Event); + DEBUG ( + (DEBUG_INFO, + "INFO: %d Microcode patches are successfully extended to TPM! The total size measured to TPM is 0x%x\n", + Count, + TotalMicrocodeSize) + ); + } else { + DEBUG ((DEBUG_ERROR, "ERROR: TpmMeasureAndLogData failed with status %a!\n", Status)); + } + + FreePool (Offsets); + FreePool (MicrocodePatchesBlob); + return; +} + +/** + + Driver to produce microcode measurement. + + Driver to produce microcode measurement. Which install a callback function on ready to boot event. + + @param ImageHandle Module's image handle + @param SystemTable Pointer of EFI_SYSTEM_TABLE + + @return EFI_SUCCESS This function always complete successfully. + +**/ +EFI_STATUS +EFIAPI +MicrocodeMeasurementDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_EVENT Event; + + // + // Measure Microcode patches + // + EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + MeasureMicrocodePatches, + NULL, + &Event + ); + + return EFI_SUCCESS; +} diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf new file mode 100644 index 000000000000..649fb9403fd2 --- /dev/null +++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf @@ -0,0 +1,56 @@ +## @file +# This driver measures microcode patches to TPM. +# +# This driver consumes gEdkiiMicrocodePatchHobGuid, packs all unique +# microcode patch found in gEdkiiMicrocodePatchHobGuid to a binary blob, +# and measures the binary blob to TPM. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MicrocodeMeasurementDxe + MODULE_UNI_FILE = MicrocodeMeasurementDxe.uni + FILE_GUID = 0A32A803-ACDF-4C89-8293-91011548CD91 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = MicrocodeMeasurementDriverEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MicrocodeMeasurementDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + UefiDriverEntryPoint + DebugLib + HobLib + MicrocodeLib + TpmMeasurementLib + +[Guids] + gEdkiiMicrocodePatchHobGuid ## CONSUMES ## HOB + +[UserExtensions.TianoCore."ExtraFiles"] + MicrocodeMeasurementDxeExtra.uni + +[Depex] + TRUE diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni new file mode 100644 index 000000000000..5a21e955fbbf --- /dev/null +++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.uni @@ -0,0 +1,15 @@ +// /** @file +// This driver measures microcode patches to TPM. +// +// This driver consumes gEdkiiMicrocodePatchHobGuid, packs all uniquemicrocode patch found in gEdkiiMicrocodePatchHobGuid to a binary blob, and measures the binary blob to TPM. +// +// Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "This driver measures Microcode Patches to TPM." + +#string STR_MODULE_DESCRIPTION #language en-US "This driver consumes gEdkiiMicrocodePatchHobGuid, packs all microcode patch found in gEdkiiMicrocodePatchHobGuid to a binary blob, and measure the binary blob to TPM." diff --git a/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni new file mode 100644 index 000000000000..6990cee8c6fd --- /dev/null +++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxeExtra.uni @@ -0,0 +1,12 @@ +// /** @file +// MicrocodeMeasurementDxe Localized Strings and Content +// +// Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Microcode Patches Measurement DXE Driver" diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index 870b45284087..d1d61dd6a03b 100644 --- a/UefiCpuPkg/UefiCpuPkg.dsc +++ b/UefiCpuPkg/UefiCpuPkg.dsc @@ -119,6 +119,7 @@ UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf + UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.inf [Components.IA32, Components.X64] UefiCpuPkg/CpuDxe/CpuDxe.inf -- 2.31.1.windows.1 ^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-12-20 5:17 UTC | newest] Thread overview: 2+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <cover.1639466246.git.longlong.yang@intel.com> 2021-12-14 7:18 ` [PATCH v4 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM Longlong Yang 2021-12-20 5:16 ` Ni, Ray
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox