REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the SecurityPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
		
			
				
	
	
		
			924 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			924 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @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 ((DEBUG_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;
 | |
|   UINT8               ActivePcrBankCount;
 | |
| 
 | |
|   //
 | |
|   // Get supported PCR
 | |
|   //
 | |
|   Status = Tpm2GetCapabilityPcrs (&Pcrs);
 | |
|   DEBUG ((DEBUG_INFO, "Supported PCRs - Count = %08x\n", Pcrs.count));
 | |
|   ActivePcrBankCount = 0;
 | |
|   //
 | |
|   // If error, assume that we have at least SHA-1 (and return the error.)
 | |
|   //
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "GetSupportedAndActivePcrs - Tpm2GetCapabilityPcrs fail!\n"));
 | |
|     *TpmHashAlgorithmBitmap = HASH_ALG_SHA1;
 | |
|     *ActivePcrBanks         = HASH_ALG_SHA1;
 | |
|     ActivePcrBankCount      = 1;
 | |
|   }
 | |
|   //
 | |
|   // Otherwise, process the return data to determine what algorithms are supported
 | |
|   // and currently allocated.
 | |
|   //
 | |
|   else {
 | |
|     *TpmHashAlgorithmBitmap = 0;
 | |
|     *ActivePcrBanks         = 0;
 | |
|     for (Index = 0; Index < Pcrs.count; Index++) {
 | |
|       switch (Pcrs.pcrSelections[Index].hash) {
 | |
|         case TPM_ALG_SHA1:
 | |
|           DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA1 present.\n"));
 | |
|           *TpmHashAlgorithmBitmap |= HASH_ALG_SHA1;
 | |
|           if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
 | |
|             DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA1 active.\n"));
 | |
|             *ActivePcrBanks |= HASH_ALG_SHA1;
 | |
|             ActivePcrBankCount++;
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         case TPM_ALG_SHA256:
 | |
|           DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA256 present.\n"));
 | |
|           *TpmHashAlgorithmBitmap |= HASH_ALG_SHA256;
 | |
|           if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
 | |
|             DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA256 active.\n"));
 | |
|             *ActivePcrBanks |= HASH_ALG_SHA256;
 | |
|             ActivePcrBankCount++;
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         case TPM_ALG_SHA384:
 | |
|           DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA384 present.\n"));
 | |
|           *TpmHashAlgorithmBitmap |= HASH_ALG_SHA384;
 | |
|           if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
 | |
|             DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA384 active.\n"));
 | |
|             *ActivePcrBanks |= HASH_ALG_SHA384;
 | |
|             ActivePcrBankCount++;
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         case TPM_ALG_SHA512:
 | |
|           DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA512 present.\n"));
 | |
|           *TpmHashAlgorithmBitmap |= HASH_ALG_SHA512;
 | |
|           if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
 | |
|             DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA512 active.\n"));
 | |
|             *ActivePcrBanks |= HASH_ALG_SHA512;
 | |
|             ActivePcrBankCount++;
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         case TPM_ALG_SM3_256:
 | |
|           DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SM3_256 present.\n"));
 | |
|           *TpmHashAlgorithmBitmap |= HASH_ALG_SM3_256;
 | |
|           if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
 | |
|             DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SM3_256 active.\n"));
 | |
|             *ActivePcrBanks |= HASH_ALG_SM3_256;
 | |
|             ActivePcrBankCount++;
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         default:
 | |
|           DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - Unsupported bank 0x%04x.\n", Pcrs.pcrSelections[Index].hash));
 | |
|           continue;
 | |
|           break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "GetSupportedAndActivePcrs - Count = %08x\n", ActivePcrBankCount));
 | |
|   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 ((DEBUG_ERROR, "Tpm2TestParms - RecvBufferSize Error - %x\n", RecvBufferSize));
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   if (SwapBytes32 (RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
 | |
|     DEBUG ((DEBUG_ERROR, "Tpm2TestParms - responseCode - %x\n", SwapBytes32 (RecvBuffer.Header.responseCode)));
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |