]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
2931123736e36ecd4309cee36c6f46f2cd5e5956
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Hash / CryptParallelHash.c
1 /** @file
2 ParallelHash Implementation.
3
4 Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "CryptParallelHash.h"
10 #include <Library/SynchronizationLib.h>
11
12 #define PARALLELHASH_CUSTOMIZATION "ParallelHash"
13
14 UINTN mBlockNum;
15 UINTN mBlockSize;
16 UINTN mLastBlockSize;
17 UINT8 *mInput;
18 UINTN mBlockResultSize;
19 UINT8 *mBlockHashResult;
20 BOOLEAN *mBlockIsCompleted;
21 SPIN_LOCK *mSpinLockList;
22
23 /**
24 Complete computation of digest of each block.
25
26 Each AP perform the function called by BSP.
27
28 @param[in] ProcedureArgument Argument of the procedure.
29 **/
30 VOID
31 EFIAPI
32 ParallelHashApExecute (
33 IN VOID *ProcedureArgument
34 )
35 {
36 UINTN Index;
37 BOOLEAN Status;
38
39 for (Index = 0; Index < mBlockNum; Index++) {
40 if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
41 //
42 // Completed, try next one.
43 //
44 if (mBlockIsCompleted[Index]) {
45 ReleaseSpinLock (&mSpinLockList[Index]);
46 continue;
47 }
48
49 //
50 // Calculate CShake256 for this block.
51 //
52 Status = CShake256HashAll (
53 mInput + Index * mBlockSize,
54 (Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
55 mBlockResultSize,
56 NULL,
57 0,
58 NULL,
59 0,
60 mBlockHashResult + Index * mBlockResultSize
61 );
62 if (!EFI_ERROR (Status)) {
63 mBlockIsCompleted[Index] = TRUE;
64 }
65
66 ReleaseSpinLock (&mSpinLockList[Index]);
67 }
68 }
69 }
70
71 /**
72 Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
73 published December 2016.
74
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.
82
83 @retval TRUE ParallelHash256 digest computation succeeded.
84 @retval FALSE ParallelHash256 digest computation failed.
85 @retval FALSE This interface is not supported.
86
87 **/
88 BOOLEAN
89 EFIAPI
90 ParallelHash256HashAll (
91 IN CONST VOID *Input,
92 IN UINTN InputByteLen,
93 IN UINTN BlockSize,
94 OUT VOID *Output,
95 IN UINTN OutputByteLen,
96 IN CONST VOID *Customization,
97 IN UINTN CustomByteLen
98 )
99 {
100 UINT8 EncBufB[sizeof (UINTN)+1];
101 UINTN EncSizeB;
102 UINT8 EncBufN[sizeof (UINTN)+1];
103 UINTN EncSizeN;
104 UINT8 EncBufL[sizeof (UINTN)+1];
105 UINTN EncSizeL;
106 UINTN Index;
107 UINT8 *CombinedInput;
108 UINTN CombinedInputSize;
109 BOOLEAN AllCompleted;
110 UINTN Offset;
111 BOOLEAN ReturnValue;
112
113 if ((InputByteLen == 0) || (OutputByteLen == 0) || (BlockSize == 0)) {
114 return FALSE;
115 }
116
117 if ((Input == NULL) || (Output == NULL)) {
118 return FALSE;
119 }
120
121 if ((CustomByteLen != 0) && (Customization == NULL)) {
122 return FALSE;
123 }
124
125 mBlockSize = BlockSize;
126
127 //
128 // Calculate block number n.
129 //
130 mBlockNum = InputByteLen % mBlockSize == 0 ? InputByteLen / mBlockSize : InputByteLen / mBlockSize + 1;
131
132 //
133 // Set hash result size of each block in bytes.
134 //
135 mBlockResultSize = OutputByteLen;
136
137 //
138 // Encode B, n, L to string and record size.
139 //
140 EncSizeB = LeftEncode (EncBufB, mBlockSize);
141 EncSizeN = RightEncode (EncBufN, mBlockNum);
142 EncSizeL = RightEncode (EncBufL, OutputByteLen * CHAR_BIT);
143
144 //
145 // Allocate buffer for combined input (newX), Block completed flag and SpinLock.
146 //
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)) {
152 ReturnValue = FALSE;
153 goto Exit;
154 }
155
156 //
157 // Fill LeftEncode(B).
158 //
159 CopyMem (CombinedInput, EncBufB, EncSizeB);
160
161 //
162 // Prepare for parallel hash.
163 //
164 mBlockHashResult = CombinedInput + EncSizeB;
165 mInput = (UINT8 *)Input;
166 mLastBlockSize = InputByteLen % mBlockSize == 0 ? mBlockSize : InputByteLen % mBlockSize;
167
168 //
169 // Initialize SpinLock for each result block.
170 //
171 for (Index = 0; Index < mBlockNum; Index++) {
172 InitializeSpinLock (&mSpinLockList[Index]);
173 }
174
175 //
176 // Dispatch blocklist to each AP.
177 //
178 DispatchBlockToAp ();
179
180 //
181 // Wait until all block hash completed.
182 //
183 do {
184 AllCompleted = TRUE;
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,
192 mBlockResultSize,
193 NULL,
194 0,
195 NULL,
196 0,
197 mBlockHashResult + Index * mBlockResultSize
198 );
199 if (ReturnValue) {
200 mBlockIsCompleted[Index] = TRUE;
201 }
202
203 ReleaseSpinLock (&mSpinLockList[Index]);
204 break;
205 }
206
207 ReleaseSpinLock (&mSpinLockList[Index]);
208 } else {
209 AllCompleted = FALSE;
210 break;
211 }
212 }
213 } while (!AllCompleted);
214
215 //
216 // Fill LeftEncode(n).
217 //
218 Offset = EncSizeB + mBlockNum * mBlockResultSize;
219 CopyMem (CombinedInput + Offset, EncBufN, EncSizeN);
220
221 //
222 // Fill LeftEncode(L).
223 //
224 Offset += EncSizeN;
225 CopyMem (CombinedInput + Offset, EncBufL, EncSizeL);
226
227 ReturnValue = CShake256HashAll (
228 CombinedInput,
229 CombinedInputSize,
230 OutputByteLen,
231 PARALLELHASH_CUSTOMIZATION,
232 AsciiStrLen (PARALLELHASH_CUSTOMIZATION),
233 Customization,
234 CustomByteLen,
235 Output
236 );
237
238 Exit:
239 ZeroMem (CombinedInput, CombinedInputSize);
240
241 if (CombinedInput != NULL) {
242 FreePool (CombinedInput);
243 }
244
245 if (mSpinLockList != NULL) {
246 FreePool ((VOID *)mSpinLockList);
247 }
248
249 if (mBlockIsCompleted != NULL) {
250 FreePool (mBlockIsCompleted);
251 }
252
253 return ReturnValue;
254 }