Home | History | Annotate | Download | only in Tpm2CommandLib
      1 /** @file
      2   Implement TPM2 EnhancedAuthorization related command.
      3 
      4 Copyright (c) 2014 - 2016, 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   TPMI_DH_ENTITY            AuthHandle;
     27   TPMI_SH_POLICY            PolicySession;
     28   UINT32                    AuthSessionSize;
     29   TPMS_AUTH_COMMAND         AuthSession;
     30   TPM2B_NONCE               NonceTPM;
     31   TPM2B_DIGEST              CpHashA;
     32   TPM2B_NONCE               PolicyRef;
     33   INT32                     Expiration;
     34 } TPM2_POLICY_SECRET_COMMAND;
     35 
     36 typedef struct {
     37   TPM2_RESPONSE_HEADER      Header;
     38   UINT32                    AuthSessionSize;
     39   TPM2B_TIMEOUT             Timeout;
     40   TPMT_TK_AUTH              PolicyTicket;
     41   TPMS_AUTH_RESPONSE        AuthSession;
     42 } TPM2_POLICY_SECRET_RESPONSE;
     43 
     44 typedef struct {
     45   TPM2_COMMAND_HEADER       Header;
     46   TPMI_SH_POLICY            PolicySession;
     47   TPML_DIGEST               HashList;
     48 } TPM2_POLICY_OR_COMMAND;
     49 
     50 typedef struct {
     51   TPM2_RESPONSE_HEADER      Header;
     52 } TPM2_POLICY_OR_RESPONSE;
     53 
     54 typedef struct {
     55   TPM2_COMMAND_HEADER       Header;
     56   TPMI_SH_POLICY            PolicySession;
     57   TPM_CC                    Code;
     58 } TPM2_POLICY_COMMAND_CODE_COMMAND;
     59 
     60 typedef struct {
     61   TPM2_RESPONSE_HEADER      Header;
     62 } TPM2_POLICY_COMMAND_CODE_RESPONSE;
     63 
     64 typedef struct {
     65   TPM2_COMMAND_HEADER       Header;
     66   TPMI_SH_POLICY            PolicySession;
     67 } TPM2_POLICY_GET_DIGEST_COMMAND;
     68 
     69 typedef struct {
     70   TPM2_RESPONSE_HEADER      Header;
     71   TPM2B_DIGEST              PolicyHash;
     72 } TPM2_POLICY_GET_DIGEST_RESPONSE;
     73 
     74 #pragma pack()
     75 
     76 /**
     77   This command includes a secret-based authorization to a policy.
     78   The caller proves knowledge of the secret value using an authorization
     79   session using the authValue associated with authHandle.
     80 
     81   @param[in]  AuthHandle         Handle for an entity providing the authorization
     82   @param[in]  PolicySession      Handle for the policy session being extended.
     83   @param[in]  AuthSession        Auth Session context
     84   @param[in]  NonceTPM           The policy nonce for the session.
     85   @param[in]  CpHashA            Digest of the command parameters to which this authorization is limited.
     86   @param[in]  PolicyRef          A reference to a policy relating to the authorization.
     87   @param[in]  Expiration         Time when authorization will expire, measured in seconds from the time that nonceTPM was generated.
     88   @param[out] Timeout            Time value used to indicate to the TPM when the ticket expires.
     89   @param[out] PolicyTicket       A ticket that includes a value indicating when the authorization expires.
     90 
     91   @retval EFI_SUCCESS            Operation completed successfully.
     92   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
     93 **/
     94 EFI_STATUS
     95 EFIAPI
     96 Tpm2PolicySecret (
     97   IN      TPMI_DH_ENTITY            AuthHandle,
     98   IN      TPMI_SH_POLICY            PolicySession,
     99   IN      TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL
    100   IN      TPM2B_NONCE               *NonceTPM,
    101   IN      TPM2B_DIGEST              *CpHashA,
    102   IN      TPM2B_NONCE               *PolicyRef,
    103   IN      INT32                     Expiration,
    104   OUT     TPM2B_TIMEOUT             *Timeout,
    105   OUT     TPMT_TK_AUTH              *PolicyTicket
    106   )
    107 {
    108   EFI_STATUS                        Status;
    109   TPM2_POLICY_SECRET_COMMAND        SendBuffer;
    110   TPM2_POLICY_SECRET_RESPONSE       RecvBuffer;
    111   UINT32                            SendBufferSize;
    112   UINT32                            RecvBufferSize;
    113   UINT8                             *Buffer;
    114   UINT32                            SessionInfoSize;
    115 
    116   //
    117   // Construct command
    118   //
    119   SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
    120   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicySecret);
    121   SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
    122   SendBuffer.PolicySession = SwapBytes32 (PolicySession);
    123 
    124   //
    125   // Add in Auth session
    126   //
    127   Buffer = (UINT8 *)&SendBuffer.AuthSession;
    128 
    129   // sessionInfoSize
    130   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
    131   Buffer += SessionInfoSize;
    132   SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
    133 
    134   //
    135   // Real data
    136   //
    137   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NonceTPM->size));
    138   Buffer += sizeof(UINT16);
    139   CopyMem (Buffer, NonceTPM->buffer, NonceTPM->size);
    140   Buffer += NonceTPM->size;
    141 
    142   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(CpHashA->size));
    143   Buffer += sizeof(UINT16);
    144   CopyMem (Buffer, CpHashA->buffer, CpHashA->size);
    145   Buffer += CpHashA->size;
    146 
    147   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PolicyRef->size));
    148   Buffer += sizeof(UINT16);
    149   CopyMem (Buffer, PolicyRef->buffer, PolicyRef->size);
    150   Buffer += PolicyRef->size;
    151 
    152   WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32((UINT32)Expiration));
    153   Buffer += sizeof(UINT32);
    154 
    155   SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
    156   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
    157 
    158   //
    159   // send Tpm command
    160   //
    161   RecvBufferSize = sizeof (RecvBuffer);
    162   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
    163   if (EFI_ERROR (Status)) {
    164     goto Done;
    165   }
    166 
    167   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
    168     DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - RecvBufferSize Error - %x\n", RecvBufferSize));
    169     Status = EFI_DEVICE_ERROR;
    170     goto Done;
    171   }
    172   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
    173     DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
    174     Status = EFI_DEVICE_ERROR;
    175     goto Done;
    176   }
    177 
    178   //
    179   // Return the response
    180   //
    181   Buffer = (UINT8 *)&RecvBuffer.Timeout;
    182   Timeout->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
    183   Buffer += sizeof(UINT16);
    184   CopyMem (Timeout->buffer, Buffer, Timeout->size);
    185 
    186   PolicyTicket->tag = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
    187   Buffer += sizeof(UINT16);
    188   PolicyTicket->hierarchy = SwapBytes32(ReadUnaligned32 ((UINT32 *)Buffer));
    189   Buffer += sizeof(UINT32);
    190   PolicyTicket->digest.size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
    191   Buffer += sizeof(UINT16);
    192   CopyMem (PolicyTicket->digest.buffer, Buffer, PolicyTicket->digest.size);
    193 
    194 Done:
    195   //
    196   // Clear AuthSession Content
    197   //
    198   ZeroMem (&SendBuffer, sizeof(SendBuffer));
    199   ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
    200   return Status;
    201 }
    202 
    203 /**
    204   This command allows options in authorizations without requiring that the TPM evaluate all of the options.
    205   If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that
    206   satisfies the policy. This command will indicate that one of the required sets of conditions has been
    207   satisfied.
    208 
    209   @param[in] PolicySession      Handle for the policy session being extended.
    210   @param[in] HashList           the list of hashes to check for a match.
    211 
    212   @retval EFI_SUCCESS            Operation completed successfully.
    213   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    214 **/
    215 EFI_STATUS
    216 EFIAPI
    217 Tpm2PolicyOR (
    218   IN TPMI_SH_POLICY           PolicySession,
    219   IN TPML_DIGEST              *HashList
    220   )
    221 {
    222   EFI_STATUS                        Status;
    223   TPM2_POLICY_OR_COMMAND            SendBuffer;
    224   TPM2_POLICY_OR_RESPONSE           RecvBuffer;
    225   UINT32                            SendBufferSize;
    226   UINT32                            RecvBufferSize;
    227   UINT8                             *Buffer;
    228   UINTN                             Index;
    229 
    230   //
    231   // Construct command
    232   //
    233   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
    234   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyOR);
    235 
    236   SendBuffer.PolicySession = SwapBytes32 (PolicySession);
    237   Buffer = (UINT8 *)&SendBuffer.HashList;
    238   WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (HashList->count));
    239   Buffer += sizeof(UINT32);
    240   for (Index = 0; Index < HashList->count; Index++) {
    241     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (HashList->digests[Index].size));
    242     Buffer += sizeof(UINT16);
    243     CopyMem (Buffer, HashList->digests[Index].buffer, HashList->digests[Index].size);
    244     Buffer += HashList->digests[Index].size;
    245   }
    246 
    247   SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
    248   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
    249 
    250   //
    251   // send Tpm command
    252   //
    253   RecvBufferSize = sizeof (RecvBuffer);
    254   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
    255   if (EFI_ERROR (Status)) {
    256     return Status;
    257   }
    258 
    259   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
    260     DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize));
    261     return EFI_DEVICE_ERROR;
    262   }
    263   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
    264     DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
    265     return EFI_DEVICE_ERROR;
    266   }
    267 
    268   return EFI_SUCCESS;
    269 }
    270 
    271 /**
    272   This command indicates that the authorization will be limited to a specific command code.
    273 
    274   @param[in]  PolicySession      Handle for the policy session being extended.
    275   @param[in]  Code               The allowed commandCode.
    276 
    277   @retval EFI_SUCCESS            Operation completed successfully.
    278   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    279 **/
    280 EFI_STATUS
    281 EFIAPI
    282 Tpm2PolicyCommandCode (
    283   IN      TPMI_SH_POLICY            PolicySession,
    284   IN      TPM_CC                    Code
    285   )
    286 {
    287   EFI_STATUS                        Status;
    288   TPM2_POLICY_COMMAND_CODE_COMMAND  SendBuffer;
    289   TPM2_POLICY_COMMAND_CODE_RESPONSE RecvBuffer;
    290   UINT32                            SendBufferSize;
    291   UINT32                            RecvBufferSize;
    292 
    293   //
    294   // Construct command
    295   //
    296   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
    297   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyCommandCode);
    298 
    299   SendBuffer.PolicySession = SwapBytes32 (PolicySession);
    300   SendBuffer.Code = SwapBytes32 (Code);
    301 
    302   SendBufferSize = (UINT32) sizeof (SendBuffer);
    303   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
    304 
    305   //
    306   // send Tpm command
    307   //
    308   RecvBufferSize = sizeof (RecvBuffer);
    309   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
    310   if (EFI_ERROR (Status)) {
    311     return Status;
    312   }
    313 
    314   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
    315     DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - RecvBufferSize Error - %x\n", RecvBufferSize));
    316     return EFI_DEVICE_ERROR;
    317   }
    318   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
    319     DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
    320     return EFI_DEVICE_ERROR;
    321   }
    322 
    323   return EFI_SUCCESS;
    324 }
    325 
    326 /**
    327   This command returns the current policyDigest of the session. This command allows the TPM
    328   to be used to perform the actions required to precompute the authPolicy for an object.
    329 
    330   @param[in]  PolicySession      Handle for the policy session.
    331   @param[out] PolicyHash         the current value of the policyHash of policySession.
    332 
    333   @retval EFI_SUCCESS            Operation completed successfully.
    334   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
    335 **/
    336 EFI_STATUS
    337 EFIAPI
    338 Tpm2PolicyGetDigest (
    339   IN      TPMI_SH_POLICY            PolicySession,
    340      OUT  TPM2B_DIGEST              *PolicyHash
    341   )
    342 {
    343   EFI_STATUS                        Status;
    344   TPM2_POLICY_GET_DIGEST_COMMAND    SendBuffer;
    345   TPM2_POLICY_GET_DIGEST_RESPONSE   RecvBuffer;
    346   UINT32                            SendBufferSize;
    347   UINT32                            RecvBufferSize;
    348 
    349   //
    350   // Construct command
    351   //
    352   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
    353   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyGetDigest);
    354 
    355   SendBuffer.PolicySession = SwapBytes32 (PolicySession);
    356 
    357   SendBufferSize = (UINT32) sizeof (SendBuffer);
    358   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
    359 
    360   //
    361   // send Tpm command
    362   //
    363   RecvBufferSize = sizeof (RecvBuffer);
    364   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
    365   if (EFI_ERROR (Status)) {
    366     return Status;
    367   }
    368 
    369   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
    370     DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - RecvBufferSize Error - %x\n", RecvBufferSize));
    371     return EFI_DEVICE_ERROR;
    372   }
    373   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
    374     DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
    375     return EFI_DEVICE_ERROR;
    376   }
    377 
    378   //
    379   // Return the response
    380   //
    381   PolicyHash->size = SwapBytes16 (RecvBuffer.PolicyHash.size);
    382   CopyMem (PolicyHash->buffer, &RecvBuffer.PolicyHash.buffer, PolicyHash->size);
    383 
    384   return EFI_SUCCESS;
    385 }
    386