diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 0ece3f20b5..f224a0b60c 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -237,6 +237,40 @@ instance is provided in-tree (MdeModulePkg/Library/GptLib/GptLib.inf). GptLib|MdeModulePkg/Library/GptLib/GptLib.inf +##### Breaking Change: New Tcg2PhysicalPresencePromptLib library class dependency + +- **Status**: Announced +- **Tracking Issue**: [tianocore/edk2#TBD](https://github.com/tianocore/edk2/issues/12832) +- **Pull Request**: [tianocore/edk2#12820](https://github.com/tianocore/edk2/pull/12820) +- **Type**: Source-Level (Non-removal) - Library class dependency addition (platform-implemented) + +**What changed**: `SecurityPkg` `DxeTcg2PhysicalPresenceLib` gained a required dependency on the new +`Tcg2PhysicalPresencePromptLib` library class declared in `SecurityPkg/SecurityPkg.dec`. Platforms +that build `DxeTcg2PhysicalPresenceLib` must resolve `Tcg2PhysicalPresencePromptLib` in their DSC or +the build fails with an unresolved library class. + +**Why it changed**: Previously, `DxeTcg2PhysicalPresenceLib` printed the Physical Presence confirmation prompt +directly to the console, giving platforms no clean way to substitute a platform-specific user-interaction mechanism. +Extracting the prompt behind a library class lets platforms provide their own prompt implementation without patching +`DxeTcg2PhysicalPresenceLib` and keeps the TPM 2.0 Physical Presence flow decoupled from any specific UI. + +**What replaces it**: Nothing is removed. `DxeTcg2PhysicalPresenceLib` now calls into the +`Tcg2PhysicalPresencePromptLib` interface, and `SecurityPkg` provides the console-based default instance for platforms +that do not implement their own. + +**How to migrate**: Platforms building `DxeTcg2PhysicalPresenceLib` must add a `Tcg2PhysicalPresencePromptLib` mapping +to their platform DSC `[LibraryClasses]` section. To keep the existing behavior, map to the in-tree console instance: + + Tcg2PhysicalPresencePromptLib|SecurityPkg/Library/Tcg2PhysicalPresencePromptLib/Tcg2PhysicalPresencePromptLibConsole.inf + +Platforms that want a custom prompt UI can instead provide their own instance implementing the +`Tcg2PhysicalPresencePromptLib` interface declared in +`SecurityPkg/Include/Library/Tcg2PhysicalPresencePromptLib.h` and map the library class to that instance in their DSC. + +**Breaking conditions**: Affects platforms and out-of-tree modules that build `SecurityPkg`'s +`DxeTcg2PhysicalPresenceLib` (`Tcg2PhysicalPresenceLib|SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf`). +Platforms that do not consume `DxeTcg2PhysicalPresenceLib` are unaffected. + ### edk2-stable202608: Behavioral Breaking Changes None diff --git a/SecurityPkg/Include/Library/Tcg2PhysicalPresencePromptLib.h b/SecurityPkg/Include/Library/Tcg2PhysicalPresencePromptLib.h new file mode 100644 index 0000000000..779df8c7c2 --- /dev/null +++ b/SecurityPkg/Include/Library/Tcg2PhysicalPresencePromptLib.h @@ -0,0 +1,47 @@ +/** @file -- Tcg2PhysicalPresencePromptLib.h +This library abstracts the action of prompting the user so that it may be overridden in a platform-specific way. +Rather than just printing to the screen. + +Copyright (c) Microsoft Corporation. +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#pragma once + +/** + Simple function to inform any callers of whether the lib is ready to present a prompt. + Since the prompt itself only returns TRUE or FALSE, make sure all other technical requirements + are out of the way. + + @retval EFI_SUCCESS Prompt is ready. + @retval EFI_NOT_READY Prompt is not ready. + @retval EFI_DEVICE_ERROR Library failed to prepare resources. + +**/ +EFI_STATUS +EFIAPI +Tcg2IsPromptReady ( + VOID + ); + +/** + Presents the given prompt string to the user and returns whether the user + confirmed the requested action. + + @param[in] PromptString The string that should occupy the body of the prompt. + @param[in] CautionKey If TRUE, the caller has instructed the user to press + the CAUTION key to confirm. + If FALSE, the caller has instructed the user to press + the ACCEPT key to confirm. + + @retval TRUE User confirmed the action. + @retval FALSE User rejected the action or a failure occurred. + +**/ +BOOLEAN +EFIAPI +Tcg2PromptForUserConfirmation ( + IN CHAR16 *PromptString, + IN BOOLEAN CautionKey + ); diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c index 93137c329b..9533fed37f 100644 --- a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c +++ b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c @@ -30,6 +30,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #define CONFIRM_BUFFER_SIZE 4096 @@ -251,50 +252,6 @@ Tcg2ExecutePhysicalPresence ( } } -/** - 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. -**/ -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. @@ -373,8 +330,7 @@ Tcg2UserConfirm ( UINTN BufSize; BOOLEAN CautionKey; BOOLEAN NoPpiInfo; - UINT16 Index; - CHAR16 DstStr[81]; + BOOLEAN Result; CHAR16 TempBuffer[1024]; CHAR16 TempBuffer2[1024]; EFI_TCG2_PROTOCOL *Tcg2Protocol; @@ -576,10 +532,12 @@ Tcg2UserConfirm ( 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); + Status = Tcg2IsPromptReady (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Tcg2IsPromptReady failed w/ Status: %r\n", Status)); + Result = FALSE; + } else { + Result = Tcg2PromptForUserConfirmation (ConfirmText, CautionKey); } FreePool (TmpStr1); @@ -587,11 +545,7 @@ Tcg2UserConfirm ( FreePool (ConfirmText); HiiRemovePackages (mTcg2PpStringPackHandle); - if (Tcg2ReadUserKey (CautionKey)) { - return TRUE; - } - - return FALSE; + return Result; } /** diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf index 4ee13090f9..b655fe1df0 100644 --- a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf +++ b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf @@ -51,6 +51,7 @@ Tpm2CommandLib Tcg2PpVendorLib VariablePolicyHelperLib + Tcg2PhysicalPresencePromptLib [Protocols] gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES diff --git a/SecurityPkg/Library/Tcg2PhysicalPresencePromptLib/Tcg2PhysicalPresencePromptLibConsole.c b/SecurityPkg/Library/Tcg2PhysicalPresencePromptLib/Tcg2PhysicalPresencePromptLibConsole.c new file mode 100644 index 0000000000..b7e21f62e7 --- /dev/null +++ b/SecurityPkg/Library/Tcg2PhysicalPresencePromptLib/Tcg2PhysicalPresencePromptLibConsole.c @@ -0,0 +1,115 @@ +/** @file + + This instance of the Tcg2PhysicalPresencePromptLib uses the + console and basic key input to prompt the user. + +Copyright (c) Microsoft Corporation. +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +/** + Simple function to inform any callers of whether the lib is ready to present a prompt. + Since the prompt itself only returns TRUE or FALSE, make sure all other technical requirements + are out of the way. + + @retval EFI_SUCCESS Prompt is ready. + @retval EFI_NOT_READY Prompt is not ready. + @retval EFI_DEVICE_ERROR Library failed to prepare resources. + +**/ +EFI_STATUS +EFIAPI +Tcg2IsPromptReady ( + VOID + ) +{ + return EFI_SUCCESS; +} + +/** + Read the specified key for user confirmation as specified by + TCG PC Client Platform Physical Presence Interface Specification + version 1.3 Revision 00.52. + + @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 +ReadUserKey ( + IN BOOLEAN CautionKey + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + + while (TRUE) { + Status = gBS->CheckEvent (gST->ConIn->WaitForKey); + if (EFI_ERROR (Status)) { + continue; + } + + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR (Status)) { + continue; + } + + if (Key.ScanCode == SCAN_ESC) { + return FALSE; + } + + if ((Key.ScanCode == SCAN_F10) && !CautionKey) { + return TRUE; + } + + if ((Key.ScanCode == SCAN_F12) && CautionKey) { + return TRUE; + } + } +} + +/** + Presents the given prompt string to the user and returns whether the user + confirmed the requested action. + + @param[in] PromptString The string that should occupy the body of the prompt. + @param[in] CautionKey If TRUE, the caller has instructed the user to press + the CAUTION key to confirm. + If FALSE, the caller has instructed the user to press + the ACCEPT key to confirm. + + @retval TRUE User confirmed the action. + @retval FALSE User rejected the action or a failure occurred. + +**/ +BOOLEAN +EFIAPI +Tcg2PromptForUserConfirmation ( + IN CHAR16 *PromptString, + IN BOOLEAN CautionKey + ) +{ + UINTN Index; + CHAR16 DstStr[81]; + + DstStr[80] = L'\0'; + for (Index = 0; Index < StrLen (PromptString); Index += 80) { + StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), PromptString + Index, sizeof (DstStr) / sizeof (CHAR16) - 1); + Print (DstStr); + } + + if (ReadUserKey (CautionKey)) { + return TRUE; + } + + return FALSE; +} diff --git a/SecurityPkg/Library/Tcg2PhysicalPresencePromptLib/Tcg2PhysicalPresencePromptLibConsole.inf b/SecurityPkg/Library/Tcg2PhysicalPresencePromptLib/Tcg2PhysicalPresencePromptLibConsole.inf new file mode 100644 index 0000000000..f580917731 --- /dev/null +++ b/SecurityPkg/Library/Tcg2PhysicalPresencePromptLib/Tcg2PhysicalPresencePromptLibConsole.inf @@ -0,0 +1,34 @@ +## @file +# This instance of the Tcg2PhysicalPresencePromptLib uses the +# console and basic key input to prompt the user. +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +[Defines] + INF_VERSION = 0x00010017 + BASE_NAME = Tcg2PhysicalPresencePromptLibConsole + FILE_GUID = 54A17646-E8E3-4BED-A7D8-D9E5E7684E85 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = Tcg2PhysicalPresencePromptLib|DXE_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + Tcg2PhysicalPresencePromptLibConsole.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseLib + UefiLib + UefiBootServicesTableLib diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec index 77c5815574..a8b10d91dd 100644 --- a/SecurityPkg/SecurityPkg.dec +++ b/SecurityPkg/SecurityPkg.dec @@ -103,6 +103,10 @@ # PlatformPKProtectionLib|Include/Library/PlatformPKProtectionLib.h + ## @libraryclass Provides platform abstraction for physical presence prompting. + # + Tcg2PhysicalPresencePromptLib|Include/Library/Tcg2PhysicalPresencePromptLib.h + ## @libraryclass Perform SPDM (following SPDM spec) and measure data to TPM (following TCG PFP spec). ## SpdmSecurityLib|Include/Library/SpdmSecurityLib.h diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc index fcb4c04973..9f9e67cafc 100644 --- a/SecurityPkg/SecurityPkg.dsc +++ b/SecurityPkg/SecurityPkg.dsc @@ -138,6 +138,7 @@ Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf + Tcg2PhysicalPresencePromptLib|SecurityPkg/Library/Tcg2PhysicalPresencePromptLib/Tcg2PhysicalPresencePromptLibConsole.inf [LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER,] HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf @@ -236,6 +237,7 @@ SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.inf + SecurityPkg/Library/Tcg2PhysicalPresencePromptLib/Tcg2PhysicalPresencePromptLibConsole.inf SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf