diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc index 0212be4a33..e72a2dbc97 100644 --- a/ArmVirtPkg/ArmVirtQemu.dsc +++ b/ArmVirtPkg/ArmVirtQemu.dsc @@ -80,6 +80,7 @@ Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf Tpm2HelpLib|SecurityPkg/Library/Tpm2HelpLib/Tpm2HelpLib.inf Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf + Tcg2PhysicalPresencePlatformLib|OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHierarchyLib.inf !else diff --git a/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc b/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc index d664775718..04541f5d91 100644 --- a/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc +++ b/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc @@ -10,6 +10,7 @@ !endif Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf + Tcg2PhysicalPresencePlatformLib|OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf !else Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf diff --git a/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h b/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h new file mode 100644 index 0000000000..4299b4af43 --- /dev/null +++ b/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h @@ -0,0 +1,41 @@ +/** @file + Returns the platform specific Physical Presence configuration. + + Copyright (c) 2020, 9elements GmbH. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __TCG2_PHYSICAL_PRESENCE_PLATFORM_LIB_H__ +#define __TCG2_PHYSICAL_PRESENCE_PLATFORM_LIB_H__ + +#include + +typedef enum { + Tcg2PhysicalPresenceTpmVersionUnknown, + Tcg2PhysicalPresenceTpmVersion12, + Tcg2PhysicalPresenceTpmVersion20 +} TCG2_PHYSICAL_PRESENCE_TPM_VERSION; + +typedef struct { + EFI_PHYSICAL_ADDRESS PpiAddress; + TCG2_PHYSICAL_PRESENCE_TPM_VERSION TpmVersion; + BOOLEAN PpiInMmio; +} TCG2_PHYSICAL_PRESENCE_PLATFORM_CONFIG; + +/** + Reads the platform specific Physical Presence configuration. + + @param[out] Config The config structure to fill in. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_INVALID_PARAMETER A required pointer argument was NULL. + @retval EFI_PROTOCOL_ERROR Invalid config entry size. +**/ +EFI_STATUS +EFIAPI +TpmPpiPlatformReadConfig ( + OUT TCG2_PHYSICAL_PRESENCE_PLATFORM_CONFIG *Config + ); + +#endif diff --git a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c index 4038020251..36f4b4e8d6 100644 --- a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c +++ b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c @@ -27,8 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include -#include #include +#include #include #include #include @@ -40,42 +40,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent EFI_HII_HANDLE mTcg2PpStringPackHandle; +#define TCG2_PHYSICAL_PRESENCE_USER_CONFIRM_TIMEOUT_100NS (3ULL * 60ULL * 10000000ULL) + #define TPM_PPI_FLAGS (QEMU_TPM_PPI_FUNC_ALLOWED_USR_REQ) STATIC volatile QEMU_TPM_PPI *mPpi; -/** - Reads QEMU PPI config from fw_cfg. - - @param[out] The Config structure to read to. - - @retval EFI_SUCCESS Operation completed successfully. - @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size. -**/ -STATIC -EFI_STATUS -QemuTpmReadConfig ( - OUT QEMU_FWCFG_TPM_CONFIG *Config - ) -{ - EFI_STATUS Status; - FIRMWARE_CONFIG_ITEM FwCfgItem; - UINTN FwCfgSize; - - Status = QemuFwCfgFindFile ("etc/tpm/config", &FwCfgItem, &FwCfgSize); - if (EFI_ERROR (Status)) { - return Status; - } - - if (FwCfgSize != sizeof (*Config)) { - return EFI_PROTOCOL_ERROR; - } - - QemuFwCfgSelectItem (FwCfgItem); - QemuFwCfgReadBytes (sizeof (*Config), Config); - return EFI_SUCCESS; -} - /** Initializes QEMU PPI memory region. @@ -88,29 +58,34 @@ QemuTpmInitPPI ( VOID ) { - EFI_STATUS Status; - QEMU_FWCFG_TPM_CONFIG Config; - EFI_PHYSICAL_ADDRESS PpiAddress64; - EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; - UINTN Idx; + EFI_STATUS Status; + TCG2_PHYSICAL_PRESENCE_PLATFORM_CONFIG Config; + EFI_PHYSICAL_ADDRESS PpiAddress64; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINTN Idx; if (mPpi != NULL) { return EFI_SUCCESS; } - Status = QemuTpmReadConfig (&Config); + Status = TpmPpiPlatformReadConfig (&Config); if (EFI_ERROR (Status)) { return Status; } - mPpi = (QEMU_TPM_PPI *)(UINTN)Config.PpiAddress; - if (mPpi == NULL) { + if ((Config.PpiAddress == 0) || (Config.PpiAddress > MAX_UINTN)) { return EFI_PROTOCOL_ERROR; } + PpiAddress64 = Config.PpiAddress; + mPpi = (QEMU_TPM_PPI *)(UINTN)PpiAddress64; DEBUG ((DEBUG_INFO, "[TPM2PP] mPpi=%p version=%d\n", mPpi, Config.TpmVersion)); - PpiAddress64 = (UINTN)mPpi; + if (PpiAddress64 > MAX_UINT64 - sizeof (*mPpi) + 1) { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi address overflows\n")); + goto InvalidPpiAddress; + } + if ((PpiAddress64 & ~(UINT64)EFI_PAGE_MASK) != ((PpiAddress64 + sizeof *mPpi - 1) & ~(UINT64)EFI_PAGE_MASK)) { @@ -124,19 +99,29 @@ QemuTpmInitPPI ( goto InvalidPpiAddress; } - if (!EFI_ERROR (Status) && - ((Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) && - (Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent))) - { - DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); - goto InvalidPpiAddress; + if (Config.PpiInMmio) { + if (!EFI_ERROR (Status) && + ((Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent))) + { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } + } else { + if (!EFI_ERROR (Status) && + ((Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeSystemMemory))) + { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } } for (Idx = 0; Idx < ARRAY_SIZE (mPpi->Func); Idx++) { mPpi->Func[Idx] = 0; } - if (Config.TpmVersion == QEMU_TPM_VERSION_2) { + if (Config.TpmVersion == Tcg2PhysicalPresenceTpmVersion20) { mPpi->Func[TCG2_PHYSICAL_PRESENCE_NO_ACTION] = TPM_PPI_FLAGS; mPpi->Func[TCG2_PHYSICAL_PRESENCE_CLEAR] = TPM_PPI_FLAGS; mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR] = TPM_PPI_FLAGS; @@ -365,31 +350,51 @@ Tcg2ReadUserKey ( EFI_STATUS Status; EFI_INPUT_KEY Key; UINT16 InputKey; + EFI_EVENT TimeoutEvent; + EFI_EVENT WaitList[2]; + UINTN WaitIndex; - InputKey = 0; - do { - Status = gBS->CheckEvent (gST->ConIn->WaitForKey); - if (!EFI_ERROR (Status)) { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - if (Key.ScanCode == SCAN_ESC) { - InputKey = Key.ScanCode; - } - - if ((Key.ScanCode == SCAN_F10) && !CautionKey) { - InputKey = Key.ScanCode; - } - - if ((Key.ScanCode == SCAN_F12) && CautionKey) { - InputKey = Key.ScanCode; - } - } - } while (InputKey == 0); - - if (InputKey != SCAN_ESC) { - return TRUE; + Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &TimeoutEvent); + if (EFI_ERROR (Status)) { + return FALSE; } - return FALSE; + Status = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + TCG2_PHYSICAL_PRESENCE_USER_CONFIRM_TIMEOUT_100NS + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (TimeoutEvent); + return FALSE; + } + + WaitList[0] = gST->ConIn->WaitForKey; + WaitList[1] = TimeoutEvent; + InputKey = 0; + + while (InputKey == 0) { + Status = gBS->WaitForEvent (ARRAY_SIZE (WaitList), WaitList, &WaitIndex); + if (EFI_ERROR (Status) || (WaitIndex == 1)) { + break; + } + + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR (Status)) { + continue; + } + + if ((Key.ScanCode == SCAN_ESC) || + ((Key.ScanCode == SCAN_F10) && !CautionKey) || + ((Key.ScanCode == SCAN_F12) && CautionKey)) + { + InputKey = Key.ScanCode; + } + } + + gBS->CloseEvent (TimeoutEvent); + + return (BOOLEAN)((InputKey != 0) && (InputKey != SCAN_ESC)); } /** diff --git a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf index 7cfc0804b2..904eafe295 100644 --- a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf +++ b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf @@ -57,12 +57,12 @@ HobLib MemoryAllocationLib PrintLib - QemuFwCfgLib Tpm2CommandLib UefiBootManagerLib UefiBootServicesTableLib UefiLib UefiRuntimeServicesTableLib + Tcg2PhysicalPresencePlatformLib [Protocols] gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES diff --git a/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c new file mode 100644 index 0000000000..abf30a7247 --- /dev/null +++ b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c @@ -0,0 +1,76 @@ +/** @file + Returns the platform specific configuration for the QEMU PPI. + + Caution: This module requires additional review when modified. + This driver will have external input - variable. + This external input must be validated carefully to avoid security issue. + +Copyright (C) 2018, Red Hat, Inc. +Copyright (c) 2018, IBM Corporation. All rights reserved.
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include + +/** + Reads QEMU PPI config from fw_cfg. + + @param[out] Config The config structure to fill in. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_INVALID_PARAMETER A required pointer argument was NULL. + @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size. +**/ +EFI_STATUS +EFIAPI +TpmPpiPlatformReadConfig ( + OUT TCG2_PHYSICAL_PRESENCE_PLATFORM_CONFIG *Config + ) +{ + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + QEMU_FWCFG_TPM_CONFIG QemuConfig; + + if (Config == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = QemuFwCfgFindFile ("etc/tpm/config", &FwCfgItem, &FwCfgSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (FwCfgSize != sizeof (QemuConfig)) { + return EFI_PROTOCOL_ERROR; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (sizeof (QemuConfig), &QemuConfig); + + Config->PpiAddress = QemuConfig.PpiAddress; + Config->PpiInMmio = TRUE; + + switch (QemuConfig.TpmVersion) { + case QEMU_TPM_VERSION_1_2: + Config->TpmVersion = Tcg2PhysicalPresenceTpmVersion12; + break; + + case QEMU_TPM_VERSION_2: + Config->TpmVersion = Tcg2PhysicalPresenceTpmVersion20; + break; + + default: + Config->TpmVersion = Tcg2PhysicalPresenceTpmVersionUnknown; + break; + } + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf new file mode 100644 index 0000000000..0ea0c08d4c --- /dev/null +++ b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf @@ -0,0 +1,36 @@ +## @file +# Returns the platform specific configuration for the QEMU PPI. +# +# Caution: This module requires additional review when modified. +# This driver will have external input - variable. +# This external input must be validated carefully to avoid security issue. +# +# Copyright (C) 2018, Red Hat, Inc. +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2PhysicalPresencePlatformLibQemu + FILE_GUID = 9336E7F0-6CA1-4E6D-A0E9-DFE5F077AA02 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresencePlatformLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DxeTcg2PhysicalPresencePlatformLib.c + +[Packages] + OvmfPkg/OvmfPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + QemuFwCfgLib diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index ce5d5dda4f..39731bdcb3 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -83,6 +83,10 @@ # QemuFwCfgLib|Include/Library/QemuFwCfgLib.h + ## @libraryclass Reads platform-specific TPM Physical Presence configuration. + # + Tcg2PhysicalPresencePlatformLib|Include/Library/Tcg2PhysicalPresencePlatformLib.h + ## @libraryclass S3 support for QEMU fw_cfg # QemuFwCfgS3Lib|Include/Library/QemuFwCfgS3Lib.h