aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2003-11-10 04:33:55 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2003-11-10 04:33:55 +0000
commitd2a897aab084b433231aab5f6908a79cba67dc5d (patch)
tree8a0b113bd44bc2be639e070b50668e4ad69091f2
parent0bdf41ad7e81451bc829365e0d9a676dda8145f9 (diff)
downloadbusybox-w32-d2a897aab084b433231aab5f6908a79cba67dc5d.tar.gz
busybox-w32-d2a897aab084b433231aab5f6908a79cba67dc5d.tar.bz2
busybox-w32-d2a897aab084b433231aab5f6908a79cba67dc5d.zip
Merge common parts of sha1sum and md5sum, which is everything except the
algorithms. Move algorithms to hash_fd and make them available via a common function.
-rw-r--r--coreutils/Config.in19
-rw-r--r--coreutils/Makefile.in4
-rw-r--r--coreutils/md5_sha1_sum.c195
-rw-r--r--include/libbb.h6
-rw-r--r--libbb/Makefile.in2
-rw-r--r--libbb/hash_fd.c848
6 files changed, 1063 insertions, 11 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in
index 90f681c04..a388cd9e8 100644
--- a/coreutils/Config.in
+++ b/coreutils/Config.in
@@ -373,14 +373,6 @@ config CONFIG_SHA1SUM
373 help 373 help
374 Compute and check SHA1 message digest 374 Compute and check SHA1 message digest
375 375
376config CONFIG_FEATURE_SHA1SUM_CHECK
377 bool " Enable -c and -w options"
378 default n
379 depends on CONFIG_SHA1SUM
380 help
381 Enabling the -c and -w options allows files to be checked
382 against pre-calculated hash values.
383
384config CONFIG_SLEEP 376config CONFIG_SLEEP
385 bool "sleep (single integer arg with no suffix)" 377 bool "sleep (single integer arg with no suffix)"
386 default n 378 default n
@@ -591,4 +583,15 @@ config CONFIG_FEATURE_HUMAN_READABLE
591 help 583 help
592 Allow df, du, and ls to have human readable output. 584 Allow df, du, and ls to have human readable output.
593 585
586comment "Common options for md5sum, sha1sum"
587 depends on CONFIG_MD5SUM || CONFIG_SHA1SUM
588
589config CONFIG_FEATURE_MD5_SHA1_SUM_CHECK
590 bool " Enable -c and -w options"
591 default n
592 depends on CONFIG_MD5SUM || CONFIG_SHA1SUM
593 help
594 Enabling the -c and -w options allows files to be checked
595 against pre-calculated hash values.
596
594endmenu 597endmenu
diff --git a/coreutils/Makefile.in b/coreutils/Makefile.in
index b672f08f7..c7ba57e04 100644
--- a/coreutils/Makefile.in
+++ b/coreutils/Makefile.in
@@ -52,7 +52,7 @@ COREUTILS-$(CONFIG_LENGTH) += length.o
52COREUTILS-$(CONFIG_LN) += ln.o 52COREUTILS-$(CONFIG_LN) += ln.o
53COREUTILS-$(CONFIG_LOGNAME) += logname.o 53COREUTILS-$(CONFIG_LOGNAME) += logname.o
54COREUTILS-$(CONFIG_LS) += ls.o 54COREUTILS-$(CONFIG_LS) += ls.o
55COREUTILS-$(CONFIG_MD5SUM) += md5sum.o 55COREUTILS-$(CONFIG_MD5SUM) += md5_sha1_sum.o
56COREUTILS-$(CONFIG_MKDIR) += mkdir.o 56COREUTILS-$(CONFIG_MKDIR) += mkdir.o
57COREUTILS-$(CONFIG_MKFIFO) += mkfifo.o 57COREUTILS-$(CONFIG_MKFIFO) += mkfifo.o
58COREUTILS-$(CONFIG_MKNOD) += mknod.o 58COREUTILS-$(CONFIG_MKNOD) += mknod.o
@@ -63,7 +63,7 @@ COREUTILS-$(CONFIG_PWD) += pwd.o
63COREUTILS-$(CONFIG_REALPATH) += realpath.o 63COREUTILS-$(CONFIG_REALPATH) += realpath.o
64COREUTILS-$(CONFIG_RM) += rm.o 64COREUTILS-$(CONFIG_RM) += rm.o
65COREUTILS-$(CONFIG_RMDIR) += rmdir.o 65COREUTILS-$(CONFIG_RMDIR) += rmdir.o
66COREUTILS-$(CONFIG_SHA1SUM) += sha1sum.o 66COREUTILS-$(CONFIG_SHA1SUM) += md5_sha1_sum.o
67COREUTILS-$(CONFIG_SLEEP) += sleep.o 67COREUTILS-$(CONFIG_SLEEP) += sleep.o
68COREUTILS-$(CONFIG_SORT) += sort.o 68COREUTILS-$(CONFIG_SORT) += sort.o
69COREUTILS-$(CONFIG_STTY) += stty.o 69COREUTILS-$(CONFIG_STTY) += stty.o
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c
new file mode 100644
index 000000000..f7c44c850
--- /dev/null
+++ b/coreutils/md5_sha1_sum.c
@@ -0,0 +1,195 @@
1/*
2 * Copyright (C) 2003 Glenn L. McGrath
3 * Copyright (C) 2003 Erik Andersen
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 of the License, or
8 * (at your option) 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
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <fcntl.h>
21#include <limits.h>
22#include <stdio.h>
23#include <stdint.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27
28#include "busybox.h"
29
30
31#define FLAG_SILENT 1
32#define FLAG_CHECK 2
33#define FLAG_WARN 4
34
35/* This might be usefull elsewhere */
36static unsigned char *hash_bin_to_hex(unsigned char *hash_value,
37 unsigned char hash_length)
38{
39 int x, len, max;
40 unsigned char *hex_value;
41
42 max = (hash_length * 2) + 2;
43 hex_value = xmalloc(max);
44 for (x = len = 0; x < hash_length; x++) {
45 len += snprintf(hex_value + len, max - len, "%02x", hash_value[x]);
46 }
47 return (hex_value);
48}
49
50static uint8_t *hash_file(const char *filename, uint8_t hash_algo)
51{
52 uint8_t *hash_value_bin;
53 uint8_t *hash_value = NULL;
54 uint8_t hash_length;
55 int src_fd;
56
57 if (strcmp(filename, "-") == 0) {
58 src_fd = fileno(stdin);
59 } else {
60 src_fd = open(filename, O_RDONLY);
61 }
62
63 if (hash_algo == HASH_MD5) {
64 hash_length = 16;
65 } else {
66 hash_length = 20;
67 }
68
69 hash_value_bin = xmalloc(hash_length);
70
71 if ((src_fd != -1) && (hash_fd(src_fd, -1, hash_algo, hash_value_bin) != -2)) {
72 hash_value = hash_bin_to_hex(hash_value_bin, hash_length);
73 } else {
74 bb_perror_msg("%s", filename);
75 }
76
77 close(src_fd);
78
79 return(hash_value);
80}
81
82/* This could become a common function for md5 as well, by using md5_stream */
83extern int hash_files(int argc, char **argv, const uint8_t hash_algo)
84{
85 uint8_t *hash_value;
86 unsigned int flags;
87 int return_value = EXIT_SUCCESS;
88
89#ifdef CONFIG_FEATURE_MD5_SHA1_SUM_CHECK
90 flags = bb_getopt_ulflags(argc, argv, "scw");
91#else
92 flags = bb_getopt_ulflags(argc, argv, "s");
93#endif
94
95#ifdef CONFIG_FEATURE_MD5_SHA1_SUM_CHECK
96 if (!(flags & FLAG_CHECK)) {
97 if (flags & FLAG_SILENT) {
98 bb_error_msg_and_die
99 ("the -s option is meaningful only when verifying checksums");
100 } else if (flags & FLAG_WARN) {
101 bb_error_msg_and_die
102 ("the -w option is meaningful only when verifying checksums");
103 }
104 }
105#endif
106
107 if (argc == optind) {
108 argv[argc++] = "-";
109 }
110#ifdef CONFIG_FEATURE_MD5_SHA1_SUM_CHECK
111 if (flags & FLAG_CHECK) {
112 FILE *pre_computed_stream;
113 int count_total = 0;
114 int count_failed = 0;
115 unsigned char *file_ptr = argv[optind];
116 char *line;
117
118 if (optind + 1 != argc) {
119 bb_error_msg_and_die
120 ("only one argument may be specified when using -c");
121 }
122
123 if (strcmp(file_ptr, "-") == 0) {
124 pre_computed_stream = stdin;
125 } else {
126 pre_computed_stream = bb_xfopen(file_ptr, "r");
127 }
128
129 while ((line = bb_get_chomped_line_from_file(pre_computed_stream)) != NULL) {
130 char *filename_ptr;
131
132 count_total++;
133 filename_ptr = strstr(line, " ");
134 if (filename_ptr == NULL) {
135 if (flags & FLAG_WARN) {
136 bb_error_msg("Invalid format");
137 }
138 free(line);
139 continue;
140 }
141 *filename_ptr = '\0';
142 filename_ptr += 2;
143
144 hash_value = hash_file(filename_ptr, hash_algo);
145
146 if (hash_value && (strcmp(hash_value, line) == 0)) {
147 printf("%s: OK\n", filename_ptr);
148 } else {
149 printf("%s: FAILED\n", filename_ptr);
150 count_failed++;
151 }
152 /* possible free(NULL) */
153 free(hash_value);
154 free(line);
155 }
156 if (count_failed) {
157 bb_error_msg("WARNING: %d of %d computed checksums did NOT match",
158 count_failed, count_total);
159 }
160 if (bb_fclose_nonstdin(pre_computed_stream) == EOF) {
161 bb_perror_msg_and_die("Couldnt close file %s", file_ptr);
162 }
163 } else
164#endif
165 while (optind < argc) {
166 unsigned char *file_ptr = argv[optind];
167
168 optind++;
169
170 hash_value = hash_file(file_ptr, hash_algo);
171 if (hash_value == NULL) {
172 return_value++;
173 }
174 else if (!flags & FLAG_SILENT) {
175 printf("%s %s\n", hash_value, file_ptr);
176 free(hash_value);
177 }
178 }
179
180 return (return_value);
181}
182
183#ifdef CONFIG_MD5SUM
184extern int md5sum_main(int argc, char **argv)
185{
186 return(hash_files(argc, argv, HASH_MD5));
187}
188#endif
189
190#ifdef CONFIG_SHA1SUM
191extern int sha1sum_main(int argc, char **argv)
192{
193 return(hash_files(argc, argv, HASH_SHA1));
194}
195#endif
diff --git a/include/libbb.h b/include/libbb.h
index 945dc95bc..21ea31690 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -473,4 +473,10 @@ extern void vfork_daemon_rexec(int argc, char **argv, char *foreground_opt);
473extern void get_terminal_width_height(int fd, int *width, int *height); 473extern void get_terminal_width_height(int fd, int *width, int *height);
474extern unsigned long get_ug_id(const char *s, long (*my_getxxnam)(const char *)); 474extern unsigned long get_ug_id(const char *s, long (*my_getxxnam)(const char *));
475extern void xregcomp(regex_t *preg, const char *regex, int cflags); 475extern void xregcomp(regex_t *preg, const char *regex, int cflags);
476
477#define HASH_SHA1 1
478#define HASH_MD5 2
479extern int hash_fd(int fd, const off_t size, const uint8_t hash_algo, uint8_t *hashval);
480
481
476#endif /* __LIBCONFIG_H__ */ 482#endif /* __LIBCONFIG_H__ */
diff --git a/libbb/Makefile.in b/libbb/Makefile.in
index bb98965c0..979419b62 100644
--- a/libbb/Makefile.in
+++ b/libbb/Makefile.in
@@ -30,7 +30,7 @@ LIBBB_SRC:= \
30 device_open.c dump.c error_msg.c error_msg_and_die.c find_mount_point.c \ 30 device_open.c dump.c error_msg.c error_msg_and_die.c find_mount_point.c \
31 find_pid_by_name.c find_root_device.c fgets_str.c full_read.c \ 31 find_pid_by_name.c find_root_device.c fgets_str.c full_read.c \
32 full_write.c get_last_path_component.c get_line_from_file.c get_ug_id.c \ 32 full_write.c get_last_path_component.c get_line_from_file.c get_ug_id.c \
33 get_terminal_width_height.c herror_msg.c herror_msg_and_die.c \ 33 get_terminal_width_height.c hash_fd.c herror_msg.c herror_msg_and_die.c \
34 human_readable.c inet_common.c inode_hash.c interface.c isdirectory.c \ 34 human_readable.c inet_common.c inode_hash.c interface.c isdirectory.c \
35 kernel_version.c last_char_is.c llist_add_to.c login.c loop.c \ 35 kernel_version.c last_char_is.c llist_add_to.c login.c loop.c \
36 make_directory.c mode_string.c module_syscalls.c mtab.c mtab_file.c \ 36 make_directory.c mode_string.c module_syscalls.c mtab.c mtab_file.c \
diff --git a/libbb/hash_fd.c b/libbb/hash_fd.c
new file mode 100644
index 000000000..b95c1369b
--- /dev/null
+++ b/libbb/hash_fd.c
@@ -0,0 +1,848 @@
1/*
2 * Based on shasum from http://www.netsw.org/crypto/hash/
3 * Majorly hacked up to use Dr Brian Gladman's sha1 code
4 *
5 * Copyright (C) 2003 Glenn L. McGrath
6 * Copyright (C) 2003 Erik Andersen
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <byteswap.h>
24#include <endian.h>
25#include <fcntl.h>
26#include <limits.h>
27#include <stdio.h>
28#include <stdint.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32
33#include "busybox.h"
34
35
36#ifdef CONFIG_SHA1SUM
37/*
38 ---------------------------------------------------------------------------
39 Begin Dr. Gladman's sha1 code
40 ---------------------------------------------------------------------------
41*/
42
43/*
44 ---------------------------------------------------------------------------
45 Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
46 All rights reserved.
47
48 LICENSE TERMS
49
50 The free distribution and use of this software in both source and binary
51 form is allowed (with or without changes) provided that:
52
53 1. distributions of this source code include the above copyright
54 notice, this list of conditions and the following disclaimer;
55
56 2. distributions in binary form include the above copyright
57 notice, this list of conditions and the following disclaimer
58 in the documentation and/or other associated materials;
59
60 3. the copyright holder's name is not used to endorse products
61 built using this software without specific written permission.
62
63 ALTERNATIVELY, provided that this notice is retained in full, this product
64 may be distributed under the terms of the GNU General Public License (GPL),
65 in which case the provisions of the GPL apply INSTEAD OF those given above.
66
67 DISCLAIMER
68
69 This software is provided 'as is' with no explicit or implied warranties
70 in respect of its properties, including, but not limited to, correctness
71 and/or fitness for purpose.
72 ---------------------------------------------------------------------------
73 Issue Date: 10/11/2002
74
75 This is a byte oriented version of SHA1 that operates on arrays of bytes
76 stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
77*/
78
79# define SHA1_BLOCK_SIZE 64
80# define SHA1_DIGEST_SIZE 20
81# define SHA1_HASH_SIZE SHA1_DIGEST_SIZE
82# define SHA2_GOOD 0
83# define SHA2_BAD 1
84
85# define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
86
87# if __BYTE_ORDER == __BIG_ENDIAN
88# define swap_b32(x) (x)
89# elif defined(bswap_32)
90# define swap_b32(x) bswap_32(x)
91# else
92# define swap_b32(x) ((rotl32((x), 8) & 0x00ff00ff) | (rotl32((x), 24) & 0xff00ff00))
93# endif /* __BYTE_ORDER */
94
95# define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
96
97/* reverse byte order in 32-bit words */
98# define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
99# define parity(x,y,z) ((x) ^ (y) ^ (z))
100# define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
101
102/* A normal version as set out in the FIPS. This version uses */
103/* partial loop unrolling and is optimised for the Pentium 4 */
104# define rnd(f,k) \
105 t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \
106 e = d; d = c; c = rotl32(b, 30); b = t
107
108/* type to hold the SHA1 context */
109typedef struct {
110 uint32_t count[2];
111 uint32_t hash[5];
112 uint32_t wbuf[16];
113} sha1_ctx;
114
115static void sha1_compile(sha1_ctx ctx[1])
116{
117 uint32_t w[80], i, a, b, c, d, e, t;
118
119 /* note that words are compiled from the buffer into 32-bit */
120 /* words in big-endian order so an order reversal is needed */
121 /* here on little endian machines */
122 for (i = 0; i < SHA1_BLOCK_SIZE / 4; ++i)
123 w[i] = swap_b32(ctx->wbuf[i]);
124
125 for (i = SHA1_BLOCK_SIZE / 4; i < 80; ++i)
126 w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
127
128 a = ctx->hash[0];
129 b = ctx->hash[1];
130 c = ctx->hash[2];
131 d = ctx->hash[3];
132 e = ctx->hash[4];
133
134 for (i = 0; i < 20; ++i) {
135 rnd(ch, 0x5a827999);
136 }
137
138 for (i = 20; i < 40; ++i) {
139 rnd(parity, 0x6ed9eba1);
140 }
141
142 for (i = 40; i < 60; ++i) {
143 rnd(maj, 0x8f1bbcdc);
144 }
145
146 for (i = 60; i < 80; ++i) {
147 rnd(parity, 0xca62c1d6);
148 }
149
150 ctx->hash[0] += a;
151 ctx->hash[1] += b;
152 ctx->hash[2] += c;
153 ctx->hash[3] += d;
154 ctx->hash[4] += e;
155}
156
157static void sha1_begin(sha1_ctx ctx[1])
158{
159 ctx->count[0] = ctx->count[1] = 0;
160 ctx->hash[0] = 0x67452301;
161 ctx->hash[1] = 0xefcdab89;
162 ctx->hash[2] = 0x98badcfe;
163 ctx->hash[3] = 0x10325476;
164 ctx->hash[4] = 0xc3d2e1f0;
165}
166
167/* SHA1 hash data in an array of bytes into hash buffer and call the */
168/* hash_compile function as required. */
169static void sha1_hash(const unsigned char data[], unsigned int len, sha1_ctx ctx[1])
170{
171 uint32_t pos = (uint32_t) (ctx->count[0] & SHA1_MASK),
172 freeb = SHA1_BLOCK_SIZE - pos;
173 const unsigned char *sp = data;
174
175 if ((ctx->count[0] += len) < len)
176 ++(ctx->count[1]);
177
178 while (len >= freeb) { /* tranfer whole blocks while possible */
179 memcpy(((unsigned char *) ctx->wbuf) + pos, sp, freeb);
180 sp += freeb;
181 len -= freeb;
182 freeb = SHA1_BLOCK_SIZE;
183 pos = 0;
184 sha1_compile(ctx);
185 }
186
187 memcpy(((unsigned char *) ctx->wbuf) + pos, sp, len);
188}
189
190/* SHA1 Final padding and digest calculation */
191# if __BYTE_ORDER == __LITTLE_ENDIAN
192static uint32_t mask[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff };
193static uint32_t bits[4] = { 0x00000080, 0x00008000, 0x00800000, 0x80000000 };
194# else
195static uint32_t mask[4] = { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 };
196static uint32_t bits[4] = { 0x80000000, 0x00800000, 0x00008000, 0x00000080 };
197# endif /* __BYTE_ORDER */
198
199void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
200{
201 uint32_t i, cnt = (uint32_t) (ctx->count[0] & SHA1_MASK);
202
203 /* mask out the rest of any partial 32-bit word and then set */
204 /* the next byte to 0x80. On big-endian machines any bytes in */
205 /* the buffer will be at the top end of 32 bit words, on little */
206 /* endian machines they will be at the bottom. Hence the AND */
207 /* and OR masks above are reversed for little endian systems */
208 ctx->wbuf[cnt >> 2] =
209 (ctx->wbuf[cnt >> 2] & mask[cnt & 3]) | bits[cnt & 3];
210
211 /* we need 9 or more empty positions, one for the padding byte */
212 /* (above) and eight for the length count. If there is not */
213 /* enough space pad and empty the buffer */
214 if (cnt > SHA1_BLOCK_SIZE - 9) {
215 if (cnt < 60)
216 ctx->wbuf[15] = 0;
217 sha1_compile(ctx);
218 cnt = 0;
219 } else /* compute a word index for the empty buffer positions */
220 cnt = (cnt >> 2) + 1;
221
222 while (cnt < 14) /* and zero pad all but last two positions */
223 ctx->wbuf[cnt++] = 0;
224
225 /* assemble the eight byte counter in the buffer in big-endian */
226 /* format */
227
228 ctx->wbuf[14] = swap_b32((ctx->count[1] << 3) | (ctx->count[0] >> 29));
229 ctx->wbuf[15] = swap_b32(ctx->count[0] << 3);
230
231 sha1_compile(ctx);
232
233 /* extract the hash value as bytes in case the hash buffer is */
234 /* misaligned for 32-bit words */
235
236 for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
237 hval[i] = (unsigned char) (ctx->hash[i >> 2] >> 8 * (~i & 3));
238}
239
240/*
241 ---------------------------------------------------------------------------
242 End of Dr. Gladman's sha1 code
243 ---------------------------------------------------------------------------
244*/
245#endif /* CONFIG_SHA1 */
246
247
248
249
250
251#ifdef CONFIG_MD5SUM
252/*
253 * md5sum.c - Compute MD5 checksum of files or strings according to the
254 * definition of MD5 in RFC 1321 from April 1992.
255 *
256 * Copyright (C) 1995-1999 Free Software Foundation, Inc.
257 * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
258 *
259 *
260 * June 29, 2001 Manuel Novoa III
261 *
262 * Added MD5SUM_SIZE_VS_SPEED configuration option.
263 *
264 * Current valid values, with data from my system for comparison, are:
265 * (using uClibc and running on linux-2.4.4.tar.bz2)
266 * user times (sec) text size (386)
267 * 0 (fastest) 1.1 6144
268 * 1 1.4 5392
269 * 2 3.0 5088
270 * 3 (smallest) 5.1 4912
271 */
272
273# define MD5SUM_SIZE_VS_SPEED 2
274
275/* Handle endian-ness */
276# if __BYTE_ORDER == __LITTLE_ENDIAN
277# define SWAP(n) (n)
278# else
279# define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24))
280# endif
281
282# if MD5SUM_SIZE_VS_SPEED == 0
283/* This array contains the bytes used to pad the buffer to the next
284 64-byte boundary. (RFC 1321, 3.1: Step 1) */
285static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
286# endif /* MD5SUM_SIZE_VS_SPEED == 0 */
287
288typedef u_int32_t md5_uint32;
289
290/* Structure to save state of computation between the single steps. */
291struct md5_ctx {
292 md5_uint32 A;
293 md5_uint32 B;
294 md5_uint32 C;
295 md5_uint32 D;
296
297 md5_uint32 total[2];
298 md5_uint32 buflen;
299 char buffer[128];
300};
301
302/* Initialize structure containing state of computation.
303 * (RFC 1321, 3.3: Step 3)
304 */
305static void md5_begin(struct md5_ctx *ctx)
306{
307 ctx->A = 0x67452301;
308 ctx->B = 0xefcdab89;
309 ctx->C = 0x98badcfe;
310 ctx->D = 0x10325476;
311
312 ctx->total[0] = ctx->total[1] = 0;
313 ctx->buflen = 0;
314}
315
316/* These are the four functions used in the four steps of the MD5 algorithm
317 * and defined in the RFC 1321. The first function is a little bit optimized
318 * (as found in Colin Plumbs public domain implementation).
319 * #define FF(b, c, d) ((b & c) | (~b & d))
320 */
321# define FF(b, c, d) (d ^ (b & (c ^ d)))
322# define FG(b, c, d) FF (d, b, c)
323# define FH(b, c, d) (b ^ c ^ d)
324# define FI(b, c, d) (c ^ (b | ~d))
325
326/* Starting with the result of former calls of this function (or the
327 * initialization function update the context for the next LEN bytes
328 * starting at BUFFER.
329 * It is necessary that LEN is a multiple of 64!!!
330 */
331static void md5_hash_block(const void *buffer, size_t len,
332 struct md5_ctx *ctx)
333{
334 md5_uint32 correct_words[16];
335 const md5_uint32 *words = buffer;
336 size_t nwords = len / sizeof(md5_uint32);
337 const md5_uint32 *endp = words + nwords;
338
339# if MD5SUM_SIZE_VS_SPEED > 0
340 static const md5_uint32 C_array[] = {
341 /* round 1 */
342 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
343 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
344 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
345 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
346 /* round 2 */
347 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
348 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
349 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
350 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
351 /* round 3 */
352 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
353 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
354 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
355 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
356 /* round 4 */
357 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
358 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
359 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
360 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
361 };
362
363 static const char P_array[] = {
364# if MD5SUM_SIZE_VS_SPEED > 1
365 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
366# endif /* MD5SUM_SIZE_VS_SPEED > 1 */
367 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
368 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
369 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
370 };
371
372# if MD5SUM_SIZE_VS_SPEED > 1
373 static const char S_array[] = {
374 7, 12, 17, 22,
375 5, 9, 14, 20,
376 4, 11, 16, 23,
377 6, 10, 15, 21
378 };
379# endif /* MD5SUM_SIZE_VS_SPEED > 1 */
380# endif
381
382 md5_uint32 A = ctx->A;
383 md5_uint32 B = ctx->B;
384 md5_uint32 C = ctx->C;
385 md5_uint32 D = ctx->D;
386
387 /* First increment the byte count. RFC 1321 specifies the possible
388 length of the file up to 2^64 bits. Here we only compute the
389 number of bytes. Do a double word increment. */
390 ctx->total[0] += len;
391 if (ctx->total[0] < len)
392 ++ctx->total[1];
393
394 /* Process all bytes in the buffer with 64 bytes in each round of
395 the loop. */
396 while (words < endp) {
397 md5_uint32 *cwp = correct_words;
398 md5_uint32 A_save = A;
399 md5_uint32 B_save = B;
400 md5_uint32 C_save = C;
401 md5_uint32 D_save = D;
402
403# if MD5SUM_SIZE_VS_SPEED > 1
404# define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
405
406 const md5_uint32 *pc;
407 const char *pp;
408 const char *ps;
409 int i;
410 md5_uint32 temp;
411
412 for (i = 0; i < 16; i++) {
413 cwp[i] = SWAP(words[i]);
414 }
415 words += 16;
416
417# if MD5SUM_SIZE_VS_SPEED > 2
418 pc = C_array;
419 pp = P_array;
420 ps = S_array - 4;
421
422 for (i = 0; i < 64; i++) {
423 if ((i & 0x0f) == 0)
424 ps += 4;
425 temp = A;
426 switch (i >> 4) {
427 case 0:
428 temp += FF(B, C, D);
429 break;
430 case 1:
431 temp += FG(B, C, D);
432 break;
433 case 2:
434 temp += FH(B, C, D);
435 break;
436 case 3:
437 temp += FI(B, C, D);
438 }
439 temp += cwp[(int) (*pp++)] + *pc++;
440 CYCLIC(temp, ps[i & 3]);
441 temp += B;
442 A = D;
443 D = C;
444 C = B;
445 B = temp;
446 }
447# else
448 pc = C_array;
449 pp = P_array;
450 ps = S_array;
451
452 for (i = 0; i < 16; i++) {
453 temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++;
454 CYCLIC(temp, ps[i & 3]);
455 temp += B;
456 A = D;
457 D = C;
458 C = B;
459 B = temp;
460 }
461
462 ps += 4;
463 for (i = 0; i < 16; i++) {
464 temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++;
465 CYCLIC(temp, ps[i & 3]);
466 temp += B;
467 A = D;
468 D = C;
469 C = B;
470 B = temp;
471 }
472 ps += 4;
473 for (i = 0; i < 16; i++) {
474 temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++;
475 CYCLIC(temp, ps[i & 3]);
476 temp += B;
477 A = D;
478 D = C;
479 C = B;
480 B = temp;
481 }
482 ps += 4;
483 for (i = 0; i < 16; i++) {
484 temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++;
485 CYCLIC(temp, ps[i & 3]);
486 temp += B;
487 A = D;
488 D = C;
489 C = B;
490 B = temp;
491 }
492
493# endif /* MD5SUM_SIZE_VS_SPEED > 2 */
494# else
495 /* First round: using the given function, the context and a constant
496 the next context is computed. Because the algorithms processing
497 unit is a 32-bit word and it is determined to work on words in
498 little endian byte order we perhaps have to change the byte order
499 before the computation. To reduce the work for the next steps
500 we store the swapped words in the array CORRECT_WORDS. */
501
502# define OP(a, b, c, d, s, T) \
503 do \
504 { \
505 a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
506 ++words; \
507 CYCLIC (a, s); \
508 a += b; \
509 } \
510 while (0)
511
512 /* It is unfortunate that C does not provide an operator for
513 cyclic rotation. Hope the C compiler is smart enough. */
514 /* gcc 2.95.4 seems to be --aaronl */
515# define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
516
517 /* Before we start, one word to the strange constants.
518 They are defined in RFC 1321 as
519
520 T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
521 */
522
523# if MD5SUM_SIZE_VS_SPEED == 1
524 const md5_uint32 *pc;
525 const char *pp;
526 int i;
527# endif /* MD5SUM_SIZE_VS_SPEED */
528
529 /* Round 1. */
530# if MD5SUM_SIZE_VS_SPEED == 1
531 pc = C_array;
532 for (i = 0; i < 4; i++) {
533 OP(A, B, C, D, 7, *pc++);
534 OP(D, A, B, C, 12, *pc++);
535 OP(C, D, A, B, 17, *pc++);
536 OP(B, C, D, A, 22, *pc++);
537 }
538# else
539 OP(A, B, C, D, 7, 0xd76aa478);
540 OP(D, A, B, C, 12, 0xe8c7b756);
541 OP(C, D, A, B, 17, 0x242070db);
542 OP(B, C, D, A, 22, 0xc1bdceee);
543 OP(A, B, C, D, 7, 0xf57c0faf);
544 OP(D, A, B, C, 12, 0x4787c62a);
545 OP(C, D, A, B, 17, 0xa8304613);
546 OP(B, C, D, A, 22, 0xfd469501);
547 OP(A, B, C, D, 7, 0x698098d8);
548 OP(D, A, B, C, 12, 0x8b44f7af);
549 OP(C, D, A, B, 17, 0xffff5bb1);
550 OP(B, C, D, A, 22, 0x895cd7be);
551 OP(A, B, C, D, 7, 0x6b901122);
552 OP(D, A, B, C, 12, 0xfd987193);
553 OP(C, D, A, B, 17, 0xa679438e);
554 OP(B, C, D, A, 22, 0x49b40821);
555# endif /* MD5SUM_SIZE_VS_SPEED == 1 */
556
557 /* For the second to fourth round we have the possibly swapped words
558 in CORRECT_WORDS. Redefine the macro to take an additional first
559 argument specifying the function to use. */
560# undef OP
561# define OP(f, a, b, c, d, k, s, T) \
562 do \
563 { \
564 a += f (b, c, d) + correct_words[k] + T; \
565 CYCLIC (a, s); \
566 a += b; \
567 } \
568 while (0)
569
570 /* Round 2. */
571# if MD5SUM_SIZE_VS_SPEED == 1
572 pp = P_array;
573 for (i = 0; i < 4; i++) {
574 OP(FG, A, B, C, D, (int) (*pp++), 5, *pc++);
575 OP(FG, D, A, B, C, (int) (*pp++), 9, *pc++);
576 OP(FG, C, D, A, B, (int) (*pp++), 14, *pc++);
577 OP(FG, B, C, D, A, (int) (*pp++), 20, *pc++);
578 }
579# else
580 OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
581 OP(FG, D, A, B, C, 6, 9, 0xc040b340);
582 OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
583 OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
584 OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
585 OP(FG, D, A, B, C, 10, 9, 0x02441453);
586 OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
587 OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
588 OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
589 OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
590 OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
591 OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
592 OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
593 OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
594 OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
595 OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
596# endif /* MD5SUM_SIZE_VS_SPEED == 1 */
597
598 /* Round 3. */
599# if MD5SUM_SIZE_VS_SPEED == 1
600 for (i = 0; i < 4; i++) {
601 OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++);
602 OP(FH, D, A, B, C, (int) (*pp++), 11, *pc++);
603 OP(FH, C, D, A, B, (int) (*pp++), 16, *pc++);
604 OP(FH, B, C, D, A, (int) (*pp++), 23, *pc++);
605 }
606# else
607 OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
608 OP(FH, D, A, B, C, 8, 11, 0x8771f681);
609 OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
610 OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
611 OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
612 OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
613 OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
614 OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
615 OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
616 OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
617 OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
618 OP(FH, B, C, D, A, 6, 23, 0x04881d05);
619 OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
620 OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
621 OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
622 OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
623# endif /* MD5SUM_SIZE_VS_SPEED == 1 */
624
625 /* Round 4. */
626# if MD5SUM_SIZE_VS_SPEED == 1
627 for (i = 0; i < 4; i++) {
628 OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++);
629 OP(FI, D, A, B, C, (int) (*pp++), 10, *pc++);
630 OP(FI, C, D, A, B, (int) (*pp++), 15, *pc++);
631 OP(FI, B, C, D, A, (int) (*pp++), 21, *pc++);
632 }
633# else
634 OP(FI, A, B, C, D, 0, 6, 0xf4292244);
635 OP(FI, D, A, B, C, 7, 10, 0x432aff97);
636 OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
637 OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
638 OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
639 OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
640 OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
641 OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
642 OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
643 OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
644 OP(FI, C, D, A, B, 6, 15, 0xa3014314);
645 OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
646 OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
647 OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
648 OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
649 OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
650# endif /* MD5SUM_SIZE_VS_SPEED == 1 */
651# endif /* MD5SUM_SIZE_VS_SPEED > 1 */
652
653 /* Add the starting values of the context. */
654 A += A_save;
655 B += B_save;
656 C += C_save;
657 D += D_save;
658 }
659
660 /* Put checksum in context given as argument. */
661 ctx->A = A;
662 ctx->B = B;
663 ctx->C = C;
664 ctx->D = D;
665}
666
667/* Starting with the result of former calls of this function (or the
668 * initialization function update the context for the next LEN bytes
669 * starting at BUFFER.
670 * It is NOT required that LEN is a multiple of 64.
671 */
672
673static void md5_hash_bytes(const void *buffer, size_t len,
674 struct md5_ctx *ctx)
675{
676 /* When we already have some bits in our internal buffer concatenate
677 both inputs first. */
678 if (ctx->buflen != 0) {
679 size_t left_over = ctx->buflen;
680 size_t add = 128 - left_over > len ? len : 128 - left_over;
681
682 memcpy(&ctx->buffer[left_over], buffer, add);
683 ctx->buflen += add;
684
685 if (left_over + add > 64) {
686 md5_hash_block(ctx->buffer, (left_over + add) & ~63, ctx);
687 /* The regions in the following copy operation cannot overlap. */
688 memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
689 (left_over + add) & 63);
690 ctx->buflen = (left_over + add) & 63;
691 }
692
693 buffer = (const char *) buffer + add;
694 len -= add;
695 }
696
697 /* Process available complete blocks. */
698 if (len > 64) {
699 md5_hash_block(buffer, len & ~63, ctx);
700 buffer = (const char *) buffer + (len & ~63);
701 len &= 63;
702 }
703
704 /* Move remaining bytes in internal buffer. */
705 if (len > 0) {
706 memcpy(ctx->buffer, buffer, len);
707 ctx->buflen = len;
708 }
709}
710
711/* Process the remaining bytes in the buffer and put result from CTX
712 * in first 16 bytes following RESBUF. The result is always in little
713 * endian byte order, so that a byte-wise output yields to the wanted
714 * ASCII representation of the message digest.
715 *
716 * IMPORTANT: On some systems it is required that RESBUF is correctly
717 * aligned for a 32 bits value.
718 */
719static void *md5_end(void *resbuf, struct md5_ctx *ctx)
720{
721 /* Take yet unprocessed bytes into account. */
722 md5_uint32 bytes = ctx->buflen;
723 size_t pad;
724
725 /* Now count remaining bytes. */
726 ctx->total[0] += bytes;
727 if (ctx->total[0] < bytes)
728 ++ctx->total[1];
729
730 pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
731# if MD5SUM_SIZE_VS_SPEED > 0
732 memset(&ctx->buffer[bytes], 0, pad);
733 ctx->buffer[bytes] = 0x80;
734# else
735 memcpy(&ctx->buffer[bytes], fillbuf, pad);
736# endif /* MD5SUM_SIZE_VS_SPEED > 0 */
737
738 /* Put the 64-bit file length in *bits* at the end of the buffer. */
739 *(md5_uint32 *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3);
740 *(md5_uint32 *) & ctx->buffer[bytes + pad + 4] =
741 SWAP(((ctx->total[1] << 3) | (ctx->total[0] >> 29)));
742
743 /* Process last bytes. */
744 md5_hash_block(ctx->buffer, bytes + pad + 8, ctx);
745
746 /* Put result from CTX in first 16 bytes following RESBUF. The result is
747 * always in little endian byte order, so that a byte-wise output yields
748 * to the wanted ASCII representation of the message digest.
749 *
750 * IMPORTANT: On some systems it is required that RESBUF is correctly
751 * aligned for a 32 bits value.
752 */
753 ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A);
754 ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B);
755 ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C);
756 ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D);
757
758 return resbuf;
759}
760#endif /* CONFIG_MD5SUM */
761
762
763
764
765extern int hash_fd(int src_fd, const off_t size, const uint8_t hash_algo,
766 uint8_t * hashval)
767{
768 int result = EXIT_SUCCESS;
769 off_t hashed_count = 0;
770 unsigned int blocksize = 0;
771 unsigned char *buffer = NULL;
772#ifdef CONFIG_SHA1SUM
773 sha1_ctx sha1_cx[1];
774#endif
775#ifdef CONFIG_MD5SUM
776 struct md5_ctx md5_cx;
777#endif
778
779
780#ifdef CONFIG_SHA1SUM
781 if (hash_algo == HASH_SHA1) {
782 /* Ensure that BLOCKSIZE is a multiple of 64. */
783 blocksize = 65536;
784 buffer = malloc(blocksize);
785 }
786#endif
787#ifdef CONFIG_MD5SUM
788 if (hash_algo == HASH_MD5) {
789 blocksize = 4096;
790 buffer = malloc(blocksize + 72);
791 }
792#endif
793
794 /* Initialize the computation context. */
795#ifdef CONFIG_SHA1SUM
796 if (hash_algo == HASH_SHA1) {
797 sha1_begin(sha1_cx);
798 }
799#endif
800#ifdef CONFIG_MD5SUM
801 if (hash_algo == HASH_MD5) {
802 md5_begin(&md5_cx);
803 }
804#endif
805 /* Iterate over full file contents. */
806 do {
807 const ssize_t count = bb_full_read(src_fd, buffer, blocksize);
808
809 if (count < 1) {
810 /* count == 0 means short read
811 * count == -1 means read error */
812 result = count - 1;
813 break;
814 }
815 hashed_count += count;
816
817 /* Process buffer */
818#ifdef CONFIG_SHA1SUM
819 if (hash_algo == HASH_SHA1) {
820 sha1_hash(buffer, count, sha1_cx);
821 }
822#endif
823#ifdef CONFIG_MD5SUM
824 if (hash_algo == HASH_MD5) {
825 if (count % 64 == 0) {
826 md5_hash_block(buffer, count, &md5_cx);
827 } else {
828 md5_hash_bytes(buffer, count, &md5_cx);
829 }
830 }
831#endif
832 } while ((size == (off_t) - 1) || (hashed_count < size));
833
834 /* Finalize and write the hash into our buffer. */
835#ifdef CONFIG_SHA1SUM
836 if (hash_algo == HASH_SHA1) {
837 sha1_end(hashval, sha1_cx);
838 }
839#endif
840#ifdef CONFIG_MD5SUM
841 if (hash_algo == HASH_MD5) {
842 md5_end(hashval, &md5_cx);
843 }
844#endif
845
846 free(buffer);
847 return result;
848}