1 /* md5sum.c - Calculate hashes md5, sha1, sha224, sha256, sha384, sha512.
2 *
3 * Copyright 2012, 2021 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 * and http://www.ietf.org/rfc/rfc4634.txt
8 *
9 * They're combined this way to share infrastructure, and because md5sum is
10 * a LSB standard command (but sha1sum and newer hashes are a good idea,
11 * see http://valerieaurora.org/hash.html).
12 *
13 * We optionally use openssl (or equivalent) to access assembly optimized
14 * versions of these functions, but provide a built-in version to reduce
15 * required dependencies.
16 *
17 * coreutils supports --status but not -s, busybox supports -s but not --status
18
19 USE_MD5SUM(NEWTOY(md5sum, "bc(check)s(status)[!bc]", TOYFLAG_USR|TOYFLAG_BIN))
20 USE_SHA1SUM(OLDTOY(sha1sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
21 USE_SHA224SUM(OLDTOY(sha224sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
22 USE_SHA256SUM(OLDTOY(sha256sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
23 USE_SHA384SUM(OLDTOY(sha384sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
24 USE_SHA512SUM(OLDTOY(sha512sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
25
26 config MD5SUM
27 bool "md5sum"
28 default y
29 help
30 usage: ???sum [-bcs] [FILE]...
31
32 Calculate hash for each input file, reading from stdin if none, writing
33 hexadecimal digits to stdout for each input file (md5=32 hex digits,
34 sha1=40, sha224=56, sha256=64, sha384=96, sha512=128) followed by filename.
35
36 -b Brief (hash only, no filename)
37 -c Check each line of each FILE is the same hash+filename we'd output
38 -s No output, exit status 0 if all hashes match, 1 otherwise
39
40 config SHA1SUM
41 bool "sha1sum"
42 default y
43 help
44 See md5sum
45
46 config SHA224SUM
47 bool "sha224sum"
48 default y
49 help
50 See md5sum
51
52 config SHA256SUM
53 bool "sha256sum"
54 default y
55 help
56 See md5sum
57
58 config SHA384SUM
59 bool "sha384sum"
60 default y
61 help
62 See md5sum
63
64 config SHA512SUM
65 bool "sha512sum"
66 default y
67 help
68 See md5sum
69 */
70
71 #define FORCE_FLAGS
72 #define FOR_md5sum
73 #include "toys.h"
74
75 #if CFG_TOYBOX_LIBCRYPTO
76 #include <openssl/md5.h>
77 #include <openssl/sha.h>
78 #else
79 typedef int SHA512_CTX;
80 #endif
81
82 GLOBALS(
83 int sawline;
84 unsigned *rconsttable32;
85 unsigned long long *rconsttable64; // for sha384,sha512
86
87 // Crypto variables blanked after summing
88 unsigned long long count, overflow;
89 union {
90 char c[128]; // bytes, 1024 bits
91 unsigned i32[16]; // 512 bits for md5,sha1,sha224,sha256
92 unsigned long long i64[16]; // 1024 bits for sha384,sha512
93 } state, buffer;
94 )
95
96 // Round constants. Static table for when we haven't got floating point support
97 #if ! CFG_TOYBOX_FLOAT
98 static const unsigned md5nofloat[64] = {
99 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
100 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
101 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
102 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
103 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
104 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
105 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
106 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
107 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
108 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
109 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
110 };
111 #else
112 #define md5nofloat 0
113 #endif
114 static unsigned long long sha512nofloat[80] = {
115 // we cannot calculate these 64-bit values using the readily
116 // available floating point data types and math functions,
117 // so we always use this lookup table (80 * 8 bytes)
118 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
119 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
120 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
121 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
122 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
123 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
124 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
125 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
126 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
127 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
128 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
129 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
130 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
131 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
132 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
133 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
134 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
135 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
136 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
137 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
138 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
139 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
140 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
141 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
142 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
143 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
144 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
145 };
146 // sha1 needs only 4 round constant values, so prefer precomputed
147 static const unsigned sha1rconsts[] = {
148 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
149 };
150
151 // bit rotations
152 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
153 #define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
154 #define ror64(value, bits) (((value) >> (bits)) | ((value) << (64 - (bits))))
155
156 // Mix next 64 bytes of data into md5 hash
157
md5_transform(void)158 static void md5_transform(void)
159 {
160 unsigned x[4], *b = TT.buffer.i32;
161 int i;
162
163 for (i = 0; i<4; i++) x[i] = TT.state.i32[i];
164 for (i = 0; i<64; i++) {
165 unsigned in, a, rot, temp;
166
167 a = (-i)&3;
168 if (i<16) {
169 in = i;
170 rot = 7+(5*(i&3));
171 temp = x[(a+1)&3];
172 temp = (temp & x[(a+2)&3]) | ((~temp) & x[(a+3)&3]);
173 } else if (i<32) {
174 in = (1+(5*i))&15;
175 temp = (i&3)+1;
176 rot = temp*5;
177 if (temp&2) rot--;
178 temp = x[(a+3)&3];
179 temp = (x[(a+1)&3] & temp) | (x[(a+2)&3] & ~temp);
180 } else if (i<48) {
181 in = (5+(3*(i&15)))&15;
182 rot = i&3;
183 rot = 4+(5*rot)+((rot+1)&6);
184 temp = x[(a+1)&3] ^ x[(a+2)&3] ^ x[(a+3)&3];
185 } else {
186 in = (7*(i&15))&15;
187 rot = (i&3)+1;
188 rot = (5*rot)+(((rot+2)&2)>>1);
189 temp = x[(a+2)&3] ^ (x[(a+1)&3] | ~x[(a+3)&3]);
190 }
191 temp += x[a] + SWAP_LE32(b[in]) + TT.rconsttable32[i];
192 x[a] = x[(a+1)&3] + ((temp<<rot) | (temp>>(32-rot)));
193 }
194 for (i = 0; i<4; i++) TT.state.i32[i] += x[i];
195 }
196
197 // Mix next 64 bytes of data into sha1 hash.
198
sha1_transform(void)199 static void sha1_transform(void)
200 {
201 int i, j, k, count;
202 unsigned *block = TT.buffer.i32, oldstate[5], *rot[5], *temp, work;
203
204 // Copy context->state.i32[] to working vars
205 for (i = 0; i<5; i++) {
206 oldstate[i] = TT.state.i32[i];
207 rot[i] = TT.state.i32 + i;
208 }
209 if (IS_BIG_ENDIAN) for (i = 0; i<16; i++) block[i] = SWAP_LE32(block[i]);
210
211 // 4 rounds of 20 operations each.
212 for (i = count = 0; i<4; i++) {
213 for (j = 0; j<20; j++) {
214 work = *rot[2] ^ *rot[3];
215 if (!i) work = (work & *rot[1]) ^ *rot[3];
216 else {
217 if (i==2) work = ((*rot[1]|*rot[2])&*rot[3])|(*rot[1]&*rot[2]);
218 else work ^= *rot[1];
219 }
220
221 if (!i && j<16)
222 work += block[count] = (ror(block[count],8)&0xFF00FF00)
223 | (rol(block[count],8)&0x00FF00FF);
224 else
225 work += block[count&15] = rol(block[(count+13)&15]
226 ^ block[(count+8)&15] ^ block[(count+2)&15] ^ block[count&15], 1);
227 *rot[4] += work + rol(*rot[0],5) + sha1rconsts[i];
228 *rot[1] = rol(*rot[1],30);
229
230 // Rotate by one for next time.
231 temp = rot[4];
232 for (k = 4; k; k--) rot[k] = rot[k-1];
233 *rot = temp;
234 count++;
235 }
236 }
237 // Add the previous values of state.i32[]
238 for (i = 0; i<5; i++) TT.state.i32[i] += oldstate[i];
239 }
240
sha2_32_transform(void)241 static void sha2_32_transform(void)
242 {
243 unsigned block[64], s0, s1, S0, S1, ch, maj, temp1, temp2, rot[8];
244 int i;
245
246 for (i = 0; i<16; i++) block[i] = SWAP_BE32(TT.buffer.i32[i]);
247
248 // Extend the message schedule array beyond first 16 words
249 for (i = 16; i<64; i++) {
250 s0 = ror(block[i-15], 7) ^ ror(block[i-15], 18) ^ (block[i-15] >> 3);
251 s1 = ror(block[i-2], 17) ^ ror(block[i-2], 19) ^ (block[i-2] >> 10);
252 block[i] = block[i-16] + s0 + block[i-7] + s1;
253 }
254 // Copy context->state.i32[] to working vars
255 for (i = 0; i<8; i++) rot[i] = TT.state.i32[i];
256 // 64 rounds
257 for (i = 0; i<64; i++) {
258 S1 = ror(rot[4],6) ^ ror(rot[4],11) ^ ror(rot[4], 25);
259 ch = (rot[4] & rot[5]) ^ ((~ rot[4]) & rot[6]);
260 temp1 = rot[7] + S1 + ch + TT.rconsttable32[i] + block[i];
261 S0 = ror(rot[0],2) ^ ror(rot[0],13) ^ ror(rot[0], 22);
262 maj = (rot[0] & rot[1]) ^ (rot[0] & rot[2]) ^ (rot[1] & rot[2]);
263 temp2 = S0 + maj;
264 memmove(rot+1, rot, 28);
265 rot[4] += temp1;
266 rot[0] = temp1 + temp2;
267 }
268
269 // Add the previous values of state.i32[]
270 for (i = 0; i<8; i++) TT.state.i32[i] += rot[i];
271 }
272
sha2_64_transform(void)273 static void sha2_64_transform(void)
274 {
275 unsigned long long block[80], s0, s1, S0, S1, ch, maj, temp1, temp2, rot[8];
276 int i;
277
278 for (i=0; i<16; i++) block[i] = SWAP_BE64(TT.buffer.i64[i]);
279
280 // Extend the message schedule array beyond first 16 words
281 for (i = 16; i<80; i++) {
282 s0 = ror64(block[i-15], 1) ^ ror64(block[i-15], 8) ^ (block[i-15] >> 7);
283 s1 = ror64(block[i-2], 19) ^ ror64(block[i-2], 61) ^ (block[i-2] >> 6);
284 block[i] = block[i-16] + s0 + block[i-7] + s1;
285 }
286 // Copy context->state.i64[] to working vars
287 for (i = 0; i<8; i++) rot[i] = TT.state.i64[i];
288 // 80 rounds
289 for (i = 0; i<80; i++) {
290 S1 = ror64(rot[4],14) ^ ror64(rot[4],18) ^ ror64(rot[4], 41);
291 ch = (rot[4] & rot[5]) ^ ((~ rot[4]) & rot[6]);
292 temp1 = rot[7] + S1 + ch + TT.rconsttable64[i] + block[i];
293 S0 = ror64(rot[0],28) ^ ror64(rot[0],34) ^ ror64(rot[0], 39);
294 maj = (rot[0] & rot[1]) ^ (rot[0] & rot[2]) ^ (rot[1] & rot[2]);
295 temp2 = S0 + maj;
296 memmove(rot+1, rot, 56);
297 rot[4] += temp1;
298 rot[0] = temp1 + temp2;
299 }
300
301 // Add the previous values of state.i64[]
302 for (i=0; i<8; i++) TT.state.i64[i] += rot[i];
303 }
304
305 // Fill the 64/128-byte (512/1024-bit) working buffer and call transform() when full.
306
hash_update(char * data,unsigned int len,void (* transform)(void),int chunksize)307 static void hash_update(char *data, unsigned int len, void (*transform)(void),
308 int chunksize)
309 {
310 unsigned int i, j;
311
312 j = TT.count & (chunksize - 1);
313 if (TT.count+len<TT.count) TT.overflow++;
314 TT.count += len;
315
316 for (;;) {
317 // Grab next chunk of data, return if it's not enough to process a frame
318 i = chunksize - j;
319 if (i>len) i = len;
320 memcpy(TT.buffer.c+j, data, i);
321 if (j+i != chunksize) break;
322
323 // Process a frame
324 transform();
325 j=0;
326 data += i;
327 len -= i;
328 }
329 }
330
331 // Initialize array tersely
332 #define HASH_INIT(name, prefix) { name, (void *)prefix##_Init, \
333 (void *)prefix##_Update, (void *)prefix##_Final, \
334 prefix##_DIGEST_LENGTH, }
335 #define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
336
337 // Call the assembly optimized library code when CFG_TOYBOX_LIBCRYPTO
do_lib_hash(int fd,char * name)338 static void do_lib_hash(int fd, char *name)
339 {
340 // Largest context
341 SHA512_CTX ctx;
342 struct hash {
343 char *name;
344 int (*init)(void *);
345 int (*update)(void *, void *, size_t);
346 int (*final)(void *, void *);
347 int digest_length;
348 } algorithms[] = {
349 USE_TOYBOX_LIBCRYPTO(
350 USE_MD5SUM(HASH_INIT("md5sum", MD5),)
351 USE_SHA1SUM(HASH_INIT("sha1sum", SHA1),)
352 USE_SHA224SUM(HASH_INIT("sha224sum", SHA224),)
353 USE_SHA256SUM(HASH_INIT("sha256sum", SHA256),)
354 USE_SHA384SUM(HASH_INIT("sha384sum", SHA384),)
355 USE_SHA512SUM(HASH_INIT("sha512sum", SHA512),)
356 )
357 }, * hash;
358 int i;
359
360 // This should never NOT match, so no need to check
361 for (i = 0; i<ARRAY_LEN(algorithms); i++)
362 if (!strcmp(toys.which->name, algorithms[i].name)) break;
363 hash = algorithms+i;
364
365 hash->init(&ctx);
366 for (;;) {
367 i = read(fd, toybuf, sizeof(toybuf));
368 if (i<1) break;
369 hash->update(&ctx, toybuf, i);
370 }
371 hash->final(toybuf+128, &ctx);
372
373 for (i = 0; i<hash->digest_length; i++)
374 sprintf(toybuf+2*i, "%02x", toybuf[i+128]);
375 }
376
do_builtin_hash(int fd,char * name)377 static void do_builtin_hash(int fd, char *name)
378 {
379 unsigned long long count[2];
380 int i, chunksize, digestlen, method;
381 volatile char *pp;
382 void (*transform)(void);
383 char buf;
384
385 // md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum
386 method = stridx("us2581", toys.which->name[4]);
387
388 // select hash type
389 transform = (void *[]){md5_transform, sha1_transform, sha2_32_transform,
390 sha2_32_transform, sha2_64_transform, sha2_64_transform}[method];
391 digestlen = (char []){16, 20, 28, 32, 48, 64}[method];
392 chunksize = 64<<(method>=4);
393 if (method<=1)
394 memcpy(TT.state.i32, (unsigned []){0x67452301, 0xEFCDAB89, 0x98BADCFE,
395 0x10325476, 0xC3D2E1F0}, 20);
396 else if (method==2)
397 memcpy(TT.state.i32, (unsigned []){0xc1059ed8, 0x367cd507, 0x3070dd17,
398 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}, 32);
399 else if (method==3)
400 memcpy(TT.state.i32, (unsigned []){0x6a09e667, 0xbb67ae85, 0x3c6ef372,
401 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}, 32);
402 else if (method==4)
403 memcpy(TT.state.i64, (unsigned long long []){0xcbbb9d5dc1059ed8,
404 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
405 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7,
406 0x47b5481dbefa4fa4}, 64);
407 else memcpy(TT.state.i64, (unsigned long long []){0x6a09e667f3bcc908,
408 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
409 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b,
410 0x5be0cd19137e2179}, 64);
411
412 TT.count = 0;
413 for (;;) {
414 i = read(fd, toybuf, sizeof(toybuf));
415 if (i<1) break;
416 hash_update(toybuf, i, transform, chunksize);
417 }
418
419 // End the message by appending a "1" bit to the data, ending with the
420 // message size (in bits, big endian), and adding enough zero bits in
421 // between to pad to the end of the next frame.
422 //
423 // Since our input up to now has been in whole bytes, we can deal with
424 // bytes here too. sha384 and 512 use 128 bit counter, so track overflow.
425 buf = 0x80;
426 count[0] = (TT.overflow<<3)+(TT.count>>61);
427 count[1] = TT.count<<3; // convert to bits
428 for (i = 0; i<2; i++)
429 count[i] = !method ? SWAP_LE64(count[i]) : SWAP_BE64(count[i]);
430 i = 8<<(method>=4);
431 do {
432 hash_update(&buf, 1, transform, chunksize);
433 buf = 0;
434 } while ((TT.count&(chunksize-1)) != chunksize-i);
435 hash_update((void *)(count+(method<4)), i, transform, chunksize);
436
437 // write digest to toybuf
438 if (method>=4) for (i=0; i<digestlen/8; i++)
439 sprintf(toybuf+16*i, "%016llx", TT.state.i64[i]);
440 else for (i=0; i<digestlen/4; i++)
441 sprintf(toybuf+8*i, "%08x",
442 !method ? bswap_32(TT.state.i32[i]) : TT.state.i32[i]);
443 // Wipe variables. Cryptographer paranoia. Avoid "optimizing" out memset
444 // by looping on a volatile pointer.
445 i = sizeof(struct md5sum_data)-offsetof(struct md5sum_data, state.i64);
446 for (pp = (void *)TT.state.i64; i; i--) *pp++ = 0;
447 pp = toybuf+strlen(toybuf)+1;
448 for (i = sizeof(toybuf)-(pp-toybuf); i; i--) *pp++ = 0;
449 }
450
451 // Callback for loopfiles()
452 // Call builtin or lib hash function, then display output if necessary
do_hash(int fd,char * name)453 static void do_hash(int fd, char *name)
454 {
455 if (CFG_TOYBOX_LIBCRYPTO) do_lib_hash(fd, name);
456 else do_builtin_hash(fd, name);
457
458 if (name) printf("%s %s\n"+4*FLAG(b), toybuf, name);
459 }
460
do_c_line(char * line)461 static void do_c_line(char *line)
462 {
463 int space = 0, fail = 0, fd;
464 char *name;
465
466 for (name = line; *name; name++) {
467 if (isspace(*name)) {
468 space++;
469 *name = 0;
470 } else if (space) break;
471 }
472 if (!space || !*line || !*name) return error_msg("bad line %s", line);
473
474 fd = !strcmp(name, "-") ? 0 : open(name, O_RDONLY);
475
476 TT.sawline = 1;
477 if (fd==-1) {
478 perror_msg_raw(name);
479 *toybuf = 0;
480 } else do_hash(fd, 0);
481 if (strcasecmp(line, toybuf)) toys.exitval = fail = 1;
482 if (!FLAG(s)) printf("%s: %s\n", name, fail ? "FAILED" : "OK");
483 if (fd>0) close(fd);
484 }
485
486 // Used instead of loopfiles_line to report error on files containing no hashes.
do_c_file(char * name)487 static void do_c_file(char *name)
488 {
489 FILE *fp = !strcmp(name, "-") ? stdin : fopen(name, "r");
490 char *line;
491
492 if (!fp) return perror_msg_raw(name);
493
494 TT.sawline = 0;
495
496 for (;;) {
497 if (!(line = xgetline(fp))) break;
498 do_c_line(line);
499 free(line);
500 }
501 if (fp!=stdin) fclose(fp);
502
503 if (!TT.sawline) error_msg("%s: no lines", name);
504 }
505
md5sum_main(void)506 void md5sum_main(void)
507 {
508 int i;
509
510 // Calculate table if we have floating point. Static version should drop
511 // out at compile time when we don't need it.
512 if (!CFG_TOYBOX_LIBCRYPTO) {
513 if (*toys.which->name == 'm') { // MD5
514 if (CFG_TOYBOX_FLOAT) {
515 TT.rconsttable32 = xmalloc(64*4);
516 for (i = 0; i<64; i++) TT.rconsttable32[i] = fabs(sin(i+1))*(1LL<<32);
517 } else TT.rconsttable32 = md5nofloat;
518 } else if (toys.which->name[3] == '2') { // sha224, sha256
519 TT.rconsttable32 = xmalloc(64*4);
520 for (i=0; i<64; i++) TT.rconsttable32[i] = sha512nofloat[i] >> 32;
521 } else TT.rconsttable64 = sha512nofloat; // sha384, sha512
522 }
523
524 if (FLAG(c)) for (i = 0; toys.optargs[i]; i++) do_c_file(toys.optargs[i]);
525 else {
526 if (FLAG(s)) error_exit("-s only with -c");
527 loopfiles(toys.optargs, do_hash);
528 }
529 }
530