blob: 9e5b496ceefc1c45af8caf71e633957bb6b8db31 [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 Vlasenko0ef64bd2010-08-16 20:14:46 +02003 * md5.c - 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 ctx->buflen = 0;
38}
39
40/* These are the four functions used in the four steps of the MD5 algorithm
41 * and defined in the RFC 1321. The first function is a little bit optimized
42 * (as found in Colin Plumbs public domain implementation).
43 * #define FF(b, c, d) ((b & c) | (~b & d))
44 */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000045#define FF(b, c, d) (d ^ (b & (c ^ d)))
46#define FG(b, c, d) FF(d, b, c)
47#define FH(b, c, d) (b ^ c ^ d)
48#define FI(b, c, d) (c ^ (b | ~d))
49
50#define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s))))
Rob Landley5cf7c2d2006-02-21 06:44:43 +000051
Rob Landley34b53192006-05-16 02:38:26 +000052/* Hash a single block, 64 bytes long and 4-byte aligned. */
53static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
Rob Landley5cf7c2d2006-02-21 06:44:43 +000054{
55 uint32_t correct_words[16];
56 const uint32_t *words = buffer;
Rob Landley5cf7c2d2006-02-21 06:44:43 +000057
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000058#if MD5_SIZE_VS_SPEED > 0
Denys Vlasenko3d160982010-10-15 18:05:51 +020059 /* Before we start, one word to the strange constants.
60 They are defined in RFC 1321 as
61 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
62 */
Rob Landley5cf7c2d2006-02-21 06:44:43 +000063 static const uint32_t C_array[] = {
64 /* round 1 */
65 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
66 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
67 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
68 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
69 /* round 2 */
70 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
71 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
72 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
73 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
74 /* round 3 */
75 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
76 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
77 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
78 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
79 /* round 4 */
80 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
81 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
82 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
83 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
84 };
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000085 static const char P_array[] ALIGN1 = {
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000086# if MD5_SIZE_VS_SPEED > 1
Rob Landley5cf7c2d2006-02-21 06:44:43 +000087 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000088# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +000089 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
90 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
91 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
92 };
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +000093# if MD5_SIZE_VS_SPEED > 1
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000094 static const char S_array[] ALIGN1 = {
Rob Landley5cf7c2d2006-02-21 06:44:43 +000095 7, 12, 17, 22,
96 5, 9, 14, 20,
97 4, 11, 16, 23,
98 6, 10, 15, 21
99 };
Denys Vlasenko3d160982010-10-15 18:05:51 +0200100# endif
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000101#endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000102 uint32_t A = ctx->A;
103 uint32_t B = ctx->B;
104 uint32_t C = ctx->C;
105 uint32_t D = ctx->D;
106
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000107 uint32_t *cwp = correct_words;
108 uint32_t A_save = A;
109 uint32_t B_save = B;
110 uint32_t C_save = C;
111 uint32_t D_save = D;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000112
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000113#if MD5_SIZE_VS_SPEED > 1
114 const uint32_t *pc;
115 const char *pp;
116 const char *ps;
117 int i;
118 uint32_t temp;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000119
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000120 for (i = 0; i < 16; i++)
121 cwp[i] = SWAP_LE32(words[i]);
122 words += 16;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000123
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000124# if MD5_SIZE_VS_SPEED > 2
125 pc = C_array;
126 pp = P_array;
127 ps = S_array - 4;
128
129 for (i = 0; i < 64; i++) {
130 if ((i & 0x0f) == 0)
131 ps += 4;
132 temp = A;
133 switch (i >> 4) {
134 case 0:
135 temp += FF(B, C, D);
136 break;
137 case 1:
138 temp += FG(B, C, D);
139 break;
140 case 2:
141 temp += FH(B, C, D);
142 break;
143 case 3:
144 temp += FI(B, C, D);
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000145 }
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000146 temp += cwp[(int) (*pp++)] + *pc++;
147 temp = rotl32(temp, ps[i & 3]);
148 temp += B;
149 A = D;
150 D = C;
151 C = B;
152 B = temp;
153 }
Denys Vlasenko3d160982010-10-15 18:05:51 +0200154# else /* MD5_SIZE_VS_SPEED == 2 */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000155 pc = C_array;
156 pp = P_array;
157 ps = S_array;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000158
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000159 for (i = 0; i < 16; i++) {
160 temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++;
161 temp = rotl32(temp, ps[i & 3]);
162 temp += B;
163 A = D;
164 D = C;
165 C = B;
166 B = temp;
167 }
168 ps += 4;
169 for (i = 0; i < 16; i++) {
170 temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++;
171 temp = rotl32(temp, ps[i & 3]);
172 temp += B;
173 A = D;
174 D = C;
175 C = B;
176 B = temp;
177 }
178 ps += 4;
179 for (i = 0; i < 16; i++) {
180 temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++;
181 temp = rotl32(temp, ps[i & 3]);
182 temp += B;
183 A = D;
184 D = C;
185 C = B;
186 B = temp;
187 }
188 ps += 4;
189 for (i = 0; i < 16; i++) {
190 temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++;
191 temp = rotl32(temp, ps[i & 3]);
192 temp += B;
193 A = D;
194 D = C;
195 C = B;
196 B = temp;
197 }
Denys Vlasenko3d160982010-10-15 18:05:51 +0200198# endif
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000199
Denys Vlasenko3d160982010-10-15 18:05:51 +0200200#else /* MD5_SIZE_VS_SPEED == 0 or 1 */
201
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000202 /* First round: using the given function, the context and a constant
Denys Vlasenko3d160982010-10-15 18:05:51 +0200203 the next context is computed. Because the algorithm's processing
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000204 unit is a 32-bit word and it is determined to work on words in
205 little endian byte order we perhaps have to change the byte order
206 before the computation. To reduce the work for the next steps
207 we store the swapped words in the array CORRECT_WORDS. */
Denys Vlasenko3d160982010-10-15 18:05:51 +0200208# undef OP
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000209# define OP(a, b, c, d, s, T) \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000210 do { \
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000211 a += FF(b, c, d) + (*cwp++ = SWAP_LE32(*words)) + T; \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000212 ++words; \
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000213 a = rotl32(a, s); \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000214 a += b; \
215 } while (0)
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000216
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000217# if MD5_SIZE_VS_SPEED == 1
218 const uint32_t *pc;
219 const char *pp;
220 int i;
Denys Vlasenko3d160982010-10-15 18:05:51 +0200221# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000222
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000223 /* Round 1. */
224# if MD5_SIZE_VS_SPEED == 1
225 pc = C_array;
226 for (i = 0; i < 4; i++) {
227 OP(A, B, C, D, 7, *pc++);
228 OP(D, A, B, C, 12, *pc++);
229 OP(C, D, A, B, 17, *pc++);
230 OP(B, C, D, A, 22, *pc++);
231 }
232# else
233 OP(A, B, C, D, 7, 0xd76aa478);
234 OP(D, A, B, C, 12, 0xe8c7b756);
235 OP(C, D, A, B, 17, 0x242070db);
236 OP(B, C, D, A, 22, 0xc1bdceee);
237 OP(A, B, C, D, 7, 0xf57c0faf);
238 OP(D, A, B, C, 12, 0x4787c62a);
239 OP(C, D, A, B, 17, 0xa8304613);
240 OP(B, C, D, A, 22, 0xfd469501);
241 OP(A, B, C, D, 7, 0x698098d8);
242 OP(D, A, B, C, 12, 0x8b44f7af);
243 OP(C, D, A, B, 17, 0xffff5bb1);
244 OP(B, C, D, A, 22, 0x895cd7be);
245 OP(A, B, C, D, 7, 0x6b901122);
246 OP(D, A, B, C, 12, 0xfd987193);
247 OP(C, D, A, B, 17, 0xa679438e);
248 OP(B, C, D, A, 22, 0x49b40821);
Denys Vlasenko3d160982010-10-15 18:05:51 +0200249# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000250
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000251 /* For the second to fourth round we have the possibly swapped words
252 in CORRECT_WORDS. Redefine the macro to take an additional first
253 argument specifying the function to use. */
254# undef OP
255# define OP(f, a, b, c, d, k, s, T) \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000256 do { \
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000257 a += f(b, c, d) + correct_words[k] + T; \
258 a = rotl32(a, s); \
Denis Vlasenko2570b2e2008-03-28 01:00:09 +0000259 a += b; \
260 } while (0)
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000261
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000262 /* Round 2. */
263# if MD5_SIZE_VS_SPEED == 1
264 pp = P_array;
265 for (i = 0; i < 4; i++) {
266 OP(FG, A, B, C, D, (int) (*pp++), 5, *pc++);
267 OP(FG, D, A, B, C, (int) (*pp++), 9, *pc++);
268 OP(FG, C, D, A, B, (int) (*pp++), 14, *pc++);
269 OP(FG, B, C, D, A, (int) (*pp++), 20, *pc++);
270 }
271# else
272 OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
273 OP(FG, D, A, B, C, 6, 9, 0xc040b340);
274 OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
275 OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
276 OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
277 OP(FG, D, A, B, C, 10, 9, 0x02441453);
278 OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
279 OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
280 OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
281 OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
282 OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
283 OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
284 OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
285 OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
286 OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
287 OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
Denys Vlasenko3d160982010-10-15 18:05:51 +0200288# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000289
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000290 /* Round 3. */
291# if MD5_SIZE_VS_SPEED == 1
292 for (i = 0; i < 4; i++) {
293 OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++);
294 OP(FH, D, A, B, C, (int) (*pp++), 11, *pc++);
295 OP(FH, C, D, A, B, (int) (*pp++), 16, *pc++);
296 OP(FH, B, C, D, A, (int) (*pp++), 23, *pc++);
297 }
298# else
299 OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
300 OP(FH, D, A, B, C, 8, 11, 0x8771f681);
301 OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
302 OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
303 OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
304 OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
305 OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
306 OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
307 OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
308 OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
309 OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
310 OP(FH, B, C, D, A, 6, 23, 0x04881d05);
311 OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
312 OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
313 OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
314 OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
Denys Vlasenko3d160982010-10-15 18:05:51 +0200315# endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000316
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000317 /* Round 4. */
318# if MD5_SIZE_VS_SPEED == 1
319 for (i = 0; i < 4; i++) {
320 OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++);
321 OP(FI, D, A, B, C, (int) (*pp++), 10, *pc++);
322 OP(FI, C, D, A, B, (int) (*pp++), 15, *pc++);
323 OP(FI, B, C, D, A, (int) (*pp++), 21, *pc++);
324 }
325# else
326 OP(FI, A, B, C, D, 0, 6, 0xf4292244);
327 OP(FI, D, A, B, C, 7, 10, 0x432aff97);
328 OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
329 OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
330 OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
331 OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
332 OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
333 OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
334 OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
335 OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
336 OP(FI, C, D, A, B, 6, 15, 0xa3014314);
337 OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
338 OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
339 OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
340 OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
341 OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
Denys Vlasenko3d160982010-10-15 18:05:51 +0200342# endif
343#endif
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000344
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000345 /* Add the starting values of the context. */
346 A += A_save;
347 B += B_save;
348 C += C_save;
349 D += D_save;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000350
351 /* Put checksum in context given as argument. */
352 ctx->A = A;
353 ctx->B = B;
354 ctx->C = C;
355 ctx->D = D;
356}
357
Rob Landley34b53192006-05-16 02:38:26 +0000358/* Feed data through a temporary buffer to call md5_hash_aligned_block()
359 * with chunks of data that are 4-byte aligned and a multiple of 64 bytes.
360 * This function's internal buffer remembers previous data until it has 64
361 * bytes worth to pass on. Call md5_end() to flush this buffer. */
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +0000362void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx)
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000363{
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000364 char *buf = (char *)buffer;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000365
Rob Landley34b53192006-05-16 02:38:26 +0000366 /* RFC 1321 specifies the possible length of the file up to 2^64 bits,
367 * Here we only track the number of bytes. */
Rob Landley34b53192006-05-16 02:38:26 +0000368 ctx->total += len;
369
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000370 /* Process all input. */
Rob Landley34b53192006-05-16 02:38:26 +0000371 while (len) {
Denis Vlasenko77ad97f2008-05-13 02:27:31 +0000372 unsigned i = 64 - ctx->buflen;
Rob Landley34b53192006-05-16 02:38:26 +0000373
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000374 /* Copy data into aligned buffer. */
Denys Vlasenkofb6e6892010-02-08 17:46:49 +0100375 if (i > len)
376 i = len;
Rob Landley34b53192006-05-16 02:38:26 +0000377 memcpy(ctx->buffer + ctx->buflen, buf, i);
378 len -= i;
379 ctx->buflen += i;
380 buf += i;
381
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000382 /* When buffer fills up, process it. */
Rob Landley34b53192006-05-16 02:38:26 +0000383 if (ctx->buflen == 64) {
384 md5_hash_block(ctx->buffer, ctx);
385 ctx->buflen = 0;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000386 }
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000387 }
388}
389
390/* Process the remaining bytes in the buffer and put result from CTX
391 * in first 16 bytes following RESBUF. The result is always in little
392 * endian byte order, so that a byte-wise output yields to the wanted
393 * ASCII representation of the message digest.
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000394 */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000395void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx)
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000396{
Denys Vlasenko3d160982010-10-15 18:05:51 +0200397 uint64_t total;
Rob Landley34b53192006-05-16 02:38:26 +0000398 char *buf = ctx->buffer;
399 int i;
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000400
Rob Landley34b53192006-05-16 02:38:26 +0000401 /* Pad data to block size. */
Rob Landley34b53192006-05-16 02:38:26 +0000402 buf[ctx->buflen++] = 0x80;
403 memset(buf + ctx->buflen, 0, 128 - ctx->buflen);
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000404
Denys Vlasenko3d160982010-10-15 18:05:51 +0200405 /* Put the 64-bit file length, expressed in *bits*,
406 * at the end of the buffer.
407 */
408 total = ctx->total << 3;
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000409 if (ctx->buflen > 56)
410 buf += 64;
Denys Vlasenko3d160982010-10-15 18:05:51 +0200411 for (i = 0; i < 8; i++) {
412 buf[56 + i] = total;
413 total >>= 8;
414 }
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000415
416 /* Process last bytes. */
Denis Vlasenkoe9b9a192008-11-11 01:38:04 +0000417 if (buf != ctx->buffer)
418 md5_hash_block(ctx->buffer, ctx);
Rob Landley34b53192006-05-16 02:38:26 +0000419 md5_hash_block(buf, ctx);
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000420
Denis Vlasenkocd2cd312009-03-12 15:40:27 +0000421 /* The MD5 result is in little endian byte order.
422 * We (ab)use the fact that A-D are consecutive in memory.
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000423 */
Denis Vlasenkocd2cd312009-03-12 15:40:27 +0000424#if BB_BIG_ENDIAN
425 ctx->A = SWAP_LE32(ctx->A);
426 ctx->B = SWAP_LE32(ctx->B);
427 ctx->C = SWAP_LE32(ctx->C);
428 ctx->D = SWAP_LE32(ctx->D);
429#endif
430 memcpy(resbuf, &ctx->A, sizeof(ctx->A) * 4);
Rob Landley5cf7c2d2006-02-21 06:44:43 +0000431}