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