/** @file | |
This library is used by other modules to measure data to TPM. | |
Copyright (c) 2020, Intel Corporation. All rights reserved. <BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <Uefi/UefiBaseType.h> | |
#include <Pi/PiFirmwareVolume.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/ReportStatusCodeLib.h> | |
#include <Library/PcdLib.h> | |
#include <Library/PrintLib.h> | |
#include <Library/TcgEventLogRecordLib.h> | |
#include <Library/TpmMeasurementLib.h> | |
#include <IndustryStandard/UefiTcgPlatform.h> | |
/** | |
Get the FvName from the FV header. | |
Causion: The FV is untrusted input. | |
@param[in] FvBase Base address of FV image. | |
@param[in] FvLength Length of FV image. | |
@return FvName pointer | |
@retval NULL FvName is NOT found | |
**/ | |
VOID * | |
TpmMeasurementGetFvName ( | |
IN EFI_PHYSICAL_ADDRESS FvBase, | |
IN UINT64 FvLength | |
) | |
{ | |
EFI_FIRMWARE_VOLUME_HEADER *FvHeader; | |
EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; | |
if (FvBase >= MAX_ADDRESS) { | |
return NULL; | |
} | |
if (FvLength >= MAX_ADDRESS - FvBase) { | |
return NULL; | |
} | |
if (FvLength < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) { | |
return NULL; | |
} | |
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase; | |
if (FvHeader->Signature != EFI_FVH_SIGNATURE) { | |
return NULL; | |
} | |
if (FvHeader->ExtHeaderOffset < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) { | |
return NULL; | |
} | |
if (FvHeader->ExtHeaderOffset + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER) > FvLength) { | |
return NULL; | |
} | |
FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(UINTN)(FvBase + FvHeader->ExtHeaderOffset); | |
return &FvExtHeader->FvName; | |
} | |
/** | |
Measure a FirmwareBlob. | |
@param[in] PcrIndex PcrIndex of the measurement. | |
@param[in] Description Description for this FirmwareBlob. | |
@param[in] FirmwareBlobBase Base address of this FirmwareBlob. | |
@param[in] FirmwareBlobLength Size in bytes of this FirmwareBlob. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_UNSUPPORTED TPM device not available. | |
@retval EFI_OUT_OF_RESOURCES Out of memory. | |
@retval EFI_DEVICE_ERROR The operation was unsuccessful. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
MeasureFirmwareBlob ( | |
IN UINT32 PcrIndex, | |
IN CHAR8 *Description OPTIONAL, | |
IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase, | |
IN UINT64 FirmwareBlobLength | |
) | |
{ | |
EFI_PLATFORM_FIRMWARE_BLOB FvBlob; | |
PLATFORM_FIRMWARE_BLOB2_STRUCT FvBlob2; | |
VOID *FvName; | |
UINT32 EventType; | |
VOID *EventLog; | |
UINT32 EventLogSize; | |
EFI_STATUS Status; | |
FvName = TpmMeasurementGetFvName (FirmwareBlobBase, FirmwareBlobLength); | |
if (((Description != NULL) || (FvName != NULL)) && | |
(PcdGet32 (PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105)) | |
{ | |
if (Description != NULL) { | |
AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDescription), "%a", Description); | |
} else { | |
AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDescription), "Fv(%g)", FvName); | |
} | |
FvBlob2.BlobDescriptionSize = sizeof (FvBlob2.BlobDescription); | |
FvBlob2.BlobBase = FirmwareBlobBase; | |
FvBlob2.BlobLength = FirmwareBlobLength; | |
EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2; | |
EventLog = &FvBlob2; | |
EventLogSize = sizeof (FvBlob2); | |
} else { | |
FvBlob.BlobBase = FirmwareBlobBase; | |
FvBlob.BlobLength = FirmwareBlobLength; | |
EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB; | |
EventLog = &FvBlob; | |
EventLogSize = sizeof (FvBlob); | |
} | |
Status = TpmMeasureAndLogData ( | |
PcrIndex, | |
EventType, | |
EventLog, | |
EventLogSize, | |
(VOID *)(UINTN)FirmwareBlobBase, | |
FirmwareBlobLength | |
); | |
return Status; | |
} | |
/** | |
Measure a HandoffTable. | |
@param[in] PcrIndex PcrIndex of the measurement. | |
@param[in] Description Description for this HandoffTable. | |
@param[in] TableGuid GUID of this HandoffTable. | |
@param[in] TableAddress Base address of this HandoffTable. | |
@param[in] TableLength Size in bytes of this HandoffTable. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_UNSUPPORTED TPM device not available. | |
@retval EFI_OUT_OF_RESOURCES Out of memory. | |
@retval EFI_DEVICE_ERROR The operation was unsuccessful. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
MeasureHandoffTable ( | |
IN UINT32 PcrIndex, | |
IN CHAR8 *Description OPTIONAL, | |
IN EFI_GUID *TableGuid, | |
IN VOID *TableAddress, | |
IN UINTN TableLength | |
) | |
{ | |
EFI_HANDOFF_TABLE_POINTERS HandoffTables; | |
HANDOFF_TABLE_POINTERS2_STRUCT HandoffTables2; | |
UINT32 EventType; | |
VOID *EventLog; | |
UINT32 EventLogSize; | |
EFI_STATUS Status; | |
if ((Description != NULL) && | |
(PcdGet32 (PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105)) | |
{ | |
AsciiSPrint ((CHAR8 *)HandoffTables2.TableDescription, sizeof (HandoffTables2.TableDescription), "%a", Description); | |
HandoffTables2.TableDescriptionSize = sizeof (HandoffTables2.TableDescription); | |
HandoffTables2.NumberOfTables = 1; | |
CopyGuid (&(HandoffTables2.TableEntry[0].VendorGuid), TableGuid); | |
HandoffTables2.TableEntry[0].VendorTable = TableAddress; | |
EventType = EV_EFI_HANDOFF_TABLES2; | |
EventLog = &HandoffTables2; | |
EventLogSize = sizeof (HandoffTables2); | |
} else { | |
HandoffTables.NumberOfTables = 1; | |
CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), TableGuid); | |
HandoffTables.TableEntry[0].VendorTable = TableAddress; | |
EventType = EV_EFI_HANDOFF_TABLES; | |
EventLog = &HandoffTables; | |
EventLogSize = sizeof (HandoffTables); | |
} | |
Status = TpmMeasureAndLogData ( | |
PcrIndex, | |
EventType, | |
EventLog, | |
EventLogSize, | |
TableAddress, | |
TableLength | |
); | |
return Status; | |
} |