From d419e9078e5cf34d8e6ae48c8acac7f2e9164148 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Mon, 6 Nov 2023 09:33:59 -0500 Subject: [PATCH] Add TPM Replay FW CFG Input Channel library instance Adds a new library instance for QEMU platforms that allows a TPM Replay event log to optionally be passed from the QEMU command line. See https://github.com/microsoft/mu_tiano_platforms/blob/main/Platforms/Docs/Q35/Features/feature_tpm_replay.md for more information about passing a TPM Replay log through the FW CFG interface. Signed-off-by: Michael Kubacki --- Common/MU | 2 +- .../Docs/Q35/Features/feature_tpm_replay.md | 15 ++++ Platforms/QemuQ35Pkg/QemuQ35Pkg.ci.yaml | 3 +- Platforms/QemuQ35Pkg/QemuQ35Pkg.dsc | 15 +++- .../BaseFwCfgInputChannelLib.c | 75 +++++++++++++++++++ .../BaseFwCfgInputChannelLib.inf | 30 ++++++++ QemuPkg/QemuPkg.ci.yaml | 2 + QemuPkg/QemuPkg.dsc | 1 + 8 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.c create mode 100644 QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.inf diff --git a/Common/MU b/Common/MU index 0033f8e82d..b9f41330c1 160000 --- a/Common/MU +++ b/Common/MU @@ -1 +1 @@ -Subproject commit 0033f8e82d4d44c75439dafbca8616cecc665d42 +Subproject commit b9f41330c15ebacb36f3fb1b9b389b37a330ab85 diff --git a/Platforms/Docs/Q35/Features/feature_tpm_replay.md b/Platforms/Docs/Q35/Features/feature_tpm_replay.md index 91a5612b82..f046d2d9b2 100644 --- a/Platforms/Docs/Q35/Features/feature_tpm_replay.md +++ b/Platforms/Docs/Q35/Features/feature_tpm_replay.md @@ -147,6 +147,21 @@ The binary can be provided to the firmware three ways: More details about these are covered in the ["Input Channels"](https://github.com/microsoft/mu_plus/blob/HEAD/TpmTestingPkg/TpmReplayPei/Readme.md#tcg-event-log-input-channels) section of the main TPM Replay feature documentation. +#### FW CFG Example + +This option allows a new log to be passed to QEMU from the host machine easily without rebuilding firmware. + +An additional argument to QEMU can be passed in the runner plugin. + +- [QemuQ35Pkg QemuRunner.py](https://github.com/microsoft/mu_tiano_platforms/blob/HEAD/Platforms/QemuQ35Pkg/Plugins/QemuRunner/QemuRunner.py) +- [QemuSbsaPkg QemuRunner.py](https://github.com/microsoft/mu_tiano_platforms/blob/HEAD/Platforms/QemuSbsaPkg/Plugins/QemuRunner/QemuRunner.py) + +The `args` variable can be updated with the fw_cfg item: + +```python + args += " -fw_cfg name=opt/org.mu/tpm_replay/event_log,file=/replaylog.bin"` +``` + ### Converting a Binary Back to a Human Readable File It may be useful to view what's in a binary. That is also possible using `TpmReplay.py`. diff --git a/Platforms/QemuQ35Pkg/QemuQ35Pkg.ci.yaml b/Platforms/QemuQ35Pkg/QemuQ35Pkg.ci.yaml index 8e06e69a47..1e034352ce 100644 --- a/Platforms/QemuQ35Pkg/QemuQ35Pkg.ci.yaml +++ b/Platforms/QemuQ35Pkg/QemuQ35Pkg.ci.yaml @@ -43,7 +43,8 @@ "MfciPkg/MfciPkg.dec", "OemPkg/OemPkg.dec", "QemuPkg/QemuPkg.dec", - "QemuQ35Pkg/QemuQ35Pkg.dec" + "QemuQ35Pkg/QemuQ35Pkg.dec", + "TpmTestingPkg/TpmTestingPkg.dec" ], # For host based unit tests "AcceptableDependencies-HOST_APPLICATION":[ diff --git a/Platforms/QemuQ35Pkg/QemuQ35Pkg.dsc b/Platforms/QemuQ35Pkg/QemuQ35Pkg.dsc index 32debb6453..da0bc6ac75 100644 --- a/Platforms/QemuQ35Pkg/QemuQ35Pkg.dsc +++ b/Platforms/QemuQ35Pkg/QemuQ35Pkg.dsc @@ -967,6 +967,7 @@ QemuQ35Pkg/Library/ResetSystemLib/StandaloneMmResetSystemLib.inf TpmTestingPkg/TpmReplayPei/Pei/TpmReplayPei.inf { FvMeasurementExclusionLib|QemuQ35Pkg/Library/PeiFvMeasurementExclusionLib/PeiFvMeasurementExclusionLib.inf + InputChannelLib|QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.inf Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x3F @@ -1510,10 +1511,19 @@ QemuQ35Pkg/Library/ResetSystemLib/StandaloneMmResetSystemLib.inf # !if $(TPM_ENABLE) == TRUE !if $(TPM_REPLAY_ENABLED) == TRUE - TpmTestingPkg/Overrides/Tcg2Dxe/Tcg2Dxe.inf + TpmTestingPkg/Overrides/Tcg2Dxe/Tcg2Dxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf + NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf + NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf + } !else SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf { -!endif Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf @@ -1525,6 +1535,7 @@ QemuQ35Pkg/Library/ResetSystemLib/StandaloneMmResetSystemLib.inf NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf } !endif +!endif !if $(TPM_CONFIG_ENABLE) == TRUE AND $(TPM_ENABLE) == TRUE SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf !endif diff --git a/QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.c b/QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.c new file mode 100644 index 0000000000..07a256c4b3 --- /dev/null +++ b/QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.c @@ -0,0 +1,75 @@ +/** @file + QEMU FW CFG TPM Event Log Input Channel Library + + Allows a TPM replay log to be passed through the FW CFG interface on QEMU. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include + +/** + Retrieves a TPM Replay Event Log through a custom interface. + + This library instance returns a log from the QEMU FW CFG interface. + https://www.qemu.org/docs/master/specs/fw_cfg.html + + @param[out] ReplayEventLog A pointer to a pointer to the buffer to hold the event log data. + @param[out] ReplayEventLogSize The size of the data placed in the buffer. + + @retval EFI_SUCCESS The TPM Replay event log was returned successfully. + @retval EFI_INVALID_PARAMETER A pointer argument given is NULL. + @retval EFI_UNSUPPORTED The function is not implemented yet. The arguments are not used. + @retval EFI_COMPROMISED_DATA The event log data found is not valid. + @retval EFI_NOT_FOUND The event log data was not found. + +**/ +EFI_STATUS +EFIAPI +GetReplayEventLogFromCustomInterface ( + OUT VOID **ReplayEventLog, + OUT UINTN *ReplayEventLogSize + ) +{ + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM LogItem; + UINTN LogSize; + UINTN LogPageCount; + VOID *LogBase; + + if ((ReplayEventLog == NULL) || (ReplayEventLogSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = QemuFwCfgFindFile ("opt/org.mu/tpm_replay/event_log", &LogItem, &LogSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "[%a] - TPM Replay FW CFG event log not found (%r).\n", __func__, Status)); + return EFI_NOT_FOUND; + } + + DEBUG ((DEBUG_INFO, "[%a] - TPM Replay FW CFG log found. Item 0x%x of size 0x%x.\n", __func__, LogItem, LogSize)); + + LogPageCount = EFI_SIZE_TO_PAGES (LogSize); + LogBase = AllocatePages (LogPageCount); + if (LogBase == NULL) { + ASSERT (LogBase != NULL); + return EFI_OUT_OF_RESOURCES; + } + + QemuFwCfgSelectItem (LogItem); + QemuFwCfgReadBytes (LogSize, LogBase); + + *ReplayEventLog = LogBase; + *ReplayEventLogSize = LogSize; + + return EFI_SUCCESS; +} diff --git a/QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.inf b/QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.inf new file mode 100644 index 0000000000..18b11f20c5 --- /dev/null +++ b/QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.inf @@ -0,0 +1,30 @@ +## @file +# FW CFG TPM Event Log Input Channel Library +# +# Copyright (c) Microsoft Corporation. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseFwCfgInputChannelLib + FILE_GUID = 8B3828C5-DC85-49F0-8AF2-0F50391EC0BC + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = InputChannelLib + +[Packages] + MdePkg/MdePkg.dec + SecurityPkg/SecurityPkg.dec + TpmTestingPkg/TpmTestingPkg.dec + QemuPkg/QemuPkg.dec + +[LibraryClasses] + DebugLib + MemoryAllocationLib + QemuFwCfgLib + +[Sources] + BaseFwCfgInputChannelLib.c diff --git a/QemuPkg/QemuPkg.ci.yaml b/QemuPkg/QemuPkg.ci.yaml index 29783afba9..5a370b23e2 100644 --- a/QemuPkg/QemuPkg.ci.yaml +++ b/QemuPkg/QemuPkg.ci.yaml @@ -42,6 +42,7 @@ "ShellPkg/ShellPkg.dec", "EmbeddedPkg/EmbeddedPkg.dec", "QemuPkg/QemuPkg.dec", + "TpmTestingPkg/TpmTestingPkg.dec" ], # For host based unit tests "AcceptableDependencies-HOST_APPLICATION":[], @@ -101,6 +102,7 @@ "pointee", "ramfb", "rebecca", + "tpmreplay", "tsegmb" ], "IgnoreStandardPaths": [], # Standard Plugin defined paths that should be ignore diff --git a/QemuPkg/QemuPkg.dsc b/QemuPkg/QemuPkg.dsc index 90f1daed5b..8bba78cd2a 100644 --- a/QemuPkg/QemuPkg.dsc +++ b/QemuPkg/QemuPkg.dsc @@ -130,6 +130,7 @@ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask|0 [Components] + QemuPkg/Library/BaseFwCfgInputChannelLib/BaseFwCfgInputChannelLib.inf QemuPkg/Library/BasePciCapLib/BasePciCapLib.inf QemuPkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.inf QemuPkg/Library/ConfigSystemModeLibQemu/ConfigSystemModeLib.inf