Home | History | Annotate | Download | only in HashLibTpm2
      1 /** @file
      2   This library uses TPM2 device to calculation hash.
      3 
      4 Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved. <BR>
      5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include <PiPei.h>
     17 #include <Library/BaseLib.h>
     18 #include <Library/BaseMemoryLib.h>
     19 #include <Library/Tpm2CommandLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/MemoryAllocationLib.h>
     22 #include <Library/HashLib.h>
     23 #include <Library/PcdLib.h>
     24 
     25 typedef struct {
     26   TPM_ALG_ID AlgoId;
     27   UINT32     Mask;
     28 } TPM2_HASH_MASK;
     29 
     30 TPM2_HASH_MASK mTpm2HashMask[] = {
     31   {TPM_ALG_SHA1,         HASH_ALG_SHA1},
     32   {TPM_ALG_SHA256,       HASH_ALG_SHA256},
     33   {TPM_ALG_SHA384,       HASH_ALG_SHA384},
     34   {TPM_ALG_SHA512,       HASH_ALG_SHA512},
     35 };
     36 
     37 /**
     38   The function get algorith from hash mask info.
     39 
     40   @return Hash algorithm
     41 **/
     42 TPM_ALG_ID
     43 Tpm2GetAlgoFromHashMask (
     44   VOID
     45   )
     46 {
     47   UINT32 HashMask;
     48   UINTN  Index;
     49 
     50   HashMask = PcdGet32 (PcdTpm2HashMask);
     51   for (Index = 0; Index < sizeof(mTpm2HashMask)/sizeof(mTpm2HashMask[0]); Index++) {
     52     if (mTpm2HashMask[Index].Mask == HashMask) {
     53       return mTpm2HashMask[Index].AlgoId;
     54     }
     55   }
     56 
     57   return TPM_ALG_NULL;
     58 }
     59 
     60 /**
     61   Start hash sequence.
     62 
     63   @param HashHandle Hash handle.
     64 
     65   @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.
     66   @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.
     67 **/
     68 EFI_STATUS
     69 EFIAPI
     70 HashStart (
     71   OUT HASH_HANDLE    *HashHandle
     72   )
     73 {
     74   TPMI_DH_OBJECT        SequenceHandle;
     75   EFI_STATUS            Status;
     76   TPM_ALG_ID            AlgoId;
     77 
     78   AlgoId = Tpm2GetAlgoFromHashMask ();
     79 
     80   Status = Tpm2HashSequenceStart (AlgoId, &SequenceHandle);
     81   if (!EFI_ERROR (Status)) {
     82     *HashHandle = (HASH_HANDLE)SequenceHandle;
     83   }
     84   return Status;
     85 }
     86 
     87 /**
     88   Update hash sequence data.
     89 
     90   @param HashHandle    Hash handle.
     91   @param DataToHash    Data to be hashed.
     92   @param DataToHashLen Data size.
     93 
     94   @retval EFI_SUCCESS     Hash sequence updated.
     95 **/
     96 EFI_STATUS
     97 EFIAPI
     98 HashUpdate (
     99   IN HASH_HANDLE    HashHandle,
    100   IN VOID           *DataToHash,
    101   IN UINTN          DataToHashLen
    102   )
    103 {
    104   UINT8            *Buffer;
    105   UINT64           HashLen;
    106   TPM2B_MAX_BUFFER HashBuffer;
    107   EFI_STATUS       Status;
    108 
    109   Buffer = (UINT8 *)(UINTN)DataToHash;
    110   for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {
    111 
    112     HashBuffer.size = sizeof(HashBuffer.buffer);
    113     CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));
    114     Buffer += sizeof(HashBuffer.buffer);
    115 
    116     Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);
    117     if (EFI_ERROR(Status)) {
    118       return EFI_DEVICE_ERROR;
    119     }
    120   }
    121 
    122   //
    123   // Last one
    124   //
    125   HashBuffer.size = (UINT16)HashLen;
    126   CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);
    127   Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);
    128   if (EFI_ERROR(Status)) {
    129     return EFI_DEVICE_ERROR;
    130   }
    131 
    132   return EFI_SUCCESS;
    133 }
    134 
    135 /**
    136   Hash sequence complete and extend to PCR.
    137 
    138   @param HashHandle    Hash handle.
    139   @param PcrIndex      PCR to be extended.
    140   @param DataToHash    Data to be hashed.
    141   @param DataToHashLen Data size.
    142   @param DigestList    Digest list.
    143 
    144   @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.
    145 **/
    146 EFI_STATUS
    147 EFIAPI
    148 HashCompleteAndExtend (
    149   IN HASH_HANDLE         HashHandle,
    150   IN TPMI_DH_PCR         PcrIndex,
    151   IN VOID                *DataToHash,
    152   IN UINTN               DataToHashLen,
    153   OUT TPML_DIGEST_VALUES *DigestList
    154   )
    155 {
    156   UINT8            *Buffer;
    157   UINT64           HashLen;
    158   TPM2B_MAX_BUFFER HashBuffer;
    159   EFI_STATUS       Status;
    160   TPM_ALG_ID       AlgoId;
    161   TPM2B_DIGEST     Result;
    162 
    163   AlgoId = Tpm2GetAlgoFromHashMask ();
    164 
    165   Buffer = (UINT8 *)(UINTN)DataToHash;
    166   for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {
    167 
    168     HashBuffer.size = sizeof(HashBuffer.buffer);
    169     CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));
    170     Buffer += sizeof(HashBuffer.buffer);
    171 
    172     Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);
    173     if (EFI_ERROR(Status)) {
    174       return EFI_DEVICE_ERROR;
    175     }
    176   }
    177 
    178   //
    179   // Last one
    180   //
    181   HashBuffer.size = (UINT16)HashLen;
    182   CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);
    183 
    184   ZeroMem(DigestList, sizeof(*DigestList));
    185   DigestList->count = HASH_COUNT;
    186 
    187   if (AlgoId == TPM_ALG_NULL) {
    188     Status = Tpm2EventSequenceComplete (
    189                PcrIndex,
    190                (TPMI_DH_OBJECT)HashHandle,
    191                &HashBuffer,
    192                DigestList
    193                );
    194   } else {
    195     Status = Tpm2SequenceComplete (
    196                (TPMI_DH_OBJECT)HashHandle,
    197                &HashBuffer,
    198                &Result
    199                );
    200     if (EFI_ERROR(Status)) {
    201       return EFI_DEVICE_ERROR;
    202     }
    203 
    204     DigestList->count = 1;
    205     DigestList->digests[0].hashAlg = AlgoId;
    206     CopyMem (&DigestList->digests[0].digest, Result.buffer, Result.size);
    207     Status = Tpm2PcrExtend (
    208                PcrIndex,
    209                DigestList
    210                );
    211   }
    212   if (EFI_ERROR(Status)) {
    213     return EFI_DEVICE_ERROR;
    214   }
    215   return EFI_SUCCESS;
    216 }
    217 
    218 /**
    219   Hash data and extend to PCR.
    220 
    221   @param PcrIndex      PCR to be extended.
    222   @param DataToHash    Data to be hashed.
    223   @param DataToHashLen Data size.
    224   @param DigestList    Digest list.
    225 
    226   @retval EFI_SUCCESS     Hash data and DigestList is returned.
    227 **/
    228 EFI_STATUS
    229 EFIAPI
    230 HashAndExtend (
    231   IN TPMI_DH_PCR                    PcrIndex,
    232   IN VOID                           *DataToHash,
    233   IN UINTN                          DataToHashLen,
    234   OUT TPML_DIGEST_VALUES            *DigestList
    235   )
    236 {
    237   EFI_STATUS         Status;
    238   UINT8              *Buffer;
    239   UINT64             HashLen;
    240   TPMI_DH_OBJECT     SequenceHandle;
    241   TPM2B_MAX_BUFFER   HashBuffer;
    242   TPM_ALG_ID         AlgoId;
    243   TPM2B_EVENT        EventData;
    244   TPM2B_DIGEST       Result;
    245 
    246   DEBUG((EFI_D_VERBOSE, "\n HashAndExtend Entry \n"));
    247 
    248   SequenceHandle = 0xFFFFFFFF; // Know bad value
    249 
    250   AlgoId = Tpm2GetAlgoFromHashMask ();
    251 
    252   if ((AlgoId == TPM_ALG_NULL) && (DataToHashLen <= sizeof(EventData.buffer))) {
    253     EventData.size = (UINT16)DataToHashLen;
    254     CopyMem (EventData.buffer, DataToHash, DataToHashLen);
    255     Status = Tpm2PcrEvent (PcrIndex, &EventData, DigestList);
    256     if (EFI_ERROR(Status)) {
    257       return EFI_DEVICE_ERROR;
    258     }
    259     return EFI_SUCCESS;
    260   }
    261 
    262   Status = Tpm2HashSequenceStart(AlgoId, &SequenceHandle);
    263   if (EFI_ERROR(Status)) {
    264     return EFI_DEVICE_ERROR;
    265   }
    266   DEBUG((EFI_D_VERBOSE, "\n Tpm2HashSequenceStart Success \n"));
    267 
    268   Buffer = (UINT8 *)(UINTN)DataToHash;
    269   for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {
    270 
    271     HashBuffer.size = sizeof(HashBuffer.buffer);
    272     CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));
    273     Buffer += sizeof(HashBuffer.buffer);
    274 
    275     Status = Tpm2SequenceUpdate(SequenceHandle, &HashBuffer);
    276     if (EFI_ERROR(Status)) {
    277       return EFI_DEVICE_ERROR;
    278     }
    279   }
    280   DEBUG((EFI_D_VERBOSE, "\n Tpm2SequenceUpdate Success \n"));
    281 
    282   HashBuffer.size = (UINT16)HashLen;
    283   CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);
    284 
    285   ZeroMem(DigestList, sizeof(*DigestList));
    286   DigestList->count = HASH_COUNT;
    287 
    288   if (AlgoId == TPM_ALG_NULL) {
    289     Status = Tpm2EventSequenceComplete (
    290                PcrIndex,
    291                SequenceHandle,
    292                &HashBuffer,
    293                DigestList
    294                );
    295     if (EFI_ERROR(Status)) {
    296       return EFI_DEVICE_ERROR;
    297     }
    298     DEBUG((EFI_D_VERBOSE, "\n Tpm2EventSequenceComplete Success \n"));
    299   } else {
    300     Status = Tpm2SequenceComplete (
    301                SequenceHandle,
    302                &HashBuffer,
    303                &Result
    304                );
    305     if (EFI_ERROR(Status)) {
    306       return EFI_DEVICE_ERROR;
    307     }
    308     DEBUG((EFI_D_VERBOSE, "\n Tpm2SequenceComplete Success \n"));
    309 
    310     DigestList->count = 1;
    311     DigestList->digests[0].hashAlg = AlgoId;
    312     CopyMem (&DigestList->digests[0].digest, Result.buffer, Result.size);
    313     Status = Tpm2PcrExtend (
    314                PcrIndex,
    315                DigestList
    316                );
    317     if (EFI_ERROR(Status)) {
    318       return EFI_DEVICE_ERROR;
    319     }
    320     DEBUG((EFI_D_VERBOSE, "\n Tpm2PcrExtend Success \n"));
    321   }
    322 
    323   return EFI_SUCCESS;
    324 }
    325 
    326 /**
    327   This service register Hash.
    328 
    329   @param HashInterface  Hash interface
    330 
    331   @retval EFI_SUCCESS          This hash interface is registered successfully.
    332   @retval EFI_UNSUPPORTED      System does not support register this interface.
    333   @retval EFI_ALREADY_STARTED  System already register this interface.
    334 **/
    335 EFI_STATUS
    336 EFIAPI
    337 RegisterHashInterfaceLib (
    338   IN HASH_INTERFACE   *HashInterface
    339   )
    340 {
    341   return EFI_UNSUPPORTED;
    342 }