blob: 1f9d59e6ecb236e63bdb55f30635ff68e5d340c2 [file] [log] [blame]
"Robert P. J. Day"63fc1a92006-07-02 19:47:05 +00001/* vi: set sw=4 ts=4: */
Rob Landley5cf7c2d2006-02-21 06:44:43 +00002/*
Denys Vlasenko70186712010-10-16 01:08:32 +02003 * Compute MD5 checksum of strings according to the
4 * definition of MD5 in RFC 1321 from April 1992.
Bernhard Reutner-Fischer421d9e52006-04-03 16:39:31 +00005 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02006 * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
Bernhard Reutner-Fischer421d9e52006-04-03 16:39:31 +00007 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02008 * Copyright (C) 1995-1999 Free Software Foundation, Inc.
9 * Copyright (C) 2001 Manuel Novoa III
10 * Copyright (C) 2003 Glenn L. McGrath
11 * Copyright (C) 2003 Erik Andersen
Rob Landley5cf7c2d2006-02-21 06:44:43 +000012 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +020013 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Rob Landley5cf7c2d2006-02-21 06:44:43 +000014 */
"Robert P. J. Day"5d8843e2006-07-10 11:41:19 +000015
Bernhard Reutner-Fischer421d9e52006-04-03 16:39:31 +000016#include "libbb.h"
Rob Landley5cf7c2d2006-02-21 06:44:43 +000017
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000018/* 0: fastest, 3: smallest */
19#if CONFIG_MD5_SIZE_VS_SPEED < 0
20# define MD5_SIZE_VS_SPEED 0
21#elif CONFIG_MD5_SIZE_VS_SPEED > 3
22# define MD5_SIZE_VS_SPEED 3
Denis Vlasenko966ec7c2006-11-01 09:13:26 +000023#else
Rob Landley5cf7c2d2006-02-21 06:44:43 +000024# define MD5_SIZE_VS_SPEED CONFIG_MD5_SIZE_VS_SPEED
Denis Vlasenko966ec7c2006-11-01 09:13:26 +000025#endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +000026
Rob Landley5cf7c2d2006-02-21 06:44:43 +000027/* Initialize structure containing state of computation.
28 * (RFC 1321, 3.3: Step 3)
29 */
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +000030void FAST_FUNC md5_begin(md5_ctx_t *ctx)
Rob Landley5cf7c2d2006-02-21 06:44:43 +000031{
32 ctx->A = 0x67452301;
33 ctx->B = 0xefcdab89;
34 ctx->C = 0x98badcfe;
35 ctx->D = 0x10325476;
Rob Landley34b53192006-05-16 02:38:26 +000036 ctx->total = 0;
Rob Landley5cf7c2d2006-02-21 06:44:43 +000037}
38
39/* These are the four functions used in the four steps of the MD5 algorithm
40 * and defined in the RFC 1321. The first function is a little bit optimized
41 * (as found in Colin Plumbs public domain implementation).
42 * #define FF(b, c, d) ((b & c) | (~b & d))
43 */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000044#define FF(b, c, d) (d ^ (b & (c ^ d)))
45#define FG(b, c, d) FF(d, b, c)
46#define FH(b, c, d) (b ^ c ^ d)
47#define FI(b, c, d) (c ^ (b | ~d))
48
49#define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s))))
Rob Landley5cf7c2d2006-02-21 06:44:43 +000050
Rob Landley34b53192006-05-16 02:38:26 +000051/* Hash a single block, 64 bytes long and 4-byte aligned. */
52static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
Rob Landley5cf7c2d2006-02-21 06:44:43 +000053{
54 uint32_t correct_words[16];
55 const uint32_t *words = buffer;
Rob Landley5cf7c2d2006-02-21 06:44:43 +000056
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000057#if MD5_SIZE_VS_SPEED > 0
Denys Vlasenko3d160982010-10-15 18:05:51 +020058 /* Before we start, one word to the strange constants.
59 They are defined in RFC 1321 as
60 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
61 */
Rob Landley5cf7c2d2006-02-21 06:44:43 +000062 static const uint32_t C_array[] = {
63 /* round 1 */
64 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
65 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
66 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
67 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
68 /* round 2 */
69 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
70 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
71 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
72 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
73 /* round 3 */
74 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
75 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
76 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
77 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
78 /* round 4 */
79 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
80 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
81 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
82 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
83 };
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000084 static const char P_array[] ALIGN1 = {
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000085# if MD5_SIZE_VS_SPEED > 1
Rob Landley5cf7c2d2006-02-21 06:44:43 +000086 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000087# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +000088 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
89 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
90 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
91 };
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000092# if MD5_SIZE_VS_SPEED > 1
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000093 static const char S_array[] ALIGN1 = {
Rob Landley5cf7c2d2006-02-21 06:44:43 +000094 7, 12, 17, 22,
95 5, 9, 14, 20,
96 4, 11, 16, 23,
97 6, 10, 15, 21
98 };
Denys Vlasenko3d160982010-10-15 18:05:51 +020099# endif
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000100#endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000101 uint32_t A = ctx->A;
102 uint32_t B = ctx->B;
103 uint32_t C = ctx->C;
104 uint32_t D = ctx->D;
105
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000106 uint32_t *cwp = correct_words;
107 uint32_t A_save = A;
108 uint32_t B_save = B;
109 uint32_t C_save = C;
110 uint32_t D_save = D;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000111
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000112#if MD5_SIZE_VS_SPEED > 1
113 const uint32_t *pc;
114 const char *pp;
115 const char *ps;
116 int i;
117 uint32_t temp;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000118
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000119 for (i = 0; i < 16; i++)
120 cwp[i] = SWAP_LE32(words[i]);
121 words += 16;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000122
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000123# if MD5_SIZE_VS_SPEED > 2
124 pc = C_array;
125 pp = P_array;
126 ps = S_array - 4;
127
128 for (i = 0; i < 64; i++) {
129 if ((i & 0x0f) == 0)
130 ps += 4;
131 temp = A;
132 switch (i >> 4) {
133 case 0:
134 temp += FF(B, C, D);
135 break;
136 case 1:
137 temp += FG(B, C, D);
138 break;
139 case 2:
140 temp += FH(B, C, D);
141 break;
142 case 3:
143 temp += FI(B, C, D);
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000144 }
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000145 temp += cwp[(int) (*pp++)] + *pc++;
146 temp = rotl32(temp, ps[i & 3]);
147 temp += B;
148 A = D;
149 D = C;
150 C = B;
151 B = temp;
152 }
Denys Vlasenko3d160982010-10-15 18:05:51 +0200153# else /* MD5_SIZE_VS_SPEED == 2 */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000154 pc = C_array;
155 pp = P_array;
156 ps = S_array;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000157
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000158 for (i = 0; i < 16; i++) {
159 temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++;
160 temp = rotl32(temp, ps[i & 3]);
161 temp += B;
162 A = D;
163 D = C;
164 C = B;
165 B = temp;
166 }
167 ps += 4;
168 for (i = 0; i < 16; i++) {
169 temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++;
170 temp = rotl32(temp, ps[i & 3]);
171 temp += B;
172 A = D;
173 D = C;
174 C = B;
175 B = temp;
176 }
177 ps += 4;
178 for (i = 0; i < 16; i++) {
179 temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++;
180 temp = rotl32(temp, ps[i & 3]);
181 temp += B;
182 A = D;
183 D = C;
184 C = B;
185 B = temp;
186 }
187 ps += 4;
188 for (i = 0; i < 16; i++) {
189 temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++;
190 temp = rotl32(temp, ps[i & 3]);
191 temp += B;
192 A = D;
193 D = C;
194 C = B;
195 B = temp;
196 }
Denys Vlasenko3d160982010-10-15 18:05:51 +0200197# endif
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000198
Denys Vlasenko3d160982010-10-15 18:05:51 +0200199#else /* MD5_SIZE_VS_SPEED == 0 or 1 */
200
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000201 /* First round: using the given function, the context and a constant
Denys Vlasenko3d160982010-10-15 18:05:51 +0200202 the next context is computed. Because the algorithm's processing
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000203 unit is a 32-bit word and it is determined to work on words in
204 little endian byte order we perhaps have to change the byte order
205 before the computation. To reduce the work for the next steps
206 we store the swapped words in the array CORRECT_WORDS. */
Denys Vlasenko3d160982010-10-15 18:05:51 +0200207# undef OP
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000208# define OP(a, b, c, d, s, T) \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000209 do { \
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000210 a += FF(b, c, d) + (*cwp++ = SWAP_LE32(*words)) + T; \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000211 ++words; \
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000212 a = rotl32(a, s); \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000213 a += b; \
214 } while (0)
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000215
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000216# if MD5_SIZE_VS_SPEED == 1
217 const uint32_t *pc;
218 const char *pp;
219 int i;
Denys Vlasenko3d160982010-10-15 18:05:51 +0200220# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000221
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000222 /* Round 1. */
223# if MD5_SIZE_VS_SPEED == 1
224 pc = C_array;
225 for (i = 0; i < 4; i++) {
226 OP(A, B, C, D, 7, *pc++);
227 OP(D, A, B, C, 12, *pc++);
228 OP(C, D, A, B, 17, *pc++);
229 OP(B, C, D, A, 22, *pc++);
230 }
231# else
232 OP(A, B, C, D, 7, 0xd76aa478);
233 OP(D, A, B, C, 12, 0xe8c7b756);
234 OP(C, D, A, B, 17, 0x242070db);
235 OP(B, C, D, A, 22, 0xc1bdceee);
236 OP(A, B, C, D, 7, 0xf57c0faf);
237 OP(D, A, B, C, 12, 0x4787c62a);
238 OP(C, D, A, B, 17, 0xa8304613);
239 OP(B, C, D, A, 22, 0xfd469501);
240 OP(A, B, C, D, 7, 0x698098d8);
241 OP(D, A, B, C, 12, 0x8b44f7af);
242 OP(C, D, A, B, 17, 0xffff5bb1);
243 OP(B, C, D, A, 22, 0x895cd7be);
244 OP(A, B, C, D, 7, 0x6b901122);
245 OP(D, A, B, C, 12, 0xfd987193);
246 OP(C, D, A, B, 17, 0xa679438e);
247 OP(B, C, D, A, 22, 0x49b40821);
Denys Vlasenko3d160982010-10-15 18:05:51 +0200248# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000249
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000250 /* For the second to fourth round we have the possibly swapped words
251 in CORRECT_WORDS. Redefine the macro to take an additional first
252 argument specifying the function to use. */
253# undef OP
254# define OP(f, a, b, c, d, k, s, T) \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000255 do { \
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000256 a += f(b, c, d) + correct_words[k] + T; \
257 a = rotl32(a, s); \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000258 a += b; \
259 } while (0)
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000260
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000261 /* Round 2. */
262# if MD5_SIZE_VS_SPEED == 1
263 pp = P_array;
264 for (i = 0; i < 4; i++) {
265 OP(FG, A, B, C, D, (int) (*pp++), 5, *pc++);
266 OP(FG, D, A, B, C, (int) (*pp++), 9, *pc++);
267 OP(FG, C, D, A, B, (int) (*pp++), 14, *pc++);
268 OP(FG, B, C, D, A, (int) (*pp++), 20, *pc++);
269 }
270# else
271 OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
272 OP(FG, D, A, B, C, 6, 9, 0xc040b340);
273 OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
274 OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
275 OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
276 OP(FG, D, A, B, C, 10, 9, 0x02441453);
277 OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
278 OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
279 OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
280 OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
281 OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
282 OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
283 OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
284 OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
285 OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
286 OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
Denys Vlasenko3d160982010-10-15 18:05:51 +0200287# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000288
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000289 /* Round 3. */
290# if MD5_SIZE_VS_SPEED == 1
291 for (i = 0; i < 4; i++) {
292 OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++);
293 OP(FH, D, A, B, C, (int) (*pp++), 11, *pc++);
294 OP(FH, C, D, A, B, (int) (*pp++), 16, *pc++);
295 OP(FH, B, C, D, A, (int) (*pp++), 23, *pc++);
296 }
297# else
298 OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
299 OP(FH, D, A, B, C, 8, 11, 0x8771f681);
300 OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
301 OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
302 OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
303 OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
304 OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
305 OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
306 OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
307 OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
308 OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
309 OP(FH, B, C, D, A, 6, 23, 0x04881d05);
310 OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
311 OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
312 OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
313 OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
Denys Vlasenko3d160982010-10-15 18:05:51 +0200314# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000315
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000316 /* Round 4. */
317# if MD5_SIZE_VS_SPEED == 1
318 for (i = 0; i < 4; i++) {
319 OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++);
320 OP(FI, D, A, B, C, (int) (*pp++), 10, *pc++);
321 OP(FI, C, D, A, B, (int) (*pp++), 15, *pc++);
322 OP(FI, B, C, D, A, (int) (*pp++), 21, *pc++);
323 }
324# else
325 OP(FI, A, B, C, D, 0, 6, 0xf4292244);
326 OP(FI, D, A, B, C, 7, 10, 0x432aff97);
327 OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
328 OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
329 OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
330 OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
331 OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
332 OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
333 OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
334 OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
335 OP(FI, C, D, A, B, 6, 15, 0xa3014314);
336 OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
337 OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
338 OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
339 OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
340 OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
Denys Vlasenko3d160982010-10-15 18:05:51 +0200341# endif
342#endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000343
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000344 /* Add the starting values of the context. */
345 A += A_save;
346 B += B_save;
347 C += C_save;
348 D += D_save;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000349
350 /* Put checksum in context given as argument. */
351 ctx->A = A;
352 ctx->B = B;
353 ctx->C = C;
354 ctx->D = D;
355}
356
Denys Vlasenko70186712010-10-16 01:08:32 +0200357/* The size of filled part of ctx->buffer: */
358#define BUFLEN(ctx) (((unsigned)ctx->total) & 63)
359
Rob Landley34b53192006-05-16 02:38:26 +0000360/* Feed data through a temporary buffer to call md5_hash_aligned_block()
361 * with chunks of data that are 4-byte aligned and a multiple of 64 bytes.
362 * This function's internal buffer remembers previous data until it has 64
363 * bytes worth to pass on. Call md5_end() to flush this buffer. */
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +0000364void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx)
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000365{
Denys Vlasenko70186712010-10-16 01:08:32 +0200366 const char *buf = buffer;
367 unsigned buflen = BUFLEN(ctx);
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000368
Denys Vlasenko70186712010-10-16 01:08:32 +0200369 /* RFC 1321 specifies the possible length of the file up to 2^64 bits.
Rob Landley34b53192006-05-16 02:38:26 +0000370 * Here we only track the number of bytes. */
Rob Landley34b53192006-05-16 02:38:26 +0000371 ctx->total += len;
372
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000373 /* Process all input. */
Denys Vlasenko70186712010-10-16 01:08:32 +0200374 while (1) {
375 unsigned i = 64 - buflen;
Denys Vlasenkofb6e6892010-02-08 17:46:49 +0100376 if (i > len)
377 i = len;
Denys Vlasenko70186712010-10-16 01:08:32 +0200378 /* Copy data into aligned buffer. */
379 memcpy(ctx->buffer + buflen, buf, i);
Rob Landley34b53192006-05-16 02:38:26 +0000380 len -= i;
Rob Landley34b53192006-05-16 02:38:26 +0000381 buf += i;
Denys Vlasenko70186712010-10-16 01:08:32 +0200382 buflen += i;
383 /* clever way to do "if (buflen != 64) break; ... ; buflen = 0;" */
384 buflen -= 64;
385 if (buflen != 0)
386 break;
387 /* Buffer is filled up, process it. */
388 md5_hash_block(ctx->buffer, ctx);
389 /*buflen = 0; - already is */
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000390 }
391}
392
393/* Process the remaining bytes in the buffer and put result from CTX
394 * in first 16 bytes following RESBUF. The result is always in little
395 * endian byte order, so that a byte-wise output yields to the wanted
396 * ASCII representation of the message digest.
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000397 */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000398void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx)
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000399{
Denys Vlasenko3d160982010-10-15 18:05:51 +0200400 uint64_t total;
Rob Landley34b53192006-05-16 02:38:26 +0000401 char *buf = ctx->buffer;
Denys Vlasenko70186712010-10-16 01:08:32 +0200402 unsigned i;
403 unsigned buflen = BUFLEN(ctx);
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000404
Rob Landley34b53192006-05-16 02:38:26 +0000405 /* Pad data to block size. */
Denys Vlasenko70186712010-10-16 01:08:32 +0200406 buf[buflen++] = 0x80;
407 memset(buf + buflen, 0, 128 - buflen);
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000408
Denys Vlasenko3d160982010-10-15 18:05:51 +0200409 /* Put the 64-bit file length, expressed in *bits*,
410 * at the end of the buffer.
411 */
Denys Vlasenko70186712010-10-16 01:08:32 +0200412 /* clever way to do "if (buflen > 56) buf += 64": */
413 buf += ((buflen + 7) & 64);
Denys Vlasenko3d160982010-10-15 18:05:51 +0200414 total = ctx->total << 3;
Denys Vlasenko3d160982010-10-15 18:05:51 +0200415 for (i = 0; i < 8; i++) {
416 buf[56 + i] = total;
417 total >>= 8;
418 }
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000419
420 /* Process last bytes. */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000421 if (buf != ctx->buffer)
422 md5_hash_block(ctx->buffer, ctx);
Rob Landley34b53192006-05-16 02:38:26 +0000423 md5_hash_block(buf, ctx);
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000424
Denis Vlasenkocd2cd312009-03-12 15:40:27 +0000425 /* The MD5 result is in little endian byte order.
426 * We (ab)use the fact that A-D are consecutive in memory.
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000427 */
Denis Vlasenkocd2cd312009-03-12 15:40:27 +0000428#if BB_BIG_ENDIAN
429 ctx->A = SWAP_LE32(ctx->A);
430 ctx->B = SWAP_LE32(ctx->B);
431 ctx->C = SWAP_LE32(ctx->C);
432 ctx->D = SWAP_LE32(ctx->D);
433#endif
434 memcpy(resbuf, &ctx->A, sizeof(ctx->A) * 4);
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000435}