]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Network/IScsiDxe/Md5.c
MdeModulePkg: Fix issue about current Ip4Dxe implementation for DHCP DORA process
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / Md5.c
... / ...
CommitLineData
1/** @file\r
2 Implementation of MD5 algorithm.\r
3\r
4Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Md5.h"\r
16\r
17CONST UINT32 Md5_Data[][2] = {\r
18 { 0, 1 },\r
19 { 1, 5 },\r
20 { 5, 3 },\r
21 { 0, 7 }\r
22};\r
23\r
24CONST UINT32 Md5_S[][4] = {\r
25 { 7, 22, 17, 12 },\r
26 { 5, 20, 14, 9 },\r
27 { 4, 23, 16 ,11 },\r
28 { 6, 21, 15, 10 },\r
29};\r
30\r
31CONST UINT32 Md5_T[] = {\r
32 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,\r
33 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,\r
34 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,\r
35 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,\r
36 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,\r
37 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,\r
38 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,\r
39 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,\r
40 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,\r
41 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,\r
42 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,\r
43 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,\r
44 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,\r
45 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,\r
46 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,\r
47 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391\r
48};\r
49\r
50CONST UINT8 Md5HashPadding[] =\r
51{\r
52 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \r
68};\r
69\r
70//\r
71// ROTATE_LEFT rotates x left n bits.\r
72//\r
73#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))\r
74\r
75#define SA MedStates[Index2 & 3]\r
76#define SB MedStates[(Index2 + 1) & 3]\r
77#define SC MedStates[(Index2 + 2) & 3]\r
78#define SD MedStates[(Index2 + 3) & 3]\r
79\r
80/**\r
81 Tf1 is one basic MD5 transform function.\r
82 \r
83 @param[in] A A 32-bit quantity.\r
84 @param[in] B A 32-bit quantity. \r
85 @param[in] C A 32-bit quantity.\r
86\r
87 @return Output was produced as a 32-bit quantity based on the\r
88 three 32-bit input quantity. \r
89**/\r
90UINT32 \r
91Tf1 (\r
92 IN UINT32 A, \r
93 IN UINT32 B, \r
94 IN UINT32 C\r
95 )\r
96{\r
97 return (A & B) | (~A & C);\r
98}\r
99\r
100/**\r
101 Tf2 is one basic MD5 transform function.\r
102 \r
103 @param[in] A A 32-bit quantity.\r
104 @param[in] B A 32-bit quantity. \r
105 @param[in] C A 32-bit quantity.\r
106\r
107 @return Output was produced as a 32-bit quantity based on the\r
108 three 32-bit input quantity. \r
109**/\r
110UINT32 \r
111Tf2 (\r
112 IN UINT32 A, \r
113 IN UINT32 B, \r
114 IN UINT32 C\r
115 )\r
116{\r
117 return (A & C) | (B & ~C);\r
118}\r
119\r
120/**\r
121 Tf3 is one basic MD5 transform function.\r
122 \r
123 @param[in] A A 32-bit quantity.\r
124 @param[in] B A 32-bit quantity. \r
125 @param[in] C A 32-bit quantity.\r
126\r
127 @return Output was produced as a 32-bit quantity based on the\r
128 three 32-bit input quantity. \r
129**/\r
130UINT32 \r
131Tf3 (\r
132 IN UINT32 A, \r
133 IN UINT32 B, \r
134 IN UINT32 C\r
135 )\r
136{\r
137 return A ^ B ^ C;\r
138}\r
139\r
140/**\r
141 Tf4 is one basic MD5 transform function.\r
142 \r
143 @param[in] A A 32-bit quantity.\r
144 @param[in] B A 32-bit quantity. \r
145 @param[in] C A 32-bit quantity.\r
146\r
147 @return Output was produced as a 32-bit quantity based on the\r
148 three 32-bit input quantity. \r
149**/\r
150UINT32 \r
151Tf4 (\r
152 IN UINT32 A, \r
153 IN UINT32 B, \r
154 IN UINT32 C\r
155 )\r
156{\r
157 return B ^ (A | ~C);\r
158}\r
159\r
160typedef\r
161UINT32\r
162(*MD5_TRANSFORM_FUNC) (\r
163 IN UINT32 A,\r
164 IN UINT32 B,\r
165 IN UINT32 C\r
166 );\r
167\r
168CONST MD5_TRANSFORM_FUNC Md5_F[] = {\r
169 Tf1,\r
170 Tf2,\r
171 Tf3,\r
172 Tf4\r
173};\r
174\r
175/**\r
176 Perform the MD5 transform on 64 bytes data segment.\r
177\r
178 @param[in, out] Md5Ctx It includes the data segment for Md5 transform.\r
179**/\r
180VOID\r
181MD5Transform (\r
182 IN OUT MD5_CTX *Md5Ctx\r
183 )\r
184{\r
185 UINT32 Index1;\r
186 UINT32 Index2;\r
187 UINT32 MedStates[MD5_HASHSIZE >> 2];\r
188 UINT32 *Data;\r
189 UINT32 IndexD;\r
190 UINT32 IndexT;\r
191\r
192 Data = (UINT32 *) Md5Ctx->M;\r
193\r
194 //\r
195 // Copy MD5 states to MedStates\r
196 //\r
197 CopyMem (MedStates, Md5Ctx->States, MD5_HASHSIZE);\r
198\r
199 IndexT = 0;\r
200 for (Index1 = 0; Index1 < 4; Index1++) {\r
201 IndexD = Md5_Data[Index1][0];\r
202 for (Index2 = 16; Index2 > 0; Index2--) {\r
203 SA += (*Md5_F[Index1]) (SB, SC, SD) + Data[IndexD] + Md5_T[IndexT];\r
204 SA = ROTATE_LEFT (SA, Md5_S[Index1][Index2 & 3]);\r
205 SA += SB;\r
206\r
207 IndexD += Md5_Data[Index1][1];\r
208 IndexD &= 15;\r
209\r
210 IndexT++;\r
211 }\r
212 }\r
213\r
214 for (Index1 = 0; Index1 < 4; Index1++) {\r
215 Md5Ctx->States[Index1] += MedStates[Index1];\r
216 }\r
217}\r
218\r
219/**\r
220 Copy data segment into the M field of MD5_CTX structure for later transform.\r
221 If the length of data segment is larger than 64 bytes, then does the transform\r
222 immediately and the generated Md5 code is stored in the States field of MD5_CTX\r
223 data struct for later accumulation. \r
224 All of Md5 code generated for the sequential 64-bytes data segaments are be\r
225 accumulated in MD5Final() function.\r
226\r
227 @param[in, out] Md5Ctx The data structure of storing the original data\r
228 segment and the final result.\r
229 @param[in] Data The data wanted to be transformed.\r
230 @param[in] DataLen The length of data.\r
231**/\r
232VOID\r
233MD5UpdateBlock (\r
234 IN OUT MD5_CTX *Md5Ctx,\r
235 IN CONST UINT8 *Data,\r
236 IN UINTN DataLen\r
237 )\r
238{\r
239 UINTN Limit;\r
240\r
241 for (Limit = 64 - Md5Ctx->Count; DataLen >= 64 - Md5Ctx->Count; Limit = 64) {\r
242 CopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, Limit);\r
243 MD5Transform (Md5Ctx);\r
244 \r
245 Md5Ctx->Count = 0;\r
246 Data += Limit;\r
247 DataLen -= Limit;\r
248 }\r
249\r
250 CopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, DataLen);\r
251 Md5Ctx->Count += DataLen;\r
252}\r
253\r
254/**\r
255 Initialize four 32-bits chaining variables and use them to do the Md5 transform.\r
256\r
257 @param[out] Md5Ctx The data structure of Md5.\r
258\r
259 @retval EFI_SUCCESS Initialization is ok.\r
260**/\r
261EFI_STATUS\r
262MD5Init (\r
263 OUT MD5_CTX *Md5Ctx\r
264 )\r
265{\r
266 ZeroMem (Md5Ctx, sizeof (*Md5Ctx));\r
267\r
268 //\r
269 // Set magic initialization constants.\r
270 //\r
271 Md5Ctx->States[0] = 0x67452301;\r
272 Md5Ctx->States[1] = 0xefcdab89;\r
273 Md5Ctx->States[2] = 0x98badcfe;\r
274 Md5Ctx->States[3] = 0x10325476; \r
275\r
276 return EFI_SUCCESS;\r
277}\r
278\r
279/**\r
280 the external interface of Md5 algorithm\r
281\r
282 @param[in, out] Md5Ctx The data structure of storing the original data\r
283 segment and the final result.\r
284 @param[in] Data The data wanted to be transformed.\r
285 @param[in] DataLen The length of data.\r
286\r
287 @retval EFI_SUCCESS The transform is ok.\r
288 @retval Others Other errors as indicated.\r
289**/\r
290EFI_STATUS\r
291MD5Update (\r
292 IN OUT MD5_CTX *Md5Ctx,\r
293 IN VOID *Data,\r
294 IN UINTN DataLen\r
295 )\r
296{\r
297 if (EFI_ERROR (Md5Ctx->Status)) {\r
298 return Md5Ctx->Status;\r
299 }\r
300\r
301 MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) Data, DataLen);\r
302 Md5Ctx->Length += DataLen;\r
303 return EFI_SUCCESS;\r
304}\r
305\r
306/**\r
307 Accumulate the MD5 value of every data segment and generate the finial\r
308 result according to MD5 algorithm.\r
309\r
310 @param[in, out] Md5Ctx The data structure of storing the original data\r
311 segment and the final result.\r
312 @param[out] HashVal The final 128-bits output.\r
313\r
314 @retval EFI_SUCCESS The transform is ok.\r
315 @retval Others Other errors as indicated.\r
316**/\r
317EFI_STATUS\r
318MD5Final (\r
319 IN OUT MD5_CTX *Md5Ctx,\r
320 OUT UINT8 *HashVal\r
321 )\r
322{\r
323 UINTN PadLength;\r
324\r
325 if (Md5Ctx->Status == EFI_ALREADY_STARTED) {\r
326 //\r
327 // Store Hashed value & Zeroize sensitive context information.\r
328 //\r
329 CopyMem (HashVal, (UINT8 *) Md5Ctx->States, MD5_HASHSIZE);\r
330 ZeroMem ((UINT8 *)Md5Ctx, sizeof (*Md5Ctx));\r
331 \r
332 return EFI_SUCCESS;\r
333 }\r
334\r
335 if (EFI_ERROR (Md5Ctx->Status)) {\r
336 return Md5Ctx->Status;\r
337 }\r
338\r
339 PadLength = Md5Ctx->Count >= 56 ? 120 : 56;\r
340 PadLength -= Md5Ctx->Count;\r
341 MD5UpdateBlock (Md5Ctx, Md5HashPadding, PadLength);\r
342 Md5Ctx->Length = LShiftU64 (Md5Ctx->Length, 3);\r
343 MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) &Md5Ctx->Length, 8);\r
344\r
345 ZeroMem (Md5Ctx->M, sizeof (Md5Ctx->M));\r
346 Md5Ctx->Length = 0;\r
347 Md5Ctx->Status = EFI_ALREADY_STARTED;\r
348 return MD5Final (Md5Ctx, HashVal);\r
349}\r
350\r