From 1abfa4ce4835639c66ae82cc0d72cffcf3f28b6b Mon Sep 17 00:00:00 2001 From: "Yao, Jiewen" Date: Thu, 13 Aug 2015 08:24:17 +0000 Subject: [PATCH] Add TPM2 support defined in trusted computing group. TCG EFI Protocol Specification for TPM Family 2.0 Revision 1.0 Version 9 at http://www.trustedcomputinggroup.org/resources/tcg_efi_protocol_specification TCG Physical Presence Interface Specification Version 1.30, Revision 00.52 at http://www.trustedcomputinggroup.org/resources/tcg_physical_presence_interface_specification Add Tcg2XXX, similar file/directory as TrEEXXX. Old TrEE driver/library can be deprecated. 1) Add Tcg2Pei/Dxe/Smm driver to log event and provide services. 2) Add Dxe/Pei/SmmTcg2PhysicalPresenceLib to support TCG PP. 3) Update Tpm2 library to use TCG2 protocol instead of TrEE protocol. Test Win8/Win10 with SecureBoot enabled, PCR7 shows bound. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: "Yao, Jiewen" Reviewed-by: "Zhang, Chao B" git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18219 6f19259b-4bc3-4df7-8a09-765794883524 --- SecurityPkg/Include/Guid/Tcg2ConfigHii.h | 25 + .../Include/Guid/Tcg2PhysicalPresenceData.h | 47 + SecurityPkg/Include/Guid/TcgEventHob.h | 9 +- .../Include/Library/Tcg2PhysicalPresenceLib.h | 160 + SecurityPkg/Include/Library/Tcg2PpVendorLib.h | 129 + .../DxeTcg2PhysicalPresenceLib.c | 1245 ++++++++ .../DxeTcg2PhysicalPresenceLib.inf | 69 + .../DxeTcg2PhysicalPresenceLib.uni | Bin 0 -> 2938 bytes .../PhysicalPresenceStrings.uni | Bin 0 -> 10998 bytes .../DxeTpm2MeasureBootLib.c | 148 +- .../DxeTpm2MeasureBootLib.inf | 2 +- .../DxeTpmMeasurementLib.c | 36 +- .../DxeTpmMeasurementLib.inf | 2 +- .../HashLibBaseCryptoRouterCommon.c | 12 +- .../HashLibBaseCryptoRouterDxe.c | 27 +- .../HashLibBaseCryptoRouterDxe.inf | 5 +- .../HashLibBaseCryptoRouterPei.c | 27 +- .../HashLibBaseCryptoRouterPei.inf | 5 +- SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c | 11 +- .../PeiTcg2PhysicalPresenceLib.c | 59 + .../PeiTcg2PhysicalPresenceLib.inf | 52 + .../PeiTcg2PhysicalPresenceLib.uni | Bin 0 -> 1754 bytes .../SmmTcg2PhysicalPresenceLib.c | 314 ++ .../SmmTcg2PhysicalPresenceLib.inf | 56 + .../SmmTcg2PhysicalPresenceLib.uni | Bin 0 -> 2706 bytes .../Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c | 133 + .../Tcg2PpVendorLibNull.inf | 37 + .../Tcg2PpVendorLibNull.uni | Bin 0 -> 1810 bytes .../Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c | 125 + .../Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf | 46 + .../Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.uni | Bin 0 -> 1970 bytes SecurityPkg/SecurityPkg.dec | 21 + SecurityPkg/SecurityPkg.dsc | 61 +- SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr | 167 ++ SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c | 280 ++ SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf | 87 + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.uni | Bin 0 -> 2124 bytes .../Tcg/Tcg2Config/Tcg2ConfigDxeExtra.uni | Bin 0 -> 1382 bytes SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c | 610 ++++ SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.h | 197 ++ SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h | 94 + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf | 78 + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni | Bin 0 -> 2206 bytes .../Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni | Bin 0 -> 1382 bytes SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c | 158 + .../Tcg/Tcg2Config/Tcg2ConfigStrings.uni | Bin 0 -> 13376 bytes SecurityPkg/Tcg/Tcg2Config/TpmDetection.c | 129 + SecurityPkg/Tcg/Tcg2Dxe/MeasureBootPeCoff.c | 357 +++ SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c | 2563 +++++++++++++++++ SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf | 112 + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.uni | Bin 0 -> 2320 bytes SecurityPkg/Tcg/Tcg2Dxe/Tcg2DxeExtra.uni | Bin 0 -> 1334 bytes SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c | 946 ++++++ SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf | 89 + SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.uni | Bin 0 -> 1876 bytes SecurityPkg/Tcg/Tcg2Pei/Tcg2PeiExtra.uni | Bin 0 -> 1342 bytes SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c | 397 +++ SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h | 87 + SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf | 80 + SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.uni | Bin 0 -> 3270 bytes SecurityPkg/Tcg/Tcg2Smm/Tcg2SmmExtra.uni | Bin 0 -> 1342 bytes SecurityPkg/Tcg/Tcg2Smm/Tpm.asl | 359 +++ 62 files changed, 9524 insertions(+), 129 deletions(-) create mode 100644 SecurityPkg/Include/Guid/Tcg2ConfigHii.h create mode 100644 SecurityPkg/Include/Guid/Tcg2PhysicalPresenceData.h create mode 100644 SecurityPkg/Include/Library/Tcg2PhysicalPresenceLib.h create mode 100644 SecurityPkg/Include/Library/Tcg2PpVendorLib.h create mode 100644 SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c create mode 100644 SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf create mode 100644 SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni create mode 100644 SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni create mode 100644 SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.c create mode 100644 SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.inf create mode 100644 SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.uni create mode 100644 SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c create mode 100644 SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf create mode 100644 SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.uni create mode 100644 SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c create mode 100644 SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf create mode 100644 SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.uni create mode 100644 SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c create mode 100644 SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf create mode 100644 SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.uni create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.uni create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxeExtra.uni create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.h create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c create mode 100644 SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni create mode 100644 SecurityPkg/Tcg/Tcg2Config/TpmDetection.c create mode 100644 SecurityPkg/Tcg/Tcg2Dxe/MeasureBootPeCoff.c create mode 100644 SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c create mode 100644 SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf create mode 100644 SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.uni create mode 100644 SecurityPkg/Tcg/Tcg2Dxe/Tcg2DxeExtra.uni create mode 100644 SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c create mode 100644 SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf create mode 100644 SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.uni create mode 100644 SecurityPkg/Tcg/Tcg2Pei/Tcg2PeiExtra.uni create mode 100644 SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c create mode 100644 SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h create mode 100644 SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf create mode 100644 SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.uni create mode 100644 SecurityPkg/Tcg/Tcg2Smm/Tcg2SmmExtra.uni create mode 100644 SecurityPkg/Tcg/Tcg2Smm/Tpm.asl diff --git a/SecurityPkg/Include/Guid/Tcg2ConfigHii.h b/SecurityPkg/Include/Guid/Tcg2ConfigHii.h new file mode 100644 index 0000000000..28e31e3475 --- /dev/null +++ b/SecurityPkg/Include/Guid/Tcg2ConfigHii.h @@ -0,0 +1,25 @@ +/** @file + GUIDs used as HII FormSet and HII Package list GUID in Tcg2Config driver. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TCG2_CONFIG_HII_GUID_H__ +#define __TCG2_CONFIG_HII_GUID_H__ + +#define TCG2_CONFIG_FORM_SET_GUID \ + { \ + 0x6339d487, 0x26ba, 0x424b, { 0x9a, 0x5d, 0x68, 0x7e, 0x25, 0xd7, 0x40, 0xbc } \ + } + +extern EFI_GUID gTcg2ConfigFormSetGuid; + +#endif diff --git a/SecurityPkg/Include/Guid/Tcg2PhysicalPresenceData.h b/SecurityPkg/Include/Guid/Tcg2PhysicalPresenceData.h new file mode 100644 index 0000000000..df43fd9c80 --- /dev/null +++ b/SecurityPkg/Include/Guid/Tcg2PhysicalPresenceData.h @@ -0,0 +1,47 @@ +/** @file + Define the variable data structures used for TCG2 physical presence. + The TPM2 request from firmware or OS is saved to variable. And it is + cleared after it is processed in the next boot cycle. The TPM2 response + is saved to variable. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TCG2_PHYSICAL_PRESENCE_DATA_GUID_H__ +#define __TCG2_PHYSICAL_PRESENCE_DATA_GUID_H__ + +#define EFI_TCG2_PHYSICAL_PRESENCE_DATA_GUID \ + { \ + 0xaeb9c5c1, 0x94f1, 0x4d02, { 0xbf, 0xd9, 0x46, 0x2, 0xdb, 0x2d, 0x3c, 0x54 } \ + } + +#define TCG2_PHYSICAL_PRESENCE_VARIABLE L"Tcg2PhysicalPresence" + +typedef struct { + UINT8 PPRequest; ///< Physical Presence request command. + UINT32 PPRequestParameter; ///< Physical Presence request Parameter. + UINT8 LastPPRequest; + UINT32 PPResponse; +} EFI_TCG2_PHYSICAL_PRESENCE; + +// +// This variable is used to save TCG2 Management Flags and corresponding operations. +// It should be protected from malicious software (e.g. Set it as read-only variable). +// +#define TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE L"Tcg2PhysicalPresenceFlags" +typedef struct { + UINT32 PPFlags; +} EFI_TCG2_PHYSICAL_PRESENCE_FLAGS; + +extern EFI_GUID gEfiTcg2PhysicalPresenceGuid; + +#endif + diff --git a/SecurityPkg/Include/Guid/TcgEventHob.h b/SecurityPkg/Include/Guid/TcgEventHob.h index c92ee8c029..1082807c36 100644 --- a/SecurityPkg/Include/Guid/TcgEventHob.h +++ b/SecurityPkg/Include/Guid/TcgEventHob.h @@ -1,5 +1,5 @@ /** @file - Defines the HOB GUID used to pass a TCG_PCR_EVENT from a TPM PEIM to + Defines the HOB GUID used to pass a TCG_PCR_EVENT or TCG_PCR_EVENT2 from a TPM PEIM to a TPM DXE Driver. A GUIDed HOB is generated for each measurement made in the PEI Phase. @@ -27,6 +27,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. extern EFI_GUID gTcgEventEntryHobGuid; +#define EFI_TCG_EVENT2_HOB_GUID \ + { \ + 0xd26c221e, 0x2430, 0x4c8a, { 0x91, 0x70, 0x3f, 0xcb, 0x45, 0x0, 0x41, 0x3f } \ + } + +extern EFI_GUID gTcgEvent2EntryHobGuid; + /// /// The Global ID of a GUIDed HOB used to record TPM device error. /// diff --git a/SecurityPkg/Include/Library/Tcg2PhysicalPresenceLib.h b/SecurityPkg/Include/Library/Tcg2PhysicalPresenceLib.h new file mode 100644 index 0000000000..ce45f17454 --- /dev/null +++ b/SecurityPkg/Include/Library/Tcg2PhysicalPresenceLib.h @@ -0,0 +1,160 @@ +/** @file + Ihis library is intended to be used by BDS modules. + This library will execute TPM2 request. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TCG2_PHYSICAL_PRESENCE_LIB_H_ +#define _TCG2_PHYSICAL_PRESENCE_LIB_H_ + +#include +#include +#include + +// +// UEFI TCG2 library definition bit of the BIOS TPM Management Flags +// +// BIT0 is reserved +#define TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR BIT1 +// BIT2 is reserved +#define TCG2_LIB_PP_FLAG_RESET_TRACK BIT3 +#define TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_TURN_ON BIT4 +#define TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_TURN_OFF BIT5 +#define TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS BIT6 +#define TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS BIT7 + +// +// UEFI TCG2 library definition bit of the BIOS Information Flags +// +#define TCG2_BIOS_INFORMATION_FLAG_HIERACHY_CONTROL_STORAGE_DISABLE BIT8 +#define TCG2_BIOS_INFORMATION_FLAG_HIERACHY_CONTROL_ENDORSEMENT_DISABLE BIT9 + +// +// UEFI TCG2 library definition bit of the BIOS Storage Management Flags +// +#define TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID BIT16 +#define TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID BIT17 + +// +// Default value +// +#define TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT (TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_TURN_OFF | \ + TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR | \ + TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS | \ + TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) + +/** + 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 PlatformAuth platform auth value. NULL means no platform auth change. +**/ +VOID +EFIAPI +Tcg2PhysicalPresenceLibProcessRequest ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL + ); + +/** + 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 + ); + +/** + Return TPM2 ManagementFlags set by PP interface. + + @retval ManagementFlags TPM2 Management Flags. +**/ +UINT32 +EFIAPI +Tcg2PhysicalPresenceLibGetManagementFlags ( + VOID + ); + +/** + The handler for TPM physical presence function: + Return TPM Operation Response to OS Environment. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + @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 + ); + + +/** + 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. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + 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 + ); + +/** + The handler for TPM physical presence function: + Get User Confirmation Status for Operation. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + Caution: This function may receive untrusted input. + + @param[in] OperationRequest TPM physical presence operation request. + + @return Return Code for Get User Confirmation Status for Operation. +**/ +UINT32 +EFIAPI +Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction ( + IN UINT32 OperationRequest + ); + +#endif diff --git a/SecurityPkg/Include/Library/Tcg2PpVendorLib.h b/SecurityPkg/Include/Library/Tcg2PpVendorLib.h new file mode 100644 index 0000000000..2434750f9f --- /dev/null +++ b/SecurityPkg/Include/Library/Tcg2PpVendorLib.h @@ -0,0 +1,129 @@ +/** @file + Ihis library is to support TCG PC Client Platform Physical Presence Interface Specification + Family "2.0" part, >= 128 Vendor Specific PPI Operation. + + The Vendor Specific PPI operation may change TPM state, BIOS TPM management + flags, and may need additional boot cycle. + + Caution: This function may receive untrusted input. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TCG2_PP_VENDOR_LIB_H_ +#define _TCG2_PP_VENDOR_LIB_H_ + +#include +#include +#include + +/** + Check and execute the requested physical presence command. + + This API should be invoked in BIOS boot phase to process pending request. + + Caution: This function may receive untrusted input. + + If OperationRequest < 128, then ASSERT(). + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. + @param[in] OperationRequest TPM physical presence operation request. + @param[in, out] ManagementFlags BIOS TPM Management Flags. + @param[out] ResetRequired If reset is required to vendor settings in effect. + True, it indicates the reset is required. + False, it indicates the reset is not required. + + @return TPM Operation Response to OS Environment. +**/ +UINT32 +EFIAPI +Tcg2PpVendorLibExecutePendingRequest ( + IN TPM2B_AUTH *PlatformAuth, OPTIONAL + IN UINT32 OperationRequest, + IN OUT UINT32 *ManagementFlags, + OUT BOOLEAN *ResetRequired + ); + +/** + Check if there is a valid physical presence command request. + + This API should be invoked in BIOS boot phase to process pending request. + + Caution: This function may receive untrusted input. + + If OperationRequest < 128, then ASSERT(). + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] ManagementFlags BIOS TPM Management 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. + 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 +EFIAPI +Tcg2PpVendorLibHasValidRequest ( + IN UINT32 OperationRequest, + IN UINT32 ManagementFlags, + OUT BOOLEAN *RequestConfirmed + ); + +/** + The callback for TPM vendor specific physical presence which is called for + Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + Caution: This function may receive untrusted input. + + If OperationRequest < 128, then ASSERT(). + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] ManagementFlags BIOS TPM Management Flags. + @param[in] RequestParameter Extra parameter from the passed package. + + @return Return Code for Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. +**/ +UINT32 +EFIAPI +Tcg2PpVendorLibSubmitRequestToPreOSFunction ( + IN UINT32 OperationRequest, + IN UINT32 ManagementFlags, + IN UINT32 RequestParameter + ); + +/** + The callback for TPM vendor specific physical presence which is called for + Get User Confirmation Status for Operation. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + Caution: This function may receive untrusted input. + + If OperationRequest < 128, then ASSERT(). + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] ManagementFlags BIOS TPM Management Flags. + + @return Return Code for Get User Confirmation Status for Operation. +**/ +UINT32 +EFIAPI +Tcg2PpVendorLibGetUserConfirmationStatusFunction ( + IN UINT32 OperationRequest, + IN UINT32 ManagementFlags + ); + +#endif diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c new file mode 100644 index 0000000000..46fc616d5e --- /dev/null +++ b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c @@ -0,0 +1,1245 @@ +/** @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 - 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#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; + +/** + 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 ((EFI_D_INFO, "Tpm2ClearControl ... \n")); + Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO); + DEBUG ((EFI_D_INFO, "Tpm2ClearControl - %r\n", Status)); + if (EFI_ERROR (Status)) { + goto Done; + } + DEBUG ((EFI_D_INFO, "Tpm2Clear ... \n")); + Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession); + DEBUG ((EFI_D_INFO, "Tpm2Clear - %r\n", Status)); + +Done: + ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac)); + return Status; +} + +/** + Alloc PCR data. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. + @param[in] SupportedPCRBanks Supported PCR banks + @param[in] PCRBanks PCR banks + + @retval EFI_SUCCESS Operation completed successfully. +**/ +EFI_STATUS +Tpm2CommandAllocPcr ( + IN TPM2B_AUTH *PlatformAuth, OPTIONAL + IN UINT32 SupportedPCRBanks, + IN UINT32 PCRBanks + ) +{ + EFI_STATUS Status; + TPMS_AUTH_COMMAND *AuthSession; + TPMS_AUTH_COMMAND LocalAuthSession; + TPML_PCR_SELECTION PcrAllocation; + TPMI_YES_NO AllocationSuccess; + UINT32 MaxPCR; + UINT32 SizeNeeded; + UINT32 SizeAvailable; + + 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); + } + + // + // Fill input + // + ZeroMem (&PcrAllocation, sizeof(PcrAllocation)); + if ((EFI_TCG2_BOOT_HASH_ALG_SHA1 & SupportedPCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA1; + PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX; + if ((EFI_TCG2_BOOT_HASH_ALG_SHA1 & PCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF; + } else { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00; + } + PcrAllocation.count++; + } + if ((EFI_TCG2_BOOT_HASH_ALG_SHA256 & SupportedPCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA256; + PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX; + if ((EFI_TCG2_BOOT_HASH_ALG_SHA256 & PCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF; + } else { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00; + } + PcrAllocation.count++; + } + if ((EFI_TCG2_BOOT_HASH_ALG_SHA384 & SupportedPCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA384; + PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX; + if ((EFI_TCG2_BOOT_HASH_ALG_SHA384 & PCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF; + } else { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00; + } + PcrAllocation.count++; + } + if ((EFI_TCG2_BOOT_HASH_ALG_SHA512 & SupportedPCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA512; + PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX; + if ((EFI_TCG2_BOOT_HASH_ALG_SHA512 & PCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF; + } else { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00; + } + PcrAllocation.count++; + } + if ((EFI_TCG2_BOOT_HASH_ALG_SM3_256 & SupportedPCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SM3_256; + PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX; + if ((EFI_TCG2_BOOT_HASH_ALG_SM3_256 & PCRBanks) != 0) { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF; + } else { + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00; + PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00; + } + PcrAllocation.count++; + } + Status = Tpm2PcrAllocate ( + TPM_RH_PLATFORM, + AuthSession, + &PcrAllocation, + &AllocationSuccess, + &MaxPCR, + &SizeNeeded, + &SizeAvailable + ); + DEBUG ((EFI_D_INFO, "Tpm2PcrAllocate - %r\n", Status)); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((EFI_D_INFO, "AllocationSuccess - %02x\n", AllocationSuccess)); + DEBUG ((EFI_D_INFO, "MaxPCR - %08x\n", MaxPCR)); + DEBUG ((EFI_D_INFO, "SizeNeeded - %08x\n", SizeNeeded)); + DEBUG ((EFI_D_INFO, "SizeAvailable - %08x\n", SizeAvailable)); + + return EFI_SUCCESS; +} + +/** + 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 ((EFI_D_INFO, "Tpm2ChangeEPS - %r\n", Status)); + 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_PROTOCOL *Tcg2Protocol; + EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability; + + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); + ASSERT_EFI_ERROR (Status); + + ProtocolCapability.Size = sizeof(ProtocolCapability); + Status = Tcg2Protocol->GetCapability ( + Tcg2Protocol, + &ProtocolCapability + ); + ASSERT_EFI_ERROR (Status); + + 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 = Tpm2CommandAllocPcr (PlatformAuth, ProtocolCapability.HashAlgorithmBitmap, 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 = Tpm2CommandAllocPcr (PlatformAuth, ProtocolCapability.HashAlgorithmBitmap, ProtocolCapability.HashAlgorithmBitmap); + 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. +**/ +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; + + 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); + + TmpStr2 = NULL; + CautionKey = FALSE; + NoPpiInfo = FALSE; + BufSize = CONFIRM_BUFFER_SIZE; + ConfirmText = AllocateZeroPool (BufSize); + ASSERT (ConfirmText != 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: + 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; + + + 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); + + 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 + ) +{ + BOOLEAN IsRequestValid; + + *RequestConfirmed = 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; + + 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] TcgPpData Point to the physical presence NV variable. + @param[in] Flags The physical presence interface flags. +**/ +VOID +Tcg2ExecutePendingTpmRequest ( + IN TPM2B_AUTH *PlatformAuth, OPTIONAL + IN EFI_TCG2_PHYSICAL_PRESENCE *TcgPpData, + IN 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) { + 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; + + 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; + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol; + EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags; + + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); + if (EFI_ERROR (Status)) { + return ; + } + + // + // Check S4 resume + // + if (GetBootModeHob () == BOOT_ON_S4_RESUME) { + DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n")); + return ; + } + + mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, DxeTcg2PhysicalPresenceLibStrings, NULL); + ASSERT (mTcg2PpStringPackHandle != NULL); + + // + // 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 = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT; + 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 ((EFI_D_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status)); + return ; + } + } + DEBUG ((EFI_D_INFO, "[TPM2] PpiFlags = %x\n", PpiFlags.PPFlags)); + + // + // 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 ((EFI_D_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status)); + ASSERT_EFI_ERROR (Status); + } + } + + // + // 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 ((EFI_D_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status)); + return ; + } + } + + DEBUG ((EFI_D_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest)); + + // + // Execute pending TPM request. + // + Tcg2ExecutePendingTpmRequest (PlatformAuth, &TcgPpData, PpiFlags); + DEBUG ((EFI_D_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_PROTOCOL *Tcg2Protocol; + EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags; + + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Check S4 resume + // + if (GetBootModeHob () == BOOT_ON_S4_RESUME) { + DEBUG ((EFI_D_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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_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_VENDOR_SPECIFIC_OPERATION) ) { + // + // This command requires UI to prompt user for Auth data. + // + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED; + } + + if (PpData.PPRequest != OperationRequest) { + 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 ((EFI_D_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 = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT; + } + return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter); + } + + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS; +} diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf new file mode 100644 index 0000000000..bad4fe41b1 --- /dev/null +++ b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf @@ -0,0 +1,69 @@ +## @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. +# +# 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) 2013 - 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeTcg2PhysicalPresenceLib + MODULE_UNI_FILE = DxeTcg2PhysicalPresenceLib.uni + FILE_GUID = 7E507A86-DE8B-4AD3-BC4C-0498389098D3 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresenceLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DxeTcg2PhysicalPresenceLib.c + PhysicalPresenceStrings.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib + PrintLib + HiiLib + HobLib + Tpm2CommandLib + Tcg2PpVendorLib + +[Protocols] + gEfiTcg2ProtocolGuid ## CONSUMES + gEdkiiVariableLockProtocolGuid ## CONSUMES + +[Guids] + ## CONSUMES ## HII + ## SOMETIMES_PRODUCES ## Variable:L"Tcg2PhysicalPresence" + ## SOMETIMES_CONSUMES ## Variable:L"Tcg2PhysicalPresence" + ## SOMETIMES_PRODUCES ## Variable:L"Tcg2PhysicalPresenceFlags" + ## SOMETIMES_CONSUMES ## Variable:L"Tcg2PhysicalPresenceFlags" + gEfiTcg2PhysicalPresenceGuid diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni new file mode 100644 index 0000000000000000000000000000000000000000..9794792d703924d9a63cb81eb970409ac46e42aa GIT binary patch literal 2938 zcmdUx-A@xy5XI-&#Q$MaUesW#=o2wU3RN4Gl70kDOvutMw6PyrmMZ_e`a5^Jy;}m} zgG5c!yQ#+KP#yTh#38upEG-_9+kJ!7V82lkG3 z%c}N>cFz14*0q`kixcK%Hes!09iB7BiPfzc#szlK3UP>EVUKB#u}=A4F#a0&jOq2U z5sy#wQ=8g=He2I%6SIWqe#NT_qL^f~>oFz7lENo4PGKu1C(GE*8E5Pg&l&8b<2>xj z>1ie*u54*94`uFdQ7z#|PrG=Q_HMJy&ZyP|S7SmZ3vo~e}80XvJ`DVA=xU^YWt zDXfUa&(TJKd&a&ppXhS{`p6dSQM55XLwIV|BU7!+L3NKKdY?lSi9N((!MspXG!gf! zJxQVKaVFrY-dtD5RP_u%)h^XXKlqXA(r6qiDn~O_(1KRhNywb)Ta5Bxqgp&;rp&CI zkr~lk1p8Ce6Nh{Fx=*{siFj;J=qXMgJ+)2xO*9ZMWndTIb1?K2+amvo?F636(a0QI zr^53oMWwJZ^NiEfw&$ygiR@ygK4U)vMLu*Ei&K*?YdnRss&xVrtzF=AioI96E3X`l z(IVn2bIP)`?$etF{iI`oud^};Hc~moZp_m&ouI1Du2)aN#C=UbiYR`L%GImY8M#bQ z%ui{Z+hvdO+chqct7=;;hXHpzTGhW0h2?jTe5s=6+9+(h*di<+h@KBsxVr?dz+ECYfe79*vdv;-RdQ_ z^8SJL4J%@<^Ve8<@hBSheuWd!n`m)BHOc2*=~jyR={;Es+%>2F#;Rug?6`hMAhp2g zf!44i7)dWFyMtO?_+0nf2&Y9@=TyikRiGPnN^W~0!U}kQ`i)#!Mf7{os1`cJp*lHO z>3>y3H%FtB^*_A(bzX1do&S;Cy8c(`cbjt+GWhqtEy~|9xARR=_V90fOT=^b69Ved AfdBvi literal 0 HcmV?d00001 diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..30f21a36c02d635752ab41be63628c4ac759743e GIT binary patch literal 10998 zcmd^_ZEqVz5Xbj565qiJLbQmcPsQJE0fWb$$?*!?!xW49DTE-Z%++VIaDU3`Jw4<6L708rh3f zpgIg^x*u!wZ~ZPu9^j*+H(rVkd>o15Sa03YcXxGupn1Lv-|On$)CuR-zfjUQ3t+b@qfpppuO=QOlO@4U7OVB9(GM4@yhWq-% zlT53;JB&JB*62`HykFD$NF%%Adtbg)oq1VQj&(qvV<-F)RyAKwKC&4e>$e@_peqfw zq(ja-8tux9p6O~e>h)RJ(0Ntk=)fo>op>Nj zf9YK!1MfDJxX_a?l%B5sK??C`+-BFa5~Yp=Sl2m7;QN0*)R7aER^H}8^=2Eqve`SiTLa6+7^m{BR%;| zU(vf7qj-8Ol-jiyxfw~8R#;OOCgU&Zn8r^>-UR|0zLasaC_fJh_yPBR)zP^D{fy-W zd3@t>9>+vvu0PPXqv!SwR{m4RUi6_H8**%^VhX-y)ra{MIrdy0bC5;G1CDx)G98C3SI);rDHm3Sl=0DtdLU~iX=h!P^060@nM!ZEF3873ZBL%D zr89YcLorNFoae8cuiU#FS$E~d7ts&Tb zr@EXjaYy+F86QjXzK-79vYKAXB_>B=i9C98Eu6%P1UbQVYR%bFRDBpZsFu;_Zc z$F6zAS*5}|?I=BRluA+cYb0USL8XywGZNoetfet<1?(`}QAtq$T1^6Gn2n}k#fGH8 zFRf-+7td6MRF0gReX~>=YI?XBU!JFXOqG)z<(4gR(2vz?Gau!8wR}q!W}UkzA8X2u z&772KBv+hc@39AZLSko%8YTm*}XM3Ej zU^b$EJ(hi|G3Ihq&!tjTX+IP{k7RLtke&yT!%8#t9+3SYb_VcLk0?;lF~T%tYsOU5 zSu}z!dJ4Jn^h>wISIy3utt{x4pmCmCucEBtuS(q)W|R4+XS~HV z+L`1$=iYn-G(s&U!&DQSrj|AGT$*~NGu5|s5Lh2T8*jA{!#s3v zNO!6;y{Ux!O}M!qtu@eFWIJfQmA0M6ZnU3eN}J88!qsfVpc7E0dGqX2{euC}#+P@r z8nG@6^0^Pu%e#e+?OWf5Gg&al0Jmsfr(!8qHPhF}(5<3J&ZET( z(RV#(xy@Y;#}_(^c);w{R((Zv-D;{HGuKyWeXWP8Xf*Av)UMU}v2JJ5ZOE;F)YGc4 zWZ#nN&bw@N-17=?HsU8Nv%Fy$!qCq~yk4nGab3+xe9`%^iWGV2yMThHx;~LtwdAMP z<15KYRJCL^Dj~0Ftt)vhs&pEf^?4JX!@9NfZ*kArj@lwZOkOmf{KB&kHnx1_ooPJA zyR26CyB{Q90<{fky@Q)5cT%n+ClfvRz4g19!+X9~DOKan5vtDNqA|m|j;bWLg`wZJ#@AFMK8-6` z*YfHJtxyENB*N4`*>&5bg?NxX;o4pUKz&s|Jb$TKHPb)^N@vA$Lo{hZ2>GTqkzS|07 zF|=xmlO~(Z!mm=B`6|byzx_4NVtT8t-EY1>cC~8$l-BpneY%dii1nW0e7k#&>ZRU! zGy9^322|(l#QPqq^<5m(N45R1tE;zWZFv9k|FP%k72ECaOg3BNsfztc#Qd)M*N)!#xfID+b%406!|8mk z#M;<8E8FV8Lw%sr%qu<`no=7vt;$^phUJ($?7|0E~&3F-k-Gd pWM!)(=d)<3#QDxUy<2KVEa?)L*mFMnnKbiRu~eG6{oX~M{{Z0+ruF~; literal 0 HcmV?d00001 diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c index a5d7fe5fa8..26bf6fb000 100644 --- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c @@ -9,10 +9,10 @@ DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content read is within the image buffer. - TrEEMeasurePeImage() function will accept untrusted PE/COFF image and validate its + Tcg2MeasurePeImage() function will accept untrusted PE/COFF image and validate its data structure within this image buffer before use. - TrEEMeasureGptTable() function will receive untrusted GPT partition table, and parse + Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse partition data carefully. Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
@@ -28,7 +28,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include -#include +#include #include #include #include @@ -51,15 +51,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // // Flag to check GPT partition. It only need be measured once. // -BOOLEAN mTrEEMeasureGptTableFlag = FALSE; -UINTN mTrEEMeasureGptCount = 0; -VOID *mTrEEFileBuffer; -UINTN mTrEEImageSize; +BOOLEAN mTcg2MeasureGptTableFlag = FALSE; +UINTN mTcg2MeasureGptCount = 0; +VOID *mTcg2FileBuffer; +UINTN mTcg2ImageSize; // // Measured FV handle cache // -EFI_HANDLE mTrEECacheMeasuredHandle = NULL; -MEASURED_HOB_DATA *mTrEEMeasuredHobData = NULL; +EFI_HANDLE mTcg2CacheMeasuredHandle = NULL; +MEASURED_HOB_DATA *mTcg2MeasuredHobData = NULL; /** Reads contents of a PE/COFF image in memory buffer. @@ -96,11 +96,11 @@ DxeTpm2MeasureBootLibImageRead ( } EndPosition = FileOffset + *ReadSize; - if (EndPosition > mTrEEImageSize) { - *ReadSize = (UINT32)(mTrEEImageSize - FileOffset); + if (EndPosition > mTcg2ImageSize) { + *ReadSize = (UINT32)(mTcg2ImageSize - FileOffset); } - if (FileOffset >= mTrEEImageSize) { + if (FileOffset >= mTcg2ImageSize) { *ReadSize = 0; } @@ -115,7 +115,7 @@ DxeTpm2MeasureBootLibImageRead ( Caution: This function may receive untrusted input. The GPT partition table is external input, so this function should parse partition data carefully. - @param TreeProtocol Pointer to the located TREE protocol instance. + @param Tcg2Protocol Pointer to the located TCG2 protocol instance. @param GptHandle Handle that GPT partition was installed. @retval EFI_SUCCESS Successfully measure GPT table. @@ -126,8 +126,8 @@ DxeTpm2MeasureBootLibImageRead ( **/ EFI_STATUS EFIAPI -TrEEMeasureGptTable ( - IN EFI_TREE_PROTOCOL *TreeProtocol, +Tcg2MeasureGptTable ( + IN EFI_TCG2_PROTOCOL *Tcg2Protocol, IN EFI_HANDLE GptHandle ) { @@ -139,11 +139,11 @@ TrEEMeasureGptTable ( UINT8 *EntryPtr; UINTN NumberOfPartition; UINT32 Index; - TrEE_EVENT *TreeEvent; + EFI_TCG2_EVENT *Tcg2Event; EFI_GPT_DATA *GptData; UINT32 EventSize; - if (mTrEEMeasureGptCount > 0) { + if (mTcg2MeasureGptCount > 0) { return EFI_SUCCESS; } @@ -212,19 +212,19 @@ TrEEMeasureGptTable ( // EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); - TreeEvent = (TrEE_EVENT *) AllocateZeroPool (EventSize + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event)); - if (TreeEvent == NULL) { + Tcg2Event = (EFI_TCG2_EVENT *) AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event)); + if (Tcg2Event == NULL) { FreePool (PrimaryHeader); FreePool (EntryPtr); return EFI_OUT_OF_RESOURCES; } - TreeEvent->Size = EventSize + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event); - TreeEvent->Header.HeaderSize = sizeof(TrEE_EVENT_HEADER); - TreeEvent->Header.HeaderVersion = TREE_EVENT_HEADER_VERSION; - TreeEvent->Header.PCRIndex = 5; - TreeEvent->Header.EventType = EV_EFI_GPT_EVENT; - GptData = (EFI_GPT_DATA *) TreeEvent->Event; + Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event); + Tcg2Event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); + Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; + Tcg2Event->Header.PCRIndex = 5; + Tcg2Event->Header.EventType = EV_EFI_GPT_EVENT; + GptData = (EFI_GPT_DATA *) Tcg2Event->Event; // // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition @@ -251,20 +251,20 @@ TrEEMeasureGptTable ( // // Measure the GPT data // - Status = TreeProtocol->HashLogExtendEvent ( - TreeProtocol, + Status = Tcg2Protocol->HashLogExtendEvent ( + Tcg2Protocol, 0, (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData, (UINT64) EventSize, - TreeEvent + Tcg2Event ); if (!EFI_ERROR (Status)) { - mTrEEMeasureGptCount++; + mTcg2MeasureGptCount++; } FreePool (PrimaryHeader); FreePool (EntryPtr); - FreePool (TreeEvent); + FreePool (Tcg2Event); return Status; } @@ -277,7 +277,7 @@ TrEEMeasureGptTable ( PE/COFF image is external input, so this function will validate its data structure within this image buffer before use. - @param[in] TreeProtocol Pointer to the located TREE protocol instance. + @param[in] Tcg2Protocol Pointer to the located TCG2 protocol instance. @param[in] ImageAddress Start address of image buffer. @param[in] ImageSize Image size @param[in] LinkTimeBase Address that the image is loaded into memory. @@ -292,8 +292,8 @@ TrEEMeasureGptTable ( **/ EFI_STATUS EFIAPI -TrEEMeasurePeImage ( - IN EFI_TREE_PROTOCOL *TreeProtocol, +Tcg2MeasurePeImage ( + IN EFI_TCG2_PROTOCOL *Tcg2Protocol, IN EFI_PHYSICAL_ADDRESS ImageAddress, IN UINTN ImageSize, IN UINTN LinkTimeBase, @@ -302,7 +302,7 @@ TrEEMeasurePeImage ( ) { EFI_STATUS Status; - TrEE_EVENT *TreeEvent; + EFI_TCG2_EVENT *Tcg2Event; EFI_IMAGE_LOAD_EVENT *ImageLoad; UINT32 FilePathSize; UINT32 EventSize; @@ -315,33 +315,33 @@ TrEEMeasurePeImage ( // Determine destination PCR by BootPolicy // EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize; - TreeEvent = AllocateZeroPool (EventSize + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event)); - if (TreeEvent == NULL) { + Tcg2Event = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event)); + if (Tcg2Event == NULL) { return EFI_OUT_OF_RESOURCES; } - TreeEvent->Size = EventSize + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event); - TreeEvent->Header.HeaderSize = sizeof(TrEE_EVENT_HEADER); - TreeEvent->Header.HeaderVersion = TREE_EVENT_HEADER_VERSION; - ImageLoad = (EFI_IMAGE_LOAD_EVENT *) TreeEvent->Event; + Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event); + Tcg2Event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); + Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; + ImageLoad = (EFI_IMAGE_LOAD_EVENT *) Tcg2Event->Event; switch (ImageType) { case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: - TreeEvent->Header.EventType = EV_EFI_BOOT_SERVICES_APPLICATION; - TreeEvent->Header.PCRIndex = 4; + Tcg2Event->Header.EventType = EV_EFI_BOOT_SERVICES_APPLICATION; + Tcg2Event->Header.PCRIndex = 4; break; case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: - TreeEvent->Header.EventType = EV_EFI_BOOT_SERVICES_DRIVER; - TreeEvent->Header.PCRIndex = 2; + Tcg2Event->Header.EventType = EV_EFI_BOOT_SERVICES_DRIVER; + Tcg2Event->Header.PCRIndex = 2; break; case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: - TreeEvent->Header.EventType = EV_EFI_RUNTIME_SERVICES_DRIVER; - TreeEvent->Header.PCRIndex = 2; + Tcg2Event->Header.EventType = EV_EFI_RUNTIME_SERVICES_DRIVER; + Tcg2Event->Header.PCRIndex = 2; break; default: DEBUG (( EFI_D_ERROR, - "TrEEMeasurePeImage: Unknown subsystem type %d", + "Tcg2MeasurePeImage: Unknown subsystem type %d", ImageType )); goto Finish; @@ -358,12 +358,12 @@ TrEEMeasurePeImage ( // // Log the PE data // - Status = TreeProtocol->HashLogExtendEvent ( - TreeProtocol, + Status = Tcg2Protocol->HashLogExtendEvent ( + Tcg2Protocol, PE_COFF_IMAGE, ImageAddress, ImageSize, - TreeEvent + Tcg2Event ); if (Status == EFI_VOLUME_FULL) { // @@ -375,7 +375,7 @@ TrEEMeasurePeImage ( } Finish: - FreePool (TreeEvent); + FreePool (Tcg2Event); return Status; } @@ -428,9 +428,9 @@ DxeTpm2MeasureBootHandler ( IN BOOLEAN BootPolicy ) { - EFI_TREE_PROTOCOL *TreeProtocol; + EFI_TCG2_PROTOCOL *Tcg2Protocol; EFI_STATUS Status; - TREE_BOOT_SERVICE_CAPABILITY ProtocolCapability; + EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability; EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode; EFI_HANDLE Handle; @@ -441,26 +441,26 @@ DxeTpm2MeasureBootHandler ( EFI_PHYSICAL_ADDRESS FvAddress; UINT32 Index; - Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol); + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); if (EFI_ERROR (Status)) { // - // TrEE protocol is not installed. So, TPM2 is not present. + // Tcg2 protocol is not installed. So, TPM2 is not present. // Don't do any measurement, and directly return EFI_SUCCESS. // - DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - TrEE - %r\n", Status)); + DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - Tcg2 - %r\n", Status)); return EFI_SUCCESS; } ProtocolCapability.Size = (UINT8) sizeof (ProtocolCapability); - Status = TreeProtocol->GetCapability ( - TreeProtocol, + Status = Tcg2Protocol->GetCapability ( + Tcg2Protocol, &ProtocolCapability ); - if (EFI_ERROR (Status) || (!ProtocolCapability.TrEEPresentFlag)) { + if (EFI_ERROR (Status) || (!ProtocolCapability.TPMPresentFlag)) { // // TPM device doesn't work or activate. // - DEBUG ((EFI_D_ERROR, "DxeTpm2MeasureBootHandler (%r) - TrEEPresentFlag - %x\n", Status, ProtocolCapability.TrEEPresentFlag)); + DEBUG ((EFI_D_ERROR, "DxeTpm2MeasureBootHandler (%r) - TPMPresentFlag - %x\n", Status, ProtocolCapability.TPMPresentFlag)); return EFI_SUCCESS; } @@ -475,7 +475,7 @@ DxeTpm2MeasureBootHandler ( // DevicePathNode = OrigDevicePathNode; Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle); - if (!EFI_ERROR (Status) && !mTrEEMeasureGptTableFlag) { + if (!EFI_ERROR (Status) && !mTcg2MeasureGptTableFlag) { // // Find the gpt partion on the given devicepath // @@ -508,13 +508,13 @@ DxeTpm2MeasureBootHandler ( // // Measure GPT disk. // - Status = TrEEMeasureGptTable (TreeProtocol, Handle); - DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - TrEEMeasureGptTable - %r\n", Status)); + Status = Tcg2MeasureGptTable (Tcg2Protocol, Handle); + DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasureGptTable - %r\n", Status)); if (!EFI_ERROR (Status)) { // // GPT disk check done. // - mTrEEMeasureGptTableFlag = TRUE; + mTcg2MeasureGptTableFlag = TRUE; } } FreePool (OrigDevicePathNode); @@ -553,7 +553,7 @@ DxeTpm2MeasureBootHandler ( // ApplicationRequired = TRUE; - if (mTrEECacheMeasuredHandle != Handle && mTrEEMeasuredHobData != NULL) { + if (mTcg2CacheMeasuredHandle != Handle && mTcg2MeasuredHobData != NULL) { // // Search for Root FV of this PE image // @@ -577,12 +577,12 @@ DxeTpm2MeasureBootHandler ( ApplicationRequired = FALSE; - for (Index = 0; Index < mTrEEMeasuredHobData->Num; Index++) { - if(mTrEEMeasuredHobData->MeasuredFvBuf[Index].BlobBase == FvAddress) { + for (Index = 0; Index < mTcg2MeasuredHobData->Num; Index++) { + if(mTcg2MeasuredHobData->MeasuredFvBuf[Index].BlobBase == FvAddress) { // // Cache measured FV for next measurement // - mTrEECacheMeasuredHandle = Handle; + mTcg2CacheMeasuredHandle = Handle; ApplicationRequired = TRUE; break; } @@ -598,8 +598,8 @@ DxeTpm2MeasureBootHandler ( goto Finish; } - mTrEEImageSize = FileSize; - mTrEEFileBuffer = FileBuffer; + mTcg2ImageSize = FileSize; + mTcg2FileBuffer = FileBuffer; // // Measure PE Image @@ -645,15 +645,15 @@ DxeTpm2MeasureBootHandler ( // // Measure PE image into TPM log. // - Status = TrEEMeasurePeImage ( - TreeProtocol, + Status = Tcg2MeasurePeImage ( + Tcg2Protocol, (EFI_PHYSICAL_ADDRESS) (UINTN) FileBuffer, FileSize, (UINTN) ImageContext.ImageAddress, ImageContext.ImageType, DevicePathNode ); - DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - TrEEMeasurePeImage - %r\n", Status)); + DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasurePeImage - %r\n", Status)); } // @@ -692,7 +692,7 @@ DxeTpm2MeasureBootLibConstructor ( GuidHob = GetFirstGuidHob (&gMeasuredFvHobGuid); if (GuidHob != NULL) { - mTrEEMeasuredHobData = GET_GUID_HOB_DATA (GuidHob); + mTcg2MeasuredHobData = GET_GUID_HOB_DATA (GuidHob); } return RegisterSecurity2Handler ( diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf index 14bf190317..1296c977b4 100644 --- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf +++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf @@ -61,7 +61,7 @@ gZeroGuid ## SOMETIMES_CONSUMES ## GUID [Protocols] - gEfiTrEEProtocolGuid ## SOMETIMES_CONSUMES + gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES diff --git a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c index ffeac59ba4..7a2ec7f221 100644 --- a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c +++ b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c @@ -1,7 +1,7 @@ /** @file This library is used by other modules to measure data to TPM. -Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.
+Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include -#include +#include #include #include @@ -120,37 +120,37 @@ Tpm20MeasureAndLogData ( ) { EFI_STATUS Status; - EFI_TREE_PROTOCOL *TreeProtocol; - TrEE_EVENT *TreeEvent; + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_TCG2_EVENT *Tcg2Event; // - // TrEEPresentFlag is checked in HashLogExtendEvent + // TPMPresentFlag is checked in HashLogExtendEvent // - Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol); + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); if (EFI_ERROR (Status)) { return Status; } - TreeEvent = (TrEE_EVENT *) AllocateZeroPool (LogLen + sizeof (TrEE_EVENT)); - if(TreeEvent == NULL) { + Tcg2Event = (EFI_TCG2_EVENT *) AllocateZeroPool (LogLen + sizeof (EFI_TCG2_EVENT)); + if(Tcg2Event == NULL) { return EFI_OUT_OF_RESOURCES; } - TreeEvent->Size = (UINT32)LogLen + sizeof (TrEE_EVENT) - sizeof(TreeEvent->Event); - TreeEvent->Header.HeaderSize = sizeof(TrEE_EVENT_HEADER); - TreeEvent->Header.HeaderVersion = TREE_EVENT_HEADER_VERSION; - TreeEvent->Header.PCRIndex = PcrIndex; - TreeEvent->Header.EventType = EventType; - CopyMem (&TreeEvent->Event[0], EventLog, LogLen); + Tcg2Event->Size = (UINT32)LogLen + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event); + Tcg2Event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); + Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; + Tcg2Event->Header.PCRIndex = PcrIndex; + Tcg2Event->Header.EventType = EventType; + CopyMem (&Tcg2Event->Event[0], EventLog, LogLen); - Status = TreeProtocol->HashLogExtendEvent ( - TreeProtocol, + Status = Tcg2Protocol->HashLogExtendEvent ( + Tcg2Protocol, 0, (EFI_PHYSICAL_ADDRESS)(UINTN)HashData, HashDataLen, - TreeEvent + Tcg2Event ); - FreePool (TreeEvent); + FreePool (Tcg2Event); return Status; } diff --git a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf index 4c61d9a217..410eb788db 100644 --- a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf +++ b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf @@ -46,4 +46,4 @@ [Protocols] gEfiTcgProtocolGuid ## SOMETIMES_CONSUMES - gEfiTrEEProtocolGuid ## SOMETIMES_CONSUMES + gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.c index 833cce2d7a..7fb5f3d1f8 100644 --- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.c +++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterCommon.c @@ -1,7 +1,7 @@ /** @file Ihis is BaseCrypto router support function. -Copyright (c) 2013, Intel Corporation. All rights reserved.
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -19,7 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include -#include +#include typedef struct { EFI_GUID Guid; @@ -27,10 +27,10 @@ typedef struct { } TPM2_HASH_MASK; TPM2_HASH_MASK mTpm2HashMask[] = { - {HASH_ALGORITHM_SHA1_GUID, TREE_BOOT_HASH_ALG_SHA1}, - {HASH_ALGORITHM_SHA256_GUID, TREE_BOOT_HASH_ALG_SHA256}, - {HASH_ALGORITHM_SHA384_GUID, TREE_BOOT_HASH_ALG_SHA384}, - {HASH_ALGORITHM_SHA512_GUID, TREE_BOOT_HASH_ALG_SHA512}, + {HASH_ALGORITHM_SHA1_GUID, HASH_ALG_SHA1}, + {HASH_ALGORITHM_SHA256_GUID, HASH_ALG_SHA256}, + {HASH_ALGORITHM_SHA384_GUID, HASH_ALG_SHA384}, + {HASH_ALGORITHM_SHA512_GUID, HASH_ALG_SHA512}, }; /** diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c index d93b33bfcf..89673373c4 100644 --- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c +++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c @@ -3,7 +3,7 @@ hash handler registerd, such as SHA1, SHA256. Platform can use PcdTpm2HashMask to mask some hash engines. -Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -44,6 +44,7 @@ HashStart ( { HASH_HANDLE *HashCtx; UINTN Index; + UINT32 HashMask; if (mHashInterfaceCount == 0) { return EFI_UNSUPPORTED; @@ -53,7 +54,10 @@ HashStart ( ASSERT (HashCtx != NULL); for (Index = 0; Index < mHashInterfaceCount; Index++) { - mHashInterface[Index].HashInit (&HashCtx[Index]); + HashMask = Tpm2GetHashMaskFromAlgo (&mHashInterface[Index].HashGuid); + if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) { + mHashInterface[Index].HashInit (&HashCtx[Index]); + } } *HashHandle = (HASH_HANDLE)HashCtx; @@ -80,6 +84,7 @@ HashUpdate ( { HASH_HANDLE *HashCtx; UINTN Index; + UINT32 HashMask; if (mHashInterfaceCount == 0) { return EFI_UNSUPPORTED; @@ -88,7 +93,10 @@ HashUpdate ( HashCtx = (HASH_HANDLE *)HashHandle; for (Index = 0; Index < mHashInterfaceCount; Index++) { - mHashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen); + HashMask = Tpm2GetHashMaskFromAlgo (&mHashInterface[Index].HashGuid); + if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) { + mHashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen); + } } return EFI_SUCCESS; @@ -119,6 +127,7 @@ HashCompleteAndExtend ( HASH_HANDLE *HashCtx; UINTN Index; EFI_STATUS Status; + UINT32 HashMask; if (mHashInterfaceCount == 0) { return EFI_UNSUPPORTED; @@ -128,9 +137,12 @@ HashCompleteAndExtend ( ZeroMem (DigestList, sizeof(*DigestList)); for (Index = 0; Index < mHashInterfaceCount; Index++) { - mHashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen); - mHashInterface[Index].HashFinal (HashCtx[Index], &Digest); - Tpm2SetHashToDigestList (DigestList, &Digest); + HashMask = Tpm2GetHashMaskFromAlgo (&mHashInterface[Index].HashGuid); + if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) { + mHashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen); + mHashInterface[Index].HashFinal (HashCtx[Index], &Digest); + Tpm2SetHashToDigestList (DigestList, &Digest); + } } FreePool (HashCtx); @@ -192,6 +204,7 @@ RegisterHashInterfaceLib ( { UINTN Index; UINT32 HashMask; + UINT32 BiosSupportedHashMask; // // Check allow @@ -204,6 +217,8 @@ RegisterHashInterfaceLib ( if (mHashInterfaceCount >= sizeof(mHashInterface)/sizeof(mHashInterface[0])) { return EFI_OUT_OF_RESOURCES; } + BiosSupportedHashMask = PcdGet32 (PcdTcg2HashAlgorithmBitmap); + PcdSet32 (PcdTcg2HashAlgorithmBitmap, BiosSupportedHashMask | HashMask); // // Check duplication diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf index 133ef09ba5..7c38ea6bc2 100644 --- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf +++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf @@ -5,7 +5,7 @@ # hash handler registered, such as SHA1, SHA256. Platform can use PcdTpm2HashMask to # mask some hash engines. # -# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
# This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License # which accompanies this distribution. The full text of the license may be found at @@ -48,5 +48,6 @@ PcdLib [Pcd] - gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap ## CONSUMES diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c index 5bc8d01ad5..98c07933d8 100644 --- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c +++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c @@ -3,7 +3,7 @@ hash handler registerd, such as SHA1, SHA256. Platform can use PcdTpm2HashMask to mask some hash engines. -Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -72,6 +72,7 @@ HashStart ( HASH_INTERFACE_HOB *HashInterfaceHob; HASH_HANDLE *HashCtx; UINTN Index; + UINT32 HashMask; HashInterfaceHob = InternalGetHashInterface (); if (HashInterfaceHob == NULL) { @@ -86,7 +87,10 @@ HashStart ( ASSERT (HashCtx != NULL); for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) { - HashInterfaceHob->HashInterface[Index].HashInit (&HashCtx[Index]); + HashMask = Tpm2GetHashMaskFromAlgo (&HashInterfaceHob->HashInterface[Index].HashGuid); + if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) { + HashInterfaceHob->HashInterface[Index].HashInit (&HashCtx[Index]); + } } *HashHandle = (HASH_HANDLE)HashCtx; @@ -114,6 +118,7 @@ HashUpdate ( HASH_INTERFACE_HOB *HashInterfaceHob; HASH_HANDLE *HashCtx; UINTN Index; + UINT32 HashMask; HashInterfaceHob = InternalGetHashInterface (); if (HashInterfaceHob == NULL) { @@ -127,7 +132,10 @@ HashUpdate ( HashCtx = (HASH_HANDLE *)HashHandle; for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) { - HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen); + HashMask = Tpm2GetHashMaskFromAlgo (&HashInterfaceHob->HashInterface[Index].HashGuid); + if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) { + HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen); + } } return EFI_SUCCESS; @@ -159,6 +167,7 @@ HashCompleteAndExtend ( HASH_HANDLE *HashCtx; UINTN Index; EFI_STATUS Status; + UINT32 HashMask; HashInterfaceHob = InternalGetHashInterface (); if (HashInterfaceHob == NULL) { @@ -173,9 +182,12 @@ HashCompleteAndExtend ( ZeroMem (DigestList, sizeof(*DigestList)); for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) { - HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen); - HashInterfaceHob->HashInterface[Index].HashFinal (HashCtx[Index], &Digest); - Tpm2SetHashToDigestList (DigestList, &Digest); + HashMask = Tpm2GetHashMaskFromAlgo (&HashInterfaceHob->HashInterface[Index].HashGuid); + if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) { + HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen); + HashInterfaceHob->HashInterface[Index].HashFinal (HashCtx[Index], &Digest); + Tpm2SetHashToDigestList (DigestList, &Digest); + } } FreePool (HashCtx); @@ -245,6 +257,7 @@ RegisterHashInterfaceLib ( HASH_INTERFACE_HOB *HashInterfaceHob; HASH_INTERFACE_HOB LocalHashInterfaceHob; UINT32 HashMask; + UINT32 BiosSupportedHashMask; // // Check allow @@ -266,6 +279,8 @@ RegisterHashInterfaceLib ( if (HashInterfaceHob->HashInterfaceCount >= HASH_COUNT) { return EFI_OUT_OF_RESOURCES; } + BiosSupportedHashMask = PcdGet32 (PcdTcg2HashAlgorithmBitmap); + PcdSet32 (PcdTcg2HashAlgorithmBitmap, BiosSupportedHashMask | HashMask); // // Check duplication diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf index 13067ee36c..c1a699fd0f 100644 --- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf +++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf @@ -5,7 +5,7 @@ # hash handler registered, such as SHA1, SHA256. Platform can use PcdTpm2HashMask to # mask some hash engines. # -# Copyright (c) 2013, Intel Corporation. All rights reserved.
+# Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
# This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License # which accompanies this distribution. The full text of the license may be found at @@ -49,5 +49,6 @@ HobLib [Pcd] - gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap ## CONSUMES diff --git a/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c b/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c index b2e01af37e..379f2f7e7e 100644 --- a/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c +++ b/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c @@ -1,7 +1,7 @@ /** @file Ihis library uses TPM2 device to calculation hash. -Copyright (c) 2013, Intel Corporation. All rights reserved.
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -20,7 +20,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include -#include typedef struct { TPM_ALG_ID AlgoId; @@ -28,10 +27,10 @@ typedef struct { } TPM2_HASH_MASK; TPM2_HASH_MASK mTpm2HashMask[] = { - {TPM_ALG_SHA1, TREE_BOOT_HASH_ALG_SHA1}, - {TPM_ALG_SHA256, TREE_BOOT_HASH_ALG_SHA256}, - {TPM_ALG_SHA384, TREE_BOOT_HASH_ALG_SHA384}, - {TPM_ALG_SHA512, TREE_BOOT_HASH_ALG_SHA512}, + {TPM_ALG_SHA1, HASH_ALG_SHA1}, + {TPM_ALG_SHA256, HASH_ALG_SHA256}, + {TPM_ALG_SHA384, HASH_ALG_SHA384}, + {TPM_ALG_SHA512, HASH_ALG_SHA512}, }; /** diff --git a/SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.c b/SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.c new file mode 100644 index 0000000000..81fe1b4d2c --- /dev/null +++ b/SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.c @@ -0,0 +1,59 @@ +/** @file + Get TPM 2.0 physical presence information. + + This library will get TPM 2.0 physical presence information. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include + +#include +#include +#include +#include + +/** + Return TPM2 ManagementFlags set by PP interface. + + @retval ManagementFlags TPM2 Management Flags. +**/ +UINT32 +EFIAPI +Tcg2PhysicalPresenceLibGetManagementFlags ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi; + EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags; + UINTN DataSize; + + Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi); + ASSERT_EFI_ERROR (Status); + + DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS); + Status = VariablePpi->GetVariable ( + VariablePpi, + TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, + &gEfiTcg2PhysicalPresenceGuid, + NULL, + &DataSize, + &PpiFlags + ); + if (EFI_ERROR (Status)) { + PpiFlags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT; + } + return PpiFlags.PPFlags; +} diff --git a/SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.inf b/SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.inf new file mode 100644 index 0000000000..6d0b7a00cb --- /dev/null +++ b/SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.inf @@ -0,0 +1,52 @@ +## @file +# Get TPM 2.0 physical presence information. +# +# This library will get TPM 2.0 physical presence information. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiTcg2PhysicalPresenceLib + MODULE_UNI_FILE = PeiTcg2PhysicalPresenceLib.uni + FILE_GUID = AB82E7BE-0970-480b-93EB-3D332B89F99E + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresenceLib|PEIM + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + PeiTcg2PhysicalPresenceLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + DebugLib + PeiServicesLib + PeiServicesTablePointerLib + +[Guids] + ## SOMETIMES_CONSUMES ## Variable:L"PhysicalPresenceFlags" + gEfiTcg2PhysicalPresenceGuid + +[Ppis] + gEfiPeiReadOnlyVariable2PpiGuid ## CONSUMES + +[Depex] + gEfiPeiReadOnlyVariable2PpiGuid \ No newline at end of file diff --git a/SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.uni b/SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.uni new file mode 100644 index 0000000000000000000000000000000000000000..d4492f69096f4e9fc2291c3cd994bef3e8fb2300 GIT binary patch literal 1754 zcmc(fTW`}q5QXO%iT_}wFM!$vD)j{+L_-Z&Kocd73Qv`Dt)*Nl$F$9#hkj=_@undN zUMgg**E>6V=FFK{|N7amhDD4QJdwS#vE??kkv+91She?&Rmq%M+rBa%TisqVU)zEHCGS0|S;JakZv5m0ge2r~^eTGlTdV!^0p@%3bXgOyikaFvDB4eyr-?E-M{K+FS zi7HN!y@%yBu?r$k;HB)Jk;syz+$dGp z4G2Rtd1FoM*xQQ7K5eA%0#1rC10{pOkhz4V^v+;8z+(mz?XAdQj(@b)f5ge0oheEO zd?~HdQeJhNyBZ32gRklh*AZ^`Rz)(Zq)v(Khhrh^z(l&J>dJM4B4*;7SDm2U1sxL3 zHLYuBtiL?q61d*FJ{j=-J=>g^LX;Z5mlSKsT3Pqu89Gq?>@^!>_x&Z#clhjbdZ>%n zQk~g%*{i?30%BBd>8j2tsl;n{lhjjQTlp7G={jc%>eJZKeu?9@TIVgyA} z`(!a}+H_Bg+uEVybWanMjL=eZiZ!9XdVIxB-=3W_$JnKWM+n*{^mB|y*CDs~QXlJG zV-~JZYs^iz*6MJJ(*^rNZMle%UEtMm%+9eVpbDeqqIXz{yKIV?;wv9T^vsuK3ydCUv0cJQ zdP&(+)Joy=r{{ng>JCh(d&XOLMxAg3mYCKa?% Izj?^{9tHRi2LJ#7 literal 0 HcmV?d00001 diff --git a/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c b/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c new file mode 100644 index 0000000000..360df720de --- /dev/null +++ b/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c @@ -0,0 +1,314 @@ +/** @file + Handle TPM 2.0 physical presence requests from OS. + + This library will handle TPM 2.0 physical presence request from OS. + + 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. + + Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction() and Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction() + will receive untrusted input and do validation. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include + +#include + +#include +#include +#include + +EFI_SMM_VARIABLE_PROTOCOL *mTcg2PpSmmVariable; + +/** + The handler for TPM physical presence function: + Return TPM Operation Response to OS Environment. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + @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 ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n")); + + // + // Get the Physical Presence variable + // + DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); + Status = mTcg2PpSmmVariable->SmmGetVariable ( + TCG2_PHYSICAL_PRESENCE_VARIABLE, + &gEfiTcg2PhysicalPresenceGuid, + NULL, + &DataSize, + &PpData + ); + if (EFI_ERROR (Status)) { + *MostRecentRequest = 0; + *Response = 0; + DEBUG ((EFI_D_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. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + 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 ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter)); + + // + // Get the Physical Presence variable + // + DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); + Status = mTcg2PpSmmVariable->SmmGetVariable ( + TCG2_PHYSICAL_PRESENCE_VARIABLE, + &gEfiTcg2PhysicalPresenceGuid, + NULL, + &DataSize, + &PpData + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_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_VENDOR_SPECIFIC_OPERATION) ) { + // + // This command requires UI to prompt user for Auth data. + // + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED; + } + + if (PpData.PPRequest != OperationRequest) { + PpData.PPRequest = (UINT8)OperationRequest; + PpData.PPRequestParameter = RequestParameter; + DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); + Status = mTcg2PpSmmVariable->SmmSetVariable ( + TCG2_PHYSICAL_PRESENCE_VARIABLE, + &gEfiTcg2PhysicalPresenceGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, + &PpData + ); + } + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_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 = mTcg2PpSmmVariable->SmmGetVariable ( + TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, + &gEfiTcg2PhysicalPresenceGuid, + NULL, + &DataSize, + &Flags + ); + if (EFI_ERROR (Status)) { + Flags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT; + } + return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter); + } + + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS; +} + +/** + The handler for TPM physical presence function: + Get User Confirmation Status for Operation. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + Caution: This function may receive untrusted input. + + @param[in] OperationRequest TPM physical presence operation request. + + @return Return Code for Get User Confirmation Status for Operation. +**/ +UINT32 +EFIAPI +Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction ( + IN UINT32 OperationRequest + ) +{ + EFI_STATUS Status; + UINTN DataSize; + EFI_TCG2_PHYSICAL_PRESENCE PpData; + EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags; + BOOLEAN RequestConfirmed; + + DEBUG ((EFI_D_INFO, "[TPM2] GetUserConfirmationStatusFunction, Request = %x\n", OperationRequest)); + + // + // Get the Physical Presence variable + // + DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE); + Status = mTcg2PpSmmVariable->SmmGetVariable ( + TCG2_PHYSICAL_PRESENCE_VARIABLE, + &gEfiTcg2PhysicalPresenceGuid, + NULL, + &DataSize, + &PpData + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status)); + return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION; + } + // + // Get the Physical Presence flags + // + DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS); + Status = mTcg2PpSmmVariable->SmmGetVariable ( + TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, + &gEfiTcg2PhysicalPresenceGuid, + NULL, + &DataSize, + &Flags + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[TPM2] Get PP flags failure! Status = %r\n", Status)); + return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION; + } + + RequestConfirmed = FALSE; + + switch (OperationRequest) { + 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; + + default: + if (OperationRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) { + RequestConfirmed = TRUE; + } else { + if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) { + return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED; + } + } + break; + } + + if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) { + return Tcg2PpVendorLibGetUserConfirmationStatusFunction (OperationRequest, Flags.PPFlags); + } + + if (RequestConfirmed) { + return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED; + } else { + return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED; + } +} + +/** + The constructor function register UNI strings into imageHandle. + + It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor successfully added string package. + @retval Other value The constructor can't add string package. +**/ +EFI_STATUS +EFIAPI +Tcg2PhysicalPresenceLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Locate SmmVariableProtocol. + // + Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mTcg2PpSmmVariable); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf b/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf new file mode 100644 index 0000000000..a351dcbaf2 --- /dev/null +++ b/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf @@ -0,0 +1,56 @@ +## @file +# Handle TPM 2.0 physical presence requests from OS. +# +# This library will handle TPM 2.0 physical presence request from OS. +# +# 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) 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmTcg2PhysicalPresenceLib + MODULE_UNI_FILE = SmmTcg2PhysicalPresenceLib.uni + FILE_GUID = AAE02741-858B-4964-9887-CA870489D944 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresenceLib|DXE_SMM_DRIVER + CONSTRUCTOR = Tcg2PhysicalPresenceLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + SmmTcg2PhysicalPresenceLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + DebugLib + Tcg2PpVendorLib + SmmServicesTableLib + +[Guids] + ## SOMETIMES_PRODUCES ## Variable:L"PhysicalPresence" + ## SOMETIMES_CONSUMES ## Variable:L"PhysicalPresence" + ## SOMETIMES_CONSUMES ## Variable:L"PhysicalPresenceFlags" + gEfiTcg2PhysicalPresenceGuid + +[Depex] + gEfiSmmVariableProtocolGuid \ No newline at end of file diff --git a/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.uni b/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.uni new file mode 100644 index 0000000000000000000000000000000000000000..c0a78097193b46debb99bfd8adbeefbfc8aa848a GIT binary patch literal 2706 zcmd6o-A@xi6vgkeiT}f-yr_XzNqiy3$j7RUN*h{&CMKk?g*NGz{ZjsU^>^;DorQq< zAYz*B?B2O^?zv~q?Ed&(vzi62C;WoFvNP-3z`FL(9uU>sTkF`!a*qaUThl%e-L$Gb zWt>>gE^NlCQ}PBLnX-PyH6qp}qUSHR@aUYGK$WSDZOC22S|AnGicxiXU@CXOctU=M z>w@R6&QO(lf0^0syuylMuwAMyYz~Vt9d5xRaUBxNnU#X6@4hRbUOLR?tSnYX#iY-Y zXqVp9Uyr*HcM+}cd(vfH(y3fC2ffewF5`7|6b)S8sHpi745VD2yNP!ZY=h?|aiMfj zTHJ50^lO|Ucr)q*FjQ5T+Pj=l)pKI{=`(w7>)hArT1=#X)=XKYfANdES!HIMd1WLt?OfsM zsVl9$cwswsU@uqBNPLnXCafF7Nj2p5c#;D3w8wfr<)@P{@wp3ljL6sCN7dr44Cp@L zM-Ai2&TU$Qr9Q&Ebog{m1c!^v@SaGIw!d$%@KWh zMh8&=bviHUD(B4Ei7kKg$x~5VkjTw;>nCG0Pt20$ldR$47HgD7n zHci~qus8f~`x~{6k^wC>wu#p9*CBVA>w9SXj2UsA{fLmXujA*8jFuxexRa0dUttuk zP%Df({;a3<5~m~Ph1&3n!H&o}aAy0&>!1pw;nfd#5_iQ^vrVpYR5fP3CRf!zF}`C) z%ys^<%PO&p%s#Gg5_%minz%_d_e$@fq@TW2HRrCFuCD(@DGk gZ|`Rmk1E{M#a+fK=y-qM_`CnMmn-}q-}L16pXRHq3;+NC literal 0 HcmV?d00001 diff --git a/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c b/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c new file mode 100644 index 0000000000..93cb312d90 --- /dev/null +++ b/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c @@ -0,0 +1,133 @@ +/** @file + NULL Tcg2 PP Vendor library instance that does not support any vendor specific PPI. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +/** + Check and execute the requested physical presence command. + + This API should be invoked in BIOS boot phase to process pending request. + + Caution: This function may receive untrusted input. + + If OperationRequest < 128, then ASSERT(). + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. + @param[in] OperationRequest TPM physical presence operation request. + @param[in, out] ManagementFlags BIOS TPM Management Flags. + @param[out] ResetRequired If reset is required to vendor settings in effect. + True, it indicates the reset is required. + False, it indicates the reset is not required. + + @return TPM Operation Response to OS Environment. +**/ +UINT32 +EFIAPI +Tcg2PpVendorLibExecutePendingRequest ( + IN TPM2B_AUTH *PlatformAuth, OPTIONAL + IN UINT32 OperationRequest, + IN OUT UINT32 *ManagementFlags, + OUT BOOLEAN *ResetRequired + ) +{ + ASSERT (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION); + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; +} + +/** + Check if there is a valid physical presence command request. + + This API should be invoked in BIOS boot phase to process pending request. + + Caution: This function may receive untrusted input. + + If OperationRequest < 128, then ASSERT(). + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] ManagementFlags BIOS TPM Management 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. + 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 +EFIAPI +Tcg2PpVendorLibHasValidRequest ( + IN UINT32 OperationRequest, + IN UINT32 ManagementFlags, + OUT BOOLEAN *RequestConfirmed + ) +{ + ASSERT (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION); + return FALSE; +} + +/** + The callback for TPM vendor specific physical presence which is called for + Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + Caution: This function may receive untrusted input. + + If OperationRequest < 128, then ASSERT(). + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] ManagementFlags BIOS TPM Management Flags. + @param[in] RequestParameter Extra parameter from the passed package. + + @return Return Code for Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. +**/ +UINT32 +EFIAPI +Tcg2PpVendorLibSubmitRequestToPreOSFunction ( + IN UINT32 OperationRequest, + IN UINT32 ManagementFlags, + IN UINT32 RequestParameter + ) +{ + ASSERT (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION); + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED; +} + +/** + The callback for TPM vendor specific physical presence which is called for + Get User Confirmation Status for Operation. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + Caution: This function may receive untrusted input. + + If OperationRequest < 128, then ASSERT(). + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] ManagementFlags BIOS TPM Management Flags. + + @return Return Code for Get User Confirmation Status for Operation. +**/ +UINT32 +EFIAPI +Tcg2PpVendorLibGetUserConfirmationStatusFunction ( + IN UINT32 OperationRequest, + IN UINT32 ManagementFlags + ) +{ + ASSERT (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION); + return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED; +} diff --git a/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf b/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf new file mode 100644 index 0000000000..f953fe95a7 --- /dev/null +++ b/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf @@ -0,0 +1,37 @@ +## @file +# NULL Tcg PP Vendor library instance that does not support any vendor specific PPI +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2PpVendorLibNull + MODULE_UNI_FILE = Tcg2PpVendorLibNull.uni + FILE_GUID = 51924AE9-BE81-4820-94BA-7C9546E702D0 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PpVendorLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + Tcg2PpVendorLibNull.c + +[Packages] + MdePkg/MdePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + DebugLib \ No newline at end of file diff --git a/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.uni b/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.uni new file mode 100644 index 0000000000000000000000000000000000000000..905a89f76686143be8090fb9b12bc95aefb37a3c GIT binary patch literal 1810 zcmds%PjAye5XI+=#CNdL3!pXuBrXUc5@NujG*RMEI8{#Krk3(gwp-xK1HZSMcta@% zZU|Z4-PxUa^Y+cyKfZUYV-fEop2%L=r4_cc-0s^wc6D}U6FcRJEVY>}n1?)(eZ*^R zbK6*nwIpuJD&zfzU2s-ejlCu+XQ#F+teTZ#a!w=8Hg2b~YuoY&OCE|6%FQo1Dm-$~ z3deHBxtJsk*TDHTNLvs}d>7;u<^v)hGC#G)_QamqG3$gpHJD4*iYa#-#IwL&Tbq+E z=kf?>;$FHtMLw<6^jf$Rg*_iV&khIwWYl{1$;%%olgee42&h?lu>clj)kxT6Q674SnpYinfMls zK2l;sJwja1#@5F^#Vc?LwfW+-m@)o-+X6O1lp0C*M)zjQvEgE#cy^Bh*5o@t2(Eq63^YYpq}#D%D;4oZEjyupAHNTb5!h1VLrE$ zTPJN$u6TnYslBrpHbc5+U~d___5nLV$p|eqr|c&5*MwE<^quf!_F0ec*&_t)6Z$#E zW9*OztklOETg<{0YKyt&Y+1(#oX$BH>cC};>>RI=V|K=V0;(_uF8c^e+_k5iDZcVi zR`2x&UuFNy{GJmr*Y_9iviMuX_Nl=M=m}a3=_cju^Ofy&+s~2vcXiyp_Kuo<@!yTt z?gEqn@%op=b^#k{B~`m9mBQsu&k^-g|1YR{#;A@{7o314mMw1cum2%if2of8YK$)G TxnWbwyA=8#)M-;gb&lSjX2~6{ literal 0 HcmV?d00001 diff --git a/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c b/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c new file mode 100644 index 0000000000..e1a92c31f4 --- /dev/null +++ b/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c @@ -0,0 +1,125 @@ +/** @file + Ihis library is TPM2 TCG2 protocol lib. + +Copyright (c) 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include + +EFI_TCG2_PROTOCOL *mTcg2Protocol = NULL; + +/** + This service enables the sending of commands to the TPM2. + + @param[in] InputParameterBlockSize Size of the TPM2 input parameter block. + @param[in] InputParameterBlock Pointer to the TPM2 input parameter block. + @param[in,out] OutputParameterBlockSize Size of the TPM2 output parameter block. + @param[in] OutputParameterBlock Pointer to the TPM2 output parameter block. + + @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received. + @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device. + @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. +**/ +EFI_STATUS +EFIAPI +Tpm2SubmitCommand ( + IN UINT32 InputParameterBlockSize, + IN UINT8 *InputParameterBlock, + IN OUT UINT32 *OutputParameterBlockSize, + IN UINT8 *OutputParameterBlock + ) +{ + EFI_STATUS Status; + TPM2_RESPONSE_HEADER *Header; + + if (mTcg2Protocol == NULL) { + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &mTcg2Protocol); + if (EFI_ERROR (Status)) { + // + // Tcg2 protocol is not installed. So, TPM2 is not present. + // + DEBUG ((EFI_D_ERROR, "Tpm2SubmitCommand - Tcg2 - %r\n", Status)); + return EFI_NOT_FOUND; + } + } + // + // Assume when Tcg2 Protocol is ready, RequestUseTpm already done. + // + Status = mTcg2Protocol->SubmitCommand ( + mTcg2Protocol, + InputParameterBlockSize, + InputParameterBlock, + *OutputParameterBlockSize, + OutputParameterBlock + ); + if (EFI_ERROR (Status)) { + return Status; + } + Header = (TPM2_RESPONSE_HEADER *)OutputParameterBlock; + *OutputParameterBlockSize = SwapBytes32 (Header->paramSize); + + return EFI_SUCCESS; +} + +/** + This service requests use TPM2. + + @retval EFI_SUCCESS Get the control of TPM2 chip. + @retval EFI_NOT_FOUND TPM2 not found. + @retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +EFIAPI +Tpm2RequestUseTpm ( + VOID + ) +{ + EFI_STATUS Status; + + if (mTcg2Protocol == NULL) { + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &mTcg2Protocol); + if (EFI_ERROR (Status)) { + // + // Tcg2 protocol is not installed. So, TPM2 is not present. + // + DEBUG ((EFI_D_ERROR, "Tpm2RequestUseTpm - Tcg2 - %r\n", Status)); + return EFI_NOT_FOUND; + } + } + // + // Assume when Tcg2 Protocol is ready, RequestUseTpm already done. + // + return EFI_SUCCESS; +} + +/** + This service register TPM2 device. + + @param Tpm2Device TPM2 device + + @retval EFI_SUCCESS This TPM2 device is registered successfully. + @retval EFI_UNSUPPORTED System does not support register this TPM2 device. + @retval EFI_ALREADY_STARTED System already register this TPM2 device. +**/ +EFI_STATUS +EFIAPI +Tpm2RegisterTpm2DeviceLib ( + IN TPM2_DEVICE_INTERFACE *Tpm2Device + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf b/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf new file mode 100644 index 0000000000..6d95ebdd50 --- /dev/null +++ b/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf @@ -0,0 +1,46 @@ +## @file +# Provides function interfaces to communicate with TPM 2.0 device +# +# This library helps to use TPM 2.0 device in library function API +# based on TPM2 protocol. +# +# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tpm2DeviceLibTcg2 + MODULE_UNI_FILE = Tpm2DeviceLibTcg2.uni + FILE_GUID = A1B0B230-67DC-431E-A94A-A96AF1EBE637 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tpm2DeviceLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF +# + +[Sources] + Tpm2DeviceLibTcg2.c + +[Packages] + MdePkg/MdePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + UefiBootServicesTableLib + +[Protocols] + gEfiTcg2ProtocolGuid ## CONSUMES diff --git a/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.uni b/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.uni new file mode 100644 index 0000000000000000000000000000000000000000..27e390d8e8a8070ea152d9f791c03d3c78a302b3 GIT binary patch literal 1970 zcmc(gTW`}q5QXO%iT|)lUjVfU6rK=5B-DTfG*K=pJXKC}m6Et}+?M=#;5)mq-I8#7 zsw{giGdpwU%-Q6}_l7mh@jl^k_QobQw}p-Ep*>(%wvJ_%+BN$l_Sfu8?8;VlVL5v# zGsn1MHO6yd36|iOV|A=jTk`14oK@mIo!zj?ZH7mm9G@AFt!_^ll}Gs$r@&E+@}6N6 zjs@e8oC)uS^$h=oU3y!{eZ_o?6CZy>hQLGL-r9TWaG(%t zLZSK>R8~|_j1J!vzYU&qn}R;)+#~!SGakdlGkebLs9e3UL+0_8>jiT~$cUk@cn$ri zV`-989#w2HmcfP?$>4Vk&vkocE$iCrJ?JW)LoHLEV@Z?*1gcrx6T9ko=<=nvZNRaj zB1hLlw}m1B&$`T`Q$iDXSEpAcmqmP?mKNlD%`0Ulur7T%uP0eE<^__V!6lI@ltL!F zQd{6h))b{y=UUdY6V{*bsIXL>y78L3;JaJx91Mym3_+L5wPvlVhu|#osxM+y=%udE zAz}W8&##!I?g~rbQYs&A&!<}kgebqot8|p3iI@KVN@0Op`DZ?2-RotF{cesmJ429< z(A-^1ohUQjijls3un06A)YC@uT@;woy5vE|oV9p1uphFwwHKBKcUyt*FQDf=-|6{GF5cUcL$_LQ@a zuY8m>c)i0{*}pP=#3JOnf6+Ees3Nj2Wt=K{3>O{Lq?{*v@4kL-8y>qj)q7BCCfuFC z-#L-m#264QvU3oLFEQJMtv+~u_Z-ke-J~gfPxwl8Qo<3jgtP|2`}}3EmDT@S< + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf + } + SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.inf + NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + } + + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf + } + + # + # TrEE - to be deprecated + # SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf { Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf @@ -237,6 +281,11 @@ SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.inf SecurityPkg/Tcg/TcgSmm/TcgSmm.inf + SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf + SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf + # + # TrEE - to be deprecated + # SecurityPkg/Tcg/TrEESmm/TrEESmm.inf # # Random Number Generator diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr b/SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr new file mode 100644 index 0000000000..fe0ef14c2f --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr @@ -0,0 +1,167 @@ +/** @file + VFR file used by the TCG2 configuration component. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Tcg2ConfigNvData.h" + +formset + guid = TCG2_CONFIG_FORM_SET_GUID, + title = STRING_TOKEN(STR_TCG2_TITLE), + help = STRING_TOKEN(STR_TCG2_HELP), + classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + + efivarstore TCG2_CONFIGURATION, + varid = TCG2_CONFIGURATION_VARSTORE_ID, + attribute = 0x03, // EFI variable attribures EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE + name = TCG2_CONFIGURATION, + guid = TCG2_CONFIG_FORM_SET_GUID; + + form formid = TCG2_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_TCG2_TITLE); + + subtitle text = STRING_TOKEN(STR_NULL); + + text + help = STRING_TOKEN(STR_TCG2_DEVICE_STATE_HELP), + text = STRING_TOKEN(STR_TCG2_DEVICE_STATE_PROMPT), + text = STRING_TOKEN(STR_TCG2_DEVICE_STATE_CONTENT); + + oneof varid = TCG2_CONFIGURATION.TpmDevice, + questionid = KEY_TPM_DEVICE, + prompt = STRING_TOKEN(STR_TCG2_DEVICE_PROMPT), + help = STRING_TOKEN(STR_TCG2_DEVICE_HELP), + flags = INTERACTIVE, + option text = STRING_TOKEN(STR_TCG2_TPM_1_2), value = TPM_DEVICE_1_2, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_TCG2_TPM_2_0_DTPM), value = TPM_DEVICE_2_0_DTPM, flags = RESET_REQUIRED; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL); + + suppressif ideqvallist TCG2_CONFIGURATION.TpmDevice == TPM_DEVICE_NULL TPM_DEVICE_1_2; + text + help = STRING_TOKEN(STR_TPM2_ACTIVE_HASH_ALGO_HELP), + text = STRING_TOKEN(STR_TPM2_ACTIVE_HASH_ALGO), + text = STRING_TOKEN(STR_TPM2_ACTIVE_HASH_ALGO_CONTENT); + text + help = STRING_TOKEN(STR_TPM2_SUPPORTED_HASH_ALGO_HELP), + text = STRING_TOKEN(STR_TPM2_SUPPORTED_HASH_ALGO), + text = STRING_TOKEN(STR_TPM2_SUPPORTED_HASH_ALGO_CONTENT); + text + help = STRING_TOKEN(STR_BIOS_HASH_ALGO_HELP), + text = STRING_TOKEN(STR_BIOS_HASH_ALGO), + text = STRING_TOKEN(STR_BIOS_HASH_ALGO_CONTENT); + + subtitle text = STRING_TOKEN(STR_NULL); + subtitle text = STRING_TOKEN(STR_TCG2_PP_OPERATION); + + oneof name = Tpm2Operation, + questionid = KEY_TPM2_OPERATION, + prompt = STRING_TOKEN(STR_TCG2_OPERATION), + help = STRING_TOKEN(STR_TCG2_OPERATION_HELP), + flags = INTERACTIVE | NUMERIC_SIZE_1, + option text = STRING_TOKEN(STR_TCG2_NO_ACTION), value = TCG2_PHYSICAL_PRESENCE_NO_ACTION, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_TCG2_ENABLE), value = TCG2_PHYSICAL_PRESENCE_ENABLE, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_TCG2_DISABLE), value = TCG2_PHYSICAL_PRESENCE_DISABLE, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_TCG2_CLEAR), value = TCG2_PHYSICAL_PRESENCE_CLEAR, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_TCG2_SET_PCD_BANKS), value = TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_TCG2_CHANGE_EPS), value = TCG2_PHYSICAL_PRESENCE_CHANGE_EPS, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_TCG2_LOG_ALL_DIGESTS), value = TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_TCG2_DISABLE_ENDORSEMENT_ENABLE_STORAGE_HIERARCHY), value = TCG2_PHYSICAL_PRESENCE_DISABLE_ENDORSEMENT_ENABLE_STORAGE_HIERARCHY, flags = RESET_REQUIRED; + + option text = STRING_TOKEN(STR_TCG2_ENABLE_BLOCK_SID), value = TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_TCG2_DISABLE_BLOCK_SID), value = TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID, flags = RESET_REQUIRED; + endoneof; + + suppressif NOT questionref(Tpm2Operation) == TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS; + numeric name = Tpm2OperationParameter, + questionid = KEY_TPM2_OPERATION_PARAMETER, + prompt = STRING_TOKEN(STR_TCG2_OPERATION_PARAMETER), + help = STRING_TOKEN(STR_TCG2_OPERATION_PARAMETER_HELP), + flags = DISPLAY_UINT_HEX | INTERACTIVE | NUMERIC_SIZE_4, + minimum = 0, + maximum = 0xFFFFFFFF, + step = 0, + default = 0, + endnumeric; + endif; + + subtitle text = STRING_TOKEN(STR_NULL); + subtitle text = STRING_TOKEN(STR_TCG2_CONFIGURATION); + + text + help = STRING_TOKEN(STR_TCG2_SUPPORTED_EVENT_LOG_FORMAT_HELP), + text = STRING_TOKEN(STR_TCG2_SUPPORTED_EVENT_LOG_FORMAT), + text = STRING_TOKEN(STR_TCG2_SUPPORTED_EVENT_LOG_FORMAT_CONTENT); + + text + help = STRING_TOKEN(STR_TCG2_HASH_ALGO_BITMAP_HELP), + text = STRING_TOKEN(STR_TCG2_HASH_ALGO_BITMAP), + text = STRING_TOKEN(STR_TCG2_HASH_ALGO_BITMAP_CONTENT); + + text + help = STRING_TOKEN(STR_TCG2_NUMBER_OF_PCR_BANKS_HELP), + text = STRING_TOKEN(STR_TCG2_NUMBER_OF_PCR_BANKS), + text = STRING_TOKEN(STR_TCG2_NUMBER_OF_PCR_BANKS_CONTENT); + + text + help = STRING_TOKEN(STR_TCG2_ACTIVE_PCR_BANKS_HELP), + text = STRING_TOKEN(STR_TCG2_ACTIVE_PCR_BANKS), + text = STRING_TOKEN(STR_TCG2_ACTIVE_PCR_BANKS_CONTENT); + + subtitle text = STRING_TOKEN(STR_NULL); + + checkbox name = TCG2ActivatePCRBank0, + questionid = KEY_TPM2_PCR_BANKS_REQUEST_0, + prompt = STRING_TOKEN(STR_TCG2_PCR_BANK_SHA1), + help = STRING_TOKEN(STR_TCG2_PCR_BANK_SHA1_HELP), + flags = INTERACTIVE, + default = 1, + endcheckbox; + + checkbox name = TCG2ActivatePCRBank1, + questionid = KEY_TPM2_PCR_BANKS_REQUEST_1, + prompt = STRING_TOKEN(STR_TCG2_PCR_BANK_SHA256), + help = STRING_TOKEN(STR_TCG2_PCR_BANK_SHA256_HELP), + flags = INTERACTIVE, + default = 0, + endcheckbox; + + checkbox name = TCG2ActivatePCRBank2, + questionid = KEY_TPM2_PCR_BANKS_REQUEST_2, + prompt = STRING_TOKEN(STR_TCG2_PCR_BANK_SHA384), + help = STRING_TOKEN(STR_TCG2_PCR_BANK_SHA384_HELP), + flags = INTERACTIVE, + default = 0, + endcheckbox; + + checkbox name = TCG2ActivatePCRBank3, + questionid = KEY_TPM2_PCR_BANKS_REQUEST_3, + prompt = STRING_TOKEN(STR_TCG2_PCR_BANK_SHA512), + help = STRING_TOKEN(STR_TCG2_PCR_BANK_SHA512_HELP), + flags = INTERACTIVE, + default = 0, + endcheckbox; + + checkbox name = TCG2ActivatePCRBank4, + questionid = KEY_TPM2_PCR_BANKS_REQUEST_4, + prompt = STRING_TOKEN(STR_TCG2_PCR_BANK_SM3_256), + help = STRING_TOKEN(STR_TCG2_PCR_BANK_SM3_256_HELP), + flags = INTERACTIVE, + default = 0, + endcheckbox; + + endif; + + endform; + +endformset; diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c new file mode 100644 index 0000000000..881368345b --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c @@ -0,0 +1,280 @@ +/** @file + The module entry point for Tcg2 configuration module. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Tcg2ConfigImpl.h" + +extern TPM_INSTANCE_ID mTpmInstanceId[TPM_DEVICE_MAX + 1]; + +/** + Update default PCR banks data. + + @param[in] HiiPackage HII Package. + @param[in] HiiPackageSize HII Package size. + @param[in] PCRBanks PCR Banks data. + +**/ +VOID +UpdateDefaultPCRBanks ( + IN VOID *HiiPackage, + IN UINTN HiiPackageSize, + IN UINT32 PCRBanks + ) +{ + EFI_HII_PACKAGE_HEADER *HiiPackageHeader; + EFI_IFR_OP_HEADER *IfrOpCodeHeader; + EFI_IFR_CHECKBOX *IfrCheckBox; + EFI_IFR_DEFAULT *IfrDefault; + + HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiPackage; + + switch (HiiPackageHeader->Type) { + case EFI_HII_PACKAGE_FORMS: + IfrOpCodeHeader = (EFI_IFR_OP_HEADER *)(HiiPackageHeader + 1); + while ((UINTN)IfrOpCodeHeader < (UINTN)HiiPackageHeader + HiiPackageHeader->Length) { + switch (IfrOpCodeHeader->OpCode) { + case EFI_IFR_CHECKBOX_OP: + IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpCodeHeader; + if ((IfrCheckBox->Question.QuestionId >= KEY_TPM2_PCR_BANKS_REQUEST_0) && (IfrCheckBox->Question.QuestionId <= KEY_TPM2_PCR_BANKS_REQUEST_4)) { + IfrDefault = (EFI_IFR_DEFAULT *)(IfrCheckBox + 1); + ASSERT (IfrDefault->Header.OpCode == EFI_IFR_DEFAULT_OP); + ASSERT (IfrDefault->Type == EFI_IFR_TYPE_BOOLEAN); + IfrDefault->Value.b = (BOOLEAN)((PCRBanks >> (IfrCheckBox->Question.QuestionId - KEY_TPM2_PCR_BANKS_REQUEST_0)) & 0x1); + } + break; + } + IfrOpCodeHeader = (EFI_IFR_OP_HEADER *)((UINTN)IfrOpCodeHeader + IfrOpCodeHeader->Length); + } + break; + } + return ; +} + +/** + The entry point for Tcg2 configuration driver. + + @param[in] ImageHandle The image handle of the driver. + @param[in] SystemTable The system table. + + @retval EFI_ALREADY_STARTED The driver already exists in system. + @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of resources. + @retval EFI_SUCCES All the related protocols are installed on the driver. + @retval Others Fail to install protocols as indicated. + +**/ +EFI_STATUS +EFIAPI +Tcg2ConfigDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + TCG2_CONFIG_PRIVATE_DATA *PrivateData; + TCG2_CONFIGURATION Tcg2Configuration; + TCG2_DEVICE_DETECTION Tcg2DeviceDetection; + UINTN Index; + UINTN DataSize; + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol; + UINT32 CurrentActivePCRBanks; + + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiCallerIdGuid, + NULL, + ImageHandle, + ImageHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + return EFI_ALREADY_STARTED; + } + + // + // Create a private data structure. + // + PrivateData = AllocateCopyPool (sizeof (TCG2_CONFIG_PRIVATE_DATA), &mTcg2ConfigPrivateDateTemplate); + ASSERT (PrivateData != NULL); + mTcg2ConfigPrivateDate = PrivateData; + // + // Install private GUID. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiCallerIdGuid, + PrivateData, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &PrivateData->Tcg2Protocol); + ASSERT_EFI_ERROR (Status); + + PrivateData->ProtocolCapability.Size = sizeof(PrivateData->ProtocolCapability); + Status = PrivateData->Tcg2Protocol->GetCapability ( + PrivateData->Tcg2Protocol, + &PrivateData->ProtocolCapability + ); + ASSERT_EFI_ERROR (Status); + + DataSize = sizeof(Tcg2Configuration); + Status = gRT->GetVariable ( + TCG2_STORAGE_NAME, + &gTcg2ConfigFormSetGuid, + NULL, + &DataSize, + &Tcg2Configuration + ); + if (EFI_ERROR (Status)) { + // + // Variable not ready, set default value + // + Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT; + } + + // + // Validation + // + if ((Tcg2Configuration.TpmDevice > TPM_DEVICE_MAX) || (Tcg2Configuration.TpmDevice < TPM_DEVICE_MIN)) { + Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT; + } + + // + // Set value for Tcg2CurrentActivePCRBanks + // Search Tcg2ConfigBin[] and update default value there + // + Status = PrivateData->Tcg2Protocol->GetActivePcrBanks (PrivateData->Tcg2Protocol, &CurrentActivePCRBanks); + ASSERT_EFI_ERROR (Status); + PrivateData->PCRBanksDesired = CurrentActivePCRBanks; + UpdateDefaultPCRBanks (Tcg2ConfigBin + sizeof(UINT32), ReadUnaligned32((UINT32 *)Tcg2ConfigBin) - sizeof(UINT32), CurrentActivePCRBanks); + + // + // Save to variable so platform driver can get it. + // + Status = gRT->SetVariable ( + TCG2_STORAGE_NAME, + &gTcg2ConfigFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(Tcg2Configuration), + &Tcg2Configuration + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_STORAGE_NAME\n")); + } + + // + // Sync data from PCD to variable, so that we do not need detect again in S3 phase. + // + Tcg2DeviceDetection.TpmDeviceDetected = TPM_DEVICE_NULL; + for (Index = 0; Index < sizeof(mTpmInstanceId)/sizeof(mTpmInstanceId[0]); Index++) { + if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &mTpmInstanceId[Index].TpmInstanceGuid)) { + Tcg2DeviceDetection.TpmDeviceDetected = mTpmInstanceId[Index].TpmDevice; + break; + } + } + + PrivateData->TpmDeviceDetected = Tcg2DeviceDetection.TpmDeviceDetected; + + // + // Save to variable so platform driver can get it. + // + Status = gRT->SetVariable ( + TCG2_DEVICE_DETECTION_NAME, + &gTcg2ConfigFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(Tcg2DeviceDetection), + &Tcg2DeviceDetection + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_DEVICE_DETECTION_NAME\n")); + Status = gRT->SetVariable ( + TCG2_DEVICE_DETECTION_NAME, + &gTcg2ConfigFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + + // + // We should lock Tcg2DeviceDetection, because it contains information needed at S3. + // + Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol); + if (!EFI_ERROR (Status)) { + Status = VariableLockProtocol->RequestToLock ( + VariableLockProtocol, + TCG2_DEVICE_DETECTION_NAME, + &gTcg2ConfigFormSetGuid + ); + ASSERT_EFI_ERROR (Status); + } + + // + // Install Tcg2 configuration form + // + Status = InstallTcg2ConfigForm (PrivateData); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + return EFI_SUCCESS; + +ErrorExit: + if (PrivateData != NULL) { + UninstallTcg2ConfigForm (PrivateData); + } + + return Status; +} + +/** + Unload the Tcg2 configuration form. + + @param[in] ImageHandle The driver's image handle. + + @retval EFI_SUCCESS The Tcg2 configuration form is unloaded. + @retval Others Failed to unload the form. + +**/ +EFI_STATUS +EFIAPI +Tcg2ConfigDriverUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + TCG2_CONFIG_PRIVATE_DATA *PrivateData; + + Status = gBS->HandleProtocol ( + ImageHandle, + &gEfiCallerIdGuid, + (VOID **) &PrivateData + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (PrivateData->Signature == TCG2_CONFIG_PRIVATE_DATA_SIGNATURE); + + gBS->UninstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiCallerIdGuid, + PrivateData, + NULL + ); + + UninstallTcg2ConfigForm (PrivateData); + + return EFI_SUCCESS; +} diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf new file mode 100644 index 0000000000..ba76541bd9 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf @@ -0,0 +1,87 @@ +## @file +# TPM device configuration for TPM 2.0 +# +# By this module, user may select TPM device, clear TPM state, etc. +# NOTE: This module is only for reference only, each platform should have its own setup page. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2ConfigDxe + MODULE_UNI_FILE = Tcg2ConfigDxe.uni + FILE_GUID = 4D9CBEF0-15A0-4D0C-83DB-5213E710C23F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = Tcg2ConfigDriverEntryPoint + UNLOAD_IMAGE = Tcg2ConfigDriverUnload + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + Tcg2ConfigDriver.c + Tcg2ConfigImpl.c + Tcg2ConfigImpl.h + Tcg2Config.vfr + Tcg2ConfigStrings.uni + Tcg2ConfigNvData.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + UefiHiiServicesLib + DebugLib + HiiLib + PcdLib + PrintLib + Tpm2DeviceLib + Tpm2CommandLib + Tcg2PhysicalPresenceLib + +[Guids] + ## PRODUCES ## HII + ## SOMETIMES_PRODUCES ## Variable:L"TCG2_CONFIGURATION" + ## SOMETIMES_CONSUMES ## Variable:L"TCG2_CONFIGURATION" + ## PRODUCES ## Variable:L"TCG2_DEVICE_DETECTION" + ## SOMETIMES_CONSUMES ## Variable:L"TCG2_DEVICE_DETECTION" + gTcg2ConfigFormSetGuid + +[Protocols] + gEfiHiiConfigAccessProtocolGuid ## PRODUCES + gEfiDevicePathProtocolGuid ## PRODUCES + gEdkiiVariableLockProtocolGuid ## CONSUMES + gEfiTcg2ProtocolGuid ## CONSUMES + +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap ## CONSUMES + +[Depex] + gEfiTcg2ProtocolGuid AND + gEfiHiiConfigRoutingProtocolGuid AND + gEfiHiiDatabaseProtocolGuid AND + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + Tcg2ConfigDxeExtra.uni diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.uni b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.uni new file mode 100644 index 0000000000000000000000000000000000000000..a5b2040b49602a80f20b25fb1d719e6bef70820c GIT binary patch literal 2124 zcmdUwTW`}q5QXO%iT_}wFMvu5m3XNTqM-pSAc+!3g{R87wo-FZob>YNf$z-5-lQsm z2PA|dd$Y4MXU?3RUH|xgXor^YJmZ(xTN~S@UD?PU+as)6%dBl*7>8J|SsgGYyyrG^ z?}@E#X}PUflP$qI#}Xrt?7&`Bh!MGNcX+Mrg2;k@Q{sl8DgQq6HP(?MO~IG1=2{&P z74f&3DQ@6C`3{GI2yqO^BmNCw6}dF6MWqcpcHD;;B^#Ei@ygkhbuK|2^JtubD}72Y z@fneMK$VFth!l$uImJ?7pL@+iW*4kpd;BF{(qwKouBj?t;kR&<+$PK;|5(R6A{MY) z!gd0lbb3Per;JDJ!b^MQ+NPjNjVtVmSrVmp+{Xh}PFR;mL=z{~8Fofohwyl9b?exh zO3%nAgG1Qe1#xpYDTgZ0VW66||58jEsjH?i(b^qxGyK&TVdummhfh)EQIyyuSVL#d zoSAS-d_}86WVz;1f9KZcE!)~zgf1(YNS7s9Rcnb7`h7@r+2>(*#`u(Rb?e$G^Uph6 zq82xFfY?!RQ8)P3rg3G2H#3M_p*hxYv5$^j@BJW-L%K62&~ zZkP_|?*s1>ziU#IOwdwehBc+XdVW5oZ_k>nHLy#GfDpA$>E{L>T}N*5PkpR+jZwHl ztufYpuG#(;r!&@t+VYHvo#EASW=-rVsKRJ@_6{>~mrXe{eC4C8!RtM~%KnY<6Dwk_ zJE5`35~^s}*9s@1r)bfpo0RkP!PBl=`_Q>dQ$2fC&xErR^g9Qs1x63FhMmJmdP&(6 z)XL!VtKXiV7GbUF5ZyYu&t~jx&nv7E{dc|(wW^Lkt3e&mg}u6?U8(+19lx*P-+ze` MI^%!*0>xeX3Db>EcmMzZ literal 0 HcmV?d00001 diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxeExtra.uni b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxeExtra.uni new file mode 100644 index 0000000000000000000000000000000000000000..c2571d74befa237adc3a176015ab656db5f67a45 GIT binary patch literal 1382 zcmZvc-ER^>6vfZ8iT}ffzEsnKlK5hbv6QtETObtD`qc2zQj+qK1>52uul~*q%ThF( z-I=*_@408ry*qz?S5#5L`<5rs7u{*12i@wmUSaiKS3`|e)v4y1h5fPWdd4TwIkutt zL`?Jx%Lv=0R?1klrM++S!NV#m72C($A3Zy2k3r}z4xBj$|| ze@o67lW75qj65r{nq!%r6ZY+4CK1hCGO{muGd%{jWqndj9ew@}pDr9G;RFl(=b$*p z6qNi#D?F@1AC^NrrZDl|dUN^&i&;6}gxLdV#d-T!9c}G~%w~a^mCErQJ=$b=WbVrJ zHQ?*GpG0^!W1cgKxu$`2j$&r^oNV>65_2k9#MP);o%Q((E(O=8pv92yzo(tR!HDJ% z^>VHyYoB@m&)vFMRkOdt9xG(d&-mh>DU2ky;^afhA=_co_ z^FQXg +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Tcg2ConfigImpl.h" +#include +#include +#include + +#define EFI_TCG2_EVENT_LOG_FORMAT_ALL (EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) + +TPM_INSTANCE_ID mTpmInstanceId[TPM_DEVICE_MAX + 1] = TPM_INSTANCE_ID_LIST; + +TCG2_CONFIG_PRIVATE_DATA *mTcg2ConfigPrivateDate; +TCG2_CONFIG_PRIVATE_DATA mTcg2ConfigPrivateDateTemplate = { + TCG2_CONFIG_PRIVATE_DATA_SIGNATURE, + { + Tcg2ExtractConfig, + Tcg2RouteConfig, + Tcg2Callback + } +}; + +HII_VENDOR_DEVICE_PATH mTcg2HiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + TCG2_CONFIG_FORM_SET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +UINT8 mCurrentPpRequest; + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Request A null-terminated Unicode string in + format. + @param[out] Progress On return, points to a character in the Request + string. Points to the string's null terminator if + request was successful. Points to the most recent + '&' before the first failing name/value pair (or + the beginning of the string if the failure is in + the first name/value pair) if the request was not + successful. + @param[out] Results A null-terminated Unicode string in + format which has all values filled + in for the names in the Request string. String to + be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this + driver. + +**/ +EFI_STATUS +EFIAPI +Tcg2ExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Request; + return EFI_NOT_FOUND; +} + +/** + Save TPM request to variable space. + + @param[in] PpRequest Physical Presence request command. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +SaveTcg2PpRequest ( + IN UINT8 PpRequest + ) +{ + UINT32 ReturnCode; + EFI_STATUS Status; + + ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (PpRequest, 0); + if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) { + mCurrentPpRequest = PpRequest; + Status = EFI_SUCCESS; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) { + Status = EFI_OUT_OF_RESOURCES; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + +/** + Save TPM request to variable space. + + @param[in] PpRequestParameter Physical Presence request parameter. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +SaveTcg2PpRequestParameter ( + IN UINT32 PpRequestParameter + ) +{ + UINT32 ReturnCode; + EFI_STATUS Status; + + ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (mCurrentPpRequest, PpRequestParameter); + if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) { + Status = EFI_SUCCESS; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) { + Status = EFI_OUT_OF_RESOURCES; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + +/** + Save Tcg2 PCR Banks request request to variable space. + + @param[in] PCRBankIndex PCR Bank Index. + @param[in] Enable Enable or disable this PCR Bank. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +SaveTcg2PCRBanksRequest ( + IN UINTN PCRBankIndex, + IN BOOLEAN Enable + ) +{ + UINT32 ReturnCode; + EFI_STATUS Status; + + if (Enable) { + mTcg2ConfigPrivateDate->PCRBanksDesired |= (0x1 << PCRBankIndex); + } else { + mTcg2ConfigPrivateDate->PCRBanksDesired &= ~(0x1 << PCRBankIndex); + } + + ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS, mTcg2ConfigPrivateDate->PCRBanksDesired); + if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) { + Status = EFI_SUCCESS; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) { + Status = EFI_OUT_OF_RESOURCES; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + +/** + This function processes the results of changes in configuration. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Configuration A null-terminated Unicode string in + format. + @param[out] Progress A pointer to a string filled in with the offset of + the most recent '&' before the first failing + name/value pair (or the beginning of the string if + the failure is in the first name/value pair) or + the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this + driver. + +**/ +EFI_STATUS +EFIAPI +Tcg2RouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_NOT_FOUND; +} + +/** + This function processes the results of changes in configuration. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Action Specifies the type of action taken by the browser. + @param[in] QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param[in] Type The type of value for the question. + @param[in] Value A pointer to the data being sent to the original + exporting driver. + @param[out] ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the + callback. + +**/ +EFI_STATUS +EFIAPI +Tcg2Callback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (Action == EFI_BROWSER_ACTION_CHANGED) { + if (QuestionId == KEY_TPM_DEVICE) { + return EFI_SUCCESS; + } + if (QuestionId == KEY_TPM2_OPERATION) { + return SaveTcg2PpRequest (Value->u8); + } + if (QuestionId == KEY_TPM2_OPERATION_PARAMETER) { + return SaveTcg2PpRequestParameter (Value->u32); + } + if ((QuestionId >= KEY_TPM2_PCR_BANKS_REQUEST_0) && (QuestionId <= KEY_TPM2_PCR_BANKS_REQUEST_4)) { + SaveTcg2PCRBanksRequest (QuestionId - KEY_TPM2_PCR_BANKS_REQUEST_0, Value->b); + } + } + + return EFI_UNSUPPORTED; +} + +/** + Append Buffer With TpmAlgHash. + + @param[in] Buffer Buffer to be appended. + @param[in] BufferSize Size of buffer. + @param[in] TpmAlgHash TpmAlgHash. + +**/ +VOID +AppendBufferWithTpmAlgHash ( + IN UINT16 *Buffer, + IN UINTN BufferSize, + IN UINT32 TpmAlgHash + ) +{ + switch (TpmAlgHash) { + case TPM_ALG_SHA1: + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + break; + case TPM_ALG_SHA256: + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + break; + case TPM_ALG_SHA384: + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + break; + case TPM_ALG_SHA512: + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + break; + case TPM_ALG_SM3_256: + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + break; + } +} + +/** + Fill Buffer With BootHashAlg. + + @param[in] Buffer Buffer to be filled. + @param[in] BufferSize Size of buffer. + @param[in] BootHashAlg BootHashAlg. + +**/ +VOID +FillBufferWithBootHashAlg ( + 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) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) { + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) { + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) { + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) { + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } +} + +/** + Fill Buffer With TCG2EventLogFormat. + + @param[in] Buffer Buffer to be filled. + @param[in] BufferSize Size of buffer. + @param[in] TCG2EventLogFormat TCG2EventLogFormat. + +**/ +VOID +FillBufferWithTCG2EventLogFormat ( + IN UINT16 *Buffer, + IN UINTN BufferSize, + IN UINT32 TCG2EventLogFormat + ) +{ + Buffer[0] = 0; + if ((TCG2EventLogFormat & EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2) != 0) { + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"TCG_1_2", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((TCG2EventLogFormat & EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) != 0) { + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"TCG_2", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + if ((TCG2EventLogFormat & (~EFI_TCG2_EVENT_LOG_FORMAT_ALL)) != 0) { + if (Buffer[0] != 0) { + StrnCat (Buffer, L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + StrnCat (Buffer, L"UNKNOWN", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } +} + +/** + Check if buffer is all zero. + + @param[in] Buffer Buffer to be checked. + @param[in] BufferSize Size of buffer to be checked. + + @retval TRUE Buffer is all zero. + @retval FALSE Buffer is not all zero. +**/ +BOOLEAN +IsZeroBuffer ( + IN VOID *Buffer, + IN UINTN BufferSize + ) +{ + UINT8 *BufferData; + UINTN Index; + + BufferData = Buffer; + for (Index = 0; Index < BufferSize; Index++) { + if (BufferData[Index] != 0) { + return FALSE; + } + } + return TRUE; +} + +/** + This function publish the TCG2 configuration Form for TPM device. + + @param[in, out] PrivateData Points to TCG2 configuration private data. + + @retval EFI_SUCCESS HII Form is installed for this network device. + @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +InstallTcg2ConfigForm ( + IN OUT TCG2_CONFIG_PRIVATE_DATA *PrivateData + ) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + UINTN Index; + TPML_PCR_SELECTION Pcrs; + CHAR16 TempBuffer[1024]; + + DriverHandle = NULL; + ConfigAccess = &PrivateData->ConfigAccess; + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverHandle, + &gEfiDevicePathProtocolGuid, + &mTcg2HiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + ConfigAccess, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + PrivateData->DriverHandle = DriverHandle; + + // + // Publish the HII package list + // + HiiHandle = HiiAddPackages ( + &gTcg2ConfigFormSetGuid, + DriverHandle, + Tcg2ConfigDxeStrings, + Tcg2ConfigBin, + NULL + ); + if (HiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + DriverHandle, + &gEfiDevicePathProtocolGuid, + &mTcg2HiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + ConfigAccess, + NULL + ); + + return EFI_OUT_OF_RESOURCES; + } + + PrivateData->HiiHandle = HiiHandle; + + // + // Update static data + // + switch (PrivateData->TpmDeviceDetected) { + case TPM_DEVICE_NULL: + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"Not Found", NULL); + break; + case TPM_DEVICE_1_2: + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"TPM 1.2", NULL); + break; + case TPM_DEVICE_2_0_DTPM: + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"TPM 2.0 (DTPM)", NULL); + break; + default: + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"Unknown", NULL); + break; + } + + Status = Tpm2GetCapabilityPcrs (&Pcrs); + if (EFI_ERROR (Status)) { + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM2_ACTIVE_HASH_ALGO_CONTENT), L"[Unknown]", NULL); + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM2_SUPPORTED_HASH_ALGO_CONTENT), L"[Unknown]", NULL); + } else { + TempBuffer[0] = 0; + for (Index = 0; Index < Pcrs.count; Index++) { + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + AppendBufferWithTpmAlgHash (TempBuffer, sizeof(TempBuffer), Pcrs.pcrSelections[Index].hash); + } + } + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM2_ACTIVE_HASH_ALGO_CONTENT), TempBuffer, NULL); + + TempBuffer[0] = 0; + for (Index = 0; Index < Pcrs.count; Index++) { + AppendBufferWithTpmAlgHash (TempBuffer, sizeof(TempBuffer), Pcrs.pcrSelections[Index].hash); + } + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM2_SUPPORTED_HASH_ALGO_CONTENT), TempBuffer, NULL); + } + + FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), PcdGet32 (PcdTcg2HashAlgorithmBitmap)); + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_BIOS_HASH_ALGO_CONTENT), TempBuffer, NULL); + + // + // Tcg2 Capability + // + FillBufferWithTCG2EventLogFormat (TempBuffer, sizeof(TempBuffer), PrivateData->ProtocolCapability.SupportedEventLogs); + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_SUPPORTED_EVENT_LOG_FORMAT_CONTENT), TempBuffer, NULL); + + FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), PrivateData->ProtocolCapability.HashAlgorithmBitmap); + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_HASH_ALGO_BITMAP_CONTENT), TempBuffer, NULL); + + UnicodeSPrint (TempBuffer, sizeof (TempBuffer), L"%d", PrivateData->ProtocolCapability.NumberOfPCRBanks); + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_NUMBER_OF_PCR_BANKS_CONTENT), TempBuffer, NULL); + + FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), PrivateData->ProtocolCapability.ActivePcrBanks); + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_ACTIVE_PCR_BANKS_CONTENT), TempBuffer, NULL); + + return EFI_SUCCESS; +} + +/** + This function removes TCG2 configuration Form. + + @param[in, out] PrivateData Points to TCG2 configuration private data. + +**/ +VOID +UninstallTcg2ConfigForm ( + IN OUT TCG2_CONFIG_PRIVATE_DATA *PrivateData + ) +{ + // + // Uninstall HII package list + // + if (PrivateData->HiiHandle != NULL) { + HiiRemovePackages (PrivateData->HiiHandle); + PrivateData->HiiHandle = NULL; + } + + // + // Uninstall HII Config Access Protocol + // + if (PrivateData->DriverHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + PrivateData->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mTcg2HiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &PrivateData->ConfigAccess, + NULL + ); + PrivateData->DriverHandle = NULL; + } + + FreePool (PrivateData); +} diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.h b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.h new file mode 100644 index 0000000000..1b9a8452e0 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.h @@ -0,0 +1,197 @@ +/** @file + The header file of HII Config Access protocol implementation of TCG2 + configuration module. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TCG2_CONFIG_IMPL_H__ +#define __TCG2_CONFIG_IMPL_H__ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Tcg2ConfigNvData.h" + +// +// Tool generated IFR binary data and String package data +// +extern UINT8 Tcg2ConfigBin[]; +extern UINT8 Tcg2ConfigDxeStrings[]; + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +typedef struct { + UINTN Signature; + + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + UINT8 TpmDeviceDetected; + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability; + UINT32 PCRBanksDesired; +} TCG2_CONFIG_PRIVATE_DATA; + +extern TCG2_CONFIG_PRIVATE_DATA mTcg2ConfigPrivateDateTemplate; +extern TCG2_CONFIG_PRIVATE_DATA *mTcg2ConfigPrivateDate; +#define TCG2_CONFIG_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('T', 'r', 'E', 'D') +#define TCG2_CONFIG_PRIVATE_DATA_FROM_THIS(a) CR (a, TCG2_CONFIG_PRIVATE_DATA, ConfigAccess, TCG2_CONFIG_PRIVATE_DATA_SIGNATURE) + + +/** + This function publish the TCG2 configuration Form for TPM device. + + @param[in, out] PrivateData Points to TCG2 configuration private data. + + @retval EFI_SUCCESS HII Form is installed for this network device. + @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +InstallTcg2ConfigForm ( + IN OUT TCG2_CONFIG_PRIVATE_DATA *PrivateData + ); + +/** + This function removes TCG2 configuration Form. + + @param[in, out] PrivateData Points to TCG2 configuration private data. + +**/ +VOID +UninstallTcg2ConfigForm ( + IN OUT TCG2_CONFIG_PRIVATE_DATA *PrivateData + ); + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Request A null-terminated Unicode string in + format. + @param[out] Progress On return, points to a character in the Request + string. Points to the string's null terminator if + request was successful. Points to the most recent + '&' before the first failing name/value pair (or + the beginning of the string if the failure is in + the first name/value pair) if the request was not + successful. + @param[out] Results A null-terminated Unicode string in + format which has all values filled + in for the names in the Request string. String to + be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this + driver. + +**/ +EFI_STATUS +EFIAPI +Tcg2ExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ); + +/** + This function processes the results of changes in configuration. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Configuration A null-terminated Unicode string in + format. + @param[out] Progress A pointer to a string filled in with the offset of + the most recent '&' before the first failing + name/value pair (or the beginning of the string if + the failure is in the first name/value pair) or + the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this + driver. + +**/ +EFI_STATUS +EFIAPI +Tcg2RouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ); + +/** + This function processes the results of changes in configuration. + + @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param[in] Action Specifies the type of action taken by the browser. + @param[in] QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param[in] Type The type of value for the question. + @param[in] Value A pointer to the data being sent to the original + exporting driver. + @param[out] ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the + callback. + +**/ +EFI_STATUS +EFIAPI +Tcg2Callback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +#endif diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h new file mode 100644 index 0000000000..65044c2bd5 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h @@ -0,0 +1,94 @@ +/** @file + Header file for NV data structure definition. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TCG2_CONFIG_NV_DATA_H__ +#define __TCG2_CONFIG_NV_DATA_H__ + +#include +#include +#include + +// +// BUGBUG: In order to pass VfrCompiler, we have to redefine below MACRO, which already in . +// +#ifndef __TCG2_H__ +#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x00000001 +#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002 +#endif +#define EFI_TCG2_EVENT_LOG_FORMAT_ALL (EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) + +#define TCG2_CONFIGURATION_VARSTORE_ID 0x0001 +#define TCG2_CONFIGURATION_FORM_ID 0x0001 + +#define KEY_TPM_DEVICE 0x2000 +#define KEY_TPM2_OPERATION 0x2001 +#define KEY_TPM2_OPERATION_PARAMETER 0x2002 +#define KEY_TPM2_PCR_BANKS_REQUEST_0 0x2003 +#define KEY_TPM2_PCR_BANKS_REQUEST_1 0x2004 +#define KEY_TPM2_PCR_BANKS_REQUEST_2 0x2005 +#define KEY_TPM2_PCR_BANKS_REQUEST_3 0x2006 +#define KEY_TPM2_PCR_BANKS_REQUEST_4 0x2007 + +#define TPM_DEVICE_NULL 0 +#define TPM_DEVICE_1_2 1 +#define TPM_DEVICE_2_0_DTPM 2 +#define TPM_DEVICE_MIN TPM_DEVICE_1_2 +#define TPM_DEVICE_MAX TPM_DEVICE_2_0_DTPM +#define TPM_DEVICE_DEFAULT TPM_DEVICE_1_2 + +#define TCG2_PROTOCOL_VERSION_DEFAULT 0x0001 +#define EFI_TCG2_EVENT_LOG_FORMAT_DEFAULT EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 + +// +// Nv Data structure referenced by IFR, TPM device user desired +// +typedef struct { + UINT8 TpmDevice; +} TCG2_CONFIGURATION; + +// +// Variable saved for S3, TPM detected, only valid in S3 path. +// This variable is ReadOnly. +// +typedef struct { + UINT8 TpmDeviceDetected; +} TCG2_DEVICE_DETECTION; + +#define TCG2_STORAGE_NAME L"TCG2_CONFIGURATION" +#define TCG2_DEVICE_DETECTION_NAME L"TCG2_DEVICE_DETECTION" + +#define TPM_INSTANCE_ID_LIST { \ + {TPM_DEVICE_INTERFACE_NONE, TPM_DEVICE_NULL}, \ + {TPM_DEVICE_INTERFACE_TPM12, TPM_DEVICE_1_2}, \ + {TPM_DEVICE_INTERFACE_TPM20_DTPM, TPM_DEVICE_2_0_DTPM}, \ +} + +// +// BUGBUG: In order to pass VfrCompiler, we have to redefine GUID here. +// +#ifndef __BASE_H__ +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} GUID; +#endif + +typedef struct { + GUID TpmInstanceGuid; + UINT8 TpmDevice; +} TPM_INSTANCE_ID; + +#endif diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf new file mode 100644 index 0000000000..cd6a92da1c --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf @@ -0,0 +1,78 @@ +## @file +# Set TPM device type +# +# This module initializes TPM device type based on variable and detection. +# NOTE: This module is only for reference only, each platform should have its own setup page. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2ConfigPei + MODULE_UNI_FILE = Tcg2ConfigPei.uni + FILE_GUID = EADD5061-93EF-4CCC-8450-F78A7F0820F0 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = Tcg2ConfigPeimEntryPoint + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# [BootMode] +# S3_RESUME ## SOMETIMES_CONSUMES +# + +[Sources] + Tcg2ConfigPeim.c + Tcg2ConfigNvData.h + TpmDetection.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + PeiServicesLib + PeimEntryPoint + DebugLib + PcdLib + TimerLib + IoLib + Tpm12CommandLib + Tpm12DeviceLib + +[Guids] + ## SOMETIMES_CONSUMES ## Variable:L"TCG2_CONFIGURATION" + ## SOMETIMES_CONSUMES ## Variable:L"TCG2_DEVICE_DETECTION" + gTcg2ConfigFormSetGuid + gEfiTpmDeviceSelectedGuid ## PRODUCES ## GUID # Used as a PPI GUID + gEfiTpmDeviceInstanceNoneGuid ## SOMETIMES_CONSUMES ## GUID # TPM device identifier + +[Ppis] + gEfiPeiReadOnlyVariable2PpiGuid ## CONSUMES + gPeiTpmInitializationDonePpiGuid ## SOMETIMES_PRODUCES + +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## PRODUCES + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy ## PRODUCES + gEfiSecurityPkgTokenSpaceGuid.PcdTpmAutoDetection ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## SOMETIMES_CONSUMES + +[Depex] + gEfiPeiMasterBootModePpiGuid AND + gEfiPeiReadOnlyVariable2PpiGuid + +[UserExtensions.TianoCore."ExtraFiles"] + Tcg2ConfigPeiExtra.uni diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni new file mode 100644 index 0000000000000000000000000000000000000000..c3095564a2a5827a59db0997a90e82d670ef0906 GIT binary patch literal 2206 zcmdUwUuzRV6vgke;CC3(7nRzm;7bv)u~8Rm5|Ry75K8_hkYq!4+gd-o`a3hp?xv*L z7eNWLvomw&+;h*I+5G%bwW>MV6MoL#*w|(^w~;-x2h3`%!ziPVt!1C+hm5a?8qhmd zZfsSGFZRVYB`PImVF|k~J+5PJNy}(GW@h%C-HQ4>zOz2@DX~Lh6EGYsdbajB{S9`H zd990MMjQA%iash;)UYPm>UQk2-o;X!v~x~{4qXy*IogQ#k?)rq4YpB-tdHO{pmK*Q zbKbMf&IL0m^NH6%9H*>a5idnDuRvngzAjan5x4RvJ)1Bt_!kPl1#Ja8X)pm#r}T*I zkLh37Gkb0?O`IZ7rN*3h?OC%+PqCZvCUu;hu&#&#O$w-9@mYJWLn2>U&D!=l*R$YL zocN0P1WwAK%D3l|!BQ1VqX7{Mm}u<=9!uio6|qvj;Ey!Vqg`U-U>V%E%>A&%*KVD? zV&x8bxrcM)XosS5hp^?_z$D~ac>T91Vy4L8QoRQ+j7$4!+>2AjXFFU9Ev~^AOF7|o zwKF&fQ5?bzQLdD+s_w(Hd@fQ|?8n|YIw5iX##8<*bK2Dq2e%jLy!9YI|l4<|9yr(e&BdjKp1Y${7=@7-bDn?}%0QFZ3T-5p&(Y`X)=LqHdpa zoB};UixzHD&eOfOU0>*`=Ppgv4sy?gyA$-g0I3N^7qq%vz({&Y*%Q=?;d9sTz~2^O zUE*1Nb@V-3a<*MxVTI>?{tGHO%lk3Z`F7x@vv1{^?qm69hPo~P(!b7E^b30ItLJad NRq)^c_&-;;=NC6vfZ8iT}ffzEsnKlK5hbv6QtETObtD`qc2zQj+qK1>52uul~*q%ThF( z-I=*_@408ry*qz?S5#5L`<5rs7u{*12i@wmUSaiKS3`|e)v4y1h5fPWdd4TwIkutt zL`?Jx%Lv=0R?1klrM++S!NV#m72C($A3Zy2k3r}z4xBj$|| ze@o67lW75qj65r{nq!%r6ZY+4CK1hCGO{muGd%{jWqndj9ew@}pDr9G;RFl(=b$*p z6qNi#D?F@1AC^NrrZDl|dUN^&i&;6}gxLdV#d-T!9c}G~%w~a^mCErQJ=$b=WbVrJ zHQ?*GpG0^!W1cgKxu$`2j$&r^oNV>65_2k9#MP);o%Q((E(O=8pv92yzo(tR!HDJ% z^>VHyYoB@m&)vFMRkOdt9xG(d&-mh>DU2ky;^afhA=_co_ z^FQXg +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Tcg2ConfigNvData.h" + +TPM_INSTANCE_ID mTpmInstanceId[] = TPM_INSTANCE_ID_LIST; + +CONST EFI_PEI_PPI_DESCRIPTOR gTpmSelectedPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiTpmDeviceSelectedGuid, + NULL +}; + +EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiTpmInitializationDonePpiGuid, + NULL +}; + +/** + This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration. + + @param SetupTpmDevice TpmDevice configuration in setup driver + + @return TpmDevice configuration +**/ +UINT8 +DetectTpmDevice ( + IN UINT8 SetupTpmDevice + ); + +/** + The entry point for Tcg2 configuration driver. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCES Convert variable to PCD successfully. + @retval Others Fail to convert variable to PCD. +**/ +EFI_STATUS +EFIAPI +Tcg2ConfigPeimEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + UINTN Size; + EFI_STATUS Status; + EFI_STATUS Status2; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi; + TCG2_CONFIGURATION Tcg2Configuration; + UINTN Index; + UINT8 TpmDevice; + + Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi); + ASSERT_EFI_ERROR (Status); + + Size = sizeof(Tcg2Configuration); + Status = VariablePpi->GetVariable ( + VariablePpi, + TCG2_STORAGE_NAME, + &gTcg2ConfigFormSetGuid, + NULL, + &Size, + &Tcg2Configuration + ); + if (EFI_ERROR (Status)) { + // + // Variable not ready, set default value + // + Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT; + } + + // + // Validation + // + if ((Tcg2Configuration.TpmDevice > TPM_DEVICE_MAX) || (Tcg2Configuration.TpmDevice < TPM_DEVICE_MIN)) { + Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT; + } + + // + // Although we have SetupVariable info, we still need detect TPM device manually. + // + DEBUG ((EFI_D_INFO, "Tcg2Configuration.TpmDevice from Setup: %x\n", Tcg2Configuration.TpmDevice)); + + if (PcdGetBool (PcdTpmAutoDetection)) { + TpmDevice = DetectTpmDevice (Tcg2Configuration.TpmDevice); + DEBUG ((EFI_D_INFO, "TpmDevice final: %x\n", TpmDevice)); + if (TpmDevice != TPM_DEVICE_NULL) { + Tcg2Configuration.TpmDevice = TpmDevice; + } + } else { + TpmDevice = Tcg2Configuration.TpmDevice; + } + + // + // Convert variable to PCD. + // This is work-around because there is no gurantee DynamicHiiPcd can return correct value in DXE phase. + // Using DynamicPcd instead. + // + // NOTE: Tcg2Configuration variable contains the desired TpmDevice type, + // while PcdTpmInstanceGuid PCD contains the real detected TpmDevice type + // + for (Index = 0; Index < sizeof(mTpmInstanceId)/sizeof(mTpmInstanceId[0]); Index++) { + if (TpmDevice == mTpmInstanceId[Index].TpmDevice) { + Size = sizeof(mTpmInstanceId[Index].TpmInstanceGuid); + PcdSetPtr (PcdTpmInstanceGuid, &Size, &mTpmInstanceId[Index].TpmInstanceGuid); + DEBUG ((EFI_D_INFO, "TpmDevice PCD: %g\n", &mTpmInstanceId[Index].TpmInstanceGuid)); + break; + } + } + + // + // Selection done + // + Status = PeiServicesInstallPpi (&gTpmSelectedPpi); + ASSERT_EFI_ERROR (Status); + + // + // Even if no TPM is selected or detected, we still need intall TpmInitializationDonePpi. + // Because TcgPei or Tcg2Pei will not run, but we still need a way to notify other driver. + // Other driver can know TPM initialization state by TpmInitializedPpi. + // + if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid)) { + Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList); + ASSERT_EFI_ERROR (Status2); + } + + return Status; +} diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..be548b86ff6398647285519704c049b9ca2c38e1 GIT binary patch literal 13376 zcmd6t?N1v=5XSd&rTz~V`9j);w=`81MNy40V3iolI7#!#B0vZVZ?#F%{PS&}-ww;2 z!M@$a1|rM8y}P~LXJ($Aotg80|1P?p^r^W&+y{5$j@^O#(fy$Fn%i*~ZlG(Y?oem@ zxoOm3}aHQ6; z9}Vetb%iI7b$w4QGzNlVY@S53T=}9e7T9&~^~<%-9s%PPDA2+{_>e3hG@bA3>9S?c zWSio-RoQb*=UXFKYF-Cly$<&D%b2559%(-2LJOuR<{9c7Y2OQDm=g=Y1Jl+A-7#x` z_#gGENxNl4qgts+rd{c@rZJHnUYY!0;%PJrLoTHM=WbCSxMNzS@4)MLL01Q|;^H-} z4|V0eaPPY(*X}H6l#lu{KHr|(bWP3I5l6Pg>8^P7O6M(UuqGXH?CEMtEPAb0)9dxM zYwOt5b#!1O6gqE-wN3Td@gr}m1zY)@(~)r*bxy}sf6f`a2hUsGW5jJgTTSP6%>t^n zuD3KI&u{ygyE+3m*O;%TUi4u`>$R@FJo!$?KXnJx%+$P`#UyCDzpln9MsGE|I($6HJAS>b>B<*b0?(PM{mB@s>@pjS&xL)>vpRTi)|E-KEM2eobryC@ zWL(kJr5VW9@ar2-#EQ?=|Lr+YW%n|QxPI%hJbY$voh=8d>^^&p_sfAQyXVQ4!-0<0 zXJ3r#h;QsdVSg#lc)cBGfUT1ivA3gL;hVe}E1zhJDMMJRXa)?89P9+GZ48GVU0#(L%%~x#v4VvV>R3O#L#-Ns*{R`^a< z!~RDO0_W#1wc6Jj+w|-0tuR@1_D)BO4{gNI2h?lQWLI~a+F!zcVErFw>@>umdGg<% z^l+uvS!1%(J6-aIw>a_jbq_ZAJV)||Ux(y{qxPPc<-l2UKkHlcO64o|?)gZpAqMn) z7SUFGPsBaxlY_e>OkKZ1$?49#XJ(bpizUa3sflXHK0o@*xg`w4EUj;9oVKETqDeBC zD%>Vd4*EvPTiNKTdfk#$HoV+hVn$zbwLD6q-$@u#kXc4UHcrLC>K4R~WGDF0;VsuH z+8gHs?0Q(y7QN#q>X$m-^f?{pU0Hh5XNTxHMHY)>YkF!LpO&|(M?D%@^6mE4j+dDH zp7mqiwY*+(OIt==^+T^zW-6?Gi>7V$=?C0fR6K4;a(8J|l2B+c689UOni zN^Zy_!hQTx*~+8sxE9N~HMutywz>kfjgb9O%Q0X1Nwe9ksn)kDQ?Xvt@lS((G<%(l zKg|LmHW`&=RM*$f;^;>)rs^|bS(g3DF;YHpEH-LQRcf;PTr5aITy!cs|&WltAX~vul@+*cE)7AvtVDETvZ&r zU%4KJjj39i%*nWx;%r=1Jg_Y$eV=Tq*1}}wq-r6~ zpAZf9wR`cNZQbXHuYGnEuZ_m}6UMhX=$Y~e@^7mWSruXO`>JX$9Nw#09ls~^NI;&; z?oSoT-W-;9#n7G(_Zy!JQRAiR72Ca1agJmCEOEkXV!b6D?L7`>%QM7Je9Gv>Cyw6` z%}$44SS}$*sRESskjA-jzMuDtRx)|A2tiyYTLM!81aZQce?VJ8zA(p#Z zHKwLHv9A5ABUP`rk!KuV3(4a06rSNWlEG#h0ecfkT2+bE#le(TYn^&98JBr-=trSs2$(72^u6 z6s@>^a#+|_rt?acXJ6&*>AHSHRh|F*#H#fLuF#6(Yb(1s@&Bh9h_&{uPIxyLxW81cIADcd5|3r)tJ&#P437VPR?zO%5mbayL}RrYc% zLH}v3kycYIvNC%&9Coq5CL858R*B=kjYVc7l~rUP!YVfNwClu1`F^Z28>y@={t#BN znWwdijq?3iWqPT~ZzuBY688X%IetGW&peG?%H!l)CN4p)4=dv_xvKJCqILeWlCOK7 Jh@&?I{{!8FR~i5S literal 0 HcmV?d00001 diff --git a/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c b/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c new file mode 100644 index 0000000000..9e93e9c2d9 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c @@ -0,0 +1,129 @@ +/** @file + TPM1.2/dTPM2.0 auto detection. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Tcg2ConfigNvData.h" + +/** + This routine return if dTPM (1.2 or 2.0) present. + + @retval TRUE dTPM present + @retval FALSE dTPM not present +**/ +BOOLEAN +IsDtpmPresent ( + VOID + ) +{ + UINT8 RegRead; + + RegRead = MmioRead8 ((UINTN)PcdGet64 (PcdTpmBaseAddress)); + if (RegRead == 0xFF) { + DEBUG ((EFI_D_ERROR, "DetectTpmDevice: Dtpm not present\n")); + return FALSE; + } else { + DEBUG ((EFI_D_INFO, "DetectTpmDevice: Dtpm present\n")); + return TRUE; + } +} + +/** + This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration. + + @param SetupTpmDevice TpmDevice configuration in setup driver + + @return TpmDevice configuration +**/ +UINT8 +DetectTpmDevice ( + IN UINT8 SetupTpmDevice + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + TCG2_DEVICE_DETECTION Tcg2DeviceDetection; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi; + UINTN Size; + + Status = PeiServicesGetBootMode (&BootMode); + ASSERT_EFI_ERROR (Status); + + // + // In S3, we rely on normal boot Detection, because we save to ReadOnly Variable in normal boot. + // + if (BootMode == BOOT_ON_S3_RESUME) { + DEBUG ((EFI_D_INFO, "DetectTpmDevice: S3 mode\n")); + + Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi); + ASSERT_EFI_ERROR (Status); + + Size = sizeof(TCG2_DEVICE_DETECTION); + ZeroMem (&Tcg2DeviceDetection, sizeof(Tcg2DeviceDetection)); + Status = VariablePpi->GetVariable ( + VariablePpi, + TCG2_DEVICE_DETECTION_NAME, + &gTcg2ConfigFormSetGuid, + NULL, + &Size, + &Tcg2DeviceDetection + ); + if (!EFI_ERROR (Status) && + (Tcg2DeviceDetection.TpmDeviceDetected >= TPM_DEVICE_MIN) && + (Tcg2DeviceDetection.TpmDeviceDetected <= TPM_DEVICE_MAX)) { + DEBUG ((EFI_D_ERROR, "TpmDevice from DeviceDetection: %x\n", Tcg2DeviceDetection.TpmDeviceDetected)); + return Tcg2DeviceDetection.TpmDeviceDetected; + } + } + + DEBUG ((EFI_D_INFO, "DetectTpmDevice:\n")); + if (!IsDtpmPresent ()) { + // dTPM not available + return TPM_DEVICE_NULL; + } + + // dTPM available and not disabled by setup + // We need check if it is TPM1.2 or TPM2.0 + // So try TPM1.2 command at first + + Status = Tpm12RequestUseTpm (); + if (EFI_ERROR (Status)) { + return TPM_DEVICE_2_0_DTPM; + } + + if (BootMode == BOOT_ON_S3_RESUME) { + Status = Tpm12Startup (TPM_ST_STATE); + } else { + Status = Tpm12Startup (TPM_ST_CLEAR); + } + if (EFI_ERROR (Status)) { + return TPM_DEVICE_2_0_DTPM; + } + + // NO initialization needed again. + PcdSet8 (PcdTpmInitializationPolicy, 0); + return TPM_DEVICE_1_2; +} diff --git a/SecurityPkg/Tcg/Tcg2Dxe/MeasureBootPeCoff.c b/SecurityPkg/Tcg/Tcg2Dxe/MeasureBootPeCoff.c new file mode 100644 index 0000000000..e2d763a548 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Dxe/MeasureBootPeCoff.c @@ -0,0 +1,357 @@ +/** @file + This module implements measuring PeCoff image for Tcg2 Protocol. + + Caution: This file requires additional review when modified. + This driver will have external input - PE/COFF image. + This external input must be validated carefully to avoid security issue like + buffer overflow, integer overflow. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Measure PE image into TPM log based on the authenticode image hashing in + PE/COFF Specification 8.0 Appendix A. + + Caution: This function may receive untrusted input. + PE/COFF image is external input, so this function will validate its data structure + within this image buffer before use. + + @param[in] PCRIndex TPM PCR index + @param[in] ImageAddress Start address of image buffer. + @param[in] ImageSize Image size + @param[out] DigestList Digeest list of this image. + + @retval EFI_SUCCESS Successfully measure image. + @retval EFI_OUT_OF_RESOURCES No enough resource to measure image. + @retval other error value +**/ +EFI_STATUS +MeasurePeImageAndExtend ( + IN UINT32 PCRIndex, + IN EFI_PHYSICAL_ADDRESS ImageAddress, + IN UINTN ImageSize, + OUT TPML_DIGEST_VALUES *DigestList + ) +{ + EFI_STATUS Status; + EFI_IMAGE_DOS_HEADER *DosHdr; + UINT32 PeCoffHeaderOffset; + EFI_IMAGE_SECTION_HEADER *Section; + UINT8 *HashBase; + UINTN HashSize; + UINTN SumOfBytesHashed; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINTN Index; + UINTN Pos; + UINT16 Magic; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + UINT32 NumberOfRvaAndSizes; + UINT32 CertSize; + HASH_HANDLE HashHandle; + + HashHandle = 0xFFFFFFFF; // Know bad value + + Status = EFI_UNSUPPORTED; + SectionHeader = NULL; + + // + // Check PE/COFF image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress; + PeCoffHeaderOffset = 0; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + PeCoffHeaderOffset = DosHdr->e_lfanew; + } + + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset); + if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { + Status = EFI_UNSUPPORTED; + goto Finish; + } + + // + // PE/COFF Image Measurement + // + // NOTE: The following codes/steps are based upon the authenticode image hashing in + // PE/COFF Specification 8.0 Appendix A. + // + // + + // 1. Load the image header into memory. + + // 2. Initialize a SHA hash context. + + Status = HashStart (&HashHandle); + if (EFI_ERROR (Status)) { + goto Finish; + } + + // + // Measuring PE/COFF Image Header; + // But CheckSum field and SECURITY data directory (certificate) are excluded + // + if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value + // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the + // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC + // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else { + // + // Get the magic value from the PE/COFF Optional Header + // + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + // + // 3. Calculate the distance from the base of the image header to the image checksum address. + // 4. Hash the image header from its base to beginning of the image checksum. + // + HashBase = (UINT8 *) (UINTN) ImageAddress; + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase); + } else { + // + // Use PE32+ offset + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase); + } + + Status = HashUpdate (HashHandle, HashBase, HashSize); + if (EFI_ERROR (Status)) { + goto Finish; + } + + // + // 5. Skip over the image checksum (it occupies a single ULONG). + // + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) { + // + // 6. Since there is no Cert Directory in optional header, hash everything + // from the end of the checksum to the end of image header. + // + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset. + // + HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress); + } else { + // + // Use PE32+ offset. + // + HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress); + } + + if (HashSize != 0) { + Status = HashUpdate (HashHandle, HashBase, HashSize); + if (EFI_ERROR (Status)) { + goto Finish; + } + } + } else { + // + // 7. Hash everything from the end of the checksum to the start of the Cert Directory. + // + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); + } else { + // + // Use PE32+ offset + // + HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); + } + + if (HashSize != 0) { + Status = HashUpdate (HashHandle, HashBase, HashSize); + if (EFI_ERROR (Status)) { + goto Finish; + } + } + + // + // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.) + // 9. Hash everything from the end of the Cert Directory to the end of image header. + // + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; + HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress); + } else { + // + // Use PE32+ offset + // + HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; + HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress); + } + + if (HashSize != 0) { + Status = HashUpdate (HashHandle, HashBase, HashSize); + if (EFI_ERROR (Status)) { + goto Finish; + } + } + } + + // + // 10. Set the SUM_OF_BYTES_HASHED to the size of the header + // + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders; + } else { + // + // Use PE32+ offset + // + SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders; + } + + // + // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER + // structures in the image. The 'NumberOfSections' field of the image + // header indicates how big the table should be. Do not include any + // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections); + if (SectionHeader == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Finish; + } + + // + // 12. Using the 'PointerToRawData' in the referenced section headers as + // a key, arrange the elements in the table in ascending order. In other + // words, sort the section headers according to the disk-file offset of + // the section. + // + Section = (EFI_IMAGE_SECTION_HEADER *) ( + (UINT8 *) (UINTN) ImageAddress + + PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + Hdr.Pe32->FileHeader.SizeOfOptionalHeader + ); + for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) { + Pos = Index; + while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) { + CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof(EFI_IMAGE_SECTION_HEADER)); + Pos--; + } + CopyMem (&SectionHeader[Pos], Section, sizeof(EFI_IMAGE_SECTION_HEADER)); + Section += 1; + } + + // + // 13. Walk through the sorted table, bring the corresponding section + // into memory, and hash the entire section (using the 'SizeOfRawData' + // field in the section header to determine the amount of data to hash). + // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED . + // 15. Repeat steps 13 and 14 for all the sections in the sorted table. + // + for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) { + Section = (EFI_IMAGE_SECTION_HEADER *) &SectionHeader[Index]; + if (Section->SizeOfRawData == 0) { + continue; + } + HashBase = (UINT8 *) (UINTN) ImageAddress + Section->PointerToRawData; + HashSize = (UINTN) Section->SizeOfRawData; + + Status = HashUpdate (HashHandle, HashBase, HashSize); + if (EFI_ERROR (Status)) { + goto Finish; + } + + SumOfBytesHashed += HashSize; + } + + // + // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra + // data in the file that needs to be added to the hash. This data begins + // at file offset SUM_OF_BYTES_HASHED and its length is: + // FileSize - (CertDirectory->Size) + // + if (ImageSize > SumOfBytesHashed) { + HashBase = (UINT8 *) (UINTN) ImageAddress + SumOfBytesHashed; + + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) { + CertSize = 0; + } else { + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset. + // + CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size; + } else { + // + // Use PE32+ offset. + // + CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size; + } + } + + if (ImageSize > CertSize + SumOfBytesHashed) { + HashSize = (UINTN) (ImageSize - CertSize - SumOfBytesHashed); + + Status = HashUpdate (HashHandle, HashBase, HashSize); + if (EFI_ERROR (Status)) { + goto Finish; + } + } else if (ImageSize < CertSize + SumOfBytesHashed) { + Status = EFI_UNSUPPORTED; + goto Finish; + } + } + + // + // 17. Finalize the SHA hash. + // + Status = HashCompleteAndExtend (HashHandle, PCRIndex, NULL, 0, DigestList); + if (EFI_ERROR (Status)) { + goto Finish; + } + +Finish: + if (SectionHeader != NULL) { + FreePool (SectionHeader); + } + + return Status; +} diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c new file mode 100644 index 0000000000..cb2a65b47c --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c @@ -0,0 +1,2563 @@ +/** @file + This module implements Tcg2 Protocol. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PERF_ID_TCG2_DXE 0x3120 + +typedef struct { + CHAR16 *VariableName; + EFI_GUID *VendorGuid; +} VARIABLE_TYPE; + +#define EFI_TCG_LOG_AREA_SIZE 0x10000 +#define EFI_TCG_FINAL_LOG_AREA_SIZE 0x1000 + +#define TCG2_DEFAULT_MAX_COMMAND_SIZE 0x1000 +#define TCG2_DEFAULT_MAX_RESPONSE_SIZE 0x1000 + +typedef struct { + EFI_GUID *EventGuid; + EFI_TCG2_EVENT_LOG_FORMAT LogFormat; +} TCG2_EVENT_INFO_STRUCT; + +TCG2_EVENT_INFO_STRUCT mTcg2EventInfo[] = { + {&gTcgEventEntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2}, + {&gTcgEvent2EntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2}, +}; + +#define TCG_EVENT_LOG_AREA_COUNT_MAX 2 + +typedef struct { + EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat; + EFI_PHYSICAL_ADDRESS Lasa; + UINT64 Laml; + UINTN EventLogSize; + UINT8 *LastEvent; + BOOLEAN EventLogStarted; + BOOLEAN EventLogTruncated; +} TCG_EVENT_LOG_AREA_STRUCT; + +typedef struct _TCG_DXE_DATA { + EFI_TCG2_BOOT_SERVICE_CAPABILITY BsCap; + TCG_EVENT_LOG_AREA_STRUCT EventLogAreaStruct[TCG_EVENT_LOG_AREA_COUNT_MAX]; + BOOLEAN GetEventLogCalled[TCG_EVENT_LOG_AREA_COUNT_MAX]; + TCG_EVENT_LOG_AREA_STRUCT FinalEventLogAreaStruct[TCG_EVENT_LOG_AREA_COUNT_MAX]; + EFI_TCG2_FINAL_EVENTS_TABLE *FinalEventsTable[TCG_EVENT_LOG_AREA_COUNT_MAX]; +} TCG_DXE_DATA; + +TCG_DXE_DATA mTcgDxeData = { + { + sizeof (EFI_TCG2_BOOT_SERVICE_CAPABILITY), // Size + { 1, 1 }, // StructureVersion + { 1, 1 }, // ProtocolVersion + EFI_TCG2_BOOT_HASH_ALG_SHA1, // HashAlgorithmBitmap + EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2, // SupportedEventLogs + TRUE, // TPMPresentFlag + TCG2_DEFAULT_MAX_COMMAND_SIZE, // MaxCommandSize + TCG2_DEFAULT_MAX_RESPONSE_SIZE, // MaxResponseSize + 0, // ManufacturerID + 0, // NumberOfPCRBanks + 0, // ActivePcrBanks + }, +}; + +UINTN mBootAttempts = 0; +CHAR16 mBootVarName[] = L"BootOrder"; + +VARIABLE_TYPE mVariableType[] = { + {EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid}, + {EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid}, + {EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid}, + {EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid}, + {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid}, +}; + +EFI_HANDLE mImageHandle; + +/** + Measure PE image into TPM log based on the authenticode image hashing in + PE/COFF Specification 8.0 Appendix A. + + Caution: This function may receive untrusted input. + PE/COFF image is external input, so this function will validate its data structure + within this image buffer before use. + + @param[in] PCRIndex TPM PCR index + @param[in] ImageAddress Start address of image buffer. + @param[in] ImageSize Image size + @param[out] DigestList Digeest list of this image. + + @retval EFI_SUCCESS Successfully measure image. + @retval EFI_OUT_OF_RESOURCES No enough resource to measure image. + @retval other error value +**/ +EFI_STATUS +MeasurePeImageAndExtend ( + IN UINT32 PCRIndex, + IN EFI_PHYSICAL_ADDRESS ImageAddress, + IN UINTN ImageSize, + OUT TPML_DIGEST_VALUES *DigestList + ); + +/** + + This function dump raw data. + + @param Data raw data + @param Size raw data size + +**/ +VOID +InternalDumpData ( + IN UINT8 *Data, + IN UINTN Size + ) +{ + UINTN Index; + for (Index = 0; Index < Size; Index++) { + DEBUG ((EFI_D_INFO, "%02x", (UINTN)Data[Index])); + } +} + +/** + + This function dump raw data with colume format. + + @param Data raw data + @param Size raw data size + +**/ +VOID +InternalDumpHex ( + IN UINT8 *Data, + IN UINTN Size + ) +{ + UINTN Index; + UINTN Count; + UINTN Left; + +#define COLUME_SIZE (16 * 2) + + Count = Size / COLUME_SIZE; + Left = Size % COLUME_SIZE; + for (Index = 0; Index < Count; Index++) { + DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE)); + InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE); + DEBUG ((EFI_D_INFO, "\n")); + } + + if (Left != 0) { + DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE)); + InternalDumpData (Data + Index * COLUME_SIZE, Left); + DEBUG ((EFI_D_INFO, "\n")); + } +} + +/** + Check if buffer is all zero. + + @param[in] Buffer Buffer to be checked. + @param[in] BufferSize Size of buffer to be checked. + + @retval TRUE Buffer is all zero. + @retval FALSE Buffer is not all zero. +**/ +BOOLEAN +IsZeroBuffer ( + IN VOID *Buffer, + IN UINTN BufferSize + ) +{ + UINT8 *BufferData; + UINTN Index; + + BufferData = Buffer; + for (Index = 0; Index < BufferSize; Index++) { + if (BufferData[Index] != 0) { + return FALSE; + } + } + return TRUE; +} + +/** + Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function + Caller is responsible to free LocationBuf. + + @param[out] LocationBuf Returns Processor Location Buffer. + @param[out] Num Returns processor number. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_UNSUPPORTED MpService protocol not found. + +**/ +EFI_STATUS +GetProcessorsCpuLocation ( + OUT EFI_CPU_PHYSICAL_LOCATION **LocationBuf, + OUT UINTN *Num + ) +{ + EFI_STATUS Status; + EFI_MP_SERVICES_PROTOCOL *MpProtocol; + UINTN ProcessorNum; + UINTN EnabledProcessorNum; + EFI_PROCESSOR_INFORMATION ProcessorInfo; + EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf; + UINTN Index; + + Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpProtocol); + if (EFI_ERROR (Status)) { + // + // MP protocol is not installed + // + return EFI_UNSUPPORTED; + } + + Status = MpProtocol->GetNumberOfProcessors( + MpProtocol, + &ProcessorNum, + &EnabledProcessorNum + ); + if (EFI_ERROR(Status)){ + return Status; + } + + Status = gBS->AllocatePool( + EfiBootServicesData, + sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum, + (VOID **) &ProcessorLocBuf + ); + if (EFI_ERROR(Status)){ + return Status; + } + + // + // Get each processor Location info + // + for (Index = 0; Index < ProcessorNum; Index++) { + Status = MpProtocol->GetProcessorInfo( + MpProtocol, + Index, + &ProcessorInfo + ); + if (EFI_ERROR(Status)){ + FreePool(ProcessorLocBuf); + return Status; + } + + // + // Get all Processor Location info & measure + // + CopyMem( + &ProcessorLocBuf[Index], + &ProcessorInfo.Location, + sizeof(EFI_CPU_PHYSICAL_LOCATION) + ); + } + + *LocationBuf = ProcessorLocBuf; + *Num = ProcessorNum; + + return Status; +} + +/** + The EFI_TCG2_PROTOCOL GetCapability function call provides protocol + capability information and state information. + + @param[in] This Indicates the calling context + @param[in, out] ProtocolCapability The caller allocates memory for a EFI_TCG2_BOOT_SERVICE_CAPABILITY + structure and sets the size field to the size of the structure allocated. + The callee fills in the fields with the EFI protocol capability information + and the current EFI TCG2 state information up to the number of fields which + fit within the size of the structure passed in. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + The ProtocolCapability variable will not be populated. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + The ProtocolCapability variable will not be populated. + @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response. + It will be partially populated (required Size field will be set). +**/ +EFI_STATUS +EFIAPI +Tcg2GetCapability ( + IN EFI_TCG2_PROTOCOL *This, + IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY *ProtocolCapability + ) +{ + DEBUG ((EFI_D_INFO, "Tcg2GetCapability ...\n")); + + if ((This == NULL) || (ProtocolCapability == NULL)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((EFI_D_INFO, "Size - 0x%x\n", ProtocolCapability->Size)); + DEBUG ((EFI_D_INFO, " 1.1 - 0x%x, 1.0 - 0x%x\n", sizeof(EFI_TCG2_BOOT_SERVICE_CAPABILITY), sizeof(TREE_BOOT_SERVICE_CAPABILITY_1_0))); + + if (ProtocolCapability->Size < mTcgDxeData.BsCap.Size) { + // + // Handle the case that firmware support 1.1 but OS only support 1.0. + // + if ((mTcgDxeData.BsCap.ProtocolVersion.Major > 0x01) || + ((mTcgDxeData.BsCap.ProtocolVersion.Major == 0x01) && ((mTcgDxeData.BsCap.ProtocolVersion.Minor > 0x00)))) { + if (ProtocolCapability->Size >= sizeof(TREE_BOOT_SERVICE_CAPABILITY_1_0)) { + CopyMem (ProtocolCapability, &mTcgDxeData.BsCap, sizeof(TREE_BOOT_SERVICE_CAPABILITY_1_0)); + ProtocolCapability->Size = sizeof(TREE_BOOT_SERVICE_CAPABILITY_1_0); + ProtocolCapability->StructureVersion.Major = 1; + ProtocolCapability->StructureVersion.Minor = 0; + ProtocolCapability->ProtocolVersion.Major = 1; + ProtocolCapability->ProtocolVersion.Minor = 0; + DEBUG ((EFI_D_ERROR, "TreeGetCapability (Compatible) - %r\n", EFI_SUCCESS)); + return EFI_SUCCESS; + } + } + ProtocolCapability->Size = mTcgDxeData.BsCap.Size; + return EFI_BUFFER_TOO_SMALL; + } + + CopyMem (ProtocolCapability, &mTcgDxeData.BsCap, mTcgDxeData.BsCap.Size); + DEBUG ((EFI_D_INFO, "Tcg2GetCapability - %r\n", EFI_SUCCESS)); + return EFI_SUCCESS; +} + +/** + This function dump PCR event. + + @param[in] EventHdr TCG PCR event structure. +**/ +VOID +DumpEvent ( + IN TCG_PCR_EVENT_HDR *EventHdr + ) +{ + UINTN Index; + + DEBUG ((EFI_D_INFO, " Event:\n")); + DEBUG ((EFI_D_INFO, " PCRIndex - %d\n", EventHdr->PCRIndex)); + DEBUG ((EFI_D_INFO, " EventType - 0x%08x\n", EventHdr->EventType)); + DEBUG ((EFI_D_INFO, " Digest - ")); + for (Index = 0; Index < sizeof(TCG_DIGEST); Index++) { + DEBUG ((EFI_D_INFO, "%02x ", EventHdr->Digest.digest[Index])); + } + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, " EventSize - 0x%08x\n", EventHdr->EventSize)); + InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize); +} + +/** + This function dump TCG_EfiSpecIDEventStruct. + + @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct. +**/ +VOID +DumpTcgEfiSpecIdEventStruct ( + IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct + ) +{ + TCG_EfiSpecIdEventAlgorithmSize *digestSize; + UINTN Index; + UINT8 *vendorInfoSize; + UINT8 *vendorInfo; + UINT32 numberOfAlgorithms; + + DEBUG ((EFI_D_INFO, " TCG_EfiSpecIDEventStruct:\n")); + DEBUG ((EFI_D_INFO, " signature - '")); + for (Index = 0; Index < sizeof(TcgEfiSpecIdEventStruct->signature); Index++) { + DEBUG ((EFI_D_INFO, "%c", TcgEfiSpecIdEventStruct->signature[Index])); + } + DEBUG ((EFI_D_INFO, "'\n")); + DEBUG ((EFI_D_INFO, " platformClass - 0x%08x\n", TcgEfiSpecIdEventStruct->platformClass)); + DEBUG ((EFI_D_INFO, " specVersion - %d.%d%d\n", TcgEfiSpecIdEventStruct->specVersionMajor, TcgEfiSpecIdEventStruct->specVersionMinor, TcgEfiSpecIdEventStruct->specErrata)); + DEBUG ((EFI_D_INFO, " uintnSize - 0x%02x\n", TcgEfiSpecIdEventStruct->uintnSize)); + + CopyMem (&numberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof(numberOfAlgorithms)); + DEBUG ((EFI_D_INFO, " numberOfAlgorithms - 0x%08x\n", numberOfAlgorithms)); + + digestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof(*TcgEfiSpecIdEventStruct) + sizeof(numberOfAlgorithms)); + for (Index = 0; Index < numberOfAlgorithms; Index++) { + DEBUG ((EFI_D_INFO, " digest(%d)\n", Index)); + DEBUG ((EFI_D_INFO, " algorithmId - 0x%04x\n", digestSize[Index].algorithmId)); + DEBUG ((EFI_D_INFO, " digestSize - 0x%04x\n", digestSize[Index].digestSize)); + } + vendorInfoSize = (UINT8 *)&digestSize[numberOfAlgorithms]; + DEBUG ((EFI_D_INFO, " vendorInfoSize - 0x%02x\n", *vendorInfoSize)); + vendorInfo = vendorInfoSize + 1; + DEBUG ((EFI_D_INFO, " vendorInfo - ")); + for (Index = 0; Index < *vendorInfoSize; Index++) { + DEBUG ((EFI_D_INFO, "%02x ", vendorInfo[Index])); + } + DEBUG ((EFI_D_INFO, "\n")); +} + +/** + This function get size of TCG_EfiSpecIDEventStruct. + + @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct. +**/ +UINTN +GetTcgEfiSpecIdEventStructSize ( + IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct + ) +{ + TCG_EfiSpecIdEventAlgorithmSize *digestSize; + UINT8 *vendorInfoSize; + UINT32 numberOfAlgorithms; + + CopyMem (&numberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof(numberOfAlgorithms)); + + digestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof(*TcgEfiSpecIdEventStruct) + sizeof(numberOfAlgorithms)); + vendorInfoSize = (UINT8 *)&digestSize[numberOfAlgorithms]; + return sizeof(TCG_EfiSpecIDEventStruct) + sizeof(UINT32) + (numberOfAlgorithms * sizeof(TCG_EfiSpecIdEventAlgorithmSize)) + sizeof(UINT8) + (*vendorInfoSize); +} + +/** + This function dump PCR event 2. + + @param[in] TcgPcrEvent2 TCG PCR event 2 structure. +**/ +VOID +DumpEvent2 ( + IN TCG_PCR_EVENT2 *TcgPcrEvent2 + ) +{ + UINTN Index; + UINT32 DigestIndex; + UINT32 DigestCount; + TPMI_ALG_HASH HashAlgo; + UINT32 DigestSize; + UINT8 *DigestBuffer; + UINT32 EventSize; + UINT8 *EventBuffer; + + DEBUG ((EFI_D_INFO, " Event:\n")); + DEBUG ((EFI_D_INFO, " PCRIndex - %d\n", TcgPcrEvent2->PCRIndex)); + DEBUG ((EFI_D_INFO, " EventType - 0x%08x\n", TcgPcrEvent2->EventType)); + + DEBUG ((EFI_D_INFO, " DigestCount: 0x%08x\n", TcgPcrEvent2->Digest.count)); + + DigestCount = TcgPcrEvent2->Digest.count; + HashAlgo = TcgPcrEvent2->Digest.digests[0].hashAlg; + DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest.digests[0].digest; + for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) { + DEBUG ((EFI_D_INFO, " HashAlgo : 0x%04x\n", HashAlgo)); + DEBUG ((EFI_D_INFO, " Digest(%d): ", DigestIndex)); + DigestSize = GetHashSizeFromAlgo (HashAlgo); + for (Index = 0; Index < DigestSize; Index++) { + DEBUG ((EFI_D_INFO, "%02x ", DigestBuffer[Index])); + } + DEBUG ((EFI_D_INFO, "\n")); + // + // Prepare next + // + CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof(TPMI_ALG_HASH)); + DigestBuffer = DigestBuffer + DigestSize + sizeof(TPMI_ALG_HASH); + } + DEBUG ((EFI_D_INFO, "\n")); + DigestBuffer = DigestBuffer - sizeof(TPMI_ALG_HASH); + + CopyMem (&EventSize, DigestBuffer, sizeof(TcgPcrEvent2->EventSize)); + DEBUG ((EFI_D_INFO, " EventSize - 0x%08x\n", EventSize)); + EventBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize); + InternalDumpHex (EventBuffer, EventSize); +} + +/** + This function returns size of TCG PCR event 2. + + @param[in] TcgPcrEvent2 TCG PCR event 2 structure. + + @return size of TCG PCR event 2. +**/ +UINTN +GetPcrEvent2Size ( + IN TCG_PCR_EVENT2 *TcgPcrEvent2 + ) +{ + UINT32 DigestIndex; + UINT32 DigestCount; + TPMI_ALG_HASH HashAlgo; + UINT32 DigestSize; + UINT8 *DigestBuffer; + UINT32 EventSize; + UINT8 *EventBuffer; + + DigestCount = TcgPcrEvent2->Digest.count; + HashAlgo = TcgPcrEvent2->Digest.digests[0].hashAlg; + DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest.digests[0].digest; + for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) { + DigestSize = GetHashSizeFromAlgo (HashAlgo); + // + // Prepare next + // + CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof(TPMI_ALG_HASH)); + DigestBuffer = DigestBuffer + DigestSize + sizeof(TPMI_ALG_HASH); + } + DigestBuffer = DigestBuffer - sizeof(TPMI_ALG_HASH); + + CopyMem (&EventSize, DigestBuffer, sizeof(TcgPcrEvent2->EventSize)); + EventBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize); + + return (UINTN)EventBuffer + EventSize - (UINTN)TcgPcrEvent2; +} + +/** + This function dump event log. + + @param[in] EventLogFormat The type of the event log for which the information is requested. + @param[in] EventLogLocation A pointer to the memory address of the event log. + @param[in] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the + address of the start of the last entry in the event log in memory. + @param[in] FinalEventsTable A pointer to the memory address of the final event table. +**/ +VOID +DumpEventLog ( + IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat, + IN EFI_PHYSICAL_ADDRESS EventLogLocation, + IN EFI_PHYSICAL_ADDRESS EventLogLastEntry, + IN EFI_TCG2_FINAL_EVENTS_TABLE *FinalEventsTable + ) +{ + TCG_PCR_EVENT_HDR *EventHdr; + TCG_PCR_EVENT2 *TcgPcrEvent2; + TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct; + UINTN NumberOfEvents; + + DEBUG ((EFI_D_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat)); + + switch (EventLogFormat) { + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2: + EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation; + while ((UINTN)EventHdr <= EventLogLastEntry) { + DumpEvent (EventHdr); + EventHdr = (TCG_PCR_EVENT_HDR *)((UINTN)EventHdr + sizeof(TCG_PCR_EVENT_HDR) + EventHdr->EventSize); + } + if (FinalEventsTable == NULL) { + DEBUG ((EFI_D_INFO, "FinalEventsTable: NOT FOUND\n")); + } else { + DEBUG ((EFI_D_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable)); + DEBUG ((EFI_D_INFO, " Version: (0x%x)\n", FinalEventsTable->Version)); + DEBUG ((EFI_D_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents)); + + EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)(FinalEventsTable + 1); + for (NumberOfEvents = 0; NumberOfEvents < FinalEventsTable->NumberOfEvents; NumberOfEvents++) { + DumpEvent (EventHdr); + EventHdr = (TCG_PCR_EVENT_HDR *)((UINTN)EventHdr + sizeof(TCG_PCR_EVENT_HDR) + EventHdr->EventSize); + } + } + break; + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2: + // + // Dump first event + // + EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation; + DumpEvent (EventHdr); + + TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)(EventHdr + 1); + DumpTcgEfiSpecIdEventStruct (TcgEfiSpecIdEventStruct); + + TcgPcrEvent2 = (TCG_PCR_EVENT2 *)((UINTN)TcgEfiSpecIdEventStruct + GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct)); + while ((UINTN)TcgPcrEvent2 <= EventLogLastEntry) { + DumpEvent2 (TcgPcrEvent2); + TcgPcrEvent2 = (TCG_PCR_EVENT2 *)((UINTN)TcgPcrEvent2 + GetPcrEvent2Size (TcgPcrEvent2)); + } + + if (FinalEventsTable == NULL) { + DEBUG ((EFI_D_INFO, "FinalEventsTable: NOT FOUND\n")); + } else { + DEBUG ((EFI_D_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable)); + DEBUG ((EFI_D_INFO, " Version: (0x%x)\n", FinalEventsTable->Version)); + DEBUG ((EFI_D_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents)); + + TcgPcrEvent2 = (TCG_PCR_EVENT2 *)(UINTN)(FinalEventsTable + 1); + for (NumberOfEvents = 0; NumberOfEvents < FinalEventsTable->NumberOfEvents; NumberOfEvents++) { + DumpEvent2 (TcgPcrEvent2); + TcgPcrEvent2 = (TCG_PCR_EVENT2 *)((UINTN)TcgPcrEvent2 + GetPcrEvent2Size (TcgPcrEvent2)); + } + } + break; + } + + return ; +} + +/** + The EFI_TCG2_PROTOCOL Get Event Log function call allows a caller to + retrieve the address of a given event log and its last entry. + + @param[in] This Indicates the calling context + @param[in] EventLogFormat The type of the event log for which the information is requested. + @param[out] EventLogLocation A pointer to the memory address of the event log. + @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the + address of the start of the last entry in the event log in memory. + @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would + have exceeded the area allocated for events, this value is set to TRUE. + Otherwise, the value will be FALSE and the Event Log will be complete. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect + (e.g. asking for an event log whose format is not supported). +**/ +EFI_STATUS +EFIAPI +Tcg2GetEventLog ( + IN EFI_TCG2_PROTOCOL *This, + IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat, + OUT EFI_PHYSICAL_ADDRESS *EventLogLocation, + OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry, + OUT BOOLEAN *EventLogTruncated + ) +{ + UINTN Index; + + DEBUG ((EFI_D_INFO, "Tcg2GetEventLog ... (0x%x)\n", EventLogFormat)); + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { + if (EventLogFormat == mTcg2EventInfo[Index].LogFormat) { + break; + } + } + + if (Index == sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0])) { + return EFI_INVALID_PARAMETER; + } + + if ((mTcg2EventInfo[Index].LogFormat & mTcgDxeData.BsCap.SupportedEventLogs) == 0) { + return EFI_INVALID_PARAMETER; + } + + if (!mTcgDxeData.BsCap.TPMPresentFlag) { + if (EventLogLocation != NULL) { + *EventLogLocation = 0; + } + if (EventLogLastEntry != NULL) { + *EventLogLastEntry = 0; + } + if (EventLogTruncated != NULL) { + *EventLogTruncated = FALSE; + } + return EFI_SUCCESS; + } + + if (EventLogLocation != NULL) { + *EventLogLocation = mTcgDxeData.EventLogAreaStruct[Index].Lasa; + DEBUG ((EFI_D_INFO, "Tcg2GetEventLog (EventLogLocation - %x)\n", *EventLogLocation)); + } + + if (EventLogLastEntry != NULL) { + if (!mTcgDxeData.EventLogAreaStruct[Index].EventLogStarted) { + *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0; + } else { + *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].LastEvent; + } + DEBUG ((EFI_D_INFO, "Tcg2GetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry)); + } + + if (EventLogTruncated != NULL) { + *EventLogTruncated = mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated; + DEBUG ((EFI_D_INFO, "Tcg2GetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated)); + } + + DEBUG ((EFI_D_INFO, "Tcg2GetEventLog - %r\n", EFI_SUCCESS)); + + // Dump Event Log for debug purpose + if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) { + DumpEventLog (EventLogFormat, *EventLogLocation, *EventLogLastEntry, mTcgDxeData.FinalEventsTable[Index]); + } + + // + // All events generated after the invocation of EFI_TCG2_GET_EVENT_LOG SHALL be stored + // in an instance of an EFI_CONFIGURATION_TABLE named by the VendorGuid of EFI_TCG2_FINAL_EVENTS_TABLE_GUID. + // + mTcgDxeData.GetEventLogCalled[Index] = TRUE; + + return EFI_SUCCESS; +} + +/** + Add a new entry to the Event Log. + + @param[in, out] EventLogPtr Pointer to the Event Log data. + @param[in, out] LogSize Size of the Event Log. + @param[in] MaxSize Maximum size of the Event Log. + @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. + @param[in] NewEventHdrSize New event header size. + @param[in] NewEventData Pointer to the new event data. + @param[in] NewEventSize New event data size. + + @retval EFI_SUCCESS The new event log entry was added. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + +**/ +EFI_STATUS +TcgCommLogEvent ( + IN OUT UINT8 **EventLogPtr, + IN OUT UINTN *LogSize, + IN UINTN MaxSize, + IN VOID *NewEventHdr, + IN UINT32 NewEventHdrSize, + IN UINT8 *NewEventData, + IN UINT32 NewEventSize + ) +{ + UINTN NewLogSize; + + if (NewEventSize > MAX_ADDRESS - NewEventHdrSize) { + return EFI_OUT_OF_RESOURCES; + } + + NewLogSize = NewEventHdrSize + NewEventSize; + + if (NewLogSize > MAX_ADDRESS - *LogSize) { + return EFI_OUT_OF_RESOURCES; + } + + if (NewLogSize + *LogSize > MaxSize) { + DEBUG ((EFI_D_INFO, " MaxSize - 0x%x\n", MaxSize)); + DEBUG ((EFI_D_INFO, " NewLogSize - 0x%x\n", NewLogSize)); + DEBUG ((EFI_D_INFO, " LogSize - 0x%x\n", *LogSize)); + DEBUG ((EFI_D_INFO, "TcgCommLogEvent - %r\n", EFI_OUT_OF_RESOURCES)); + return EFI_OUT_OF_RESOURCES; + } + + *EventLogPtr += *LogSize; + *LogSize += NewLogSize; + CopyMem (*EventLogPtr, NewEventHdr, NewEventHdrSize); + CopyMem ( + *EventLogPtr + NewEventHdrSize, + NewEventData, + NewEventSize + ); + return EFI_SUCCESS; +} + +/** + Add a new entry to the Event Log. + + @param[in] EventLogFormat The type of the event log for which the information is requested. + @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. + @param[in] NewEventHdrSize New event header size. + @param[in] NewEventData Pointer to the new event data. + @param[in] NewEventSize New event data size. + + @retval EFI_SUCCESS The new event log entry was added. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + +**/ +EFI_STATUS +TcgDxeLogEvent ( + IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat, + IN VOID *NewEventHdr, + IN UINT32 NewEventHdrSize, + IN UINT8 *NewEventData, + IN UINT32 NewEventSize + ) +{ + EFI_STATUS Status; + UINTN Index; + TCG_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct; + + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { + if (EventLogFormat == mTcg2EventInfo[Index].LogFormat) { + break; + } + } + + if (Index == sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0])) { + return EFI_INVALID_PARAMETER; + } + + if (!mTcgDxeData.GetEventLogCalled[Index]) { + EventLogAreaStruct = &mTcgDxeData.EventLogAreaStruct[Index]; + } else { + EventLogAreaStruct = &mTcgDxeData.FinalEventLogAreaStruct[Index]; + } + + if (EventLogAreaStruct->EventLogTruncated) { + return EFI_VOLUME_FULL; + } + + EventLogAreaStruct->LastEvent = (UINT8*)(UINTN)EventLogAreaStruct->Lasa; + Status = TcgCommLogEvent ( + &EventLogAreaStruct->LastEvent, + &EventLogAreaStruct->EventLogSize, + (UINTN)EventLogAreaStruct->Laml, + NewEventHdr, + NewEventHdrSize, + NewEventData, + NewEventSize + ); + + if (Status == EFI_DEVICE_ERROR) { + return EFI_DEVICE_ERROR; + } else if (Status == EFI_OUT_OF_RESOURCES) { + EventLogAreaStruct->EventLogTruncated = TRUE; + return EFI_VOLUME_FULL; + } else if (Status == EFI_SUCCESS) { + EventLogAreaStruct->EventLogStarted = TRUE; + if (mTcgDxeData.GetEventLogCalled[Index]) { + (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents ++; + } + } + + return Status; +} + +/** + This function get digest from digest list. + + @param HashAlg digest algorithm + @param DigestList digest list + @param Digest digest + + @retval EFI_SUCCESS Sha1Digest is found and returned. + @retval EFI_NOT_FOUND Sha1Digest is not found. +**/ +EFI_STATUS +Tpm2GetDigestFromDigestList ( + IN TPMI_ALG_HASH HashAlg, + IN TPML_DIGEST_VALUES *DigestList, + IN VOID *Digest + ) +{ + UINTN Index; + UINT16 DigestSize; + + DigestSize = GetHashSizeFromAlgo (HashAlg); + for (Index = 0; Index < DigestList->count; Index++) { + if (DigestList->digests[Index].hashAlg == HashAlg) { + CopyMem ( + Digest, + &DigestList->digests[Index].digest, + DigestSize + ); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Get TPML_DIGEST_VALUES data size. + + @param[in] DigestList TPML_DIGEST_VALUES data. + + @return TPML_DIGEST_VALUES data size. +**/ +UINT32 +GetDigestListSize ( + IN TPML_DIGEST_VALUES *DigestList + ) +{ + UINTN Index; + UINT16 DigestSize; + UINT32 TotalSize; + + TotalSize = sizeof(DigestList->count); + for (Index = 0; Index < DigestList->count; Index++) { + DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg); + TotalSize += sizeof(DigestList->digests[Index].hashAlg) + DigestSize; + } + + return TotalSize; +} + +/** + Get TPML_DIGEST_VALUES compact binary buffer size. + + @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer. + + @return TPML_DIGEST_VALUES compact binary buffer size. +**/ +UINT32 +GetDigestListBinSize ( + IN VOID *DigestListBin + ) +{ + UINTN Index; + UINT16 DigestSize; + UINT32 TotalSize; + UINT32 Count; + TPMI_ALG_HASH HashAlg; + + Count = ReadUnaligned32 (DigestListBin); + TotalSize = sizeof(Count); + DigestListBin = (UINT8 *)DigestListBin + sizeof(Count); + for (Index = 0; Index < Count; Index++) { + HashAlg = ReadUnaligned16 (DigestListBin); + TotalSize += sizeof(HashAlg); + DigestListBin = (UINT8 *)DigestListBin + sizeof(HashAlg); + + DigestSize = GetHashSizeFromAlgo (HashAlg); + TotalSize += DigestSize; + DigestListBin = (UINT8 *)DigestListBin + DigestSize; + } + + return TotalSize; +} + +/** + Return if hash alg is supported in TPM PCR bank. + + @param HashAlg Hash algorithm to be checked. + + @retval TRUE Hash algorithm is supported. + @retval FALSE Hash algorithm is not supported. +**/ +BOOLEAN +IsHashAlgSupportedInPcrBank ( + IN TPMI_ALG_HASH HashAlg + ) +{ + switch (HashAlg) { + case TPM_ALG_SHA1: + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) { + return TRUE; + } + break; + case TPM_ALG_SHA256: + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) { + return TRUE; + } + break; + case TPM_ALG_SHA384: + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) { + return TRUE; + } + break; + case TPM_ALG_SHA512: + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) { + return TRUE; + } + break; + case TPM_ALG_SM3_256: + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) { + return TRUE; + } + break; + } + + return FALSE; +} + +/** + Copy TPML_DIGEST_VALUES into a buffer + + @param[in,out] Buffer Buffer to hold TPML_DIGEST_VALUES. + @param[in] DigestList TPML_DIGEST_VALUES to be copied. + + @return The end of buffer to hold TPML_DIGEST_VALUES. +**/ +VOID * +CopyDigestListToBuffer ( + IN OUT VOID *Buffer, + IN TPML_DIGEST_VALUES *DigestList + ) +{ + UINTN Index; + UINT16 DigestSize; + + CopyMem (Buffer, &DigestList->count, sizeof(DigestList->count)); + Buffer = (UINT8 *)Buffer + sizeof(DigestList->count); + for (Index = 0; Index < DigestList->count; Index++) { + if (!IsHashAlgSupportedInPcrBank (DigestList->digests[Index].hashAlg)) { + DEBUG ((EFI_D_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg)); + continue; + } + CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof(DigestList->digests[Index].hashAlg)); + Buffer = (UINT8 *)Buffer + sizeof(DigestList->digests[Index].hashAlg); + DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg); + CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize); + Buffer = (UINT8 *)Buffer + DigestSize; + } + + return Buffer; +} + +/** + Add a new entry to the Event Log. + + @param[in] DigestList A list of digest. + @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. + @param[in] NewEventData Pointer to the new event data. + + @retval EFI_SUCCESS The new event log entry was added. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. +**/ +EFI_STATUS +TcgDxeLogHashEvent ( + IN TPML_DIGEST_VALUES *DigestList, + IN OUT TCG_PCR_EVENT_HDR *NewEventHdr, + IN UINT8 *NewEventData + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + UINTN Index; + EFI_STATUS RetStatus; + TCG_PCR_EVENT2 TcgPcrEvent2; + UINT8 *DigestBuffer; + + DEBUG ((EFI_D_INFO, "SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs)); + + RetStatus = EFI_SUCCESS; + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { + if ((mTcgDxeData.BsCap.SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { + DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat)); + switch (mTcg2EventInfo[Index].LogFormat) { + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2: + Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest); + if (!EFI_ERROR (Status)) { + // + // Enter critical region + // + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + Status = TcgDxeLogEvent ( + mTcg2EventInfo[Index].LogFormat, + NewEventHdr, + sizeof(TCG_PCR_EVENT_HDR), + NewEventData, + NewEventHdr->EventSize + ); + if (Status != EFI_SUCCESS) { + RetStatus = Status; + } + gBS->RestoreTPL (OldTpl); + // + // Exit critical region + // + } + break; + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2: + ZeroMem (&TcgPcrEvent2, sizeof(TcgPcrEvent2)); + TcgPcrEvent2.PCRIndex = NewEventHdr->PCRIndex; + TcgPcrEvent2.EventType = NewEventHdr->EventType; + DigestBuffer = (UINT8 *)&TcgPcrEvent2.Digest; + DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList); + CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(NewEventHdr->EventSize)); + DigestBuffer = DigestBuffer + sizeof(NewEventHdr->EventSize); + + // + // Enter critical region + // + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + Status = TcgDxeLogEvent ( + mTcg2EventInfo[Index].LogFormat, + &TcgPcrEvent2, + sizeof(TcgPcrEvent2.PCRIndex) + sizeof(TcgPcrEvent2.EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2.EventSize), + NewEventData, + NewEventHdr->EventSize + ); + if (Status != EFI_SUCCESS) { + RetStatus = Status; + } + gBS->RestoreTPL (OldTpl); + // + // Exit critical region + // + break; + } + } + } + + return RetStatus; +} + +/** + Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result, + and add an entry to the Event Log. + + @param[in] Flags Bitmap providing additional information. + @param[in] HashData Physical address of the start of the data buffer + to be hashed, extended, and logged. + @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData + @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. + @param[in] NewEventData Pointer to the new event data. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + +**/ +EFI_STATUS +TcgDxeHashLogExtendEvent ( + IN UINT64 Flags, + IN UINT8 *HashData, + IN UINT64 HashDataLen, + IN OUT TCG_PCR_EVENT_HDR *NewEventHdr, + IN UINT8 *NewEventData + ) +{ + EFI_STATUS Status; + TPML_DIGEST_VALUES DigestList; + + if (!mTcgDxeData.BsCap.TPMPresentFlag) { + return EFI_DEVICE_ERROR; + } + + Status = HashAndExtend ( + NewEventHdr->PCRIndex, + HashData, + (UINTN)HashDataLen, + &DigestList + ); + if (!EFI_ERROR (Status)) { + if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) { + Status = TcgDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData); + } + } + + if (Status == EFI_DEVICE_ERROR) { + DEBUG ((EFI_D_ERROR, "TcgDxeHashLogExtendEvent - %r. Disable TPM.\n", Status)); + mTcgDxeData.BsCap.TPMPresentFlag = FALSE; + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) + ); + } + + return Status; +} + +/** + The EFI_TCG2_PROTOCOL HashLogExtendEvent function call provides callers with + an opportunity to extend and optionally log events without requiring + knowledge of actual TPM commands. + The extend operation will occur even if this function cannot create an event + log entry (e.g. due to the event log being full). + + @param[in] This Indicates the calling context + @param[in] Flags Bitmap providing additional information. + @param[in] DataToHash Physical address of the start of the data buffer to be hashed. + @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash. + @param[in] Event Pointer to data buffer containing information about the event. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_UNSUPPORTED The PE/COFF image type is not supported. +**/ +EFI_STATUS +EFIAPI +Tcg2HashLogExtendEvent ( + IN EFI_TCG2_PROTOCOL *This, + IN UINT64 Flags, + IN EFI_PHYSICAL_ADDRESS DataToHash, + IN UINT64 DataToHashLen, + IN EFI_TCG2_EVENT *Event + ) +{ + EFI_STATUS Status; + TCG_PCR_EVENT_HDR NewEventHdr; + TPML_DIGEST_VALUES DigestList; + + DEBUG ((EFI_D_INFO, "Tcg2HashLogExtendEvent ...\n")); + + if ((This == NULL) || (DataToHash == 0) || (Event == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (!mTcgDxeData.BsCap.TPMPresentFlag) { + return EFI_DEVICE_ERROR; + } + + if (Event->Size < Event->Header.HeaderSize + sizeof(UINT32)) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Header.PCRIndex > MAX_PCR_INDEX) { + return EFI_INVALID_PARAMETER; + } + + NewEventHdr.PCRIndex = Event->Header.PCRIndex; + NewEventHdr.EventType = Event->Header.EventType; + NewEventHdr.EventSize = Event->Size - sizeof(UINT32) - Event->Header.HeaderSize; + if ((Flags & PE_COFF_IMAGE) != 0) { + Status = MeasurePeImageAndExtend ( + NewEventHdr.PCRIndex, + DataToHash, + (UINTN)DataToHashLen, + &DigestList + ); + if (!EFI_ERROR (Status)) { + if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) { + Status = TcgDxeLogHashEvent (&DigestList, &NewEventHdr, Event->Event); + } + } + if (Status == EFI_DEVICE_ERROR) { + DEBUG ((EFI_D_ERROR, "MeasurePeImageAndExtend - %r. Disable TPM.\n", Status)); + mTcgDxeData.BsCap.TPMPresentFlag = FALSE; + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) + ); + } + } else { + Status = TcgDxeHashLogExtendEvent ( + Flags, + (UINT8 *) (UINTN) DataToHash, + DataToHashLen, + &NewEventHdr, + Event->Event + ); + } + DEBUG ((EFI_D_INFO, "Tcg2HashLogExtendEvent - %r\n", Status)); + return Status; +} + +/** + This service enables the sending of commands to the TPM. + + @param[in] This Indicates the calling context + @param[in] InputParameterBlockSize Size of the TPM input parameter block. + @param[in] InputParameterBlock Pointer to the TPM input parameter block. + @param[in] OutputParameterBlockSize Size of the TPM output parameter block. + @param[in] OutputParameterBlock Pointer to the TPM output parameter block. + + @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received. + @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. +**/ +EFI_STATUS +EFIAPI +Tcg2SubmitCommand ( + IN EFI_TCG2_PROTOCOL *This, + IN UINT32 InputParameterBlockSize, + IN UINT8 *InputParameterBlock, + IN UINT32 OutputParameterBlockSize, + IN UINT8 *OutputParameterBlock + ) +{ + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "Tcg2SubmitCommand ...\n")); + + if ((This == NULL) || + (InputParameterBlockSize == 0) || (InputParameterBlock == NULL) || + (OutputParameterBlockSize == 0) || (OutputParameterBlock == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (!mTcgDxeData.BsCap.TPMPresentFlag) { + return EFI_DEVICE_ERROR; + } + + if (InputParameterBlockSize >= mTcgDxeData.BsCap.MaxCommandSize) { + return EFI_INVALID_PARAMETER; + } + if (OutputParameterBlockSize >= mTcgDxeData.BsCap.MaxResponseSize) { + return EFI_INVALID_PARAMETER; + } + + Status = Tpm2SubmitCommand ( + InputParameterBlockSize, + InputParameterBlock, + &OutputParameterBlockSize, + OutputParameterBlock + ); + DEBUG ((EFI_D_INFO, "Tcg2SubmitCommand - %r\n", Status)); + return Status; +} + +/** + This service returns the currently active PCR banks. + + @param[in] This Indicates the calling context + @param[out] ActivePcrBanks Pointer to the variable receiving the bitmap of currently active PCR banks. + + @retval EFI_SUCCESS The bitmap of active PCR banks was stored in the ActivePcrBanks parameter. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. +**/ +EFI_STATUS +EFIAPI +Tcg2GetActivePCRBanks ( + IN EFI_TCG2_PROTOCOL *This, + OUT UINT32 *ActivePcrBanks + ) +{ + if (ActivePcrBanks == NULL) { + return EFI_INVALID_PARAMETER; + } + *ActivePcrBanks = mTcgDxeData.BsCap.ActivePcrBanks; + return EFI_SUCCESS; +} + +/** + This service sets the currently active PCR banks. + + @param[in] This Indicates the calling context + @param[in] ActivePcrBanks Bitmap of the requested active PCR banks. At least one bit SHALL be set. + + @retval EFI_SUCCESS The bitmap in ActivePcrBank parameter is already active. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. +**/ +EFI_STATUS +EFIAPI +Tcg2SetActivePCRBanks ( + IN EFI_TCG2_PROTOCOL *This, + IN UINT32 ActivePcrBanks + ) +{ + EFI_STATUS Status; + UINT32 ReturnCode; + + DEBUG ((EFI_D_INFO, "Tcg2SetActivePCRBanks ... (0x%x)\n", ActivePcrBanks)); + + if (ActivePcrBanks == 0) { + return EFI_INVALID_PARAMETER; + } + if ((ActivePcrBanks & (~mTcgDxeData.BsCap.HashAlgorithmBitmap)) != 0) { + return EFI_INVALID_PARAMETER; + } + if (ActivePcrBanks == mTcgDxeData.BsCap.ActivePcrBanks) { + // + // Need clear previous SET_PCR_BANKS setting + // + ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (TCG2_PHYSICAL_PRESENCE_NO_ACTION, 0); + } else { + ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS, ActivePcrBanks); + } + + if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) { + Status = EFI_SUCCESS; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) { + Status = EFI_OUT_OF_RESOURCES; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_DEVICE_ERROR; + } + + DEBUG ((EFI_D_INFO, "Tcg2SetActivePCRBanks - %r\n", Status)); + + return Status; +} + +/** + This service retrieves the result of a previous invocation of SetActivePcrBanks. + + @param[in] This Indicates the calling context + @param[out] OperationPresent Non-zero value to indicate a SetActivePcrBank operation was invoked during the last boot. + @param[out] Response The response from the SetActivePcrBank request. + + @retval EFI_SUCCESS The result value could be returned. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. +**/ +EFI_STATUS +EFIAPI +Tcg2GetResultOfSetActivePcrBanks ( + IN EFI_TCG2_PROTOCOL *This, + OUT UINT32 *OperationPresent, + OUT UINT32 *Response + ) +{ + UINT32 ReturnCode; + + if ((OperationPresent == NULL) || (Response == NULL)) { + return EFI_INVALID_PARAMETER; + } + + ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (OperationPresent, Response); + if (ReturnCode == TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS) { + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } +} + +EFI_TCG2_PROTOCOL mTcg2Protocol = { + Tcg2GetCapability, + Tcg2GetEventLog, + Tcg2HashLogExtendEvent, + Tcg2SubmitCommand, + Tcg2GetActivePCRBanks, + Tcg2SetActivePCRBanks, + Tcg2GetResultOfSetActivePcrBanks, +}; + +/** + Initialize the Event Log and log events passed from the PEI phase. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. + +**/ +EFI_STATUS +SetupEventLog ( + VOID + ) +{ + EFI_STATUS Status; + VOID *TcgEvent; + EFI_PEI_HOB_POINTERS GuidHob; + EFI_PHYSICAL_ADDRESS Lasa; + UINTN Index; + UINT32 DigestListBinSize; + UINT32 EventSize; + TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct; + UINT8 TempBuf[sizeof(TCG_EfiSpecIDEventStruct) + (HASH_COUNT * sizeof(TCG_EfiSpecIdEventAlgorithmSize)) + sizeof(UINT8)]; + TCG_PCR_EVENT_HDR FirstPcrEvent; + TCG_EfiSpecIdEventAlgorithmSize *digestSize; + UINT8 *vendorInfoSize; + UINT32 numberOfAlgorithms; + + DEBUG ((EFI_D_INFO, "SetupEventLog\n")); + + // + // 1. Create Log Area + // + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { + if ((mTcgDxeData.BsCap.SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { + mTcgDxeData.EventLogAreaStruct[Index].EventLogFormat = mTcg2EventInfo[Index].LogFormat; + Lasa = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES (EFI_TCG_LOG_AREA_SIZE), + &Lasa + ); + if (EFI_ERROR (Status)) { + return Status; + } + mTcgDxeData.EventLogAreaStruct[Index].Lasa = Lasa; + mTcgDxeData.EventLogAreaStruct[Index].Laml = EFI_TCG_LOG_AREA_SIZE; + // + // To initialize them as 0xFF is recommended + // because the OS can know the last entry for that. + // + SetMem ((VOID *)(UINTN)Lasa, EFI_TCG_LOG_AREA_SIZE, 0xFF); + // + // Create first entry for Log Header Entry Data + // + if (mTcg2EventInfo[Index].LogFormat != EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2) { + // + // TcgEfiSpecIdEventStruct + // + TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)TempBuf; + CopyMem (TcgEfiSpecIdEventStruct->signature, TCG_EfiSpecIDEventStruct_SIGNATURE_03, sizeof(TcgEfiSpecIdEventStruct->signature)); + TcgEfiSpecIdEventStruct->platformClass = PcdGet8 (PcdTpmPlatformClass); + TcgEfiSpecIdEventStruct->specVersionMajor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MAJOR_TPM2; + TcgEfiSpecIdEventStruct->specVersionMinor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM2; + TcgEfiSpecIdEventStruct->specErrata = TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2; + TcgEfiSpecIdEventStruct->uintnSize = sizeof(UINTN)/sizeof(UINT32); + numberOfAlgorithms = 0; + digestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof(*TcgEfiSpecIdEventStruct) + sizeof(numberOfAlgorithms)); + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) { + digestSize[numberOfAlgorithms].algorithmId = TPM_ALG_SHA1; + digestSize[numberOfAlgorithms].digestSize = SHA1_DIGEST_SIZE; + numberOfAlgorithms++; + } + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) { + digestSize[numberOfAlgorithms].algorithmId = TPM_ALG_SHA256; + digestSize[numberOfAlgorithms].digestSize = SHA256_DIGEST_SIZE; + numberOfAlgorithms++; + } + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) { + digestSize[numberOfAlgorithms].algorithmId = TPM_ALG_SHA384; + digestSize[numberOfAlgorithms].digestSize = SHA384_DIGEST_SIZE; + numberOfAlgorithms++; + } + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) { + digestSize[numberOfAlgorithms].algorithmId = TPM_ALG_SHA512; + digestSize[numberOfAlgorithms].digestSize = SHA512_DIGEST_SIZE; + numberOfAlgorithms++; + } + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) { + digestSize[numberOfAlgorithms].algorithmId = TPM_ALG_SM3_256; + digestSize[numberOfAlgorithms].digestSize = SM3_256_DIGEST_SIZE; + numberOfAlgorithms++; + } + CopyMem (TcgEfiSpecIdEventStruct + 1, &numberOfAlgorithms, sizeof(numberOfAlgorithms)); + vendorInfoSize = (UINT8 *)&digestSize[numberOfAlgorithms]; + *vendorInfoSize = 0; + + // + // FirstPcrEvent + // + FirstPcrEvent.PCRIndex = 0; + FirstPcrEvent.EventType = EV_NO_ACTION; + ZeroMem (&FirstPcrEvent.Digest, sizeof(FirstPcrEvent.Digest)); + FirstPcrEvent.EventSize = (UINT32)GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct); + + // + // Record + // + Status = TcgDxeLogEvent ( + mTcg2EventInfo[Index].LogFormat, + &FirstPcrEvent, + sizeof(FirstPcrEvent), + (UINT8 *)TcgEfiSpecIdEventStruct, + FirstPcrEvent.EventSize + ); + } + } + } + + // + // 2. Create Final Log Area + // + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { + if ((mTcgDxeData.BsCap.SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { + Lasa = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES (EFI_TCG_FINAL_LOG_AREA_SIZE), + &Lasa + ); + if (EFI_ERROR (Status)) { + return Status; + } + SetMem ((VOID *)(UINTN)Lasa, EFI_TCG_FINAL_LOG_AREA_SIZE, 0xFF); + + // + // Initialize + // + mTcgDxeData.FinalEventsTable[Index] = (VOID *)(UINTN)Lasa; + (mTcgDxeData.FinalEventsTable[Index])->Version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION; + (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents = 0; + + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogFormat = mTcg2EventInfo[Index].LogFormat; + mTcgDxeData.FinalEventLogAreaStruct[Index].Lasa = Lasa + sizeof(EFI_TCG2_FINAL_EVENTS_TABLE); + mTcgDxeData.FinalEventLogAreaStruct[Index].Laml = EFI_TCG_FINAL_LOG_AREA_SIZE - sizeof(EFI_TCG2_FINAL_EVENTS_TABLE); + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogSize = 0; + mTcgDxeData.FinalEventLogAreaStruct[Index].LastEvent = (VOID *)(UINTN)mTcgDxeData.FinalEventLogAreaStruct[Index].Lasa; + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogStarted = FALSE; + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogTruncated = FALSE; + + if (mTcg2EventInfo[Index].LogFormat == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) { + // + // Install to configuration table + // + Status = gBS->InstallConfigurationTable (&gEfiTcg2FinalEventsTableGuid, (VOID *)mTcgDxeData.FinalEventsTable[1]); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + } + + // + // 3. Sync data from PEI to DXE + // + Status = EFI_SUCCESS; + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { + if ((mTcgDxeData.BsCap.SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { + GuidHob.Raw = GetHobList (); + Status = EFI_SUCCESS; + while (!EFI_ERROR (Status) && + (GuidHob.Raw = GetNextGuidHob (mTcg2EventInfo[Index].EventGuid, GuidHob.Raw)) != NULL) { + TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid); + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + switch (mTcg2EventInfo[Index].LogFormat) { + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2: + Status = TcgDxeLogEvent ( + mTcg2EventInfo[Index].LogFormat, + TcgEvent, + sizeof(TCG_PCR_EVENT_HDR), + ((TCG_PCR_EVENT*)TcgEvent)->Event, + ((TCG_PCR_EVENT_HDR*)TcgEvent)->EventSize + ); + break; + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2: + DigestListBinSize = GetDigestListBinSize ((UINT8 *)TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE)); + CopyMem (&EventSize, (UINT8 *)TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE) + DigestListBinSize, sizeof(UINT32)); + Status = TcgDxeLogEvent ( + mTcg2EventInfo[Index].LogFormat, + TcgEvent, + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE) + DigestListBinSize + sizeof(UINT32), + (UINT8 *)TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE) + DigestListBinSize + sizeof(UINT32), + EventSize + ); + break; + } + } + } + } + + return Status; +} + +/** + Measure and log an action string, and extend the measurement result into PCR[5]. + + @param[in] String A specific string that indicates an Action event. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +TcgMeasureAction ( + IN CHAR8 *String + ) +{ + TCG_PCR_EVENT_HDR TcgEvent; + + TcgEvent.PCRIndex = 5; + TcgEvent.EventType = EV_EFI_ACTION; + TcgEvent.EventSize = (UINT32)AsciiStrLen (String); + return TcgDxeHashLogExtendEvent ( + 0, + (UINT8*)String, + TcgEvent.EventSize, + &TcgEvent, + (UINT8 *) String + ); +} + +/** + Measure and log EFI handoff tables, and extend the measurement result into PCR[1]. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +MeasureHandoffTables ( + VOID + ) +{ + EFI_STATUS Status; + SMBIOS_TABLE_ENTRY_POINT *SmbiosTable; + TCG_PCR_EVENT_HDR TcgEvent; + EFI_HANDOFF_TABLE_POINTERS HandoffTables; + UINTN ProcessorNum; + EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf; + + ProcessorLocBuf = NULL; + + // + // Measure SMBIOS with EV_EFI_HANDOFF_TABLES to PCR[1] + // + Status = EfiGetSystemConfigurationTable ( + &gEfiSmbiosTableGuid, + (VOID **) &SmbiosTable + ); + + if (!EFI_ERROR (Status) && SmbiosTable != NULL) { + TcgEvent.PCRIndex = 1; + TcgEvent.EventType = EV_EFI_HANDOFF_TABLES; + TcgEvent.EventSize = sizeof (HandoffTables); + + HandoffTables.NumberOfTables = 1; + HandoffTables.TableEntry[0].VendorGuid = gEfiSmbiosTableGuid; + HandoffTables.TableEntry[0].VendorTable = SmbiosTable; + + DEBUG ((DEBUG_INFO, "The Smbios Table starts at: 0x%x\n", SmbiosTable->TableAddress)); + DEBUG ((DEBUG_INFO, "The Smbios Table size: 0x%x\n", SmbiosTable->TableLength)); + + Status = TcgDxeHashLogExtendEvent ( + 0, + (UINT8*)(UINTN)SmbiosTable->TableAddress, + SmbiosTable->TableLength, + &TcgEvent, + (UINT8*)&HandoffTables + ); + } + + if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) { + // + // Tcg Server spec. + // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1] + // + Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum); + + if (!EFI_ERROR(Status)){ + TcgEvent.PCRIndex = 1; + TcgEvent.EventType = EV_TABLE_OF_DEVICES; + TcgEvent.EventSize = sizeof (HandoffTables); + + HandoffTables.NumberOfTables = 1; + HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid; + HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf; + + Status = TcgDxeHashLogExtendEvent ( + 0, + (UINT8*)(UINTN)ProcessorLocBuf, + sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum, + &TcgEvent, + (UINT8*)&HandoffTables + ); + + FreePool(ProcessorLocBuf); + } + } + + return Status; +} + +/** + Measure and log Separator event, and extend the measurement result into a specific PCR. + + @param[in] PCRIndex PCR index. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +MeasureSeparatorEvent ( + IN TPM_PCRINDEX PCRIndex + ) +{ + TCG_PCR_EVENT_HDR TcgEvent; + UINT32 EventData; + + DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent Pcr - %x\n", PCRIndex)); + + EventData = 0; + TcgEvent.PCRIndex = PCRIndex; + TcgEvent.EventType = EV_SEPARATOR; + TcgEvent.EventSize = (UINT32)sizeof (EventData); + return TcgDxeHashLogExtendEvent ( + 0, + (UINT8 *)&EventData, + sizeof (EventData), + &TcgEvent, + (UINT8 *)&EventData + ); +} + +/** + Measure and log an EFI variable, and extend the measurement result into a specific PCR. + + @param[in] PCRIndex PCR Index. + @param[in] EventType Event type. + @param[in] VarName A Null-terminated string that is the name of the vendor's variable. + @param[in] VendorGuid A unique identifier for the vendor. + @param[in] VarData The content of the variable data. + @param[in] VarSize The size of the variable data. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +MeasureVariable ( + IN TPM_PCRINDEX PCRIndex, + IN TCG_EVENTTYPE EventType, + IN CHAR16 *VarName, + IN EFI_GUID *VendorGuid, + IN VOID *VarData, + IN UINTN VarSize + ) +{ + EFI_STATUS Status; + TCG_PCR_EVENT_HDR TcgEvent; + UINTN VarNameLength; + EFI_VARIABLE_DATA_TREE *VarLog; + + DEBUG ((EFI_D_INFO, "Tcg2Dxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PCRIndex, (UINTN)EventType)); + DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid)); + + VarNameLength = StrLen (VarName); + TcgEvent.PCRIndex = PCRIndex; + TcgEvent.EventType = EventType; + + TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize + - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData)); + + VarLog = (EFI_VARIABLE_DATA_TREE *)AllocatePool (TcgEvent.EventSize); + if (VarLog == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + VarLog->VariableName = *VendorGuid; + VarLog->UnicodeNameLength = VarNameLength; + VarLog->VariableDataLength = VarSize; + CopyMem ( + VarLog->UnicodeName, + VarName, + VarNameLength * sizeof (*VarName) + ); + if (VarSize != 0 && VarData != NULL) { + CopyMem ( + (CHAR16 *)VarLog->UnicodeName + VarNameLength, + VarData, + VarSize + ); + } + + if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) { + // + // Digest is the event data (EFI_VARIABLE_DATA) + // + Status = TcgDxeHashLogExtendEvent ( + 0, + (UINT8*)VarLog, + TcgEvent.EventSize, + &TcgEvent, + (UINT8*)VarLog + ); + } else { + Status = TcgDxeHashLogExtendEvent ( + 0, + (UINT8*)VarData, + VarSize, + &TcgEvent, + (UINT8*)VarLog + ); + } + FreePool (VarLog); + return Status; +} + +/** + Read then Measure and log an EFI variable, and extend the measurement result into a specific PCR. + + @param[in] PCRIndex PCR Index. + @param[in] EventType Event type. + @param[in] VarName A Null-terminated string that is the name of the vendor's variable. + @param[in] VendorGuid A unique identifier for the vendor. + @param[out] VarSize The size of the variable data. + @param[out] VarData Pointer to the content of the variable. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +ReadAndMeasureVariable ( + IN TPM_PCRINDEX PCRIndex, + IN TCG_EVENTTYPE EventType, + IN CHAR16 *VarName, + IN EFI_GUID *VendorGuid, + OUT UINTN *VarSize, + OUT VOID **VarData + ) +{ + EFI_STATUS Status; + + Status = GetVariable2 (VarName, VendorGuid, VarData, VarSize); + if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) { + if (EFI_ERROR (Status)) { + // + // It is valid case, so we need handle it. + // + *VarData = NULL; + *VarSize = 0; + } + } else { + // + // if status error, VarData is freed and set NULL by GetVariable2 + // + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } + + Status = MeasureVariable ( + PCRIndex, + EventType, + VarName, + VendorGuid, + *VarData, + *VarSize + ); + return Status; +} + +/** + Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5]. + + @param[in] VarName A Null-terminated string that is the name of the vendor's variable. + @param[in] VendorGuid A unique identifier for the vendor. + @param[out] VarSize The size of the variable data. + @param[out] VarData Pointer to the content of the variable. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +ReadAndMeasureBootVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VendorGuid, + OUT UINTN *VarSize, + OUT VOID **VarData + ) +{ + return ReadAndMeasureVariable ( + 5, + EV_EFI_VARIABLE_BOOT, + VarName, + VendorGuid, + VarSize, + VarData + ); +} + +/** + Read then Measure and log an EFI Secure variable, and extend the measurement result into PCR[7]. + + @param[in] VarName A Null-terminated string that is the name of the vendor's variable. + @param[in] VendorGuid A unique identifier for the vendor. + @param[out] VarSize The size of the variable data. + @param[out] VarData Pointer to the content of the variable. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +ReadAndMeasureSecureVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VendorGuid, + OUT UINTN *VarSize, + OUT VOID **VarData + ) +{ + return ReadAndMeasureVariable ( + 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + VarName, + VendorGuid, + VarSize, + VarData + ); +} + +/** + Measure and log all EFI boot variables, and extend the measurement result into a specific PCR. + + The EFI boot variables are BootOrder and Boot#### variables. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +MeasureAllBootVariables ( + VOID + ) +{ + EFI_STATUS Status; + UINT16 *BootOrder; + UINTN BootCount; + UINTN Index; + VOID *BootVarData; + UINTN Size; + + Status = ReadAndMeasureBootVariable ( + mBootVarName, + &gEfiGlobalVariableGuid, + &BootCount, + (VOID **) &BootOrder + ); + if (Status == EFI_NOT_FOUND || BootOrder == NULL) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + // + // BootOrder can't be NULL if status is not EFI_NOT_FOUND + // + FreePool (BootOrder); + return Status; + } + + BootCount /= sizeof (*BootOrder); + for (Index = 0; Index < BootCount; Index++) { + UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]); + Status = ReadAndMeasureBootVariable ( + mBootVarName, + &gEfiGlobalVariableGuid, + &Size, + &BootVarData + ); + if (!EFI_ERROR (Status)) { + FreePool (BootVarData); + } + } + + FreePool (BootOrder); + return EFI_SUCCESS; +} + +/** + Measure and log all EFI Secure variables, and extend the measurement result into a specific PCR. + + The EFI boot variables are BootOrder and Boot#### variables. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +MeasureAllSecureVariables ( + VOID + ) +{ + EFI_STATUS Status; + VOID *Data; + UINTN DataSize; + UINTN Index; + + Status = EFI_NOT_FOUND; + for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) { + Status = ReadAndMeasureSecureVariable ( + mVariableType[Index].VariableName, + mVariableType[Index].VendorGuid, + &DataSize, + &Data + ); + if (!EFI_ERROR (Status)) { + if (Data != NULL) { + FreePool (Data); + } + } + } + + return EFI_SUCCESS; +} + +/** + Measure and log launch of FirmwareDebugger, and extend the measurement result into a specific PCR. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +MeasureLaunchOfFirmwareDebugger ( + VOID + ) +{ + TCG_PCR_EVENT_HDR TcgEvent; + + TcgEvent.PCRIndex = 7; + TcgEvent.EventType = EV_EFI_ACTION; + TcgEvent.EventSize = sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1; + return TcgDxeHashLogExtendEvent ( + 0, + (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING, + sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1, + &TcgEvent, + (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING + ); +} + +/** + Measure and log all Secure Boot Policy, and extend the measurement result into a specific PCR. + + Platform firmware adhering to the policy must therefore measure the following values into PCR[7]: (in order listed) + - The contents of the SecureBoot variable + - The contents of the PK variable + - The contents of the KEK variable + - The contents of the EFI_IMAGE_SECURITY_DATABASE variable + - The contents of the EFI_IMAGE_SECURITY_DATABASE1 variable + - Separator + - Entries in the EFI_IMAGE_SECURITY_DATABASE that are used to validate EFI Drivers or EFI Boot Applications in the boot path + + NOTE: Because of the above, UEFI variables PK, KEK, EFI_IMAGE_SECURITY_DATABASE, + EFI_IMAGE_SECURITY_DATABASE1 and SecureBoot SHALL NOT be measured into PCR[3]. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +MeasureSecureBootPolicy ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + VOID *Protocol; + + Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol); + if (EFI_ERROR (Status)) { + return; + } + + if (PcdGetBool (PcdFirmwareDebuggerInitialized)) { + Status = MeasureLaunchOfFirmwareDebugger (); + DEBUG ((EFI_D_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status)); + } + + Status = MeasureAllSecureVariables (); + DEBUG ((EFI_D_INFO, "MeasureAllSecureVariables - %r\n", Status)); + + // + // We need measure Separator(7) here, because this event must be between SecureBootPolicy (Configure) + // and ImageVerification (Authority) + // There might be a case that we need measure UEFI image from DriverOrder, besides BootOrder. So + // the Authority measurement happen before ReadToBoot event. + // + Status = MeasureSeparatorEvent (7); + DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent - %r\n", Status)); + return ; +} + +/** + Ready to Boot Event notification handler. + + Sequence of OS boot events is measured in this event notification handler. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context + +**/ +VOID +EFIAPI +OnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + TPM_PCRINDEX PcrIndex; + + PERF_START_EX (mImageHandle, "EventRec", "Tcg2Dxe", 0, PERF_ID_TCG2_DXE); + if (mBootAttempts == 0) { + + // + // Measure handoff tables. + // + Status = MeasureHandoffTables (); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n")); + } + + // + // Measure BootOrder & Boot#### variables. + // + Status = MeasureAllBootVariables (); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n")); + } + + // + // 1. This is the first boot attempt. + // + Status = TcgMeasureAction ( + EFI_CALLING_EFI_APPLICATION + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION)); + } + + // + // 2. Draw a line between pre-boot env and entering post-boot env. + // PCR[7] is already done. + // + for (PcrIndex = 0; PcrIndex < 7; PcrIndex++) { + Status = MeasureSeparatorEvent (PcrIndex); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Seperator Event not Measured. Error!\n")); + } + } + + // + // 3. Measure GPT. It would be done in SAP driver. + // + + // + // 4. Measure PE/COFF OS loader. It would be done in SAP driver. + // + + // + // 5. Read & Measure variable. BootOrder already measured. + // + } else { + // + // 6. Not first attempt, meaning a return from last attempt + // + Status = TcgMeasureAction ( + EFI_RETURNING_FROM_EFI_APPLICATOIN + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN)); + } + } + + DEBUG ((EFI_D_INFO, "TPM2 Tcg2Dxe Measure Data when ReadyToBoot\n")); + // + // Increase boot attempt counter. + // + mBootAttempts++; + PERF_END_EX (mImageHandle, "EventRec", "Tcg2Dxe", 0, PERF_ID_TCG2_DXE + 1); +} + +/** + Exit Boot Services Event notification handler. + + Measure invocation and success of ExitBootServices. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context + +**/ +VOID +EFIAPI +OnExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + // + // Measure invocation of ExitBootServices, + // + Status = TcgMeasureAction ( + EFI_EXIT_BOOT_SERVICES_INVOCATION + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION)); + } + + // + // Measure success of ExitBootServices + // + Status = TcgMeasureAction ( + EFI_EXIT_BOOT_SERVICES_SUCCEEDED + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED)); + } +} + +/** + Exit Boot Services Failed Event notification handler. + + Measure Failure of ExitBootServices. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context + +**/ +VOID +EFIAPI +OnExitBootServicesFailed ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + // + // Measure Failure of ExitBootServices, + // + Status = TcgMeasureAction ( + EFI_EXIT_BOOT_SERVICES_FAILED + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED)); + } + +} + +/** + The function install Tcg2 protocol. + + @retval EFI_SUCCESS Tcg2 protocol is installed. + @retval other Some error occurs. +**/ +EFI_STATUS +InstallTcg2 ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiTcg2ProtocolGuid, + &mTcg2Protocol, + NULL + ); + return Status; +} + +/** + The driver's entry point. It publishes EFI Tcg2 Protocol. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. +**/ +EFI_STATUS +EFIAPI +DriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + VOID *Registration; + UINT32 MaxCommandSize; + UINT32 MaxResponseSize; + TPML_PCR_SELECTION Pcrs; + UINTN Index; + EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap; + UINT32 ActivePCRBanks; + UINT32 NumberOfPCRBanks; + + mImageHandle = ImageHandle; + + if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) || + CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ + DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n")); + return EFI_UNSUPPORTED; + } + + if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { + DEBUG ((EFI_D_ERROR, "TPM2 error!\n")); + return EFI_DEVICE_ERROR; + } + + Status = Tpm2RequestUseTpm (); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "TPM2 not detected!\n")); + return Status; + } + + // + // Fill information + // + ASSERT (TCG_EVENT_LOG_AREA_COUNT_MAX == sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0])); + + mTcgDxeData.BsCap.Size = sizeof(EFI_TCG2_BOOT_SERVICE_CAPABILITY); + mTcgDxeData.BsCap.ProtocolVersion.Major = 1; + mTcgDxeData.BsCap.ProtocolVersion.Minor = 1; + mTcgDxeData.BsCap.StructureVersion.Major = 1; + mTcgDxeData.BsCap.StructureVersion.Minor = 1; + + DEBUG ((EFI_D_INFO, "Tcg2.ProtocolVersion - %02x.%02x\n", mTcgDxeData.BsCap.ProtocolVersion.Major, mTcgDxeData.BsCap.ProtocolVersion.Minor)); + DEBUG ((EFI_D_INFO, "Tcg2.StructureVersion - %02x.%02x\n", mTcgDxeData.BsCap.StructureVersion.Major, mTcgDxeData.BsCap.StructureVersion.Minor)); + + Status = Tpm2GetCapabilityManufactureID (&mTcgDxeData.BsCap.ManufacturerID); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityManufactureID fail!\n")); + } else { + DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityManufactureID - %08x\n", mTcgDxeData.BsCap.ManufacturerID)); + } + + DEBUG_CODE ( + UINT32 FirmwareVersion1; + UINT32 FirmwareVersion2; + + Status = Tpm2GetCapabilityFirmwareVersion (&FirmwareVersion1, &FirmwareVersion2); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityFirmwareVersion fail!\n")); + } else { + DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityFirmwareVersion - %08x %08x\n", FirmwareVersion1, FirmwareVersion2)); + } + ); + + Status = Tpm2GetCapabilityMaxCommandResponseSize (&MaxCommandSize, &MaxResponseSize); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize fail!\n")); + } else { + mTcgDxeData.BsCap.MaxCommandSize = (UINT16)MaxCommandSize; + mTcgDxeData.BsCap.MaxResponseSize = (UINT16)MaxResponseSize; + DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityMaxCommandResponseSize - %08x, %08x\n", MaxCommandSize, MaxResponseSize)); + } + + // + // Get supported PCR and current Active PCRs + // + Status = Tpm2GetCapabilityPcrs (&Pcrs); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n")); + TpmHashAlgorithmBitmap = EFI_TCG2_BOOT_HASH_ALG_SHA1; + NumberOfPCRBanks = 1; + ActivePCRBanks = EFI_TCG2_BOOT_HASH_ALG_SHA1; + } else { + DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count)); + NumberOfPCRBanks = 0; + TpmHashAlgorithmBitmap = 0; + ActivePCRBanks = 0; + for (Index = 0; Index < Pcrs.count; Index++) { + DEBUG ((EFI_D_INFO, "hash - %x\n", Pcrs.pcrSelections[Index].hash)); + switch (Pcrs.pcrSelections[Index].hash) { + case TPM_ALG_SHA1: + TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SHA1; + NumberOfPCRBanks ++; + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA1; + } + break; + case TPM_ALG_SHA256: + TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SHA256; + NumberOfPCRBanks ++; + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA256; + } + break; + case TPM_ALG_SHA384: + TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SHA384; + NumberOfPCRBanks ++; + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA384; + } + break; + case TPM_ALG_SHA512: + TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SHA512; + NumberOfPCRBanks ++; + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA512; + } + break; + case TPM_ALG_SM3_256: + TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SM3_256; + NumberOfPCRBanks ++; + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SM3_256; + } + break; + } + } + } + mTcgDxeData.BsCap.HashAlgorithmBitmap = TpmHashAlgorithmBitmap & PcdGet32 (PcdTcg2HashAlgorithmBitmap); + mTcgDxeData.BsCap.ActivePcrBanks = ActivePCRBanks & PcdGet32 (PcdTcg2HashAlgorithmBitmap); + + if (PcdGet32 (PcdTcg2NumberOfPCRBanks) == 0) { + mTcgDxeData.BsCap.NumberOfPCRBanks = NumberOfPCRBanks; + } else { + mTcgDxeData.BsCap.NumberOfPCRBanks = PcdGet32 (PcdTcg2NumberOfPCRBanks); + if (PcdGet32 (PcdTcg2NumberOfPCRBanks) > NumberOfPCRBanks) { + DEBUG ((EFI_D_ERROR, "ERROR: PcdTcg2NumberOfPCRBanks(0x%x) > NumberOfPCRBanks(0x%x)\n", PcdGet32 (PcdTcg2NumberOfPCRBanks), NumberOfPCRBanks)); + mTcgDxeData.BsCap.NumberOfPCRBanks = NumberOfPCRBanks; + } + } + + mTcgDxeData.BsCap.SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; + if ((mTcgDxeData.BsCap.ActivePcrBanks & TREE_BOOT_HASH_ALG_SHA1) == 0) { + // + // No need to expose TCG1.2 event log if SHA1 bank does not exist. + // + mTcgDxeData.BsCap.SupportedEventLogs &= ~TREE_EVENT_LOG_FORMAT_TCG_1_2; + } + + DEBUG ((EFI_D_INFO, "Tcg2.SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs)); + DEBUG ((EFI_D_INFO, "Tcg2.HashAlgorithmBitmap - 0x%08x\n", mTcgDxeData.BsCap.HashAlgorithmBitmap)); + DEBUG ((EFI_D_INFO, "Tcg2.NumberOfPCRBanks - 0x%08x\n", mTcgDxeData.BsCap.NumberOfPCRBanks)); + DEBUG ((EFI_D_INFO, "Tcg2.ActivePcrBanks - 0x%08x\n", mTcgDxeData.BsCap.ActivePcrBanks)); + + if (mTcgDxeData.BsCap.TPMPresentFlag) { + // + // Setup the log area and copy event log from hob list to it + // + Status = SetupEventLog (); + ASSERT_EFI_ERROR (Status); + + // + // Measure handoff tables, Boot#### variables etc. + // + Status = EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + OnReadyToBoot, + NULL, + &Event + ); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + OnExitBootServices, + NULL, + &gEfiEventExitBootServicesGuid, + &Event + ); + + // + // Measure Exit Boot Service failed + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + OnExitBootServicesFailed, + NULL, + &gEventExitBootServicesFailedGuid, + &Event + ); + + // + // Create event callback, because we need access variable on SecureBootPolicyVariable + // We should use VariableWriteArch instead of VariableArch, because Variable driver + // may update SecureBoot value based on last setting. + // + EfiCreateProtocolNotifyEvent (&gEfiVariableWriteArchProtocolGuid, TPL_CALLBACK, MeasureSecureBootPolicy, NULL, &Registration); + } + + // + // Install Tcg2Protocol + // + Status = InstallTcg2 (); + DEBUG ((EFI_D_INFO, "InstallTcg2 - %r\n", Status)); + + return Status; +} diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf new file mode 100644 index 0000000000..d6ac07ea6e --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf @@ -0,0 +1,112 @@ +## @file +# Produces Tcg2 protocol and measure boot environment +# This module will produce Tcg2 protocol and measure boot environment. +# +# Caution: This module requires additional review when modified. +# This driver will have external input - PE/COFF image. +# This external input must be validated carefully to avoid security issue like +# buffer overflow, integer overflow. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2Dxe + MODULE_UNI_FILE = Tcg2Dxe.uni + FILE_GUID = FDFF263D-5F68-4591-87BA-B768F445A9AF + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DriverEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF +# + +[Sources] + Tcg2Dxe.c + MeasureBootPeCoff.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + UefiBootServicesTableLib + HobLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib + Tpm2CommandLib + PrintLib + UefiLib + Tpm2DeviceLib + HashLib + PerformanceLib + ReportStatusCodeLib + Tcg2PhysicalPresenceLib + +[Guids] + ## SOMETIMES_CONSUMES ## SystemTable # Smbios Table + ## SOMETIMES_CONSUMES ## GUID # Handoff Table for measurement. + gEfiSmbiosTableGuid + + ## SOMETIMES_CONSUMES ## Variable:L"SecureBoot" + ## SOMETIMES_CONSUMES ## Variable:L"PK" + ## SOMETIMES_CONSUMES ## Variable:L"KEK" + ## SOMETIMES_CONSUMES ## Variable:L"BootXXXX" + gEfiGlobalVariableGuid + + ## SOMETIMES_CONSUMES ## Variable:L"db" + ## SOMETIMES_CONSUMES ## Variable:L"dbx" + gEfiImageSecurityDatabaseGuid + + gTcgEventEntryHobGuid ## SOMETIMES_CONSUMES ## HOB + gTpmErrorHobGuid ## SOMETIMES_CONSUMES ## HOB + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + gEventExitBootServicesFailedGuid ## SOMETIMES_CONSUMES ## Event + gEfiTpmDeviceInstanceNoneGuid ## SOMETIMES_CONSUMES ## GUID # TPM device identifier + gEfiTpmDeviceInstanceTpm12Guid ## SOMETIMES_CONSUMES ## GUID # TPM device identifier + + gTcgEvent2EntryHobGuid ## SOMETIMES_CONSUMES ## HOB + +[Protocols] + gEfiTcg2ProtocolGuid ## PRODUCES + gEfiTcg2FinalEventsTableGuid ## PRODUCES + gEfiAcpiTableProtocolGuid ## NOTIFY + gEfiMpServiceProtocolGuid ## SOMETIMES_CONSUMES + gEfiVariableWriteArchProtocolGuid ## NOTIFY + +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass ## SOMETIMES_CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdFirmwareDebuggerInitialized ## SOMETIMES_CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## SOMETIMES_CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeSubClassTpmDevice ## SOMETIMES_CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTcg2NumberOfPCRBanks ## CONSUMES + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + Tcg2DxeExtra.uni diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.uni b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.uni new file mode 100644 index 0000000000000000000000000000000000000000..8fd8b2a367662d019e789147a839fa36961984ce GIT binary patch literal 2320 zcmd6o-A@xy5XI-&#Q$MaUerLVB)$-1gtB5I(x#N4Poy7P+SqPuKT!U8^>^m7y$b>L zMPoMI`!RFRoH;Xh`{R4fYL@VO#*^3^8`{_=mf2%_#I9^DTiDD7wzfX|OLjU|wB;)_>e zU!9?1h3Eydzr(A#VV0C;b#hz7dh9vu!Q~;g%Ki(!$~UOjC6@u~;&j(_lU1r@(%=wJ5tk4La+Lh|xh$wr`p41yNn|l_C?XYfHO16NcjW`8)Nkmm%@vl7Um<+nkLp{=GuDpl%PI#`_Q!lBDt{CN=fRf>Px^DYvACo<%Ipce zo-*#*b9-Sg9lL?5!j{51v*488$~tsQ70W($c|pstnYR=tu4Ue20)LWqzVxgW`ZsO>a*aUrb?{lw%>QUh9^uT>o ztu7c7-aXzrx8{Vb(zjp|`fmzSL=iK2#`_@ajQYiM2X<Qh6>a*QQAJ(v%;t+y>zP)7WsA{~3jZPuM`bDxiR@7o8~4U|mK zQe%hR2K{x$EOmX)?1V98U*EHU5Vdd6&nX_Kj@)FXKGwU!C|sdd7!Q1{)pm)~Id-8o zJz`?#c(t9`3HuFDh0*lrZC2v0J;m(cD<4G-Uiv~Q`X|QsSj1d+JH3e#vPkXY1}CC7 z(4s{*Ddu76>lXFXzhTX}YfrzeP0xh86ZE?PsR_mzXsKPmNP0=xebnl}=b>lIZ;P{I@Ym(|66{6eX)DXY+-ly+Fs$+USd<5Ti5#bj6bkT%kiW{W%e7- z4BxeFtzf+(a>F{slK-686?=DXtT3zD@2_p=&d%+D$iR+4f5Y6hclO>s*a>!2qAW_x z!qy-c*6;fDEiCDr!d%N=X0UohZz6@&tT7#eB)oE!r#acOLQmVq&=~zfmNyZx+I4NcY5c!FXm@tRs{R&{A`PH=@7BSfSH* zYy;*HzrH1p&}bj=jf6y8JLDKkeXOy?EL@?sn0s!m)yW>G8}@}7yNrR|5H)hl2KXaT zg%P{#BUa)rpK>O|Dn?m-)K_Aa{U`HxcEnuYUsz`Gw+QV=jnkkH zfqP>*&M)6l-7k7I^oB^g+fv;jD5LrYw_wMhj=>L!8Nl)iD{yE>R8E~gr`jo_dQJ5| uC0_iLtp(OOHS4lI#x96ezxww}@07k|-?yI61u^QMwR?^F+&KhASpNW7#?LhX literal 0 HcmV?d00001 diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c new file mode 100644 index 0000000000..ec94c24e4c --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c @@ -0,0 +1,946 @@ +/** @file + Initialize TPM2 device and measure FVs before handing off control to DXE. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PERF_ID_TCG2_PEI 0x3080 + +typedef struct { + EFI_GUID *EventGuid; + EFI_TCG2_EVENT_LOG_FORMAT LogFormat; +} TCG2_EVENT_INFO_STRUCT; + +TCG2_EVENT_INFO_STRUCT mTcg2EventInfo[] = { + {&gTcgEventEntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2}, + {&gTcgEvent2EntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2}, +}; + +BOOLEAN mImageInMemory = FALSE; +EFI_PEI_FILE_HANDLE mFileHandle; + +EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiTpmInitializedPpiGuid, + NULL +}; + +EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiTpmInitializationDonePpiGuid, + NULL +}; + +EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo; +UINT32 mMeasuredBaseFvIndex = 0; + +EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo; +UINT32 mMeasuredChildFvIndex = 0; + +/** + Measure and record the Firmware Volum Information once FvInfoPPI install. + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param[in] NotifyDescriptor Address of the notification descriptor data structure. + @param[in] Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS The FV Info is measured and recorded to TPM. + @return Others Fail to measure FV. + +**/ +EFI_STATUS +EFIAPI +FirmwareVolmeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + Record all measured Firmware Volum Information into a Guid Hob + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param[in] NotifyDescriptor Address of the notification descriptor data structure. + @param[in] Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS The FV Info is measured and recorded to TPM. + @return Others Fail to measure FV. + +**/ +EFI_STATUS +EFIAPI +EndofPeiSignalNotifyCallBack ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + &gEfiPeiFirmwareVolumeInfoPpiGuid, + FirmwareVolmeInfoPpiNotifyCallback + }, + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + &gEfiPeiFirmwareVolumeInfo2PpiGuid, + FirmwareVolmeInfoPpiNotifyCallback + }, + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + EndofPeiSignalNotifyCallBack + } +}; + +EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi; + +/** + This function get digest from digest list. + + @param HashAlg digest algorithm + @param DigestList digest list + @param Digest digest + + @retval EFI_SUCCESS Sha1Digest is found and returned. + @retval EFI_NOT_FOUND Sha1Digest is not found. +**/ +EFI_STATUS +Tpm2GetDigestFromDigestList ( + IN TPMI_ALG_HASH HashAlg, + IN TPML_DIGEST_VALUES *DigestList, + IN VOID *Digest + ) +{ + UINTN Index; + UINT16 DigestSize; + + DigestSize = GetHashSizeFromAlgo (HashAlg); + for (Index = 0; Index < DigestList->count; Index++) { + if (DigestList->digests[Index].hashAlg == HashAlg) { + CopyMem ( + Digest, + &DigestList->digests[Index].digest, + DigestSize + ); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Record all measured Firmware Volum Information into a Guid Hob + Guid Hob payload layout is + + UINT32 *************************** FIRMWARE_BLOB number + EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param[in] NotifyDescriptor Address of the notification descriptor data structure. + @param[in] Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS The FV Info is measured and recorded to TPM. + @return Others Fail to measure FV. + +**/ +EFI_STATUS +EFIAPI +EndofPeiSignalNotifyCallBack ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + MEASURED_HOB_DATA *MeasuredHobData; + + MeasuredHobData = NULL; + + // + // Create a Guid hob to save all measured Fv + // + MeasuredHobData = BuildGuidHob( + &gMeasuredFvHobGuid, + sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex) + ); + + if (MeasuredHobData != NULL){ + // + // Save measured FV info enty number + // + MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex; + + // + // Save measured base Fv info + // + CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex)); + + // + // Save measured child Fv info + // + CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex)); + } + + return EFI_SUCCESS; +} + +/** + Check if buffer is all zero. + + @param[in] Buffer Buffer to be checked. + @param[in] BufferSize Size of buffer to be checked. + + @retval TRUE Buffer is all zero. + @retval FALSE Buffer is not all zero. +**/ +BOOLEAN +IsZeroBuffer ( + IN VOID *Buffer, + IN UINTN BufferSize + ) +{ + UINT8 *BufferData; + UINTN Index; + + BufferData = Buffer; + for (Index = 0; Index < BufferSize; Index++) { + if (BufferData[Index] != 0) { + return FALSE; + } + } + return TRUE; +} + +/** + Get TPML_DIGEST_VALUES data size. + + @param[in] DigestList TPML_DIGEST_VALUES data. + + @return TPML_DIGEST_VALUES data size. +**/ +UINT32 +GetDigestListSize ( + IN TPML_DIGEST_VALUES *DigestList + ) +{ + UINTN Index; + UINT16 DigestSize; + UINT32 TotalSize; + + TotalSize = sizeof(DigestList->count); + for (Index = 0; Index < DigestList->count; Index++) { + DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg); + TotalSize += sizeof(DigestList->digests[Index].hashAlg) + DigestSize; + } + + return TotalSize; +} + +/** + Return if hash alg is supported in TPM PCR bank. + + @param HashAlg Hash algorithm to be checked. + + @retval TRUE Hash algorithm is supported. + @retval FALSE Hash algorithm is not supported. +**/ +BOOLEAN +IsHashAlgSupportedInPcrBank ( + IN TPMI_ALG_HASH HashAlg + ) +{ + UINT32 ActivePcrBanks; + + ActivePcrBanks = PcdGet32 (PcdTpm2HashMask); + switch (HashAlg) { + case TPM_ALG_SHA1: + if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) { + return TRUE; + } + break; + case TPM_ALG_SHA256: + if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) { + return TRUE; + } + break; + case TPM_ALG_SHA384: + if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) { + return TRUE; + } + break; + case TPM_ALG_SHA512: + if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) { + return TRUE; + } + break; + case TPM_ALG_SM3_256: + if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) { + return TRUE; + } + break; + } + + return FALSE; +} + +/** + Copy TPML_DIGEST_VALUES into a buffer + + @param[in,out] Buffer Buffer to hold TPML_DIGEST_VALUES. + @param[in] DigestList TPML_DIGEST_VALUES to be copied. + + @return The end of buffer to hold TPML_DIGEST_VALUES. +**/ +VOID * +CopyDigestListToBuffer ( + IN OUT VOID *Buffer, + IN TPML_DIGEST_VALUES *DigestList + ) +{ + UINTN Index; + UINT16 DigestSize; + + CopyMem (Buffer, &DigestList->count, sizeof(DigestList->count)); + Buffer = (UINT8 *)Buffer + sizeof(DigestList->count); + for (Index = 0; Index < DigestList->count; Index++) { + if (!IsHashAlgSupportedInPcrBank (DigestList->digests[Index].hashAlg)) { + DEBUG ((EFI_D_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg)); + continue; + } + CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof(DigestList->digests[Index].hashAlg)); + Buffer = (UINT8 *)Buffer + sizeof(DigestList->digests[Index].hashAlg); + DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg); + CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize); + Buffer = (UINT8 *)Buffer + DigestSize; + } + + return Buffer; +} + +/** + Set Tpm2HashMask PCD value accroding to TPM2 PCR bank. +**/ +VOID +SetTpm2HashMask ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 ActivePcrBanks; + TPML_PCR_SELECTION Pcrs; + UINTN Index; + + DEBUG ((EFI_D_ERROR, "SetTpm2HashMask!\n")); + + Status = Tpm2GetCapabilityPcrs (&Pcrs); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n")); + ActivePcrBanks = EFI_TCG2_BOOT_HASH_ALG_SHA1; + } else { + DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count)); + ActivePcrBanks = 0; + for (Index = 0; Index < Pcrs.count; Index++) { + DEBUG ((EFI_D_INFO, "hash - %x\n", Pcrs.pcrSelections[Index].hash)); + switch (Pcrs.pcrSelections[Index].hash) { + case TPM_ALG_SHA1: + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA1; + } + break; + case TPM_ALG_SHA256: + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA256; + } + break; + case TPM_ALG_SHA384: + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA384; + } + break; + case TPM_ALG_SHA512: + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA512; + } + break; + case TPM_ALG_SM3_256: + if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { + ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SM3_256; + } + break; + } + } + } + PcdSet32 (PcdTpm2HashMask, ActivePcrBanks); +} + +/** + Add a new entry to the Event Log. + + @param[in] DigestList A list of digest. + @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. + @param[in] NewEventData Pointer to the new event data. + + @retval EFI_SUCCESS The new event log entry was added. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. +**/ +EFI_STATUS +LogHashEvent ( + IN TPML_DIGEST_VALUES *DigestList, + IN OUT TCG_PCR_EVENT_HDR *NewEventHdr, + IN UINT8 *NewEventData + ) +{ + VOID *HobData; + EFI_STATUS Status; + UINTN Index; + EFI_STATUS RetStatus; + UINT32 SupportedEventLogs; + TCG_PCR_EVENT2 *TcgPcrEvent2; + UINT8 *DigestBuffer; + + SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; + + RetStatus = EFI_SUCCESS; + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { + if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { + DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat)); + switch (mTcg2EventInfo[Index].LogFormat) { + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2: + Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest); + if (!EFI_ERROR (Status)) { + HobData = BuildGuidHob ( + &gTcgEventEntryHobGuid, + sizeof (*NewEventHdr) + NewEventHdr->EventSize + ); + if (HobData == NULL) { + RetStatus = EFI_OUT_OF_RESOURCES; + break; + } + + CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr)); + HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr)); + CopyMem (HobData, NewEventData, NewEventHdr->EventSize); + } + break; + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2: + HobData = BuildGuidHob ( + &gTcgEvent2EntryHobGuid, + sizeof(TcgPcrEvent2->PCRIndex) + sizeof(TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2->EventSize) + NewEventHdr->EventSize + ); + if (HobData == NULL) { + RetStatus = EFI_OUT_OF_RESOURCES; + break; + } + + TcgPcrEvent2 = HobData; + TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex; + TcgPcrEvent2->EventType = NewEventHdr->EventType; + DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest; + DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList); + CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(TcgPcrEvent2->EventSize)); + DigestBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize); + CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize); + break; + } + } + } + + return RetStatus; +} + +/** + Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result, + and build a GUIDed HOB recording the event which will be passed to the DXE phase and + added into the Event Log. + + @param[in] Flags Bitmap providing additional information. + @param[in] HashData Physical address of the start of the data buffer + to be hashed, extended, and logged. + @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData. + @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. + @param[in] NewEventData Pointer to the new event data. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + +**/ +EFI_STATUS +HashLogExtendEvent ( + IN UINT64 Flags, + IN UINT8 *HashData, + IN UINTN HashDataLen, + IN TCG_PCR_EVENT_HDR *NewEventHdr, + IN UINT8 *NewEventData + ) +{ + EFI_STATUS Status; + TPML_DIGEST_VALUES DigestList; + + if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { + return EFI_DEVICE_ERROR; + } + + Status = HashAndExtend ( + NewEventHdr->PCRIndex, + HashData, + HashDataLen, + &DigestList + ); + if (!EFI_ERROR (Status)) { + if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) { + Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData); + } + } + + if (Status == EFI_DEVICE_ERROR) { + DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status)); + BuildGuidHob (&gTpmErrorHobGuid,0); + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) + ); + } + + return Status; +} + +/** + Measure CRTM version. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + +**/ +EFI_STATUS +MeasureCRTMVersion ( + VOID + ) +{ + TCG_PCR_EVENT_HDR TcgEventHdr; + + // + // Use FirmwareVersion string to represent CRTM version. + // OEMs should get real CRTM version string and measure it. + // + + TcgEventHdr.PCRIndex = 0; + TcgEventHdr.EventType = EV_S_CRTM_VERSION; + TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString)); + + return HashLogExtendEvent ( + 0, + (UINT8*)PcdGetPtr (PcdFirmwareVersionString), + TcgEventHdr.EventSize, + &TcgEventHdr, + (UINT8*)PcdGetPtr (PcdFirmwareVersionString) + ); +} + +/** + Measure FV image. + Add it into the measured FV list after the FV is measured successfully. + + @param[in] FvBase Base address of FV image. + @param[in] FvLength Length of FV image. + + @retval EFI_SUCCESS Fv image is measured successfully + or it has been already measured. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + +**/ +EFI_STATUS +MeasureFvImage ( + IN EFI_PHYSICAL_ADDRESS FvBase, + IN UINT64 FvLength + ) +{ + UINT32 Index; + EFI_STATUS Status; + EFI_PLATFORM_FIRMWARE_BLOB FvBlob; + TCG_PCR_EVENT_HDR TcgEventHdr; + + // + // Check if it is in Excluded FV list + // + if (mMeasurementExcludedFvPpi != NULL) { + for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) { + if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) { + DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase)); + DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength)); + return EFI_SUCCESS; + } + } + } + + // + // Check whether FV is in the measured FV list. + // + for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) { + if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) { + return EFI_SUCCESS; + } + } + + // + // Measure and record the FV to the TPM + // + FvBlob.BlobBase = FvBase; + FvBlob.BlobLength = FvLength; + + DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase)); + DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength)); + + TcgEventHdr.PCRIndex = 0; + TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB; + TcgEventHdr.EventSize = sizeof (FvBlob); + + Status = HashLogExtendEvent ( + 0, + (UINT8*) (UINTN) FvBlob.BlobBase, + (UINTN) FvBlob.BlobLength, + &TcgEventHdr, + (UINT8*) &FvBlob + ); + + // + // Add new FV into the measured FV list. + // + ASSERT (mMeasuredBaseFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)); + if (mMeasuredBaseFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) { + mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase; + mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength; + mMeasuredBaseFvIndex++; + } + + return Status; +} + +/** + Measure main BIOS. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + +**/ +EFI_STATUS +MeasureMainBios ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 FvInstances; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_FV_INFO VolumeInfo; + EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; + + PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI); + FvInstances = 0; + while (TRUE) { + // + // Traverse all firmware volume instances of Static Core Root of Trust for Measurement + // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special + // platform for special CRTM TPM measuring. + // + Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle); + if (EFI_ERROR (Status)) { + break; + } + + // + // Measure and record the firmware volume that is dispatched by PeiCore + // + Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo); + ASSERT_EFI_ERROR (Status); + // + // Locate the corresponding FV_PPI according to founded FV's format guid + // + Status = PeiServicesLocatePpi ( + &VolumeInfo.FvFormat, + 0, + NULL, + (VOID**)&FvPpi + ); + if (!EFI_ERROR (Status)) { + MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize); + } + + FvInstances++; + } + PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1); + + return EFI_SUCCESS; +} + +/** + Measure and record the Firmware Volum Information once FvInfoPPI install. + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param[in] NotifyDescriptor Address of the notification descriptor data structure. + @param[in] Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS The FV Info is measured and recorded to TPM. + @return Others Fail to measure FV. + +**/ +EFI_STATUS +EFIAPI +FirmwareVolmeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv; + EFI_STATUS Status; + EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; + UINTN Index; + + Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi; + + // + // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi. + // + Status = PeiServicesLocatePpi ( + &Fv->FvFormat, + 0, + NULL, + (VOID**)&FvPpi + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // This is an FV from an FFS file, and the parent FV must have already been measured, + // No need to measure twice, so just record the FV and return + // + if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) { + + ASSERT (mMeasuredChildFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)); + if (mMeasuredChildFvIndex < FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) { + // + // Check whether FV is in the measured child FV list. + // + for (Index = 0; Index < mMeasuredChildFvIndex; Index++) { + if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) { + return EFI_SUCCESS; + } + } + mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo; + mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize; + mMeasuredChildFvIndex++; + } + return EFI_SUCCESS; + } + + return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize); +} + +/** + Do measurement after memory is ready. + + @param[in] PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + +**/ +EFI_STATUS +PeimEntryMP ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + Status = PeiServicesLocatePpi ( + &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, + 0, + NULL, + (VOID**)&mMeasurementExcludedFvPpi + ); + // Do not check status, because it is optional + + mMeasuredBaseFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported)); + ASSERT (mMeasuredBaseFvInfo != NULL); + mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported)); + ASSERT (mMeasuredChildFvInfo != NULL); + + if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) { + Status = MeasureCRTMVersion (); + } + + Status = MeasureMainBios (); + + // + // Post callbacks: + // for the FvInfoPpi services to measure and record + // the additional Fvs to TPM + // + Status = PeiServicesNotifyPpi (&mNotifyList[0]); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Entry point of this module. + + @param[in] FileHandle Handle of the file being invoked. + @param[in] PeiServices Describes the list of possible PEI Services. + + @return Status. + +**/ +EFI_STATUS +EFIAPI +PeimEntryMA ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_STATUS Status2; + EFI_BOOT_MODE BootMode; + + if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) || + CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ + DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n")); + return EFI_UNSUPPORTED; + } + + if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { + DEBUG ((EFI_D_ERROR, "TPM2 error!\n")); + return EFI_DEVICE_ERROR; + } + + Status = PeiServicesGetBootMode (&BootMode); + ASSERT_EFI_ERROR (Status); + + // + // In S3 path, skip shadow logic. no measurement is required + // + if (BootMode != BOOT_ON_S3_RESUME) { + Status = (**PeiServices).RegisterForShadow(FileHandle); + if (Status == EFI_ALREADY_STARTED) { + mImageInMemory = TRUE; + mFileHandle = FileHandle; + } else if (Status == EFI_NOT_FOUND) { + ASSERT_EFI_ERROR (Status); + } + } + + if (!mImageInMemory) { + // + // Initialize TPM device + // + Status = Tpm2RequestUseTpm (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n")); + goto Done; + } + + if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) { + if (BootMode == BOOT_ON_S3_RESUME) { + Status = Tpm2Startup (TPM_SU_STATE); + if (EFI_ERROR (Status) ) { + Status = Tpm2Startup (TPM_SU_CLEAR); + } + } else { + Status = Tpm2Startup (TPM_SU_CLEAR); + } + if (EFI_ERROR (Status) ) { + goto Done; + } + } + + // + // Update Tpm2HashMask according to PCR bank. + // + SetTpm2HashMask (); + // + // TpmSelfTest is optional on S3 path, skip it to save S3 time + // + if (BootMode != BOOT_ON_S3_RESUME) { + if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) { + Status = Tpm2SelfTest (NO); + if (EFI_ERROR (Status)) { + goto Done; + } + } + } + + // + // Only intall TpmInitializedPpi on success + // + Status = PeiServicesInstallPpi (&mTpmInitializedPpiList); + ASSERT_EFI_ERROR (Status); + } + + if (mImageInMemory) { + Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices); + return Status; + } + +Done: + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n")); + BuildGuidHob (&gTpmErrorHobGuid,0); + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) + ); + } + // + // Always intall TpmInitializationDonePpi no matter success or fail. + // Other driver can know TPM initialization state by TpmInitializedPpi. + // + Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList); + ASSERT_EFI_ERROR (Status2); + + return Status; +} diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf new file mode 100644 index 0000000000..29ca3aa918 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf @@ -0,0 +1,89 @@ +## @file +# Initializes TPM 2.0 device and measure FVs in PEI phase +# +# This module will initialize TPM device, measure reported FVs and BIOS version. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2Pei + MODULE_UNI_FILE = Tcg2Pei.uni + FILE_GUID = A0C98B77-CBA5-4BB8-993B-4AF6CE33ECE4 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = PeimEntryMA + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# [BootMode] +# S3_RESUME ## SOMETIMES_CONSUMES +# + +[Sources] + Tcg2Pei.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + HobLib + PeimEntryPoint + PeiServicesLib + BaseMemoryLib + DebugLib + Tpm2CommandLib + PeiServicesTablePointerLib + Tpm2DeviceLib + HashLib + PerformanceLib + MemoryAllocationLib + ReportStatusCodeLib + Tcg2PhysicalPresenceLib + +[Guids] + gTcgEventEntryHobGuid ## PRODUCES ## HOB + gTpmErrorHobGuid ## SOMETIMES_PRODUCES ## HOB + gMeasuredFvHobGuid ## PRODUCES ## HOB + gTcgEvent2EntryHobGuid ## PRODUCES ## HOB + gEfiTpmDeviceInstanceNoneGuid ## SOMETIMES_PRODUCES ## GUID # TPM device identifier + gEfiTpmDeviceInstanceTpm12Guid ## SOMETIMES_PRODUCES ## GUID # TPM device identifier + +[Ppis] + gEfiPeiFirmwareVolumeInfoPpiGuid ## SOMETIMES_CONSUMES ## NOTIFY + gEfiPeiFirmwareVolumeInfo2PpiGuid ## SOMETIMES_CONSUMES ## NOTIFY + gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid ## SOMETIMES_CONSUMES + gPeiTpmInitializedPpiGuid ## SOMETIMES_PRODUCES + gPeiTpmInitializationDonePpiGuid ## PRODUCES + gEfiEndOfPeiSignalPpiGuid ## SOMETIMES_CONSUMES ## NOTIFY + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString ## SOMETIMES_CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2InitializationPolicy ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2SelfTestPolicy ## SOMETIMES_CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2ScrtmPolicy ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxFvSupported ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeSubClassTpmDevice ## SOMETIMES_CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask ## CONSUMES + +[Depex] + gEfiPeiMasterBootModePpiGuid AND + gEfiPeiReadOnlyVariable2PpiGuid AND + gEfiTpmDeviceSelectedGuid + +[UserExtensions.TianoCore."ExtraFiles"] + Tcg2PeiExtra.uni diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.uni b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.uni new file mode 100644 index 0000000000000000000000000000000000000000..5a226bcce44e032b47c42e32c8952a06f43d27b9 GIT binary patch literal 1876 zcmd6o-ER_65XI-&#Q$MKU(~dqO?)xN2(ne87Q%hH{DS!gl( zVq(bMyLV>pxo6JIU4H(kSj8g76Mm7swku2Q#xCulJ-{ko!=~64j6R;kzT?fXcdca~ znNO{3Pnk#9SNMm_5wTM&kxf|jiCAP&F$KwigSzeyZ92{GqD+% zOXnBaE!G=;5%Yb91;1Th#|IdR*Bs=O950=7&N0uS2FIp#*t;Skg-b&Gl)Q76`5f6B zJabzUmDm{O3wAw1lgG@b==9892+tY5x%<|x>zK$1YjG6|^+2{gM<}7L>I_wW z>daL69ACRt16fuKRjqFWp0X|3A#cii&Lo^Q0jWR{Gew3@)VsVh`nA|sqegYsANIHu zwYl|98uAqGezpl5geVT7+jLgOT3HX^sT+{jMXHMZm3O0RD9+z_-sQBfOVDyn)L^rJ zwoyQg7CXACa~4$Mh2KK;RM1xOsViNEO-em0D7mYBhGhWrk)7P}ltH;>6pD219XC+- zuuX@*Fv1w`b?fF?QXufKX`Ppr2zRI*#1rO?|9qiMhip z)Dm;e*IFI#aJs-R)TW;p*#%K;XLgRg0je;XetMggxXY$9yTmF+r-rCAVs-i#=J$BS zT=!4koxojL#P)fMQ=m7{qD439%=*FGuCHdrxl2=xqixSjsZ9h6>Gu_+CKx@?Vpdgh z51uM&b&31k@5pb9u$FYl*tzCpAH{a*dHrv0;RDIGRNA*w(PN6o3 Qvi)oF{84{J+KYSB> zH@3E%^@7M1>mio>=fp19oBCK{mUGx&+Q!e$?19M0jzNFN+_Vq&(LUJ;c2c0s3(VY> zAm`*+lT|tD?3}?#5n>Y1#3d*DihpiT&bDq}tYtm>y1iq?rw@nJZ?Ggj14TI=K`C#v zCSvOAF+4N&mcF+sZXe+hE9FbE=Ac#hL%cdI?Z#LOXC|dee4U;Y8J@6JjiHSgb?y%* zw3}m>OhT?lXI-L*nIhAzK2jp1y4ATBRl8t)wa2C6`s`Ya8O3h@wkaHhC=Nj{0u+?B3# z`!Rv`_d(Vj^xFxr3!X)>vZ}u25^tEnjPOvcu_?eW7+dV`R5P^_*E7e*&s7 zI-b49O5EjB&OWhQ>H? zzcCH>%XhTx7rh#KL!{kZp>7wH-u4D}V0S +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Tcg2Smm.h" + +EFI_TPM2_ACPI_TABLE mTpm2AcpiTemplate = { + { + EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE, + sizeof (mTpm2AcpiTemplate), + EFI_TPM2_ACPI_TABLE_REVISION, + // + // Compiler initializes the remaining bytes to 0 + // These fields should be filled in in production + // + }, + 0, // Flags + 0, // Control Area + EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod +}; + +EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable; +TCG_NVS *mTcgNvs; + +/** + Software SMI callback for TPM physical presence which is called from ACPI method. + + Caution: This function may receive untrusted input. + Variable and ACPINvs are external input, so this function will validate + its data structure to be valid value. + + @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param[in] Context Points to an optional handler context which was specified when the + handler was registered. + @param[in, out] CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param[in, out] CommBufferSize The size of the CommBuffer. + + @retval EFI_SUCCESS The interrupt was handled successfully. + +**/ +EFI_STATUS +EFIAPI +PhysicalPresenceCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommBufferSize + ) +{ + UINT32 MostRecentRequest; + UINT32 Response; + + if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) { + mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction ( + &MostRecentRequest, + &Response + ); + mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest; + mTcgNvs->PhysicalPresence.Response = Response; + return EFI_SUCCESS; + } else if ((mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS) + || (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) { + mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction ( + mTcgNvs->PhysicalPresence.Request, + mTcgNvs->PhysicalPresence.RequestParameter + ); + } else if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) { + mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PhysicalPresence.Request); + } + + return EFI_SUCCESS; +} + + +/** + Software SMI callback for MemoryClear which is called from ACPI method. + + Caution: This function may receive untrusted input. + Variable and ACPINvs are external input, so this function will validate + its data structure to be valid value. + + @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param[in] Context Points to an optional handler context which was specified when the + handler was registered. + @param[in, out] CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param[in, out] CommBufferSize The size of the CommBuffer. + + @retval EFI_SUCCESS The interrupt was handled successfully. + +**/ +EFI_STATUS +EFIAPI +MemoryClearCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommBufferSize + ) +{ + EFI_STATUS Status; + UINTN DataSize; + UINT8 MorControl; + + mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS; + if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) { + MorControl = (UINT8) mTcgNvs->MemoryClear.Request; + } else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) { + DataSize = sizeof (UINT8); + Status = mSmmVariable->SmmGetVariable ( + MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, + &gEfiMemoryOverwriteControlDataGuid, + NULL, + &DataSize, + &MorControl + ); + if (EFI_ERROR (Status)) { + mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE; + DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status)); + return EFI_SUCCESS; + } + + if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) { + return EFI_SUCCESS; + } + MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK; + } + + DataSize = sizeof (UINT8); + Status = mSmmVariable->SmmSetVariable ( + MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, + &gEfiMemoryOverwriteControlDataGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, + &MorControl + ); + if (EFI_ERROR (Status)) { + mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE; + DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status)); + } + + return EFI_SUCCESS; +} + +/** + Find the operation region in TCG ACPI table by given Name and Size, + and initialize it if the region is found. + + @param[in, out] Table The TPM item in ACPI table. + @param[in] Name The name string to find in TPM table. + @param[in] Size The size of the region to find. + + @return The allocated address for the found region. + +**/ +VOID * +AssignOpRegion ( + EFI_ACPI_DESCRIPTION_HEADER *Table, + UINT32 Name, + UINT16 Size + ) +{ + EFI_STATUS Status; + AML_OP_REGION_32_8 *OpRegion; + EFI_PHYSICAL_ADDRESS MemoryAddress; + + MemoryAddress = SIZE_4GB - 1; + + // + // Patch some pointers for the ASL code before loading the SSDT. + // + for (OpRegion = (AML_OP_REGION_32_8 *) (Table + 1); + OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length); + OpRegion = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) { + if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) && + (OpRegion->NameString == Name) && + (OpRegion->DWordPrefix == AML_DWORD_PREFIX) && + (OpRegion->BytePrefix == AML_BYTE_PREFIX)) { + + Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress); + ASSERT_EFI_ERROR (Status); + ZeroMem ((VOID *)(UINTN)MemoryAddress, Size); + OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress; + OpRegion->RegionLen = (UINT8) Size; + break; + } + } + + return (VOID *) (UINTN) MemoryAddress; +} + +/** + Initialize and publish TPM items in ACPI table. + + @retval EFI_SUCCESS The TCG ACPI table is published successfully. + @retval Others The TCG ACPI table is not published. + +**/ +EFI_STATUS +PublishAcpiTable ( + VOID + ) +{ + EFI_STATUS Status; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + UINTN TableKey; + EFI_ACPI_DESCRIPTION_HEADER *Table; + UINTN TableSize; + + Status = GetSectionFromFv ( + &gEfiCallerIdGuid, + EFI_SECTION_RAW, + 0, + (VOID **) &Table, + &TableSize + ); + ASSERT_EFI_ERROR (Status); + + + // + // Measure to PCR[0] with event EV_POST_CODE ACPI DATA + // + TpmMeasureAndLogData( + 0, + EV_POST_CODE, + EV_POSTCODE_INFO_ACPI_DATA, + ACPI_DATA_LEN, + Table, + TableSize + ); + + + ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l')); + CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) ); + mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS)); + ASSERT (mTcgNvs != NULL); + + // + // Publish the TPM ACPI table + // + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); + ASSERT_EFI_ERROR (Status); + + TableKey = 0; + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + Table, + TableSize, + &TableKey + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Publish TPM2 ACPI table + + @retval EFI_SUCCESS The TPM2 ACPI table is published successfully. + @retval Others The TPM2 ACPI table is not published. + +**/ +EFI_STATUS +PublishTpm2 ( + VOID + ) +{ + EFI_STATUS Status; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + UINTN TableKey; + UINT64 OemTableId; + + // + // Measure to PCR[0] with event EV_POST_CODE ACPI DATA + // + TpmMeasureAndLogData( + 0, + EV_POST_CODE, + EV_POSTCODE_INFO_ACPI_DATA, + ACPI_DATA_LEN, + &mTpm2AcpiTemplate, + sizeof(mTpm2AcpiTemplate) + ); + + CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId)); + OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId); + CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64)); + mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); + mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); + mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); + + // + // Construct ACPI table + // + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); + ASSERT_EFI_ERROR (Status); + + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + &mTpm2AcpiTemplate, + sizeof(mTpm2AcpiTemplate), + &TableKey + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + The driver's entry point. + + It install callbacks for TPM physical presence and MemoryClear, and locate + SMM variable to be used in the callback function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval Others Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeTcgSmm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch; + EFI_SMM_SW_REGISTER_CONTEXT SwContext; + EFI_HANDLE SwHandle; + + if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){ + DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n")); + return EFI_UNSUPPORTED; + } + + Status = PublishAcpiTable (); + ASSERT_EFI_ERROR (Status); + + // + // Get the Sw dispatch protocol and register SMI callback functions. + // + Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch); + ASSERT_EFI_ERROR (Status); + SwContext.SwSmiInputValue = (UINTN) -1; + Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue; + + SwContext.SwSmiInputValue = (UINTN) -1; + Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue; + + // + // Locate SmmVariableProtocol. + // + Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable); + ASSERT_EFI_ERROR (Status); + + // + // Set TPM2 ACPI table + // + Status = PublishTpm2 (); + ASSERT_EFI_ERROR (Status); + + + return EFI_SUCCESS; +} + diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h new file mode 100644 index 0000000000..ebd71edb77 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h @@ -0,0 +1,87 @@ +/** @file + The header file for Tcg2 SMM driver. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TCG2_SMM_H__ +#define __TCG2_SMM_H__ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(1) +typedef struct { + UINT8 SoftwareSmi; + UINT32 Parameter; + UINT32 Response; + UINT32 Request; + UINT32 RequestParameter; + UINT32 LastRequest; + UINT32 ReturnCode; +} PHYSICAL_PRESENCE_NVS; + +typedef struct { + UINT8 SoftwareSmi; + UINT32 Parameter; + UINT32 Request; + UINT32 ReturnCode; +} MEMORY_CLEAR_NVS; + +typedef struct { + PHYSICAL_PRESENCE_NVS PhysicalPresence; + MEMORY_CLEAR_NVS MemoryClear; +} TCG_NVS; + +typedef struct { + UINT8 OpRegionOp; + UINT32 NameString; + UINT8 RegionSpace; + UINT8 DWordPrefix; + UINT32 RegionOffset; + UINT8 BytePrefix; + UINT8 RegionLen; +} AML_OP_REGION_32_8; +#pragma pack() + +// +// The definition for TCG MOR +// +#define ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE 1 +#define ACPI_FUNCTION_PTS_CLEAR_MOR_BIT 2 + +// +// The return code for Memory Clear Interface Functions +// +#define MOR_REQUEST_SUCCESS 0 +#define MOR_REQUEST_GENERAL_FAILURE 1 + +#endif // __TCG_SMM_H__ diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf new file mode 100644 index 0000000000..ef30ec79e0 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf @@ -0,0 +1,80 @@ +## @file +# Provides ACPI metholds for TPM 2.0 support +# +# This driver implements TPM 2.0 definition block in ACPI table and +# registers SMI callback functions for Tcg2 physical presence and +# MemoryClear to handle the requests from ACPI method. +# +# Caution: This module requires additional review when modified. +# This driver will have external input - variable and ACPINvs data in SMM mode. +# This external input must be validated carefully to avoid security issue. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2Smm + MODULE_UNI_FILE = Tcg2Smm.uni + FILE_GUID = 44A20657-10B8-4049-A148-ACD8812AF257 + MODULE_TYPE = DXE_SMM_DRIVER + PI_SPECIFICATION_VERSION = 0x0001000A + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeTcgSmm + +[Sources] + Tcg2Smm.h + Tcg2Smm.c + Tpm.asl + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + UefiDriverEntryPoint + SmmServicesTableLib + UefiBootServicesTableLib + DebugLib + DxeServicesLib + TpmMeasurementLib + Tpm2DeviceLib + Tcg2PhysicalPresenceLib + +[Guids] + ## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControl" + ## SOMETIMES_CONSUMES ## Variable:L"MemoryOverwriteRequestControl" + gEfiMemoryOverwriteControlDataGuid + + gEfiTpmDeviceInstanceTpm20DtpmGuid ## PRODUCES ## GUID # TPM device identifier + +[Protocols] + gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES + gEfiSmmVariableProtocolGuid ## CONSUMES + gEfiAcpiTableProtocolGuid ## CONSUMES + +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## SOMETIMES_CONSUMES + +[Depex] + gEfiAcpiTableProtocolGuid AND + gEfiSmmSwDispatch2ProtocolGuid AND + gEfiSmmVariableProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + Tcg2SmmExtra.uni diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.uni b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.uni new file mode 100644 index 0000000000000000000000000000000000000000..3d9dcac18aa836c653dd9d5ca377d152a0b418b4 GIT binary patch literal 3270 zcmd6pQEw7K6ov1ziT`0kU(~dqO?+vLv8AX)TL`78CMFGZm$DI9gr$`~uYPBy%Pgc- zAJm%7GP`%~+R6jR zjj`l5WPZe~<_0{^7`u2JG45K`o-)pDVN)*6=Bwx-OP46AixA_Hk}q*_QgTckBITN} zR#`Tq3z?8lxO47|r^x!O%k08F^Q^ft^4xlEKEc{!E?!}Z$eY+DE9S%!3S~T@8dZFO z_lT>{=pzrPY{GMqcb$d0y@7*>8iuwcQhF0X7Uh|9YxQk7j_ayy<`)ntvgc~Rnv6K*>OR*hH6jJC$-Itm@*5nS1KSwYIiFzVk3a`+NK;v_%a<4A&DNU)q zB{tvf9{!p0)?P|b%)-@@J0EFPJFJYX+{+9emd^hY-i6^25gs${vOAyIbKB;*314DR z+||i8W0iizh2K+EX7(L2^)qFcD4G~6v^)c+@8SzPu#UZ4sVm?KUDY1Qh@u=)s8@7Q zv-a2p9y$Xww11cne_T^7S)S37IMtmn6guhlv;lu><&-yuV+=60m9?2;~r;&1$t*6j2z8v(cYQs=80V z%Y6~6s;JP8)_Fy4Vp`|Lb19{HUFrn)3odXP@MK&6DA|L)Y!$^L|>;oH5|XEcFfqo zu9M0~2;4W(a|4eP7rDigbgbVBqv9%Rh4H|>>utM)>5O?rZMlq*o#EAS$d0i$iK-Ya zm%YQAu*;^LU3}%EtlsN2zRLcQ@f|ZluKm}z$>OVM*oRe|5WNW(ZPcWkhoy5U@TY(B zn!_%e?k$+l=}WP9Jb&jzY7ygXMzIH3|LrM>FFZ8iP6o^WEV{}27Uuao=!Dv40bzxf*Zgpz!(Z|l|H gv{g{c{eAV6zp&O-cK=^HWo-Y$SI(T1FPsNI04Ed-AOHXW literal 0 HcmV?d00001 diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2SmmExtra.uni b/SecurityPkg/Tcg/Tcg2Smm/Tcg2SmmExtra.uni new file mode 100644 index 0000000000000000000000000000000000000000..173c4ebb709b4e91f275f14f46549855b7b5e9b4 GIT binary patch literal 1342 zcmZ9MTW`}q5QXO%iT_}wF9o#;MB)V@MAMpL(Oi^^3QtvTO)aHy=g7j^i6wb@9l$~F-{7UWr3O7 z8swZfTcRpPos|nX$wN#6nz-ad-|*-5pH{RC_LGf)&mr!G&l z#bfUCDLgaQ*1q;qoIb)LR*IK0T7p*LkFjdEw3{+oIWs9$;%oP;i15T%*%;e|R{MUj zL#sLCl1Yg5=&VZ=F_UMy(??2VWVhPaB5PO7Zw|OrT%TQwDXrKYo;HPp5XB+rrC1y0 zI`sse`+1S7Vt}z-}1R;XM3D(Sr=;8BSvC)iF5AhjUi50{4Uu+tg}OaZ`nwa{f!zgl1b&Q92bOI{k)xfEIaU6GY>#PGYs&vQ u{^F--HLxzpS(EuG;~ZbrYk0r(PU$9xx($4;@lpM({WTg8uMLW@%KtwSch7qO literal 0 HcmV?d00001 diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl b/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl new file mode 100644 index 0000000000..80dfb3bd4e --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl @@ -0,0 +1,359 @@ +/** @file + The TPM2 definition block in ACPI table for TCG2 physical presence + and MemoryClear. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +DefinitionBlock ( + "Tpm.aml", + "SSDT", + 2, + "INTEL ", + "Tpm2Tabl", + 0x1000 + ) +{ + Scope (\_SB) + { + Device (TPM) + { + // + // TCG2 + // + Name (_HID, "MSFT0101") + + // + // Readable name of this device, don't know if this way is correct yet + // + Name (_STR, Unicode ("TPM 2.0 Device")) + + // + // Return the resource consumed by TPM device + // + Name (_CRS, ResourceTemplate () { + Memory32Fixed (ReadOnly, 0xfed40000, 0x5000) + }) + + // + // Operational region for Smi port access + // + OperationRegion (SMIP, SystemIO, 0xB2, 1) + Field (SMIP, ByteAcc, NoLock, Preserve) + { + IOB2, 8 + } + + // + // Operational region for TPM access + // + OperationRegion (TPMR, SystemMemory, 0xfed40000, 0x5000) + Field (TPMR, AnyAcc, NoLock, Preserve) + { + ACC0, 8, + } + + // + // Operational region for TPM support, TPM Physical Presence and TPM Memory Clear + // Region Offset 0xFFFF0000 and Length 0xF0 will be fixed in C code. + // + OperationRegion (TNVS, SystemMemory, 0xFFFF0000, 0xF0) + Field (TNVS, AnyAcc, NoLock, Preserve) + { + PPIN, 8, // Software SMI for Physical Presence Interface + PPIP, 32, // Used for save physical presence paramter + PPRP, 32, // Physical Presence request operation response + PPRQ, 32, // Physical Presence request operation + PPRM, 32, // Physical Presence request operation parameter + LPPR, 32, // Last Physical Presence request operation + FRET, 32, // Physical Presence function return code + MCIN, 8, // Software SMI for Memory Clear Interface + MCIP, 32, // Used for save the Mor paramter + MORD, 32, // Memory Overwrite Request Data + MRET, 32 // Memory Overwrite function return code + } + + Method (PTS, 1, Serialized) + { + // + // Detect Sx state for MOR, only S4, S5 need to handle + // + If (LAnd (LLess (Arg0, 6), LGreater (Arg0, 3))) + { + // + // Bit4 -- DisableAutoDetect. 0 -- Firmware MAY autodetect. + // + If (LNot (And (MORD, 0x10))) + { + // + // Triggle the SMI through ACPI _PTS method. + // + Store (0x02, MCIP) + + // + // Triggle the SMI interrupt + // + Store (MCIN, IOB2) + } + } + Return (0) + } + + Method (_STA, 0) + { + if (LEqual (ACC0, 0xff)) + { + Return (0) + } + Return (0x0f) + } + + // + // TCG Hardware Information + // + Method (HINF, 3, Serialized, 0, {BuffObj, PkgObj}, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj + { + // + // Switch by function index + // + Switch (ToInteger(Arg1)) + { + Case (0) + { + // + // Standard query + // + Return (Buffer () {0x03}) + } + Case (1) + { + // + // Return failure if no TPM present + // + Name(TPMV, Package () {0x01, Package () {0x2, 0x0}}) + if (LEqual (_STA (), 0x00)) + { + Return (Package () {0x00}) + } + + // + // Return TPM version + // + Return (TPMV) + } + Default {BreakPoint} + } + Return (Buffer () {0}) + } + + Name(TPM2, Package (0x02){ + Zero, + Zero + }) + + Name(TPM3, Package (0x03){ + Zero, + Zero, + Zero + }) + + // + // TCG Physical Presence Interface + // + Method (TPPI, 3, Serialized, 0, {BuffObj, PkgObj, IntObj, StrObj}, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj + { + // + // Switch by function index + // + Switch (ToInteger(Arg1)) + { + Case (0) + { + // + // Standard query, supports function 1-8 + // + Return (Buffer () {0xFF, 0x01}) + } + Case (1) + { + // + // a) Get Physical Presence Interface Version + // + Return ("1.2") + } + Case (2) + { + // + // b) Submit TPM Operation Request to Pre-OS Environment + // + + Store (DerefOf (Index (Arg2, 0x00)), PPRQ) + Store (0x02, PPIP) + + // + // Triggle the SMI interrupt + // + Store (PPIN, IOB2) + Return (FRET) + + + } + Case (3) + { + // + // c) Get Pending TPM Operation Requested By the OS + // + + Store (PPRQ, Index (TPM2, 0x01)) + Return (TPM2) + } + Case (4) + { + // + // d) Get Platform-Specific Action to Transition to Pre-OS Environment + // + Return (2) + } + Case (5) + { + // + // e) Return TPM Operation Response to OS Environment + // + Store (0x05, PPIP) + + // + // Triggle the SMI interrupt + // + Store (PPIN, IOB2) + + Store (LPPR, Index (TPM3, 0x01)) + Store (PPRP, Index (TPM3, 0x02)) + + Return (TPM3) + } + Case (6) + { + + // + // f) Submit preferred user language (Not implemented) + // + + Return (3) + + } + Case (7) + { + // + // g) Submit TPM Operation Request to Pre-OS Environment 2 + // + Store (7, PPIP) + Store (DerefOf (Index (Arg2, 0x00)), PPRQ) + Store (0, PPRM) + If (LEqual (PPRQ, 23)) { + Store (DerefOf (Index (Arg2, 0x01)), PPRM) + } + + // + // Triggle the SMI interrupt + // + Store (PPIN, IOB2) + Return (FRET) + } + Case (8) + { + // + // e) Get User Confirmation Status for Operation + // + Store (8, PPIP) + Store (DerefOf (Index (Arg2, 0x00)), PPRQ) + + // + // Triggle the SMI interrupt + // + Store (PPIN, IOB2) + + Return (FRET) + } + + Default {BreakPoint} + } + Return (1) + } + + Method (TMCI, 3, Serialized, 0, IntObj, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj + { + // + // Switch by function index + // + Switch (ToInteger (Arg1)) + { + Case (0) + { + // + // Standard query, supports function 1-1 + // + Return (Buffer () {0x03}) + } + Case (1) + { + // + // Save the Operation Value of the Request to MORD (reserved memory) + // + Store (DerefOf (Index (Arg2, 0x00)), MORD) + + // + // Triggle the SMI through ACPI _DSM method. + // + Store (0x01, MCIP) + + // + // Triggle the SMI interrupt + // + Store (MCIN, IOB2) + Return (MRET) + } + Default {BreakPoint} + } + Return (1) + } + + Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) + { + + // + // TCG Hardware Information + // + If(LEqual(Arg0, ToUUID ("cf8e16a5-c1e8-4e25-b712-4f54a96702c8"))) + { + Return (HINF (Arg1, Arg2, Arg3)) + } + + // + // TCG Physical Presence Interface + // + If(LEqual(Arg0, ToUUID ("3dddfaa6-361b-4eb4-a424-8d10089d1653"))) + { + Return (TPPI (Arg1, Arg2, Arg3)) + } + + // + // TCG Memory Clear Interface + // + If(LEqual(Arg0, ToUUID ("376054ed-cc13-4675-901c-4756d7f2d45d"))) + { + Return (TMCI (Arg1, Arg2, Arg3)) + } + + Return (Buffer () {0}) + } + } + } +} -- 2.39.2