]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/Md5.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / Md5.c
1 /** @file
2 Implementation of MD5 algorithm
3
4 Copyright (c) 2004 - 2008, Intel Corporation
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 Module Name:
14
15 Md5.c
16
17 Abstract:
18
19 Implementation of MD5 algorithm
20
21 **/
22
23 #include "Md5.h"
24
25 CONST UINT32 MD5_K[][2] = {
26 { 0, 1 },
27 { 1, 5 },
28 { 5, 3 },
29 { 0, 7 }
30 };
31
32 CONST UINT32 MD5_S[][4] = {
33 { 7, 22, 17, 12 },
34 { 5, 20, 14, 9 },
35 { 4, 23, 16 ,11 },
36 { 6, 21, 15, 10 },
37 };
38
39 CONST UINT32 MD5_T[] = {
40 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
41 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
42 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
43 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
44 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
45 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
46 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
47 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
48 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
49 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
50 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
51 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
52 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
53 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
54 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
55 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
56 };
57
58 CONST UINT8 Md5HashPadding[] =
59 {
60 0x80, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
76 };
77
78 //
79 // ROTATE_LEFT rotates x left n bits.
80 //
81 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
82
83 #define SA S[j & 3]
84 #define SB S[(j + 1) & 3]
85 #define SC S[(j + 2) & 3]
86 #define SD S[(j + 3) & 3]
87
88 //
89 // TF1, TF2, TF3, TF4 are basic MD5 transform functions
90 //
91 UINT32 TF1 (UINT32 A, UINT32 B, UINT32 C)
92 {
93 return (A & B) | (~A & C);
94 }
95
96 UINT32 TF2 (UINT32 A, UINT32 B, UINT32 C)
97 {
98 return (A & C) | (B & ~C);
99 }
100
101 UINT32 TF3 (UINT32 A, UINT32 B, UINT32 C)
102 {
103 return A ^ B ^ C;
104 }
105
106 UINT32 TF4 (UINT32 A, UINT32 B, UINT32 C)
107 {
108 return B ^ (A | ~C);
109 }
110
111 typedef
112 UINT32
113 (*MD5_TRANSFORM_FUNC) (
114 IN UINT32 A,
115 IN UINT32 B,
116 IN UINT32 C
117 );
118
119 CONST MD5_TRANSFORM_FUNC MD5_F[] = {
120 TF1,
121 TF2,
122 TF3,
123 TF4
124 };
125
126 /**
127 Perform the MD5 transform on 64 bytes data segment
128
129 @param Md5Ctx[in] it includes the data segment for Md5 transform
130
131 @retval NONE.
132
133 **/
134 VOID
135 MD5Transform (
136 IN MD5_CTX *Md5Ctx
137 )
138 {
139 UINT32 i;
140 UINT32 j;
141 UINT32 S[MD5_HASHSIZE >> 2];
142 UINT32 *X;
143 UINT32 k;
144 UINT32 t;
145
146 X = (UINT32 *) Md5Ctx->M;
147
148 //
149 // Copy MD5 states to S
150 //
151 CopyMem (S, Md5Ctx->States, MD5_HASHSIZE);
152
153 t = 0;
154 for (i = 0; i < 4; i++) {
155 k = MD5_K[i][0];
156 for (j = 16; j > 0; j--) {
157 SA += (*MD5_F[i]) (SB, SC, SD) + X[k] + MD5_T[t];
158 SA = ROTATE_LEFT (SA, MD5_S[i][j & 3]);
159 SA += SB;
160
161 k += MD5_K[i][1];
162 k &= 15;
163
164 t++;
165 }
166 }
167
168 for (i = 0; i < 4; i++) {
169 Md5Ctx->States[i] += S[i];
170 }
171 }
172
173 /**
174 Copy data segment into the M field of MD5_CTX structure for later transform.
175 If the length of data segment is larger than 64 bytes, then does the transform
176 immediately and the generated Md5 code is stored in the States field of MD5_CTX
177 data struct for later accumulation.
178 All of Md5 code generated for the sequential 64-bytes data segaments are be
179 accumulated in MD5Final() function.
180
181 @param Md5Ctx[in] the data structure of storing the original data
182 segment and the final result.
183
184 @param Data[in] the data wanted to be transformed
185
186 @param DataLen[in] the length of data
187
188 @retval NONE.
189 **/
190 VOID
191 MD5UpdateBlock (
192 IN MD5_CTX *Md5Ctx,
193 IN CONST UINT8 *Data,
194 IN UINTN DataLen
195 )
196 {
197 UINTN Limit;
198
199 for (Limit = 64 - Md5Ctx->Count; DataLen >= 64 - Md5Ctx->Count; Limit = 64) {
200 CopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, Limit);
201 MD5Transform (Md5Ctx);
202
203 Md5Ctx->Count = 0;
204 Data += Limit;
205 DataLen -= Limit;
206 }
207
208 CopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, DataLen);
209 Md5Ctx->Count += DataLen;
210 }
211
212 /**
213 Initialize four 32-bits chaining variables and use them to do the Md5 transform.
214
215 @param Md5Ctx[in] the data structure of Md5
216
217 @retval EFI_SUCCESS initialization is ok
218
219 **/
220 EFI_STATUS
221 MD5Init (
222 IN MD5_CTX *Md5Ctx
223 )
224 {
225 ZeroMem (Md5Ctx, sizeof (*Md5Ctx));
226
227 //
228 // Set magic initialization constants.
229 //
230 Md5Ctx->States[0] = 0x67452301;
231 Md5Ctx->States[1] = 0xefcdab89;
232 Md5Ctx->States[2] = 0x98badcfe;
233 Md5Ctx->States[3] = 0x10325476;
234
235 return EFI_SUCCESS;
236 }
237
238 /**
239 the external interface of Md5 algorithm
240
241 @param Md5Ctx[in] the data structure of storing the original data
242 segment and the final result.
243
244 @param Data[in] the data wanted to be transformed.
245
246 @param DataLen[in] the length of data.
247
248 @retval EFI_SUCCESS the transform is ok.
249
250 **/
251 EFI_STATUS
252 MD5Update (
253 IN MD5_CTX *Md5Ctx,
254 IN VOID *Data,
255 IN UINTN DataLen
256 )
257 {
258 if (EFI_ERROR (Md5Ctx->Status)) {
259 return Md5Ctx->Status;
260 }
261
262 MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) Data, DataLen);
263 Md5Ctx->Length += DataLen;
264 return EFI_SUCCESS;
265 }
266
267 /**
268 accumulate the MD5 value of every data segment and generate the finial
269 result according to MD5 algorithm
270
271 @param Md5Ctx[in] the data structure of storing the original data
272 segment and the final result.
273
274 @param HashVal[out] the final 128-bits output.
275
276 @retval EFI_SUCCESS the transform is ok.
277
278 **/
279 EFI_STATUS
280 MD5Final (
281 IN MD5_CTX *Md5Ctx,
282 OUT UINT8 *HashVal
283 )
284 {
285 UINTN PadLength;
286
287 if (Md5Ctx->Status == EFI_ALREADY_STARTED) {
288 //
289 // Store Hashed value & Zeroize sensitive context information.
290 //
291 CopyMem (HashVal, (UINT8 *) Md5Ctx->States, MD5_HASHSIZE);
292 ZeroMem ((UINT8 *)Md5Ctx, sizeof (*Md5Ctx));
293
294 return EFI_SUCCESS;
295 }
296
297 if (EFI_ERROR (Md5Ctx->Status)) {
298 return Md5Ctx->Status;
299 }
300
301 PadLength = Md5Ctx->Count >= 56 ? 120 : 56;
302 PadLength -= Md5Ctx->Count;
303 MD5UpdateBlock (Md5Ctx, Md5HashPadding, PadLength);
304 Md5Ctx->Length = LShiftU64 (Md5Ctx->Length, 3);
305 MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) &Md5Ctx->Length, 8);
306
307 ZeroMem (Md5Ctx->M, sizeof (Md5Ctx->M));
308 Md5Ctx->Length = 0;
309 Md5Ctx->Status = EFI_ALREADY_STARTED;
310 return MD5Final (Md5Ctx, HashVal);
311 }
312