public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V3 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM
       [not found] <cover.1639394321.git.longlong.yang@intel.com>
@ 2021-12-13 11:19 ` longlong.yang
  2021-12-14  1:56   ` Ni, Ray
  0 siblings, 1 reply; 3+ messages in thread
From: longlong.yang @ 2021-12-13 11:19 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                 | 280 ++++++++++++++++++
 .../MicrocodeMeasurementDxe.inf               |  56 ++++
 .../MicrocodeMeasurementDxe.uni               |  15 +
 .../MicrocodeMeasurementDxeExtra.uni          |  12 +
 UefiCpuPkg/UefiCpuPkg.dsc                     |   1 +
 5 files changed, 364 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..6f7dcda789f9
--- /dev/null
+++ b/UefiCpuPkg/MicrocodeMeasurementDxe/MicrocodeMeasurementDxe.c
@@ -0,0 +1,280 @@
+/** @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: We assumed that the order of address of every microcode patch in RAM is the same
+  // with the order of those in the Microcode Firmware Volume in FLASH. If any future updates
+  // made this assumption untenable, then 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] 3+ messages in thread

* Re: [PATCH V3 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM
  2021-12-13 11:19 ` [PATCH V3 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM longlong.yang
@ 2021-12-14  1:56   ` Ni, Ray
  2021-12-14  3:02     ` Longlong Yang
  0 siblings, 1 reply; 3+ messages in thread
From: Ni, Ray @ 2021-12-14  1:56 UTC (permalink / raw)
  To: Yang, Longlong, devel@edk2.groups.io
  Cc: Dong, Eric, Kumar, Rahul1, Yao, Jiewen, Xu, Min M, Zhang, Qi1

> +
> +  //
> +  // 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: We assumed that the order of address of every microcode patch in RAM is the same
> +  // with the order of those in the Microcode Firmware Volume in FLASH. If any future updates
> +  // made this assumption untenable, then needs a new solution to measure microcode patches.
> +  //

Can you explain the above comments?
If you only measure the microcode which will be applied to CPU, why do you care about the order?

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH V3 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM
  2021-12-14  1:56   ` Ni, Ray
@ 2021-12-14  3:02     ` Longlong Yang
  0 siblings, 0 replies; 3+ messages in thread
From: Longlong Yang @ 2021-12-14  3:02 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io
  Cc: Dong, Eric, Kumar, Rahul1, Yao, Jiewen, Xu, Min M, Zhang, Qi1

Hi Ray,

The order is required by the hash function.
By measuring an object, we first need to get the hash or the digest of that object, and then extend the hash/digest or measurement to TPM device. If there are more than one microcode patches applied to CPU, we need to measure all of those patches. My design on measuring multiple microcode patches is that we first pack those patches into a single binary blob, and then measure the binary blob by calling TpmMeasureAndLogData function. In TpmMeasureAndLogData function, the hash of binary blob will be calculated. If the order got changed, then the hash will change too, and then the attestation will be impacted. Therefore we need make sure if microcode didn't get updated, then the hash/digest should the same every time we measure them. So we should sort the patches to make sure the binary blob is device specific same. 

BRs
Longlong

-----Original Message-----
From: Ni, Ray <ray.ni@intel.com> 
Sent: Tuesday, December 14, 2021 9:57 AM
To: Yang, Longlong <longlong.yang@intel.com>; devel@edk2.groups.io
Cc: Dong, Eric <eric.dong@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: RE: [PATCH V3 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM

> +
> +  //
> +  // 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: We assumed that the order of address of every microcode 
> + patch in RAM is the same  // with the order of those in the 
> + Microcode Firmware Volume in FLASH. If any future updates  // made this assumption untenable, then needs a new solution to measure microcode patches.
> +  //

Can you explain the above comments?
If you only measure the microcode which will be applied to CPU, why do you care about the order?

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-12-14  3:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cover.1639394321.git.longlong.yang@intel.com>
2021-12-13 11:19 ` [PATCH V3 1/1] UefiCpuPkg: Extend measurement of microcode patches to TPM longlong.yang
2021-12-14  1:56   ` Ni, Ray
2021-12-14  3:02     ` Longlong Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox