2 ParallelHash Implementation.
4 Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "CryptParallelHash.h"
10 #include <Library/SynchronizationLib.h>
12 #define PARALLELHASH_CUSTOMIZATION "ParallelHash"
18 UINTN mBlockResultSize
;
19 UINT8
*mBlockHashResult
;
20 BOOLEAN
*mBlockIsCompleted
;
21 SPIN_LOCK
*mSpinLockList
;
24 Complete computation of digest of each block.
26 Each AP perform the function called by BSP.
28 @param[in] ProcedureArgument Argument of the procedure.
32 ParallelHashApExecute (
33 IN VOID
*ProcedureArgument
39 for (Index
= 0; Index
< mBlockNum
; Index
++) {
40 if (AcquireSpinLockOrFail (&mSpinLockList
[Index
])) {
42 // Completed, try next one.
44 if (mBlockIsCompleted
[Index
]) {
45 ReleaseSpinLock (&mSpinLockList
[Index
]);
50 // Calculate CShake256 for this block.
52 Status
= CShake256HashAll (
53 mInput
+ Index
* mBlockSize
,
54 (Index
== (mBlockNum
- 1)) ? mLastBlockSize
: mBlockSize
,
60 mBlockHashResult
+ Index
* mBlockResultSize
62 if (!EFI_ERROR (Status
)) {
63 mBlockIsCompleted
[Index
] = TRUE
;
66 ReleaseSpinLock (&mSpinLockList
[Index
]);
72 Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
73 published December 2016.
75 @param[in] Input Pointer to the input message (X).
76 @param[in] InputByteLen The number(>0) of input bytes provided for the input data.
77 @param[in] BlockSize The size of each block (B).
78 @param[out] Output Pointer to the output buffer.
79 @param[in] OutputByteLen The desired number of output bytes (L).
80 @param[in] Customization Pointer to the customization string (S).
81 @param[in] CustomByteLen The length of the customization string in bytes.
83 @retval TRUE ParallelHash256 digest computation succeeded.
84 @retval FALSE ParallelHash256 digest computation failed.
85 @retval FALSE This interface is not supported.
90 ParallelHash256HashAll (
92 IN UINTN InputByteLen
,
95 IN UINTN OutputByteLen
,
96 IN CONST VOID
*Customization
,
97 IN UINTN CustomByteLen
100 UINT8 EncBufB
[sizeof (UINTN
)+1];
102 UINT8 EncBufN
[sizeof (UINTN
)+1];
104 UINT8 EncBufL
[sizeof (UINTN
)+1];
107 UINT8
*CombinedInput
;
108 UINTN CombinedInputSize
;
109 BOOLEAN AllCompleted
;
113 if ((InputByteLen
== 0) || (OutputByteLen
== 0) || (BlockSize
== 0)) {
117 if ((Input
== NULL
) || (Output
== NULL
)) {
121 if ((CustomByteLen
!= 0) && (Customization
== NULL
)) {
125 mBlockSize
= BlockSize
;
128 // Calculate block number n.
130 mBlockNum
= InputByteLen
% mBlockSize
== 0 ? InputByteLen
/ mBlockSize
: InputByteLen
/ mBlockSize
+ 1;
133 // Set hash result size of each block in bytes.
135 mBlockResultSize
= OutputByteLen
;
138 // Encode B, n, L to string and record size.
140 EncSizeB
= LeftEncode (EncBufB
, mBlockSize
);
141 EncSizeN
= RightEncode (EncBufN
, mBlockNum
);
142 EncSizeL
= RightEncode (EncBufL
, OutputByteLen
* CHAR_BIT
);
145 // Allocate buffer for combined input (newX), Block completed flag and SpinLock.
147 CombinedInputSize
= EncSizeB
+ EncSizeN
+ EncSizeL
+ mBlockNum
* mBlockResultSize
;
148 CombinedInput
= AllocateZeroPool (CombinedInputSize
);
149 mBlockIsCompleted
= AllocateZeroPool (mBlockNum
* sizeof (BOOLEAN
));
150 mSpinLockList
= AllocatePool (mBlockNum
* sizeof (SPIN_LOCK
));
151 if ((CombinedInput
== NULL
) || (mBlockIsCompleted
== NULL
) || (mSpinLockList
== NULL
)) {
157 // Fill LeftEncode(B).
159 CopyMem (CombinedInput
, EncBufB
, EncSizeB
);
162 // Prepare for parallel hash.
164 mBlockHashResult
= CombinedInput
+ EncSizeB
;
165 mInput
= (UINT8
*)Input
;
166 mLastBlockSize
= InputByteLen
% mBlockSize
== 0 ? mBlockSize
: InputByteLen
% mBlockSize
;
169 // Initialize SpinLock for each result block.
171 for (Index
= 0; Index
< mBlockNum
; Index
++) {
172 InitializeSpinLock (&mSpinLockList
[Index
]);
176 // Dispatch blocklist to each AP.
178 DispatchBlockToAp ();
181 // Wait until all block hash completed.
185 for (Index
= 0; Index
< mBlockNum
; Index
++) {
186 if (AcquireSpinLockOrFail (&mSpinLockList
[Index
])) {
187 if (!mBlockIsCompleted
[Index
]) {
188 AllCompleted
= FALSE
;
189 ReturnValue
= CShake256HashAll (
190 mInput
+ Index
* mBlockSize
,
191 (Index
== (mBlockNum
- 1)) ? mLastBlockSize
: mBlockSize
,
197 mBlockHashResult
+ Index
* mBlockResultSize
200 mBlockIsCompleted
[Index
] = TRUE
;
203 ReleaseSpinLock (&mSpinLockList
[Index
]);
207 ReleaseSpinLock (&mSpinLockList
[Index
]);
209 AllCompleted
= FALSE
;
213 } while (!AllCompleted
);
216 // Fill LeftEncode(n).
218 Offset
= EncSizeB
+ mBlockNum
* mBlockResultSize
;
219 CopyMem (CombinedInput
+ Offset
, EncBufN
, EncSizeN
);
222 // Fill LeftEncode(L).
225 CopyMem (CombinedInput
+ Offset
, EncBufL
, EncSizeL
);
227 ReturnValue
= CShake256HashAll (
231 PARALLELHASH_CUSTOMIZATION
,
232 AsciiStrLen (PARALLELHASH_CUSTOMIZATION
),
239 ZeroMem (CombinedInput
, CombinedInputSize
);
241 if (CombinedInput
!= NULL
) {
242 FreePool (CombinedInput
);
245 if (mSpinLockList
!= NULL
) {
246 FreePool ((VOID
*)mSpinLockList
);
249 if (mBlockIsCompleted
!= NULL
) {
250 FreePool (mBlockIsCompleted
);