/** @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); }