diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2003-11-10 04:33:55 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2003-11-10 04:33:55 +0000 |
commit | d2a897aab084b433231aab5f6908a79cba67dc5d (patch) | |
tree | 8a0b113bd44bc2be639e070b50668e4ad69091f2 | |
parent | 0bdf41ad7e81451bc829365e0d9a676dda8145f9 (diff) | |
download | busybox-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.in | 19 | ||||
-rw-r--r-- | coreutils/Makefile.in | 4 | ||||
-rw-r--r-- | coreutils/md5_sha1_sum.c | 195 | ||||
-rw-r--r-- | include/libbb.h | 6 | ||||
-rw-r--r-- | libbb/Makefile.in | 2 | ||||
-rw-r--r-- | libbb/hash_fd.c | 848 |
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 | ||
376 | config 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 | |||
384 | config CONFIG_SLEEP | 376 | config 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 | ||
586 | comment "Common options for md5sum, sha1sum" | ||
587 | depends on CONFIG_MD5SUM || CONFIG_SHA1SUM | ||
588 | |||
589 | config 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 | |||
594 | endmenu | 597 | endmenu |
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 | |||
52 | COREUTILS-$(CONFIG_LN) += ln.o | 52 | COREUTILS-$(CONFIG_LN) += ln.o |
53 | COREUTILS-$(CONFIG_LOGNAME) += logname.o | 53 | COREUTILS-$(CONFIG_LOGNAME) += logname.o |
54 | COREUTILS-$(CONFIG_LS) += ls.o | 54 | COREUTILS-$(CONFIG_LS) += ls.o |
55 | COREUTILS-$(CONFIG_MD5SUM) += md5sum.o | 55 | COREUTILS-$(CONFIG_MD5SUM) += md5_sha1_sum.o |
56 | COREUTILS-$(CONFIG_MKDIR) += mkdir.o | 56 | COREUTILS-$(CONFIG_MKDIR) += mkdir.o |
57 | COREUTILS-$(CONFIG_MKFIFO) += mkfifo.o | 57 | COREUTILS-$(CONFIG_MKFIFO) += mkfifo.o |
58 | COREUTILS-$(CONFIG_MKNOD) += mknod.o | 58 | COREUTILS-$(CONFIG_MKNOD) += mknod.o |
@@ -63,7 +63,7 @@ COREUTILS-$(CONFIG_PWD) += pwd.o | |||
63 | COREUTILS-$(CONFIG_REALPATH) += realpath.o | 63 | COREUTILS-$(CONFIG_REALPATH) += realpath.o |
64 | COREUTILS-$(CONFIG_RM) += rm.o | 64 | COREUTILS-$(CONFIG_RM) += rm.o |
65 | COREUTILS-$(CONFIG_RMDIR) += rmdir.o | 65 | COREUTILS-$(CONFIG_RMDIR) += rmdir.o |
66 | COREUTILS-$(CONFIG_SHA1SUM) += sha1sum.o | 66 | COREUTILS-$(CONFIG_SHA1SUM) += md5_sha1_sum.o |
67 | COREUTILS-$(CONFIG_SLEEP) += sleep.o | 67 | COREUTILS-$(CONFIG_SLEEP) += sleep.o |
68 | COREUTILS-$(CONFIG_SORT) += sort.o | 68 | COREUTILS-$(CONFIG_SORT) += sort.o |
69 | COREUTILS-$(CONFIG_STTY) += stty.o | 69 | COREUTILS-$(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 */ | ||
36 | static 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 | |||
50 | static 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 */ | ||
83 | extern 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 | ||
184 | extern int md5sum_main(int argc, char **argv) | ||
185 | { | ||
186 | return(hash_files(argc, argv, HASH_MD5)); | ||
187 | } | ||
188 | #endif | ||
189 | |||
190 | #ifdef CONFIG_SHA1SUM | ||
191 | extern 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); | |||
473 | extern void get_terminal_width_height(int fd, int *width, int *height); | 473 | extern void get_terminal_width_height(int fd, int *width, int *height); |
474 | extern unsigned long get_ug_id(const char *s, long (*my_getxxnam)(const char *)); | 474 | extern unsigned long get_ug_id(const char *s, long (*my_getxxnam)(const char *)); |
475 | extern void xregcomp(regex_t *preg, const char *regex, int cflags); | 475 | extern void xregcomp(regex_t *preg, const char *regex, int cflags); |
476 | |||
477 | #define HASH_SHA1 1 | ||
478 | #define HASH_MD5 2 | ||
479 | extern 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 */ | ||
109 | typedef struct { | ||
110 | uint32_t count[2]; | ||
111 | uint32_t hash[5]; | ||
112 | uint32_t wbuf[16]; | ||
113 | } sha1_ctx; | ||
114 | |||
115 | static 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 | |||
157 | static 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. */ | ||
169 | static 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 | ||
192 | static uint32_t mask[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; | ||
193 | static uint32_t bits[4] = { 0x00000080, 0x00008000, 0x00800000, 0x80000000 }; | ||
194 | # else | ||
195 | static uint32_t mask[4] = { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 }; | ||
196 | static uint32_t bits[4] = { 0x80000000, 0x00800000, 0x00008000, 0x00000080 }; | ||
197 | # endif /* __BYTE_ORDER */ | ||
198 | |||
199 | void 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) */ | ||
285 | static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; | ||
286 | # endif /* MD5SUM_SIZE_VS_SPEED == 0 */ | ||
287 | |||
288 | typedef u_int32_t md5_uint32; | ||
289 | |||
290 | /* Structure to save state of computation between the single steps. */ | ||
291 | struct 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 | */ | ||
305 | static 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 | */ | ||
331 | static 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 | |||
673 | static 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 | */ | ||
719 | static 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 | |||
765 | extern 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 | } | ||