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