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