]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
SecurityPkg: Fix few typos
[mirror_edk2.git] / SecurityPkg / Library / HashLibBaseCryptoRouter / HashLibBaseCryptoRouterPei.c
1 /** @file
2 This library is BaseCrypto router. It will redirect hash request to each individual
3 hash handler registered, such as SHA1, SHA256.
4 Platform can use PcdTpm2HashMask to mask some hash engines.
5
6 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include <PiPei.h>
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/Tpm2CommandLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/PcdLib.h>
18 #include <Library/HobLib.h>
19 #include <Library/HashLib.h>
20 #include <Guid/ZeroGuid.h>
21
22 #include "HashLibBaseCryptoRouterCommon.h"
23
24 #define HASH_LIB_PEI_ROUTER_GUID \
25 { 0x84681c08, 0x6873, 0x46f3, { 0x8b, 0xb7, 0xab, 0x66, 0x18, 0x95, 0xa1, 0xb3 } }
26
27 EFI_GUID mHashLibPeiRouterGuid = HASH_LIB_PEI_ROUTER_GUID;
28
29 typedef struct {
30 //
31 // If gZeroGuid, SupportedHashMask is 0 for FIRST module which consumes HashLib
32 // or the hash algorithm bitmap of LAST module which consumes HashLib.
33 // HashInterfaceCount and HashInterface are all 0.
34 // If gEfiCallerIdGuid, HashInterfaceCount, HashInterface and SupportedHashMask
35 // are the hash interface information of CURRENT module which consumes HashLib.
36 //
37 EFI_GUID Identifier;
38 UINTN HashInterfaceCount;
39 HASH_INTERFACE HashInterface[HASH_COUNT];
40 UINT32 SupportedHashMask;
41 } HASH_INTERFACE_HOB;
42
43 /**
44 This function gets hash interface hob.
45
46 @param Identifier Identifier to get hash interface hob.
47
48 @retval hash interface hob.
49 **/
50 HASH_INTERFACE_HOB *
51 InternalGetHashInterfaceHob (
52 EFI_GUID *Identifier
53 )
54 {
55 EFI_PEI_HOB_POINTERS Hob;
56 HASH_INTERFACE_HOB *HashInterfaceHob;
57
58 Hob.Raw = GetFirstGuidHob (&mHashLibPeiRouterGuid);
59 while (Hob.Raw != NULL) {
60 HashInterfaceHob = GET_GUID_HOB_DATA (Hob);
61 if (CompareGuid (&HashInterfaceHob->Identifier, Identifier)) {
62 //
63 // Found the matched one.
64 //
65 return HashInterfaceHob;
66 }
67 Hob.Raw = GET_NEXT_HOB (Hob);
68 Hob.Raw = GetNextGuidHob (&mHashLibPeiRouterGuid, Hob.Raw);
69 }
70 return NULL;
71 }
72
73 /**
74 This function creates hash interface hob.
75
76 @param Identifier Identifier to create hash interface hob.
77
78 @retval hash interface hob.
79 **/
80 HASH_INTERFACE_HOB *
81 InternalCreateHashInterfaceHob (
82 EFI_GUID *Identifier
83 )
84 {
85 HASH_INTERFACE_HOB LocalHashInterfaceHob;
86
87 ZeroMem (&LocalHashInterfaceHob, sizeof(LocalHashInterfaceHob));
88 CopyGuid (&LocalHashInterfaceHob.Identifier, Identifier);
89 return BuildGuidDataHob (&mHashLibPeiRouterGuid, &LocalHashInterfaceHob, sizeof(LocalHashInterfaceHob));
90 }
91
92 /**
93 Check mismatch of supported HashMask between modules
94 that may link different HashInstanceLib instances.
95
96 @param HashInterfaceHobCurrent Pointer to hash interface hob for CURRENT module.
97
98 **/
99 VOID
100 CheckSupportedHashMaskMismatch (
101 IN HASH_INTERFACE_HOB *HashInterfaceHobCurrent
102 )
103 {
104 HASH_INTERFACE_HOB *HashInterfaceHobLast;
105
106 HashInterfaceHobLast = InternalGetHashInterfaceHob (&gZeroGuid);
107 ASSERT (HashInterfaceHobLast != NULL);
108
109 if ((HashInterfaceHobLast->SupportedHashMask != 0) &&
110 (HashInterfaceHobCurrent->SupportedHashMask != HashInterfaceHobLast->SupportedHashMask)) {
111 DEBUG ((
112 DEBUG_WARN,
113 "WARNING: There is mismatch of supported HashMask (0x%x - 0x%x) between modules\n",
114 HashInterfaceHobCurrent->SupportedHashMask,
115 HashInterfaceHobLast->SupportedHashMask
116 ));
117 DEBUG ((DEBUG_WARN, "that are linking different HashInstanceLib instances!\n"));
118 }
119 }
120
121 /**
122 Start hash sequence.
123
124 @param HashHandle Hash handle.
125
126 @retval EFI_SUCCESS Hash sequence start and HandleHandle returned.
127 @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.
128 **/
129 EFI_STATUS
130 EFIAPI
131 HashStart (
132 OUT HASH_HANDLE *HashHandle
133 )
134 {
135 HASH_INTERFACE_HOB *HashInterfaceHob;
136 HASH_HANDLE *HashCtx;
137 UINTN Index;
138 UINT32 HashMask;
139
140 HashInterfaceHob = InternalGetHashInterfaceHob (&gEfiCallerIdGuid);
141 if (HashInterfaceHob == NULL) {
142 return EFI_UNSUPPORTED;
143 }
144
145 if (HashInterfaceHob->HashInterfaceCount == 0) {
146 return EFI_UNSUPPORTED;
147 }
148
149 CheckSupportedHashMaskMismatch (HashInterfaceHob);
150
151 HashCtx = AllocatePool (sizeof(*HashCtx) * HashInterfaceHob->HashInterfaceCount);
152 ASSERT (HashCtx != NULL);
153
154 for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {
155 HashMask = Tpm2GetHashMaskFromAlgo (&HashInterfaceHob->HashInterface[Index].HashGuid);
156 if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) {
157 HashInterfaceHob->HashInterface[Index].HashInit (&HashCtx[Index]);
158 }
159 }
160
161 *HashHandle = (HASH_HANDLE)HashCtx;
162
163 return EFI_SUCCESS;
164 }
165
166 /**
167 Update hash sequence data.
168
169 @param HashHandle Hash handle.
170 @param DataToHash Data to be hashed.
171 @param DataToHashLen Data size.
172
173 @retval EFI_SUCCESS Hash sequence updated.
174 **/
175 EFI_STATUS
176 EFIAPI
177 HashUpdate (
178 IN HASH_HANDLE HashHandle,
179 IN VOID *DataToHash,
180 IN UINTN DataToHashLen
181 )
182 {
183 HASH_INTERFACE_HOB *HashInterfaceHob;
184 HASH_HANDLE *HashCtx;
185 UINTN Index;
186 UINT32 HashMask;
187
188 HashInterfaceHob = InternalGetHashInterfaceHob (&gEfiCallerIdGuid);
189 if (HashInterfaceHob == NULL) {
190 return EFI_UNSUPPORTED;
191 }
192
193 if (HashInterfaceHob->HashInterfaceCount == 0) {
194 return EFI_UNSUPPORTED;
195 }
196
197 CheckSupportedHashMaskMismatch (HashInterfaceHob);
198
199 HashCtx = (HASH_HANDLE *)HashHandle;
200
201 for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {
202 HashMask = Tpm2GetHashMaskFromAlgo (&HashInterfaceHob->HashInterface[Index].HashGuid);
203 if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) {
204 HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);
205 }
206 }
207
208 return EFI_SUCCESS;
209 }
210
211 /**
212 Hash sequence complete and extend to PCR.
213
214 @param HashHandle Hash handle.
215 @param PcrIndex PCR to be extended.
216 @param DataToHash Data to be hashed.
217 @param DataToHashLen Data size.
218 @param DigestList Digest list.
219
220 @retval EFI_SUCCESS Hash sequence complete and DigestList is returned.
221 **/
222 EFI_STATUS
223 EFIAPI
224 HashCompleteAndExtend (
225 IN HASH_HANDLE HashHandle,
226 IN TPMI_DH_PCR PcrIndex,
227 IN VOID *DataToHash,
228 IN UINTN DataToHashLen,
229 OUT TPML_DIGEST_VALUES *DigestList
230 )
231 {
232 TPML_DIGEST_VALUES Digest;
233 HASH_INTERFACE_HOB *HashInterfaceHob;
234 HASH_HANDLE *HashCtx;
235 UINTN Index;
236 EFI_STATUS Status;
237 UINT32 HashMask;
238
239 HashInterfaceHob = InternalGetHashInterfaceHob (&gEfiCallerIdGuid);
240 if (HashInterfaceHob == NULL) {
241 return EFI_UNSUPPORTED;
242 }
243
244 if (HashInterfaceHob->HashInterfaceCount == 0) {
245 return EFI_UNSUPPORTED;
246 }
247
248 CheckSupportedHashMaskMismatch (HashInterfaceHob);
249
250 HashCtx = (HASH_HANDLE *)HashHandle;
251 ZeroMem (DigestList, sizeof(*DigestList));
252
253 for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {
254 HashMask = Tpm2GetHashMaskFromAlgo (&HashInterfaceHob->HashInterface[Index].HashGuid);
255 if ((HashMask & PcdGet32 (PcdTpm2HashMask)) != 0) {
256 HashInterfaceHob->HashInterface[Index].HashUpdate (HashCtx[Index], DataToHash, DataToHashLen);
257 HashInterfaceHob->HashInterface[Index].HashFinal (HashCtx[Index], &Digest);
258 Tpm2SetHashToDigestList (DigestList, &Digest);
259 }
260 }
261
262 FreePool (HashCtx);
263
264 Status = Tpm2PcrExtend (
265 PcrIndex,
266 DigestList
267 );
268 return Status;
269 }
270
271 /**
272 Hash data and extend to PCR.
273
274 @param PcrIndex PCR to be extended.
275 @param DataToHash Data to be hashed.
276 @param DataToHashLen Data size.
277 @param DigestList Digest list.
278
279 @retval EFI_SUCCESS Hash data and DigestList is returned.
280 **/
281 EFI_STATUS
282 EFIAPI
283 HashAndExtend (
284 IN TPMI_DH_PCR PcrIndex,
285 IN VOID *DataToHash,
286 IN UINTN DataToHashLen,
287 OUT TPML_DIGEST_VALUES *DigestList
288 )
289 {
290 HASH_INTERFACE_HOB *HashInterfaceHob;
291 HASH_HANDLE HashHandle;
292 EFI_STATUS Status;
293
294 HashInterfaceHob = InternalGetHashInterfaceHob (&gEfiCallerIdGuid);
295 if (HashInterfaceHob == NULL) {
296 return EFI_UNSUPPORTED;
297 }
298
299 if (HashInterfaceHob->HashInterfaceCount == 0) {
300 return EFI_UNSUPPORTED;
301 }
302
303 CheckSupportedHashMaskMismatch (HashInterfaceHob);
304
305 HashStart (&HashHandle);
306 HashUpdate (HashHandle, DataToHash, DataToHashLen);
307 Status = HashCompleteAndExtend (HashHandle, PcrIndex, NULL, 0, DigestList);
308
309 return Status;
310 }
311
312 /**
313 This service register Hash.
314
315 @param HashInterface Hash interface
316
317 @retval EFI_SUCCESS This hash interface is registered successfully.
318 @retval EFI_UNSUPPORTED System does not support register this interface.
319 @retval EFI_ALREADY_STARTED System already register this interface.
320 **/
321 EFI_STATUS
322 EFIAPI
323 RegisterHashInterfaceLib (
324 IN HASH_INTERFACE *HashInterface
325 )
326 {
327 UINTN Index;
328 HASH_INTERFACE_HOB *HashInterfaceHob;
329 UINT32 HashMask;
330 EFI_STATUS Status;
331
332 //
333 // Check allow
334 //
335 HashMask = Tpm2GetHashMaskFromAlgo (&HashInterface->HashGuid);
336 if ((HashMask & PcdGet32 (PcdTpm2HashMask)) == 0) {
337 return EFI_UNSUPPORTED;
338 }
339
340 HashInterfaceHob = InternalGetHashInterfaceHob (&gEfiCallerIdGuid);
341 if (HashInterfaceHob == NULL) {
342 HashInterfaceHob = InternalCreateHashInterfaceHob (&gEfiCallerIdGuid);
343 if (HashInterfaceHob == NULL) {
344 return EFI_OUT_OF_RESOURCES;
345 }
346 }
347
348 if (HashInterfaceHob->HashInterfaceCount >= HASH_COUNT) {
349 return EFI_OUT_OF_RESOURCES;
350 }
351
352 //
353 // Check duplication
354 //
355 for (Index = 0; Index < HashInterfaceHob->HashInterfaceCount; Index++) {
356 if (CompareGuid (&HashInterfaceHob->HashInterface[Index].HashGuid, &HashInterface->HashGuid)) {
357 DEBUG ((DEBUG_ERROR, "Hash Interface (%g) has been registered\n", &HashInterface->HashGuid));
358 return EFI_ALREADY_STARTED;
359 }
360 }
361
362 //
363 // Record hash algorithm bitmap of CURRENT module which consumes HashLib.
364 //
365 HashInterfaceHob->SupportedHashMask = PcdGet32 (PcdTcg2HashAlgorithmBitmap) | HashMask;
366 Status = PcdSet32S (PcdTcg2HashAlgorithmBitmap, HashInterfaceHob->SupportedHashMask);
367 ASSERT_EFI_ERROR (Status);
368
369 CopyMem (&HashInterfaceHob->HashInterface[HashInterfaceHob->HashInterfaceCount], HashInterface, sizeof(*HashInterface));
370 HashInterfaceHob->HashInterfaceCount ++;
371
372 return EFI_SUCCESS;
373 }
374
375 /**
376 The constructor function of HashLibBaseCryptoRouterPei.
377
378 @param FileHandle The handle of FFS header the loaded driver.
379 @param PeiServices The pointer to the PEI services.
380
381 @retval EFI_SUCCESS The constructor executes successfully.
382 @retval EFI_OUT_OF_RESOURCES There is no enough resource for the constructor.
383
384 **/
385 EFI_STATUS
386 EFIAPI
387 HashLibBaseCryptoRouterPeiConstructor (
388 IN EFI_PEI_FILE_HANDLE FileHandle,
389 IN CONST EFI_PEI_SERVICES **PeiServices
390 )
391 {
392 EFI_STATUS Status;
393 HASH_INTERFACE_HOB *HashInterfaceHob;
394
395 HashInterfaceHob = InternalGetHashInterfaceHob (&gZeroGuid);
396 if (HashInterfaceHob == NULL) {
397 //
398 // No HOB with gZeroGuid Identifier has been created,
399 // this is FIRST module which consumes HashLib.
400 // Create the HOB with gZeroGuid Identifier.
401 //
402 HashInterfaceHob = InternalCreateHashInterfaceHob (&gZeroGuid);
403 if (HashInterfaceHob == NULL) {
404 return EFI_OUT_OF_RESOURCES;
405 }
406 } else {
407 //
408 // Record hash algorithm bitmap of LAST module which also consumes HashLib.
409 //
410 HashInterfaceHob->SupportedHashMask = PcdGet32 (PcdTcg2HashAlgorithmBitmap);
411 }
412
413 HashInterfaceHob = InternalGetHashInterfaceHob (&gEfiCallerIdGuid);
414 if (HashInterfaceHob != NULL) {
415 //
416 // In PEI phase, some modules may call RegisterForShadow and will be
417 // shadowed and executed again after memory is discovered.
418 // This is the second execution of this module, clear the hash interface
419 // information registered at its first execution.
420 //
421 ZeroMem (&HashInterfaceHob->HashInterface, sizeof (HashInterfaceHob->HashInterface));
422 HashInterfaceHob->HashInterfaceCount = 0;
423 HashInterfaceHob->SupportedHashMask = 0;
424 }
425
426 //
427 // Set PcdTcg2HashAlgorithmBitmap to 0 in CONSTRUCTOR for CURRENT module.
428 //
429 Status = PcdSet32S (PcdTcg2HashAlgorithmBitmap, 0);
430 ASSERT_EFI_ERROR (Status);
431
432 return EFI_SUCCESS;
433 }