/** @file\r
- The library instance provides security service of TPM2 measure boot.\r
+ The library instance provides security service of TPM2 measure boot and\r
+ Confidential Computing (CC) measure boot.\r
\r
Caution: This file requires additional review when modified.\r
This library will have external input - PE/COFF image and GPT partition.\r
#include <Library/PeCoffLib.h>\r
#include <Library/SecurityManagementLib.h>\r
#include <Library/HobLib.h>\r
+#include <Protocol/CcMeasurement.h>\r
+\r
+typedef struct {\r
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;\r
+} MEASURE_BOOT_PROTOCOLS;\r
\r
//\r
// Flag to check GPT partition. It only need be measured once.\r
Caution: This function may receive untrusted input.\r
The GPT partition table is external input, so this function should parse partition data carefully.\r
\r
- @param Tcg2Protocol Pointer to the located TCG2 protocol instance.\r
+ @param MeasureBootProtocols Pointer to the located MeasureBoot protocol instances (i.e. TCG2/CC protocol).\r
@param GptHandle Handle that GPT partition was installed.\r
\r
@retval EFI_SUCCESS Successfully measure GPT table.\r
EFI_STATUS\r
EFIAPI\r
Tcg2MeasureGptTable (\r
- IN EFI_TCG2_PROTOCOL *Tcg2Protocol,\r
- IN EFI_HANDLE GptHandle\r
+ IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols,\r
+ IN EFI_HANDLE GptHandle\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
- EFI_DISK_IO_PROTOCOL *DiskIo;\r
- EFI_PARTITION_TABLE_HEADER *PrimaryHeader;\r
- EFI_PARTITION_ENTRY *PartitionEntry;\r
- UINT8 *EntryPtr;\r
- UINTN NumberOfPartition;\r
- UINT32 Index;\r
- EFI_TCG2_EVENT *Tcg2Event;\r
- EFI_GPT_DATA *GptData;\r
- UINT32 EventSize;\r
+ EFI_STATUS Status;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+ EFI_DISK_IO_PROTOCOL *DiskIo;\r
+ EFI_PARTITION_TABLE_HEADER *PrimaryHeader;\r
+ EFI_PARTITION_ENTRY *PartitionEntry;\r
+ UINT8 *EntryPtr;\r
+ UINTN NumberOfPartition;\r
+ UINT32 Index;\r
+ UINT8 *EventPtr;\r
+ EFI_TCG2_EVENT *Tcg2Event;\r
+ EFI_CC_EVENT *CcEvent;\r
+ EFI_GPT_DATA *GptData;\r
+ UINT32 EventSize;\r
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;\r
+ EFI_CC_MR_INDEX MrIndex;\r
\r
if (mTcg2MeasureGptCount > 0) {\r
return EFI_SUCCESS;\r
}\r
\r
+ PrimaryHeader = NULL;\r
+ EntryPtr = NULL;\r
+ EventPtr = NULL;\r
+\r
+ Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;\r
+ CcProtocol = MeasureBootProtocols->CcProtocol;\r
+\r
+ if ((Tcg2Protocol == NULL) && (CcProtocol == NULL)) {\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (sizeof (EFI_CC_EVENT) != sizeof (EFI_TCG2_EVENT)) {\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
if (EFI_ERROR (Status)) {\r
return EFI_UNSUPPORTED;\r
return EFI_DEVICE_ERROR;\r
}\r
\r
+ //\r
+ // PrimaryHeader->SizeOfPartitionEntry should not be zero\r
+ //\r
+ if (PrimaryHeader->SizeOfPartitionEntry == 0) {\r
+ DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n"));\r
+ FreePool (PrimaryHeader);\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
//\r
// Read the partition entry.\r
//\r
}\r
\r
//\r
- // Prepare Data for Measurement\r
+ // Prepare Data for Measurement (CcProtocol and Tcg2Protocol)\r
//\r
EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)\r
+ NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
- Tcg2Event = (EFI_TCG2_EVENT *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));\r
- if (Tcg2Event == NULL) {\r
- FreePool (PrimaryHeader);\r
- FreePool (EntryPtr);\r
- return EFI_OUT_OF_RESOURCES;\r
+ EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));\r
+ if (EventPtr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
}\r
\r
+ Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;\r
Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);\r
Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);\r
Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;\r
}\r
\r
//\r
- // Measure the GPT data\r
+ // Only one of TCG2_PROTOCOL or CC_MEASUREMENT_PROTOCOL is exposed.\r
+ // So Measure the GPT data with one of the protocol.\r
//\r
- Status = Tcg2Protocol->HashLogExtendEvent (\r
- Tcg2Protocol,\r
- 0,\r
- (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,\r
- (UINT64)EventSize,\r
- Tcg2Event\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- mTcg2MeasureGptCount++;\r
+ if (CcProtocol != NULL) {\r
+ //\r
+ // EFI_CC_EVENT share the same data structure with EFI_TCG2_EVENT\r
+ // except the MrIndex and PCRIndex in Header.\r
+ // Tcg2Event has been created and initialized before. So only the MrIndex need\r
+ // be adjusted.\r
+ //\r
+ Status = CcProtocol->MapPcrToMrIndex (CcProtocol, Tcg2Event->Header.PCRIndex, &MrIndex);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Cannot map PcrIndex(%d) to MrIndex\n", Tcg2Event->Header.PCRIndex));\r
+ goto Exit;\r
+ }\r
+\r
+ CcEvent = (EFI_CC_EVENT *)EventPtr;\r
+ CcEvent->Header.MrIndex = MrIndex;\r
+ Status = CcProtocol->HashLogExtendEvent (\r
+ CcProtocol,\r
+ 0,\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,\r
+ (UINT64)EventSize,\r
+ CcEvent\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ mTcg2MeasureGptCount++;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Cc MeasureGptTable - %r\n", Status));\r
+ } else if (Tcg2Protocol != NULL) {\r
+ //\r
+ // If Tcg2Protocol is installed, then Measure GPT data with this protocol.\r
+ //\r
+ Status = Tcg2Protocol->HashLogExtendEvent (\r
+ Tcg2Protocol,\r
+ 0,\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,\r
+ (UINT64)EventSize,\r
+ Tcg2Event\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ mTcg2MeasureGptCount++;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2 MeasureGptTable - %r\n", Status));\r
}\r
\r
- FreePool (PrimaryHeader);\r
- FreePool (EntryPtr);\r
- FreePool (Tcg2Event);\r
+Exit:\r
+ if (PrimaryHeader != NULL) {\r
+ FreePool (PrimaryHeader);\r
+ }\r
+\r
+ if (EntryPtr != NULL) {\r
+ FreePool (EntryPtr);\r
+ }\r
+\r
+ if (EventPtr != NULL) {\r
+ FreePool (EventPtr);\r
+ }\r
\r
return Status;\r
}\r
PE/COFF image is external input, so this function will validate its data structure\r
within this image buffer before use.\r
\r
- @param[in] Tcg2Protocol Pointer to the located TCG2 protocol instance.\r
- @param[in] ImageAddress Start address of image buffer.\r
- @param[in] ImageSize Image size\r
- @param[in] LinkTimeBase Address that the image is loaded into memory.\r
- @param[in] ImageType Image subsystem type.\r
- @param[in] FilePath File path is corresponding to the input image.\r
+ @param[in] MeasureBootProtocols Pointer to the located MeasureBoot protocol instances.\r
+ @param[in] ImageAddress Start address of image buffer.\r
+ @param[in] ImageSize Image size\r
+ @param[in] LinkTimeBase Address that the image is loaded into memory.\r
+ @param[in] ImageType Image subsystem type.\r
+ @param[in] FilePath File path is corresponding to the input image.\r
\r
@retval EFI_SUCCESS Successfully measure image.\r
@retval EFI_OUT_OF_RESOURCES No enough resource to measure image.\r
EFI_STATUS\r
EFIAPI\r
Tcg2MeasurePeImage (\r
- IN EFI_TCG2_PROTOCOL *Tcg2Protocol,\r
+ IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols,\r
IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
IN UINTN ImageSize,\r
IN UINTN LinkTimeBase,\r
IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_TCG2_EVENT *Tcg2Event;\r
- EFI_IMAGE_LOAD_EVENT *ImageLoad;\r
- UINT32 FilePathSize;\r
- UINT32 EventSize;\r
-\r
- Status = EFI_UNSUPPORTED;\r
- ImageLoad = NULL;\r
+ EFI_STATUS Status;\r
+ EFI_TCG2_EVENT *Tcg2Event;\r
+ EFI_IMAGE_LOAD_EVENT *ImageLoad;\r
+ UINT32 FilePathSize;\r
+ UINT32 EventSize;\r
+ EFI_CC_EVENT *CcEvent;\r
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;\r
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
+ UINT8 *EventPtr;\r
+ EFI_CC_MR_INDEX MrIndex;\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ ImageLoad = NULL;\r
+ EventPtr = NULL;\r
+\r
+ Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;\r
+ CcProtocol = MeasureBootProtocols->CcProtocol;\r
+\r
+ if ((Tcg2Protocol == NULL) && (CcProtocol == NULL)) {\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (sizeof (EFI_CC_EVENT) != sizeof (EFI_TCG2_EVENT)) {\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
FilePathSize = (UINT32)GetDevicePathSize (FilePath);\r
\r
//\r
// Determine destination PCR by BootPolicy\r
//\r
EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;\r
- Tcg2Event = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));\r
- if (Tcg2Event == NULL) {\r
+ EventPtr = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));\r
+ if (EventPtr == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
+ Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;\r
Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);\r
Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);\r
Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;\r
//\r
// Log the PE data\r
//\r
- Status = Tcg2Protocol->HashLogExtendEvent (\r
- Tcg2Protocol,\r
+ if (CcProtocol != NULL) {\r
+ Status = CcProtocol->MapPcrToMrIndex (CcProtocol, Tcg2Event->Header.PCRIndex, &MrIndex);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Cannot map PcrIndex(%d) to MrIndex\n", Tcg2Event->Header.PCRIndex));\r
+ goto Finish;\r
+ }\r
+\r
+ CcEvent = (EFI_CC_EVENT *)EventPtr;\r
+ CcEvent->Header.MrIndex = MrIndex;\r
+\r
+ Status = CcProtocol->HashLogExtendEvent (\r
+ CcProtocol,\r
PE_COFF_IMAGE,\r
ImageAddress,\r
ImageSize,\r
- Tcg2Event\r
+ CcEvent\r
);\r
+ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Cc MeasurePeImage - %r\n", Status));\r
+ } else if (Tcg2Protocol != NULL) {\r
+ Status = Tcg2Protocol->HashLogExtendEvent (\r
+ Tcg2Protocol,\r
+ PE_COFF_IMAGE,\r
+ ImageAddress,\r
+ ImageSize,\r
+ Tcg2Event\r
+ );\r
+ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2 MeasurePeImage - %r\n", Status));\r
+ }\r
+\r
if (Status == EFI_VOLUME_FULL) {\r
//\r
// Volume full here means the image is hashed and its result is extended to PCR.\r
}\r
\r
Finish:\r
- FreePool (Tcg2Event);\r
+ if (EventPtr != NULL) {\r
+ FreePool (EventPtr);\r
+ }\r
\r
return Status;\r
}\r
\r
+/**\r
+ Get the measure boot protocols.\r
+\r
+ There are 2 measure boot, TCG2 protocol based and Cc measurement protocol based.\r
+\r
+ @param MeasureBootProtocols Pointer to the located measure boot protocol instances.\r
+\r
+ @retval EFI_SUCCESS Sucessfully locate the measure boot protocol instances (at least one instance).\r
+ @retval EFI_UNSUPPORTED Measure boot is not supported.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetMeasureBootProtocols (\r
+ MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
+ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol;\r
+ EFI_TCG2_BOOT_SERVICE_CAPABILITY Tcg2ProtocolCapability;\r
+ EFI_CC_BOOT_SERVICE_CAPABILITY CcProtocolCapability;\r
+\r
+ CcProtocol = NULL;\r
+ Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **)&CcProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Cc Measurement protocol is not installed.\r
+ //\r
+ DEBUG ((DEBUG_VERBOSE, "CcMeasurementProtocol is not installed. - %r\n", Status));\r
+ } else {\r
+ ZeroMem (&CcProtocolCapability, sizeof (CcProtocolCapability));\r
+ CcProtocolCapability.Size = sizeof (CcProtocolCapability);\r
+ Status = CcProtocol->GetCapability (CcProtocol, &CcProtocolCapability);\r
+ if (EFI_ERROR (Status) || (CcProtocolCapability.CcType.Type == EFI_CC_TYPE_NONE)) {\r
+ DEBUG ((DEBUG_ERROR, " CcProtocol->GetCapability returns : %x, %r\n", CcProtocolCapability.CcType.Type, Status));\r
+ CcProtocol = NULL;\r
+ }\r
+ }\r
+\r
+ Tcg2Protocol = NULL;\r
+ Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Tcg2 protocol is not installed. So, TPM2 is not present.\r
+ //\r
+ DEBUG ((DEBUG_VERBOSE, "Tcg2Protocol is not installed. - %r\n", Status));\r
+ } else {\r
+ Tcg2ProtocolCapability.Size = (UINT8)sizeof (Tcg2ProtocolCapability);\r
+ Status = Tcg2Protocol->GetCapability (Tcg2Protocol, &Tcg2ProtocolCapability);\r
+ if (EFI_ERROR (Status) || (!Tcg2ProtocolCapability.TPMPresentFlag)) {\r
+ //\r
+ // TPM device doesn't work or activate.\r
+ //\r
+ DEBUG ((DEBUG_ERROR, "TPMPresentFlag=FALSE %r\n", Status));\r
+ Tcg2Protocol = NULL;\r
+ }\r
+ }\r
+\r
+ MeasureBootProtocols->Tcg2Protocol = Tcg2Protocol;\r
+ MeasureBootProtocols->CcProtocol = CcProtocol;\r
+\r
+ return (Tcg2Protocol == NULL && CcProtocol == NULL) ? EFI_UNSUPPORTED : EFI_SUCCESS;\r
+}\r
+\r
/**\r
The security handler is used to abstract platform-specific policy\r
from the DXE core response to an attempt to use a file that returns a\r
IN BOOLEAN BootPolicy\r
)\r
{\r
- EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
+ MEASURE_BOOT_PROTOCOLS MeasureBootProtocols;\r
EFI_STATUS Status;\r
- EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability;\r
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;\r
EFI_HANDLE Handle;\r
EFI_PHYSICAL_ADDRESS FvAddress;\r
UINT32 Index;\r
\r
- Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);\r
+ MeasureBootProtocols.Tcg2Protocol = NULL;\r
+ MeasureBootProtocols.CcProtocol = NULL;\r
+\r
+ Status = GetMeasureBootProtocols (&MeasureBootProtocols);\r
+\r
if (EFI_ERROR (Status)) {\r
//\r
- // Tcg2 protocol is not installed. So, TPM2 is not present.\r
+ // None of Measured boot protocols (Tcg2, Cc) is installed.\r
// Don't do any measurement, and directly return EFI_SUCCESS.\r
//\r
- DEBUG ((DEBUG_VERBOSE, "DxeTpm2MeasureBootHandler - Tcg2 - %r\n", Status));\r
+ DEBUG ((DEBUG_INFO, "None of Tcg2Protocol/CcMeasurementProtocol is installed.\n"));\r
return EFI_SUCCESS;\r
}\r
\r
- ProtocolCapability.Size = (UINT8)sizeof (ProtocolCapability);\r
- Status = Tcg2Protocol->GetCapability (\r
- Tcg2Protocol,\r
- &ProtocolCapability\r
- );\r
- if (EFI_ERROR (Status) || (!ProtocolCapability.TPMPresentFlag)) {\r
- //\r
- // TPM device doesn't work or activate.\r
- //\r
- DEBUG ((DEBUG_ERROR, "DxeTpm2MeasureBootHandler (%r) - TPMPresentFlag - %x\n", Status, ProtocolCapability.TPMPresentFlag));\r
- return EFI_SUCCESS;\r
- }\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n",\r
+ MeasureBootProtocols.Tcg2Protocol,\r
+ MeasureBootProtocols.CcProtocol\r
+ ));\r
\r
//\r
// Copy File Device Path\r
//\r
// Measure GPT disk.\r
//\r
- Status = Tcg2MeasureGptTable (Tcg2Protocol, Handle);\r
- DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasureGptTable - %r\n", Status));\r
+ Status = Tcg2MeasureGptTable (&MeasureBootProtocols, Handle);\r
+\r
if (!EFI_ERROR (Status)) {\r
//\r
// GPT disk check done.\r
// Measure PE image into TPM log.\r
//\r
Status = Tcg2MeasurePeImage (\r
- Tcg2Protocol,\r
+ &MeasureBootProtocols,\r
(EFI_PHYSICAL_ADDRESS)(UINTN)FileBuffer,\r
FileSize,\r
(UINTN)ImageContext.ImageAddress,\r
ImageContext.ImageType,\r
DevicePathNode\r
);\r
- DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasurePeImage - %r\n", Status));\r
}\r
\r
//\r