Home | History | Annotate | Download | only in Tpm2CommandLib
      1 /** @file
      2   Implement TPM2 help.
      3 
      4 Copyright (c) 2013 - 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 typedef struct {
     23   TPMI_ALG_HASH              HashAlgo;
     24   UINT16                     HashSize;
     25   UINT32                     HashMask;
     26 } INTERNAL_HASH_INFO;
     27 
     28 STATIC INTERNAL_HASH_INFO mHashInfo[] = {
     29   {TPM_ALG_SHA1,          SHA1_DIGEST_SIZE,     HASH_ALG_SHA1},
     30   {TPM_ALG_SHA256,        SHA256_DIGEST_SIZE,   HASH_ALG_SHA256},
     31   {TPM_ALG_SM3_256,       SM3_256_DIGEST_SIZE,  HASH_ALG_SM3_256},
     32   {TPM_ALG_SHA384,        SHA384_DIGEST_SIZE,   HASH_ALG_SHA384},
     33   {TPM_ALG_SHA512,        SHA512_DIGEST_SIZE,   HASH_ALG_SHA512},
     34 };
     35 
     36 /**
     37   Return size of digest.
     38 
     39   @param[in] HashAlgo  Hash algorithm
     40 
     41   @return size of digest
     42 **/
     43 UINT16
     44 EFIAPI
     45 GetHashSizeFromAlgo (
     46   IN TPMI_ALG_HASH    HashAlgo
     47   )
     48 {
     49   UINTN  Index;
     50 
     51   for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) {
     52     if (mHashInfo[Index].HashAlgo == HashAlgo) {
     53       return mHashInfo[Index].HashSize;
     54     }
     55   }
     56   return 0;
     57 }
     58 
     59 /**
     60   Get hash mask from algorithm.
     61 
     62   @param[in] HashAlgo   Hash algorithm
     63 
     64   @return Hash mask
     65 **/
     66 UINT32
     67 EFIAPI
     68 GetHashMaskFromAlgo (
     69   IN TPMI_ALG_HASH     HashAlgo
     70   )
     71 {
     72   UINTN  Index;
     73 
     74   for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) {
     75     if (mHashInfo[Index].HashAlgo == HashAlgo) {
     76       return mHashInfo[Index].HashMask;
     77     }
     78   }
     79   return 0;
     80 }
     81 
     82 /**
     83   Copy AuthSessionIn to TPM2 command buffer.
     84 
     85   @param [in]  AuthSessionIn   Input AuthSession data
     86   @param [out] AuthSessionOut  Output AuthSession data in TPM2 command buffer
     87 
     88   @return AuthSession size
     89 **/
     90 UINT32
     91 EFIAPI
     92 CopyAuthSessionCommand (
     93   IN      TPMS_AUTH_COMMAND         *AuthSessionIn, OPTIONAL
     94   OUT     UINT8                     *AuthSessionOut
     95   )
     96 {
     97   UINT8  *Buffer;
     98 
     99   Buffer = (UINT8 *)AuthSessionOut;
    100 
    101   //
    102   // Add in Auth session
    103   //
    104   if (AuthSessionIn != NULL) {
    105     //  sessionHandle
    106     WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(AuthSessionIn->sessionHandle));
    107     Buffer += sizeof(UINT32);
    108 
    109     // nonce
    110     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->nonce.size));
    111     Buffer += sizeof(UINT16);
    112 
    113     CopyMem (Buffer, AuthSessionIn->nonce.buffer, AuthSessionIn->nonce.size);
    114     Buffer += AuthSessionIn->nonce.size;
    115 
    116     // sessionAttributes
    117     *(UINT8 *)Buffer = *(UINT8 *)&AuthSessionIn->sessionAttributes;
    118     Buffer++;
    119 
    120     // hmac
    121     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->hmac.size));
    122     Buffer += sizeof(UINT16);
    123 
    124     CopyMem (Buffer, AuthSessionIn->hmac.buffer, AuthSessionIn->hmac.size);
    125     Buffer += AuthSessionIn->hmac.size;
    126   } else {
    127     //  sessionHandle
    128     WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(TPM_RS_PW));
    129     Buffer += sizeof(UINT32);
    130 
    131     // nonce = nullNonce
    132     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));
    133     Buffer += sizeof(UINT16);
    134 
    135     // sessionAttributes = 0
    136     *(UINT8 *)Buffer = 0x00;
    137     Buffer++;
    138 
    139     // hmac = nullAuth
    140     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));
    141     Buffer += sizeof(UINT16);
    142   }
    143 
    144   return (UINT32)(UINTN)(Buffer - (UINT8 *)AuthSessionOut);
    145 }
    146 
    147 /**
    148   Copy AuthSessionIn from TPM2 response buffer.
    149 
    150   @param [in]  AuthSessionIn   Input AuthSession data in TPM2 response buffer
    151   @param [out] AuthSessionOut  Output AuthSession data
    152 
    153   @return AuthSession size
    154 **/
    155 UINT32
    156 EFIAPI
    157 CopyAuthSessionResponse (
    158   IN      UINT8                      *AuthSessionIn,
    159   OUT     TPMS_AUTH_RESPONSE         *AuthSessionOut OPTIONAL
    160   )
    161 {
    162   UINT8                      *Buffer;
    163   TPMS_AUTH_RESPONSE         LocalAuthSessionOut;
    164 
    165   if (AuthSessionOut == NULL) {
    166     AuthSessionOut = &LocalAuthSessionOut;
    167   }
    168 
    169   Buffer = (UINT8 *)AuthSessionIn;
    170 
    171   // nonce
    172   AuthSessionOut->nonce.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
    173   Buffer += sizeof(UINT16);
    174 
    175   CopyMem (AuthSessionOut->nonce.buffer, Buffer, AuthSessionOut->nonce.size);
    176   Buffer += AuthSessionOut->nonce.size;
    177 
    178   // sessionAttributes
    179   *(UINT8 *)&AuthSessionOut->sessionAttributes = *(UINT8 *)Buffer;
    180   Buffer++;
    181 
    182   // hmac
    183   AuthSessionOut->hmac.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
    184   Buffer += sizeof(UINT16);
    185 
    186   CopyMem (AuthSessionOut->hmac.buffer, Buffer, AuthSessionOut->hmac.size);
    187   Buffer += AuthSessionOut->hmac.size;
    188 
    189   return (UINT32)(UINTN)(Buffer - (UINT8 *)AuthSessionIn);
    190 }
    191 
    192 /**
    193   Return if hash alg is supported in HashAlgorithmMask.
    194 
    195   @param HashAlg            Hash algorithm to be checked.
    196   @param HashAlgorithmMask  Bitfield of allowed hash algorithms.
    197 
    198   @retval TRUE  Hash algorithm is supported.
    199   @retval FALSE Hash algorithm is not supported.
    200 **/
    201 BOOLEAN
    202 EFIAPI
    203 IsHashAlgSupportedInHashAlgorithmMask(
    204   IN TPMI_ALG_HASH  HashAlg,
    205   IN UINT32         HashAlgorithmMask
    206   )
    207 {
    208   switch (HashAlg) {
    209   case TPM_ALG_SHA1:
    210     if ((HashAlgorithmMask & HASH_ALG_SHA1) != 0) {
    211       return TRUE;
    212     }
    213     break;
    214   case TPM_ALG_SHA256:
    215     if ((HashAlgorithmMask & HASH_ALG_SHA256) != 0) {
    216       return TRUE;
    217     }
    218     break;
    219   case TPM_ALG_SHA384:
    220     if ((HashAlgorithmMask & HASH_ALG_SHA384) != 0) {
    221       return TRUE;
    222     }
    223     break;
    224   case TPM_ALG_SHA512:
    225     if ((HashAlgorithmMask & HASH_ALG_SHA512) != 0) {
    226       return TRUE;
    227     }
    228     break;
    229   case TPM_ALG_SM3_256:
    230     if ((HashAlgorithmMask & HASH_ALG_SM3_256) != 0) {
    231       return TRUE;
    232     }
    233     break;
    234   }
    235 
    236   return FALSE;
    237 }
    238 
    239 /**
    240   Copy TPML_DIGEST_VALUES into a buffer
    241 
    242   @param[in,out] Buffer             Buffer to hold copied TPML_DIGEST_VALUES compact binary.
    243   @param[in]     DigestList         TPML_DIGEST_VALUES to be copied.
    244   @param[in]     HashAlgorithmMask  HASH bits corresponding to the desired digests to copy.
    245 
    246   @return The end of buffer to hold TPML_DIGEST_VALUES.
    247 **/
    248 VOID *
    249 EFIAPI
    250 CopyDigestListToBuffer (
    251   IN OUT VOID                       *Buffer,
    252   IN TPML_DIGEST_VALUES             *DigestList,
    253   IN UINT32                         HashAlgorithmMask
    254   )
    255 {
    256   UINTN  Index;
    257   UINT16 DigestSize;
    258   UINT32 DigestListCount;
    259   UINT32 *DigestListCountPtr;
    260 
    261   DigestListCountPtr = (UINT32 *) Buffer;
    262   DigestListCount = 0;
    263   Buffer = (UINT8 *)Buffer + sizeof(DigestList->count);
    264   for (Index = 0; Index < DigestList->count; Index++) {
    265     if (!IsHashAlgSupportedInHashAlgorithmMask(DigestList->digests[Index].hashAlg, HashAlgorithmMask)) {
    266       DEBUG ((EFI_D_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg));
    267       continue;
    268     }
    269     CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof(DigestList->digests[Index].hashAlg));
    270     Buffer = (UINT8 *)Buffer + sizeof(DigestList->digests[Index].hashAlg);
    271     DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);
    272     CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize);
    273     Buffer = (UINT8 *)Buffer + DigestSize;
    274     DigestListCount++;
    275   }
    276   WriteUnaligned32 (DigestListCountPtr, DigestListCount);
    277 
    278   return Buffer;
    279 }
    280 
    281 /**
    282   Get TPML_DIGEST_VALUES data size.
    283 
    284   @param[in]     DigestList    TPML_DIGEST_VALUES data.
    285 
    286   @return TPML_DIGEST_VALUES data size.
    287 **/
    288 UINT32
    289 EFIAPI
    290 GetDigestListSize (
    291   IN TPML_DIGEST_VALUES             *DigestList
    292   )
    293 {
    294   UINTN  Index;
    295   UINT16 DigestSize;
    296   UINT32 TotalSize;
    297 
    298   TotalSize = sizeof(DigestList->count);
    299   for (Index = 0; Index < DigestList->count; Index++) {
    300     DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);
    301     TotalSize += sizeof(DigestList->digests[Index].hashAlg) + DigestSize;
    302   }
    303 
    304   return TotalSize;
    305 }
    306 
    307 /**
    308   This function get digest from digest list.
    309 
    310   @param[in]  HashAlg       Digest algorithm
    311   @param[in]  DigestList    Digest list
    312   @param[out] Digest        Digest
    313 
    314   @retval EFI_SUCCESS       Digest is found and returned.
    315   @retval EFI_NOT_FOUND     Digest is not found.
    316 **/
    317 EFI_STATUS
    318 EFIAPI
    319 GetDigestFromDigestList (
    320   IN TPMI_ALG_HASH      HashAlg,
    321   IN TPML_DIGEST_VALUES *DigestList,
    322   OUT VOID              *Digest
    323   )
    324 {
    325   UINTN  Index;
    326   UINT16 DigestSize;
    327 
    328   DigestSize = GetHashSizeFromAlgo (HashAlg);
    329   for (Index = 0; Index < DigestList->count; Index++) {
    330     if (DigestList->digests[Index].hashAlg == HashAlg) {
    331       CopyMem (
    332         Digest,
    333         &DigestList->digests[Index].digest,
    334         DigestSize
    335         );
    336       return EFI_SUCCESS;
    337     }
    338   }
    339 
    340   return EFI_NOT_FOUND;
    341 }
    342