aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/SecurityPkg/Library/Tpm2CommandLib
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/SecurityPkg/Library/Tpm2CommandLib')
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c889
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf50
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.uni16
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Context.c80
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c213
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c396
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c344
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c797
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c689
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c116
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c1042
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Object.c379
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c512
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Session.c168
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c121
-rw-r--r--roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Test.c60
16 files changed, 5872 insertions, 0 deletions
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c
new file mode 100644
index 000000000..17c0c3a15
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c
@@ -0,0 +1,889 @@
+/** @file
+ Implement TPM2 Capability related command.
+
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPM_CAP Capability;
+ UINT32 Property;
+ UINT32 PropertyCount;
+} TPM2_GET_CAPABILITY_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ TPMI_YES_NO MoreData;
+ TPMS_CAPABILITY_DATA CapabilityData;
+} TPM2_GET_CAPABILITY_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMT_PUBLIC_PARMS Parameters;
+} TPM2_TEST_PARMS_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+} TPM2_TEST_PARMS_RESPONSE;
+
+#pragma pack()
+
+#define TPMA_CC_COMMANDINDEX_MASK 0x2000FFFF
+
+/**
+ This command returns various information regarding the TPM and its current state.
+
+ The capability parameter determines the category of data returned. The property parameter
+ selects the first value of the selected category to be returned. If there is no property
+ that corresponds to the value of property, the next higher value is returned, if it exists.
+ The moreData parameter will have a value of YES if there are more values of the requested
+ type that were not returned.
+ If no next capability exists, the TPM will return a zero-length list and moreData will have
+ a value of NO.
+
+ NOTE:
+ To simplify this function, leave returned CapabilityData for caller to unpack since there are
+ many capability categories and only few categories will be used in firmware. It means the caller
+ need swap the byte order for the fields in CapabilityData.
+
+ @param[in] Capability Group selection; determines the format of the response.
+ @param[in] Property Further definition of information.
+ @param[in] PropertyCount Number of properties of the indicated type to return.
+ @param[out] MoreData Flag to indicate if there are more values of this type.
+ @param[out] CapabilityData The capability data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapability (
+ IN TPM_CAP Capability,
+ IN UINT32 Property,
+ IN UINT32 PropertyCount,
+ OUT TPMI_YES_NO *MoreData,
+ OUT TPMS_CAPABILITY_DATA *CapabilityData
+ )
+{
+ EFI_STATUS Status;
+ TPM2_GET_CAPABILITY_COMMAND SendBuffer;
+ TPM2_GET_CAPABILITY_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_GetCapability);
+
+ SendBuffer.Capability = SwapBytes32 (Capability);
+ SendBuffer.Property = SwapBytes32 (Property);
+ SendBuffer.PropertyCount = SwapBytes32 (PropertyCount);
+
+ SendBufferSize = (UINT32) sizeof (SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT8)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2GetCapability: Response Code error! 0x%08x\r\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Return the response
+ //
+ *MoreData = RecvBuffer.MoreData;
+ //
+ // Does not unpack all possible property here, the caller should unpack it and note the byte order.
+ //
+ CopyMem (CapabilityData, &RecvBuffer.CapabilityData, RecvBufferSize - sizeof (TPM2_RESPONSE_HEADER) - sizeof (UINT8));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the information of TPM Family.
+
+ This function parse the value got from TPM2_GetCapability and return the Family.
+
+ @param[out] Family The Family of TPM. (a 4-octet character string)
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityFamily (
+ OUT CHAR8 *Family
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_FAMILY_INDICATOR,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ CopyMem (Family, &TpmCap.data.tpmProperties.tpmProperty->value, 4);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the information of TPM manufacture ID.
+
+ This function parse the value got from TPM2_GetCapability and return the TPM manufacture ID.
+
+ @param[out] ManufactureId The manufacture ID of TPM.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityManufactureID (
+ OUT UINT32 *ManufactureId
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_MANUFACTURER,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ *ManufactureId = TpmCap.data.tpmProperties.tpmProperty->value;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the information of TPM FirmwareVersion.
+
+ This function parse the value got from TPM2_GetCapability and return the TPM FirmwareVersion.
+
+ @param[out] FirmwareVersion1 The FirmwareVersion1.
+ @param[out] FirmwareVersion2 The FirmwareVersion2.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityFirmwareVersion (
+ OUT UINT32 *FirmwareVersion1,
+ OUT UINT32 *FirmwareVersion2
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_FIRMWARE_VERSION_1,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ *FirmwareVersion1 = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_FIRMWARE_VERSION_2,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ *FirmwareVersion2 = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the information of the maximum value for commandSize and responseSize in a command.
+
+ This function parse the value got from TPM2_GetCapability and return the max command size and response size
+
+ @param[out] MaxCommandSize The maximum value for commandSize in a command.
+ @param[out] MaxResponseSize The maximum value for responseSize in a command.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityMaxCommandResponseSize (
+ OUT UINT32 *MaxCommandSize,
+ OUT UINT32 *MaxResponseSize
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_MAX_COMMAND_SIZE,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *MaxCommandSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_MAX_RESPONSE_SIZE,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *MaxResponseSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns Returns a list of TPMS_ALG_PROPERTIES. Each entry is an
+ algorithm ID and a set of properties of the algorithm.
+
+ This function parse the value got from TPM2_GetCapability and return the list.
+
+ @param[out] AlgList List of algorithm.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilitySupportedAlg (
+ OUT TPML_ALG_PROPERTY *AlgList
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_ALGS,
+ 1,
+ MAX_CAP_ALGS,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (AlgList, &TpmCap.data.algorithms, sizeof (TPML_ALG_PROPERTY));
+
+ AlgList->count = SwapBytes32 (AlgList->count);
+ if (AlgList->count > MAX_CAP_ALGS) {
+ DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilitySupportedAlg - AlgList->count error %x\n", AlgList->count));
+ return EFI_DEVICE_ERROR;
+ }
+
+ for (Index = 0; Index < AlgList->count; Index++) {
+ AlgList->algProperties[Index].alg = SwapBytes16 (AlgList->algProperties[Index].alg);
+ WriteUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties)));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the information of TPM LockoutCounter.
+
+ This function parse the value got from TPM2_GetCapability and return the LockoutCounter.
+
+ @param[out] LockoutCounter The LockoutCounter of TPM.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityLockoutCounter (
+ OUT UINT32 *LockoutCounter
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_LOCKOUT_COUNTER,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ *LockoutCounter = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the information of TPM LockoutInterval.
+
+ This function parse the value got from TPM2_GetCapability and return the LockoutInterval.
+
+ @param[out] LockoutInterval The LockoutInterval of TPM.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityLockoutInterval (
+ OUT UINT32 *LockoutInterval
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_LOCKOUT_INTERVAL,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ *LockoutInterval = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the information of TPM InputBufferSize.
+
+ This function parse the value got from TPM2_GetCapability and return the InputBufferSize.
+
+ @param[out] InputBufferSize The InputBufferSize of TPM.
+ the maximum size of a parameter (typically, a TPM2B_MAX_BUFFER)
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityInputBufferSize (
+ OUT UINT32 *InputBufferSize
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_INPUT_BUFFER,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ *InputBufferSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the information of TPM PCRs.
+
+ This function parse the value got from TPM2_GetCapability and return the PcrSelection.
+
+ @param[out] Pcrs The Pcr Selection
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityPcrs (
+ OUT TPML_PCR_SELECTION *Pcrs
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+ UINTN Index;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_PCRS,
+ 0,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Pcrs->count = SwapBytes32 (TpmCap.data.assignedPCR.count);
+ if (Pcrs->count > HASH_COUNT) {
+ DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs - Pcrs->count error %x\n", Pcrs->count));
+ return EFI_DEVICE_ERROR;
+ }
+
+ for (Index = 0; Index < Pcrs->count; Index++) {
+ Pcrs->pcrSelections[Index].hash = SwapBytes16 (TpmCap.data.assignedPCR.pcrSelections[Index].hash);
+ Pcrs->pcrSelections[Index].sizeofSelect = TpmCap.data.assignedPCR.pcrSelections[Index].sizeofSelect;
+ if (Pcrs->pcrSelections[Index].sizeofSelect > PCR_SELECT_MAX) {
+ DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs - sizeofSelect error %x\n", Pcrs->pcrSelections[Index].sizeofSelect));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem (Pcrs->pcrSelections[Index].pcrSelect, TpmCap.data.assignedPCR.pcrSelections[Index].pcrSelect, Pcrs->pcrSelections[Index].sizeofSelect);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will query the TPM to determine which hashing algorithms
+ are supported and which PCR banks are currently active.
+
+ @param[out] TpmHashAlgorithmBitmap A bitmask containing the algorithms supported by the TPM.
+ @param[out] ActivePcrBanks A bitmask containing the PCRs currently allocated.
+
+ @retval EFI_SUCCESS TPM was successfully queried and return values can be trusted.
+ @retval Others An error occurred, likely in communication with the TPM.
+
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilitySupportedAndActivePcrs (
+ OUT UINT32 *TpmHashAlgorithmBitmap,
+ OUT UINT32 *ActivePcrBanks
+ )
+{
+ EFI_STATUS Status;
+ TPML_PCR_SELECTION Pcrs;
+ UINTN Index;
+
+ //
+ // Get supported PCR and current Active PCRs.
+ //
+ Status = Tpm2GetCapabilityPcrs (&Pcrs);
+
+ //
+ // If error, assume that we have at least SHA-1 (and return the error.)
+ //
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "GetSupportedAndActivePcrs - Tpm2GetCapabilityPcrs fail!\n"));
+ *TpmHashAlgorithmBitmap = HASH_ALG_SHA1;
+ *ActivePcrBanks = HASH_ALG_SHA1;
+ }
+ //
+ // Otherwise, process the return data to determine what algorithms are supported
+ // and currently allocated.
+ //
+ else {
+ DEBUG ((EFI_D_INFO, "GetSupportedAndActivePcrs - Count = %08x\n", Pcrs.count));
+ *TpmHashAlgorithmBitmap = 0;
+ *ActivePcrBanks = 0;
+ for (Index = 0; Index < Pcrs.count; Index++) {
+ switch (Pcrs.pcrSelections[Index].hash) {
+ case TPM_ALG_SHA1:
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA1 present.\n"));
+ *TpmHashAlgorithmBitmap |= HASH_ALG_SHA1;
+ if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA1 active.\n"));
+ *ActivePcrBanks |= HASH_ALG_SHA1;
+ }
+ break;
+ case TPM_ALG_SHA256:
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA256 present.\n"));
+ *TpmHashAlgorithmBitmap |= HASH_ALG_SHA256;
+ if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA256 active.\n"));
+ *ActivePcrBanks |= HASH_ALG_SHA256;
+ }
+ break;
+ case TPM_ALG_SHA384:
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA384 present.\n"));
+ *TpmHashAlgorithmBitmap |= HASH_ALG_SHA384;
+ if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA384 active.\n"));
+ *ActivePcrBanks |= HASH_ALG_SHA384;
+ }
+ break;
+ case TPM_ALG_SHA512:
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA512 present.\n"));
+ *TpmHashAlgorithmBitmap |= HASH_ALG_SHA512;
+ if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA512 active.\n"));
+ *ActivePcrBanks |= HASH_ALG_SHA512;
+ }
+ break;
+ case TPM_ALG_SM3_256:
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SM3_256 present.\n"));
+ *TpmHashAlgorithmBitmap |= HASH_ALG_SM3_256;
+ if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
+ DEBUG ((EFI_D_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SM3_256 active.\n"));
+ *ActivePcrBanks |= HASH_ALG_SM3_256;
+ }
+ break;
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ This command returns the information of TPM AlgorithmSet.
+
+ This function parse the value got from TPM2_GetCapability and return the AlgorithmSet.
+
+ @param[out] AlgorithmSet The AlgorithmSet of TPM.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityAlgorithmSet (
+ OUT UINT32 *AlgorithmSet
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_ALGORITHM_SET,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ *AlgorithmSet = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will query if the command is supported.
+
+ @param[In] Command TPM_CC command starts from TPM_CC_FIRST.
+ @param[out] IsCmdImpl The command is supported or not.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityIsCommandImplemented (
+ IN TPM_CC Command,
+ OUT BOOLEAN *IsCmdImpl
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+ UINT32 Attribute;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_COMMANDS,
+ Command,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (&Attribute, &TpmCap.data.command.commandAttributes[0], sizeof (UINT32));
+ *IsCmdImpl = (Command == (SwapBytes32(Attribute) & TPMA_CC_COMMANDINDEX_MASK));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command is used to check to see if specific combinations of algorithm parameters are supported.
+
+ @param[in] Parameters Algorithm parameters to be validated
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2TestParms (
+ IN TPMT_PUBLIC_PARMS *Parameters
+ )
+{
+ EFI_STATUS Status;
+ TPM2_TEST_PARMS_COMMAND SendBuffer;
+ TPM2_TEST_PARMS_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_TestParms);
+
+ Buffer = (UINT8 *)&SendBuffer.Parameters;
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->type));
+ Buffer += sizeof(UINT16);
+ switch (Parameters->type) {
+ case TPM_ALG_KEYEDHASH:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.scheme));
+ Buffer += sizeof(UINT16);
+ switch (Parameters->parameters.keyedHashDetail.scheme.scheme) {
+ case TPM_ALG_HMAC:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.hmac.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_XOR:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.hashAlg));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.kdf));
+ Buffer += sizeof(UINT16);
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ case TPM_ALG_SYMCIPHER:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.algorithm));
+ Buffer += sizeof(UINT16);
+ switch (Parameters->parameters.symDetail.algorithm) {
+ case TPM_ALG_AES:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.aes));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.aes));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_SM4:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.SM4));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.SM4));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_XOR:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.xor));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ case TPM_ALG_RSA:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.algorithm));
+ Buffer += sizeof(UINT16);
+ switch (Parameters->parameters.rsaDetail.symmetric.algorithm) {
+ case TPM_ALG_AES:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.aes));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.aes));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_SM4:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.SM4));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.SM4));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.scheme));
+ Buffer += sizeof(UINT16);
+ switch (Parameters->parameters.rsaDetail.scheme.scheme) {
+ case TPM_ALG_RSASSA:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsassa.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_RSAPSS:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsapss.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_RSAES:
+ break;
+ case TPM_ALG_OAEP:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.oaep.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.keyBits));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Parameters->parameters.rsaDetail.exponent));
+ Buffer += sizeof(UINT32);
+ break;
+ case TPM_ALG_ECC:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.algorithm));
+ Buffer += sizeof(UINT16);
+ switch (Parameters->parameters.eccDetail.symmetric.algorithm) {
+ case TPM_ALG_AES:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.aes));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.aes));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_SM4:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.SM4));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.SM4));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.scheme));
+ Buffer += sizeof(UINT16);
+ switch (Parameters->parameters.eccDetail.scheme.scheme) {
+ case TPM_ALG_ECDSA:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdsa.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_ECDAA:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdaa.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_ECSCHNORR:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecSchnorr.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_ECDH:
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.curveID));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.scheme));
+ Buffer += sizeof(UINT16);
+ switch (Parameters->parameters.eccDetail.kdf.scheme) {
+ case TPM_ALG_MGF1:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.mgf1.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_KDF1_SP800_108:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_sp800_108.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_KDF1_SP800_56a:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_SP800_56a.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_KDF2:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf2.hashAlg));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2TestParms - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2TestParms - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
new file mode 100644
index 000000000..f584f34ae
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
@@ -0,0 +1,50 @@
+## @file
+# Provides some TPM 2.0 commands
+#
+# This library is used by other modules to send TPM 2.0 command.
+#
+# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Tpm2CommandLib
+ MODULE_UNI_FILE = Tpm2CommandLib.uni
+ FILE_GUID = 2F572F32-8BE5-4868-BD1D-7438AD97DC27
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = Tpm2CommandLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ Tpm2Capability.c
+ Tpm2Sequences.c
+ Tpm2Integrity.c
+ Tpm2Hierarchy.c
+ Tpm2NVStorage.c
+ Tpm2Startup.c
+ Tpm2Session.c
+ Tpm2Context.c
+ Tpm2EnhancedAuthorization.c
+ Tpm2Test.c
+ Tpm2DictionaryAttack.c
+ Tpm2Object.c
+ Tpm2Miscellaneous.c
+ Tpm2Help.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ Tpm2DeviceLib
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.uni b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.uni
new file mode 100644
index 000000000..2bcd50e77
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Provides some TPM 2.0 commands
+//
+// This library is used by other modules to send TPM 2.0 command.
+//
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Provides some TPM 2.0 command functions"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This library is used by other modules to send TPM 2.0 command."
+
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Context.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Context.c
new file mode 100644
index 000000000..80b15a51f
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Context.c
@@ -0,0 +1,80 @@
+/** @file
+ Implement TPM2 Context related command.
+
+Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_DH_CONTEXT FlushHandle;
+} TPM2_FLUSH_CONTEXT_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+} TPM2_FLUSH_CONTEXT_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command causes all context associated with a loaded object or session to be removed from TPM memory.
+
+ @param[in] FlushHandle The handle of the item to flush.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2FlushContext (
+ IN TPMI_DH_CONTEXT FlushHandle
+ )
+{
+ EFI_STATUS Status;
+ TPM2_FLUSH_CONTEXT_COMMAND SendBuffer;
+ TPM2_FLUSH_CONTEXT_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_FlushContext);
+
+ SendBuffer.FlushHandle = SwapBytes32 (FlushHandle);
+
+ SendBufferSize = (UINT32) sizeof (SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2FlushContext - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2FlushContext - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c
new file mode 100644
index 000000000..f50211387
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c
@@ -0,0 +1,213 @@
+/** @file
+ Implement TPM2 DictionaryAttack related command.
+
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_LOCKOUT LockHandle;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+} TPM2_DICTIONARY_ATTACK_LOCK_RESET_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_DICTIONARY_ATTACK_LOCK_RESET_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_LOCKOUT LockHandle;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ UINT32 NewMaxTries;
+ UINT32 NewRecoveryTime;
+ UINT32 LockoutRecovery;
+} TPM2_DICTIONARY_ATTACK_PARAMETERS_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_DICTIONARY_ATTACK_PARAMETERS_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command cancels the effect of a TPM lockout due to a number of successive authorization failures.
+ If this command is properly authorized, the lockout counter is set to zero.
+
+ @param[in] LockHandle TPM_RH_LOCKOUT
+ @param[in] AuthSession Auth Session context
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2DictionaryAttackLockReset (
+ IN TPMI_RH_LOCKOUT LockHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession
+ )
+{
+ EFI_STATUS Status;
+ TPM2_DICTIONARY_ATTACK_LOCK_RESET_COMMAND SendBuffer;
+ TPM2_DICTIONARY_ATTACK_LOCK_RESET_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_DictionaryAttackLockReset);
+
+ SendBuffer.LockHandle = SwapBytes32 (LockHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackLockReset - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackLockReset - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
+
+/**
+ This command cancels the effect of a TPM lockout due to a number of successive authorization failures.
+ If this command is properly authorized, the lockout counter is set to zero.
+
+ @param[in] LockHandle TPM_RH_LOCKOUT
+ @param[in] AuthSession Auth Session context
+ @param[in] NewMaxTries Count of authorization failures before the lockout is imposed
+ @param[in] NewRecoveryTime Time in seconds before the authorization failure count is automatically decremented
+ @param[in] LockoutRecovery Time in seconds after a lockoutAuth failure before use of lockoutAuth is allowed
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2DictionaryAttackParameters (
+ IN TPMI_RH_LOCKOUT LockHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession,
+ IN UINT32 NewMaxTries,
+ IN UINT32 NewRecoveryTime,
+ IN UINT32 LockoutRecovery
+ )
+{
+ EFI_STATUS Status;
+ TPM2_DICTIONARY_ATTACK_PARAMETERS_COMMAND SendBuffer;
+ TPM2_DICTIONARY_ATTACK_PARAMETERS_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_DictionaryAttackParameters);
+
+ SendBuffer.LockHandle = SwapBytes32 (LockHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ //
+ // Real data
+ //
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(NewMaxTries));
+ Buffer += sizeof(UINT32);
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(NewRecoveryTime));
+ Buffer += sizeof(UINT32);
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(LockoutRecovery));
+ Buffer += sizeof(UINT32);
+
+ SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackParameters - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackParameters - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBufferSize, sizeof(SendBufferSize));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c
new file mode 100644
index 000000000..61c636726
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c
@@ -0,0 +1,396 @@
+/** @file
+ Implement TPM2 EnhancedAuthorization related command.
+
+Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_DH_ENTITY AuthHandle;
+ TPMI_SH_POLICY PolicySession;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ TPM2B_NONCE NonceTPM;
+ TPM2B_DIGEST CpHashA;
+ TPM2B_NONCE PolicyRef;
+ INT32 Expiration;
+} TPM2_POLICY_SECRET_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPM2B_TIMEOUT Timeout;
+ TPMT_TK_AUTH PolicyTicket;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_POLICY_SECRET_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_SH_POLICY PolicySession;
+ TPML_DIGEST HashList;
+} TPM2_POLICY_OR_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+} TPM2_POLICY_OR_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_SH_POLICY PolicySession;
+ TPM_CC Code;
+} TPM2_POLICY_COMMAND_CODE_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+} TPM2_POLICY_COMMAND_CODE_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_SH_POLICY PolicySession;
+} TPM2_POLICY_GET_DIGEST_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ TPM2B_DIGEST PolicyHash;
+} TPM2_POLICY_GET_DIGEST_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command includes a secret-based authorization to a policy.
+ The caller proves knowledge of the secret value using an authorization
+ session using the authValue associated with authHandle.
+
+ @param[in] AuthHandle Handle for an entity providing the authorization
+ @param[in] PolicySession Handle for the policy session being extended.
+ @param[in] AuthSession Auth Session context
+ @param[in] NonceTPM The policy nonce for the session.
+ @param[in] CpHashA Digest of the command parameters to which this authorization is limited.
+ @param[in] PolicyRef A reference to a policy relating to the authorization.
+ @param[in] Expiration Time when authorization will expire, measured in seconds from the time that nonceTPM was generated.
+ @param[out] Timeout Time value used to indicate to the TPM when the ticket expires.
+ @param[out] PolicyTicket A ticket that includes a value indicating when the authorization expires.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PolicySecret (
+ IN TPMI_DH_ENTITY AuthHandle,
+ IN TPMI_SH_POLICY PolicySession,
+ IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
+ IN TPM2B_NONCE *NonceTPM,
+ IN TPM2B_DIGEST *CpHashA,
+ IN TPM2B_NONCE *PolicyRef,
+ IN INT32 Expiration,
+ OUT TPM2B_TIMEOUT *Timeout,
+ OUT TPMT_TK_AUTH *PolicyTicket
+ )
+{
+ EFI_STATUS Status;
+ TPM2_POLICY_SECRET_COMMAND SendBuffer;
+ TPM2_POLICY_SECRET_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicySecret);
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+ SendBuffer.PolicySession = SwapBytes32 (PolicySession);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ //
+ // Real data
+ //
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NonceTPM->size));
+ Buffer += sizeof(UINT16);
+ CopyMem (Buffer, NonceTPM->buffer, NonceTPM->size);
+ Buffer += NonceTPM->size;
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(CpHashA->size));
+ Buffer += sizeof(UINT16);
+ CopyMem (Buffer, CpHashA->buffer, CpHashA->size);
+ Buffer += CpHashA->size;
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PolicyRef->size));
+ Buffer += sizeof(UINT16);
+ CopyMem (Buffer, PolicyRef->buffer, PolicyRef->size);
+ Buffer += PolicyRef->size;
+
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32((UINT32)Expiration));
+ Buffer += sizeof(UINT32);
+
+ SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Return the response
+ //
+ Buffer = (UINT8 *)&RecvBuffer.Timeout;
+ Timeout->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
+ if (Timeout->size > sizeof(UINT64)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - Timeout->size error %x\n", Timeout->size));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ Buffer += sizeof(UINT16);
+ CopyMem (Timeout->buffer, Buffer, Timeout->size);
+
+ PolicyTicket->tag = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ PolicyTicket->hierarchy = SwapBytes32(ReadUnaligned32 ((UINT32 *)Buffer));
+ Buffer += sizeof(UINT32);
+ PolicyTicket->digest.size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ if (PolicyTicket->digest.size > sizeof(TPMU_HA)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - digest.size error %x\n", PolicyTicket->digest.size));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ CopyMem (PolicyTicket->digest.buffer, Buffer, PolicyTicket->digest.size);
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
+
+/**
+ This command allows options in authorizations without requiring that the TPM evaluate all of the options.
+ If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that
+ satisfies the policy. This command will indicate that one of the required sets of conditions has been
+ satisfied.
+
+ @param[in] PolicySession Handle for the policy session being extended.
+ @param[in] HashList the list of hashes to check for a match.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PolicyOR (
+ IN TPMI_SH_POLICY PolicySession,
+ IN TPML_DIGEST *HashList
+ )
+{
+ EFI_STATUS Status;
+ TPM2_POLICY_OR_COMMAND SendBuffer;
+ TPM2_POLICY_OR_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINTN Index;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyOR);
+
+ SendBuffer.PolicySession = SwapBytes32 (PolicySession);
+ Buffer = (UINT8 *)&SendBuffer.HashList;
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (HashList->count));
+ Buffer += sizeof(UINT32);
+ for (Index = 0; Index < HashList->count; Index++) {
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (HashList->digests[Index].size));
+ Buffer += sizeof(UINT16);
+ CopyMem (Buffer, HashList->digests[Index].buffer, HashList->digests[Index].size);
+ Buffer += HashList->digests[Index].size;
+ }
+
+ SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command indicates that the authorization will be limited to a specific command code.
+
+ @param[in] PolicySession Handle for the policy session being extended.
+ @param[in] Code The allowed commandCode.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PolicyCommandCode (
+ IN TPMI_SH_POLICY PolicySession,
+ IN TPM_CC Code
+ )
+{
+ EFI_STATUS Status;
+ TPM2_POLICY_COMMAND_CODE_COMMAND SendBuffer;
+ TPM2_POLICY_COMMAND_CODE_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyCommandCode);
+
+ SendBuffer.PolicySession = SwapBytes32 (PolicySession);
+ SendBuffer.Code = SwapBytes32 (Code);
+
+ SendBufferSize = (UINT32) sizeof (SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the current policyDigest of the session. This command allows the TPM
+ to be used to perform the actions required to precompute the authPolicy for an object.
+
+ @param[in] PolicySession Handle for the policy session.
+ @param[out] PolicyHash the current value of the policyHash of policySession.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PolicyGetDigest (
+ IN TPMI_SH_POLICY PolicySession,
+ OUT TPM2B_DIGEST *PolicyHash
+ )
+{
+ EFI_STATUS Status;
+ TPM2_POLICY_GET_DIGEST_COMMAND SendBuffer;
+ TPM2_POLICY_GET_DIGEST_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyGetDigest);
+
+ SendBuffer.PolicySession = SwapBytes32 (PolicySession);
+
+ SendBufferSize = (UINT32) sizeof (SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Return the response
+ //
+ PolicyHash->size = SwapBytes16 (RecvBuffer.PolicyHash.size);
+ if (PolicyHash->size > sizeof(TPMU_HA)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2PolicyGetDigest - PolicyHash->size error %x\n", PolicyHash->size));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CopyMem (PolicyHash->buffer, &RecvBuffer.PolicyHash.buffer, PolicyHash->size);
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c
new file mode 100644
index 000000000..36c240d12
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c
@@ -0,0 +1,344 @@
+/** @file
+ Implement TPM2 help.
+
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+typedef struct {
+ TPMI_ALG_HASH HashAlgo;
+ UINT16 HashSize;
+ UINT32 HashMask;
+} INTERNAL_HASH_INFO;
+
+STATIC INTERNAL_HASH_INFO mHashInfo[] = {
+ {TPM_ALG_SHA1, SHA1_DIGEST_SIZE, HASH_ALG_SHA1},
+ {TPM_ALG_SHA256, SHA256_DIGEST_SIZE, HASH_ALG_SHA256},
+ {TPM_ALG_SM3_256, SM3_256_DIGEST_SIZE, HASH_ALG_SM3_256},
+ {TPM_ALG_SHA384, SHA384_DIGEST_SIZE, HASH_ALG_SHA384},
+ {TPM_ALG_SHA512, SHA512_DIGEST_SIZE, HASH_ALG_SHA512},
+};
+
+/**
+ Return size of digest.
+
+ @param[in] HashAlgo Hash algorithm
+
+ @return size of digest
+**/
+UINT16
+EFIAPI
+GetHashSizeFromAlgo (
+ IN TPMI_ALG_HASH HashAlgo
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) {
+ if (mHashInfo[Index].HashAlgo == HashAlgo) {
+ return mHashInfo[Index].HashSize;
+ }
+ }
+ return 0;
+}
+
+/**
+ Get hash mask from algorithm.
+
+ @param[in] HashAlgo Hash algorithm
+
+ @return Hash mask
+**/
+UINT32
+EFIAPI
+GetHashMaskFromAlgo (
+ IN TPMI_ALG_HASH HashAlgo
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) {
+ if (mHashInfo[Index].HashAlgo == HashAlgo) {
+ return mHashInfo[Index].HashMask;
+ }
+ }
+ return 0;
+}
+
+/**
+ Copy AuthSessionIn to TPM2 command buffer.
+
+ @param [in] AuthSessionIn Input AuthSession data
+ @param [out] AuthSessionOut Output AuthSession data in TPM2 command buffer
+
+ @return AuthSession size
+**/
+UINT32
+EFIAPI
+CopyAuthSessionCommand (
+ IN TPMS_AUTH_COMMAND *AuthSessionIn, OPTIONAL
+ OUT UINT8 *AuthSessionOut
+ )
+{
+ UINT8 *Buffer;
+
+ Buffer = (UINT8 *)AuthSessionOut;
+
+ //
+ // Add in Auth session
+ //
+ if (AuthSessionIn != NULL) {
+ // sessionHandle
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(AuthSessionIn->sessionHandle));
+ Buffer += sizeof(UINT32);
+
+ // nonce
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->nonce.size));
+ Buffer += sizeof(UINT16);
+
+ CopyMem (Buffer, AuthSessionIn->nonce.buffer, AuthSessionIn->nonce.size);
+ Buffer += AuthSessionIn->nonce.size;
+
+ // sessionAttributes
+ *(UINT8 *)Buffer = *(UINT8 *)&AuthSessionIn->sessionAttributes;
+ Buffer++;
+
+ // hmac
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->hmac.size));
+ Buffer += sizeof(UINT16);
+
+ CopyMem (Buffer, AuthSessionIn->hmac.buffer, AuthSessionIn->hmac.size);
+ Buffer += AuthSessionIn->hmac.size;
+ } else {
+ // sessionHandle
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(TPM_RS_PW));
+ Buffer += sizeof(UINT32);
+
+ // nonce = nullNonce
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));
+ Buffer += sizeof(UINT16);
+
+ // sessionAttributes = 0
+ *(UINT8 *)Buffer = 0x00;
+ Buffer++;
+
+ // hmac = nullAuth
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));
+ Buffer += sizeof(UINT16);
+ }
+
+ return (UINT32)((UINTN)Buffer - (UINTN)AuthSessionOut);
+}
+
+/**
+ Copy AuthSessionIn from TPM2 response buffer.
+
+ @param [in] AuthSessionIn Input AuthSession data in TPM2 response buffer
+ @param [out] AuthSessionOut Output AuthSession data
+
+ @return 0 copy failed
+ else AuthSession size
+**/
+UINT32
+EFIAPI
+CopyAuthSessionResponse (
+ IN UINT8 *AuthSessionIn,
+ OUT TPMS_AUTH_RESPONSE *AuthSessionOut OPTIONAL
+ )
+{
+ UINT8 *Buffer;
+ TPMS_AUTH_RESPONSE LocalAuthSessionOut;
+
+ if (AuthSessionOut == NULL) {
+ AuthSessionOut = &LocalAuthSessionOut;
+ }
+
+ Buffer = (UINT8 *)AuthSessionIn;
+
+ // nonce
+ AuthSessionOut->nonce.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ if (AuthSessionOut->nonce.size > sizeof(TPMU_HA)) {
+ DEBUG ((DEBUG_ERROR, "CopyAuthSessionResponse - nonce.size error %x\n", AuthSessionOut->nonce.size));
+ return 0;
+ }
+
+ CopyMem (AuthSessionOut->nonce.buffer, Buffer, AuthSessionOut->nonce.size);
+ Buffer += AuthSessionOut->nonce.size;
+
+ // sessionAttributes
+ *(UINT8 *)&AuthSessionOut->sessionAttributes = *(UINT8 *)Buffer;
+ Buffer++;
+
+ // hmac
+ AuthSessionOut->hmac.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ if (AuthSessionOut->hmac.size > sizeof(TPMU_HA)) {
+ DEBUG ((DEBUG_ERROR, "CopyAuthSessionResponse - hmac.size error %x\n", AuthSessionOut->hmac.size));
+ return 0;
+ }
+
+ CopyMem (AuthSessionOut->hmac.buffer, Buffer, AuthSessionOut->hmac.size);
+ Buffer += AuthSessionOut->hmac.size;
+
+ return (UINT32)((UINTN)Buffer - (UINTN)AuthSessionIn);
+}
+
+/**
+ Return if hash alg is supported in HashAlgorithmMask.
+
+ @param HashAlg Hash algorithm to be checked.
+ @param HashAlgorithmMask Bitfield of allowed hash algorithms.
+
+ @retval TRUE Hash algorithm is supported.
+ @retval FALSE Hash algorithm is not supported.
+**/
+BOOLEAN
+EFIAPI
+IsHashAlgSupportedInHashAlgorithmMask(
+ IN TPMI_ALG_HASH HashAlg,
+ IN UINT32 HashAlgorithmMask
+ )
+{
+ switch (HashAlg) {
+ case TPM_ALG_SHA1:
+ if ((HashAlgorithmMask & HASH_ALG_SHA1) != 0) {
+ return TRUE;
+ }
+ break;
+ case TPM_ALG_SHA256:
+ if ((HashAlgorithmMask & HASH_ALG_SHA256) != 0) {
+ return TRUE;
+ }
+ break;
+ case TPM_ALG_SHA384:
+ if ((HashAlgorithmMask & HASH_ALG_SHA384) != 0) {
+ return TRUE;
+ }
+ break;
+ case TPM_ALG_SHA512:
+ if ((HashAlgorithmMask & HASH_ALG_SHA512) != 0) {
+ return TRUE;
+ }
+ break;
+ case TPM_ALG_SM3_256:
+ if ((HashAlgorithmMask & HASH_ALG_SM3_256) != 0) {
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/**
+ Copy TPML_DIGEST_VALUES into a buffer
+
+ @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.
+ @param[in] DigestList TPML_DIGEST_VALUES to be copied.
+ @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.
+
+ @return The end of buffer to hold TPML_DIGEST_VALUES.
+**/
+VOID *
+EFIAPI
+CopyDigestListToBuffer (
+ IN OUT VOID *Buffer,
+ IN TPML_DIGEST_VALUES *DigestList,
+ IN UINT32 HashAlgorithmMask
+ )
+{
+ UINTN Index;
+ UINT16 DigestSize;
+ UINT32 DigestListCount;
+ UINT32 *DigestListCountPtr;
+
+ DigestListCountPtr = (UINT32 *) Buffer;
+ DigestListCount = 0;
+ Buffer = (UINT8 *)Buffer + sizeof(DigestList->count);
+ for (Index = 0; Index < DigestList->count; Index++) {
+ if (!IsHashAlgSupportedInHashAlgorithmMask(DigestList->digests[Index].hashAlg, HashAlgorithmMask)) {
+ 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;
+ DigestListCount++;
+ }
+ WriteUnaligned32 (DigestListCountPtr, DigestListCount);
+
+ return Buffer;
+}
+
+/**
+ Get TPML_DIGEST_VALUES data size.
+
+ @param[in] DigestList TPML_DIGEST_VALUES data.
+
+ @return TPML_DIGEST_VALUES data size.
+**/
+UINT32
+EFIAPI
+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;
+}
+
+/**
+ This function get digest from digest list.
+
+ @param[in] HashAlg Digest algorithm
+ @param[in] DigestList Digest list
+ @param[out] Digest Digest
+
+ @retval EFI_SUCCESS Digest is found and returned.
+ @retval EFI_NOT_FOUND Digest is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetDigestFromDigestList (
+ IN TPMI_ALG_HASH HashAlg,
+ IN TPML_DIGEST_VALUES *DigestList,
+ OUT 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;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c
new file mode 100644
index 000000000..dc36963c0
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c
@@ -0,0 +1,797 @@
+/** @file
+ Implement TPM2 Hierarchy related command.
+
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_HIERARCHY_AUTH AuthHandle;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ TPM2B_DIGEST AuthPolicy;
+ TPMI_ALG_HASH HashAlg;
+} TPM2_SET_PRIMARY_POLICY_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_SET_PRIMARY_POLICY_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_CLEAR AuthHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSession;
+} TPM2_CLEAR_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_CLEAR_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_CLEAR AuthHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ TPMI_YES_NO Disable;
+} TPM2_CLEAR_CONTROL_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_CLEAR_CONTROL_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_HIERARCHY_AUTH AuthHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ TPM2B_AUTH NewAuth;
+} TPM2_HIERARCHY_CHANGE_AUTH_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_HIERARCHY_CHANGE_AUTH_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_PLATFORM AuthHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSession;
+} TPM2_CHANGE_EPS_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_CHANGE_EPS_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_PLATFORM AuthHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSession;
+} TPM2_CHANGE_PPS_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_CHANGE_PPS_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_HIERARCHY AuthHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ TPMI_RH_HIERARCHY Hierarchy;
+ TPMI_YES_NO State;
+} TPM2_HIERARCHY_CONTROL_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_HIERARCHY_CONTROL_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command allows setting of the authorization policy for the platform hierarchy (platformPolicy), the
+ storage hierarchy (ownerPolicy), and and the endorsement hierarchy (endorsementPolicy).
+
+ @param[in] AuthHandle TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} parameters to be validated
+ @param[in] AuthSession Auth Session context
+ @param[in] AuthPolicy An authorization policy hash
+ @param[in] HashAlg The hash algorithm to use for the policy
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SetPrimaryPolicy (
+ IN TPMI_RH_HIERARCHY_AUTH AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession,
+ IN TPM2B_DIGEST *AuthPolicy,
+ IN TPMI_ALG_HASH HashAlg
+ )
+{
+ EFI_STATUS Status;
+ TPM2_SET_PRIMARY_POLICY_COMMAND SendBuffer;
+ TPM2_SET_PRIMARY_POLICY_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_SetPrimaryPolicy);
+
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ //
+ // Real data
+ //
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(AuthPolicy->size));
+ Buffer += sizeof(UINT16);
+ CopyMem (Buffer, AuthPolicy->buffer, AuthPolicy->size);
+ Buffer += AuthPolicy->size;
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(HashAlg));
+ Buffer += sizeof(UINT16);
+
+ SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
+
+/**
+ This command removes all TPM context associated with a specific Owner.
+
+ @param[in] AuthHandle TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
+ @param[in] AuthSession Auth Session context
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2Clear (
+ IN TPMI_RH_CLEAR AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ TPM2_CLEAR_COMMAND Cmd;
+ TPM2_CLEAR_RESPONSE Res;
+ UINT32 ResultBufSize;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_Clear);
+ Cmd.AuthHandle = SwapBytes32(AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&Cmd.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "Clear: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "Clear: Response size too large! %d\r\n", RespSize));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Clear: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Unmarshal the response
+ //
+
+ // None
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&Cmd, sizeof(Cmd));
+ ZeroMem (&Res, sizeof(Res));
+ return Status;
+}
+
+/**
+ Disables and enables the execution of TPM2_Clear().
+
+ @param[in] AuthHandle TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
+ @param[in] AuthSession Auth Session context
+ @param[in] Disable YES if the disableOwnerClear flag is to be SET,
+ NO if the flag is to be CLEAR.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2ClearControl (
+ IN TPMI_RH_CLEAR AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
+ IN TPMI_YES_NO Disable
+ )
+{
+ EFI_STATUS Status;
+ TPM2_CLEAR_CONTROL_COMMAND Cmd;
+ TPM2_CLEAR_CONTROL_RESPONSE Res;
+ UINT32 ResultBufSize;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_ClearControl);
+ Cmd.AuthHandle = SwapBytes32(AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&Cmd.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ // disable
+ *(UINT8 *)Buffer = Disable;
+ Buffer++;
+
+ CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "ClearControl: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "ClearControl: Response size too large! %d\r\n", RespSize));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "ClearControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Unmarshal the response
+ //
+
+ // None
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&Cmd, sizeof(Cmd));
+ ZeroMem (&Res, sizeof(Res));
+ return Status;
+}
+
+/**
+ This command allows the authorization secret for a hierarchy or lockout to be changed using the current
+ authorization value as the command authorization.
+
+ @param[in] AuthHandle TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+ @param[in] AuthSession Auth Session context
+ @param[in] NewAuth New authorization secret
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2HierarchyChangeAuth (
+ IN TPMI_RH_HIERARCHY_AUTH AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession,
+ IN TPM2B_AUTH *NewAuth
+ )
+{
+ EFI_STATUS Status;
+ TPM2_HIERARCHY_CHANGE_AUTH_COMMAND Cmd;
+ TPM2_HIERARCHY_CHANGE_AUTH_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ UINT8 *ResultBuf;
+ UINT32 ResultBufSize;
+
+ //
+ // Construct command
+ //
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd));
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_HierarchyChangeAuth);
+ Cmd.AuthHandle = SwapBytes32(AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&Cmd.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ // New Authorization size
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NewAuth->size));
+ Buffer += sizeof(UINT16);
+
+ // New Authorization
+ CopyMem(Buffer, NewAuth->buffer, NewAuth->size);
+ Buffer += NewAuth->size;
+
+ CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ ResultBuf = (UINT8 *) &Res;
+ ResultBufSize = sizeof(Res);
+
+ //
+ // Call the TPM
+ //
+ Status = Tpm2SubmitCommand (
+ CmdSize,
+ (UINT8 *)&Cmd,
+ &ResultBufSize,
+ ResultBuf
+ );
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Response size too large! %d\r\n", RespSize));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG((EFI_D_ERROR,"HierarchyChangeAuth: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&Cmd, sizeof(Cmd));
+ ZeroMem (&Res, sizeof(Res));
+ return Status;
+}
+
+/**
+ This replaces the current EPS with a value from the RNG and sets the Endorsement hierarchy controls to
+ their default initialization values.
+
+ @param[in] AuthHandle TPM_RH_PLATFORM+{PP}
+ @param[in] AuthSession Auth Session context
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2ChangeEPS (
+ IN TPMI_RH_PLATFORM AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession
+ )
+{
+ EFI_STATUS Status;
+ TPM2_CHANGE_EPS_COMMAND Cmd;
+ TPM2_CHANGE_EPS_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ UINT8 *ResultBuf;
+ UINT32 ResultBufSize;
+
+ //
+ // Construct command
+ //
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd));
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_ChangeEPS);
+ Cmd.AuthHandle = SwapBytes32(AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&Cmd.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ ResultBuf = (UINT8 *) &Res;
+ ResultBufSize = sizeof(Res);
+
+ //
+ // Call the TPM
+ //
+ Status = Tpm2SubmitCommand (
+ CmdSize,
+ (UINT8 *)&Cmd,
+ &ResultBufSize,
+ ResultBuf
+ );
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "ChangeEPS: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "ChangeEPS: Response size too large! %d\r\n", RespSize));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG((EFI_D_ERROR,"ChangeEPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&Cmd, sizeof(Cmd));
+ ZeroMem (&Res, sizeof(Res));
+ return Status;
+}
+
+/**
+ This replaces the current PPS with a value from the RNG and sets platformPolicy to the default
+ initialization value (the Empty Buffer).
+
+ @param[in] AuthHandle TPM_RH_PLATFORM+{PP}
+ @param[in] AuthSession Auth Session context
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2ChangePPS (
+ IN TPMI_RH_PLATFORM AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession
+ )
+{
+ EFI_STATUS Status;
+ TPM2_CHANGE_PPS_COMMAND Cmd;
+ TPM2_CHANGE_PPS_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ UINT8 *ResultBuf;
+ UINT32 ResultBufSize;
+
+ //
+ // Construct command
+ //
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd));
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_ChangePPS);
+ Cmd.AuthHandle = SwapBytes32(AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&Cmd.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ ResultBuf = (UINT8 *) &Res;
+ ResultBufSize = sizeof(Res);
+
+ //
+ // Call the TPM
+ //
+ Status = Tpm2SubmitCommand (
+ CmdSize,
+ (UINT8 *)&Cmd,
+ &ResultBufSize,
+ ResultBuf
+ );
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "ChangePPS: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "ChangePPS: Response size too large! %d\r\n", RespSize));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG((EFI_D_ERROR,"ChangePPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&Cmd, sizeof(Cmd));
+ ZeroMem (&Res, sizeof(Res));
+ return Status;
+}
+
+/**
+ This command enables and disables use of a hierarchy.
+
+ @param[in] AuthHandle TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
+ @param[in] AuthSession Auth Session context
+ @param[in] Hierarchy Hierarchy of the enable being modified
+ @param[in] State YES if the enable should be SET,
+ NO if the enable should be CLEAR
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2HierarchyControl (
+ IN TPMI_RH_HIERARCHY AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession,
+ IN TPMI_RH_HIERARCHY Hierarchy,
+ IN TPMI_YES_NO State
+ )
+{
+ EFI_STATUS Status;
+ TPM2_HIERARCHY_CONTROL_COMMAND Cmd;
+ TPM2_HIERARCHY_CONTROL_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ UINT8 *ResultBuf;
+ UINT32 ResultBufSize;
+
+ //
+ // Construct command
+ //
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd));
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_HierarchyControl);
+ Cmd.AuthHandle = SwapBytes32(AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&Cmd.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Hierarchy));
+ Buffer += sizeof(UINT32);
+
+ *(UINT8 *)Buffer = State;
+ Buffer++;
+
+ CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ ResultBuf = (UINT8 *) &Res;
+ ResultBufSize = sizeof(Res);
+
+ //
+ // Call the TPM
+ //
+ Status = Tpm2SubmitCommand (
+ CmdSize,
+ (UINT8 *)&Cmd,
+ &ResultBufSize,
+ ResultBuf
+ );
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "HierarchyControl: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "HierarchyControl: Response size too large! %d\r\n", RespSize));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG((EFI_D_ERROR,"HierarchyControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&Cmd, sizeof(Cmd));
+ ZeroMem (&Res, sizeof(Res));
+ return Status;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
new file mode 100644
index 000000000..ddb15178f
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
@@ -0,0 +1,689 @@
+/** @file
+ Implement TPM2 Integrity related command.
+
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_DH_PCR PcrHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSessionPcr;
+ TPML_DIGEST_VALUES DigestValues;
+} TPM2_PCR_EXTEND_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPMS_AUTH_RESPONSE AuthSessionPcr;
+} TPM2_PCR_EXTEND_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_DH_PCR PcrHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSessionPcr;
+ TPM2B_EVENT EventData;
+} TPM2_PCR_EVENT_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPML_DIGEST_VALUES Digests;
+ TPMS_AUTH_RESPONSE AuthSessionPcr;
+} TPM2_PCR_EVENT_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPML_PCR_SELECTION PcrSelectionIn;
+} TPM2_PCR_READ_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 PcrUpdateCounter;
+ TPML_PCR_SELECTION PcrSelectionOut;
+ TPML_DIGEST PcrValues;
+} TPM2_PCR_READ_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_PLATFORM AuthHandle;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ TPML_PCR_SELECTION PcrAllocation;
+} TPM2_PCR_ALLOCATE_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMI_YES_NO AllocationSuccess;
+ UINT32 MaxPCR;
+ UINT32 SizeNeeded;
+ UINT32 SizeAvailable;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_PCR_ALLOCATE_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command is used to cause an update to the indicated PCR.
+ The digests parameter contains one or more tagged digest value identified by an algorithm ID.
+ For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg).
+
+ @param[in] PcrHandle Handle of the PCR
+ @param[in] Digests List of tagged digest values to be extended
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PcrExtend (
+ IN TPMI_DH_PCR PcrHandle,
+ IN TPML_DIGEST_VALUES *Digests
+ )
+{
+ EFI_STATUS Status;
+ TPM2_PCR_EXTEND_COMMAND Cmd;
+ TPM2_PCR_EXTEND_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT32 ResultBufSize;
+ UINT8 *Buffer;
+ UINTN Index;
+ UINT32 SessionInfoSize;
+ UINT16 DigestSize;
+
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Extend);
+ Cmd.PcrHandle = SwapBytes32(PcrHandle);
+
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
+ Buffer += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ //Digest Count
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Digests->count));
+ Buffer += sizeof(UINT32);
+
+ //Digest
+ for (Index = 0; Index < Digests->count; Index++) {
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Digests->digests[Index].hashAlg));
+ Buffer += sizeof(UINT16);
+ DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
+ if (DigestSize == 0) {
+ DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem(
+ Buffer,
+ &Digests->digests[Index].digest,
+ DigestSize
+ );
+ Buffer += DigestSize;
+ }
+
+ CmdSize = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Unmarshal the response
+ //
+
+ // None
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command is used to cause an update to the indicated PCR.
+ The data in eventData is hashed using the hash algorithm associated with each bank in which the
+ indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle
+ references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in
+ TPM2_PCR_Extend().
+ A TPM shall support an Event.size of zero through 1,024 inclusive.
+
+ @param[in] PcrHandle Handle of the PCR
+ @param[in] EventData Event data in sized buffer
+ @param[out] Digests List of digest
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PcrEvent (
+ IN TPMI_DH_PCR PcrHandle,
+ IN TPM2B_EVENT *EventData,
+ OUT TPML_DIGEST_VALUES *Digests
+ )
+{
+ EFI_STATUS Status;
+ TPM2_PCR_EVENT_COMMAND Cmd;
+ TPM2_PCR_EVENT_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT32 ResultBufSize;
+ UINT8 *Buffer;
+ UINTN Index;
+ UINT32 SessionInfoSize;
+ UINT16 DigestSize;
+
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Event);
+ Cmd.PcrHandle = SwapBytes32(PcrHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
+ Buffer += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ // Event
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(EventData->size));
+ Buffer += sizeof(UINT16);
+
+ CopyMem (Buffer, EventData->buffer, EventData->size);
+ Buffer += EventData->size;
+
+ CmdSize = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n", RespSize));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Unmarshal the response
+ //
+ Buffer = (UINT8 *)&Res.Digests;
+
+ Digests->count = SwapBytes32 (ReadUnaligned32 ((UINT32 *)Buffer));
+ if (Digests->count > HASH_COUNT) {
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent - Digests->count error %x\n", Digests->count));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Buffer += sizeof(UINT32);
+ for (Index = 0; Index < Digests->count; Index++) {
+ Digests->digests[Index].hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
+ if (DigestSize == 0) {
+ DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem(
+ &Digests->digests[Index].digest,
+ Buffer,
+ DigestSize
+ );
+ Buffer += DigestSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command returns the values of all PCR specified in pcrSelect.
+
+ @param[in] PcrSelectionIn The selection of PCR to read.
+ @param[out] PcrUpdateCounter The current value of the PCR update counter.
+ @param[out] PcrSelectionOut The PCR in the returned list.
+ @param[out] PcrValues The contents of the PCR indicated in pcrSelect.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PcrRead (
+ IN TPML_PCR_SELECTION *PcrSelectionIn,
+ OUT UINT32 *PcrUpdateCounter,
+ OUT TPML_PCR_SELECTION *PcrSelectionOut,
+ OUT TPML_DIGEST *PcrValues
+ )
+{
+ EFI_STATUS Status;
+ TPM2_PCR_READ_COMMAND SendBuffer;
+ TPM2_PCR_READ_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINTN Index;
+ TPML_DIGEST *PcrValuesOut;
+ TPM2B_DIGEST *Digests;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PCR_Read);
+
+ SendBuffer.PcrSelectionIn.count = SwapBytes32(PcrSelectionIn->count);
+ for (Index = 0; Index < PcrSelectionIn->count; Index++) {
+ SendBuffer.PcrSelectionIn.pcrSelections[Index].hash = SwapBytes16(PcrSelectionIn->pcrSelections[Index].hash);
+ SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect = PcrSelectionIn->pcrSelections[Index].sizeofSelect;
+ CopyMem (&SendBuffer.PcrSelectionIn.pcrSelections[Index].pcrSelect, &PcrSelectionIn->pcrSelections[Index].pcrSelect, SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect);
+ }
+
+ SendBufferSize = sizeof(SendBuffer.Header) + sizeof(SendBuffer.PcrSelectionIn.count) + sizeof(SendBuffer.PcrSelectionIn.pcrSelections[0]) * PcrSelectionIn->count;
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Return the response
+ //
+
+ //
+ // PcrUpdateCounter
+ //
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ *PcrUpdateCounter = SwapBytes32(RecvBuffer.PcrUpdateCounter);
+
+ //
+ // PcrSelectionOut
+ //
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ PcrSelectionOut->count = SwapBytes32(RecvBuffer.PcrSelectionOut.count);
+ if (PcrSelectionOut->count > HASH_COUNT) {
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - PcrSelectionOut->count error %x\n", PcrSelectionOut->count));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ for (Index = 0; Index < PcrSelectionOut->count; Index++) {
+ PcrSelectionOut->pcrSelections[Index].hash = SwapBytes16(RecvBuffer.PcrSelectionOut.pcrSelections[Index].hash);
+ PcrSelectionOut->pcrSelections[Index].sizeofSelect = RecvBuffer.PcrSelectionOut.pcrSelections[Index].sizeofSelect;
+ if (PcrSelectionOut->pcrSelections[Index].sizeofSelect > PCR_SELECT_MAX) {
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem (&PcrSelectionOut->pcrSelections[Index].pcrSelect, &RecvBuffer.PcrSelectionOut.pcrSelections[Index].pcrSelect, PcrSelectionOut->pcrSelections[Index].sizeofSelect);
+ }
+
+ //
+ // PcrValues
+ //
+ PcrValuesOut = (TPML_DIGEST *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count);
+ PcrValues->count = SwapBytes32(PcrValuesOut->count);
+ //
+ // The number of digests in list is not greater than 8 per TPML_DIGEST definition
+ //
+ if (PcrValues->count > 8) {
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - PcrValues->count error %x\n", PcrValues->count));
+ return EFI_DEVICE_ERROR;
+ }
+ Digests = PcrValuesOut->digests;
+ for (Index = 0; Index < PcrValues->count; Index++) {
+ PcrValues->digests[Index].size = SwapBytes16(Digests->size);
+ if (PcrValues->digests[Index].size > sizeof(TPMU_HA)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - Digest.size error %x\n", PcrValues->digests[Index].size));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem (&PcrValues->digests[Index].buffer, &Digests->buffer, PcrValues->digests[Index].size);
+ Digests = (TPM2B_DIGEST *)((UINT8 *)Digests + sizeof(Digests->size) + PcrValues->digests[Index].size);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command is used to set the desired PCR allocation of PCR and algorithms.
+
+ @param[in] AuthHandle TPM_RH_PLATFORM+{PP}
+ @param[in] AuthSession Auth Session context
+ @param[in] PcrAllocation The requested allocation
+ @param[out] AllocationSuccess YES if the allocation succeeded
+ @param[out] MaxPCR maximum number of PCR that may be in a bank
+ @param[out] SizeNeeded number of octets required to satisfy the request
+ @param[out] SizeAvailable Number of octets available. Computed before the allocation
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PcrAllocate (
+ IN TPMI_RH_PLATFORM AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession,
+ IN TPML_PCR_SELECTION *PcrAllocation,
+ OUT TPMI_YES_NO *AllocationSuccess,
+ OUT UINT32 *MaxPCR,
+ OUT UINT32 *SizeNeeded,
+ OUT UINT32 *SizeAvailable
+ )
+{
+ EFI_STATUS Status;
+ TPM2_PCR_ALLOCATE_COMMAND Cmd;
+ TPM2_PCR_ALLOCATE_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ UINT8 *ResultBuf;
+ UINT32 ResultBufSize;
+ UINTN Index;
+
+ //
+ // Construct command
+ //
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd));
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Allocate);
+ Cmd.AuthHandle = SwapBytes32(AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&Cmd.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ Cmd.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ // Count
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(PcrAllocation->count));
+ Buffer += sizeof(UINT32);
+ for (Index = 0; Index < PcrAllocation->count; Index++) {
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PcrAllocation->pcrSelections[Index].hash));
+ Buffer += sizeof(UINT16);
+ *(UINT8 *)Buffer = PcrAllocation->pcrSelections[Index].sizeofSelect;
+ Buffer++;
+ CopyMem (Buffer, PcrAllocation->pcrSelections[Index].pcrSelect, PcrAllocation->pcrSelections[Index].sizeofSelect);
+ Buffer += PcrAllocation->pcrSelections[Index].sizeofSelect;
+ }
+
+ CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ ResultBuf = (UINT8 *) &Res;
+ ResultBufSize = sizeof(Res);
+
+ //
+ // Call the TPM
+ //
+ Status = Tpm2SubmitCommand (
+ CmdSize,
+ (UINT8 *)&Cmd,
+ &ResultBufSize,
+ ResultBuf
+ );
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize));
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG((EFI_D_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ //
+ // Return the response
+ //
+ *AllocationSuccess = Res.AllocationSuccess;
+ *MaxPCR = SwapBytes32(Res.MaxPCR);
+ *SizeNeeded = SwapBytes32(Res.SizeNeeded);
+ *SizeAvailable = SwapBytes32(Res.SizeAvailable);
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&Cmd, sizeof(Cmd));
+ ZeroMem (&Res, sizeof(Res));
+ return Status;
+}
+
+/**
+ Alloc PCR data.
+
+ @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
+ @param[in] SupportedPCRBanks Supported PCR banks
+ @param[in] PCRBanks PCR banks
+
+ @retval EFI_SUCCESS Operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PcrAllocateBanks (
+ IN TPM2B_AUTH *PlatformAuth, OPTIONAL
+ IN UINT32 SupportedPCRBanks,
+ IN UINT32 PCRBanks
+ )
+{
+ EFI_STATUS Status;
+ TPMS_AUTH_COMMAND *AuthSession;
+ TPMS_AUTH_COMMAND LocalAuthSession;
+ TPML_PCR_SELECTION PcrAllocation;
+ TPMI_YES_NO AllocationSuccess;
+ UINT32 MaxPCR;
+ UINT32 SizeNeeded;
+ UINT32 SizeAvailable;
+
+ if (PlatformAuth == NULL) {
+ AuthSession = NULL;
+ } else {
+ AuthSession = &LocalAuthSession;
+ ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
+ LocalAuthSession.sessionHandle = TPM_RS_PW;
+ LocalAuthSession.hmac.size = PlatformAuth->size;
+ CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
+ }
+
+ //
+ // Fill input
+ //
+ ZeroMem (&PcrAllocation, sizeof(PcrAllocation));
+ if ((HASH_ALG_SHA1 & SupportedPCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA1;
+ PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
+ if ((HASH_ALG_SHA1 & PCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
+ } else {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
+ }
+ PcrAllocation.count++;
+ }
+ if ((HASH_ALG_SHA256 & SupportedPCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA256;
+ PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
+ if ((HASH_ALG_SHA256 & PCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
+ } else {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
+ }
+ PcrAllocation.count++;
+ }
+ if ((HASH_ALG_SHA384 & SupportedPCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA384;
+ PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
+ if ((HASH_ALG_SHA384 & PCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
+ } else {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
+ }
+ PcrAllocation.count++;
+ }
+ if ((HASH_ALG_SHA512 & SupportedPCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA512;
+ PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
+ if ((HASH_ALG_SHA512 & PCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
+ } else {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
+ }
+ PcrAllocation.count++;
+ }
+ if ((HASH_ALG_SM3_256 & SupportedPCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SM3_256;
+ PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
+ if ((HASH_ALG_SM3_256 & PCRBanks) != 0) {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
+ } else {
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
+ PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
+ }
+ PcrAllocation.count++;
+ }
+ Status = Tpm2PcrAllocate (
+ TPM_RH_PLATFORM,
+ AuthSession,
+ &PcrAllocation,
+ &AllocationSuccess,
+ &MaxPCR,
+ &SizeNeeded,
+ &SizeAvailable
+ );
+ DEBUG ((EFI_D_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n", Status));
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ DEBUG ((EFI_D_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));
+ DEBUG ((EFI_D_INFO, "MaxPCR - %08x\n", MaxPCR));
+ DEBUG ((EFI_D_INFO, "SizeNeeded - %08x\n", SizeNeeded));
+ DEBUG ((EFI_D_INFO, "SizeAvailable - %08x\n", SizeAvailable));
+
+Done:
+ ZeroMem(&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));
+ return Status;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c
new file mode 100644
index 000000000..32bff4584
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c
@@ -0,0 +1,116 @@
+/** @file
+ Implement TPM2 Miscellaneous related command.
+
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_HIERARCHY_AUTH AuthHandle;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ UINT32 AlgorithmSet;
+} TPM2_SET_ALGORITHM_SET_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_SET_ALGORITHM_SET_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command allows the platform to change the set of algorithms that are used by the TPM.
+ The algorithmSet setting is a vendor-dependent value.
+
+ @param[in] AuthHandle TPM_RH_PLATFORM
+ @param[in] AuthSession Auth Session context
+ @param[in] AlgorithmSet A TPM vendor-dependent value indicating the
+ algorithm set selection
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SetAlgorithmSet (
+ IN TPMI_RH_PLATFORM AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession,
+ IN UINT32 AlgorithmSet
+ )
+{
+ EFI_STATUS Status;
+ TPM2_SET_ALGORITHM_SET_COMMAND SendBuffer;
+ TPM2_SET_ALGORITHM_SET_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_SetAlgorithmSet);
+
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ //
+ // Real data
+ //
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(AlgorithmSet));
+ Buffer += sizeof(UINT32);
+
+ SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2SetAlgorithmSet - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2SetAlgorithmSet - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
new file mode 100644
index 000000000..87572de20
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
@@ -0,0 +1,1042 @@
+/** @file
+ Implement TPM2 NVStorage related command.
+
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+#define RC_NV_ReadPublic_nvIndex (TPM_RC_H + TPM_RC_1)
+
+#define RC_NV_DefineSpace_authHandle (TPM_RC_H + TPM_RC_1)
+#define RC_NV_DefineSpace_auth (TPM_RC_P + TPM_RC_1)
+#define RC_NV_DefineSpace_publicInfo (TPM_RC_P + TPM_RC_2)
+
+#define RC_NV_UndefineSpace_authHandle (TPM_RC_H + TPM_RC_1)
+#define RC_NV_UndefineSpace_nvIndex (TPM_RC_H + TPM_RC_2)
+
+#define RC_NV_Read_authHandle (TPM_RC_H + TPM_RC_1)
+#define RC_NV_Read_nvIndex (TPM_RC_H + TPM_RC_2)
+#define RC_NV_Read_size (TPM_RC_P + TPM_RC_1)
+#define RC_NV_Read_offset (TPM_RC_P + TPM_RC_2)
+
+#define RC_NV_Write_authHandle (TPM_RC_H + TPM_RC_1)
+#define RC_NV_Write_nvIndex (TPM_RC_H + TPM_RC_2)
+#define RC_NV_Write_data (TPM_RC_P + TPM_RC_1)
+#define RC_NV_Write_offset (TPM_RC_P + TPM_RC_2)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_NV_INDEX NvIndex;
+} TPM2_NV_READPUBLIC_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ TPM2B_NV_PUBLIC NvPublic;
+ TPM2B_NAME NvName;
+} TPM2_NV_READPUBLIC_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_PROVISION AuthHandle;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ TPM2B_AUTH Auth;
+ TPM2B_NV_PUBLIC NvPublic;
+} TPM2_NV_DEFINESPACE_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_NV_DEFINESPACE_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_PROVISION AuthHandle;
+ TPMI_RH_NV_INDEX NvIndex;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+} TPM2_NV_UNDEFINESPACE_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_NV_UNDEFINESPACE_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_NV_AUTH AuthHandle;
+ TPMI_RH_NV_INDEX NvIndex;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ UINT16 Size;
+ UINT16 Offset;
+} TPM2_NV_READ_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPM2B_MAX_BUFFER Data;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_NV_READ_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_NV_AUTH AuthHandle;
+ TPMI_RH_NV_INDEX NvIndex;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ TPM2B_MAX_BUFFER Data;
+ UINT16 Offset;
+} TPM2_NV_WRITE_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_NV_WRITE_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_NV_AUTH AuthHandle;
+ TPMI_RH_NV_INDEX NvIndex;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+} TPM2_NV_READLOCK_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_NV_READLOCK_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_NV_AUTH AuthHandle;
+ TPMI_RH_NV_INDEX NvIndex;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+} TPM2_NV_WRITELOCK_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_NV_WRITELOCK_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_PROVISION AuthHandle;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+} TPM2_NV_GLOBALWRITELOCK_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_NV_GLOBALWRITELOCK_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command is used to read the public area and Name of an NV Index.
+
+ @param[in] NvIndex The NV Index.
+ @param[out] NvPublic The public area of the index.
+ @param[out] NvName The Name of the nvIndex.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvReadPublic (
+ IN TPMI_RH_NV_INDEX NvIndex,
+ OUT TPM2B_NV_PUBLIC *NvPublic,
+ OUT TPM2B_NAME *NvName
+ )
+{
+ EFI_STATUS Status;
+ TPM2_NV_READPUBLIC_COMMAND SendBuffer;
+ TPM2_NV_READPUBLIC_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT16 NvPublicSize;
+ UINT16 NvNameSize;
+ UINT8 *Buffer;
+ TPM_RC ResponseCode;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadPublic);
+
+ SendBuffer.NvIndex = SwapBytes32 (NvIndex);
+
+ SendBufferSize = (UINT32) sizeof (SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ }
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ case TPM_RC_HANDLE + RC_NV_ReadPublic_nvIndex: // TPM_RC_NV_DEFINED:
+ return EFI_NOT_FOUND;
+ case TPM_RC_VALUE + RC_NV_ReadPublic_nvIndex:
+ return EFI_INVALID_PARAMETER;
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + sizeof(UINT16)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Basic check
+ //
+ NvPublicSize = SwapBytes16 (RecvBuffer.NvPublic.size);
+ if (NvPublicSize > sizeof(TPMS_NV_PUBLIC)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvPublic.size error %x\n", NvPublicSize));
+ return EFI_DEVICE_ERROR;
+ }
+
+ NvNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize)));
+ if (NvNameSize > sizeof(TPMU_NAME)){
+ DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvNameSize error %x\n", NvNameSize));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x\n", RecvBufferSize));
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Return the response
+ //
+ CopyMem (NvPublic, &RecvBuffer.NvPublic, sizeof(UINT16) + NvPublicSize);
+ NvPublic->size = NvPublicSize;
+ NvPublic->nvPublic.nvIndex = SwapBytes32 (NvPublic->nvPublic.nvIndex);
+ NvPublic->nvPublic.nameAlg = SwapBytes16 (NvPublic->nvPublic.nameAlg);
+ WriteUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes)));
+ NvPublic->nvPublic.authPolicy.size = SwapBytes16 (NvPublic->nvPublic.authPolicy.size);
+ Buffer = (UINT8 *)&RecvBuffer.NvPublic.nvPublic.authPolicy;
+ Buffer += sizeof(UINT16) + NvPublic->nvPublic.authPolicy.size;
+ NvPublic->nvPublic.dataSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+
+ CopyMem (NvName->name, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16), NvNameSize);
+ NvName->size = NvNameSize;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command defines the attributes of an NV Index and causes the TPM to
+ reserve space to hold the data associated with the index.
+ If a definition already exists at the index, the TPM will return TPM_RC_NV_DEFINED.
+
+ @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.
+ @param[in] AuthSession Auth Session context
+ @param[in] Auth The authorization data.
+ @param[in] NvPublic The public area of the index.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_ALREADY_STARTED The command was returned successfully, but NvIndex is already defined.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvDefineSpace (
+ IN TPMI_RH_PROVISION AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
+ IN TPM2B_AUTH *Auth,
+ IN TPM2B_NV_PUBLIC *NvPublic
+ )
+{
+ EFI_STATUS Status;
+ TPM2_NV_DEFINESPACE_COMMAND SendBuffer;
+ TPM2_NV_DEFINESPACE_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT16 NvPublicSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ TPM_RC ResponseCode;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_DefineSpace);
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ //
+ // IndexAuth
+ //
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Auth->size));
+ Buffer += sizeof(UINT16);
+ CopyMem(Buffer, Auth->buffer, Auth->size);
+ Buffer += Auth->size;
+
+ //
+ // NvPublic
+ //
+ NvPublicSize = NvPublic->size;
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublicSize));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (NvPublic->nvPublic.nvIndex));
+ Buffer += sizeof(UINT32);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.nameAlg));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes)));
+ Buffer += sizeof(UINT32);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.authPolicy.size));
+ Buffer += sizeof(UINT16);
+ CopyMem (Buffer, NvPublic->nvPublic.authPolicy.buffer, NvPublic->nvPublic.authPolicy.size);
+ Buffer += NvPublic->nvPublic.authPolicy.size;
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.dataSize));
+ Buffer += sizeof(UINT16);
+
+ SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ }
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ case TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo:
+ case TPM_RC_SIZE + RC_NV_DefineSpace_auth:
+ Status = EFI_BAD_BUFFER_SIZE;
+ break;
+ case TPM_RC_ATTRIBUTES:
+ case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo:
+ Status = EFI_UNSUPPORTED;
+ break;
+ case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_NV_DEFINED:
+ Status = EFI_ALREADY_STARTED;
+ break;
+ case TPM_RC_VALUE + RC_NV_DefineSpace_publicInfo:
+ case TPM_RC_VALUE + RC_NV_DefineSpace_authHandle:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_NV_SPACE:
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
+
+/**
+ This command removes an index from the TPM.
+
+ @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.
+ @param[in] NvIndex The NV Index.
+ @param[in] AuthSession Auth Session context
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvUndefineSpace (
+ IN TPMI_RH_PROVISION AuthHandle,
+ IN TPMI_RH_NV_INDEX NvIndex,
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ TPM2_NV_UNDEFINESPACE_COMMAND SendBuffer;
+ TPM2_NV_UNDEFINESPACE_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ TPM_RC ResponseCode;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_UndefineSpace);
+
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+ SendBuffer.NvIndex = SwapBytes32 (NvIndex);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ }
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ case TPM_RC_ATTRIBUTES:
+ case TPM_RC_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex:
+ Status = EFI_UNSUPPORTED;
+ break;
+ case TPM_RC_NV_AUTHORIZATION:
+ Status = EFI_SECURITY_VIOLATION;
+ break;
+ case TPM_RC_HANDLE + RC_NV_UndefineSpace_nvIndex: // TPM_RC_NV_DEFINED:
+ Status = EFI_NOT_FOUND;
+ break;
+ case TPM_RC_HANDLE + RC_NV_UndefineSpace_authHandle: // TPM_RC_NV_DEFINED:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_VALUE + RC_NV_UndefineSpace_authHandle:
+ case TPM_RC_VALUE + RC_NV_UndefineSpace_nvIndex:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
+
+/**
+ This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace().
+
+ @param[in] AuthHandle the handle indicating the source of the authorization value.
+ @param[in] NvIndex The index to be read.
+ @param[in] AuthSession Auth Session context
+ @param[in] Size Number of bytes to read.
+ @param[in] Offset Byte offset into the area.
+ @param[in,out] OutData The data read.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvRead (
+ IN TPMI_RH_NV_AUTH AuthHandle,
+ IN TPMI_RH_NV_INDEX NvIndex,
+ IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
+ IN UINT16 Size,
+ IN UINT16 Offset,
+ IN OUT TPM2B_MAX_BUFFER *OutData
+ )
+{
+ EFI_STATUS Status;
+ TPM2_NV_READ_COMMAND SendBuffer;
+ TPM2_NV_READ_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ TPM_RC ResponseCode;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Read);
+
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+ SendBuffer.NvIndex = SwapBytes32 (NvIndex);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Size));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset));
+ Buffer += sizeof(UINT16);
+
+ SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvRead - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvRead - responseCode - %x\n", ResponseCode));
+ }
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ case TPM_RC_NV_AUTHORIZATION:
+ Status = EFI_SECURITY_VIOLATION;
+ break;
+ case TPM_RC_NV_LOCKED:
+ Status = EFI_ACCESS_DENIED;
+ break;
+ case TPM_RC_NV_RANGE:
+ Status = EFI_BAD_BUFFER_SIZE;
+ break;
+ case TPM_RC_NV_UNINITIALIZED:
+ Status = EFI_NOT_READY;
+ break;
+ case TPM_RC_HANDLE + RC_NV_Read_nvIndex: // TPM_RC_NV_DEFINED:
+ Status = EFI_NOT_FOUND;
+ break;
+ case TPM_RC_HANDLE + RC_NV_Read_authHandle: // TPM_RC_NV_DEFINED:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_VALUE + RC_NV_Read_nvIndex:
+ case TPM_RC_VALUE + RC_NV_Read_authHandle:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_BAD_AUTH + RC_NV_Read_authHandle + TPM_RC_S:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_AUTH_UNAVAILABLE:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_AUTH_FAIL + RC_NV_Read_authHandle + TPM_RC_S:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_ATTRIBUTES + RC_NV_Read_authHandle + TPM_RC_S:
+ Status = EFI_UNSUPPORTED;
+ break;
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ if (Status != EFI_SUCCESS) {
+ goto Done;
+ }
+
+ //
+ // Return the response
+ //
+ OutData->size = SwapBytes16 (RecvBuffer.Data.size);
+ if (OutData->size > MAX_DIGEST_BUFFER) {
+ DEBUG ((DEBUG_ERROR, "Tpm2NvRead - OutData->size error %x\n", OutData->size));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ CopyMem (OutData->buffer, &RecvBuffer.Data.buffer, OutData->size);
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
+
+/**
+ This command writes a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace().
+
+ @param[in] AuthHandle the handle indicating the source of the authorization value.
+ @param[in] NvIndex The NV Index of the area to write.
+ @param[in] AuthSession Auth Session context
+ @param[in] InData The data to write.
+ @param[in] Offset The offset into the NV Area.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvWrite (
+ IN TPMI_RH_NV_AUTH AuthHandle,
+ IN TPMI_RH_NV_INDEX NvIndex,
+ IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
+ IN TPM2B_MAX_BUFFER *InData,
+ IN UINT16 Offset
+ )
+{
+ EFI_STATUS Status;
+ TPM2_NV_WRITE_COMMAND SendBuffer;
+ TPM2_NV_WRITE_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ TPM_RC ResponseCode;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Write);
+
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+ SendBuffer.NvIndex = SwapBytes32 (NvIndex);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (InData->size));
+ Buffer += sizeof(UINT16);
+ CopyMem (Buffer, InData->buffer, InData->size);
+ Buffer += InData->size;
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset));
+ Buffer += sizeof(UINT16);
+
+ SendBufferSize = (UINT32) (Buffer - (UINT8 *)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - responseCode - %x\n", ResponseCode));
+ }
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ case TPM_RC_ATTRIBUTES:
+ Status = EFI_UNSUPPORTED;
+ break;
+ case TPM_RC_NV_AUTHORIZATION:
+ Status = EFI_SECURITY_VIOLATION;
+ break;
+ case TPM_RC_NV_LOCKED:
+ Status = EFI_ACCESS_DENIED;
+ break;
+ case TPM_RC_NV_RANGE:
+ Status = EFI_BAD_BUFFER_SIZE;
+ break;
+ case TPM_RC_HANDLE + RC_NV_Write_nvIndex: // TPM_RC_NV_DEFINED:
+ Status = EFI_NOT_FOUND;
+ break;
+ case TPM_RC_HANDLE + RC_NV_Write_authHandle: // TPM_RC_NV_DEFINED:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_VALUE + RC_NV_Write_nvIndex:
+ case TPM_RC_VALUE + RC_NV_Write_authHandle:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_BAD_AUTH + RC_NV_Write_authHandle + TPM_RC_S:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_AUTH_UNAVAILABLE:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_AUTH_FAIL + RC_NV_Write_authHandle + TPM_RC_S:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ case TPM_RC_ATTRIBUTES + RC_NV_Write_authHandle + TPM_RC_S:
+ Status = EFI_UNSUPPORTED;
+ break;
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
+
+/**
+ This command may be used to prevent further reads of the Index until the next TPM2_Startup (TPM_SU_CLEAR).
+
+ @param[in] AuthHandle the handle indicating the source of the authorization value.
+ @param[in] NvIndex The NV Index of the area to lock.
+ @param[in] AuthSession Auth Session context
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvReadLock (
+ IN TPMI_RH_NV_AUTH AuthHandle,
+ IN TPMI_RH_NV_INDEX NvIndex,
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ TPM2_NV_READLOCK_COMMAND SendBuffer;
+ TPM2_NV_READLOCK_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ TPM_RC ResponseCode;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadLock);
+
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+ SendBuffer.NvIndex = SwapBytes32 (NvIndex);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ }
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
+
+/**
+ This command may be used to inhibit further writes of the Index.
+
+ @param[in] AuthHandle the handle indicating the source of the authorization value.
+ @param[in] NvIndex The NV Index of the area to lock.
+ @param[in] AuthSession Auth Session context
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvWriteLock (
+ IN TPMI_RH_NV_AUTH AuthHandle,
+ IN TPMI_RH_NV_INDEX NvIndex,
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ TPM2_NV_WRITELOCK_COMMAND SendBuffer;
+ TPM2_NV_WRITELOCK_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ TPM_RC ResponseCode;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_WriteLock);
+
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+ SendBuffer.NvIndex = SwapBytes32 (NvIndex);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ }
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
+
+/**
+ The command will SET TPMA_NV_WRITELOCKED for all indexes that have their TPMA_NV_GLOBALLOCK attribute SET.
+
+ @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.
+ @param[in] AuthSession Auth Session context
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvGlobalWriteLock (
+ IN TPMI_RH_PROVISION AuthHandle,
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ TPM2_NV_GLOBALWRITELOCK_COMMAND SendBuffer;
+ TPM2_NV_GLOBALWRITELOCK_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ TPM_RC ResponseCode;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_GlobalWriteLock);
+
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
+
+ SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ }
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof(SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
+ return Status;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Object.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Object.c
new file mode 100644
index 000000000..f5301f04d
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Object.c
@@ -0,0 +1,379 @@
+/** @file
+ Implement TPM2 Object related command.
+
+Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_DH_OBJECT ObjectHandle;
+} TPM2_READ_PUBLIC_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ TPM2B_PUBLIC OutPublic;
+ TPM2B_NAME Name;
+ TPM2B_NAME QualifiedName;
+} TPM2_READ_PUBLIC_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command allows access to the public area of a loaded object.
+
+ @param[in] ObjectHandle TPM handle of an object
+ @param[out] OutPublic Structure containing the public area of an object
+ @param[out] Name Name of the object
+ @param[out] QualifiedName The Qualified Name of the object
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2ReadPublic (
+ IN TPMI_DH_OBJECT ObjectHandle,
+ OUT TPM2B_PUBLIC *OutPublic,
+ OUT TPM2B_NAME *Name,
+ OUT TPM2B_NAME *QualifiedName
+ )
+{
+ EFI_STATUS Status;
+ TPM2_READ_PUBLIC_COMMAND SendBuffer;
+ TPM2_READ_PUBLIC_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ TPM_RC ResponseCode;
+ UINT8 *Buffer;
+ UINT16 OutPublicSize;
+ UINT16 NameSize;
+ UINT16 QualifiedNameSize;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_ReadPublic);
+
+ SendBuffer.ObjectHandle = SwapBytes32 (ObjectHandle);
+
+ SendBufferSize = (UINT32) sizeof (SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ }
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ case TPM_RC_SEQUENCE:
+ // objectHandle references a sequence object
+ return EFI_INVALID_PARAMETER;
+ default:
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Basic check
+ //
+ OutPublicSize = SwapBytes16 (RecvBuffer.OutPublic.size);
+ if (OutPublicSize > sizeof(TPMT_PUBLIC)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - OutPublicSize error %x\n", OutPublicSize));
+ return EFI_DEVICE_ERROR;
+ }
+
+ NameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) +
+ sizeof(UINT16) + OutPublicSize)));
+ if (NameSize > sizeof(TPMU_NAME)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - NameSize error %x\n", NameSize));
+ return EFI_DEVICE_ERROR;
+ }
+
+ QualifiedNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) +
+ sizeof(UINT16) + OutPublicSize +
+ sizeof(UINT16) + NameSize)));
+ if (QualifiedNameSize > sizeof(TPMU_NAME)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - QualifiedNameSize error %x\n", QualifiedNameSize));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + OutPublicSize + sizeof(UINT16) + NameSize + sizeof(UINT16) + QualifiedNameSize) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - RecvBufferSize %x Error - OutPublicSize %x, NameSize %x, QualifiedNameSize %x\n", RecvBufferSize, OutPublicSize, NameSize, QualifiedNameSize));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Return the response
+ //
+ Buffer = (UINT8 *)&RecvBuffer.OutPublic;
+ CopyMem (OutPublic, &RecvBuffer.OutPublic, sizeof(UINT16) + OutPublicSize);
+ OutPublic->size = OutPublicSize;
+ OutPublic->publicArea.type = SwapBytes16 (OutPublic->publicArea.type);
+ OutPublic->publicArea.nameAlg = SwapBytes16 (OutPublic->publicArea.nameAlg);
+ WriteUnaligned32 ((UINT32 *)&OutPublic->publicArea.objectAttributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&OutPublic->publicArea.objectAttributes)));
+ Buffer = (UINT8 *)&RecvBuffer.OutPublic.publicArea.authPolicy;
+ OutPublic->publicArea.authPolicy.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ if (OutPublic->publicArea.authPolicy.size > sizeof(TPMU_HA)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - authPolicy.size error %x\n", OutPublic->publicArea.authPolicy.size));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CopyMem (OutPublic->publicArea.authPolicy.buffer, Buffer, OutPublic->publicArea.authPolicy.size);
+ Buffer += OutPublic->publicArea.authPolicy.size;
+
+ // TPMU_PUBLIC_PARMS
+ switch (OutPublic->publicArea.type) {
+ case TPM_ALG_KEYEDHASH:
+ OutPublic->publicArea.parameters.keyedHashDetail.scheme.scheme = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ switch (OutPublic->publicArea.parameters.keyedHashDetail.scheme.scheme) {
+ case TPM_ALG_HMAC:
+ OutPublic->publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_XOR:
+ OutPublic->publicArea.parameters.keyedHashDetail.scheme.details.xor.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ OutPublic->publicArea.parameters.keyedHashDetail.scheme.details.xor.kdf = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ case TPM_ALG_SYMCIPHER:
+ OutPublic->publicArea.parameters.symDetail.algorithm = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ switch (OutPublic->publicArea.parameters.symDetail.algorithm) {
+ case TPM_ALG_AES:
+ OutPublic->publicArea.parameters.symDetail.keyBits.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ OutPublic->publicArea.parameters.symDetail.mode.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_SM4:
+ OutPublic->publicArea.parameters.symDetail.keyBits.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ OutPublic->publicArea.parameters.symDetail.mode.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_XOR:
+ OutPublic->publicArea.parameters.symDetail.keyBits.xor = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ break;
+ case TPM_ALG_RSA:
+ OutPublic->publicArea.parameters.rsaDetail.symmetric.algorithm = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ switch (OutPublic->publicArea.parameters.rsaDetail.symmetric.algorithm) {
+ case TPM_ALG_AES:
+ OutPublic->publicArea.parameters.rsaDetail.symmetric.keyBits.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ OutPublic->publicArea.parameters.rsaDetail.symmetric.mode.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_SM4:
+ OutPublic->publicArea.parameters.rsaDetail.symmetric.keyBits.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ OutPublic->publicArea.parameters.rsaDetail.symmetric.mode.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ OutPublic->publicArea.parameters.rsaDetail.scheme.scheme = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ switch (OutPublic->publicArea.parameters.rsaDetail.scheme.scheme) {
+ case TPM_ALG_RSASSA:
+ OutPublic->publicArea.parameters.rsaDetail.scheme.details.rsassa.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_RSAPSS:
+ OutPublic->publicArea.parameters.rsaDetail.scheme.details.rsapss.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_RSAES:
+ break;
+ case TPM_ALG_OAEP:
+ OutPublic->publicArea.parameters.rsaDetail.scheme.details.oaep.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ OutPublic->publicArea.parameters.rsaDetail.keyBits = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ OutPublic->publicArea.parameters.rsaDetail.exponent = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT32);
+ break;
+ case TPM_ALG_ECC:
+ OutPublic->publicArea.parameters.eccDetail.symmetric.algorithm = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ switch (OutPublic->publicArea.parameters.eccDetail.symmetric.algorithm) {
+ case TPM_ALG_AES:
+ OutPublic->publicArea.parameters.eccDetail.symmetric.keyBits.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ OutPublic->publicArea.parameters.eccDetail.symmetric.mode.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_SM4:
+ OutPublic->publicArea.parameters.eccDetail.symmetric.keyBits.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ OutPublic->publicArea.parameters.eccDetail.symmetric.mode.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ OutPublic->publicArea.parameters.eccDetail.scheme.scheme = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ switch (OutPublic->publicArea.parameters.eccDetail.scheme.scheme) {
+ case TPM_ALG_ECDSA:
+ OutPublic->publicArea.parameters.eccDetail.scheme.details.ecdsa.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_ECDAA:
+ OutPublic->publicArea.parameters.eccDetail.scheme.details.ecdaa.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_ECSCHNORR:
+ OutPublic->publicArea.parameters.eccDetail.scheme.details.ecSchnorr.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_ECDH:
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ OutPublic->publicArea.parameters.eccDetail.curveID = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ OutPublic->publicArea.parameters.eccDetail.kdf.scheme = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ switch (OutPublic->publicArea.parameters.eccDetail.kdf.scheme) {
+ case TPM_ALG_MGF1:
+ OutPublic->publicArea.parameters.eccDetail.kdf.details.mgf1.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_KDF1_SP800_108:
+ OutPublic->publicArea.parameters.eccDetail.kdf.details.kdf1_sp800_108.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_KDF1_SP800_56a:
+ OutPublic->publicArea.parameters.eccDetail.kdf.details.kdf1_SP800_56a.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_KDF2:
+ OutPublic->publicArea.parameters.eccDetail.kdf.details.kdf2.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ // TPMU_PUBLIC_ID
+ switch (OutPublic->publicArea.type) {
+ case TPM_ALG_KEYEDHASH:
+ OutPublic->publicArea.unique.keyedHash.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ if(OutPublic->publicArea.unique.keyedHash.size > sizeof(TPMU_HA)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - keyedHash.size error %x\n", OutPublic->publicArea.unique.keyedHash.size));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem (OutPublic->publicArea.unique.keyedHash.buffer, Buffer, OutPublic->publicArea.unique.keyedHash.size);
+ Buffer += OutPublic->publicArea.unique.keyedHash.size;
+ break;
+ case TPM_ALG_SYMCIPHER:
+ OutPublic->publicArea.unique.sym.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ if(OutPublic->publicArea.unique.sym.size > sizeof(TPMU_HA)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - sym.size error %x\n", OutPublic->publicArea.unique.sym.size));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem (OutPublic->publicArea.unique.sym.buffer, Buffer, OutPublic->publicArea.unique.sym.size);
+ Buffer += OutPublic->publicArea.unique.sym.size;
+ break;
+ case TPM_ALG_RSA:
+ OutPublic->publicArea.unique.rsa.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ if(OutPublic->publicArea.unique.rsa.size > MAX_RSA_KEY_BYTES) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - rsa.size error %x\n", OutPublic->publicArea.unique.rsa.size));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem (OutPublic->publicArea.unique.rsa.buffer, Buffer, OutPublic->publicArea.unique.rsa.size);
+ Buffer += OutPublic->publicArea.unique.rsa.size;
+ break;
+ case TPM_ALG_ECC:
+ OutPublic->publicArea.unique.ecc.x.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ if (OutPublic->publicArea.unique.ecc.x.size > MAX_ECC_KEY_BYTES) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - ecc.x.size error %x\n", OutPublic->publicArea.unique.ecc.x.size));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem (OutPublic->publicArea.unique.ecc.x.buffer, Buffer, OutPublic->publicArea.unique.ecc.x.size);
+ Buffer += OutPublic->publicArea.unique.ecc.x.size;
+ OutPublic->publicArea.unique.ecc.y.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
+ Buffer += sizeof(UINT16);
+ if (OutPublic->publicArea.unique.ecc.y.size > MAX_ECC_KEY_BYTES) {
+ DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - ecc.y.size error %x\n", OutPublic->publicArea.unique.ecc.y.size));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem (OutPublic->publicArea.unique.ecc.y.buffer, Buffer, OutPublic->publicArea.unique.ecc.y.size);
+ Buffer += OutPublic->publicArea.unique.ecc.y.size;
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ CopyMem (Name->name, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + OutPublicSize + sizeof(UINT16), NameSize);
+ Name->size = NameSize;
+
+ CopyMem (QualifiedName->name, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + OutPublicSize + sizeof(UINT16) + NameSize + sizeof(UINT16), QualifiedNameSize);
+ QualifiedName->size = QualifiedNameSize;
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c
new file mode 100644
index 000000000..201c2170f
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c
@@ -0,0 +1,512 @@
+/** @file
+ Implement TPM2 Sequences related command.
+
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPM2B_AUTH Auth;
+ TPMI_ALG_HASH HashAlg;
+} TPM2_HASH_SEQUENCE_START_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ TPMI_DH_OBJECT SequenceHandle;
+} TPM2_HASH_SEQUENCE_START_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_DH_OBJECT SequenceHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSessionSeq;
+ TPM2B_MAX_BUFFER Buffer;
+} TPM2_SEQUENCE_UPDATE_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPMS_AUTH_RESPONSE AuthSessionSeq;
+} TPM2_SEQUENCE_UPDATE_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_DH_PCR PcrHandle;
+ TPMI_DH_OBJECT SequenceHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSessionPcr;
+ TPMS_AUTH_COMMAND AuthSessionSeq;
+ TPM2B_MAX_BUFFER Buffer;
+} TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPML_DIGEST_VALUES Results;
+ TPMS_AUTH_RESPONSE AuthSessionPcr;
+ TPMS_AUTH_RESPONSE AuthSessionSeq;
+} TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_DH_OBJECT SequenceHandle;
+ UINT32 AuthorizationSize;
+ TPMS_AUTH_COMMAND AuthSessionSeq;
+ TPM2B_MAX_BUFFER Buffer;
+ TPMI_RH_HIERARCHY Hierarchy;
+} TPM2_SEQUENCE_COMPLETE_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 ParameterSize;
+ TPM2B_DIGEST Digest;
+ TPMS_AUTH_RESPONSE AuthSessionSeq;
+} TPM2_SEQUENCE_COMPLETE_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command starts a hash or an Event sequence.
+ If hashAlg is an implemented hash, then a hash sequence is started.
+ If hashAlg is TPM_ALG_NULL, then an Event sequence is started.
+
+ @param[in] HashAlg The hash algorithm to use for the hash sequence
+ An Event sequence starts if this is TPM_ALG_NULL.
+ @param[out] SequenceHandle A handle to reference the sequence
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2HashSequenceStart (
+ IN TPMI_ALG_HASH HashAlg,
+ OUT TPMI_DH_OBJECT *SequenceHandle
+ )
+{
+ EFI_STATUS Status;
+ TPM2_HASH_SEQUENCE_START_COMMAND Cmd;
+ TPM2_HASH_SEQUENCE_START_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *Buffer;
+ UINT32 ResultBufSize;
+
+ ZeroMem(&Cmd, sizeof(Cmd));
+
+ //
+ // Construct command
+ //
+ Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_HashSequenceStart);
+
+ Buffer = (UINT8 *)&Cmd.Auth;
+
+ // auth = nullAuth
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));
+ Buffer += sizeof(UINT16);
+
+ // hashAlg
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(HashAlg));
+ Buffer += sizeof(UINT16);
+
+ CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ //
+ // Call the TPM
+ //
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "HashSequenceStart: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "HashSequenceStart: Response size too large! %d\r\n", RespSize));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "HashSequenceStart: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Unmarshal the response
+ //
+
+ // sequenceHandle
+ *SequenceHandle = SwapBytes32(Res.SequenceHandle);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command is used to add data to a hash or HMAC sequence.
+ The amount of data in buffer may be any size up to the limits of the TPM.
+ NOTE: In all TPM, a buffer size of 1,024 octets is allowed.
+
+ @param[in] SequenceHandle Handle for the sequence object
+ @param[in] Buffer Data to be added to hash
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SequenceUpdate (
+ IN TPMI_DH_OBJECT SequenceHandle,
+ IN TPM2B_MAX_BUFFER *Buffer
+ )
+{
+ EFI_STATUS Status;
+ TPM2_SEQUENCE_UPDATE_COMMAND Cmd;
+ TPM2_SEQUENCE_UPDATE_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *BufferPtr;
+ UINT32 SessionInfoSize;
+ UINT32 ResultBufSize;
+
+ ZeroMem(&Cmd, sizeof(Cmd));
+
+ //
+ // Construct command
+ //
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceUpdate);
+ Cmd.SequenceHandle = SwapBytes32(SequenceHandle);
+
+ //
+ // Add in Auth session
+ //
+ BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);
+ BufferPtr += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ // buffer.size
+ WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));
+ BufferPtr += sizeof(UINT16);
+
+ CopyMem(BufferPtr, &Buffer->buffer, Buffer->size);
+ BufferPtr += Buffer->size;
+
+ CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ //
+ // Call the TPM
+ //
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd,&ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "SequenceUpdate: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "SequenceUpdate: Response size too large! %d\r\n", RespSize));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "SequenceUpdate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Unmarshal the response
+ //
+
+ // None
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command adds the last part of data, if any, to an Event sequence and returns the result in a digest list.
+ If pcrHandle references a PCR and not TPM_RH_NULL, then the returned digest list is processed in
+ the same manner as the digest list input parameter to TPM2_PCR_Extend() with the pcrHandle in each
+ bank extended with the associated digest value.
+
+ @param[in] PcrHandle PCR to be extended with the Event data
+ @param[in] SequenceHandle Authorization for the sequence
+ @param[in] Buffer Data to be added to the Event
+ @param[out] Results List of digests computed for the PCR
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2EventSequenceComplete (
+ IN TPMI_DH_PCR PcrHandle,
+ IN TPMI_DH_OBJECT SequenceHandle,
+ IN TPM2B_MAX_BUFFER *Buffer,
+ OUT TPML_DIGEST_VALUES *Results
+ )
+{
+ EFI_STATUS Status;
+ TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND Cmd;
+ TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *BufferPtr;
+ UINT32 SessionInfoSize;
+ UINT32 SessionInfoSize2;
+ UINT32 Index;
+ UINT32 ResultBufSize;
+ UINT16 DigestSize;
+
+ ZeroMem(&Cmd, sizeof(Cmd));
+
+ //
+ // Construct command
+ //
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_EventSequenceComplete);
+ Cmd.PcrHandle = SwapBytes32(PcrHandle);
+ Cmd.SequenceHandle = SwapBytes32(SequenceHandle);
+
+ //
+ // Add in pcrHandle Auth session
+ //
+ BufferPtr = (UINT8 *)&Cmd.AuthSessionPcr;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);
+ BufferPtr += SessionInfoSize;
+
+ // sessionInfoSize
+ SessionInfoSize2 = CopyAuthSessionCommand (NULL, BufferPtr);
+ BufferPtr += SessionInfoSize2;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize + SessionInfoSize2);
+
+ // buffer.size
+ WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));
+ BufferPtr += sizeof(UINT16);
+
+ CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);
+ BufferPtr += Buffer->size;
+
+ CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ //
+ // Call the TPM
+ //
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Response size too large! %d\r\n", RespSize));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Unmarshal the response
+ //
+
+ BufferPtr = (UINT8 *)&Res.Results;
+
+ // count
+ Results->count = SwapBytes32(ReadUnaligned32 ((UINT32 *)BufferPtr));
+ if (Results->count > HASH_COUNT) {
+ DEBUG ((DEBUG_ERROR, "Tpm2EventSequenceComplete - Results->count error %x\n", Results->count));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BufferPtr += sizeof(UINT32);
+
+ for (Index = 0; Index < Results->count; Index++) {
+ Results->digests[Index].hashAlg = SwapBytes16(ReadUnaligned16 ((UINT16 *)BufferPtr));
+ BufferPtr += sizeof(UINT16);
+
+ DigestSize = GetHashSizeFromAlgo (Results->digests[Index].hashAlg);
+ if (DigestSize == 0) {
+ DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Unknown hash algorithm %d\r\n", Results->digests[Index].hashAlg));
+ return EFI_DEVICE_ERROR;
+ }
+ CopyMem(
+ &Results->digests[Index].digest,
+ BufferPtr,
+ DigestSize
+ );
+ BufferPtr += DigestSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.
+
+ @param[in] SequenceHandle Authorization for the sequence
+ @param[in] Buffer Data to be added to the hash/HMAC
+ @param[out] Result The returned HMAC or digest in a sized buffer
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SequenceComplete (
+ IN TPMI_DH_OBJECT SequenceHandle,
+ IN TPM2B_MAX_BUFFER *Buffer,
+ OUT TPM2B_DIGEST *Result
+ )
+{
+ EFI_STATUS Status;
+ TPM2_SEQUENCE_COMPLETE_COMMAND Cmd;
+ TPM2_SEQUENCE_COMPLETE_RESPONSE Res;
+ UINT32 CmdSize;
+ UINT32 RespSize;
+ UINT8 *BufferPtr;
+ UINT32 SessionInfoSize;
+ UINT32 ResultBufSize;
+
+ ZeroMem(&Cmd, sizeof(Cmd));
+
+ //
+ // Construct command
+ //
+ Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceComplete);
+ Cmd.SequenceHandle = SwapBytes32(SequenceHandle);
+
+ //
+ // Add in Auth session
+ //
+ BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);
+ BufferPtr += SessionInfoSize;
+ Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
+
+ // buffer.size
+ WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));
+ BufferPtr += sizeof(UINT16);
+
+ CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);
+ BufferPtr += Buffer->size;
+
+ // Hierarchy
+ WriteUnaligned32 ((UINT32 *)BufferPtr, SwapBytes32 (TPM_RH_NULL));
+ BufferPtr += sizeof (UINT32);
+
+ CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);
+ Cmd.Header.paramSize = SwapBytes32(CmdSize);
+
+ //
+ // Call the TPM
+ //
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (ResultBufSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Validate response headers
+ //
+ RespSize = SwapBytes32(Res.Header.paramSize);
+ if (RespSize > sizeof(Res)) {
+ DEBUG ((EFI_D_ERROR, "SequenceComplete: Response size too large! %d\r\n", RespSize));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Fail if command failed
+ //
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "SequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Unmarshal the response
+ //
+
+ BufferPtr = (UINT8 *)&Res.Digest;
+
+ // digestSize
+ Result->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)BufferPtr));
+ if (Result->size > sizeof(TPMU_HA)){
+ DEBUG ((DEBUG_ERROR, "Tpm2SequenceComplete - Result->size error %x\n", Result->size));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BufferPtr += sizeof(UINT16);
+
+ CopyMem(
+ Result->buffer,
+ BufferPtr,
+ Result->size
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Session.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Session.c
new file mode 100644
index 000000000..57367432d
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Session.c
@@ -0,0 +1,168 @@
+/** @file
+ Implement TPM2 Session related command.
+
+Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_DH_OBJECT TpmKey;
+ TPMI_DH_ENTITY Bind;
+ TPM2B_NONCE NonceCaller;
+ TPM2B_ENCRYPTED_SECRET Salt;
+ TPM_SE SessionType;
+ TPMT_SYM_DEF Symmetric;
+ TPMI_ALG_HASH AuthHash;
+} TPM2_START_AUTH_SESSION_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ TPMI_SH_AUTH_SESSION SessionHandle;
+ TPM2B_NONCE NonceTPM;
+} TPM2_START_AUTH_SESSION_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command is used to start an authorization session using alternative methods of
+ establishing the session key (sessionKey) that is used for authorization and encrypting value.
+
+ @param[in] TpmKey Handle of a loaded decrypt key used to encrypt salt.
+ @param[in] Bind Entity providing the authValue.
+ @param[in] NonceCaller Initial nonceCaller, sets nonce size for the session.
+ @param[in] Salt Value encrypted according to the type of tpmKey.
+ @param[in] SessionType Indicates the type of the session.
+ @param[in] Symmetric The algorithm and key size for parameter encryption.
+ @param[in] AuthHash Hash algorithm to use for the session.
+ @param[out] SessionHandle Handle for the newly created session.
+ @param[out] NonceTPM The initial nonce from the TPM, used in the computation of the sessionKey.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2StartAuthSession (
+ IN TPMI_DH_OBJECT TpmKey,
+ IN TPMI_DH_ENTITY Bind,
+ IN TPM2B_NONCE *NonceCaller,
+ IN TPM2B_ENCRYPTED_SECRET *Salt,
+ IN TPM_SE SessionType,
+ IN TPMT_SYM_DEF *Symmetric,
+ IN TPMI_ALG_HASH AuthHash,
+ OUT TPMI_SH_AUTH_SESSION *SessionHandle,
+ OUT TPM2B_NONCE *NonceTPM
+ )
+{
+ EFI_STATUS Status;
+ TPM2_START_AUTH_SESSION_COMMAND SendBuffer;
+ TPM2_START_AUTH_SESSION_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_StartAuthSession);
+
+ SendBuffer.TpmKey = SwapBytes32 (TpmKey);
+ SendBuffer.Bind = SwapBytes32 (Bind);
+ Buffer = (UINT8 *)&SendBuffer.NonceCaller;
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NonceCaller->size));
+ Buffer += sizeof(UINT16);
+ CopyMem (Buffer, NonceCaller->buffer, NonceCaller->size);
+ Buffer += NonceCaller->size;
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Salt->size));
+ Buffer += sizeof(UINT16);
+ CopyMem (Buffer, Salt->secret, Salt->size);
+ Buffer += Salt->size;
+
+ *(TPM_SE *)Buffer = SessionType;
+ Buffer++;
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->algorithm));
+ Buffer += sizeof(UINT16);
+ switch (Symmetric->algorithm) {
+ case TPM_ALG_NULL:
+ break;
+ case TPM_ALG_AES:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.aes));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.aes));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_SM4:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.SM4));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.SM4));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_SYMCIPHER:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.sym));
+ Buffer += sizeof(UINT16);
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.sym));
+ Buffer += sizeof(UINT16);
+ break;
+ case TPM_ALG_XOR:
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.xor));
+ Buffer += sizeof(UINT16);
+ break;
+ default:
+ ASSERT (FALSE);
+ DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - Symmetric->algorithm - %x\n", Symmetric->algorithm));
+ return EFI_UNSUPPORTED;
+ }
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthHash));
+ Buffer += sizeof(UINT16);
+
+ SendBufferSize = (UINT32) ((UINTN)Buffer - (UINTN)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - RecvBufferSize Error - %x\n", RecvBufferSize));
+ return EFI_DEVICE_ERROR;
+ }
+ if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Return the response
+ //
+ *SessionHandle = SwapBytes32 (RecvBuffer.SessionHandle);
+ NonceTPM->size = SwapBytes16 (RecvBuffer.NonceTPM.size);
+ if (NonceTPM->size > sizeof(TPMU_HA)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - NonceTPM->size error %x\n", NonceTPM->size));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CopyMem (NonceTPM->buffer, &RecvBuffer.NonceTPM.buffer, NonceTPM->size);
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c
new file mode 100644
index 000000000..41f2367ba
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c
@@ -0,0 +1,121 @@
+/** @file
+ Implement TPM2 Startup related command.
+
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved. <BR>
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPM_SU StartupType;
+} TPM2_STARTUP_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+} TPM2_STARTUP_RESPONSE;
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPM_SU ShutdownType;
+} TPM2_SHUTDOWN_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+} TPM2_SHUTDOWN_RESPONSE;
+
+#pragma pack()
+
+/**
+ Send Startup command to TPM2.
+
+ @param[in] StartupType TPM_SU_CLEAR or TPM_SU_STATE
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2Startup (
+ IN TPM_SU StartupType
+ )
+{
+ EFI_STATUS Status;
+ TPM2_STARTUP_COMMAND Cmd;
+ TPM2_STARTUP_RESPONSE Res;
+ UINT32 ResultBufSize;
+ TPM_RC ResponseCode;
+
+ Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd));
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_Startup);
+ Cmd.StartupType = SwapBytes16(StartupType);
+
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (sizeof(Cmd), (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ ResponseCode = SwapBytes32(Res.Header.responseCode);
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ DEBUG ((DEBUG_INFO, "TPM2Startup: TPM_RC_SUCCESS\n"));
+ return EFI_SUCCESS;
+ case TPM_RC_INITIALIZE:
+ // TPM_RC_INITIALIZE can be returned if Tpm2Startup is not required.
+ DEBUG ((DEBUG_INFO, "TPM2Startup: TPM_RC_INITIALIZE\n"));
+ return EFI_SUCCESS;
+ default:
+ DEBUG ((EFI_D_ERROR, "Tpm2Startup: Response Code error! 0x%08x\r\n", ResponseCode));
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+/**
+ Send Shutdown command to TPM2.
+
+ @param[in] ShutdownType TPM_SU_CLEAR or TPM_SU_STATE.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2Shutdown (
+ IN TPM_SU ShutdownType
+ )
+{
+ EFI_STATUS Status;
+ TPM2_SHUTDOWN_COMMAND Cmd;
+ TPM2_SHUTDOWN_RESPONSE Res;
+ UINT32 ResultBufSize;
+
+ Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd));
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_Shutdown);
+ Cmd.ShutdownType = SwapBytes16(ShutdownType);
+
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (sizeof(Cmd), (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Tpm2Shutdown: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Test.c b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Test.c
new file mode 100644
index 000000000..78f8feba8
--- /dev/null
+++ b/roms/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Test.c
@@ -0,0 +1,60 @@
+/** @file
+ Implement TPM2 Test related command.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_YES_NO FullTest;
+} TPM2_SELF_TEST_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+} TPM2_SELF_TEST_RESPONSE;
+
+#pragma pack()
+
+/**
+ This command causes the TPM to perform a test of its capabilities.
+ If the fullTest is YES, the TPM will test all functions.
+ If fullTest = NO, the TPM will only test those functions that have not previously been tested.
+
+ @param[in] FullTest YES if full test to be performed
+ NO if only test of untested functions required
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SelfTest (
+ IN TPMI_YES_NO FullTest
+ )
+{
+ EFI_STATUS Status;
+ TPM2_SELF_TEST_COMMAND Cmd;
+ TPM2_SELF_TEST_RESPONSE Res;
+ UINT32 ResultBufSize;
+
+ Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
+ Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd));
+ Cmd.Header.commandCode = SwapBytes32(TPM_CC_SelfTest);
+ Cmd.FullTest = FullTest;
+
+ ResultBufSize = sizeof(Res);
+ Status = Tpm2SubmitCommand (sizeof(Cmd), (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
+
+ return Status;
+}