2018-05-18 14:23:03 +02:00
/** @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 . < BR >
Copyright ( c ) 2013 - 2016 , Intel Corporation . All rights reserved . < BR >
2019-04-04 01:06:33 +02:00
SPDX - License - Identifier : BSD - 2 - Clause - Patent
2018-05-18 14:23:03 +02:00
* */
# include <PiDxe.h>
# include <Guid/Tcg2PhysicalPresenceData.h>
# include <IndustryStandard/QemuTpm.h>
# include <Protocol/Tcg2Protocol.h>
# include <Library/BaseMemoryLib.h>
# include <Library/DebugLib.h>
# include <Library/DxeServicesTableLib.h>
# include <Library/HiiLib.h>
# include <Library/HobLib.h>
# include <Library/MemoryAllocationLib.h>
# include <Library/PrintLib.h>
# include <Library/QemuFwCfgLib.h>
# include <Library/Tpm2CommandLib.h>
# include <Library/UefiBootServicesTableLib.h>
# include <Library/UefiLib.h>
# include <Library/UefiRuntimeServicesTableLib.h>
# include <Library/Tcg2PhysicalPresenceLib.h>
# 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) \n New 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 ;
}