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