From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../DxeTcg2PhysicalPresenceLib.c | 917 +++++++++++++++++++++ .../DxeTcg2PhysicalPresenceLib.inf | 71 ++ .../PhysicalPresenceStrings.uni | 38 + 3 files changed, 1026 insertions(+) create mode 100644 roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c create mode 100644 roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf create mode 100644 roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/PhysicalPresenceStrings.uni (limited to 'roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu') diff --git a/roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c b/roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c new file mode 100644 index 000000000..00d76ba2c --- /dev/null +++ b/roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c @@ -0,0 +1,917 @@ +/** @file + Execute pending TPM2 requests from OS or BIOS. + + 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. + + Tcg2ExecutePendingTpmRequest() will receive untrusted input and do validation. + +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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define CONFIRM_BUFFER_SIZE 4096 + +EFI_HII_HANDLE mTcg2PpStringPackHandle; + +#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. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR PPI address is invalid. +**/ +STATIC +EFI_STATUS +QemuTpmInitPPI ( + VOID + ) +{ + EFI_STATUS Status; + QEMU_FWCFG_TPM_CONFIG Config; + EFI_PHYSICAL_ADDRESS PpiAddress64; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINTN Idx; + + if (mPpi != NULL) { + return EFI_SUCCESS; + } + + Status = QemuTpmReadConfig (&Config); + if (EFI_ERROR (Status)) { + return Status; + } + + mPpi = (QEMU_TPM_PPI *)(UINTN)Config.PpiAddress; + if (mPpi == NULL) { + return EFI_PROTOCOL_ERROR; + } + + DEBUG ((DEBUG_INFO, "[TPM2PP] mPpi=%p version=%d\n", mPpi, Config.TpmVersion)); + + PpiAddress64 = (UINTN)mPpi; + if ((PpiAddress64 & ~(UINT64)EFI_PAGE_MASK) != + ((PpiAddress64 + sizeof *mPpi - 1) & ~(UINT64)EFI_PAGE_MASK)) { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi crosses a page boundary\n")); + goto InvalidPpiAddress; + } + + Status = gDS->GetMemorySpaceDescriptor (PpiAddress64, &Descriptor); + if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) { + ASSERT_EFI_ERROR (Status); + 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; + } + + for (Idx = 0; Idx < ARRAY_SIZE (mPpi->Func); Idx++) { + mPpi->Func[Idx] = 0; + } + if (Config.TpmVersion == QEMU_TPM_VERSION_2) { + 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; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_CHANGE_EPS] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID] = TPM_PPI_FLAGS; + } + + if (mPpi->In == 0) { + mPpi->In = 1; + mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->LastRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->NextStep = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + } + + return EFI_SUCCESS; + +InvalidPpiAddress: + mPpi = NULL; + return EFI_PROTOCOL_ERROR; +} + + +/** + Get string by string id from HII Interface. + + @param[in] Id String ID. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +STATIC +CHAR16 * +Tcg2PhysicalPresenceGetStringById ( + IN EFI_STRING_ID Id + ) +{ + return HiiGetString (mTcg2PpStringPackHandle, Id, NULL); +} + + +/** + Send ClearControl and Clear command to TPM. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_TIMEOUT The register can't run into the expected status in time. + @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small. + @retval EFI_DEVICE_ERROR Unexpected device behavior. + +**/ +EFI_STATUS +EFIAPI +Tpm2CommandClear ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL + ) +{ + EFI_STATUS Status; + TPMS_AUTH_COMMAND *AuthSession; + TPMS_AUTH_COMMAND LocalAuthSession; + + if (PlatformAuth == NULL) { + AuthSession = NULL; + } else { + AuthSession = &LocalAuthSession; + ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession)); + LocalAuthSession.sessionHandle = TPM_RS_PW; + LocalAuthSession.hmac.size = PlatformAuth->size; + CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size); + } + + DEBUG ((DEBUG_INFO, "Tpm2ClearControl ... \n")); + Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO); + DEBUG ((DEBUG_INFO, "Tpm2ClearControl - %r\n", Status)); + if (EFI_ERROR (Status)) { + goto Done; + } + DEBUG ((DEBUG_INFO, "Tpm2Clear ... \n")); + Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession); + DEBUG ((DEBUG_INFO, "Tpm2Clear - %r\n", Status)); + +Done: + ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac)); + return Status; +} + + +/** + Change EPS. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. + + @retval EFI_SUCCESS Operation completed successfully. +**/ +STATIC +EFI_STATUS +Tpm2CommandChangeEps ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL + ) +{ + EFI_STATUS Status; + TPMS_AUTH_COMMAND *AuthSession; + TPMS_AUTH_COMMAND LocalAuthSession; + + if (PlatformAuth == NULL) { + AuthSession = NULL; + } else { + AuthSession = &LocalAuthSession; + ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession)); + LocalAuthSession.sessionHandle = TPM_RS_PW; + LocalAuthSession.hmac.size = PlatformAuth->size; + CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size); + } + + Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession); + DEBUG ((DEBUG_INFO, "Tpm2ChangeEPS - %r\n", Status)); + + ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac)); + return Status; +} + + +/** + Execute physical presence operation requested by the OS. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. + @param[in] CommandCode Physical presence operation value. + @param[in] CommandParameter Physical presence operation parameter. + + @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Unknown physical presence operation. + @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Error occurred during sending command to TPM or + receiving response from TPM. + @retval Others Return code from the TPM device after command execution. +**/ +STATIC +UINT32 +Tcg2ExecutePhysicalPresence ( + IN TPM2B_AUTH *PlatformAuth, OPTIONAL + IN UINT32 CommandCode, + IN UINT32 CommandParameter + ) +{ + EFI_STATUS Status; + EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap; + UINT32 ActivePcrBanks; + + switch (CommandCode) { + case TCG2_PHYSICAL_PRESENCE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3: + Status = Tpm2CommandClear (PlatformAuth); + if (EFI_ERROR (Status)) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } else { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } + + case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS: + Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks); + ASSERT_EFI_ERROR (Status); + + // + // PP spec requirements: + // Firmware should check that all requested (set) hashing algorithms are supported with respective PCR banks. + // Firmware has to ensure that at least one PCR banks is active. + // If not, an error is returned and no action is taken. + // + if (CommandParameter == 0 || (CommandParameter & (~TpmHashAlgorithmBitmap)) != 0) { + DEBUG((DEBUG_ERROR, "PCR banks %x to allocate are not supported by TPM. Skip operation\n", CommandParameter)); + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } + + Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, CommandParameter); + if (EFI_ERROR (Status)) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } else { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } + + case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS: + Status = Tpm2CommandChangeEps (PlatformAuth); + if (EFI_ERROR (Status)) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } else { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } + + case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS: + Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks); + ASSERT_EFI_ERROR (Status); + Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, TpmHashAlgorithmBitmap); + if (EFI_ERROR (Status)) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } else { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } + + default: + if (CommandCode <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } else { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } + } +} + + +/** + Read the specified key for user confirmation. + + @param[in] CautionKey If true, F12 is used as confirm key; + If false, F10 is used as confirm key. + + @retval TRUE User confirmed the changes by input. + @retval FALSE User discarded the changes. +**/ +STATIC +BOOLEAN +Tcg2ReadUserKey ( + IN BOOLEAN CautionKey + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + UINT16 InputKey; + + 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; + } + + return FALSE; +} + + +/** + Fill Buffer With BootHashAlg. + + @param[in] Buffer Buffer to be filled. + @param[in] BufferSize Size of buffer. + @param[in] BootHashAlg BootHashAlg. + +**/ +STATIC +VOID +Tcg2FillBufferWithBootHashAlg ( + IN UINT16 *Buffer, + IN UINTN BufferSize, + IN UINT32 BootHashAlg + ) +{ + Buffer[0] = 0; + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } +} + + +/** + Display the confirm text and get user confirmation. + + @param[in] TpmPpCommand The requested TPM physical presence command. + @param[in] TpmPpCommandParameter The requested TPM physical presence command parameter. + + @retval TRUE The user has confirmed the changes. + @retval FALSE The user doesn't confirm the changes. +**/ +STATIC +BOOLEAN +Tcg2UserConfirm ( + IN UINT32 TpmPpCommand, + IN UINT32 TpmPpCommandParameter + ) +{ + CHAR16 *ConfirmText; + CHAR16 *TmpStr1; + CHAR16 *TmpStr2; + UINTN BufSize; + BOOLEAN CautionKey; + BOOLEAN NoPpiInfo; + UINT16 Index; + CHAR16 DstStr[81]; + CHAR16 TempBuffer[1024]; + CHAR16 TempBuffer2[1024]; + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability; + UINT32 CurrentPCRBanks; + EFI_STATUS Status; + + TmpStr2 = NULL; + CautionKey = FALSE; + NoPpiInfo = FALSE; + BufSize = CONFIRM_BUFFER_SIZE; + ConfirmText = AllocateZeroPool (BufSize); + ASSERT (ConfirmText != NULL); + + mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, Tcg2PhysicalPresenceLibQemuStrings, NULL); + ASSERT (mTcg2PpStringPackHandle != NULL); + + switch (TpmPpCommand) { + + case TCG2_PHYSICAL_PRESENCE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3: + CautionKey = TRUE; + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + break; + + case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS: + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); + ASSERT_EFI_ERROR (Status); + + ProtocolCapability.Size = sizeof(ProtocolCapability); + Status = Tcg2Protocol->GetCapability ( + Tcg2Protocol, + &ProtocolCapability + ); + ASSERT_EFI_ERROR (Status); + + Status = Tcg2Protocol->GetActivePcrBanks ( + Tcg2Protocol, + &CurrentPCRBanks + ); + ASSERT_EFI_ERROR (Status); + + CautionKey = TRUE; + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + Tcg2FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), TpmPpCommandParameter); + Tcg2FillBufferWithBootHashAlg (TempBuffer2, sizeof(TempBuffer2), CurrentPCRBanks); + + TmpStr1 = AllocateZeroPool (BufSize); + ASSERT (TmpStr1 != NULL); + UnicodeSPrint (TmpStr1, BufSize, L"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks, TempBuffer2, TpmPpCommandParameter, TempBuffer); + + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + break; + + case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS: + CautionKey = TRUE; + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + break; + + case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID: + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ENABLE_BLOCK_SID)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + break; + + case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID: + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_DISABLE_BLOCK_SID)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + break; + + default: + ; + } + + if (TmpStr2 == NULL) { + FreePool (ConfirmText); + return FALSE; + } + + if (TpmPpCommand < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) { + if (CautionKey) { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY)); + } else { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + } + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + if (NoPpiInfo) { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + } + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY)); + } else { + if (CautionKey) { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY)); + } else { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY)); + } + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + if (NoPpiInfo) { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + } + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY)); + } + BufSize -= StrSize (ConfirmText); + UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2); + + DstStr[80] = L'\0'; + for (Index = 0; Index < StrLen (ConfirmText); Index += 80) { + StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1); + Print (DstStr); + } + + FreePool (TmpStr1); + FreePool (TmpStr2); + FreePool (ConfirmText); + HiiRemovePackages (mTcg2PpStringPackHandle); + + if (Tcg2ReadUserKey (CautionKey)) { + return TRUE; + } + + return FALSE; +} + + +/** + Check if there is a valid physical presence command request. Also updates parameter value + to whether the requested physical presence command already confirmed by user + + @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI. + True, it indicates the command doesn't require user confirm, or already confirmed + in last boot cycle by user. + False, it indicates the command need user confirm from UI. + + @retval TRUE Physical Presence operation command is valid. + @retval FALSE Physical Presence operation command is invalid. + +**/ +STATIC +BOOLEAN +Tcg2HaveValidTpmRequest ( + OUT BOOLEAN *RequestConfirmed + ) +{ + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_STATUS Status; + + *RequestConfirmed = FALSE; + + if (mPpi->Request <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) { + // + // Need TCG2 protocol. + // + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); + if (EFI_ERROR (Status)) { + return FALSE; + } + } + + switch (mPpi->Request) { + case TCG2_PHYSICAL_PRESENCE_NO_ACTION: + case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS: + *RequestConfirmed = TRUE; + return TRUE; + + case TCG2_PHYSICAL_PRESENCE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3: + case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS: + case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS: + case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID: + case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID: + break; + + default: + // + // Wrong Physical Presence command + // + return FALSE; + } + + // + // Physical Presence command is correct + // + return TRUE; +} + + +/** + Check and execute the requested physical presence command. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. +**/ +STATIC +VOID +Tcg2ExecutePendingTpmRequest ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL + ) +{ + BOOLEAN RequestConfirmed; + + if (mPpi->Request == TCG2_PHYSICAL_PRESENCE_NO_ACTION) { + // + // No operation request + // + return; + } + + if (!Tcg2HaveValidTpmRequest (&RequestConfirmed)) { + // + // Invalid operation request. + // + if (mPpi->Request <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) { + mPpi->Response = TCG_PP_OPERATION_RESPONSE_SUCCESS; + } else { + mPpi->Response = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } + mPpi->LastRequest = mPpi->Request; + mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->RequestParameter = 0; + return; + } + + if (!RequestConfirmed) { + // + // Print confirm text and wait for approval. + // + RequestConfirmed = Tcg2UserConfirm (mPpi->Request, mPpi->RequestParameter); + } + + // + // Execute requested physical presence command + // + mPpi->Response = TCG_PP_OPERATION_RESPONSE_USER_ABORT; + if (RequestConfirmed) { + mPpi->Response = Tcg2ExecutePhysicalPresence ( + PlatformAuth, + mPpi->Request, + mPpi->RequestParameter + ); + } + + // + // Clear request + // + mPpi->LastRequest = mPpi->Request; + mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->RequestParameter = 0; + + if (mPpi->Response == TCG_PP_OPERATION_RESPONSE_USER_ABORT) { + return; + } + + // + // Reset system to make new TPM settings in effect + // + switch (mPpi->LastRequest) { + case TCG2_PHYSICAL_PRESENCE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3: + case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS: + case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS: + case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS: + break; + + case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID: + case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID: + break; + + default: + if (mPpi->Request != TCG2_PHYSICAL_PRESENCE_NO_ACTION) { + break; + } + return; + } + + Print (L"Rebooting system to make TPM2 settings in effect\n"); + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + ASSERT (FALSE); +} + + +/** + Check and execute the pending TPM request. + + The TPM request may come from OS or BIOS. This API will display request information and wait + for user confirmation if TPM request exists. The TPM request will be sent to TPM device after + the TPM request is confirmed, and one or more reset may be required to make TPM request to + take effect. + + This API should be invoked after console in and console out are all ready as they are required + to display request information and get user input to confirm the request. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. +**/ +VOID +EFIAPI +Tcg2PhysicalPresenceLibProcessRequest ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL + ) +{ + EFI_STATUS Status; + + Status = QemuTpmInitPPI (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[TPM2PP] no PPI\n")); + return ; + } + + // + // Check S4 resume + // + if (GetBootModeHob () == BOOT_ON_S4_RESUME) { + DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n")); + return ; + } + + DEBUG ((DEBUG_INFO, "[TPM2PP] PPRequest=%x (PPRequestParameter=%x)\n", mPpi->Request, mPpi->RequestParameter)); + Tcg2ExecutePendingTpmRequest (PlatformAuth); +} + + +/** + The handler for TPM physical presence function: + Return TPM Operation Response to OS Environment. + + @param[out] MostRecentRequest Most recent operation request. + @param[out] Response Response to the most recent operation request. + + @return Return Code for Return TPM Operation Response to OS Environment. +**/ +UINT32 +EFIAPI +Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction ( + OUT UINT32 *MostRecentRequest, + OUT UINT32 *Response + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "[TPM2PP] ReturnOperationResponseToOsFunction\n")); + + Status = QemuTpmInitPPI (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[TPM2PP] no PPI\n")); + *MostRecentRequest = 0; + *Response = 0; + return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE; + } + + *MostRecentRequest = mPpi->LastRequest; + *Response = mPpi->Response; + + return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS; +} + + +/** + The handler for TPM physical presence function: + Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. + + Caution: This function may receive untrusted input. + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] RequestParameter TPM physical presence operation request parameter. + + @return Return Code for Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. +**/ +UINT32 +EFIAPI +Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction ( + IN UINT32 OperationRequest, + IN UINT32 RequestParameter + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "[TPM2PP] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter)); + + Status = QemuTpmInitPPI (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[TPM2PP] no PPI\n")); + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE; + } + + mPpi->Request = OperationRequest; + mPpi->RequestParameter = RequestParameter; + + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS; +} diff --git a/roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf b/roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf new file mode 100644 index 000000000..85ce0e2b2 --- /dev/null +++ b/roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf @@ -0,0 +1,71 @@ +## @file +# Executes TPM 2.0 requests from OS or BIOS +# +# This library will check and execute TPM 2.0 request from OS or +# BIOS. The request may ask for user confirmation before +# execution. It is a clone of +# "SecurityPkg/Library/DxeTcg2PhysicalPresenceLib" with: +# +# - removed all the functions that are unreachable from +# Tcg2PhysicalPresenceLibProcessRequest() [called from platform +# BDS], or SubmitRequestToPreOSFunction() and +# ReturnOperationResponseToOsFunction() [called from Tcg2Dxe]. +# +# - replaced everything that's related to the +# TCG2_PHYSICAL_PRESENCE*_VARIABLE variables, with direct access to +# the QEMU structures. +# +# 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 = Tcg2PhysicalPresenceLibQemu + FILE_GUID = 41D3E698-9EEC-41FF-9CBB-5FE79A0CF326 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresenceLib|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] + DxeTcg2PhysicalPresenceLib.c + PhysicalPresenceStrings.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + DxeServicesTableLib + HiiLib + HobLib + MemoryAllocationLib + PrintLib + QemuFwCfgLib + Tpm2CommandLib + UefiBootServicesTableLib + UefiLib + UefiRuntimeServicesTableLib + +[Protocols] + gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + ## SOMETIMES_CONSUMES ## HII + gEfiTcg2PhysicalPresenceGuid diff --git a/roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/PhysicalPresenceStrings.uni b/roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/PhysicalPresenceStrings.uni new file mode 100644 index 000000000..ea9ff41a1 --- /dev/null +++ b/roms/edk2/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/PhysicalPresenceStrings.uni @@ -0,0 +1,38 @@ +/** @file + String definitions for TPM 2.0 physical presence confirm text. + +Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#langdef en-US "English" + +#string TPM_HEAD_STR #language en-US "A configuration change was requested to %s this computer's TPM (Trusted Platform Module)\n\n" + +#string TPM_ACCEPT_KEY #language en-US "Press F10 " +#string TPM_CAUTION_KEY #language en-US "Press F12 " +#string TPM_REJECT_KEY #language en-US "to %s the TPM \nPress ESC to reject this change request and continue\n" + +#string TPM_CLEAR #language en-US "clear" +#string TPM_SET_PCR_BANKS #language en-US "change the boot measurements to use PCR bank(s) of" +#string TPM_CHANGE_EPS #language en-US "clear and change identity of" + +#string TPM_NO_PPI_INFO #language en-US "to approve future Operating System requests " + +#string TPM_WARNING_CLEAR #language en-US "WARNING: Clearing erases information stored on the TPM. You will lose all created keys and access to data encrypted by these keys. " +#string TPM_WARNING_SET_PCR_BANKS_1 #language en-US "WARNING: Changing the PCR bank(s) of the boot measurements may prevent the Operating System from properly processing the measurements. Please check if your Operating System supports the new PCR bank(s).\n\n" +#string TPM_WARNING_SET_PCR_BANKS_2 #language en-US "WARNING: Secrets in the TPM that are bound to the boot state of your machine may become unusable.\n\n" +#string TPM_WARNING_CHANGE_EPS_1 #language en-US "WARNING: Clearing erases information stored on the TPM. You will lose all created keys and access to data encrypted with these keys.\n\n" +#string TPM_WARNING_CHANGE_EPS_2 #language en-US "WARNING: Changing the identity of the TPM may require additional steps to establish trust into the new identity.\n\n" + +#string TCG_STORAGE_HEAD_STR #language en-US "A configuration change was requested to %s on subsequent boots\n\n" + +#string TCG_STORAGE_ACCEPT_KEY #language en-US "Press F10 " +#string TCG_STORAGE_CAUTION_KEY #language en-US "Press F12 " +#string TCG_STORAGE_REJECT_KEY #language en-US "to %s\nPress ESC to reject this change request and continue\n" + +#string TCG_STORAGE_NO_PPI_INFO #language en-US "to approve future Operating System requests " + +#string TCG_STORAGE_ENABLE_BLOCK_SID #language en-US "issue a Block SID authentication command" +#string TCG_STORAGE_DISABLE_BLOCK_SID #language en-US "disable issuing a Block SID authentication command" -- cgit