aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277>2003-11-18 18:56:25 +0000
committerbug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277>2003-11-18 18:56:25 +0000
commit64d081253f6b21127868d7b8a85efede1c3a12ce (patch)
tree4b51a526cecb5d2457499c78d39fda4f396176aa
parent6a2880c66feaca6c43083887f071dea3a97bd0fd (diff)
downloadbusybox-w32-64d081253f6b21127868d7b8a85efede1c3a12ce.tar.gz
busybox-w32-64d081253f6b21127868d7b8a85efede1c3a12ce.tar.bz2
busybox-w32-64d081253f6b21127868d7b8a85efede1c3a12ce.zip
Replaced by md5_sha1_sum.c
git-svn-id: svn://busybox.net/trunk/busybox@7935 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--coreutils/md5sum.c1102
1 files changed, 0 insertions, 1102 deletions
diff --git a/coreutils/md5sum.c b/coreutils/md5sum.c
deleted file mode 100644
index c0294f4cd..000000000
--- a/coreutils/md5sum.c
+++ /dev/null
@@ -1,1102 +0,0 @@
1/* md5sum.c - Compute MD5 checksum of files or strings according to the
2 * definition of MD5 in RFC 1321 from April 1992.
3 * Copyright (C) 1995-1999 Free Software Foundation, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu> */
21/* Hacked to work with BusyBox by Alfred M. Szmidt <ams@trillian.itslinux.org> */
22
23/*
24 * June 29, 2001 Manuel Novoa III
25 *
26 * Added MD5SUM_SIZE_VS_SPEED configuration option.
27 *
28 * Current valid values, with data from my system for comparison, are:
29 * (using uClibc and running on linux-2.4.4.tar.bz2)
30 * user times (sec) text size (386)
31 * 0 (fastest) 1.1 6144
32 * 1 1.4 5392
33 * 2 3.0 5088
34 * 3 (smallest) 5.1 4912
35 */
36
37#define MD5SUM_SIZE_VS_SPEED 2
38
39/**********************************************************************/
40
41#include <stdio.h>
42#include <errno.h>
43#include <ctype.h>
44#include <getopt.h>
45#include <stdlib.h>
46#include <string.h>
47#include <endian.h>
48#include <sys/types.h>
49#if defined HAVE_LIMITS_H
50# include <limits.h>
51#endif
52#include "busybox.h"
53
54/* For some silly reason, this file uses backwards TRUE and FALSE conventions */
55#undef TRUE
56#undef FALSE
57#define FALSE ((int) 1)
58#define TRUE ((int) 0)
59
60//----------------------------------------------------------------------------
61//--------md5.c
62//----------------------------------------------------------------------------
63
64/* md5.c - Functions to compute MD5 message digest of files or memory blocks
65 * according to the definition of MD5 in RFC 1321 from April 1992.
66 */
67
68/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
69
70//----------------------------------------------------------------------------
71//--------md5.h
72//----------------------------------------------------------------------------
73
74/* md5.h - Declaration of functions and data types used for MD5 sum
75 computing library functions. */
76
77typedef u_int32_t md5_uint32;
78
79/* Structure to save state of computation between the single steps. */
80struct md5_ctx {
81 md5_uint32 A;
82 md5_uint32 B;
83 md5_uint32 C;
84 md5_uint32 D;
85
86 md5_uint32 total[2];
87 md5_uint32 buflen;
88 char buffer[128];
89};
90
91/*
92 * The following three functions are build up the low level used in
93 * the functions `md5_stream' and `md5_buffer'.
94 */
95
96/* Initialize structure containing state of computation.
97 (RFC 1321, 3.3: Step 3) */
98static void md5_init_ctx __P((struct md5_ctx * ctx));
99
100/* Starting with the result of former calls of this function (or the
101 initialization function update the context for the next LEN bytes
102 starting at BUFFER.
103 It is necessary that LEN is a multiple of 64!!! */
104static void md5_process_block __P((const void *buffer, size_t len,
105 struct md5_ctx * ctx));
106
107/* Starting with the result of former calls of this function (or the
108 initialization function update the context for the next LEN bytes
109 starting at BUFFER.
110 It is NOT required that LEN is a multiple of 64. */
111static void md5_process_bytes __P((const void *buffer, size_t len,
112 struct md5_ctx * ctx));
113
114/* Process the remaining bytes in the buffer and put result from CTX
115 in first 16 bytes following RESBUF. The result is always in little
116 endian byte order, so that a byte-wise output yields to the wanted
117 ASCII representation of the message digest.
118
119 IMPORTANT: On some systems it is required that RESBUF is correctly
120 aligned for a 32 bits value. */
121static void *md5_finish_ctx __P((struct md5_ctx * ctx, void *resbuf));
122
123
124
125
126/* Compute MD5 message digest for bytes read from STREAM. The
127 resulting message digest number will be written into the 16 bytes
128 beginning at RESBLOCK. */
129static int md5_stream __P((FILE * stream, void *resblock));
130
131/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
132 result is always in little endian byte order, so that a byte-wise
133 output yields to the wanted ASCII representation of the message
134 digest. */
135static void *md5_buffer __P((const char *buffer, size_t len, void *resblock));
136
137//----------------------------------------------------------------------------
138//--------end of md5.h
139//----------------------------------------------------------------------------
140
141/* Handle endian-ness */
142#if __BYTE_ORDER == __LITTLE_ENDIAN
143#define SWAP(n) (n)
144#else
145#define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24))
146#endif
147
148
149
150#if MD5SUM_SIZE_VS_SPEED == 0
151/* This array contains the bytes used to pad the buffer to the next
152 64-byte boundary. (RFC 1321, 3.1: Step 1) */
153static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
154#endif
155
156/* Initialize structure containing state of computation.
157 (RFC 1321, 3.3: Step 3) */
158void md5_init_ctx(struct md5_ctx *ctx)
159{
160 ctx->A = 0x67452301;
161 ctx->B = 0xefcdab89;
162 ctx->C = 0x98badcfe;
163 ctx->D = 0x10325476;
164
165 ctx->total[0] = ctx->total[1] = 0;
166 ctx->buflen = 0;
167}
168
169/* Process the remaining bytes in the internal buffer and the usual
170 prolog according to the standard and write the result to RESBUF.
171
172 IMPORTANT: On some systems it is required that RESBUF is correctly
173 aligned for a 32 bits value. */
174static void *md5_finish_ctx(struct md5_ctx *ctx, void *resbuf)
175{
176 /* Take yet unprocessed bytes into account. */
177 md5_uint32 bytes = ctx->buflen;
178 size_t pad;
179
180 /* Now count remaining bytes. */
181 ctx->total[0] += bytes;
182 if (ctx->total[0] < bytes)
183 ++ctx->total[1];
184
185 pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
186#if MD5SUM_SIZE_VS_SPEED > 0
187 memset(&ctx->buffer[bytes], 0, pad);
188 ctx->buffer[bytes] = 0x80;
189#else
190 memcpy(&ctx->buffer[bytes], fillbuf, pad);
191#endif
192
193 /* Put the 64-bit file length in *bits* at the end of the buffer. */
194 *(md5_uint32 *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3);
195 *(md5_uint32 *) & ctx->buffer[bytes + pad + 4] =
196 SWAP(((ctx->total[1] << 3) | (ctx->total[0] >> 29)));
197
198 /* Process last bytes. */
199 md5_process_block(ctx->buffer, bytes + pad + 8, ctx);
200
201/* Put result from CTX in first 16 bytes following RESBUF. The result is
202 always in little endian byte order, so that a byte-wise output yields
203 to the wanted ASCII representation of the message digest.
204
205 IMPORTANT: On some systems it is required that RESBUF is correctly
206 aligned for a 32 bits value. */
207 ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A);
208 ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B);
209 ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C);
210 ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D);
211
212 return resbuf;
213}
214
215/* Compute MD5 message digest for bytes read from STREAM. The
216 resulting message digest number will be written into the 16 bytes
217 beginning at RESBLOCK. */
218static int md5_stream(FILE * stream, void *resblock)
219{
220 /* Important: BLOCKSIZE must be a multiple of 64. */
221 static const int BLOCKSIZE = 4096;
222 struct md5_ctx ctx;
223 char buffer[BLOCKSIZE + 72];
224 size_t sum;
225
226 /* Initialize the computation context. */
227 md5_init_ctx(&ctx);
228
229 /* Iterate over full file contents. */
230 while (1) {
231 /* We read the file in blocks of BLOCKSIZE bytes. One call of the
232 computation function processes the whole buffer so that with the
233 next round of the loop another block can be read. */
234 size_t n;
235
236 sum = 0;
237
238 /* Read block. Take care for partial reads. */
239 do {
240 n = fread(buffer + sum, 1, BLOCKSIZE - sum, stream);
241
242 sum += n;
243 }
244 while (sum < BLOCKSIZE && n != 0);
245 if (n == 0 && ferror(stream))
246 return 1;
247
248 /* If end of file is reached, end the loop. */
249 if (n == 0)
250 break;
251
252 /* Process buffer with BLOCKSIZE bytes. Note that
253 BLOCKSIZE % 64 == 0
254 */
255 md5_process_block(buffer, BLOCKSIZE, &ctx);
256 }
257
258 /* Add the last bytes if necessary. */
259 if (sum > 0)
260 md5_process_bytes(buffer, sum, &ctx);
261
262 /* Construct result in desired memory. */
263 md5_finish_ctx(&ctx, resblock);
264 return 0;
265}
266
267/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
268 result is always in little endian byte order, so that a byte-wise
269 output yields to the wanted ASCII representation of the message
270 digest. */
271static void *md5_buffer(const char *buffer, size_t len, void *resblock)
272{
273 struct md5_ctx ctx;
274
275 /* Initialize the computation context. */
276 md5_init_ctx(&ctx);
277
278 /* Process whole buffer but last len % 64 bytes. */
279 md5_process_bytes(buffer, len, &ctx);
280
281 /* Put result in desired memory area. */
282 return md5_finish_ctx(&ctx, resblock);
283}
284
285static void md5_process_bytes(const void *buffer, size_t len,
286 struct md5_ctx *ctx)
287{
288 /* When we already have some bits in our internal buffer concatenate
289 both inputs first. */
290 if (ctx->buflen != 0) {
291 size_t left_over = ctx->buflen;
292 size_t add = 128 - left_over > len ? len : 128 - left_over;
293
294 memcpy(&ctx->buffer[left_over], buffer, add);
295 ctx->buflen += add;
296
297 if (left_over + add > 64) {
298 md5_process_block(ctx->buffer, (left_over + add) & ~63, ctx);
299 /* The regions in the following copy operation cannot overlap. */
300 memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
301 (left_over + add) & 63);
302 ctx->buflen = (left_over + add) & 63;
303 }
304
305 buffer = (const char *) buffer + add;
306 len -= add;
307 }
308
309 /* Process available complete blocks. */
310 if (len > 64) {
311 md5_process_block(buffer, len & ~63, ctx);
312 buffer = (const char *) buffer + (len & ~63);
313 len &= 63;
314 }
315
316 /* Move remaining bytes in internal buffer. */
317 if (len > 0) {
318 memcpy(ctx->buffer, buffer, len);
319 ctx->buflen = len;
320 }
321}
322
323/* These are the four functions used in the four steps of the MD5 algorithm
324 and defined in the RFC 1321. The first function is a little bit optimized
325 (as found in Colin Plumbs public domain implementation). */
326/* #define FF(b, c, d) ((b & c) | (~b & d)) */
327#define FF(b, c, d) (d ^ (b & (c ^ d)))
328#define FG(b, c, d) FF (d, b, c)
329#define FH(b, c, d) (b ^ c ^ d)
330#define FI(b, c, d) (c ^ (b | ~d))
331
332/* Process LEN bytes of BUFFER, accumulating context into CTX.
333 It is assumed that LEN % 64 == 0. */
334static void md5_process_block(const void *buffer, size_t len,
335 struct md5_ctx *ctx)
336{
337 md5_uint32 correct_words[16];
338 const md5_uint32 *words = buffer;
339 size_t nwords = len / sizeof(md5_uint32);
340 const md5_uint32 *endp = words + nwords;
341
342#if MD5SUM_SIZE_VS_SPEED > 0
343 static const md5_uint32 C_array[] = {
344 /* round 1 */
345 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
346 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
347 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
348 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
349 /* round 2 */
350 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
351 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
352 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
353 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
354 /* round 3 */
355 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
356 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
357 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
358 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
359 /* round 4 */
360 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
361 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
362 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
363 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
364 };
365
366 static const char P_array[] = {
367#if MD5SUM_SIZE_VS_SPEED > 1
368 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
369#endif
370 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
371 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
372 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
373 };
374
375#if MD5SUM_SIZE_VS_SPEED > 1
376 static const char S_array[] = {
377 7, 12, 17, 22,
378 5, 9, 14, 20,
379 4, 11, 16, 23,
380 6, 10, 15, 21
381 };
382#endif
383#endif
384
385 md5_uint32 A = ctx->A;
386 md5_uint32 B = ctx->B;
387 md5_uint32 C = ctx->C;
388 md5_uint32 D = ctx->D;
389
390 /* First increment the byte count. RFC 1321 specifies the possible
391 length of the file up to 2^64 bits. Here we only compute the
392 number of bytes. Do a double word increment. */
393 ctx->total[0] += len;
394 if (ctx->total[0] < len)
395 ++ctx->total[1];
396
397 /* Process all bytes in the buffer with 64 bytes in each round of
398 the loop. */
399 while (words < endp) {
400 md5_uint32 *cwp = correct_words;
401 md5_uint32 A_save = A;
402 md5_uint32 B_save = B;
403 md5_uint32 C_save = C;
404 md5_uint32 D_save = D;
405
406#if MD5SUM_SIZE_VS_SPEED > 1
407#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
408
409 const md5_uint32 *pc;
410 const char *pp;
411 const char *ps;
412 int i;
413 md5_uint32 temp;
414
415 for (i = 0; i < 16; i++) {
416 cwp[i] = SWAP(words[i]);
417 }
418 words += 16;
419
420#if MD5SUM_SIZE_VS_SPEED > 2
421 pc = C_array;
422 pp = P_array;
423 ps = S_array - 4;
424
425 for (i = 0; i < 64; i++) {
426 if ((i & 0x0f) == 0)
427 ps += 4;
428 temp = A;
429 switch (i >> 4) {
430 case 0:
431 temp += FF(B, C, D);
432 break;
433 case 1:
434 temp += FG(B, C, D);
435 break;
436 case 2:
437 temp += FH(B, C, D);
438 break;
439 case 3:
440 temp += FI(B, C, D);
441 }
442 temp += cwp[(int) (*pp++)] + *pc++;
443 CYCLIC(temp, ps[i & 3]);
444 temp += B;
445 A = D;
446 D = C;
447 C = B;
448 B = temp;
449 }
450#else
451 pc = C_array;
452 pp = P_array;
453 ps = S_array;
454
455 for (i = 0; i < 16; i++) {
456 temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++;
457 CYCLIC(temp, ps[i & 3]);
458 temp += B;
459 A = D;
460 D = C;
461 C = B;
462 B = temp;
463 }
464
465 ps += 4;
466 for (i = 0; i < 16; i++) {
467 temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++;
468 CYCLIC(temp, ps[i & 3]);
469 temp += B;
470 A = D;
471 D = C;
472 C = B;
473 B = temp;
474 }
475 ps += 4;
476 for (i = 0; i < 16; i++) {
477 temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++;
478 CYCLIC(temp, ps[i & 3]);
479 temp += B;
480 A = D;
481 D = C;
482 C = B;
483 B = temp;
484 }
485 ps += 4;
486 for (i = 0; i < 16; i++) {
487 temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++;
488 CYCLIC(temp, ps[i & 3]);
489 temp += B;
490 A = D;
491 D = C;
492 C = B;
493 B = temp;
494 }
495
496#endif
497#else
498 /* First round: using the given function, the context and a constant
499 the next context is computed. Because the algorithms processing
500 unit is a 32-bit word and it is determined to work on words in
501 little endian byte order we perhaps have to change the byte order
502 before the computation. To reduce the work for the next steps
503 we store the swapped words in the array CORRECT_WORDS. */
504
505#define OP(a, b, c, d, s, T) \
506 do \
507 { \
508 a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
509 ++words; \
510 CYCLIC (a, s); \
511 a += b; \
512 } \
513 while (0)
514
515 /* It is unfortunate that C does not provide an operator for
516 cyclic rotation. Hope the C compiler is smart enough. */
517 /* gcc 2.95.4 seems to be --aaronl */
518#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
519
520 /* Before we start, one word to the strange constants.
521 They are defined in RFC 1321 as
522
523 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
524 */
525
526#if MD5SUM_SIZE_VS_SPEED == 1
527 const md5_uint32 *pc;
528 const char *pp;
529 int i;
530#endif
531
532 /* Round 1. */
533#if MD5SUM_SIZE_VS_SPEED == 1
534 pc = C_array;
535 for (i = 0; i < 4; i++) {
536 OP(A, B, C, D, 7, *pc++);
537 OP(D, A, B, C, 12, *pc++);
538 OP(C, D, A, B, 17, *pc++);
539 OP(B, C, D, A, 22, *pc++);
540 }
541#else
542 OP(A, B, C, D, 7, 0xd76aa478);
543 OP(D, A, B, C, 12, 0xe8c7b756);
544 OP(C, D, A, B, 17, 0x242070db);
545 OP(B, C, D, A, 22, 0xc1bdceee);
546 OP(A, B, C, D, 7, 0xf57c0faf);
547 OP(D, A, B, C, 12, 0x4787c62a);
548 OP(C, D, A, B, 17, 0xa8304613);
549 OP(B, C, D, A, 22, 0xfd469501);
550 OP(A, B, C, D, 7, 0x698098d8);
551 OP(D, A, B, C, 12, 0x8b44f7af);
552 OP(C, D, A, B, 17, 0xffff5bb1);
553 OP(B, C, D, A, 22, 0x895cd7be);
554 OP(A, B, C, D, 7, 0x6b901122);
555 OP(D, A, B, C, 12, 0xfd987193);
556 OP(C, D, A, B, 17, 0xa679438e);
557 OP(B, C, D, A, 22, 0x49b40821);
558#endif
559
560 /* For the second to fourth round we have the possibly swapped words
561 in CORRECT_WORDS. Redefine the macro to take an additional first
562 argument specifying the function to use. */
563#undef OP
564#define OP(f, a, b, c, d, k, s, T) \
565 do \
566 { \
567 a += f (b, c, d) + correct_words[k] + T; \
568 CYCLIC (a, s); \
569 a += b; \
570 } \
571 while (0)
572
573 /* Round 2. */
574#if MD5SUM_SIZE_VS_SPEED == 1
575 pp = P_array;
576 for (i = 0; i < 4; i++) {
577 OP(FG, A, B, C, D, (int) (*pp++), 5, *pc++);
578 OP(FG, D, A, B, C, (int) (*pp++), 9, *pc++);
579 OP(FG, C, D, A, B, (int) (*pp++), 14, *pc++);
580 OP(FG, B, C, D, A, (int) (*pp++), 20, *pc++);
581 }
582#else
583 OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
584 OP(FG, D, A, B, C, 6, 9, 0xc040b340);
585 OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
586 OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
587 OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
588 OP(FG, D, A, B, C, 10, 9, 0x02441453);
589 OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
590 OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
591 OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
592 OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
593 OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
594 OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
595 OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
596 OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
597 OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
598 OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
599#endif
600
601 /* Round 3. */
602#if MD5SUM_SIZE_VS_SPEED == 1
603 for (i = 0; i < 4; i++) {
604 OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++);
605 OP(FH, D, A, B, C, (int) (*pp++), 11, *pc++);
606 OP(FH, C, D, A, B, (int) (*pp++), 16, *pc++);
607 OP(FH, B, C, D, A, (int) (*pp++), 23, *pc++);
608 }
609#else
610 OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
611 OP(FH, D, A, B, C, 8, 11, 0x8771f681);
612 OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
613 OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
614 OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
615 OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
616 OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
617 OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
618 OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
619 OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
620 OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
621 OP(FH, B, C, D, A, 6, 23, 0x04881d05);
622 OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
623 OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
624 OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
625 OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
626#endif
627
628 /* Round 4. */
629#if MD5SUM_SIZE_VS_SPEED == 1
630 for (i = 0; i < 4; i++) {
631 OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++);
632 OP(FI, D, A, B, C, (int) (*pp++), 10, *pc++);
633 OP(FI, C, D, A, B, (int) (*pp++), 15, *pc++);
634 OP(FI, B, C, D, A, (int) (*pp++), 21, *pc++);
635 }
636#else
637 OP(FI, A, B, C, D, 0, 6, 0xf4292244);
638 OP(FI, D, A, B, C, 7, 10, 0x432aff97);
639 OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
640 OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
641 OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
642 OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
643 OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
644 OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
645 OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
646 OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
647 OP(FI, C, D, A, B, 6, 15, 0xa3014314);
648 OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
649 OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
650 OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
651 OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
652 OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
653#endif
654#endif
655
656 /* Add the starting values of the context. */
657 A += A_save;
658 B += B_save;
659 C += C_save;
660 D += D_save;
661 }
662
663 /* Put checksum in context given as argument. */
664 ctx->A = A;
665 ctx->B = B;
666 ctx->C = C;
667 ctx->D = D;
668}
669
670//----------------------------------------------------------------------------
671//--------end of md5.c
672//----------------------------------------------------------------------------
673
674#define ISWHITE(c) ((c) == ' ' || (c) == '\t')
675#define ISXDIGIT(c) (isxdigit (c))
676
677/* The minimum length of a valid digest line in a file produced
678 by `md5sum FILE' and read by `md5sum -c'. This length does
679 not include any newline character at the end of a line. */
680static const int MIN_DIGEST_LINE_LENGTH = 35; /* 32 - message digest length
681 2 - blank and binary indicator
682 1 - minimum filename length */
683
684static int have_read_stdin; /* Nonzero if any of the files read were
685 the standard input. */
686
687static int status_only = 0; /* With -c, don't generate any output.
688 The exit code indicates success or failure */
689static int warn = 0; /* With -w, print a message to standard error warning
690 about each improperly formatted MD5 checksum line */
691
692static int split_3(char *s, size_t s_len, unsigned char **u, char **w)
693{
694 size_t i = 0;
695 int escaped_filename = 0;
696
697 while (ISWHITE(s[i]))
698 ++i;
699
700 /* The line must have at least 35 (36 if the first is a backslash)
701 more characters to contain correct message digest information.
702 Ignore this line if it is too short. */
703 if (!(s_len - i >= MIN_DIGEST_LINE_LENGTH
704 || (s[i] == '\\' && s_len - i >= 1 + MIN_DIGEST_LINE_LENGTH)))
705 return FALSE;
706
707 if (s[i] == '\\') {
708 ++i;
709 escaped_filename = 1;
710 }
711 *u = (unsigned char *) &s[i];
712
713 /* The first field has to be the 32-character hexadecimal
714 representation of the message digest. If it is not followed
715 immediately by a white space it's an error. */
716 i += 32;
717 if (!ISWHITE(s[i]))
718 return FALSE;
719
720 s[i++] = '\0';
721
722 if (s[i] != ' ' && s[i] != '*')
723 return FALSE;
724
725 /* All characters between the type indicator and end of line are
726 significant -- that includes leading and trailing white space. */
727 *w = &s[++i];
728
729 if (escaped_filename) {
730 /* Translate each `\n' string in the file name to a NEWLINE,
731 and each `\\' string to a backslash. */
732
733 char *dst = &s[i];
734
735 while (i < s_len) {
736 switch (s[i]) {
737 case '\\':
738 if (i == s_len - 1) {
739 /* A valid line does not end with a backslash. */
740 return FALSE;
741 }
742 ++i;
743 switch (s[i++]) {
744 case 'n':
745 *dst++ = '\n';
746 break;
747 case '\\':
748 *dst++ = '\\';
749 break;
750 default:
751 /* Only `\' or `n' may follow a backslash. */
752 return FALSE;
753 }
754 break;
755
756 case '\0':
757 /* The file name may not contain a NUL. */
758 return FALSE;
759 break;
760
761 default:
762 *dst++ = s[i++];
763 break;
764 }
765 }
766 *dst = '\0';
767 }
768 return TRUE;
769}
770
771static inline int hex_digits(unsigned char const *s)
772{
773 while (*s) {
774 if (!ISXDIGIT(*s))
775 return TRUE;
776 ++s;
777 }
778 return FALSE;
779}
780
781/* An interface to md5_stream. Operate on FILENAME (it may be "-") and
782 put the result in *MD5_RESULT. Return non-zero upon failure, zero
783 to indicate success. */
784static int md5_file(const char *filename, unsigned char *md5_result)
785{
786 FILE *fp;
787
788 if (filename[0] == '-' && filename[1] == '\0') {
789 have_read_stdin = 1;
790 fp = stdin;
791 } else {
792 fp = bb_wfopen(filename, "r");
793 if (fp == NULL)
794 return FALSE;
795 }
796
797 if (md5_stream(fp, md5_result)) {
798 bb_perror_msg("%s", filename);
799
800 if (fp != stdin)
801 fclose(fp);
802 return FALSE;
803 }
804
805 if (fp != stdin && fclose(fp) == EOF) {
806 bb_perror_msg("%s", filename);
807 return FALSE;
808 }
809
810 return TRUE;
811}
812
813static int md5_check(const char *checkfile_name)
814{
815 FILE *checkfile_stream;
816 int n_properly_formated_lines = 0;
817 int n_mismatched_checksums = 0;
818 int n_open_or_read_failures = 0;
819 unsigned char md5buffer[16];
820 size_t line_number;
821 char line[BUFSIZ];
822
823 if (checkfile_name[0] == '-' && checkfile_name[1] == '\0') {
824 have_read_stdin = 1;
825 checkfile_stream = stdin;
826 } else {
827 checkfile_stream = bb_wfopen(checkfile_name, "r");
828 if (checkfile_stream == NULL)
829 return FALSE;
830 }
831
832 line_number = 0;
833
834 do {
835 char *filename;
836 unsigned char *md5num;
837 int line_length;
838
839 ++line_number;
840
841 fgets(line, BUFSIZ - 1, checkfile_stream);
842 line_length = strlen(line);
843
844 if (line_length <= 0 || line == NULL)
845 break;
846
847 /* Ignore comment lines, which begin with a '#' character. */
848 if (line[0] == '#')
849 continue;
850
851 /* Remove any trailing newline. */
852 if (line[line_length - 1] == '\n')
853 line[--line_length] = '\0';
854
855 if (split_3(line, line_length, &md5num, &filename)
856 || !hex_digits(md5num)) {
857 if (warn) {
858 bb_error_msg
859 ("%s: %lu: improperly formatted MD5 checksum line",
860 checkfile_name, (unsigned long) line_number);
861 }
862 } else {
863 static const char bin2hex[] = {
864 '0', '1', '2', '3',
865 '4', '5', '6', '7',
866 '8', '9', 'a', 'b',
867 'c', 'd', 'e', 'f'
868 };
869
870 ++n_properly_formated_lines;
871
872 if (md5_file(filename, md5buffer)) {
873 ++n_open_or_read_failures;
874 if (!status_only) {
875 printf("%s: FAILED open or read\n", filename);
876 fflush(stdout);
877 }
878 } else {
879 size_t cnt;
880
881 /* Compare generated binary number with text representation
882 in check file. Ignore case of hex digits. */
883 for (cnt = 0; cnt < 16; ++cnt) {
884 if (tolower(md5num[2 * cnt])
885 != bin2hex[md5buffer[cnt] >> 4]
886 || (tolower(md5num[2 * cnt + 1])
887 != (bin2hex[md5buffer[cnt] & 0xf])))
888 break;
889 }
890 if (cnt != 16)
891 ++n_mismatched_checksums;
892
893 if (!status_only) {
894 printf("%s: %s\n", filename,
895 (cnt != 16 ? "FAILED" : "OK"));
896 fflush(stdout);
897 }
898 }
899 }
900 }
901
902 while (!feof(checkfile_stream) && !ferror(checkfile_stream));
903
904 if (ferror(checkfile_stream)) {
905 bb_error_msg("%s: read error", checkfile_name);
906 return FALSE;
907 }
908
909 if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) {
910 bb_perror_msg("md5sum: %s", checkfile_name);
911 return FALSE;
912 }
913
914 if (n_properly_formated_lines == 0) {
915 /* Warn if no tests are found. */
916 bb_error_msg("%s: no properly formatted MD5 checksum lines found",
917 checkfile_name);
918 return FALSE;
919 } else {
920 if (!status_only) {
921 int n_computed_checkums = (n_properly_formated_lines
922 - n_open_or_read_failures);
923
924 if (n_open_or_read_failures > 0) {
925 bb_error_msg
926 ("WARNING: %d of %d listed files could not be read",
927 n_open_or_read_failures, n_properly_formated_lines);
928 return FALSE;
929 }
930
931 if (n_mismatched_checksums > 0) {
932 bb_error_msg
933 ("WARNING: %d of %d computed checksums did NOT match",
934 n_mismatched_checksums, n_computed_checkums);
935 return FALSE;
936 }
937 }
938 }
939
940 return ((n_properly_formated_lines > 0 && n_mismatched_checksums == 0
941 && n_open_or_read_failures == 0) ? 0 : 1);
942}
943
944int md5sum_main(int argc, char **argv)
945{
946 unsigned char md5buffer[16];
947 int do_check = 0;
948 int opt;
949 char **string = NULL;
950 size_t n_strings = 0;
951 size_t err = 0;
952 char file_type_specified = 0;
953 char binary = 0;
954
955 while ((opt = getopt(argc, argv, "g:bcstw")) != -1) {
956 switch (opt) {
957 case 'g':{ /* read a string */
958 if (string == NULL)
959 string = (char **) xmalloc((argc - 1) * sizeof(char *));
960
961 string[n_strings++] = optarg;
962 break;
963 }
964
965 case 'b': /* read files in binary mode */
966 file_type_specified = 1;
967 binary = 1;
968 break;
969
970 case 'c': /* check MD5 sums against given list */
971 do_check = 1;
972 break;
973
974 case 's': /* don't output anything, status code shows success */
975 status_only = 1;
976 warn = 0;
977 break;
978
979 case 't': /* read files in text mode (default) */
980 file_type_specified = 1;
981 binary = 0;
982 break;
983
984 case 'w': /* warn about improperly formated MD5 checksum lines */
985 status_only = 0;
986 warn = 1;
987 break;
988
989 default:
990 bb_show_usage();
991 }
992 }
993
994 if (file_type_specified && do_check) {
995 bb_error_msg_and_die
996 ("the -b and -t options are meaningless when verifying checksums");
997 }
998
999 if (n_strings > 0 && do_check) {
1000 bb_error_msg_and_die("the -g and -c options are mutually exclusive");
1001 }
1002
1003 if (status_only && !do_check) {
1004 bb_error_msg_and_die
1005 ("the -s option is meaningful only when verifying checksums");
1006 }
1007
1008 if (warn && !do_check) {
1009 bb_error_msg_and_die
1010 ("the -w option is meaningful only when verifying checksums");
1011 }
1012
1013 if (n_strings > 0) {
1014 size_t i;
1015
1016 if (optind < argc) {
1017 bb_error_msg_and_die("no files may be specified when using -g");
1018 }
1019 for (i = 0; i < n_strings; ++i) {
1020 size_t cnt;
1021
1022 md5_buffer(string[i], strlen(string[i]), md5buffer);
1023
1024 for (cnt = 0; cnt < 16; ++cnt)
1025 printf("%02x", md5buffer[cnt]);
1026
1027 printf(" \"%s\"\n", string[i]);
1028 }
1029 } else if (do_check) {
1030 if (optind + 1 < argc) {
1031 bb_error_msg("only one argument may be specified when using -c");
1032 }
1033
1034 err = md5_check((optind == argc) ? "-" : argv[optind]);
1035 } else {
1036 if (optind == argc)
1037 argv[argc++] = "-";
1038
1039 for (; optind < argc; ++optind) {
1040 int fail;
1041 char *file = argv[optind];
1042
1043 fail = md5_file(file, md5buffer);
1044 err |= fail;
1045 if (!fail && file[0] == '-' && file[1] == '\0') {
1046 size_t i;
1047
1048 for (i = 0; i < 16; ++i)
1049 printf("%02x", md5buffer[i]);
1050 putchar('\n');
1051 } else if (!fail) {
1052 size_t i;
1053
1054 /* Output a leading backslash if the file name contains
1055 a newline or backslash. */
1056 if (strchr(file, '\n') || strchr(file, '\\'))
1057 putchar('\\');
1058
1059 for (i = 0; i < 16; ++i)
1060 printf("%02x", md5buffer[i]);
1061
1062 putchar(' ');
1063 if (binary)
1064 putchar('*');
1065 else
1066 putchar(' ');
1067
1068 /* Translate each NEWLINE byte to the string, "\\n",
1069 and each backslash to "\\\\". */
1070 for (i = 0; i < strlen(file); ++i) {
1071 switch (file[i]) {
1072 case '\n':
1073 fputs("\\n", stdout);
1074 break;
1075
1076 case '\\':
1077 fputs("\\\\", stdout);
1078 break;
1079
1080 default:
1081 putchar(file[i]);
1082 break;
1083 }
1084 }
1085 putchar('\n');
1086 }
1087 }
1088 }
1089
1090 if (fclose(stdout) == EOF) {
1091 bb_error_msg_and_die("write error");
1092 }
1093
1094 if (have_read_stdin && fclose(stdin) == EOF) {
1095 bb_error_msg_and_die(bb_msg_standard_input);
1096 }
1097
1098 if (err == 0)
1099 return EXIT_SUCCESS;
1100 else
1101 return EXIT_FAILURE;
1102}