/** @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. | |
Tpm2ExecutePendingTpmRequest() will receive untrusted input and do validation. | |
Copyright (c) 2013 - 2020, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <PiDxe.h> | |
#include <Protocol/Tcg2Protocol.h> | |
#include <Protocol/VariableLock.h> | |
#include <Library/DebugLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/UefiRuntimeServicesTableLib.h> | |
#include <Library/UefiDriverEntryPoint.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Library/UefiLib.h> | |
#include <Library/MemoryAllocationLib.h> | |
#include <Library/PrintLib.h> | |
#include <Library/HiiLib.h> | |
#include <Library/HobLib.h> | |
#include <Guid/EventGroup.h> | |
#include <Guid/Tcg2PhysicalPresenceData.h> | |
#include <Library/Tpm2CommandLib.h> | |
#include <Library/Tcg2PhysicalPresenceLib.h> | |
#include <Library/Tcg2PpVendorLib.h> | |
#define CONFIRM_BUFFER_SIZE 4096 | |
EFI_HII_HANDLE mTcg2PpStringPackHandle; | |
/** | |
Get string by string id from HII Interface. | |
@param[in] Id String ID. | |
@retval CHAR16 * String from ID. | |
@retval NULL If error occurs. | |
**/ | |
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. | |
**/ | |
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. | |
@param[in, out] PpiFlags The physical presence interface flags. | |
@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. | |
**/ | |
UINT32 | |
Tcg2ExecutePhysicalPresence ( | |
IN TPM2B_AUTH *PlatformAuth OPTIONAL, | |
IN UINT32 CommandCode, | |
IN UINT32 CommandParameter, | |
IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *PpiFlags | |
) | |
{ | |
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_PP_REQUIRED_FOR_CLEAR_TRUE: | |
PpiFlags->PPFlags |= TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR; | |
return TCG_PP_OPERATION_RESPONSE_SUCCESS; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE: | |
PpiFlags->PPFlags &= ~TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR; | |
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; | |
} | |
case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID: | |
PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID; | |
return TCG_PP_OPERATION_RESPONSE_SUCCESS; | |
case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID: | |
PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID; | |
return TCG_PP_OPERATION_RESPONSE_SUCCESS; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE: | |
PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID; | |
return TCG_PP_OPERATION_RESPONSE_SUCCESS; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE: | |
PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID; | |
return TCG_PP_OPERATION_RESPONSE_SUCCESS; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE: | |
PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID; | |
return TCG_PP_OPERATION_RESPONSE_SUCCESS; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE: | |
PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID; | |
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. | |
**/ | |
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. | |
**/ | |
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. | |
**/ | |
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, DxeTcg2PhysicalPresenceLibStrings, 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_PP_REQUIRED_FOR_CLEAR_FALSE: | |
CautionKey = TRUE; | |
NoPpiInfo = TRUE; | |
TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR)); | |
TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR)); | |
UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); | |
FreePool (TmpStr1); | |
TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR)); | |
StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); | |
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; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE: | |
NoPpiInfo = TRUE; | |
TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_ENABLE_BLOCK_SID)); | |
TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_HEAD_STR)); | |
UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); | |
FreePool (TmpStr1); | |
break; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE: | |
NoPpiInfo = TRUE; | |
TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_DISABLE_BLOCK_SID)); | |
TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_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[in] TcgPpData EFI Tcg2 Physical Presence request data. | |
@param[in] Flags The physical presence interface flags. | |
@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. | |
**/ | |
BOOLEAN | |
Tcg2HaveValidTpmRequest ( | |
IN EFI_TCG2_PHYSICAL_PRESENCE *TcgPpData, | |
IN EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags, | |
OUT BOOLEAN *RequestConfirmed | |
) | |
{ | |
EFI_TCG2_PROTOCOL *Tcg2Protocol; | |
EFI_STATUS Status; | |
BOOLEAN IsRequestValid; | |
*RequestConfirmed = FALSE; | |
if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) { | |
// | |
// Need TCG2 protocol. | |
// | |
Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol); | |
if (EFI_ERROR (Status)) { | |
return FALSE; | |
} | |
} | |
switch (TcgPpData->PPRequest) { | |
case TCG2_PHYSICAL_PRESENCE_NO_ACTION: | |
*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: | |
if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) { | |
*RequestConfirmed = TRUE; | |
} | |
break; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE: | |
*RequestConfirmed = TRUE; | |
break; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE: | |
break; | |
case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS: | |
if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) { | |
*RequestConfirmed = TRUE; | |
} | |
break; | |
case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS: | |
if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) { | |
*RequestConfirmed = TRUE; | |
} | |
break; | |
case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS: | |
*RequestConfirmed = TRUE; | |
break; | |
case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID: | |
if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) { | |
*RequestConfirmed = TRUE; | |
} | |
break; | |
case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID: | |
if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) { | |
*RequestConfirmed = TRUE; | |
} | |
break; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE: | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE: | |
*RequestConfirmed = TRUE; | |
break; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE: | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE: | |
break; | |
default: | |
if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) { | |
IsRequestValid = Tcg2PpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed); | |
if (!IsRequestValid) { | |
return FALSE; | |
} else { | |
break; | |
} | |
} else { | |
// | |
// Wrong Physical Presence command | |
// | |
return FALSE; | |
} | |
} | |
if ((Flags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) != 0) { | |
// | |
// It had been confirmed in last boot, it doesn't need confirm again. | |
// | |
*RequestConfirmed = TRUE; | |
} | |
// | |
// Physical Presence command is correct | |
// | |
return TRUE; | |
} | |
/** | |
Check and execute the requested physical presence command. | |
Caution: This function may receive untrusted input. | |
TcgPpData variable is external input, so this function will validate | |
its data structure to be valid value. | |
@param[in] PlatformAuth platform auth value. NULL means no platform auth change. | |
@param[in, out] TcgPpData Pointer to the physical presence NV variable. | |
@param[in, out] Flags Pointer to the physical presence interface flags. | |
**/ | |
VOID | |
Tcg2ExecutePendingTpmRequest ( | |
IN TPM2B_AUTH *PlatformAuth OPTIONAL, | |
IN OUT EFI_TCG2_PHYSICAL_PRESENCE *TcgPpData, | |
IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *Flags | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN DataSize; | |
BOOLEAN RequestConfirmed; | |
EFI_TCG2_PHYSICAL_PRESENCE_FLAGS NewFlags; | |
BOOLEAN ResetRequired; | |
UINT32 NewPPFlags; | |
if (TcgPpData->PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) { | |
// | |
// No operation request | |
// | |
return; | |
} | |
if (!Tcg2HaveValidTpmRequest (TcgPpData, *Flags, &RequestConfirmed)) { | |
// | |
// Invalid operation request. | |
// | |
if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) { | |
TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_SUCCESS; | |
} else { | |
TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; | |
} | |
TcgPpData->LastPPRequest = TcgPpData->PPRequest; | |
TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION; | |
TcgPpData->PPRequestParameter = 0; | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); | |
Status = gRT->SetVariable ( | |
TCG2_PHYSICAL_PRESENCE_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, | |
DataSize, | |
TcgPpData | |
); | |
return; | |
} | |
ResetRequired = FALSE; | |
if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) { | |
NewFlags = *Flags; | |
NewPPFlags = NewFlags.PPFlags; | |
TcgPpData->PPResponse = Tcg2PpVendorLibExecutePendingRequest (PlatformAuth, TcgPpData->PPRequest, &NewPPFlags, &ResetRequired); | |
NewFlags.PPFlags = NewPPFlags; | |
} else { | |
if (!RequestConfirmed) { | |
// | |
// Print confirm text and wait for approval. | |
// | |
RequestConfirmed = Tcg2UserConfirm (TcgPpData->PPRequest, TcgPpData->PPRequestParameter); | |
} | |
// | |
// Execute requested physical presence command | |
// | |
TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT; | |
NewFlags = *Flags; | |
if (RequestConfirmed) { | |
TcgPpData->PPResponse = Tcg2ExecutePhysicalPresence ( | |
PlatformAuth, | |
TcgPpData->PPRequest, | |
TcgPpData->PPRequestParameter, | |
&NewFlags | |
); | |
} | |
} | |
// | |
// Save the flags if it is updated. | |
// | |
if (CompareMem (Flags, &NewFlags, sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS)) != 0) { | |
*Flags = NewFlags; | |
Status = gRT->SetVariable ( | |
TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, | |
sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS), | |
&NewFlags | |
); | |
} | |
// | |
// Clear request | |
// | |
if ((NewFlags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) == 0) { | |
TcgPpData->LastPPRequest = TcgPpData->PPRequest; | |
TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION; | |
TcgPpData->PPRequestParameter = 0; | |
} | |
// | |
// Save changes | |
// | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); | |
Status = gRT->SetVariable ( | |
TCG2_PHYSICAL_PRESENCE_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, | |
DataSize, | |
TcgPpData | |
); | |
if (EFI_ERROR (Status)) { | |
return; | |
} | |
if (TcgPpData->PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) { | |
return; | |
} | |
// | |
// Reset system to make new TPM settings in effect | |
// | |
switch (TcgPpData->LastPPRequest) { | |
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; | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE: | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE: | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE: | |
case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE: | |
return; | |
default: | |
if (TcgPpData->LastPPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) { | |
if (ResetRequired) { | |
break; | |
} else { | |
return; | |
} | |
} | |
if (TcgPpData->PPRequest != 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; | |
UINTN DataSize; | |
EFI_TCG2_PHYSICAL_PRESENCE TcgPpData; | |
EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol; | |
EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags; | |
// | |
// This flags variable controls whether physical presence is required for TPM command. | |
// It should be protected from malicious software. We set it as read-only variable here. | |
// | |
Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol); | |
if (!EFI_ERROR (Status)) { | |
Status = VariableLockProtocol->RequestToLock ( | |
VariableLockProtocol, | |
TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((DEBUG_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status)); | |
ASSERT_EFI_ERROR (Status); | |
} | |
} | |
// | |
// Check S4 resume | |
// | |
if (GetBootModeHob () == BOOT_ON_S4_RESUME) { | |
DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n")); | |
return; | |
} | |
// | |
// Initialize physical presence flags. | |
// | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS); | |
Status = gRT->GetVariable ( | |
TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
NULL, | |
&DataSize, | |
&PpiFlags | |
); | |
if (EFI_ERROR (Status)) { | |
PpiFlags.PPFlags = PcdGet32 (PcdTcg2PhysicalPresenceFlags); | |
Status = gRT->SetVariable ( | |
TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, | |
sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS), | |
&PpiFlags | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((DEBUG_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status)); | |
return; | |
} | |
DEBUG ((DEBUG_INFO, "[TPM2] Initial physical presence flags value is 0x%x\n", PpiFlags.PPFlags)); | |
} | |
// | |
// Initialize physical presence variable. | |
// | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); | |
Status = gRT->GetVariable ( | |
TCG2_PHYSICAL_PRESENCE_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
NULL, | |
&DataSize, | |
&TcgPpData | |
); | |
if (EFI_ERROR (Status)) { | |
ZeroMem ((VOID *)&TcgPpData, sizeof (TcgPpData)); | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); | |
Status = gRT->SetVariable ( | |
TCG2_PHYSICAL_PRESENCE_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, | |
DataSize, | |
&TcgPpData | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((DEBUG_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status)); | |
return; | |
} | |
} | |
DEBUG ((DEBUG_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest)); | |
// | |
// Execute pending TPM request. | |
// | |
Tcg2ExecutePendingTpmRequest (PlatformAuth, &TcgPpData, &PpiFlags); | |
DEBUG ((DEBUG_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags)); | |
} | |
/** | |
Check if the pending TPM request needs user input to confirm. | |
The TPM request may come from OS. This API will check if TPM request exists and need user | |
input to confirmation. | |
@retval TRUE TPM needs input to confirm user physical presence. | |
@retval FALSE TPM doesn't need input to confirm user physical presence. | |
**/ | |
BOOLEAN | |
EFIAPI | |
Tcg2PhysicalPresenceLibNeedUserConfirm ( | |
VOID | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_TCG2_PHYSICAL_PRESENCE TcgPpData; | |
UINTN DataSize; | |
BOOLEAN RequestConfirmed; | |
EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags; | |
// | |
// Check S4 resume | |
// | |
if (GetBootModeHob () == BOOT_ON_S4_RESUME) { | |
DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n")); | |
return FALSE; | |
} | |
// | |
// Check Tpm requests | |
// | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); | |
Status = gRT->GetVariable ( | |
TCG2_PHYSICAL_PRESENCE_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
NULL, | |
&DataSize, | |
&TcgPpData | |
); | |
if (EFI_ERROR (Status)) { | |
return FALSE; | |
} | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS); | |
Status = gRT->GetVariable ( | |
TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
NULL, | |
&DataSize, | |
&PpiFlags | |
); | |
if (EFI_ERROR (Status)) { | |
return FALSE; | |
} | |
if (TcgPpData.PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) { | |
// | |
// No operation request | |
// | |
return FALSE; | |
} | |
if (!Tcg2HaveValidTpmRequest (&TcgPpData, PpiFlags, &RequestConfirmed)) { | |
// | |
// Invalid operation request. | |
// | |
return FALSE; | |
} | |
if (!RequestConfirmed) { | |
// | |
// Need UI to confirm | |
// | |
return TRUE; | |
} | |
return FALSE; | |
} | |
/** | |
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; | |
UINTN DataSize; | |
EFI_TCG2_PHYSICAL_PRESENCE PpData; | |
DEBUG ((DEBUG_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n")); | |
// | |
// Get the Physical Presence variable | |
// | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); | |
Status = gRT->GetVariable ( | |
TCG2_PHYSICAL_PRESENCE_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
NULL, | |
&DataSize, | |
&PpData | |
); | |
if (EFI_ERROR (Status)) { | |
*MostRecentRequest = 0; | |
*Response = 0; | |
DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status)); | |
return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE; | |
} | |
*MostRecentRequest = PpData.LastPPRequest; | |
*Response = PpData.PPResponse; | |
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; | |
UINTN DataSize; | |
EFI_TCG2_PHYSICAL_PRESENCE PpData; | |
EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags; | |
DEBUG ((DEBUG_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter)); | |
// | |
// Get the Physical Presence variable | |
// | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); | |
Status = gRT->GetVariable ( | |
TCG2_PHYSICAL_PRESENCE_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
NULL, | |
&DataSize, | |
&PpData | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status)); | |
return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE; | |
} | |
if ((OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) && | |
(OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN)) | |
{ | |
return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED; | |
} | |
if ((PpData.PPRequest != OperationRequest) || | |
(PpData.PPRequestParameter != RequestParameter)) | |
{ | |
PpData.PPRequest = (UINT8)OperationRequest; | |
PpData.PPRequestParameter = RequestParameter; | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); | |
Status = gRT->SetVariable ( | |
TCG2_PHYSICAL_PRESENCE_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, | |
DataSize, | |
&PpData | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((DEBUG_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status)); | |
return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE; | |
} | |
} | |
if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) { | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS); | |
Status = gRT->GetVariable ( | |
TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
NULL, | |
&DataSize, | |
&Flags | |
); | |
if (EFI_ERROR (Status)) { | |
Flags.PPFlags = PcdGet32 (PcdTcg2PhysicalPresenceFlags); | |
} | |
return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter); | |
} | |
return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS; | |
} | |
/** | |
Return TPM2 ManagementFlags set by PP interface. | |
@retval ManagementFlags TPM2 Management Flags. | |
**/ | |
UINT32 | |
EFIAPI | |
Tcg2PhysicalPresenceLibGetManagementFlags ( | |
VOID | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags; | |
UINTN DataSize; | |
DEBUG ((DEBUG_INFO, "[TPM2] GetManagementFlags\n")); | |
DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS); | |
Status = gRT->GetVariable ( | |
TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, | |
&gEfiTcg2PhysicalPresenceGuid, | |
NULL, | |
&DataSize, | |
&PpiFlags | |
); | |
if (EFI_ERROR (Status)) { | |
PpiFlags.PPFlags = PcdGet32 (PcdTcg2PhysicalPresenceFlags); | |
} | |
return PpiFlags.PPFlags; | |
} |