modified: SpatialOmicsCoord.py
[GalaxyCodeBases.git] / c_cpp / etc / md5_sha / shsdrvr.c
blobf7473b0e5832492008c131eaaac0deeb4a9bf23a
1 /*
2 * shsdrvr - old shs driver code
4 * @(#) $Revision: 13.4 $
5 * @(#) $Id: shsdrvr.c,v 13.4 2010/10/12 21:09:35 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/hash/RCS/shsdrvr.c,v $
8 **************************************************************************
9 * This version implements the old Secure Hash Algorithm specified by *
10 * (FIPS Pub 180). This version is kept for backward compatibility with *
11 * shs version 2.10.1. See the shs utility for the new standard. *
12 **************************************************************************
14 * This file was written by Landon Curt Noll.
16 * This code has been placed in the public domain. Please do not
17 * copyright this code.
19 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO
20 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MER-
21 * CHANTABILITY AND FITNESS. IN NO EVENT SHALL LANDON CURT
22 * NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
23 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
25 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 * chongo (was here) /\oo/\
29 * http://www.isthe.com/chongo/index.html
31 * Share and enjoy! :-)
33 ***
35 * NOTE: The version information below refers to all shs code, not
36 * just this file. In particular, this file was created by
37 * Landon Curt Noll.
39 * Version 1.1: 02 Sep 1992? original authors
40 * This code is based on code by Peter C. Gutmann. Much thanks goes
41 * to Peter C. Gutman (pgut1@cs.aukuni.ac.nz) , Shawn A. Clifford
42 * (sac@eng.ufl.edu), Pat Myrto (pat@rwing.uucp) and others who wrote
43 * and/or worked on the original code.
45 * Version 2.1: 31 Dec 1993 Landon Curt Noll
46 * Reformatted, performance improvements and bug fixes
48 * Version 2.2: 02 Jan 1994 Landon Curt Noll
49 * fixed -p usage
50 * better error messages
51 * added -c help
52 * added -c 0 (concatenation)
53 * reordered -i stat buffer pre-pending
55 * Version 2.3: 03 Jan 1994 Landon Curt Noll
56 * added -c 1 (side by side)
57 * added -c 2 (even force to be odd)
58 * added -c x (shs dual test suite)
59 * changed -c help to be -c h
60 * changed -c operand to type[,opt[,...]]
61 * prefix & string ABI now can take arbitrary binary data
62 * fixed memory leak
63 * fixed even/odd byte split bug
64 * added -P file
65 * added -q
66 * added UNROLL_LOOPS to control shs.c loop unrolling
67 * major performance improvements
69 * Version 2.4: 05 Jan 1994 Landon Curt Noll
70 * renamed calc mode to dual mode
71 * removed all -c code
72 * added -d (dual digests, space separated)
73 * rewrote most of the file, string and stream logic using shsdual code
75 * Version 2.5: 08 Jan 1994 Landon Curt Noll
76 * added (new) -c (print 0x in front of digests)
77 * removed st_blksize and st_blocks from -i preprocessing data
78 * only print .0 suffix if -i and digesting a file
79 * non-zero edit codes are now unique
80 * changed the dual test suite (shorter, added non alpha numeric chars)
81 * -i requires filenames
82 * fixed @(#) what string code
83 * boolean logic simplication by Rich Schroeppel (rcs@cs.arizona.edu)
84 * on the fly in a circular buffer by Colin Plumb (colin@nyx10.cs.du.edu)
86 * Version 2.6: 11 Jan 1994 Landon Curt Noll
87 * Merged the shs and md5 Makefiles to build both in the same directory
88 * alignment and byte order performance improvements
89 * eliminate wateful memory copies
90 * shs transform contains no function calls
91 * beta release
93 * Version 2.7: 13 Jan 1994 Landon Curt Noll
94 * code cleanup
95 * chunk is now 64 bytes, block is determined by blocking factor
96 * magic 64 and 64 related values defined in terms of #defines
97 * added blocking code (-b block_len)
98 * added xor feedback code (-f)
99 * added xor feedback and block options to performance test
100 * performance improvements
102 * Version 2.8: 16 Jan 1994 Landon Curt Noll
103 * code cleanup
104 * performance improvements
105 * removed blocking and feedback code
106 * count bytes in driver, convert to 64 bit count in final transform
107 * added debug mode
108 * handle read errors and EOF better
109 * prefix strings not multiple of 64 bytes in length do not slow down hash
110 * renumbered exit codes
111 * fixed dual digest split bug
112 * byte sex swapping is now controlled thru the SHS_TRANSFORM macro
113 * shsTransform() is now called via the SHS_TRANSFORM macro
115 * Version 2.9: 12 Feb 1994 Landon Curt Noll
116 * prep for beta release
117 * removed all feedback code
119 * Version 2.10: 25 Mar 1994 Landon Curt Noll
120 * must_align catchs signal to detect misaligned access
122 * Version 3.1: 09 Mar 1995 Landon Curt Noll
123 * Bumped version from 2.10 to 3.1.
125 * Moved stream and file routines into shsio.c.
127 * Version 3.2: 17 Nov 1995 Landon Curt Noll
128 * Fixed help string.
130 * Added multiple digests capability instead of just dual. Added
131 * -m num to denote 2 or more multiple digests.
133 * Added -C to prevent spaces (and later 0x if -c) between multi digests.
135 * Version 3.3: 01 Sep 1996 Landon Curt Noll
136 * Provide sha as well as shs.
138 * Version 4.1: 13 Aug 2006 Landon Curt Noll
139 * Port to ANSI C.
140 * Fixed all known compile warnings.
141 * Allow access to the internal hash transform function.
142 * The shsTransform() function performs the byte swapping now.
143 * Eliminated use of SHS_TRANSFORM macro.
144 * Improved the way -v prints version. Now -v prints the RCS version,
145 * not version listed in the above comment.
148 #include <stdio.h>
149 #include <stdlib.h>
150 #include <string.h>
151 #include <sys/types.h>
152 #include <time.h>
153 #include <sys/time.h>
154 #include <sys/resource.h>
155 #include <unistd.h>
156 #include "shs.h"
158 /* size of test in megabytes */
159 #define TEST_MEG 16
161 /* number of chunks to process */
162 #define TEST_CHUNKS (TEST_MEG*1024*1024/SHS_READSIZE)
164 /* SHS1 test suite strings */
165 #define ENTRY(str) {(BYTE *)str, NULL, sizeof(str)-1}
166 struct shs_test {
167 BYTE *ro_data; /* read only string data or NULL to test */
168 BYTE *data; /* data or NULL to test */
169 int len; /* length of data */
170 } shs_test_data[] = {
171 ENTRY(""),
172 ENTRY("a"),
173 ENTRY("abc"),
174 ENTRY("message digest"),
175 ENTRY("abcdefghijklmnopqrstuvwxyz"),
176 ENTRY("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
177 ENTRY("12345678901234567890123456789012345678901234567890123456789012345678901234567890"),
178 ENTRY("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
180 #define MAX_SHS_TEST_DATA ((int)(sizeof(shs_test_data)/sizeof(shs_test_data[0])))
182 /* shs test filenames */
183 char *shs_test_file[] = {
184 "file1",
185 "file2",
187 #define MAX_SHS_TEST_FILE ((int)(sizeof(shs_test_file)/sizeof(shs_test_file[0])))
189 /* where the test files are located by default */
190 #if !defined(TLIB)
191 #define TLIB "."
192 #endif
194 /* Prototypes of the static functions */
195 static void shsOutput(char*, int, int, int, SHS_INFO*);
196 static int shsPreFileRead(char*, BYTE**);
197 static void shsTestSuite(void);
198 static void shsHelp(void);
200 /* global variables */
201 int c_flag = 0; /* 1 => print C style digest with leading 0x */
202 int i_flag = 0; /* 1 => process inode & filename */
203 int q_flag = 0; /* 1 => print the digest only */
204 int debug = 0; /* 1 => add debug */
205 char *program = "<program name unknown>"; /* our name */
209 * shsOutput - output the digest
211 * given:
212 * str print string after digest, NULL => none
213 * quot 1 => surround str with a double quotes
214 * hexhdr 1 => print 0x before the hex value
215 * trail 1 => print a trailing ".0"
216 * dig current digest
218 static void
219 shsOutput(char *str, int quot, int hexhdr, int trail, SHS_INFO *dig)
222 * finalize the digest
224 shsFinal(dig);
225 #if defined(DEBUG)
226 if (debug) {
227 fprintf(stderr, "DEBUG: octet count: %lld\n", dig->octets);
228 fprintf(stderr, "DEBUG: octet count: 0x%016llx\n", dig->octets);
229 fprintf(stderr, "DEBUG: bit count: %lld\n", dig->octets<<3);
230 fprintf(stderr, "DEBUG: bit count: 0x%016llx\n", dig->octets<<3);
232 #endif
235 * print the digest
237 shsPrint(hexhdr, trail, dig);
238 if (str && !q_flag) {
239 if (quot) {
240 printf(" \"%s\"\n", str);
241 } else {
242 printf(" %s\n", str);
244 } else {
245 putchar('\n');
247 fflush(stdout);
252 * shsPrint - print a digest in hex
254 * Prints message digest buffer in shsInfo as 40 hexadecimal digits. Order is
255 * from low-order byte to high-order byte of digest. Each byte is printed
256 * with high-order hexadecimal digit first.
258 * If hexhdr, then print a leading "0x". If trail, then print a trailing ".0".
260 * given:
261 * hexhdr 1 => print 0x before the hex value
262 * trail 1 => print a trailing ".0"
263 * shsInfo hash state
265 void
266 shsPrint(int hexhdr, int trail, SHS_INFO *shsInfo)
268 if (hexhdr) {
269 fputs("0x", stdout);
271 printf("%08x%08x%08x%08x%08x",
272 shsInfo->digest[0], shsInfo->digest[1], shsInfo->digest[2],
273 shsInfo->digest[3], shsInfo->digest[4]);
274 if (trail) {
275 fputs(".0", stdout);
281 * shsTimeTrial - measure the speed of SHS1
283 * Measures user time required to digest TEST_MEG megabytes of characters.
285 * This function will time blocking and under xor feedback mode if they
286 * are set.
288 static void
289 shsTimeTrial(void)
291 ULONG data[SHS_READWORDS]; /* test buffer */
292 SHS_INFO shsInfo; /* hash state */
293 struct rusage start; /* test start time */
294 struct rusage stop; /* test end time */
295 double usrsec; /* duration of test in user seconds */
296 unsigned int i;
299 * initialize test data
301 for (i = 0; i < SHS_READSIZE; i++) {
302 ((BYTE *)data)[i] = (BYTE)(i & 0xFF);
306 * announce test
308 if (!q_flag) {
309 printf("shs time trial for %d megs of test data ...", TEST_MEG);
310 fflush(stdout);
314 * digest data in SHS_READSIZE byte chunks
316 getrusage(RUSAGE_SELF, &start);
317 shsInit(&shsInfo);
318 for (i=0; i < TEST_CHUNKS; ++i) {
319 shsfullUpdate(&shsInfo, (BYTE *)data, SHS_READSIZE);
321 shsFinal(&shsInfo);
322 getrusage(RUSAGE_SELF, &stop);
325 * announce the test results
327 usrsec = (stop.ru_utime.tv_sec - start.ru_utime.tv_sec) +
328 (double)(stop.ru_utime.tv_usec - start.ru_utime.tv_usec)/1000000.0;
329 if (!q_flag) {
330 putchar('\n');
332 shsPrint(0, 0, &shsInfo);
333 if (q_flag) {
334 putchar('\n');
335 } else {
336 printf(" is digest of test data\n");
337 printf("user seconds to process test data: %.2f\n", usrsec);
338 printf("characters processed per user second: %d\n",
339 (int)((double)TEST_MEG*1024.0*1024.0/usrsec));
345 * shsTestSuite - run a standard suite of test data
347 static void
348 shsTestSuite(void)
350 struct shs_test *t; /* current shs test */
351 struct stat buf; /* stat of a test file */
352 SHS_INFO digest; /* test digest */
353 char **f; /* current file being tested */
354 int i;
357 * copy our test strings into writable data
359 for (i=0, t=shs_test_data; i < MAX_SHS_TEST_DATA; ++i, ++t) {
360 if (t->ro_data != NULL) {
361 t->data = (BYTE *)malloc(t->len + 1);
362 if (t->data == NULL) {
363 fprintf(stderr, "%s: malloc #4 failed\n", program);
364 exit(4);
366 strcpy((char *)t->data, (char *)t->ro_data);
371 * print test header
373 puts("old shs test suite results:");
376 * find all of the test files
378 for (i=0, f=shs_test_file; i < MAX_SHS_TEST_FILE; ++i, ++f) {
379 if (stat(*f, &buf) < 0) {
380 /* no file1 in this directory, cd to the test suite directory */
381 if (chdir(TLIB) < 0) {
382 fflush(stdout);
383 fprintf(stderr,
384 "%s: cannot find %s or %s/%s\n", program, *f, TLIB, *f);
385 return;
391 * try all combinations of test strings as prefixes and data
393 for (i=0, t=shs_test_data; i < MAX_SHS_TEST_DATA; ++i, ++t) {
394 shsInit(&digest);
395 shsUpdate(&digest, t->data, t->len);
396 shsOutput((char *)t->ro_data, 1, c_flag, i_flag, &digest);
400 * try the files with all test strings as prefixes
402 for (i=0, f=shs_test_file; i < MAX_SHS_TEST_FILE; ++i, ++f) {
403 shsInit(&digest);
404 shsFile(NULL, 0, *f, 0, &digest);
405 shsOutput(*f, 0, c_flag, i_flag, &digest);
407 exit(0);
412 * shsPreFileRead - read and process a prepend file
414 * given:
415 * pre_file form pre_str from file pre_file
416 * buf pointer to pre_str pointer
418 * Returns the length of pre_str, and modifies pre_str to
419 * point at the malloced prepend data.
421 static int
422 shsPreFileRead(char *pre_file, BYTE **buf)
424 struct stat statbuf; /* stat for pre_file */
425 int pre_len; /* length of pre_file to be used */
426 int bytes; /* bytes read from pre_file */
427 FILE *pre; /* pre_file descriptor */
429 /* obtain the length that we will use */
430 if (stat(pre_file, &statbuf) < 0) {
431 fprintf(stderr, "%s: unpable to find prepend file %s\n",
432 program, pre_file);
433 exit(5);
435 pre_len = statbuf.st_size;
436 if (pre_len > SHS_MAX_PRE_FILE) {
437 /* don't use beyond SHS_MAX_PRE_FILE in size */
438 pre_len = SHS_MAX_PRE_FILE;
441 /* malloc our pre string */
442 *buf = (BYTE *)malloc(pre_len+1);
443 if (*buf == NULL) {
444 fprintf(stderr, "%s: malloc #3 failed\n", program);
445 exit(6);
448 /* open our pre_file */
449 pre = fopen(pre_file, "rb");
450 if (pre == NULL) {
451 fprintf(stderr, "%s: unable to open prepend file %s\n",
452 program, pre_file);
453 exit(7);
456 /* read our pre_file data */
457 bytes = fread((char *)(*buf), 1, pre_len, pre);
458 if (bytes != pre_len) {
459 fprintf(stderr,
460 "%s: unable to read %d bytes from prepend file %s\n",
461 program, pre_len, pre_file);
462 exit(8);
465 /* return our length */
466 return (pre_len);
471 * shsHelp - print shs help message and exit
473 static void
474 shsHelp(void)
476 fprintf(stderr,
477 "%s [-cCd%shimqtx][-p prefix][-P pfile][-s str] [file ...]\n",
478 program,
479 #if defined(DEBUG)
481 #else
483 #endif
485 fprintf(stderr,
486 " -c print C style digests with a leading 0x\n");
487 fprintf(stderr,
488 " -C do not space seperate multi digests\n");
489 fprintf(stderr,
490 " -d same as -m 2\n");
491 #if defined(DEBUG)
492 fprintf(stderr,
493 " -D debug mode\n");
494 #endif
495 fprintf(stderr,
496 " -h prints this message\n");
497 fprintf(stderr,
498 " -i process inode and filename as well as file data\n");
499 fprintf(stderr,
500 " -m num process num digests on every num-th byte\n");
501 fprintf(stderr,
502 " -p prefix prepend str to data before digesting\n");
503 fprintf(stderr,
504 " -P pfile prepend the file 'str' to data before digesting\n");
505 fprintf(stderr,
506 " -q print only the digest\n");
507 fprintf(stderr,
508 " -r reverse feedback mode\n");
509 fprintf(stderr,
510 " -s str prints digest and contents of string\n");
511 fprintf(stderr,
512 " -t prints time statistics for %dM chars\n", TEST_MEG);
513 fprintf(stderr,
514 " -v print version\n");
515 fprintf(stderr,
516 " -x execute an extended standard suite of test data\n");
517 fprintf(stderr,
518 " file print digest and name of file\n");
519 fprintf(stderr,
520 " (no args) print digest of stdin\n");
521 exit(0);
526 * main - shs main control function
529 main(int argc, char *argv[])
531 SHS_INFO digest; /* our current digest */
532 BYTE *pre_str = NULL; /* pre-process this data first */
533 char *pre_file = NULL; /* pre-process this file first */
534 char *data_str = NULL; /* data is this string, not a file */
535 UINT pre_str_len; /* length of pre_str or pre_file */
536 UINT data_str_len; /* length of data_str */
537 int C_flag = 0; /* 1 => don't space seperate multi digests */
538 int d_flag = 0; /* 1 => dual digest mode */
539 int m_flag = 0; /* 1 => multi digest mode */
540 int t_flag = 0; /* 1 => -t was given */
541 int x_flag = 0; /* 1 => -x was given */
542 int multi = 0; /* number of digests to do in parallel */
543 extern char *optarg; /* argument to option */
544 extern int optind; /* option index */
545 int c;
548 * parse args
550 program = argv[0];
551 while ((c = getopt(argc, argv, "cCdDihm:p:P:qs:tvx")) != -1) {
552 switch (c) {
553 case 'c':
554 c_flag = 1;
555 break;
556 case 'C':
557 C_flag = 1;
558 break;
559 case 'd':
560 d_flag = 1;
561 multi = 2;
562 break;
563 case 'D':
564 #if defined(DEBUG)
565 debug = 1;
566 #else
567 fprintf(stderr, "%s: not compiled with -DDEBUG\n", program);
568 exit(9);
569 /*NOTREACHED*/
570 #endif
571 break;
572 case 'h':
573 shsHelp();
574 /*NOTREACHED*/
575 break;
576 case 'i':
577 i_flag = 1;
578 break;
579 case 'm':
580 m_flag = 1;
581 multi = atoi(optarg);
582 break;
583 case 'p':
584 pre_str = (BYTE *)optarg;
585 break;
586 case 'q':
587 q_flag = 1;
588 break;
589 case 'P':
590 pre_file = optarg;
591 break;
592 case 's':
593 data_str = optarg;
594 break;
595 case 't':
596 t_flag = 1;
597 break;
598 case 'v':
599 printf("%s: version %s\n", program, SHS_VERSION);
600 exit(0);
601 case 'x':
602 x_flag = 1;
603 break;
604 default:
605 shsHelp();
606 break;
609 /* arg checking */
610 if (data_str && optind != argc) {
611 fprintf(stderr, "%s: -s is not compatible with digesting files\n",
612 program);
613 exit(10);
615 if (i_flag && optind == argc) {
616 fprintf(stderr, "%s: -i works only on filenames\n", program);
617 exit(11);
619 if (d_flag && m_flag) {
620 fprintf(stderr, "%s: -d imples -m 2, use one or the other\n", program);
621 exit(12);
623 if ((d_flag || m_flag) && multi < 2) {
624 fprintf(stderr, "%s: multi count must be > 1\n", program);
625 exit(13);
627 if (C_flag && !d_flag && !m_flag) {
628 fprintf(stderr, "%s: -C requires -d or -m num\n", program);
629 exit(14);
633 * process -x if needed
635 if (x_flag) {
636 if (d_flag) {
637 multiTest();
638 } else {
639 shsTestSuite();
641 exit(0);
645 * process -t if needed
647 if (t_flag) {
648 shsTimeTrial();
649 exit(0);
653 * process -P or -p if needed
655 if (pre_str && pre_file) {
656 fprintf(stderr, "%s: -p and -P conflict\n", program);
657 exit(15);
659 if (pre_file) {
660 pre_str_len = shsPreFileRead(pre_file, &pre_str);
661 } else if (pre_str) {
662 pre_str_len = strlen((char *)pre_str);
663 } else {
664 pre_str_len = 0;
666 if (pre_str_len > SHS_MAX_PRE_FILE) {
667 fprintf(stderr, "%s: prefix may not be longer than %d bytes\n",
668 program, SHS_MAX_PRE_FILE);
669 exit(15);
673 * if -d of -m num, perform multi digest processing instead
675 if (d_flag || m_flag) {
676 multiMain(argc, argv, pre_str, pre_str_len, data_str, C_flag,
677 (UINT)multi);
680 * if no -d and no -m num, process string, stdin or files
682 } else {
685 * case: digest a string
687 if (data_str != NULL) {
688 data_str_len = strlen(data_str);
689 shsInit(&digest);
690 shsUpdate(&digest, pre_str, pre_str_len);
691 shsUpdate(&digest, (BYTE *)data_str, data_str_len);
692 shsOutput(data_str, 1, c_flag, i_flag, &digest);
695 * case: digest stdin
697 } else if (optind == argc) {
698 shsInit(&digest);
699 shsStream(pre_str, pre_str_len, stdin, &digest);
700 shsOutput(NULL, 0, c_flag, i_flag, &digest);
703 * case: digest files
705 } else {
706 for (; optind < argc; optind++) {
707 shsInit(&digest);
708 shsFile(pre_str, pre_str_len, argv[optind], i_flag, &digest);
709 shsOutput(argv[optind], 0, c_flag, i_flag, &digest);
714 /* all done */
715 /* exit(0); */
716 return 0;