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/MmServicesTableLib.h>
11 #include <Library/SynchronizationLib.h>
13 #define PARALLELHASH_CUSTOMIZATION "ParallelHash"
19 UINTN mBlockResultSize
;
20 UINT8
*mBlockHashResult
;
21 BOOLEAN
*mBlockIsCompleted
;
22 SPIN_LOCK
*mSpinLockList
;
25 Complete computation of digest of each block.
27 Each AP perform the function called by BSP.
29 @param[in] ProcedureArgument Argument of the procedure.
33 ParallelHashApExecute (
34 IN VOID
*ProcedureArgument
40 for (Index
= 0; Index
< mBlockNum
; Index
++) {
41 if (AcquireSpinLockOrFail (&mSpinLockList
[Index
])) {
43 // Completed, try next one.
45 if (mBlockIsCompleted
[Index
]) {
46 ReleaseSpinLock (&mSpinLockList
[Index
]);
51 // Calculate CShake256 for this block.
53 Status
= CShake256HashAll (
54 mInput
+ Index
* mBlockSize
,
55 (Index
== (mBlockNum
- 1)) ? mLastBlockSize
: mBlockSize
,
61 mBlockHashResult
+ Index
* mBlockResultSize
63 if (!EFI_ERROR (Status
)) {
64 mBlockIsCompleted
[Index
] = TRUE
;
67 ReleaseSpinLock (&mSpinLockList
[Index
]);
73 Dispatch the block task to each AP in SMM mode.
84 for (Index
= 0; Index
< gMmst
->NumberOfCpus
; Index
++) {
85 if (Index
!= gMmst
->CurrentlyExecutingCpu
) {
86 gMmst
->MmStartupThisAp (ParallelHashApExecute
, Index
, NULL
);
94 Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
95 published December 2016.
97 @param[in] Input Pointer to the input message (X).
98 @param[in] InputByteLen The number(>0) of input bytes provided for the input data.
99 @param[in] BlockSize The size of each block (B).
100 @param[out] Output Pointer to the output buffer.
101 @param[in] OutputByteLen The desired number of output bytes (L).
102 @param[in] Customization Pointer to the customization string (S).
103 @param[in] CustomByteLen The length of the customization string in bytes.
105 @retval TRUE ParallelHash256 digest computation succeeded.
106 @retval FALSE ParallelHash256 digest computation failed.
107 @retval FALSE This interface is not supported.
112 ParallelHash256HashAll (
113 IN CONST VOID
*Input
,
114 IN UINTN InputByteLen
,
117 IN UINTN OutputByteLen
,
118 IN CONST VOID
*Customization
,
119 IN UINTN CustomByteLen
122 UINT8 EncBufB
[sizeof (UINTN
)+1];
124 UINT8 EncBufN
[sizeof (UINTN
)+1];
126 UINT8 EncBufL
[sizeof (UINTN
)+1];
129 UINT8
*CombinedInput
;
130 UINTN CombinedInputSize
;
131 BOOLEAN AllCompleted
;
135 if ((InputByteLen
== 0) || (OutputByteLen
== 0) || (BlockSize
== 0)) {
139 if ((Input
== NULL
) || (Output
== NULL
)) {
143 if ((CustomByteLen
!= 0) && (Customization
== NULL
)) {
147 mBlockSize
= BlockSize
;
150 // Calculate block number n.
152 mBlockNum
= InputByteLen
% mBlockSize
== 0 ? InputByteLen
/ mBlockSize
: InputByteLen
/ mBlockSize
+ 1;
155 // Set hash result size of each block in bytes.
157 mBlockResultSize
= OutputByteLen
;
160 // Encode B, n, L to string and record size.
162 EncSizeB
= LeftEncode (EncBufB
, mBlockSize
);
163 EncSizeN
= RightEncode (EncBufN
, mBlockNum
);
164 EncSizeL
= RightEncode (EncBufL
, OutputByteLen
* CHAR_BIT
);
167 // Allocate buffer for combined input (newX), Block completed flag and SpinLock.
169 CombinedInputSize
= EncSizeB
+ EncSizeN
+ EncSizeL
+ mBlockNum
* mBlockResultSize
;
170 CombinedInput
= AllocateZeroPool (CombinedInputSize
);
171 mBlockIsCompleted
= AllocateZeroPool (mBlockNum
* sizeof (BOOLEAN
));
172 mSpinLockList
= AllocatePool (mBlockNum
* sizeof (SPIN_LOCK
));
173 if ((CombinedInput
== NULL
) || (mBlockIsCompleted
== NULL
) || (mSpinLockList
== NULL
)) {
179 // Fill LeftEncode(B).
181 CopyMem (CombinedInput
, EncBufB
, EncSizeB
);
184 // Prepare for parallel hash.
186 mBlockHashResult
= CombinedInput
+ EncSizeB
;
187 mInput
= (UINT8
*)Input
;
188 mLastBlockSize
= InputByteLen
% mBlockSize
== 0 ? mBlockSize
: InputByteLen
% mBlockSize
;
191 // Initialize SpinLock for each result block.
193 for (Index
= 0; Index
< mBlockNum
; Index
++) {
194 InitializeSpinLock (&mSpinLockList
[Index
]);
198 // Dispatch blocklist to each AP.
201 MmDispatchBlockToAP ();
205 // Wait until all block hash completed.
209 for (Index
= 0; Index
< mBlockNum
; Index
++) {
210 if (AcquireSpinLockOrFail (&mSpinLockList
[Index
])) {
211 if (!mBlockIsCompleted
[Index
]) {
212 AllCompleted
= FALSE
;
213 ReturnValue
= CShake256HashAll (
214 mInput
+ Index
* mBlockSize
,
215 (Index
== (mBlockNum
- 1)) ? mLastBlockSize
: mBlockSize
,
221 mBlockHashResult
+ Index
* mBlockResultSize
224 mBlockIsCompleted
[Index
] = TRUE
;
227 ReleaseSpinLock (&mSpinLockList
[Index
]);
231 ReleaseSpinLock (&mSpinLockList
[Index
]);
233 AllCompleted
= FALSE
;
237 } while (!AllCompleted
);
240 // Fill LeftEncode(n).
242 Offset
= EncSizeB
+ mBlockNum
* mBlockResultSize
;
243 CopyMem (CombinedInput
+ Offset
, EncBufN
, EncSizeN
);
246 // Fill LeftEncode(L).
249 CopyMem (CombinedInput
+ Offset
, EncBufL
, EncSizeL
);
251 ReturnValue
= CShake256HashAll (
255 PARALLELHASH_CUSTOMIZATION
,
256 AsciiStrLen (PARALLELHASH_CUSTOMIZATION
),
263 ZeroMem (CombinedInput
, CombinedInputSize
);
265 if (CombinedInput
!= NULL
) {
266 FreePool (CombinedInput
);
269 if (mSpinLockList
!= NULL
) {
270 FreePool ((VOID
*)mSpinLockList
);
273 if (mBlockIsCompleted
!= NULL
) {
274 FreePool (mBlockIsCompleted
);