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/HobLib.h>
25 #include <Library/HashLib.h>
26 
27 #include "HashLibBaseCryptoRouterCommon.h"
28 
29 #define HASH_LIB_PEI_ROUTER_GUID \
30   { 0x84681c08, 0x6873, 0x46f3, { 0x8b, 0xb7, 0xab, 0x66, 0x18, 0x95, 0xa1, 0xb3 } }
31 
32 EFI_GUID mHashLibPeiRouterGuid = HASH_LIB_PEI_ROUTER_GUID;
33 
34 typedef struct {
35   UINTN            HashInterfaceCount;
36   HASH_INTERFACE   HashInterface[HASH_COUNT];
37 } HASH_INTERFACE_HOB;
38 
39 /**
40   This function get hash interface.
41 
42   @retval hash interface.
43 **/
44 HASH_INTERFACE_HOB *
InternalGetHashInterface(VOID)45 InternalGetHashInterface (
46   VOID
47   )
48 {
49   EFI_HOB_GUID_TYPE *Hob;
50 
51   Hob = GetFirstGuidHob (&mHashLibPeiRouterGuid);
52   if (Hob == NULL) {
53     return NULL;
54   }
55   return (HASH_INTERFACE_HOB *)(Hob + 1);
56 }
57 
58 /**
59   Start hash sequence.
60 
61   @param HashHandle Hash handle.
62 
63   @retval EFI_SUCCESS          Hash sequence start and HandleHandle returned.
64   @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.
65 **/
66 EFI_STATUS
67 EFIAPI
HashStart(OUT HASH_HANDLE * HashHandle)68 HashStart (
69   OUT HASH_HANDLE    *HashHandle
70   )
71 {
72   HASH_INTERFACE_HOB *HashInterfaceHob;
73   HASH_HANDLE        *HashCtx;
74   UINTN              Index;
75   UINT32             HashMask;
76 
77   HashInterfaceHob = InternalGetHashInterface ();
78   if (HashInterfaceHob == NULL) {
79     return EFI_UNSUPPORTED;
80   }
81 
82   if (HashInterfaceHob->HashInterfaceCount == 0) {
83     return EFI_UNSUPPORTED;
84   }
85 
86   HashCtx = AllocatePool (sizeof(*HashCtx) * HashInterfaceHob->HashInterfaceCount);
87   ASSERT (HashCtx != NULL);
88 
89   for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {
90     HashMask = Tpm2GetHashMaskFromAlgo (&HashInterfaceHob->HashInterface[Index].HashGuid);
91     if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) {
92       HashInterfaceHob->HashInterface[Index].HashInit (&HashCtx[Index]);
93     }
94   }
95 
96   *HashHandle = (HASH_HANDLE)HashCtx;
97 
98   return EFI_SUCCESS;
99 }
100 
101 /**
102   Update hash sequence data.
103 
104   @param HashHandle    Hash handle.
105   @param DataToHash    Data to be hashed.
106   @param DataToHashLen Data size.
107 
108   @retval EFI_SUCCESS     Hash sequence updated.
109 **/
110 EFI_STATUS
111 EFIAPI
HashUpdate(IN HASH_HANDLE HashHandle,IN VOID * DataToHash,IN UINTN DataToHashLen)112 HashUpdate (
113   IN HASH_HANDLE    HashHandle,
114   IN VOID           *DataToHash,
115   IN UINTN          DataToHashLen
116   )
117 {
118   HASH_INTERFACE_HOB *HashInterfaceHob;
119   HASH_HANDLE        *HashCtx;
120   UINTN              Index;
121   UINT32             HashMask;
122 
123   HashInterfaceHob = InternalGetHashInterface ();
124   if (HashInterfaceHob == NULL) {
125     return EFI_UNSUPPORTED;
126   }
127 
128   if (HashInterfaceHob->HashInterfaceCount == 0) {
129     return EFI_UNSUPPORTED;
130   }
131 
132   HashCtx = (HASH_HANDLE *)HashHandle;
133 
134   for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {
135     HashMask = Tpm2GetHashMaskFromAlgo (&HashInterfaceHob->HashInterface[Index].HashGuid);
136     if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) {
137       HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);
138     }
139   }
140 
141   return EFI_SUCCESS;
142 }
143 
144 /**
145   Hash sequence complete and extend to PCR.
146 
147   @param HashHandle    Hash handle.
148   @param PcrIndex      PCR to be extended.
149   @param DataToHash    Data to be hashed.
150   @param DataToHashLen Data size.
151   @param DigestList    Digest list.
152 
153   @retval EFI_SUCCESS     Hash sequence complete and DigestList is returned.
154 **/
155 EFI_STATUS
156 EFIAPI
HashCompleteAndExtend(IN HASH_HANDLE HashHandle,IN TPMI_DH_PCR PcrIndex,IN VOID * DataToHash,IN UINTN DataToHashLen,OUT TPML_DIGEST_VALUES * DigestList)157 HashCompleteAndExtend (
158   IN HASH_HANDLE         HashHandle,
159   IN TPMI_DH_PCR         PcrIndex,
160   IN VOID                *DataToHash,
161   IN UINTN               DataToHashLen,
162   OUT TPML_DIGEST_VALUES *DigestList
163   )
164 {
165   TPML_DIGEST_VALUES Digest;
166   HASH_INTERFACE_HOB *HashInterfaceHob;
167   HASH_HANDLE        *HashCtx;
168   UINTN              Index;
169   EFI_STATUS         Status;
170   UINT32             HashMask;
171 
172   HashInterfaceHob = InternalGetHashInterface ();
173   if (HashInterfaceHob == NULL) {
174     return EFI_UNSUPPORTED;
175   }
176 
177   if (HashInterfaceHob->HashInterfaceCount == 0) {
178     return EFI_UNSUPPORTED;
179   }
180 
181   HashCtx = (HASH_HANDLE *)HashHandle;
182   ZeroMem (DigestList, sizeof(*DigestList));
183 
184   for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {
185     HashMask = Tpm2GetHashMaskFromAlgo (&HashInterfaceHob->HashInterface[Index].HashGuid);
186     if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) {
187       HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);
188       HashInterfaceHob->HashInterface[Index].HashFinal (HashCtx[Index], &Digest);
189       Tpm2SetHashToDigestList (DigestList, &Digest);
190     }
191   }
192 
193   FreePool (HashCtx);
194 
195   Status = Tpm2PcrExtend (
196              PcrIndex,
197              DigestList
198              );
199   return Status;
200 }
201 
202 /**
203   Hash data and extend to PCR.
204 
205   @param PcrIndex      PCR to be extended.
206   @param DataToHash    Data to be hashed.
207   @param DataToHashLen Data size.
208   @param DigestList    Digest list.
209 
210   @retval EFI_SUCCESS     Hash data and DigestList is returned.
211 **/
212 EFI_STATUS
213 EFIAPI
HashAndExtend(IN TPMI_DH_PCR PcrIndex,IN VOID * DataToHash,IN UINTN DataToHashLen,OUT TPML_DIGEST_VALUES * DigestList)214 HashAndExtend (
215   IN TPMI_DH_PCR                    PcrIndex,
216   IN VOID                           *DataToHash,
217   IN UINTN                          DataToHashLen,
218   OUT TPML_DIGEST_VALUES            *DigestList
219   )
220 {
221   HASH_INTERFACE_HOB *HashInterfaceHob;
222   HASH_HANDLE        HashHandle;
223   EFI_STATUS         Status;
224 
225   HashInterfaceHob = InternalGetHashInterface ();
226   if (HashInterfaceHob == NULL) {
227     return EFI_UNSUPPORTED;
228   }
229 
230   if (HashInterfaceHob->HashInterfaceCount == 0) {
231     return EFI_UNSUPPORTED;
232   }
233 
234   HashStart (&HashHandle);
235   HashUpdate (HashHandle, DataToHash, DataToHashLen);
236   Status = HashCompleteAndExtend (HashHandle, PcrIndex, NULL, 0, DigestList);
237 
238   return Status;
239 }
240 
241 /**
242   This service register Hash.
243 
244   @param HashInterface  Hash interface
245 
246   @retval EFI_SUCCESS          This hash interface is registered successfully.
247   @retval EFI_UNSUPPORTED      System does not support register this interface.
248   @retval EFI_ALREADY_STARTED  System already register this interface.
249 **/
250 EFI_STATUS
251 EFIAPI
RegisterHashInterfaceLib(IN HASH_INTERFACE * HashInterface)252 RegisterHashInterfaceLib (
253   IN HASH_INTERFACE   *HashInterface
254   )
255 {
256   UINTN              Index;
257   HASH_INTERFACE_HOB *HashInterfaceHob;
258   HASH_INTERFACE_HOB LocalHashInterfaceHob;
259   UINT32             HashMask;
260   UINT32             BiosSupportedHashMask;
261   EFI_STATUS         Status;
262 
263   //
264   // Check allow
265   //
266   HashMask = Tpm2GetHashMaskFromAlgo (&HashInterface->HashGuid);
267   if ((HashMask & PcdGet32 (PcdTpm2HashMask)) == 0) {
268     return EFI_UNSUPPORTED;
269   }
270 
271   HashInterfaceHob = InternalGetHashInterface ();
272   if (HashInterfaceHob == NULL) {
273     ZeroMem (&LocalHashInterfaceHob, sizeof(LocalHashInterfaceHob));
274     HashInterfaceHob = BuildGuidDataHob (&mHashLibPeiRouterGuid, &LocalHashInterfaceHob, sizeof(LocalHashInterfaceHob));
275     if (HashInterfaceHob == NULL) {
276       return EFI_OUT_OF_RESOURCES;
277     }
278   }
279 
280   if (HashInterfaceHob->HashInterfaceCount >= HASH_COUNT) {
281     return EFI_OUT_OF_RESOURCES;
282   }
283   BiosSupportedHashMask = PcdGet32 (PcdTcg2HashAlgorithmBitmap);
284   Status = PcdSet32S (PcdTcg2HashAlgorithmBitmap, BiosSupportedHashMask | HashMask);
285   ASSERT_EFI_ERROR (Status);
286 
287   //
288   // Check duplication
289   //
290   for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {
291     if (CompareGuid (&HashInterfaceHob->HashInterface[Index].HashGuid, &HashInterface->HashGuid)) {
292       //
293       // In PEI phase, there will be shadow driver dispatched again.
294       //
295       DEBUG ((EFI_D_INFO, "RegisterHashInterfaceLib - Override\n"));
296       CopyMem (&HashInterfaceHob->HashInterface[Index], HashInterface, sizeof(*HashInterface));
297       return EFI_SUCCESS;
298     }
299   }
300 
301   CopyMem (&HashInterfaceHob->HashInterface[HashInterfaceHob->HashInterfaceCount], HashInterface, sizeof(*HashInterface));
302   HashInterfaceHob->HashInterfaceCount ++;
303 
304   return EFI_SUCCESS;
305 }