Home | History | Annotate | Download | only in Tpm2CommandLib
      1 /** @file
      2   Implement TPM2 Capability related command.
      3 
      4 Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include <IndustryStandard/UefiTcgPlatform.h>
     16 #include <Library/Tpm2CommandLib.h>
     17 #include <Library/Tpm2DeviceLib.h>
     18 #include <Library/BaseMemoryLib.h>
     19 #include <Library/BaseLib.h>
     20 #include <Library/DebugLib.h>
     21 
     22 #pragma pack(1)
     23 
     24 typedef struct {
     25   TPM2_COMMAND_HEADER       Header;
     26   TPM_CAP                   Capability;
     27   UINT32                    Property;
     28   UINT32                    PropertyCount;
     29 } TPM2_GET_CAPABILITY_COMMAND;
     30 
     31 typedef struct {
     32   TPM2_RESPONSE_HEADER      Header;
     33   TPMI_YES_NO               MoreData;
     34   TPMS_CAPABILITY_DATA      CapabilityData;
     35 } TPM2_GET_CAPABILITY_RESPONSE;
     36 
     37 typedef struct {
     38   TPM2_COMMAND_HEADER       Header;
     39   TPMT_PUBLIC_PARMS         Parameters;
     40 } TPM2_TEST_PARMS_COMMAND;
     41 
     42 typedef struct {
     43   TPM2_RESPONSE_HEADER       Header;
     44 } TPM2_TEST_PARMS_RESPONSE;
     45 
     46 #pragma pack()
     47 
     48 /**
     49   This command returns various information regarding the TPM and its current state.
     50 
     51   The capability parameter determines the category of data returned. The property parameter
     52   selects the first value of the selected category to be returned. If there is no property
     53   that corresponds to the value of property, the next higher value is returned, if it exists.
     54   The moreData parameter will have a value of YES if there are more values of the requested
     55   type that were not returned.
     56   If no next capability exists, the TPM will return a zero-length list and moreData will have
     57   a value of NO.
     58 
     59   NOTE:
     60   To simplify this function, leave returned CapabilityData for caller to unpack since there are
     61   many capability categories and only few categories will be used in firmware. It means the caller
     62   need swap the byte order for the feilds in CapabilityData.
     63 
     64   @param[in]  Capability         Group selection; determines the format of the response.
     65   @param[in]  Property           Further definition of information.
     66   @param[in]  PropertyCount      Number of properties of the indicated type to return.
     67   @param[out] MoreData           Flag to indicate if there are more values of this type.
     68   @param[out] CapabilityData     The capability data.
     69 
     70   @retval EFI_SUCCESS            Operation completed successfully.
     71   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
     72 **/
     73 EFI_STATUS
     74 EFIAPI
     75 Tpm2GetCapability (
     76   IN      TPM_CAP                   Capability,
     77   IN      UINT32                    Property,
     78   IN      UINT32                    PropertyCount,
     79   OUT     TPMI_YES_NO               *MoreData,
     80   OUT     TPMS_CAPABILITY_DATA      *CapabilityData
     81   )
     82 {
     83   EFI_STATUS                        Status;
     84   TPM2_GET_CAPABILITY_COMMAND       SendBuffer;
     85   TPM2_GET_CAPABILITY_RESPONSE      RecvBuffer;
     86   UINT32                            SendBufferSize;
     87   UINT32                            RecvBufferSize;
     88 
     89   //
     90   // Construct command
     91   //
     92   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
     93   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_GetCapability);
     94 
     95   SendBuffer.Capability = SwapBytes32 (Capability);
     96   SendBuffer.Property = SwapBytes32 (Property);
     97   SendBuffer.PropertyCount = SwapBytes32 (PropertyCount);
     98 
     99   SendBufferSize = (UINT32) sizeof (SendBuffer);
    100   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
    101 
    102   //
    103   // send Tpm command
    104   //
    105   RecvBufferSize = sizeof (RecvBuffer);
    106   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer );
    107   if (EFI_ERROR (Status)) {
    108     return Status;
    109   }
    110 
    111   if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT8)) {
    112     return EFI_DEVICE_ERROR;
    113   }
    114 
    115   //
    116   // Return the response
    117   //
    118   *MoreData = RecvBuffer.MoreData;
    119   //
    120   // Does not unpack all possiable property here, the caller should unpack it and note the byte order.
    121   //
    122   CopyMem (CapabilityData, &RecvBuffer.CapabilityData, RecvBufferSize - sizeof (TPM2_RESPONSE_HEADER) - sizeof (UINT8));
    123 
    124   return EFI_SUCCESS;
    125 }
    126 
    127 /**
    128   This command returns the information of TPM Family.
    129 
    130   This function parse the value got from TPM2_GetCapability and return the Family.
    131 
    132   @param[out] Family             The Family of TPM. (a 4-octet character string)
    133 
    134   @retval EFI_SUCCESS            Operation completed successfully.
    135   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    136 **/
    137 EFI_STATUS
    138 EFIAPI
    139 Tpm2GetCapabilityFamily (
    140   OUT     CHAR8                     *Family
    141   )
    142 {
    143   TPMS_CAPABILITY_DATA    TpmCap;
    144   TPMI_YES_NO             MoreData;
    145   EFI_STATUS              Status;
    146 
    147   Status = Tpm2GetCapability (
    148              TPM_CAP_TPM_PROPERTIES,
    149              TPM_PT_FAMILY_INDICATOR,
    150              1,
    151              &MoreData,
    152              &TpmCap
    153              );
    154   if (EFI_ERROR (Status)) {
    155     return Status;
    156   }
    157   CopyMem (Family, &TpmCap.data.tpmProperties.tpmProperty->value, 4);
    158 
    159   return EFI_SUCCESS;
    160 }
    161 
    162 /**
    163   This command returns the information of TPM manufacture ID.
    164 
    165   This function parse the value got from TPM2_GetCapability and return the TPM manufacture ID.
    166 
    167   @param[out] ManufactureId      The manufacture ID of TPM.
    168 
    169   @retval EFI_SUCCESS            Operation completed successfully.
    170   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    171 **/
    172 EFI_STATUS
    173 EFIAPI
    174 Tpm2GetCapabilityManufactureID (
    175   OUT     UINT32                    *ManufactureId
    176   )
    177 {
    178   TPMS_CAPABILITY_DATA    TpmCap;
    179   TPMI_YES_NO             MoreData;
    180   EFI_STATUS              Status;
    181 
    182   Status = Tpm2GetCapability (
    183              TPM_CAP_TPM_PROPERTIES,
    184              TPM_PT_MANUFACTURER,
    185              1,
    186              &MoreData,
    187              &TpmCap
    188              );
    189   if (EFI_ERROR (Status)) {
    190     return Status;
    191   }
    192   *ManufactureId = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
    193 
    194   return EFI_SUCCESS;
    195 }
    196 
    197 /**
    198   This command returns the information of TPM FirmwareVersion.
    199 
    200   This function parse the value got from TPM2_GetCapability and return the TPM FirmwareVersion.
    201 
    202   @param[out] FirmwareVersion1   The FirmwareVersion1.
    203   @param[out] FirmwareVersion2   The FirmwareVersion2.
    204 
    205   @retval EFI_SUCCESS            Operation completed successfully.
    206   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    207 **/
    208 EFI_STATUS
    209 EFIAPI
    210 Tpm2GetCapabilityFirmwareVersion (
    211   OUT     UINT32                    *FirmwareVersion1,
    212   OUT     UINT32                    *FirmwareVersion2
    213   )
    214 {
    215   TPMS_CAPABILITY_DATA    TpmCap;
    216   TPMI_YES_NO             MoreData;
    217   EFI_STATUS              Status;
    218 
    219   Status = Tpm2GetCapability (
    220              TPM_CAP_TPM_PROPERTIES,
    221              TPM_PT_FIRMWARE_VERSION_1,
    222              1,
    223              &MoreData,
    224              &TpmCap
    225              );
    226   if (EFI_ERROR (Status)) {
    227     return Status;
    228   }
    229   *FirmwareVersion1 = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
    230 
    231   Status = Tpm2GetCapability (
    232              TPM_CAP_TPM_PROPERTIES,
    233              TPM_PT_FIRMWARE_VERSION_2,
    234              1,
    235              &MoreData,
    236              &TpmCap
    237              );
    238   if (EFI_ERROR (Status)) {
    239     return Status;
    240   }
    241   *FirmwareVersion2 = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
    242 
    243   return EFI_SUCCESS;
    244 }
    245 
    246 /**
    247   This command returns the information of the maximum value for commandSize and responseSize in a command.
    248 
    249   This function parse the value got from TPM2_GetCapability and return the max command size and response size
    250 
    251   @param[out] MaxCommandSize     The maximum value for commandSize in a command.
    252   @param[out] MaxResponseSize    The maximum value for responseSize in a command.
    253 
    254   @retval EFI_SUCCESS            Operation completed successfully.
    255   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    256 **/
    257 EFI_STATUS
    258 EFIAPI
    259 Tpm2GetCapabilityMaxCommandResponseSize (
    260   OUT UINT32                    *MaxCommandSize,
    261   OUT UINT32                    *MaxResponseSize
    262   )
    263 {
    264   TPMS_CAPABILITY_DATA    TpmCap;
    265   TPMI_YES_NO             MoreData;
    266   EFI_STATUS              Status;
    267 
    268   Status = Tpm2GetCapability (
    269              TPM_CAP_TPM_PROPERTIES,
    270              TPM_PT_MAX_COMMAND_SIZE,
    271              1,
    272              &MoreData,
    273              &TpmCap
    274              );
    275   if (EFI_ERROR (Status)) {
    276     return Status;
    277   }
    278 
    279   *MaxCommandSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
    280 
    281   Status = Tpm2GetCapability (
    282              TPM_CAP_TPM_PROPERTIES,
    283              TPM_PT_MAX_RESPONSE_SIZE,
    284              1,
    285              &MoreData,
    286              &TpmCap
    287              );
    288   if (EFI_ERROR (Status)) {
    289     return Status;
    290   }
    291 
    292   *MaxResponseSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
    293   return EFI_SUCCESS;
    294 }
    295 
    296 /**
    297   This command returns Returns a list of TPMS_ALG_PROPERTIES. Each entry is an
    298   algorithm ID and a set of properties of the algorithm.
    299 
    300   This function parse the value got from TPM2_GetCapability and return the list.
    301 
    302   @param[out] AlgList      List of algorithm.
    303 
    304   @retval EFI_SUCCESS            Operation completed successfully.
    305   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    306 **/
    307 EFI_STATUS
    308 EFIAPI
    309 Tpm2GetCapabilitySupportedAlg (
    310   OUT TPML_ALG_PROPERTY      *AlgList
    311   )
    312 {
    313   TPMS_CAPABILITY_DATA    TpmCap;
    314   TPMI_YES_NO             MoreData;
    315   UINTN                   Index;
    316   EFI_STATUS              Status;
    317 
    318   Status = Tpm2GetCapability (
    319              TPM_CAP_ALGS,
    320              1,
    321              MAX_CAP_ALGS,
    322              &MoreData,
    323              &TpmCap
    324              );
    325   if (EFI_ERROR (Status)) {
    326     return Status;
    327   }
    328 
    329   CopyMem (AlgList, &TpmCap.data.algorithms, sizeof (TPML_ALG_PROPERTY));
    330 
    331   AlgList->count = SwapBytes32 (AlgList->count);
    332   for (Index = 0; Index < AlgList->count; Index++) {
    333     AlgList->algProperties[Index].alg = SwapBytes16 (AlgList->algProperties[Index].alg);
    334     WriteUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties)));
    335   }
    336 
    337   return EFI_SUCCESS;
    338 }
    339 
    340 /**
    341   This command returns the information of TPM LockoutCounter.
    342 
    343   This function parse the value got from TPM2_GetCapability and return the LockoutCounter.
    344 
    345   @param[out] LockoutCounter     The LockoutCounter of TPM.
    346 
    347   @retval EFI_SUCCESS            Operation completed successfully.
    348   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    349 **/
    350 EFI_STATUS
    351 EFIAPI
    352 Tpm2GetCapabilityLockoutCounter (
    353   OUT     UINT32                    *LockoutCounter
    354   )
    355 {
    356   TPMS_CAPABILITY_DATA    TpmCap;
    357   TPMI_YES_NO             MoreData;
    358   EFI_STATUS              Status;
    359 
    360   Status = Tpm2GetCapability (
    361              TPM_CAP_TPM_PROPERTIES,
    362              TPM_PT_LOCKOUT_COUNTER,
    363              1,
    364              &MoreData,
    365              &TpmCap
    366              );
    367   if (EFI_ERROR (Status)) {
    368     return Status;
    369   }
    370   *LockoutCounter = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
    371 
    372   return EFI_SUCCESS;
    373 }
    374 
    375 /**
    376   This command returns the information of TPM LockoutInterval.
    377 
    378   This function parse the value got from TPM2_GetCapability and return the LockoutInterval.
    379 
    380   @param[out] LockoutInterval    The LockoutInterval of TPM.
    381 
    382   @retval EFI_SUCCESS            Operation completed successfully.
    383   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    384 **/
    385 EFI_STATUS
    386 EFIAPI
    387 Tpm2GetCapabilityLockoutInterval (
    388   OUT     UINT32                    *LockoutInterval
    389   )
    390 {
    391   TPMS_CAPABILITY_DATA    TpmCap;
    392   TPMI_YES_NO             MoreData;
    393   EFI_STATUS              Status;
    394 
    395   Status = Tpm2GetCapability (
    396              TPM_CAP_TPM_PROPERTIES,
    397              TPM_PT_LOCKOUT_INTERVAL,
    398              1,
    399              &MoreData,
    400              &TpmCap
    401              );
    402   if (EFI_ERROR (Status)) {
    403     return Status;
    404   }
    405   *LockoutInterval = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
    406 
    407   return EFI_SUCCESS;
    408 }
    409 
    410 /**
    411   This command returns the information of TPM InputBufferSize.
    412 
    413   This function parse the value got from TPM2_GetCapability and return the InputBufferSize.
    414 
    415   @param[out] InputBufferSize    The InputBufferSize of TPM.
    416                                  the maximum size of a parameter (typically, a TPM2B_MAX_BUFFER)
    417 
    418   @retval EFI_SUCCESS            Operation completed successfully.
    419   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    420 **/
    421 EFI_STATUS
    422 EFIAPI
    423 Tpm2GetCapabilityInputBufferSize (
    424   OUT     UINT32                    *InputBufferSize
    425   )
    426 {
    427   TPMS_CAPABILITY_DATA    TpmCap;
    428   TPMI_YES_NO             MoreData;
    429   EFI_STATUS              Status;
    430 
    431   Status = Tpm2GetCapability (
    432              TPM_CAP_TPM_PROPERTIES,
    433              TPM_PT_INPUT_BUFFER,
    434              1,
    435              &MoreData,
    436              &TpmCap
    437              );
    438   if (EFI_ERROR (Status)) {
    439     return Status;
    440   }
    441   *InputBufferSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
    442 
    443   return EFI_SUCCESS;
    444 }
    445 
    446 /**
    447   This command returns the information of TPM PCRs.
    448 
    449   This function parse the value got from TPM2_GetCapability and return the PcrSelection.
    450 
    451   @param[out] Pcrs    The Pcr Selection
    452 
    453   @retval EFI_SUCCESS            Operation completed successfully.
    454   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    455 **/
    456 EFI_STATUS
    457 EFIAPI
    458 Tpm2GetCapabilityPcrs (
    459   OUT TPML_PCR_SELECTION      *Pcrs
    460   )
    461 {
    462   TPMS_CAPABILITY_DATA    TpmCap;
    463   TPMI_YES_NO             MoreData;
    464   EFI_STATUS              Status;
    465   UINTN                   Index;
    466 
    467   Status = Tpm2GetCapability (
    468              TPM_CAP_PCRS,
    469              0,
    470              1,
    471              &MoreData,
    472              &TpmCap
    473              );
    474   if (EFI_ERROR (Status)) {
    475     return Status;
    476   }
    477 
    478   Pcrs->count = SwapBytes32 (TpmCap.data.assignedPCR.count);
    479   for (Index = 0; Index < Pcrs->count; Index++) {
    480     Pcrs->pcrSelections[Index].hash = SwapBytes16 (TpmCap.data.assignedPCR.pcrSelections[Index].hash);
    481     Pcrs->pcrSelections[Index].sizeofSelect = TpmCap.data.assignedPCR.pcrSelections[Index].sizeofSelect;
    482     CopyMem (Pcrs->pcrSelections[Index].pcrSelect, TpmCap.data.assignedPCR.pcrSelections[Index].pcrSelect, Pcrs->pcrSelections[Index].sizeofSelect);
    483   }
    484 
    485   return EFI_SUCCESS;
    486 }
    487 
    488 /**
    489   This command returns the information of TPM AlgorithmSet.
    490 
    491   This function parse the value got from TPM2_GetCapability and return the AlgorithmSet.
    492 
    493   @param[out] AlgorithmSet    The AlgorithmSet of TPM.
    494 
    495   @retval EFI_SUCCESS            Operation completed successfully.
    496   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    497 **/
    498 EFI_STATUS
    499 EFIAPI
    500 Tpm2GetCapabilityAlgorithmSet (
    501   OUT     UINT32      *AlgorithmSet
    502   )
    503 {
    504   TPMS_CAPABILITY_DATA    TpmCap;
    505   TPMI_YES_NO             MoreData;
    506   EFI_STATUS              Status;
    507 
    508   Status = Tpm2GetCapability (
    509              TPM_CAP_TPM_PROPERTIES,
    510              TPM_PT_ALGORITHM_SET,
    511              1,
    512              &MoreData,
    513              &TpmCap
    514              );
    515   if (EFI_ERROR (Status)) {
    516     return Status;
    517   }
    518   *AlgorithmSet = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
    519 
    520   return EFI_SUCCESS;
    521 }
    522 
    523 /**
    524   This command is used to check to see if specific combinations of algorithm parameters are supported.
    525 
    526   @param[in]  Parameters              Algorithm parameters to be validated
    527 
    528   @retval EFI_SUCCESS      Operation completed successfully.
    529   @retval EFI_DEVICE_ERROR Unexpected device behavior.
    530 **/
    531 EFI_STATUS
    532 EFIAPI
    533 Tpm2TestParms (
    534   IN  TPMT_PUBLIC_PARMS           *Parameters
    535   )
    536 {
    537   EFI_STATUS                        Status;
    538   TPM2_TEST_PARMS_COMMAND           SendBuffer;
    539   TPM2_TEST_PARMS_RESPONSE          RecvBuffer;
    540   UINT32                            SendBufferSize;
    541   UINT32                            RecvBufferSize;
    542   UINT8                             *Buffer;
    543 
    544   //
    545   // Construct command
    546   //
    547   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
    548   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_TestParms);
    549 
    550   Buffer = (UINT8 *)&SendBuffer.Parameters;
    551   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->type));
    552   Buffer += sizeof(UINT16);
    553   switch (Parameters->type) {
    554   case TPM_ALG_KEYEDHASH:
    555     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.scheme));
    556     Buffer += sizeof(UINT16);
    557     switch (Parameters->parameters.keyedHashDetail.scheme.scheme) {
    558     case TPM_ALG_HMAC:
    559       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.hmac.hashAlg));
    560       Buffer += sizeof(UINT16);
    561       break;
    562     case TPM_ALG_XOR:
    563       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.hashAlg));
    564       Buffer += sizeof(UINT16);
    565       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.kdf));
    566       Buffer += sizeof(UINT16);
    567       break;
    568     default:
    569       return EFI_INVALID_PARAMETER;
    570     }
    571   case TPM_ALG_SYMCIPHER:
    572     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.algorithm));
    573     Buffer += sizeof(UINT16);
    574     switch (Parameters->parameters.symDetail.algorithm) {
    575     case TPM_ALG_AES:
    576       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.aes));
    577       Buffer += sizeof(UINT16);
    578       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.aes));
    579       Buffer += sizeof(UINT16);
    580       break;
    581     case TPM_ALG_SM4:
    582       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.SM4));
    583       Buffer += sizeof(UINT16);
    584       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.SM4));
    585       Buffer += sizeof(UINT16);
    586       break;
    587     case TPM_ALG_XOR:
    588       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.xor));
    589       Buffer += sizeof(UINT16);
    590       break;
    591     case TPM_ALG_NULL:
    592       break;
    593     default:
    594       return EFI_INVALID_PARAMETER;
    595     }
    596     break;
    597   case TPM_ALG_RSA:
    598     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.algorithm));
    599     Buffer += sizeof(UINT16);
    600     switch (Parameters->parameters.rsaDetail.symmetric.algorithm) {
    601     case TPM_ALG_AES:
    602       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.aes));
    603       Buffer += sizeof(UINT16);
    604       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.aes));
    605       Buffer += sizeof(UINT16);
    606       break;
    607     case TPM_ALG_SM4:
    608       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.SM4));
    609       Buffer += sizeof(UINT16);
    610       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.SM4));
    611       Buffer += sizeof(UINT16);
    612       break;
    613     case TPM_ALG_NULL:
    614       break;
    615     default:
    616       return EFI_INVALID_PARAMETER;
    617     }
    618     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.scheme));
    619     Buffer += sizeof(UINT16);
    620     switch (Parameters->parameters.rsaDetail.scheme.scheme) {
    621     case TPM_ALG_RSASSA:
    622       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsassa.hashAlg));
    623       Buffer += sizeof(UINT16);
    624       break;
    625     case TPM_ALG_RSAPSS:
    626       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsapss.hashAlg));
    627       Buffer += sizeof(UINT16);
    628       break;
    629     case TPM_ALG_RSAES:
    630       break;
    631     case TPM_ALG_OAEP:
    632       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.oaep.hashAlg));
    633       Buffer += sizeof(UINT16);
    634       break;
    635     case TPM_ALG_NULL:
    636       break;
    637     default:
    638       return EFI_INVALID_PARAMETER;
    639     }
    640     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.keyBits));
    641     Buffer += sizeof(UINT16);
    642     WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Parameters->parameters.rsaDetail.exponent));
    643     Buffer += sizeof(UINT32);
    644     break;
    645   case TPM_ALG_ECC:
    646     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.algorithm));
    647     Buffer += sizeof(UINT16);
    648     switch (Parameters->parameters.eccDetail.symmetric.algorithm) {
    649     case TPM_ALG_AES:
    650       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.aes));
    651       Buffer += sizeof(UINT16);
    652       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.aes));
    653       Buffer += sizeof(UINT16);
    654       break;
    655     case TPM_ALG_SM4:
    656       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.SM4));
    657       Buffer += sizeof(UINT16);
    658       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.SM4));
    659       Buffer += sizeof(UINT16);
    660       break;
    661     case TPM_ALG_NULL:
    662       break;
    663     default:
    664       return EFI_INVALID_PARAMETER;
    665     }
    666     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.scheme));
    667     Buffer += sizeof(UINT16);
    668     switch (Parameters->parameters.eccDetail.scheme.scheme) {
    669     case TPM_ALG_ECDSA:
    670       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdsa.hashAlg));
    671       Buffer += sizeof(UINT16);
    672       break;
    673     case TPM_ALG_ECDAA:
    674       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdaa.hashAlg));
    675       Buffer += sizeof(UINT16);
    676       break;
    677     case TPM_ALG_ECSCHNORR:
    678       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecSchnorr.hashAlg));
    679       Buffer += sizeof(UINT16);
    680       break;
    681     case TPM_ALG_ECDH:
    682       break;
    683     case TPM_ALG_NULL:
    684       break;
    685     default:
    686       return EFI_INVALID_PARAMETER;
    687     }
    688     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.curveID));
    689     Buffer += sizeof(UINT16);
    690     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.scheme));
    691     Buffer += sizeof(UINT16);
    692     switch (Parameters->parameters.eccDetail.kdf.scheme) {
    693     case TPM_ALG_MGF1:
    694       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.mgf1.hashAlg));
    695       Buffer += sizeof(UINT16);
    696       break;
    697     case TPM_ALG_KDF1_SP800_108:
    698       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_sp800_108.hashAlg));
    699       Buffer += sizeof(UINT16);
    700       break;
    701     case TPM_ALG_KDF1_SP800_56a:
    702       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_SP800_56a.hashAlg));
    703       Buffer += sizeof(UINT16);
    704       break;
    705     case TPM_ALG_KDF2:
    706       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf2.hashAlg));
    707       Buffer += sizeof(UINT16);
    708       break;
    709     case TPM_ALG_NULL:
    710       break;
    711     default:
    712       return EFI_INVALID_PARAMETER;
    713     }
    714     break;
    715   default:
    716     return EFI_INVALID_PARAMETER;
    717   }
    718 
    719   SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
    720   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
    721 
    722   //
    723   // send Tpm command
    724   //
    725   RecvBufferSize = sizeof (RecvBuffer);
    726   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
    727   if (EFI_ERROR (Status)) {
    728     return Status;
    729   }
    730 
    731   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
    732     DEBUG ((EFI_D_ERROR, "Tpm2TestParms - RecvBufferSize Error - %x\n", RecvBufferSize));
    733     return EFI_DEVICE_ERROR;
    734   }
    735   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
    736     DEBUG ((EFI_D_ERROR, "Tpm2TestParms - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
    737     return EFI_UNSUPPORTED;
    738   }
    739 
    740   return EFI_SUCCESS;
    741 }
    742