1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
85typedef int SHA512_CTX;
86#endif
87
88GLOBALS(
89 struct arg_list *c;
90
91 int sawline;
92
93
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
106
107
108
109static 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
123static 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
131
132static 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
167
168static const unsigned rconsts[]={0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6};
169
170static void sha1_transform(void)
171{
172 int i, j, k, count;
173 unsigned *block = TT.buffer.i;
174 unsigned *rot[5], *temp;
175
176
177 for (i=0; i<5; i++) {
178 TT.oldstate[i] = TT.state[i];
179 rot[i] = TT.state + i;
180 }
181
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
203 temp = rot[4];
204 for (k=4; k; k--) rot[k] = rot[k-1];
205 *rot = temp;
206 count++;
207 }
208 }
209
210 for (i=0; i<5; i++) TT.state[i] += TT.oldstate[i];
211}
212
213
214
215static 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
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
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
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
246static void do_lib_hash(int fd, char *name)
247{
248
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
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
286
287static 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
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
312
313
314
315
316
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
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
338static 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
347static 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
377
378
379int 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
409void 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
421void sha1sum_main(void)
422{
423 md5sum_main();
424}
425