From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by mx.groups.io with SMTP id smtpd.web08.22833.1639466383618273290 for ; Mon, 13 Dec 2021 23:19:43 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.com header.s=intel header.b=SYBpzhiS; spf=pass (domain: intel.com, ip: 134.134.136.31, mailfrom: longlong.yang@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1639466383; x=1671002383; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5BQmp7hwgsNH2yTPmX5gsFM8WAddWpMKCHL2zV8INOM=; b=SYBpzhiSB0tzRBNOWgpSW1VqLFE3USd3fQ6Hh/V8BhT8b/SYbJNKHtRK Z/HLo9qqQG3IkAX98ijbM/FYzsX9+xkeBkM/5bsPBYHp7p/3zU361EZxV Mhq4QBf06XzQcx5iLPPID3+2fGadH0XtCSl3tpvaBuDm8gK8LCbttvra5 81qZg8Nu+8Xyf/EvHigSxppIeLvZu+sIN3cQ8PIffizfz2SnPtrTB0YBz zbzjs7IIoyzt8RW8wZr5wHaeCNeGlxeFIgPM/wVp2IguiSVfQIgOTbUhH AsyIiegnm3X+o466oOHZA2CVnZHfZLVzMKyaYlDrchSWPWx90f0q7fPmu Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10197"; a="299696732" X-IronPort-AV: E=Sophos;i="5.88,204,1635231600"; d="scan'208";a="299696732" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Dec 2021 23:19:25 -0800 X-IronPort-AV: E=Sophos;i="5.88,204,1635231600"; d="scan'208";a="518109200" Received: from longlon1-mobl2.ccr.corp.intel.com ([10.238.1.97]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Dec 2021 23:19:22 -0800 From: "Longlong Yang" To: devel@edk2.groups.io Cc: Longlong Yang , Eric Dong , Ray Ni , Rahul Kumar , Jiewen Yao , Min M Xu , Qi Zhang Subject: [PATCH v4 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM Date: Tue, 14 Dec 2021 15:18:55 +0800 Message-Id: <0c4c9dfe09316f5766970418ad750f29b36d008d.1639466246.git.longlong.yang@intel.com> X-Mailer: git-send-email 2.31.1.windows.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 Cc: Ray Ni Cc: Rahul Kumar Cc: Jiewen Yao Cc: Min M Xu Cc: Qi Zhang Signed-off-by: Longlong Yang --- .../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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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.
+# +# 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.
+// +// 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.
+// +// 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