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 USE_MD5SUM(NEWTOY(md5sum, "bc*[!bc]", TOYFLAG_USR|TOYFLAG_BIN))
17 USE_SHA1SUM(NEWTOY(sha1sum, "bc*[!bc]", TOYFLAG_USR|TOYFLAG_BIN))
18 USE_SHA224SUM(OLDTOY(sha224sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN))
19 USE_SHA256SUM(OLDTOY(sha256sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN))
20 USE_SHA384SUM(OLDTOY(sha384sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN))
21 USE_SHA512SUM(OLDTOY(sha512sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN))
22
23 config MD5SUM
24 bool "md5sum"
25 default y
26 help
27 usage: md5sum [-b] [-c FILE] [FILE]...
28
29 Calculate md5 hash for each input file, reading from stdin if none.
30 Output one hash (32 hex digits) for each input file, followed by filename.
31
32 -b brief (hash only, no filename)
33 -c Check each line of FILE is the same hash+filename we'd output.
34
35 config SHA1SUM
36 bool "sha1sum"
37 default y
38 help
39 usage: sha?sum [-b] [-c FILE] [FILE]...
40
41 calculate sha hash for each input file, reading from stdin if none. Output
42 one hash (40 hex digits for sha1, 56 for sha224, 64 for sha256, 96 for sha384,
43 and 128 for sha512) for each input file, followed by filename.
44
45 -b brief (hash only, no filename)
46 -c Check each line of FILE is the same hash+filename we'd output.
47
48 config SHA224SUM
49 bool "sha224sum"
50 default y
51 depends on TOYBOX_LIBCRYPTO
52 help
53 See sha1sum
54
55 config SHA256SUM
56 bool "sha256sum"
57 default y
58 depends on TOYBOX_LIBCRYPTO
59 help
60 See sha1sum
61
62 config SHA384SUM
63 bool "sha384sum"
64 default y
65 depends on TOYBOX_LIBCRYPTO
66 help
67 See sha1sum
68
69 config SHA512SUM
70 bool "sha512sum"
71 default y
72 depends on TOYBOX_LIBCRYPTO
73 help
74 See sha1sum
75 */
76
77 #define FORCE_FLAGS
78 #define FOR_md5sum
79 #include "toys.h"
80
81 #if CFG_TOYBOX_LIBCRYPTO
82 #include <openssl/md5.h>
83 #include <openssl/sha.h>
84 #else
85 typedef int SHA512_CTX;
86 #endif
87
88 GLOBALS(
89 struct arg_list *c;
90
91 int sawline;
92
93 // Crypto variables blanked after summing
94 unsigned state[5];
95 unsigned oldstate[5];
96 uint64_t count;
97 union {
98 char c[64];
99 unsigned i[16];
100 } buffer;
101 )
102
103 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
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 static const uint8_t md5rot[64] = {
124 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
125 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
126 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
127 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
128 };
129
130 // Mix next 64 bytes of data into md5 hash
131
md5_transform(void)132 static void md5_transform(void)
133 {
134 unsigned x[4], *b = TT.buffer.i;
135 int i;
136
137 memcpy(x, TT.state, sizeof(x));
138
139 for (i=0; i<64; i++) {
140 unsigned int in, temp, swap;
141 if (i<16) {
142 in = i;
143 temp = x[1];
144 temp = (temp & x[2]) | ((~temp) & x[3]);
145 } else if (i<32) {
146 in = (1+(5*i))&15;
147 temp = x[3];
148 temp = (x[1] & temp) | (x[2] & ~temp);
149 } else if (i<48) {
150 in = (3*i+5)&15;
151 temp = x[1] ^ x[2] ^ x[3];
152 } else {
153 in = (7*i)&15;
154 temp = x[2] ^ (x[1] | ~x[3]);
155 }
156 temp += x[0] + b[in] + md5table[i];
157 swap = x[3];
158 x[3] = x[2];
159 x[2] = x[1];
160 x[1] += rol(temp, md5rot[i]);
161 x[0] = swap;
162 }
163 for (i=0; i<4; i++) TT.state[i] += x[i];
164 }
165
166 // Mix next 64 bytes of data into sha1 hash.
167
168 static const unsigned rconsts[]={0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6};
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(char * line,size_t len)347 static int do_c(char *line, size_t len)
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 printf("%s: %s\n", name, fail ? "FAILED" : "OK");
370 if (fd>0) close(fd);
371 }
372
373 return 0;
374 }
375
376 // Open file, read each line, and call do_line(). Returns 0 if file existed
377 // and we read it to the end, 1 if interrupted by callback, 2 of didn't exist
378 // do_line returns 0 to free line, 1 to keep line, 2 to end loop
looplines(char * name,int trim,int (* do_line)(char * line,size_t len))379 int looplines(char *name, int trim, int (*do_line)(char *line, size_t len))
380 {
381 FILE *fp = !strcmp(name, "-") ? stdin : fopen(name, "r");
382 int rc = 0;
383
384 if (!fp) {
385 perror_msg_raw(name);
386
387 return 2;
388 }
389
390 for (;;) {
391 char *line = 0;
392 ssize_t len;
393
394 if ((len = getline(&line, (void *)&len, fp))<1) break;
395 if (line[len-1]=='\n') len--;
396 if (trim) line[len] = 0;
397 len = do_line(line, len);
398 if (!len) free(line);
399 if (len==2) {
400 rc = 2;
401 break;
402 }
403 }
404 if (fp!=stdin) fclose(fp);
405
406 return rc;
407 }
408
md5sum_main(void)409 void md5sum_main(void)
410 {
411 struct arg_list *al;
412
413 if (!TT.c) loopfiles(toys.optargs, do_hash);
414 else for (al = TT.c; al; al = al->next) {
415 TT.sawline = 0;
416 looplines(al->arg, 1, do_c);
417 if (!TT.sawline) error_msg("%s: no lines", al->arg);
418 }
419 }
420
sha1sum_main(void)421 void sha1sum_main(void)
422 {
423 md5sum_main();
424 }
425