/** @file | |
This library is used by FSP modules to measure data to TPM. | |
Copyright (c) 2020, Intel Corporation. All rights reserved. <BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <PiPei.h> | |
#include <Uefi.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/PeiServicesLib.h> | |
#include <Library/PeiServicesTablePointerLib.h> | |
#include <Library/PcdLib.h> | |
#include <Library/PrintLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/FspWrapperApiLib.h> | |
#include <Library/TpmMeasurementLib.h> | |
#include <Library/FspMeasurementLib.h> | |
#include <Library/TcgEventLogRecordLib.h> | |
#include <Library/HashLib.h> | |
#include <Ppi/Tcg.h> | |
#include <IndustryStandard/UefiTcgPlatform.h> | |
/** | |
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 | |
); | |
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); | |
} |