]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.c
OvmfPkg/Csm/LegacyBiosDxe: Update to make it build for OVMF
[mirror_edk2.git] / SecurityPkg / Hash2DxeCrypto / Hash2DxeCrypto.c
1 /** @file
2 This module implements Hash2 Protocol.
3
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <Uefi.h>
11 #include <Protocol/Hash2.h>
12 #include <Library/BaseLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Library/MemoryAllocationLib.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/BaseCryptLib.h>
18
19 #include "Driver.h"
20
21 /**
22 Retrieves the size, in bytes, of the context buffer required for hash operations.
23
24 If this interface is not supported, then return zero.
25
26 @return The size, in bytes, of the context buffer required for hash operations.
27 @retval 0 This interface is not supported.
28
29 **/
30 typedef
31 UINTN
32 (EFIAPI *EFI_HASH_GET_CONTEXT_SIZE) (
33 VOID
34 );
35
36 /**
37 Initializes user-supplied memory pointed by Sha1Context as hash context for
38 subsequent use.
39
40 If HashContext is NULL, then return FALSE.
41 If this interface is not supported, then return FALSE.
42
43 @param[out] HashContext Pointer to Hashcontext being initialized.
44
45 @retval TRUE Hash context initialization succeeded.
46 @retval FALSE Hash context initialization failed.
47 @retval FALSE This interface is not supported.
48
49 **/
50 typedef
51 BOOLEAN
52 (EFIAPI *EFI_HASH_INIT) (
53 OUT VOID *HashContext
54 );
55
56 /**
57 Digests the input data and updates Hash context.
58
59 This function performs Hash digest on a data buffer of the specified size.
60 It can be called multiple times to compute the digest of long or discontinuous data streams.
61 Hash context should be already correctly initialized by HashInit(), and should not be finalized
62 by HashFinal(). Behavior with invalid context is undefined.
63
64 If HashContext is NULL, then return FALSE.
65 If this interface is not supported, then return FALSE.
66
67 @param[in, out] HashContext Pointer to the Hash context.
68 @param[in] Data Pointer to the buffer containing the data to be hashed.
69 @param[in] DataSize Size of Data buffer in bytes.
70
71 @retval TRUE SHA-1 data digest succeeded.
72 @retval FALSE SHA-1 data digest failed.
73 @retval FALSE This interface is not supported.
74
75 **/
76 typedef
77 BOOLEAN
78 (EFIAPI *EFI_HASH_UPDATE) (
79 IN OUT VOID *HashContext,
80 IN CONST VOID *Data,
81 IN UINTN DataSize
82 );
83
84 /**
85 Completes computation of the Hash digest value.
86
87 This function completes hash computation and retrieves the digest value into
88 the specified memory. After this function has been called, the Hash context cannot
89 be used again.
90 Hash context should be already correctly intialized by HashInit(), and should not be
91 finalized by HashFinal(). Behavior with invalid Hash context is undefined.
92
93 If HashContext is NULL, then return FALSE.
94 If HashValue is NULL, then return FALSE.
95 If this interface is not supported, then return FALSE.
96
97 @param[in, out] HashContext Pointer to the Hash context.
98 @param[out] HashValue Pointer to a buffer that receives the Hash digest
99 value.
100
101 @retval TRUE Hash digest computation succeeded.
102 @retval FALSE Hash digest computation failed.
103 @retval FALSE This interface is not supported.
104
105 **/
106 typedef
107 BOOLEAN
108 (EFIAPI *EFI_HASH_FINAL) (
109 IN OUT VOID *HashContext,
110 OUT UINT8 *HashValue
111 );
112
113 typedef struct {
114 EFI_GUID *Guid;
115 UINT32 HashSize;
116 EFI_HASH_GET_CONTEXT_SIZE GetContextSize;
117 EFI_HASH_INIT Init;
118 EFI_HASH_UPDATE Update;
119 EFI_HASH_FINAL Final;
120 } EFI_HASH_INFO;
121
122 EFI_HASH_INFO mHashInfo[] = {
123 {&gEfiHashAlgorithmMD5Guid, sizeof(EFI_MD5_HASH2), Md5GetContextSize, Md5Init, Md5Update, Md5Final },
124 {&gEfiHashAlgorithmSha1Guid, sizeof(EFI_SHA1_HASH2), Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
125 {&gEfiHashAlgorithmSha256Guid, sizeof(EFI_SHA256_HASH2), Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final },
126 {&gEfiHashAlgorithmSha384Guid, sizeof(EFI_SHA384_HASH2), Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final },
127 {&gEfiHashAlgorithmSha512Guid, sizeof(EFI_SHA512_HASH2), Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final },
128 };
129
130 /**
131 Returns the size of the hash which results from a specific algorithm.
132
133 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
134 @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
135 @param[out] HashSize Holds the returned size of the algorithm's hash.
136
137 @retval EFI_SUCCESS Hash size returned successfully.
138 @retval EFI_INVALID_PARAMETER This or HashSize is NULL.
139 @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this driver
140 or HashAlgorithm is null.
141
142 **/
143 EFI_STATUS
144 EFIAPI
145 BaseCrypto2GetHashSize (
146 IN CONST EFI_HASH2_PROTOCOL *This,
147 IN CONST EFI_GUID *HashAlgorithm,
148 OUT UINTN *HashSize
149 );
150
151 /**
152 Creates a hash for the specified message text. The hash is not extendable.
153 The output is final with any algorithm-required padding added by the function.
154
155 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
156 @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
157 @param[in] Message Points to the start of the message.
158 @param[in] MessageSize The size of Message, in bytes.
159 @param[in,out] Hash On input, points to a caller-allocated buffer of the size
160 returned by GetHashSize() for the specified HashAlgorithm.
161 On output, the buffer holds the resulting hash computed from the message.
162
163 @retval EFI_SUCCESS Hash returned successfully.
164 @retval EFI_INVALID_PARAMETER This or Hash is NULL.
165 @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this driver
166 or HashAlgorithm is Null.
167 @retval EFI_OUT_OF_RESOURCES Some resource required by the function is not available
168 or MessageSize is greater than platform maximum.
169
170 **/
171 EFI_STATUS
172 EFIAPI
173 BaseCrypto2Hash (
174 IN CONST EFI_HASH2_PROTOCOL *This,
175 IN CONST EFI_GUID *HashAlgorithm,
176 IN CONST UINT8 *Message,
177 IN UINTN MessageSize,
178 IN OUT EFI_HASH2_OUTPUT *Hash
179 );
180
181 /**
182 This function must be called to initialize a digest calculation to be subsequently performed using the
183 EFI_HASH2_PROTOCOL functions HashUpdate() and HashFinal().
184
185 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
186 @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
187
188 @retval EFI_SUCCESS Initialized successfully.
189 @retval EFI_INVALID_PARAMETER This is NULL.
190 @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this driver
191 or HashAlgorithm is Null.
192 @retval EFI_OUT_OF_RESOURCES Process failed due to lack of required resource.
193 @retval EFI_ALREADY_STARTED This function is called when the operation in progress is still in processing Hash(),
194 or HashInit() is already called before and not terminated by HashFinal() yet on the same instance.
195
196 **/
197 EFI_STATUS
198 EFIAPI
199 BaseCrypto2HashInit (
200 IN CONST EFI_HASH2_PROTOCOL *This,
201 IN CONST EFI_GUID *HashAlgorithm
202 );
203
204 /**
205 Updates the hash of a computation in progress by adding a message text.
206
207 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
208 @param[in] Message Points to the start of the message.
209 @param[in] MessageSize The size of Message, in bytes.
210
211 @retval EFI_SUCCESS Digest in progress updated successfully.
212 @retval EFI_INVALID_PARAMETER This or Hash is NULL.
213 @retval EFI_OUT_OF_RESOURCES Some resource required by the function is not available
214 or MessageSize is greater than platform maximum.
215 @retval EFI_NOT_READY This call was not preceded by a valid call to HashInit(),
216 or the operation in progress was terminated by a call to Hash() or HashFinal() on the same instance.
217
218 **/
219 EFI_STATUS
220 EFIAPI
221 BaseCrypto2HashUpdate (
222 IN CONST EFI_HASH2_PROTOCOL *This,
223 IN CONST UINT8 *Message,
224 IN UINTN MessageSize
225 );
226
227 /**
228 Finalizes a hash operation in progress and returns calculation result.
229 The output is final with any necessary padding added by the function.
230 The hash may not be further updated or extended after HashFinal().
231
232 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
233 @param[in,out] Hash On input, points to a caller-allocated buffer of the size
234 returned by GetHashSize() for the specified HashAlgorithm specified in preceding HashInit().
235 On output, the buffer holds the resulting hash computed from the message.
236
237 @retval EFI_SUCCESS Hash returned successfully.
238 @retval EFI_INVALID_PARAMETER This or Hash is NULL.
239 @retval EFI_NOT_READY This call was not preceded by a valid call to HashInit() and at least one call to HashUpdate(),
240 or the operation in progress was canceled by a call to Hash() on the same instance.
241
242 **/
243 EFI_STATUS
244 EFIAPI
245 BaseCrypto2HashFinal (
246 IN CONST EFI_HASH2_PROTOCOL *This,
247 IN OUT EFI_HASH2_OUTPUT *Hash
248 );
249
250 EFI_HASH2_PROTOCOL mHash2Protocol = {
251 BaseCrypto2GetHashSize,
252 BaseCrypto2Hash,
253 BaseCrypto2HashInit,
254 BaseCrypto2HashUpdate,
255 BaseCrypto2HashFinal,
256 };
257
258 /**
259 Returns hash information.
260
261 @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
262
263 @return Hash information.
264 **/
265 EFI_HASH_INFO *
266 GetHashInfo (
267 IN CONST EFI_GUID *HashAlgorithm
268 )
269 {
270 UINTN Index;
271
272 for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) {
273 if (CompareGuid (HashAlgorithm, mHashInfo[Index].Guid)) {
274 return &mHashInfo[Index];
275 }
276 }
277 return NULL;
278 }
279
280 /**
281 Returns the size of the hash which results from a specific algorithm.
282
283 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
284 @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
285 @param[out] HashSize Holds the returned size of the algorithm's hash.
286
287 @retval EFI_SUCCESS Hash size returned successfully.
288 @retval EFI_INVALID_PARAMETER This or HashSize is NULL.
289 @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this driver
290 or HashAlgorithm is null.
291
292 **/
293 EFI_STATUS
294 EFIAPI
295 BaseCrypto2GetHashSize (
296 IN CONST EFI_HASH2_PROTOCOL *This,
297 IN CONST EFI_GUID *HashAlgorithm,
298 OUT UINTN *HashSize
299 )
300 {
301 EFI_HASH_INFO *HashInfo;
302
303 if ((This == NULL) || (HashSize == NULL)) {
304 return EFI_INVALID_PARAMETER;
305 }
306
307 if (HashAlgorithm == NULL) {
308 return EFI_UNSUPPORTED;
309 }
310
311 HashInfo = GetHashInfo (HashAlgorithm);
312 if (HashInfo == NULL) {
313 return EFI_UNSUPPORTED;
314 }
315
316 *HashSize = HashInfo->HashSize;
317 return EFI_SUCCESS;
318 }
319
320 /**
321 Creates a hash for the specified message text. The hash is not extendable.
322 The output is final with any algorithm-required padding added by the function.
323
324 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
325 @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
326 @param[in] Message Points to the start of the message.
327 @param[in] MessageSize The size of Message, in bytes.
328 @param[in,out] Hash On input, points to a caller-allocated buffer of the size
329 returned by GetHashSize() for the specified HashAlgorithm.
330 On output, the buffer holds the resulting hash computed from the message.
331
332 @retval EFI_SUCCESS Hash returned successfully.
333 @retval EFI_INVALID_PARAMETER This or Hash is NULL.
334 @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this driver
335 or HashAlgorithm is Null.
336 @retval EFI_OUT_OF_RESOURCES Some resource required by the function is not available
337 or MessageSize is greater than platform maximum.
338
339 **/
340 EFI_STATUS
341 EFIAPI
342 BaseCrypto2Hash (
343 IN CONST EFI_HASH2_PROTOCOL *This,
344 IN CONST EFI_GUID *HashAlgorithm,
345 IN CONST UINT8 *Message,
346 IN UINTN MessageSize,
347 IN OUT EFI_HASH2_OUTPUT *Hash
348 )
349 {
350 EFI_HASH_INFO *HashInfo;
351 VOID *HashCtx;
352 UINTN CtxSize;
353 BOOLEAN Ret;
354 EFI_STATUS Status;
355 HASH2_INSTANCE_DATA *Instance;
356
357 Status = EFI_SUCCESS;
358
359 if ((This == NULL) || (Hash == NULL)) {
360 return EFI_INVALID_PARAMETER;
361 }
362
363 if (HashAlgorithm == NULL) {
364 return EFI_UNSUPPORTED;
365 }
366
367 HashInfo = GetHashInfo (HashAlgorithm);
368 if (HashInfo == NULL) {
369 return EFI_UNSUPPORTED;
370 }
371
372 Instance = HASH2_INSTANCE_DATA_FROM_THIS(This);
373 if (Instance->HashContext != NULL) {
374 FreePool (Instance->HashContext);
375 }
376 Instance->HashInfoContext = NULL;
377 Instance->HashContext = NULL;
378
379 //
380 // Start hash sequence
381 //
382 CtxSize = HashInfo->GetContextSize ();
383 if (CtxSize == 0) {
384 return EFI_UNSUPPORTED;
385 }
386 HashCtx = AllocatePool (CtxSize);
387 if (HashCtx == NULL) {
388 return EFI_OUT_OF_RESOURCES;
389 }
390
391 Ret = HashInfo->Init (HashCtx);
392 if (!Ret) {
393 Status = EFI_OUT_OF_RESOURCES;
394 goto Done;
395 }
396
397 //
398 // Setup the context
399 //
400 Instance->HashContext = HashCtx;
401 Instance->HashInfoContext = HashInfo;
402
403 Ret = HashInfo->Update (HashCtx, Message, MessageSize);
404 if (!Ret) {
405 Status = EFI_OUT_OF_RESOURCES;
406 goto Done;
407 }
408
409 Ret = HashInfo->Final (HashCtx, (UINT8 *)Hash->Sha1Hash);
410 if (!Ret) {
411 Status = EFI_OUT_OF_RESOURCES;
412 goto Done;
413 }
414 Done:
415 //
416 // Cleanup the context
417 //
418 FreePool (HashCtx);
419 Instance->HashInfoContext = NULL;
420 Instance->HashContext = NULL;
421 return Status;
422 }
423
424 /**
425 This function must be called to initialize a digest calculation to be subsequently performed using the
426 EFI_HASH2_PROTOCOL functions HashUpdate() and HashFinal().
427
428 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
429 @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
430
431 @retval EFI_SUCCESS Initialized successfully.
432 @retval EFI_INVALID_PARAMETER This is NULL.
433 @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this driver
434 or HashAlgorithm is Null.
435 @retval EFI_OUT_OF_RESOURCES Process failed due to lack of required resource.
436 @retval EFI_ALREADY_STARTED This function is called when the operation in progress is still in processing Hash(),
437 or HashInit() is already called before and not terminated by HashFinal() yet on the same instance.
438
439 **/
440 EFI_STATUS
441 EFIAPI
442 BaseCrypto2HashInit (
443 IN CONST EFI_HASH2_PROTOCOL *This,
444 IN CONST EFI_GUID *HashAlgorithm
445 )
446 {
447 EFI_HASH_INFO *HashInfo;
448 VOID *HashCtx;
449 UINTN CtxSize;
450 BOOLEAN Ret;
451 HASH2_INSTANCE_DATA *Instance;
452
453 if (This == NULL) {
454 return EFI_INVALID_PARAMETER;
455 }
456
457 if (HashAlgorithm == NULL) {
458 return EFI_UNSUPPORTED;
459 }
460
461 HashInfo = GetHashInfo (HashAlgorithm);
462 if (HashInfo == NULL) {
463 return EFI_UNSUPPORTED;
464 }
465
466 //
467 // Consistency Check
468 //
469 Instance = HASH2_INSTANCE_DATA_FROM_THIS(This);
470 if ((Instance->HashContext != NULL) || (Instance->HashInfoContext != NULL)) {
471 return EFI_ALREADY_STARTED;
472 }
473
474 //
475 // Start hash sequence
476 //
477 CtxSize = HashInfo->GetContextSize ();
478 if (CtxSize == 0) {
479 return EFI_UNSUPPORTED;
480 }
481 HashCtx = AllocatePool (CtxSize);
482 if (HashCtx == NULL) {
483 return EFI_OUT_OF_RESOURCES;
484 }
485
486 Ret = HashInfo->Init (HashCtx);
487 if (!Ret) {
488 FreePool (HashCtx);
489 return EFI_OUT_OF_RESOURCES;
490 }
491
492 //
493 // Setup the context
494 //
495 Instance->HashContext = HashCtx;
496 Instance->HashInfoContext = HashInfo;
497 Instance->Updated = FALSE;
498
499 return EFI_SUCCESS;
500 }
501
502 /**
503 Updates the hash of a computation in progress by adding a message text.
504
505 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
506 @param[in] Message Points to the start of the message.
507 @param[in] MessageSize The size of Message, in bytes.
508
509 @retval EFI_SUCCESS Digest in progress updated successfully.
510 @retval EFI_INVALID_PARAMETER This or Hash is NULL.
511 @retval EFI_OUT_OF_RESOURCES Some resource required by the function is not available
512 or MessageSize is greater than platform maximum.
513 @retval EFI_NOT_READY This call was not preceded by a valid call to HashInit(),
514 or the operation in progress was terminated by a call to Hash() or HashFinal() on the same instance.
515
516 **/
517 EFI_STATUS
518 EFIAPI
519 BaseCrypto2HashUpdate (
520 IN CONST EFI_HASH2_PROTOCOL *This,
521 IN CONST UINT8 *Message,
522 IN UINTN MessageSize
523 )
524 {
525 EFI_HASH_INFO *HashInfo;
526 VOID *HashCtx;
527 BOOLEAN Ret;
528 HASH2_INSTANCE_DATA *Instance;
529
530 if (This == NULL) {
531 return EFI_INVALID_PARAMETER;
532 }
533
534 //
535 // Consistency Check
536 //
537 Instance = HASH2_INSTANCE_DATA_FROM_THIS(This);
538 if ((Instance->HashContext == NULL) || (Instance->HashInfoContext == NULL)) {
539 return EFI_NOT_READY;
540 }
541 HashInfo = Instance->HashInfoContext;
542 HashCtx = Instance->HashContext;
543
544 Ret = HashInfo->Update (HashCtx, Message, MessageSize);
545 if (!Ret) {
546 return EFI_OUT_OF_RESOURCES;
547 }
548
549 Instance->Updated = TRUE;
550
551 return EFI_SUCCESS;
552 }
553
554 /**
555 Finalizes a hash operation in progress and returns calculation result.
556 The output is final with any necessary padding added by the function.
557 The hash may not be further updated or extended after HashFinal().
558
559 @param[in] This Points to this instance of EFI_HASH2_PROTOCOL.
560 @param[in,out] Hash On input, points to a caller-allocated buffer of the size
561 returned by GetHashSize() for the specified HashAlgorithm specified in preceding HashInit().
562 On output, the buffer holds the resulting hash computed from the message.
563
564 @retval EFI_SUCCESS Hash returned successfully.
565 @retval EFI_INVALID_PARAMETER This or Hash is NULL.
566 @retval EFI_NOT_READY This call was not preceded by a valid call to HashInit() and at least one call to HashUpdate(),
567 or the operation in progress was canceled by a call to Hash() on the same instance.
568
569 **/
570 EFI_STATUS
571 EFIAPI
572 BaseCrypto2HashFinal (
573 IN CONST EFI_HASH2_PROTOCOL *This,
574 IN OUT EFI_HASH2_OUTPUT *Hash
575 )
576 {
577 EFI_HASH_INFO *HashInfo;
578 VOID *HashCtx;
579 BOOLEAN Ret;
580 HASH2_INSTANCE_DATA *Instance;
581
582 if ((This == NULL) || (Hash == NULL)) {
583 return EFI_INVALID_PARAMETER;
584 }
585
586 //
587 // Consistency Check
588 //
589 Instance = HASH2_INSTANCE_DATA_FROM_THIS(This);
590 if ((Instance->HashContext == NULL) || (Instance->HashInfoContext == NULL) ||
591 (!Instance->Updated)) {
592 return EFI_NOT_READY;
593 }
594 HashInfo = Instance->HashInfoContext;
595 HashCtx = Instance->HashContext;
596
597 Ret = HashInfo->Final (HashCtx, (UINT8 *)Hash->Sha1Hash);
598
599 //
600 // Cleanup the context
601 //
602 FreePool (HashCtx);
603 Instance->HashInfoContext = NULL;
604 Instance->HashContext = NULL;
605 Instance->Updated = FALSE;
606
607 if (!Ret) {
608 return EFI_OUT_OF_RESOURCES;
609 }
610
611 return EFI_SUCCESS;
612 }