1 /** @file
2   Ihis library is BaseCrypto router. It will redirect hash request to each individual
3   hash handler registerd, such as SHA1, SHA256.
4   Platform can use PcdTpm2HashMask to mask some hash engines.
5 
6 Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved. <BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution.  The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11 
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 **/
16 
17 #include <PiPei.h>
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/Tpm2CommandLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/PcdLib.h>
24 #include <Library/HashLib.h>
25 
26 #include "HashLibBaseCryptoRouterCommon.h"
27 
28 HASH_INTERFACE   mHashInterface[HASH_COUNT] = {{{0}, NULL, NULL, NULL}};
29 UINTN            mHashInterfaceCount = 0;
30 
31 /**
32   Start hash sequence.
33 
34   @param HashHandle Hash handle.
35 
36   @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.
37   @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.
38 **/
39 EFI_STATUS
40 EFIAPI
HashStart(OUT HASH_HANDLE * HashHandle)41 HashStart (
42   OUT HASH_HANDLE    *HashHandle
43   )
44 {
45   HASH_HANDLE  *HashCtx;
46   UINTN        Index;
47   UINT32       HashMask;
48 
49   if (mHashInterfaceCount == 0) {
50     return EFI_UNSUPPORTED;
51   }
52 
53   HashCtx = AllocatePool (sizeof(*HashCtx) * mHashInterfaceCount);
54   ASSERT (HashCtx != NULL);
55 
56   for (Index = 0; Index < mHashInterfaceCount; Index++) {
57     HashMask = Tpm2GetHashMaskFromAlgo (&mHashInterface[Index].HashGuid);
58     if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) {
59       mHashInterface[Index].HashInit (&HashCtx[Index]);
60     }
61   }
62 
63   *HashHandle = (HASH_HANDLE)HashCtx;
64 
65   return EFI_SUCCESS;
66 }
67 
68 /**
69   Update hash sequence data.
70 
71   @param HashHandle    Hash handle.
72   @param DataToHash    Data to be hashed.
73   @param DataToHashLen Data size.
74 
75   @retval EFI_SUCCESS     Hash sequence updated.
76 **/
77 EFI_STATUS
78 EFIAPI
HashUpdate(IN HASH_HANDLE HashHandle,IN VOID * DataToHash,IN UINTN DataToHashLen)79 HashUpdate (
80   IN HASH_HANDLE    HashHandle,
81   IN VOID           *DataToHash,
82   IN UINTN          DataToHashLen
83   )
84 {
85   HASH_HANDLE  *HashCtx;
86   UINTN        Index;
87   UINT32       HashMask;
88 
89   if (mHashInterfaceCount == 0) {
90     return EFI_UNSUPPORTED;
91   }
92 
93   HashCtx = (HASH_HANDLE *)HashHandle;
94 
95   for (Index = 0; Index < mHashInterfaceCount; Index++) {
96     HashMask = Tpm2GetHashMaskFromAlgo (&mHashInterface[Index].HashGuid);
97     if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) {
98       mHashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);
99     }
100   }
101 
102   return EFI_SUCCESS;
103 }
104 
105 /**
106   Hash sequence complete and extend to PCR.
107 
108   @param HashHandle    Hash handle.
109   @param PcrIndex      PCR to be extended.
110   @param DataToHash    Data to be hashed.
111   @param DataToHashLen Data size.
112   @param DigestList    Digest list.
113 
114   @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.
115 **/
116 EFI_STATUS
117 EFIAPI
HashCompleteAndExtend(IN HASH_HANDLE HashHandle,IN TPMI_DH_PCR PcrIndex,IN VOID * DataToHash,IN UINTN DataToHashLen,OUT TPML_DIGEST_VALUES * DigestList)118 HashCompleteAndExtend (
119   IN HASH_HANDLE         HashHandle,
120   IN TPMI_DH_PCR         PcrIndex,
121   IN VOID                *DataToHash,
122   IN UINTN               DataToHashLen,
123   OUT TPML_DIGEST_VALUES *DigestList
124   )
125 {
126   TPML_DIGEST_VALUES Digest;
127   HASH_HANDLE        *HashCtx;
128   UINTN              Index;
129   EFI_STATUS         Status;
130   UINT32             HashMask;
131 
132   if (mHashInterfaceCount == 0) {
133     return EFI_UNSUPPORTED;
134   }
135 
136   HashCtx = (HASH_HANDLE *)HashHandle;
137   ZeroMem (DigestList, sizeof(*DigestList));
138 
139   for (Index = 0; Index < mHashInterfaceCount; Index++) {
140     HashMask = Tpm2GetHashMaskFromAlgo (&mHashInterface[Index].HashGuid);
141     if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) {
142       mHashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);
143       mHashInterface[Index].HashFinal (HashCtx[Index], &Digest);
144       Tpm2SetHashToDigestList (DigestList, &Digest);
145     }
146   }
147 
148   FreePool (HashCtx);
149 
150   Status = Tpm2PcrExtend (
151              PcrIndex,
152              DigestList
153              );
154   return Status;
155 }
156 
157 /**
158   Hash data and extend to PCR.
159 
160   @param PcrIndex      PCR to be extended.
161   @param DataToHash    Data to be hashed.
162   @param DataToHashLen Data size.
163   @param DigestList    Digest list.
164 
165   @retval EFI_SUCCESS     Hash data and DigestList is returned.
166 **/
167 EFI_STATUS
168 EFIAPI
HashAndExtend(IN TPMI_DH_PCR PcrIndex,IN VOID * DataToHash,IN UINTN DataToHashLen,OUT TPML_DIGEST_VALUES * DigestList)169 HashAndExtend (
170   IN TPMI_DH_PCR                    PcrIndex,
171   IN VOID                           *DataToHash,
172   IN UINTN                          DataToHashLen,
173   OUT TPML_DIGEST_VALUES            *DigestList
174   )
175 {
176   HASH_HANDLE    HashHandle;
177   EFI_STATUS     Status;
178 
179   if (mHashInterfaceCount == 0) {
180     return EFI_UNSUPPORTED;
181   }
182 
183   HashStart (&HashHandle);
184   HashUpdate (HashHandle, DataToHash, DataToHashLen);
185   Status = HashCompleteAndExtend (HashHandle, PcrIndex, NULL, 0, DigestList);
186 
187   return Status;
188 }
189 
190 /**
191   This service register Hash.
192 
193   @param HashInterface  Hash interface
194 
195   @retval EFI_SUCCESS          This hash interface is registered successfully.
196   @retval EFI_UNSUPPORTED      System does not support register this interface.
197   @retval EFI_ALREADY_STARTED  System already register this interface.
198 **/
199 EFI_STATUS
200 EFIAPI
RegisterHashInterfaceLib(IN HASH_INTERFACE * HashInterface)201 RegisterHashInterfaceLib (
202   IN HASH_INTERFACE   *HashInterface
203   )
204 {
205   UINTN              Index;
206   UINT32             HashMask;
207   UINT32             BiosSupportedHashMask;
208   EFI_STATUS         Status;
209 
210   //
211   // Check allow
212   //
213   HashMask = Tpm2GetHashMaskFromAlgo (&HashInterface->HashGuid);
214   if ((HashMask & PcdGet32 (PcdTpm2HashMask)) == 0) {
215     return EFI_UNSUPPORTED;
216   }
217 
218   if (mHashInterfaceCount >= sizeof(mHashInterface)/sizeof(mHashInterface[0])) {
219     return EFI_OUT_OF_RESOURCES;
220   }
221   BiosSupportedHashMask = PcdGet32 (PcdTcg2HashAlgorithmBitmap);
222   Status = PcdSet32S (PcdTcg2HashAlgorithmBitmap, BiosSupportedHashMask | HashMask);
223   ASSERT_EFI_ERROR (Status);
224 
225   //
226   // Check duplication
227   //
228   for (Index = 0; Index < mHashInterfaceCount; Index++) {
229     if (CompareGuid (&mHashInterface[Index].HashGuid, &HashInterface->HashGuid)) {
230       return EFI_ALREADY_STARTED;
231     }
232   }
233 
234   CopyMem (&mHashInterface[mHashInterfaceCount], HashInterface, sizeof(*HashInterface));
235   mHashInterfaceCount ++;
236 
237   return EFI_SUCCESS;
238 }