diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c | 889 |
1 files changed, 889 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c new file mode 100644 index 00000000..d33540fb --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/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; +} |