diff options
author | Yao, Jiewen <Jiewen.Yao@intel.com> | 2015-08-13 08:24:17 +0000 |
---|---|---|
committer | jyao1 <jyao1@Edk2> | 2015-08-13 08:24:17 +0000 |
commit | 1abfa4ce4835639c66ae82cc0d72cffcf3f28b6b (patch) | |
tree | 9688e07a23a004cf3cc14d5cbb119fc4f0cd5495 /SecurityPkg/Tcg | |
parent | 59b226d6d7e2b9e6ea8751abb366dd1a7d643a4c (diff) | |
download | edk2-1abfa4ce4835639c66ae82cc0d72cffcf3f28b6b.tar.gz edk2-1abfa4ce4835639c66ae82cc0d72cffcf3f28b6b.tar.bz2 edk2-1abfa4ce4835639c66ae82cc0d72cffcf3f28b6b.zip |
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" <Jiewen.Yao@intel.com>
Reviewed-by: "Zhang, Chao B" <chao.b.zhang@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18219 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'SecurityPkg/Tcg')
29 files changed, 6790 insertions, 0 deletions
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.<BR>
+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.<BR>
+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.<BR>
+# 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 Binary files differnew file mode 100644 index 0000000000..a5b2040b49 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.uni diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxeExtra.uni b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxeExtra.uni Binary files differnew file mode 100644 index 0000000000..c2571d74be --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxeExtra.uni diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c new file mode 100644 index 0000000000..e1835b9613 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c @@ -0,0 +1,610 @@ +/** @file
+ HII Config Access protocol implementation of TCG2 configuration module.
+ NOTE: This module is only for reference only, each platform should have its own setup page.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+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 <Library/PcdLib.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Guid/TpmInstance.h>
+
+#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
+ <ConfigRequest> 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
+ <ConfigAltResp> 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 <ConfigResp>
+ 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.<BR>
+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 <Uefi.h>
+
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/Tcg2Protocol.h>
+#include <Protocol/VariableLock.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HiiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#include <Guid/MdeModuleHii.h>
+
+#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
+ <ConfigRequest> 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
+ <ConfigAltResp> 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 <ConfigResp>
+ 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.<BR>
+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 <Guid/HiiPlatformSetupFormset.h>
+#include <Guid/Tcg2ConfigHii.h>
+#include <IndustryStandard/TcgPhysicalPresence.h>
+
+//
+// BUGBUG: In order to pass VfrCompiler, we have to redefine below MACRO, which already in <Protocol/Tcg2Protocol.h>.
+//
+#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.<BR>
+# 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 Binary files differnew file mode 100644 index 0000000000..c3095564a2 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni Binary files differnew file mode 100644 index 0000000000..c2571d74be --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c new file mode 100644 index 0000000000..34767c0f49 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c @@ -0,0 +1,158 @@ +/** @file
+ The module entry point for Tcg2 configuration module.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+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 <PiPei.h>
+
+#include <Guid/TpmInstance.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/TpmInitialized.h>
+#include <Protocol/Tcg2Protocol.h>
+
+#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 Binary files differnew file mode 100644 index 0000000000..be548b86ff --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni 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.<BR>
+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 <PiPei.h>
+#include <Ppi/ReadOnlyVariable2.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/Tpm12DeviceLib.h>
+#include <Library/Tpm12CommandLib.h>
+#include <IndustryStandard/Tpm12.h>
+
+#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.<BR>
+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 <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/HashLib.h>
+
+/**
+ 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.<BR>
+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 <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/SmBios.h>
+#include <IndustryStandard/TcpaAcpi.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/SmBios.h>
+#include <Guid/HobList.h>
+#include <Guid/TcgEventHob.h>
+#include <Guid/EventGroup.h>
+#include <Guid/EventExitBootServiceFailed.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/TpmInstance.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/MpService.h>
+#include <Protocol/VariableWrite.h>
+#include <Protocol/Tcg2Protocol.h>
+#include <Protocol/TrEEProtocol.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/HobLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/HashLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#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.<BR>
+# 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 Binary files differnew file mode 100644 index 0000000000..8fd8b2a367 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.uni diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2DxeExtra.uni b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2DxeExtra.uni Binary files differnew file mode 100644 index 0000000000..dbc52510eb --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2DxeExtra.uni 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.<BR>
+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 <PiPei.h>
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Ppi/FirmwareVolumeInfo2.h>
+#include <Ppi/LockPhysicalPresence.h>
+#include <Ppi/TpmInitialized.h>
+#include <Ppi/FirmwareVolume.h>
+#include <Ppi/EndOfPeiPhase.h>
+#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
+
+#include <Guid/TcgEventHob.h>
+#include <Guid/MeasuredFvHob.h>
+#include <Guid/TpmInstance.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/HashLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Protocol/Tcg2Protocol.h>
+#include <Library/PerformanceLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#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.<BR>
+# 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 Binary files differnew file mode 100644 index 0000000000..5a226bcce4 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.uni diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2PeiExtra.uni b/SecurityPkg/Tcg/Tcg2Pei/Tcg2PeiExtra.uni Binary files differnew file mode 100644 index 0000000000..426fc77392 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2PeiExtra.uni diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c new file mode 100644 index 0000000000..503cc18dd9 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c @@ -0,0 +1,397 @@ +/** @file
+ It updates TPM2 items in ACPI table and registers SMI2 callback
+ functions for Tcg2 physical presence, ClearMemory, and sample
+ for dTPM StartMethod.
+
+ 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.
+
+ PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+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.<BR>
+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 <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Tpm2Acpi.h>
+
+#include <Guid/MemoryOverwriteControl.h>
+#include <Guid/TpmInstance.h>
+
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/SmmVariable.h>
+#include <Protocol/Tcg2Protocol.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/TpmMeasurementLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#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.<BR>
+# 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 Binary files differnew file mode 100644 index 0000000000..3d9dcac18a --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.uni diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2SmmExtra.uni b/SecurityPkg/Tcg/Tcg2Smm/Tcg2SmmExtra.uni Binary files differnew file mode 100644 index 0000000000..173c4ebb70 --- /dev/null +++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2SmmExtra.uni 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.<BR>
+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})
+ }
+ }
+ }
+}
|