/** @file
This library is used by FSP modules to measure data to TPM.
Copyright (c) 2020, 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
#include
#include
/**
Tpm measure and log data, and extend the measurement result into a specific PCR.
@param[in] PcrIndex PCR Index.
@param[in] EventType Event type.
@param[in] EventLog Measurement event log.
@param[in] LogLen Event log length in bytes.
@param[in] HashData The start of the data buffer to be hashed, extended.
@param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
@param[in] Flags Bitmap providing additional information.
@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
TpmMeasureAndLogDataWithFlags (
IN UINT32 PcrIndex,
IN UINT32 EventType,
IN VOID *EventLog,
IN UINT32 LogLen,
IN VOID *HashData,
IN UINT64 HashDataLen,
IN UINT64 Flags
)
{
EFI_STATUS Status;
EDKII_TCG_PPI *TcgPpi;
TCG_PCR_EVENT_HDR TcgEventHdr;
Status = PeiServicesLocatePpi (
&gEdkiiTcgPpiGuid,
0,
NULL,
(VOID **)&TcgPpi
);
if (EFI_ERROR (Status)) {
return Status;
}
TcgEventHdr.PCRIndex = PcrIndex;
TcgEventHdr.EventType = EventType;
TcgEventHdr.EventSize = LogLen;
Status = TcgPpi->HashLogExtendEvent (
TcgPpi,
Flags,
HashData,
(UINTN)HashDataLen,
&TcgEventHdr,
EventLog
);
return Status;
}
/**
Measure a FSP FirmwareBlob.
@param[in] Description Description for this FirmwareBlob.
@param[in] FirmwareBlobBase Base address of this FirmwareBlob.
@param[in] FirmwareBlobLength Size in bytes of this FirmwareBlob.
@param[in] CfgRegionOffset Configuration region offset in bytes.
@param[in] CfgRegionSize Configuration region in bytes.
@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.
**/
STATIC
EFI_STATUS
EFIAPI
MeasureFspFirmwareBlobWithCfg (
IN CHAR8 *Description OPTIONAL,
IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,
IN UINT64 FirmwareBlobLength,
IN UINT32 CfgRegionOffset,
IN UINT32 CfgRegionSize
)
{
EFI_PLATFORM_FIRMWARE_BLOB FvBlob, UpdBlob;
PLATFORM_FIRMWARE_BLOB2_STRUCT FvBlob2, UpdBlob2;
VOID *FvName;
UINT32 FvEventType;
VOID *FvEventLog, *UpdEventLog;
UINT32 FvEventLogSize, UpdEventLogSize;
EFI_STATUS Status;
HASH_HANDLE HashHandle;
UINT8 *HashBase;
UINTN HashSize;
TPML_DIGEST_VALUES DigestList;
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);
AsciiSPrint ((CHAR8 *)UpdBlob2.BlobDescription, sizeof (UpdBlob2.BlobDescription), "%aUDP", Description);
} else {
AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDescription), "Fv(%g)", FvName);
AsciiSPrint ((CHAR8 *)UpdBlob2.BlobDescription, sizeof (UpdBlob2.BlobDescription), "(%g)UDP", FvName);
}
FvBlob2.BlobDescriptionSize = sizeof (FvBlob2.BlobDescription);
FvBlob2.BlobBase = FirmwareBlobBase;
FvBlob2.BlobLength = FirmwareBlobLength;
FvEventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
FvEventLog = &FvBlob2;
FvEventLogSize = sizeof (FvBlob2);
UpdBlob2.BlobDescriptionSize = sizeof (UpdBlob2.BlobDescription);
UpdBlob2.BlobBase = CfgRegionOffset;
UpdBlob2.BlobLength = CfgRegionSize;
UpdEventLog = &UpdBlob2;
UpdEventLogSize = sizeof (UpdBlob2);
} else {
FvBlob.BlobBase = FirmwareBlobBase;
FvBlob.BlobLength = FirmwareBlobLength;
FvEventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
FvEventLog = &FvBlob;
FvEventLogSize = sizeof (FvBlob);
UpdBlob.BlobBase = CfgRegionOffset;
UpdBlob.BlobLength = CfgRegionSize;
UpdEventLog = &UpdBlob;
UpdEventLogSize = sizeof (UpdBlob);
}
/** Initialize a SHA hash context. **/
Status = HashStart (&HashHandle);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "HashStart failed - %r\n", Status));
return Status;
}
/** Hash FSP binary before UDP **/
HashBase = (UINT8 *)(UINTN)FirmwareBlobBase;
HashSize = (UINTN)CfgRegionOffset;
Status = HashUpdate (HashHandle, HashBase, HashSize);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "HashUpdate failed - %r\n", Status));
return Status;
}
/** Hash FSP binary after UDP **/
HashBase = (UINT8 *)(UINTN)FirmwareBlobBase + CfgRegionOffset + CfgRegionSize;
HashSize = (UINTN)(FirmwareBlobLength - CfgRegionOffset - CfgRegionSize);
Status = HashUpdate (HashHandle, HashBase, HashSize);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "HashUpdate failed - %r\n", Status));
return Status;
}
/** Finalize the SHA hash. **/
Status = HashCompleteAndExtend (HashHandle, 0, NULL, 0, &DigestList);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "HashCompleteAndExtend failed - %r\n", Status));
return Status;
}
Status = TpmMeasureAndLogDataWithFlags (
0,
FvEventType,
FvEventLog,
FvEventLogSize,
(UINT8 *)&DigestList,
(UINTN)sizeof (DigestList),
EDKII_TCG_PRE_HASH_LOG_ONLY
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "TpmMeasureAndLogDataWithFlags failed - %r\n", Status));
return Status;
}
Status = TpmMeasureAndLogData (
1,
EV_PLATFORM_CONFIG_FLAGS,
UpdEventLog,
UpdEventLogSize,
(UINT8 *)(UINTN)FirmwareBlobBase + CfgRegionOffset,
CfgRegionSize
);
return Status;
}
/**
Measure a FSP FirmwareBlob.
@param[in] PcrIndex PCR Index.
@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
MeasureFspFirmwareBlob (
IN UINT32 PcrIndex,
IN CHAR8 *Description OPTIONAL,
IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,
IN UINT64 FirmwareBlobLength
)
{
UINT32 FspMeasureMask;
FSP_INFO_HEADER *FspHeaderPtr;
FspMeasureMask = PcdGet32 (PcdFspMeasurementConfig);
if ((FspMeasureMask & FSP_MEASURE_FSPUPD) != 0) {
FspHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader (FirmwareBlobBase);
if (FspHeaderPtr != NULL) {
return MeasureFspFirmwareBlobWithCfg (
Description,
FirmwareBlobBase,
FirmwareBlobLength,
FspHeaderPtr->CfgRegionOffset,
FspHeaderPtr->CfgRegionSize
);
}
}
return MeasureFirmwareBlob (PcrIndex, Description, FirmwareBlobBase, FirmwareBlobLength);
}