diff --git a/SecurityPkg/Include/Library/TcgEventLogRecordLib.h b/SecurityPkg/Include/Library/TcgEventLogRecordLib.h new file mode 100644 index 0000000000..99d634c34e --- /dev/null +++ b/SecurityPkg/Include/Library/TcgEventLogRecordLib.h @@ -0,0 +1,97 @@ +/** @file + This library is used by other modules to measure Firmware to TPM. + +Copyright (c) 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _TCG_EVENTLOGRECORD_LIB_H_ +#define _TCG_EVENTLOGRECORD_LIB_H_ + +#include + +#pragma pack (1) + +#define PLATFORM_FIRMWARE_BLOB_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)" +typedef struct { + UINT8 BlobDescriptionSize; + UINT8 BlobDescription[sizeof(PLATFORM_FIRMWARE_BLOB_DESC)]; + EFI_PHYSICAL_ADDRESS BlobBase; + UINT64 BlobLength; +} PLATFORM_FIRMWARE_BLOB2_STRUCT; + +#define HANDOFF_TABLE_POINTER_DESC "1234567890ABCDEF" +typedef struct { + UINT8 TableDescriptionSize; + UINT8 TableDescription[sizeof(HANDOFF_TABLE_POINTER_DESC)]; + UINT64 NumberOfTables; + EFI_CONFIGURATION_TABLE TableEntry[1]; +} HANDOFF_TABLE_POINTERS2_STRUCT; + +#pragma pack () + +/** + 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 + ); + +/** + Measure a 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 +MeasureFirmwareBlob ( + IN UINT32 PcrIndex, + IN CHAR8 *Description OPTIONAL, + IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase, + IN UINT64 FirmwareBlobLength + ); + +/** + 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 + ); + +#endif diff --git a/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.c b/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.c new file mode 100644 index 0000000000..e8a53fca0d --- /dev/null +++ b/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.c @@ -0,0 +1,197 @@ +/** @file + This library is used by other 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 + +/** + 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; +} diff --git a/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf b/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf new file mode 100644 index 0000000000..71388f43f6 --- /dev/null +++ b/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf @@ -0,0 +1,40 @@ +## @file +# Provides interface for firmwware TPM measurement +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TcgEventLogRecordLib + MODULE_UNI_FILE = TcgEventLogRecordLib.uni + FILE_GUID = F8125B2A-3922-4A22-A6F8-3B6159A25A3B + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TcgEventLogRecordLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + PcdLib + TpmMeasurementLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES diff --git a/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.uni b/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.uni new file mode 100644 index 0000000000..b1ca410074 --- /dev/null +++ b/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Provides interface for firmwware TPM measurement +// +// This library provides MeasureFirmwareBlob() and MeasureHandoffTable() +// to measure and log data, and extend the measurement result into a specific PCR. +// +// Copyright (c) 2020, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Provides Firmware TPM measurement functions for TPM1.2 and TPM 2.0" + +#string STR_MODULE_DESCRIPTION #language en-US "This library provides MeasureFirmwareBlob() and MeasureHandoffTable() to measure and log data, and extend the measurement result into a specific PCR." +