1 /* md5sum.c - Calculate RFC 1321 md5 hash and sha1 hash.
2 *
3 * Copyright 2012 Rob Landley <rob@landley.net>
4 *
5 * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/md5sum.html
6 * and http://www.ietf.org/rfc/rfc1321.txt
7 *
8 * They're combined this way to share infrastructure, and because md5sum is
9 * and LSB standard command (but sha1sum and newer hashes are a good idea,
10 * see http://valerieaurora.org/hash.html).
11 *
12 * We optionally use openssl (or equivalent) to access assembly optimized
13 * versions of these functions, but provide a built-in version to reduce
14 * required dependencies.
15 *
16 * coreutils supports --status but not -s, busybox supports -s but not --status
17
18 USE_MD5SUM(NEWTOY(md5sum, "bc(check)s(status)[!bc]", TOYFLAG_USR|TOYFLAG_BIN))
19 USE_SHA1SUM(NEWTOY(sha1sum, "bc(check)s(status)[!bc]", TOYFLAG_USR|TOYFLAG_BIN))
20 USE_TOYBOX_LIBCRYPTO(USE_SHA224SUM(OLDTOY(sha224sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN)))
21 USE_TOYBOX_LIBCRYPTO(USE_SHA256SUM(OLDTOY(sha256sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN)))
22 USE_TOYBOX_LIBCRYPTO(USE_SHA384SUM(OLDTOY(sha384sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN)))
23 USE_TOYBOX_LIBCRYPTO(USE_SHA512SUM(OLDTOY(sha512sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN)))
24
25 config MD5SUM
26 bool "md5sum"
27 default y
28 help
29 usage: md5sum [-bcs] [FILE]...
30
31 Calculate md5 hash for each input file, reading from stdin if none.
32 Output one hash (32 hex digits) for each input file, followed by filename.
33
34 -b Brief (hash only, no filename)
35 -c Check each line of each FILE is the same hash+filename we'd output
36 -s No output, exit status 0 if all hashes match, 1 otherwise
37
38 config SHA1SUM
39 bool "sha1sum"
40 default y
41 help
42 usage: sha?sum [-bcs] [FILE]...
43
44 Calculate sha hash for each input file, reading from stdin if none. Output
45 one hash (40 hex digits for sha1, 56 for sha224, 64 for sha256, 96 for sha384,
46 and 128 for sha512) for each input file, followed by filename.
47
48 -b Brief (hash only, no filename)
49 -c Check each line of each FILE is the same hash+filename we'd output
50 -s No output, exit status 0 if all hashes match, 1 otherwise
51
52 config SHA224SUM
53 bool "sha224sum"
54 default y
55 depends on TOYBOX_LIBCRYPTO
56 help
57 See sha1sum
58
59 config SHA256SUM
60 bool "sha256sum"
61 default y
62 depends on TOYBOX_LIBCRYPTO
63 help
64 See sha1sum
65
66 config SHA384SUM
67 bool "sha384sum"
68 default y
69 depends on TOYBOX_LIBCRYPTO
70 help
71 See sha1sum
72
73 config SHA512SUM
74 bool "sha512sum"
75 default y
76 depends on TOYBOX_LIBCRYPTO
77 help
78 See sha1sum
79 */
80
81 #define FORCE_FLAGS
82 #define FOR_md5sum
83 #include "toys.h"
84
85 #if CFG_TOYBOX_LIBCRYPTO
86 #include <openssl/md5.h>
87 #include <openssl/sha.h>
88 #else
89 typedef int SHA512_CTX;
90 #endif
91
92 GLOBALS(
93 int sawline;
94
95 // Crypto variables blanked after summing
96 unsigned state[5];
97 unsigned oldstate[5];
98 uint64_t count;
99 union {
100 char c[64];
101 unsigned i[16];
102 } buffer;
103 )
104
105 // for(i=0; i<64; i++) md5table[i] = abs(sin(i+1))*(1<<32); But calculating
106 // that involves not just floating point but pulling in -lm (and arguing with
107 // C about whether 1<<32 is a valid thing to do on 32 bit platforms) so:
108
109 static uint32_t md5table[64] = {
110 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
111 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
112 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
113 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
114 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
115 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
116 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
117 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
118 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
119 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
120 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
121 };
122
123 // Mix next 64 bytes of data into md5 hash
124
md5_transform(void)125 static void md5_transform(void)
126 {
127 unsigned x[4], *b = (unsigned *)TT.buffer.c;
128 int i;
129
130 memcpy(x, TT.state, sizeof(x));
131
132 for (i=0; i<64; i++) {
133 unsigned int in, a, rot, temp;
134
135 a = (-i)&3;
136 if (i<16) {
137 in = i;
138 rot = 7+(5*(i&3));
139 temp = x[(a+1)&3];
140 temp = (temp & x[(a+2)&3]) | ((~temp) & x[(a+3)&3]);
141 } else if (i<32) {
142 in = (1+(5*i))&15;
143 temp = (i&3)+1;
144 rot = temp*5;
145 if (temp&2) rot--;
146 temp = x[(a+3)&3];
147 temp = (x[(a+1)&3] & temp) | (x[(a+2)&3] & ~temp);
148 } else if (i<48) {
149 in = (5+(3*(i&15)))&15;
150 rot = i&3;
151 rot = 4+(5*rot)+((rot+1)&6);
152 temp = x[(a+1)&3] ^ x[(a+2)&3] ^ x[(a+3)&3];
153 } else {
154 in = (7*(i&15))&15;
155 rot = (i&3)+1;
156 rot = (5*rot)+(((rot+2)&2)>>1);
157 temp = x[(a+2)&3] ^ (x[(a+1)&3] | ~x[(a+3)&3]);
158 }
159 temp += x[a] + b[in] + md5table[i];
160 x[a] = x[(a+1)&3] + ((temp<<rot) | (temp>>(32-rot)));
161 }
162 for (i=0; i<4; i++) TT.state[i] += x[i];
163 }
164
165 // Mix next 64 bytes of data into sha1 hash.
166
167 static const unsigned rconsts[]={0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6};
168 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
169
sha1_transform(void)170 static void sha1_transform(void)
171 {
172 int i, j, k, count;
173 unsigned *block = TT.buffer.i;
174 unsigned *rot[5], *temp;
175
176 // Copy context->state[] to working vars
177 for (i=0; i<5; i++) {
178 TT.oldstate[i] = TT.state[i];
179 rot[i] = TT.state + i;
180 }
181 // 4 rounds of 20 operations each.
182 for (i=count=0; i<4; i++) {
183 for (j=0; j<20; j++) {
184 unsigned work;
185
186 work = *rot[2] ^ *rot[3];
187 if (!i) work = (work & *rot[1]) ^ *rot[3];
188 else {
189 if (i==2) work = ((*rot[1]|*rot[2])&*rot[3])|(*rot[1]&*rot[2]);
190 else work ^= *rot[1];
191 }
192
193 if (!i && j<16)
194 work += block[count] = (rol(block[count],24)&0xFF00FF00)
195 | (rol(block[count],8)&0x00FF00FF);
196 else
197 work += block[count&15] = rol(block[(count+13)&15]
198 ^ block[(count+8)&15] ^ block[(count+2)&15] ^ block[count&15], 1);
199 *rot[4] += work + rol(*rot[0],5) + rconsts[i];
200 *rot[1] = rol(*rot[1],30);
201
202 // Rotate by one for next time.
203 temp = rot[4];
204 for (k=4; k; k--) rot[k] = rot[k-1];
205 *rot = temp;
206 count++;
207 }
208 }
209 // Add the previous values of state[]
210 for (i=0; i<5; i++) TT.state[i] += TT.oldstate[i];
211 }
212
213 // Fill the 64-byte working buffer and call transform() when full.
214
hash_update(char * data,unsigned int len,void (* transform)(void))215 static void hash_update(char *data, unsigned int len, void (*transform)(void))
216 {
217 unsigned int i, j;
218
219 j = TT.count & 63;
220 TT.count += len;
221
222 for (;;) {
223 // Grab next chunk of data, return if it's not enough to process a frame
224 i = 64 - j;
225 if (i>len) i = len;
226 memcpy(TT.buffer.c+j, data, i);
227 if (j+i != 64) break;
228
229 // Process a frame
230 if (IS_BIG_ENDIAN)
231 for (j=0; j<16; j++) TT.buffer.i[j] = SWAP_LE32(TT.buffer.i[j]);
232 transform();
233 j=0;
234 data += i;
235 len -= i;
236 }
237 }
238
239 // Initialize array tersely
240 #define HASH_INIT(name, prefix) { name, (void *)prefix##_Init, \
241 (void *)prefix##_Update, (void *)prefix##_Final, \
242 prefix##_DIGEST_LENGTH, }
243 #define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
244
245 // Call the assembly optimized library code when CFG_TOYBOX_LIBCRYPTO
do_lib_hash(int fd,char * name)246 static void do_lib_hash(int fd, char *name)
247 {
248 // Largest context
249 SHA512_CTX ctx;
250 struct hash {
251 char *name;
252 int (*init)(void *);
253 int (*update)(void *, void *, size_t);
254 int (*final)(void *, void *);
255 int digest_length;
256 } algorithms[] = {
257 USE_TOYBOX_LIBCRYPTO(
258 USE_MD5SUM(HASH_INIT("md5sum", MD5),)
259 USE_SHA1SUM(HASH_INIT("sha1sum", SHA1),)
260 USE_SHA224SUM(HASH_INIT("sha224sum", SHA224),)
261 USE_SHA256SUM(HASH_INIT("sha256sum", SHA256),)
262 USE_SHA384SUM(HASH_INIT("sha384sum", SHA384),)
263 USE_SHA512SUM(HASH_INIT("sha512sum", SHA512),)
264 )
265 }, * hash;
266 int i;
267
268 // This should never NOT match, so no need to check
269 for (i = 0; i<ARRAY_LEN(algorithms); i++)
270 if (!strcmp(toys.which->name, algorithms[i].name)) break;
271 hash = algorithms+i;
272
273 hash->init(&ctx);
274 for (;;) {
275 i = read(fd, toybuf, sizeof(toybuf));
276 if (i<1) break;
277 hash->update(&ctx, toybuf, i);
278 }
279 hash->final(toybuf+128, &ctx);
280
281 for (i = 0; i<hash->digest_length; i++)
282 sprintf(toybuf+2*i, "%02x", toybuf[i+128]);
283 }
284
285 // Callback for loopfiles()
286
do_builtin_hash(int fd,char * name)287 static void do_builtin_hash(int fd, char *name)
288 {
289 uint64_t count;
290 int i, sha1=toys.which->name[0]=='s';
291 char buf;
292 void (*transform)(void);
293
294 /* SHA1 initialization constants (md5sum uses first 4) */
295 TT.state[0] = 0x67452301;
296 TT.state[1] = 0xEFCDAB89;
297 TT.state[2] = 0x98BADCFE;
298 TT.state[3] = 0x10325476;
299 TT.state[4] = 0xC3D2E1F0;
300 TT.count = 0;
301
302 transform = sha1 ? sha1_transform : md5_transform;
303 for (;;) {
304 i = read(fd, toybuf, sizeof(toybuf));
305 if (i<1) break;
306 hash_update(toybuf, i, transform);
307 }
308
309 count = TT.count << 3;
310
311 // End the message by appending a "1" bit to the data, ending with the
312 // message size (in bits, big endian), and adding enough zero bits in
313 // between to pad to the end of the next 64-byte frame.
314 //
315 // Since our input up to now has been in whole bytes, we can deal with
316 // bytes here too.
317
318 buf = 0x80;
319 do {
320 hash_update(&buf, 1, transform);
321 buf = 0;
322 } while ((TT.count & 63) != 56);
323 count = sha1 ? SWAP_BE64(count) : SWAP_LE64(count);
324 hash_update((void *)&count, 8, transform);
325
326 if (sha1)
327 for (i = 0; i < 20; i++)
328 sprintf(toybuf+2*i, "%02x", 255&(TT.state[i>>2] >> ((3-(i & 3)) * 8)));
329 else for (i=0; i<4; i++) sprintf(toybuf+8*i, "%08x", bswap_32(TT.state[i]));
330
331 // Wipe variables. Cryptographer paranoia.
332 memset(TT.state, 0, sizeof(TT)-((long)TT.state-(long)&TT));
333 i = strlen(toybuf)+1;
334 memset(toybuf+i, 0, sizeof(toybuf)-i);
335 }
336
337 // Call builtin or lib hash function, then display output if necessary
do_hash(int fd,char * name)338 static void do_hash(int fd, char *name)
339 {
340 if (CFG_TOYBOX_LIBCRYPTO) do_lib_hash(fd, name);
341 else do_builtin_hash(fd, name);
342
343 if (name)
344 printf((toys.optflags & FLAG_b) ? "%s\n" : "%s %s\n", toybuf, name);
345 }
346
do_c_line(char * line)347 static int do_c_line(char *line)
348 {
349 int space = 0, fail = 0;
350 char *name;
351
352 for (name = line; *name; name++) {
353 if (isspace(*name)) {
354 space++;
355 *name = 0;
356 } else if (space) break;
357 }
358
359 if (!space || !*line || !*name) error_msg("bad line %s", line);
360 else {
361 int fd = !strcmp(name, "-") ? 0 : open(name, O_RDONLY);
362
363 TT.sawline = 1;
364 if (fd==-1) {
365 perror_msg_raw(name);
366 *toybuf = 0;
367 } else do_hash(fd, 0);
368 if (strcasecmp(line, toybuf)) toys.exitval = fail = 1;
369 if (!FLAG(s)) printf("%s: %s\n", name, fail ? "FAILED" : "OK");
370 if (fd>0) close(fd);
371 }
372
373 return 0;
374 }
375
376 // Used instead of loopfiles_line to report error on files containing no hashes.
do_c_file(char * name)377 static void do_c_file(char *name)
378 {
379 FILE *fp = !strcmp(name, "-") ? stdin : fopen(name, "r");
380
381 if (!fp) {
382 perror_msg_raw(name);
383 return;
384 }
385
386 TT.sawline = 0;
387
388 for (;;) {
389 char *line = 0;
390 ssize_t len;
391
392 if ((len = getline(&line, (void *)&len, fp))<1) break;
393 if (line[len-1]=='\n') line[len-1] = 0;
394 do_c_line(line);
395 free(line);
396 }
397 if (fp!=stdin) fclose(fp);
398
399 if (!TT.sawline) error_msg("%s: no lines", name);
400 }
401
md5sum_main(void)402 void md5sum_main(void)
403 {
404 char **arg;
405
406 if (FLAG(c)) for (arg = toys.optargs; *arg; arg++) do_c_file(*arg);
407 else {
408 if (FLAG(s)) error_exit("-s only with -c");
409 loopfiles(toys.optargs, do_hash);
410 }
411 }
412
sha1sum_main(void)413 void sha1sum_main(void)
414 {
415 md5sum_main();
416 }
417