1 /* $OpenBSD: md5.c,v 1.32 2004/12/29 17:32:44 millert Exp $ */
2 /* $OpenBSD: crc.c,v 1.2 2004/05/10 19:48:07 deraadt Exp $ */
3 /* $OpenBSD: crc.h,v 1.1 2004/05/02 17:53:29 millert Exp $ */
4
5 /*
6 * Copyright (c) 2001, 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * Sponsored in part by the Defense Advanced Research Projects
13 * Agency (DARPA) and Air Force Research Laboratory, Air Force
14 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
15 */
16
17 /*-
18 * Copyright (c) 2007, 2009, 2011, 2014
19 * Thorsten Glaser <tg@mirbsd.org>
20 *
21 * Provided that these terms and disclaimer and all copyright notices
22 * are retained or reproduced in an accompanying document, permission
23 * is granted to deal in this work without restriction, including un-
24 * limited rights to use, publicly perform, distribute, sell, modify,
25 * merge, give away, or sublicence.
26 *
27 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
28 * the utmost extent permitted by applicable law, neither express nor
29 * implied; without malicious intent or gross negligence. In no event
30 * may a licensor, author or contributor be held liable for indirect,
31 * direct, other damage, loss, or other issues arising in any way out
32 * of dealing in the work, even if advised of the possibility of such
33 * damage or existence of a defect, except proven that it results out
34 * of said person's immediate fault when using the work as intended.
35 */
36
37 #include <sys/param.h>
38 #include <sys/time.h>
39 #include <ctype.h>
40 #include <err.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
47 #include <unistd.h>
48
49 #include <adler32.h>
50 #include <md4.h>
51 #include <md5.h>
52 #include <rmd160.h>
53 #include <sfv.h>
54 #include <sha1.h>
55 #include <sha2.h>
56 #include <suma.h>
57 #include <tiger.h>
58 #include <whirlpool.h>
59
60 #ifdef __MirBSD__
61 /* for OAAT1S; XXX drop this long-term */
62 extern const uint8_t RFC1321_padding[64];
63 #endif
64
65 __RCSID("$MirOS: src/bin/md5/cksum.c,v 1.18 2014/02/19 17:15:10 tg Exp $");
66
67 #define MAX_DIGEST_LEN 128
68
69 #define CKSUM_DIGEST_LENGTH 4
70 #define CKSUM_DIGEST_STRING_LENGTH (10 + 1 + 19)
71
72 typedef struct CKSUMContext {
73 uint32_t crc;
74 off_t len;
75 } CKSUM_CTX;
76
77 #define SUM_DIGEST_LENGTH 4
78 typedef CKSUM_CTX SUM_CTX;
79
80 #define SYSVSUM_DIGEST_LENGTH 4
81 typedef CKSUM_CTX SYSVSUM_CTX;
82
83 typedef uint32_t BAFH_CTX;
84 typedef uint32_t CDB_CTX;
85 typedef uint32_t NZAT_CTX;
86 typedef uint64_t SIZE_CTX;
87
88 typedef CKSUM_CTX OAATS_CTX;
89
90 union ANY_CTX {
91 CKSUM_CTX cksum;
92 MD4_CTX md4;
93 MD5_CTX md5;
94 RMD160_CTX rmd160;
95 SHA1_CTX sha1;
96 SHA256_CTX sha256;
97 SHA384_CTX sha384;
98 SHA512_CTX sha512;
99 SUM_CTX sum;
100 SYSVSUM_CTX sysvsum;
101 SUMA_CTX suma;
102 ADLER32_CTX adler32;
103 SFV_CTX sfv;
104 TIGER_CTX tiger;
105 WHIRLPOOL_CTX whirlpool;
106 SIZE_CTX size;
107 CDB_CTX cdb;
108 OAATS_CTX oaats;
109 NZAT_CTX nzat;
110 BAFH_CTX bafh;
111 };
112
113 void digest_print(const char *, const char *, const char *);
114 void digest_print_short(const char *, const char *, const char *);
115 void digest_print_string(const char *, const char *, const char *);
116 void digest_print_sfv(const char *, const char *, const char *);
117 void digest_printbin_pad(const char *);
118 void digest_printbin_string(const char *);
119 void digest_printbin_stringle(const char *);
120 void cksum_addpool(const char *) __attribute__((__nonnull__(1)));
121
122 char *ucase_End(uint32_t *, char *);
123 char *ulld_End(CKSUM_CTX *, char *);
124
125 void SIZE_Init(SIZE_CTX *);
126 void SIZE_Update(SIZE_CTX *, const uint8_t *, size_t);
127 char *SIZE_End(SIZE_CTX *, char *);
128
129 void CDB_Init(CDB_CTX *);
130 void CDB_Update(CDB_CTX *, const uint8_t *, size_t);
131 #define CDB_End ucase_End
132
133 #define CKSUM_Init OAAT_Init
134 void CKSUM_Update(CKSUM_CTX *, const u_int8_t *, size_t);
135 void CKSUM_Final(CKSUM_CTX *);
136 char *CKSUM_End(CKSUM_CTX *, char *);
137 char *CKSUM_Data(const u_int8_t *, size_t, char *);
138
139 void OAAT_Init(OAATS_CTX *);
140 void OAAT1_Init(OAATS_CTX *);
141 void OAAT_Update(OAATS_CTX *, const uint8_t *, size_t);
142 void OAAT_Final(OAATS_CTX *);
143 char *OAAT_End(OAATS_CTX *, char *);
144 #ifdef __MirBSD__
145 char *OAAT1S_End(OAATS_CTX *, char *);
146 #endif
147
148 void NZAT_Init(NZAT_CTX *);
149 void NZAT_Update(NZAT_CTX *, const uint8_t *, size_t);
150 void NZAT_Final(NZAT_CTX *);
151 void NZAAT_Final(NZAT_CTX *);
152 char *NZAT_End(NZAT_CTX *, char *);
153 char *NZAAT_End(NZAT_CTX *, char *);
154
155 #define BAFH_Init NZAT_Init
156 #define BAFH_Update NZAT_Update
157 char *BAFH_End(BAFH_CTX *, char *);
158
159 #define SUM_Init OAAT_Init
160 void SUM_Update(SUM_CTX *, const u_int8_t *, size_t);
161 void SUM_Final(SUM_CTX *);
162 char *SUM_End(SUM_CTX *, char *);
163 char *SUM_Data(const u_int8_t *, size_t, char *);
164
165 #define SYSVSUM_Init OAAT_Init
166 void SYSVSUM_Update(SYSVSUM_CTX *, const u_int8_t *, size_t);
167 void SYSVSUM_Final(SYSVSUM_CTX *);
168 char *SYSVSUM_End(SYSVSUM_CTX *, char *);
169 char *SYSVSUM_Data(const u_int8_t *, size_t, char *);
170
171 /* when adding, change lines with context matching NHASHMOD */
172
173 /* NHASHMOD: total number of hash functions */
174 #ifdef __MirBSD__
175 #define NHASHES 23
176 #else
177 #define NHASHES 22
178 #endif
179 struct hash_functions {
180 const char *name;
181 size_t digestlen;
182 void *ctx; /* XXX - only used by digest_file() */
183 void (*init)(void *);
184 void (*update)(void *, const unsigned char *, unsigned int);
185 char * (*end)(void *, char *);
186 void (*printbin)(const char *);
187 void (*print)(const char *, const char *, const char *);
188 void (*printstr)(const char *, const char *, const char *);
189 } functions[NHASHES + 1] = {
190 {
191 "CKSUM",
192 CKSUM_DIGEST_LENGTH * 2,
193 NULL,
194 (void (*)(void *))CKSUM_Init,
195 (void (*)(void *, const unsigned char *, unsigned int))CKSUM_Update,
196 (char *(*)(void *, char *))CKSUM_End,
197 digest_printbin_pad,
198 digest_print_short,
199 digest_print_short
200 }, {
201 "SUM",
202 SUM_DIGEST_LENGTH * 2,
203 NULL,
204 (void (*)(void *))SUM_Init,
205 (void (*)(void *, const unsigned char *, unsigned int))SUM_Update,
206 (char *(*)(void *, char *))SUM_End,
207 digest_printbin_pad,
208 digest_print_short,
209 digest_print_short
210 }, {
211 "SYSVSUM",
212 SYSVSUM_DIGEST_LENGTH * 2,
213 NULL,
214 (void (*)(void *))SYSVSUM_Init,
215 (void (*)(void *, const unsigned char *, unsigned int))SYSVSUM_Update,
216 (char *(*)(void *, char *))SYSVSUM_End,
217 digest_printbin_pad,
218 digest_print_short,
219 digest_print_short
220 }, {
221 "ADLER32",
222 ADLER32_DIGEST_LENGTH * 2,
223 NULL,
224 (void (*)(void *))ADLER32Init,
225 (void (*)(void *, const unsigned char *, unsigned int))ADLER32Update,
226 (char *(*)(void *, char *))ADLER32End,
227 digest_printbin_string,
228 digest_print,
229 digest_print_string
230 }, {
231 "BAFH",
232 8,
233 NULL,
234 (void (*)(void *))BAFH_Init,
235 (void (*)(void *, const unsigned char *, unsigned int))BAFH_Update,
236 (char *(*)(void *, char *))BAFH_End,
237 digest_printbin_stringle,
238 digest_print,
239 digest_print_string
240 }, {
241 "CDB",
242 8,
243 NULL,
244 (void (*)(void *))CDB_Init,
245 (void (*)(void *, const unsigned char *, unsigned int))CDB_Update,
246 (char *(*)(void *, char *))CDB_End,
247 digest_printbin_stringle,
248 digest_print,
249 digest_print_string
250 }, {
251 "NZAT",
252 8,
253 NULL,
254 (void (*)(void *))NZAT_Init,
255 (void (*)(void *, const unsigned char *, unsigned int))NZAT_Update,
256 (char *(*)(void *, char *))NZAT_End,
257 digest_printbin_stringle,
258 digest_print,
259 digest_print_string
260 }, {
261 "NZAAT",
262 8,
263 NULL,
264 (void (*)(void *))NZAT_Init,
265 (void (*)(void *, const unsigned char *, unsigned int))NZAT_Update,
266 (char *(*)(void *, char *))NZAAT_End,
267 digest_printbin_stringle,
268 digest_print,
269 digest_print_string
270 }, {
271 "OAAT",
272 8,
273 NULL,
274 (void (*)(void *))OAAT_Init,
275 (void (*)(void *, const unsigned char *, unsigned int))OAAT_Update,
276 (char *(*)(void *, char *))OAAT_End,
277 digest_printbin_stringle,
278 digest_print,
279 digest_print_string
280 }, {
281 "OAAT1",
282 8,
283 NULL,
284 (void (*)(void *))OAAT1_Init,
285 (void (*)(void *, const unsigned char *, unsigned int))OAAT_Update,
286 (char *(*)(void *, char *))OAAT_End,
287 digest_printbin_stringle,
288 digest_print,
289 digest_print_string
290 }, {
291 #ifdef __MirBSD__
292 "OAAT1S",
293 8,
294 NULL,
295 (void (*)(void *))OAAT1_Init,
296 (void (*)(void *, const unsigned char *, unsigned int))OAAT_Update,
297 (char *(*)(void *, char *))OAAT1S_End,
298 digest_printbin_stringle,
299 digest_print,
300 digest_print_string
301 }, {
302 #endif
303 "SUMA",
304 SUMA_DIGEST_LENGTH * 2,
305 NULL,
306 (void (*)(void *))SUMAInit,
307 (void (*)(void *, const unsigned char *, unsigned int))SUMAUpdate,
308 (char *(*)(void *, char *))SUMAEnd,
309 digest_printbin_stringle,
310 digest_print,
311 digest_print_string
312 }, {
313 "SFV",
314 SFV_DIGEST_LENGTH * 2,
315 NULL,
316 (void (*)(void *))SFVInit,
317 (void (*)(void *, const unsigned char *, unsigned int))SFVUpdate,
318 (char *(*)(void *, char *))SFVEnd,
319 digest_printbin_stringle,
320 digest_print_sfv,
321 digest_print_sfv
322 }, {
323 "SIZE",
324 16,
325 NULL,
326 (void (*)(void *))SIZE_Init,
327 (void (*)(void *, const unsigned char *, unsigned int))SIZE_Update,
328 (char *(*)(void *, char *))SIZE_End,
329 digest_printbin_pad,
330 digest_print,
331 digest_print_string
332 },
333 /* NHASHMOD: non-GNU functions above, GNU functions below */
334 #ifdef __MirBSD__
335 #define NHASHES_NONGNU 14
336 #else
337 #define NHASHES_NONGNU 13
338 #endif
339
340 {
341 "MD4",
342 MD4_DIGEST_LENGTH * 2,
343 NULL,
344 (void (*)(void *))MD4Init,
345 (void (*)(void *, const unsigned char *, unsigned int))MD4Update,
346 (char *(*)(void *, char *))MD4End,
347 digest_printbin_string,
348 digest_print,
349 digest_print_string
350 }, {
351 "MD5",
352 MD5_DIGEST_LENGTH * 2,
353 NULL,
354 (void (*)(void *))MD5Init,
355 (void (*)(void *, const unsigned char *, unsigned int))MD5Update,
356 (char *(*)(void *, char *))MD5End,
357 digest_printbin_string,
358 digest_print,
359 digest_print_string
360 }, {
361 "RMD160",
362 RMD160_DIGEST_LENGTH * 2,
363 NULL,
364 (void (*)(void *))RMD160Init,
365 (void (*)(void *, const unsigned char *, unsigned int))RMD160Update,
366 (char *(*)(void *, char *))RMD160End,
367 digest_printbin_string,
368 digest_print,
369 digest_print_string
370 }, {
371 "SHA1",
372 SHA1_DIGEST_LENGTH * 2,
373 NULL,
374 (void (*)(void *))SHA1Init,
375 (void (*)(void *, const unsigned char *, unsigned int))SHA1Update,
376 (char *(*)(void *, char *))SHA1End,
377 digest_printbin_string,
378 digest_print,
379 digest_print_string
380 }, {
381 "SHA256",
382 SHA256_DIGEST_LENGTH * 2,
383 NULL,
384 (void (*)(void *))SHA256_Init,
385 (void (*)(void *, const unsigned char *, unsigned int))SHA256_Update,
386 (char *(*)(void *, char *))SHA256_End,
387 digest_printbin_string,
388 digest_print,
389 digest_print_string
390 }, {
391 "SHA384",
392 SHA384_DIGEST_LENGTH * 2,
393 NULL,
394 (void (*)(void *))SHA384_Init,
395 (void (*)(void *, const unsigned char *, unsigned int))SHA384_Update,
396 (char *(*)(void *, char *))SHA384_End,
397 digest_printbin_string,
398 digest_print,
399 digest_print_string
400 }, {
401 "SHA512",
402 SHA512_DIGEST_LENGTH * 2,
403 NULL,
404 (void (*)(void *))SHA512_Init,
405 (void (*)(void *, const unsigned char *, unsigned int))SHA512_Update,
406 (char *(*)(void *, char *))SHA512_End,
407 digest_printbin_string,
408 digest_print,
409 digest_print_string
410 }, {
411 "TIGER",
412 TIGER_DIGEST_LENGTH * 2,
413 NULL,
414 (void (*)(void *))TIGERInit,
415 (void (*)(void *, const unsigned char *, unsigned int))TIGERUpdate,
416 (char *(*)(void *, char *))TIGEREnd,
417 digest_printbin_string,
418 digest_print,
419 digest_print_string
420 }, {
421 "WHIRLPOOL",
422 WHIRLPOOL_DIGEST_LENGTH * 2,
423 NULL,
424 (void (*)(void *))WHIRLPOOLInit,
425 (void (*)(void *, const unsigned char *, unsigned int))WHIRLPOOLUpdate,
426 (char *(*)(void *, char *))WHIRLPOOLEnd,
427 digest_printbin_string,
428 digest_print,
429 digest_print_string
430 }, {
431 NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
432 },
433 };
434
435 __dead void usage(void);
436 void digest_file(const char *, struct hash_functions **, int, int, int);
437 int digest_filelist(const char *, struct hash_functions *);
438 void digest_string(char *, struct hash_functions **, int);
439 void digest_test(struct hash_functions **);
440 void digest_time(struct hash_functions **);
441
442 extern const char *__progname;
443
444 int
main(int argc,char ** argv)445 main(int argc, char **argv)
446 {
447 struct hash_functions *hf = NULL, *hashes[NHASHES + 1];
448 int fl, i, error;
449 int cflag, pflag, tflag, xflag, bflag, gnuflag;
450 char *cp, *input_string;
451
452 input_string = NULL;
453 error = cflag = pflag = tflag = xflag = bflag = gnuflag = 0;
454 memset(hashes, 0, sizeof(hashes));
455 while ((fl = getopt(argc, argv, "a:bcGo:ps:tx")) != -1) {
456 switch (fl) {
457 case 'a':
458 while ((cp = strsep(&optarg, " \t,")) != NULL) {
459 if (*cp == '\0')
460 continue;
461 for (hf = functions; hf->name != NULL; hf++)
462 if (strcasecmp(hf->name, cp) == 0)
463 break;
464 if (hf->name == NULL) {
465 warnx("unknown algorithm \"%s\"", cp);
466 usage();
467 }
468 for (i = 0; i < NHASHES && hashes[i] != hf; i++)
469 if (hashes[i] == NULL) {
470 hashes[i] = hf;
471 break;
472 }
473 }
474 break;
475 case 'b':
476 bflag = 1;
477 break;
478 case 'c':
479 cflag = 1;
480 break;
481 case 'G':
482 gnuflag = 1;
483 break;
484 case 'o':
485 if (strcmp(optarg, "1") == 0)
486 hf = &functions[1];
487 else if (strcmp(optarg, "2") == 0)
488 hf = &functions[2];
489 else {
490 warnx("illegal argument to -o option");
491 usage();
492 }
493 for (i = 0; i < NHASHES && hashes[i] != hf; i++) {
494 if (hashes[i] == NULL) {
495 hashes[i] = hf;
496 break;
497 }
498 }
499 break;
500 case 'p':
501 pflag = 1;
502 break;
503 case 's':
504 input_string = optarg;
505 break;
506 case 't':
507 tflag = 1;
508 break;
509 case 'x':
510 xflag = 1;
511 break;
512 default:
513 usage();
514 }
515 }
516 argc -= optind;
517 argv += optind;
518
519 /* Most arguments are mutually exclusive */
520 fl = pflag + tflag + xflag + cflag + (input_string != NULL) +
521 bflag - (bflag & (pflag || input_string != NULL));
522 if (fl > 1 || (fl && argc && cflag == 0 && bflag == 0) ||
523 (gnuflag && fl))
524 usage();
525 if (cflag != 0 && hashes[1] != NULL)
526 errx(1, "only a single algorithm may be specified in -c mode");
527
528 /* No algorithm specified, check the name we were called as. */
529 if (hashes[0] == NULL) {
530 char *progname2;
531
532 if ((progname2 = strdup(__progname)) == NULL)
533 err(1, "out of memory");
534 if (strlen(progname2) > 3) {
535 cp = progname2 + strlen(progname2) - 3;
536 if (strcasecmp(cp, "sum") == 0) {
537 gnuflag |= 2;
538 *cp = '\0';
539 }
540 }
541
542 for (hf = functions; hf->name != NULL; hf++) {
543 if ((gnuflag & 2) &&
544 strcasecmp(hf->name, __progname) == 0) {
545 gnuflag &= ~2;
546 hashes[0] = hf;
547 break;
548 } else if (strcasecmp(hf->name, progname2) == 0) {
549 hashes[0] = hf;
550 break;
551 }
552 }
553 if (hashes[0] == NULL)
554 hashes[0] = &functions[0]; /* default to cksum */
555 if (gnuflag & 2) {
556 if (cflag || pflag || input_string || xflag) {
557 fprintf(stderr,
558 "usage: %s [-b] [-t] [file ...]\n"
559 "note: GNU syntax -c and -w are not supported.\n",
560 __progname);
561 __progname = progname2;
562 usage();
563 }
564 bflag = 0;
565 tflag = 0;
566 }
567 free(progname2);
568 }
569
570 if (tflag)
571 digest_time(hashes);
572 else if (xflag)
573 digest_test(hashes);
574 else if (input_string)
575 digest_string(input_string, hashes, bflag);
576 else if (cflag) {
577 if (argc == 0)
578 error = digest_filelist("-", hashes[0]);
579 else
580 while (argc--)
581 error += digest_filelist(*argv++, hashes[0]);
582 } else if (pflag || argc == 0)
583 digest_file("-", hashes, pflag, bflag, gnuflag);
584 else
585 while (argc--)
586 digest_file(*argv++, hashes, 0, bflag, gnuflag);
587
588 return(error ? EXIT_FAILURE : EXIT_SUCCESS);
589 }
590
591 void
digest_string(char * string,struct hash_functions ** hashes,int dobin)592 digest_string(char *string, struct hash_functions **hashes, int dobin)
593 {
594 struct hash_functions *hf;
595 char digest[MAX_DIGEST_LEN + 1];
596 union ANY_CTX context;
597
598 while (*hashes != NULL) {
599 hf = *hashes++;
600 hf->init(&context);
601 hf->update(&context, (const unsigned char *)string,
602 (unsigned int)strlen(string));
603 (void)hf->end(&context, digest);
604 cksum_addpool(digest);
605 if (dobin)
606 hf->printbin(digest);
607 else
608 hf->printstr(hf->name, string, digest);
609 }
610 }
611
612 void
digest_print(const char * name,const char * what,const char * digest)613 digest_print(const char *name, const char *what, const char *digest)
614 {
615 (void)printf("%s (%s) = %s\n", name, what, digest);
616 }
617
618 void
digest_print_string(const char * name,const char * what,const char * digest)619 digest_print_string(const char *name, const char *what, const char *digest)
620 {
621 (void)printf("%s (\"%s\") = %s\n", name, what, digest);
622 }
623
624 void
digest_print_short(const char * name,const char * what,const char * digest)625 digest_print_short(const char *name __attribute__((__unused__)),
626 const char *what, const char *digest)
627 {
628 (void)printf("%s %s\n", digest, what);
629 }
630
631 void
digest_print_sfv(const char * name,const char * what,const char * digest)632 digest_print_sfv(const char *name __attribute__((__unused__)),
633 const char *what, const char *digest)
634
635 {
636 (void)printf("%s %s\n", what, digest);
637 }
638
639 void
digest_file(const char * file,struct hash_functions ** hashes,int echo,int dobin,int dognu)640 digest_file(const char *file, struct hash_functions **hashes, int echo,
641 int dobin, int dognu)
642 {
643 struct hash_functions **hfp;
644 int fd;
645 ssize_t nread;
646 u_char data[BUFSIZ];
647 char digest[MAX_DIGEST_LEN + 1];
648
649 if (strcmp(file, "-") == 0)
650 fd = STDIN_FILENO;
651 else if ((fd = open(file, O_RDONLY, 0)) == -1) {
652 warn("cannot open %s", file);
653 return;
654 }
655
656 if (echo)
657 fflush(stdout);
658
659 for (hfp = hashes; *hfp != NULL; hfp++) {
660 if (((*hfp)->ctx = malloc(sizeof(union ANY_CTX))) == NULL)
661 err(1, NULL);
662 (*hfp)->init((*hfp)->ctx);
663 }
664 while ((nread = read(fd, data, sizeof(data))) > 0) {
665 if (echo)
666 write(STDOUT_FILENO, data, (size_t)nread);
667 for (hfp = hashes; *hfp != NULL; hfp++)
668 (*hfp)->update((*hfp)->ctx, data, (unsigned int)nread);
669 }
670 if (nread == -1) {
671 warn("%s: read error", file);
672 if (fd != STDIN_FILENO)
673 close(fd);
674 return;
675 }
676 if (fd != STDIN_FILENO)
677 close(fd);
678 for (hfp = hashes; *hfp != NULL; hfp++) {
679 (void)(*hfp)->end((*hfp)->ctx, digest);
680 free((*hfp)->ctx);
681 cksum_addpool(digest);
682 if (dobin)
683 (*hfp)->printbin(digest);
684 else if (dognu)
685 printf("%s %s\n", digest,
686 fd == STDIN_FILENO ? "-" : file);
687 else if (fd == STDIN_FILENO)
688 (void)puts(digest);
689 else
690 (*hfp)->print((*hfp)->name, file, digest);
691 }
692 }
693
694 /*
695 * Parse through the input file looking for valid lines.
696 * If one is found, use this checksum and file as a reference and
697 * generate a new checksum against the file on the filesystem.
698 * Print out the result of each comparison.
699 */
700 int
digest_filelist(const char * file,struct hash_functions * defhash)701 digest_filelist(const char *file, struct hash_functions *defhash)
702 {
703 int fd, found, error;
704 unsigned int algorithm_max, algorithm_min;
705 const char *algorithm;
706 char *filename, *checksum, *buf, *p;
707 char digest[MAX_DIGEST_LEN + 1];
708 char *lbuf = NULL;
709 FILE *fp;
710 ssize_t nread;
711 size_t len;
712 u_char data[BUFSIZ];
713 union ANY_CTX context;
714 struct hash_functions *hf;
715
716 if (strcmp(file, "-") == 0) {
717 fp = stdin;
718 } else if ((fp = fopen(file, "r")) == NULL) {
719 warn("cannot open %s", file);
720 return(1);
721 }
722
723 /* NHASHMOD: first GNU style function (and list below) */
724 if (defhash < &functions[NHASHES_NONGNU])
725 /*
726 * no GNU format for cksum, sum, sysvsum, adler32, cdb,
727 * bafh, nzat, nzaat, oaat, oaat1, oaat1s, suma, sfv, size
728 */
729 defhash = NULL;
730
731 algorithm_max = algorithm_min = strlen(functions[0].name);
732 for (hf = &functions[1]; hf->name != NULL; hf++) {
733 len = strlen(hf->name);
734 algorithm_max = MAX(algorithm_max, len);
735 algorithm_min = MIN(algorithm_min, len);
736 }
737
738 error = found = 0;
739 while ((buf = fgetln(fp, &len))) {
740 if (buf[len - 1] == '\n')
741 buf[len - 1] = '\0';
742 else {
743 if ((lbuf = malloc(len + 1)) == NULL)
744 err(1, NULL);
745
746 (void)memcpy(lbuf, buf, len);
747 lbuf[len] = '\0';
748 buf = lbuf;
749 }
750 while (isspace(*buf))
751 buf++;
752
753 /*
754 * Crack the line into an algorithm, filename, and checksum.
755 * Lines are of the form:
756 * ALGORITHM (FILENAME) = CHECKSUM
757 *
758 * Fallback on GNU form:
759 * CHECKSUM FILENAME
760 */
761 p = strchr(buf, ' ');
762 if (p != NULL && *(p + 1) == '(') {
763 /* BSD form */
764 *p = '\0';
765 algorithm = buf;
766 len = strlen(algorithm);
767 if (len > algorithm_max || len < algorithm_min)
768 continue;
769
770 filename = p + 2;
771 p = strrchr(filename, ')');
772 if (p == NULL || strncmp(p + 1, " = ", (size_t)3) != 0)
773 continue;
774 *p = '\0';
775
776 checksum = p + 4;
777 p = strpbrk(checksum, " \t\r");
778 if (p != NULL)
779 *p = '\0';
780
781 /*
782 * Check that the algorithm is one we recognize.
783 */
784 for (hf = functions; hf->name != NULL; hf++) {
785 if (strcmp(algorithm, hf->name) == 0)
786 break;
787 }
788 if (hf->name == NULL ||
789 strlen(checksum) != hf->digestlen)
790 continue;
791 } else {
792 /* could be GNU form */
793 if ((hf = defhash) == NULL)
794 continue;
795 algorithm = hf->name;
796 checksum = buf;
797 if ((p = strchr(checksum, ' ')) == NULL)
798 continue;
799 *p++ = '\0';
800 while (isspace(*p))
801 p++;
802 if (*p == '\0')
803 continue;
804 filename = p;
805 p = strpbrk(filename, "\t\r");
806 if (p != NULL)
807 *p = '\0';
808 }
809
810 if ((fd = open(filename, O_RDONLY, 0)) == -1) {
811 warn("cannot open %s", filename);
812 (void)printf("(%s) %s: FAILED\n", algorithm, filename);
813 error = 1;
814 continue;
815 }
816
817 found = 1;
818 hf->init(&context);
819 while ((nread = read(fd, data, sizeof(data))) > 0)
820 hf->update(&context, data, (unsigned int)nread);
821 if (nread == -1) {
822 warn("%s: read error", file);
823 error = 1;
824 close(fd);
825 continue;
826 }
827 close(fd);
828 (void)hf->end(&context, digest);
829 cksum_addpool(digest);
830
831 if (strcmp(checksum, digest) == 0)
832 (void)printf("(%s) %s: OK\n", algorithm, filename);
833 else
834 (void)printf("(%s) %s: FAILED\n", algorithm, filename);
835 }
836 if (fp != stdin)
837 fclose(fp);
838 if (!found)
839 warnx("%s: no properly formatted checksum lines found", file);
840 if (lbuf != NULL)
841 free(lbuf);
842 return(error || !found);
843 }
844
845 #define TEST_BLOCK_LEN 10000
846 #define TEST_BLOCK_COUNT 10000
847
848 #ifndef timersub
849 #define timersub(tvp, uvp, vvp) \
850 do { \
851 (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
852 (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
853 if ((vvp)->tv_usec < 0) { \
854 (vvp)->tv_sec--; \
855 (vvp)->tv_usec += 1000000; \
856 } \
857 } while (0)
858 #endif
859
860 void
digest_time(struct hash_functions ** hashes)861 digest_time(struct hash_functions **hashes)
862 {
863 struct hash_functions *hf;
864 struct timeval start, stop, res;
865 union ANY_CTX context;
866 unsigned i;
867 u_char data[TEST_BLOCK_LEN];
868 char digest[MAX_DIGEST_LEN + 1];
869 double elapsed;
870
871 while (*hashes != NULL) {
872 hf = *hashes++;
873 (void)printf("%s time trial. Processing %d %d-byte blocks...",
874 hf->name, TEST_BLOCK_COUNT, TEST_BLOCK_LEN);
875 fflush(stdout);
876
877 /* Initialize data based on block number. */
878 for (i = 0; i < TEST_BLOCK_LEN; i++)
879 data[i] = (u_char)(i & 0xff);
880
881 gettimeofday(&start, NULL);
882 hf->init(&context);
883 for (i = 0; i < TEST_BLOCK_COUNT; i++)
884 hf->update(&context, data, TEST_BLOCK_LEN);
885 (void)hf->end(&context, digest);
886 gettimeofday(&stop, NULL);
887 timersub(&stop, &start, &res);
888 elapsed = res.tv_sec + res.tv_usec / 1000000.0;
889
890 (void)printf("\nDigest = %s\n", digest);
891 (void)printf("Time = %f seconds\n", elapsed);
892 (void)printf("Speed = %f bytes/second\n",
893 TEST_BLOCK_LEN * TEST_BLOCK_COUNT / elapsed);
894 }
895 }
896
897 void
digest_test(struct hash_functions ** hashes)898 digest_test(struct hash_functions **hashes)
899 {
900 struct hash_functions *hf;
901 union ANY_CTX context;
902 int i;
903 char digest[MAX_DIGEST_LEN + 1];
904 unsigned char buf[1000];
905 const char *test_strings[] = {
906 "",
907 "a",
908 "abc",
909 "message digest",
910 "abcdefghijklmnopqrstuvwxyz",
911 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
912 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
913 "0123456789",
914 "12345678901234567890123456789012345678901234567890123456789"
915 "012345678901234567890",
916 };
917
918 while (*hashes != NULL) {
919 hf = *hashes++;
920 (void)printf("%s test suite:\n", hf->name);
921
922 for (i = 0; i < 8; i++) {
923 hf->init(&context);
924 hf->update((void *)&context,
925 (unsigned const char *)test_strings[i],
926 (unsigned int)strlen(test_strings[i]));
927 (void)hf->end(&context, digest);
928 hf->printstr(hf->name, test_strings[i], digest);
929 }
930
931 /* Now simulate a string of a million 'a' characters. */
932 memset(buf, 'a', sizeof(buf));
933 hf->init(&context);
934 for (i = 0; i < 1000; i++)
935 hf->update(&context, buf,
936 (unsigned int)sizeof(buf));
937 (void)hf->end(&context, digest);
938 hf->print(hf->name, "one million 'a' characters",
939 digest);
940 }
941 }
942
943 void
usage(void)944 usage(void)
945 {
946 fprintf(stderr, "usage: %s [-[b]p | -t | -x | -c [cklst ...] | "
947 "-[b]s string | [-bG] file ...]\n", __progname);
948 if (strcmp(__progname, "cksum") == 0)
949 fprintf(stderr, " [-a algorithms]] [-o 1 | 2]\n");
950
951 exit(EXIT_FAILURE);
952 }
953
954 void
digest_printbin_pad(const char * digest)955 digest_printbin_pad(const char *digest)
956 {
957 uint64_t one, two;
958 char *c;
959
960 one = strtoll(digest, &c, 10);
961 if (*c) {
962 two = strtoll(++c, NULL, 10);
963 if (asprintf(&c, "%016llX%016llX", one, two) == -1)
964 return;
965 } else if (asprintf(&c, "%016llX", one) == -1)
966 return;
967 digest_printbin_string(c);
968 free(c);
969 }
970
971 void
digest_printbin_string(const char * digest)972 digest_printbin_string(const char *digest)
973 {
974 int i, j, k;
975
976 for (i = 0; i < (ssize_t)(strlen(digest)/2); ++i) {
977 j = digest[i * 2] - 0x30;
978 k = digest[i * 2 + 1] - 0x30;
979 if ((j < 0) || (k < 0))
980 break;
981 j = (j > 9) ? (((j - 7) > 15) ? (j - 0x27) : (j - 7)) : j;
982 k = (k > 9) ? (((k - 7) > 15) ? (k - 0x27) : (k - 7)) : k;
983 if ((j < 0) || (k < 0) || (j > 15) || (k > 15))
984 break;
985 putchar((j << 4) | k);
986 }
987 }
988
989 void
digest_printbin_stringle(const char * digest)990 digest_printbin_stringle(const char *digest)
991 {
992 uint32_t dgst;
993 char *c;
994
995 dgst = strtoul(digest, NULL, 16);
996 if (asprintf(&c, "%02X%02X%02X%02X",
997 dgst & 0xff, (dgst >> 8) & 0xff,
998 (dgst >> 16) & 0xff, dgst >> 24) == -1)
999 return;
1000 digest_printbin_string(c);
1001 free(c);
1002 }
1003
1004 void
SIZE_Init(SIZE_CTX * ctx)1005 SIZE_Init(SIZE_CTX *ctx)
1006 {
1007 *ctx = 0;
1008 }
1009
1010 void
SIZE_Update(SIZE_CTX * ctx,const uint8_t * buf,size_t n)1011 SIZE_Update(SIZE_CTX *ctx, const uint8_t *buf __attribute__((__unused__)), size_t n)
1012 {
1013 *ctx += n;
1014 }
1015
1016 char *
SIZE_End(SIZE_CTX * ctx,char * digest)1017 SIZE_End(SIZE_CTX *ctx, char *digest)
1018 {
1019 if (digest == NULL) {
1020 if (asprintf(&digest, "%llu", *ctx) == -1)
1021 return (NULL);
1022 } else
1023 snprintf(digest, 21, "%llu", *ctx);
1024
1025 return (digest);
1026 }
1027
1028 void
CDB_Init(CDB_CTX * ctx)1029 CDB_Init(CDB_CTX *ctx)
1030 {
1031 *ctx = 5381;
1032 }
1033
1034 void
CDB_Update(CDB_CTX * ctx,const uint8_t * buf,size_t n)1035 CDB_Update(CDB_CTX *ctx, const uint8_t *buf, size_t n)
1036 {
1037 register uint32_t h;
1038
1039 h = *ctx;
1040 while (n--)
1041 h = ((h << 5) + h) ^ *buf++;
1042 *ctx = h;
1043 }
1044
1045 char *
ucase_End(CDB_CTX * ctx,char * digest)1046 ucase_End(CDB_CTX *ctx, char *digest)
1047 {
1048 if (digest == NULL) {
1049 if (asprintf(&digest, "%08X", *ctx) == -1)
1050 return (NULL);
1051 } else
1052 snprintf(digest, 17, "%08X", *ctx);
1053
1054 return (digest);
1055 }
1056
1057 void
OAAT_Init(OAATS_CTX * ctx)1058 OAAT_Init(OAATS_CTX *ctx)
1059 {
1060 ctx->crc = 0;
1061 ctx->len = 0;
1062 }
1063
1064 void
OAAT1_Init(OAATS_CTX * ctx)1065 OAAT1_Init(OAATS_CTX *ctx)
1066 {
1067 ctx->crc = 0x100;
1068 ctx->len = 0;
1069 }
1070
1071 void
OAAT_Update(OAATS_CTX * ctx,const uint8_t * buf,size_t n)1072 OAAT_Update(OAATS_CTX *ctx, const uint8_t *buf, size_t n)
1073 {
1074 register uint32_t h;
1075
1076 ctx->len += n;
1077 h = ctx->crc;
1078 while (n--) {
1079 h += *buf++;
1080 h += h << 10;
1081 h ^= h >> 6;
1082 }
1083 ctx->crc = h;
1084 }
1085
1086 void
OAAT_Final(OAATS_CTX * ctx)1087 OAAT_Final(OAATS_CTX *ctx)
1088 {
1089 register uint32_t h;
1090
1091 h = ctx->crc;
1092 h += h << 3;
1093 h ^= h >> 11;
1094 h += h << 15;
1095 ctx->crc = h;
1096 }
1097
1098 #ifdef __MirBSD__
1099 char *
OAAT1S_End(OAATS_CTX * ctx,char * digest)1100 OAAT1S_End(OAATS_CTX *ctx, char *digest)
1101 {
1102 uint8_t le_len[8];
1103 uint64_t bits;
1104
1105 bits = ctx->len << 3;
1106 le_len[0] = bits & 0xFF; bits >>= 8;
1107 le_len[1] = bits & 0xFF; bits >>= 8;
1108 le_len[2] = bits & 0xFF; bits >>= 8;
1109 le_len[3] = bits & 0xFF; bits >>= 8;
1110 le_len[4] = bits & 0xFF; bits >>= 8;
1111 le_len[5] = bits & 0xFF; bits >>= 8;
1112 le_len[6] = bits & 0xFF; bits >>= 8;
1113 le_len[7] = bits;
1114
1115 /* look, ma! mirabilos can do nicer formulas than Markus Friedl */
1116 OAAT_Update(ctx, RFC1321_padding, 64 - ((ctx->len + 8) & 63));
1117 OAAT_Update(ctx, le_len, 8);
1118
1119 return (OAAT_End(ctx, digest));
1120 }
1121 #endif
1122
1123 char *
OAAT_End(OAATS_CTX * ctx,char * digest)1124 OAAT_End(OAATS_CTX *ctx, char *digest)
1125 {
1126 OAAT_Final(ctx);
1127 return (ucase_End(&ctx->crc, digest));
1128 }
1129
1130 void
NZAT_Init(NZAT_CTX * ctx)1131 NZAT_Init(NZAT_CTX *ctx)
1132 {
1133 *ctx = 0;
1134 }
1135
1136 void
NZAT_Update(NZAT_CTX * ctx,const uint8_t * buf,size_t n)1137 NZAT_Update(NZAT_CTX *ctx, const uint8_t *buf, size_t n)
1138 {
1139 register uint32_t h;
1140
1141 h = *ctx;
1142 while (n--) {
1143 h += (uint8_t)(*buf++);
1144 ++h;
1145 h += h << 10;
1146 h ^= h >> 6;
1147 }
1148 *ctx = h;
1149 }
1150
1151 void
NZAT_Final(NZAT_CTX * ctx)1152 NZAT_Final(NZAT_CTX *ctx)
1153 {
1154 register uint32_t h;
1155
1156 h = *ctx;
1157 if (h == 0) {
1158 ++h;
1159 } else {
1160 h += h << 10;
1161 h ^= h >> 6;
1162 h += h << 3;
1163 h ^= h >> 11;
1164 h += h << 15;
1165 }
1166 *ctx = h;
1167 }
1168
1169 void
NZAAT_Final(NZAT_CTX * ctx)1170 NZAAT_Final(NZAT_CTX *ctx)
1171 {
1172 register uint32_t h;
1173
1174 h = *ctx;
1175 h += h << 10;
1176 h ^= h >> 6;
1177 h += h << 3;
1178 h ^= h >> 11;
1179 h += h << 15;
1180 *ctx = h;
1181 }
1182
1183 char *
NZAT_End(NZAT_CTX * ctx,char * digest)1184 NZAT_End(NZAT_CTX *ctx, char *digest)
1185 {
1186 NZAT_Final(ctx);
1187 return (ucase_End(ctx, digest));
1188 }
1189
1190 char *
NZAAT_End(NZAT_CTX * ctx,char * digest)1191 NZAAT_End(NZAT_CTX *ctx, char *digest)
1192 {
1193 NZAAT_Final(ctx);
1194 return (ucase_End(ctx, digest));
1195 }
1196
1197 #define BAFHror_md5(eax,cl) (((eax) >> (cl)) | ((eax) << (32 - (cl))))
1198
1199 #define BAFHFinish_md5(h) do { \
1200 register uint32_t BAFHFinish_v; \
1201 \
1202 BAFHFinish_v = ((h) >> 7) & 0x01010101U; \
1203 BAFHFinish_v += BAFHFinish_v << 1; \
1204 BAFHFinish_v += BAFHFinish_v << 3; \
1205 BAFHFinish_v ^= ((h) << 1) & 0xFEFEFEFEU; \
1206 \
1207 BAFHFinish_v ^= BAFHror_md5(BAFHFinish_v, 8); \
1208 BAFHFinish_v ^= ((h) = BAFHror_md5((h), 8)); \
1209 BAFHFinish_v ^= ((h) = BAFHror_md5((h), 8)); \
1210 (h) = BAFHror_md5((h), 8) ^ BAFHFinish_v; \
1211 } while (/* CONSTCOND */ 0)
1212
1213 char *
BAFH_End(BAFH_CTX * ctx,char * digest)1214 BAFH_End(BAFH_CTX *ctx, char *digest)
1215 {
1216 register uint32_t h;
1217
1218 h = *ctx;
1219 BAFHFinish_md5(h);
1220 *ctx = h;
1221 return (ucase_End(ctx, digest));
1222 }
1223
1224 /*
1225 * Table-driven version of the following polynomial from POSIX 1003.2:
1226 * G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 +
1227 * x^7 + x^5 + x^4 + x^2 + x + 1
1228 */
1229 static const uint32_t crc32tab[] = {
1230 0x00000000U,
1231 0x04c11db7U, 0x09823b6eU, 0x0d4326d9U, 0x130476dcU, 0x17c56b6bU,
1232 0x1a864db2U, 0x1e475005U, 0x2608edb8U, 0x22c9f00fU, 0x2f8ad6d6U,
1233 0x2b4bcb61U, 0x350c9b64U, 0x31cd86d3U, 0x3c8ea00aU, 0x384fbdbdU,
1234 0x4c11db70U, 0x48d0c6c7U, 0x4593e01eU, 0x4152fda9U, 0x5f15adacU,
1235 0x5bd4b01bU, 0x569796c2U, 0x52568b75U, 0x6a1936c8U, 0x6ed82b7fU,
1236 0x639b0da6U, 0x675a1011U, 0x791d4014U, 0x7ddc5da3U, 0x709f7b7aU,
1237 0x745e66cdU, 0x9823b6e0U, 0x9ce2ab57U, 0x91a18d8eU, 0x95609039U,
1238 0x8b27c03cU, 0x8fe6dd8bU, 0x82a5fb52U, 0x8664e6e5U, 0xbe2b5b58U,
1239 0xbaea46efU, 0xb7a96036U, 0xb3687d81U, 0xad2f2d84U, 0xa9ee3033U,
1240 0xa4ad16eaU, 0xa06c0b5dU, 0xd4326d90U, 0xd0f37027U, 0xddb056feU,
1241 0xd9714b49U, 0xc7361b4cU, 0xc3f706fbU, 0xceb42022U, 0xca753d95U,
1242 0xf23a8028U, 0xf6fb9d9fU, 0xfbb8bb46U, 0xff79a6f1U, 0xe13ef6f4U,
1243 0xe5ffeb43U, 0xe8bccd9aU, 0xec7dd02dU, 0x34867077U, 0x30476dc0U,
1244 0x3d044b19U, 0x39c556aeU, 0x278206abU, 0x23431b1cU, 0x2e003dc5U,
1245 0x2ac12072U, 0x128e9dcfU, 0x164f8078U, 0x1b0ca6a1U, 0x1fcdbb16U,
1246 0x018aeb13U, 0x054bf6a4U, 0x0808d07dU, 0x0cc9cdcaU, 0x7897ab07U,
1247 0x7c56b6b0U, 0x71159069U, 0x75d48ddeU, 0x6b93dddbU, 0x6f52c06cU,
1248 0x6211e6b5U, 0x66d0fb02U, 0x5e9f46bfU, 0x5a5e5b08U, 0x571d7dd1U,
1249 0x53dc6066U, 0x4d9b3063U, 0x495a2dd4U, 0x44190b0dU, 0x40d816baU,
1250 0xaca5c697U, 0xa864db20U, 0xa527fdf9U, 0xa1e6e04eU, 0xbfa1b04bU,
1251 0xbb60adfcU, 0xb6238b25U, 0xb2e29692U, 0x8aad2b2fU, 0x8e6c3698U,
1252 0x832f1041U, 0x87ee0df6U, 0x99a95df3U, 0x9d684044U, 0x902b669dU,
1253 0x94ea7b2aU, 0xe0b41de7U, 0xe4750050U, 0xe9362689U, 0xedf73b3eU,
1254 0xf3b06b3bU, 0xf771768cU, 0xfa325055U, 0xfef34de2U, 0xc6bcf05fU,
1255 0xc27dede8U, 0xcf3ecb31U, 0xcbffd686U, 0xd5b88683U, 0xd1799b34U,
1256 0xdc3abdedU, 0xd8fba05aU, 0x690ce0eeU, 0x6dcdfd59U, 0x608edb80U,
1257 0x644fc637U, 0x7a089632U, 0x7ec98b85U, 0x738aad5cU, 0x774bb0ebU,
1258 0x4f040d56U, 0x4bc510e1U, 0x46863638U, 0x42472b8fU, 0x5c007b8aU,
1259 0x58c1663dU, 0x558240e4U, 0x51435d53U, 0x251d3b9eU, 0x21dc2629U,
1260 0x2c9f00f0U, 0x285e1d47U, 0x36194d42U, 0x32d850f5U, 0x3f9b762cU,
1261 0x3b5a6b9bU, 0x0315d626U, 0x07d4cb91U, 0x0a97ed48U, 0x0e56f0ffU,
1262 0x1011a0faU, 0x14d0bd4dU, 0x19939b94U, 0x1d528623U, 0xf12f560eU,
1263 0xf5ee4bb9U, 0xf8ad6d60U, 0xfc6c70d7U, 0xe22b20d2U, 0xe6ea3d65U,
1264 0xeba91bbcU, 0xef68060bU, 0xd727bbb6U, 0xd3e6a601U, 0xdea580d8U,
1265 0xda649d6fU, 0xc423cd6aU, 0xc0e2d0ddU, 0xcda1f604U, 0xc960ebb3U,
1266 0xbd3e8d7eU, 0xb9ff90c9U, 0xb4bcb610U, 0xb07daba7U, 0xae3afba2U,
1267 0xaafbe615U, 0xa7b8c0ccU, 0xa379dd7bU, 0x9b3660c6U, 0x9ff77d71U,
1268 0x92b45ba8U, 0x9675461fU, 0x8832161aU, 0x8cf30badU, 0x81b02d74U,
1269 0x857130c3U, 0x5d8a9099U, 0x594b8d2eU, 0x5408abf7U, 0x50c9b640U,
1270 0x4e8ee645U, 0x4a4ffbf2U, 0x470cdd2bU, 0x43cdc09cU, 0x7b827d21U,
1271 0x7f436096U, 0x7200464fU, 0x76c15bf8U, 0x68860bfdU, 0x6c47164aU,
1272 0x61043093U, 0x65c52d24U, 0x119b4be9U, 0x155a565eU, 0x18197087U,
1273 0x1cd86d30U, 0x029f3d35U, 0x065e2082U, 0x0b1d065bU, 0x0fdc1becU,
1274 0x3793a651U, 0x3352bbe6U, 0x3e119d3fU, 0x3ad08088U, 0x2497d08dU,
1275 0x2056cd3aU, 0x2d15ebe3U, 0x29d4f654U, 0xc5a92679U, 0xc1683bceU,
1276 0xcc2b1d17U, 0xc8ea00a0U, 0xd6ad50a5U, 0xd26c4d12U, 0xdf2f6bcbU,
1277 0xdbee767cU, 0xe3a1cbc1U, 0xe760d676U, 0xea23f0afU, 0xeee2ed18U,
1278 0xf0a5bd1dU, 0xf464a0aaU, 0xf9278673U, 0xfde69bc4U, 0x89b8fd09U,
1279 0x8d79e0beU, 0x803ac667U, 0x84fbdbd0U, 0x9abc8bd5U, 0x9e7d9662U,
1280 0x933eb0bbU, 0x97ffad0cU, 0xafb010b1U, 0xab710d06U, 0xa6322bdfU,
1281 0xa2f33668U, 0xbcb4666dU, 0xb8757bdaU, 0xb5365d03U, 0xb1f740b4U
1282 };
1283
1284 #define UPDATE(crc, byte) do { \
1285 (crc) = ((crc) << 8) ^ crc32tab[((crc) >> 24) ^ (byte)]; \
1286 } while(/* CONSTCOND */ 0)
1287
1288 void
CKSUM_Update(CKSUM_CTX * ctx,const unsigned char * buf,size_t len)1289 CKSUM_Update(CKSUM_CTX *ctx, const unsigned char *buf, size_t len)
1290 {
1291 size_t i;
1292
1293 for (i = 0; i < len; i++)
1294 UPDATE(ctx->crc, buf[i]);
1295 ctx->len += len;
1296 }
1297
1298 void
CKSUM_Final(CKSUM_CTX * ctx)1299 CKSUM_Final(CKSUM_CTX *ctx)
1300 {
1301 off_t len = ctx->len;
1302
1303 /* add in number of bytes read and finish */
1304 while (len != 0) {
1305 UPDATE(ctx->crc, len & 0xff);
1306 len >>= 8;
1307 }
1308 ctx->crc = ~ctx->crc;
1309 }
1310 #undef UPDATE
1311
1312 char *
CKSUM_End(CKSUM_CTX * ctx,char * outstr)1313 CKSUM_End(CKSUM_CTX *ctx, char *outstr)
1314 {
1315 CKSUM_Final(ctx);
1316 return (ulld_End(ctx, outstr));
1317 }
1318
1319 char *
ulld_End(CKSUM_CTX * ctx,char * outstr)1320 ulld_End(CKSUM_CTX *ctx, char *outstr)
1321 {
1322 if (outstr == NULL) {
1323 if (asprintf(&outstr, "%u %lld", ctx->crc,
1324 (int64_t)ctx->len) == -1)
1325 return (NULL);
1326 } else {
1327 (void)snprintf(outstr, (size_t)CKSUM_DIGEST_STRING_LENGTH,
1328 "%u %lld", ctx->crc, (int64_t)ctx->len);
1329 }
1330
1331 return (outstr);
1332 }
1333
1334 void
SUM_Update(SUM_CTX * ctx,const unsigned char * buf,size_t len)1335 SUM_Update(SUM_CTX *ctx, const unsigned char *buf, size_t len)
1336 {
1337 size_t i;
1338
1339 for (i = 0; i < len; i++) {
1340 ctx->crc = ((ctx->crc >> 1) + ((ctx->crc & 1) << 15) + buf[i]);
1341 ctx->crc &= 0xffff;
1342 }
1343 ctx->len += len;
1344 }
1345
1346 void
SUM_Final(SUM_CTX * ctx)1347 SUM_Final(SUM_CTX *ctx)
1348 {
1349 ctx->len = (ctx->len + 1023) / 1024; /* convert to 1 KiB blocks */
1350 }
1351
1352 char *
SUM_End(SUM_CTX * ctx,char * outstr)1353 SUM_End(SUM_CTX *ctx, char *outstr)
1354 {
1355 SUM_Final(ctx);
1356 return (ulld_End(ctx, outstr));
1357 }
1358
1359 void
SYSVSUM_Update(SYSVSUM_CTX * ctx,const unsigned char * buf,size_t len)1360 SYSVSUM_Update(SYSVSUM_CTX *ctx, const unsigned char *buf, size_t len)
1361 {
1362 size_t i;
1363
1364 for (i = 0; i < len; i++)
1365 ctx->crc += buf[i];
1366 ctx->len += len;
1367 }
1368
1369 void
SYSVSUM_Final(SYSVSUM_CTX * ctx)1370 SYSVSUM_Final(SYSVSUM_CTX *ctx)
1371 {
1372 ctx->crc = (ctx->crc & 0xffff) + (ctx->crc >> 16);
1373 ctx->crc = (ctx->crc & 0xffff) + (ctx->crc >> 16);
1374 ctx->len = (ctx->len + 511) / 512; /* convert to 512 byte blocks */
1375 }
1376
1377 char *
SYSVSUM_End(SYSVSUM_CTX * ctx,char * outstr)1378 SYSVSUM_End(SYSVSUM_CTX *ctx, char *outstr)
1379 {
1380 SYSVSUM_Final(ctx);
1381 return (ulld_End(ctx, outstr));
1382 }
1383
1384 void
cksum_addpool(const char * s)1385 cksum_addpool(const char *s)
1386 {
1387 #if defined(arc4random_pushb_fast)
1388 arc4random_pushb_fast(s, strlen(s) + 1);
1389 #else
1390 ADLER32_CTX tmp;
1391
1392 ADLER32Update(&tmp, (const uint8_t *)s, strlen(s));
1393 #if defined(arc4random_pushk)
1394 arc4random_pushk(&tmp, sizeof (ADLER32_CTX));
1395 #elif defined(MirBSD) && (MirBSD > 0x09A1)
1396 arc4random_pushb(&tmp, sizeof (ADLER32_CTX));
1397 #endif
1398 #endif
1399 }
1400