modified: SpatialOmicsCoord.py
[GalaxyCodeBases.git] / c_cpp / etc / md5_sha / md5drvr.c
blobffcc2b2e53b4d414ad425cf7a659b282737e53c1
1 /*
2 * md5drvr - md5 driver code
4 * @(#) $Revision: 13.3 $
5 * @(#) $Id: md5drvr.c,v 13.3 2006/08/14 10:21:59 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/hash/RCS/md5drvr.c,v $
8 * This file was written by RSA Data Security.
10 * This file was modified by Landon Curt Noll.
12 * This code has been placed in the public domain. Please do not
13 * copyright this code.
15 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MER-
17 * CHANTABILITY AND FITNESS. IN NO EVENT SHALL LANDON CURT
18 * NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
19 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * chongo (was here) /\oo/\
25 * http://www.isthe.com/chongo/index.html
27 * Share and enjoy! :-)
29 ***
31 * NOTE: The version information below refers to all md5 code, not
32 * just this file. In particular, this file was created by
33 * Landon Curt Noll.
35 * Version 1.1: 17 Feb 1990 RLR
36 * Original code written.
38 * Version 1.2: 27 Dec 1990 SRD,AJ,BSK,JT
39 * C reference version.
41 * Version 1.3: 27 Apr 1991 RLR
42 * G modified to have y&~z instead of y&z
43 * FF, GG, HH modified to add in last register done
44 * access pattern: round 2 works mod 5, round 3 works mod 3
45 * distinct additive constant for each step
46 * round 4 added, working mod 7
48 * Version 1.4: 10 Jul 1991 SRD,AJ,BSK,JT
49 * Constant correction.
51 * Version 2.1: 31 Dec 1993 Landon Curt Noll
52 * Modified/Re-wrote md5.c
54 * Version 2.2: 09 Jan 1994 Landon Curt Noll
55 * md5drvr.c and md5dual.c code cloned from shs version 2.5.8 94/01/09
56 * performance tuning
58 * Version 2.3: 10 Jan 1994 Landon Curt Noll
59 * added MUST_ALIGN for Sparc and other RISC architectures
60 * use must_align.c to automatically determine if MUST_ALIGN is required
61 * performance tuning
62 * increased test to 64 megabytes due to increased performance
64 * Version 2.4: non-existent version
66 * Version 2.5: non-existent version
68 * Version 2.6: 10 Jan 1994 Landon Curt Noll
69 * Merged the shs and md5 Makefiles to build both in the same directory
70 * Bumped version to 2.6 to match level to shs
71 * Test suite header now says md5 (not MD5)
72 * Minor performance improvements
74 * Version 2.7: 14 Jan 1994 Landon Curt Noll
75 * code cleanup
76 * chunk is now 64 bytes, block is determined by blocking factor
77 * magic 64 and 64 related values defined in terms of #defines
78 * fixed bit count carry bug
79 * fixed writable strings test bug
81 * Version 2.8: 22 Jan 1994 Landon Curt Noll
82 * code cleanup
83 * count bytes in driver, convert to 64 bit count in final transform
84 * handle read errors and EOF better
85 * prefix strings not multiple of 64 bytes in length do not slow down hash
86 * renumbered exit codes
87 * fixed dual digest split bug
89 * Version 2.9: 05 Feb 1994 Landon Curt Noll
90 * prep for beta release
92 * Version 2.10: 25 Mar 1994 Landon Curt Noll
93 * must_align catchs signal to detect misaligned access
94 * malloc type not declared
96 * Version 2.11: 09 Mar 1995 Landon Curt Noll
97 * Moved stream and file routines to md5io.c.
99 * Version 2.12: 17 Nov 1995 Landon Curt Noll
100 * Fixed help string.
102 * Version 3.1: non-existent version
104 * Version 4.1: 13 Aug 2006 Landon Curt Noll
105 * Bump to version 4.1 to match the version of SHA and SHA-1 drvr files.
106 * Port to ANSI C.
107 * Fixed all known compile warnings.
108 * Allow access to the internal hash transform function (to help code)
109 * that makes direct use of the cryprographic hash source.
110 * Improved the way -v prints version. Now -v prints the RCS version,
111 * not version listed in the above comment.
114 #include <stdio.h>
115 #include <stdlib.h>
116 #include <string.h>
117 #include <sys/types.h>
118 #include <sys/stat.h>
119 #include <sys/time.h>
120 #include <sys/resource.h>
121 #include <unistd.h>
122 #include "md5.h"
124 /* size of test in megabytes */
125 #define TEST_MEG 64
127 /* number of chunks to process */
128 #define TEST_CHUNKS (TEST_MEG*1024*1024/MD5_READSIZE)
130 /* MD5 test suite strings */
131 #define ENTRY(str) {(BYTE *)str, NULL, sizeof(str)-1}
132 struct MD5_test {
133 BYTE *ro_data; /* read only string data or NULL to test */
134 BYTE *data; /* data or NULL to test */
135 int len; /* length of data */
136 } MD5_test_data[] = {
137 ENTRY(""),
138 ENTRY("a"),
139 ENTRY("abc"),
140 ENTRY("message digest"),
141 ENTRY("abcdefghijklmnopqrstuvwxyz"),
142 ENTRY("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
143 ENTRY("12345678901234567890123456789012345678901234567890123456789012345678901234567890")
145 #define MAX_MD5_TEST_DATA ((int)(sizeof(MD5_test_data)/sizeof(MD5_test_data[0])))
147 /* MD5 test filenames */
148 char *MD5_test_file[] = {
149 "file1",
150 "file2",
152 #define MAX_MD5_TEST_FILE ((int)(sizeof(MD5_test_file)/sizeof(MD5_test_file[0])))
154 /* where the test files are located by default */
155 #if !defined(TLIB)
156 #define TLIB "."
157 #endif
159 /* Prototypes of the static functions */
160 static void MD5Output(char*, int, MD5_CTX*);
161 static int MD5PreFileRead(char*, BYTE**);
162 static void MD5TestSuite(void);
163 static void MD5Help(void);
165 /* global variables */
166 static int c_flag = 0; /* 1 => print C style digest with leading 0x */
167 int i_flag = 0; /* 1 => process inode & filename */
168 int q_flag = 0; /* 1 => print the digest only */
169 int dot_zero = 0; /* 1 => print .0 after the digest */
170 int debug = 0; /* 1 => add debug */
171 char *program = "<program name unknown>"; /* our name */
175 * MD5Output - output the digest
177 * given:
178 * str print string after digest, NULL => none
179 * quot 1 => surround str with a double quotes
180 * dig current digest
182 static void
183 MD5Output(char *str, int quot, MD5_CTX *dig)
186 * finalize the digest
188 MD5Final(dig);
191 * print the digest
193 MD5Print(dig);
194 if (str && !q_flag) {
195 if (quot) {
196 printf(" \"%s\"\n", str);
197 } else {
198 printf(" %s\n", str);
200 } else {
201 putchar('\n');
203 fflush(stdout);
208 * MD5Print - print a digest in hex
210 * Prints message digest buffer in MD5Info as 40 hexadecimal digits. Order is
211 * from low-order byte to high-order byte of digest. Each byte is printed
212 * with high-order hexadecimal digit first.
214 * If -c, then print a leading "0x". If -i, then print a trailing ".0".
216 void
217 MD5Print(MD5_CTX *MD5Info)
219 int i;
221 if (c_flag) {
222 fputs("0x", stdout);
224 for (i = 0; i < 16; i++) {
225 printf ("%02x", MD5Info->digest[i]);
227 if (dot_zero) {
228 fputs(".0", stdout);
234 * A time trial routine, to measure the speed of MD5.
236 * Measures user time required to digest TEST_MEG megabytes of characters.
238 static void
239 MD5TimeTrial(void)
241 BYTE data[MD5_READSIZE]; /* test buffer */
242 MD5_CTX MD5Info; /* hash state */
243 struct rusage start; /* test start time */
244 struct rusage stop; /* test end time */
245 double usrsec; /* duration of test in user seconds */
246 unsigned int i;
248 /* initialize test data */
249 for (i = 0; i < MD5_READSIZE; i++)
250 data[i] = (BYTE)(i & 0xFF);
252 /* start timer */
253 if (!q_flag) {
254 printf("md5 time trial for %d megabytes of test data ...", TEST_MEG);
255 fflush(stdout);
257 getrusage(RUSAGE_SELF, &start);
259 /* digest data in MD5_READSIZE byte chunk */
260 MD5Init(&MD5Info);
261 for (i=0; i < TEST_CHUNKS; ++i) {
262 MD5fullUpdate(&MD5Info, data, MD5_READSIZE);
264 MD5COUNT(&MD5Info, MD5_READSIZE*TEST_CHUNKS);
265 MD5Final(&MD5Info);
267 /* stop timer, get time difference */
268 getrusage(RUSAGE_SELF, &stop);
269 usrsec = (stop.ru_utime.tv_sec - start.ru_utime.tv_sec) +
270 (double)(stop.ru_utime.tv_usec - start.ru_utime.tv_usec)/1000000.0;
271 if (!q_flag) {
272 putchar('\n');
274 MD5Print(&MD5Info);
275 if (q_flag) {
276 putchar('\n');
277 } else {
278 printf(" is digest of test data\n");
279 printf("user seconds to process test data: %.2f\n", usrsec);
280 printf("characters processed per user second: %d\n",
281 (int)((double)TEST_MEG*1024.0*1024.0/usrsec));
287 * Runs a standard suite of test data.
289 static void
290 MD5TestSuite(void)
292 struct MD5_test *t; /* current MD5 test */
293 struct stat buf; /* stat of a test file */
294 MD5_CTX digest; /* test digest */
295 char **f; /* current file being tested */
296 int i;
299 * copy our test strings into writable data
301 for (i=0, t=MD5_test_data; i < MAX_MD5_TEST_DATA; ++i, ++t) {
302 if (t->ro_data != NULL) {
303 t->data = (BYTE *)malloc(t->len + 1);
304 if (t->data == NULL) {
305 fprintf(stderr, "%s: malloc #4 failed\n", program);
306 exit(4);
308 strcpy((char *)t->data, (char *)t->ro_data);
313 * print test header
315 puts("md5 test suite results:");
318 * find all of the test files
320 for (i=0, f=MD5_test_file; i < MAX_MD5_TEST_FILE; ++i, ++f) {
321 if (stat(*f, &buf) < 0) {
322 /* no file1 in this directory, cd to the test suite directory */
323 if (chdir(TLIB) < 0) {
324 fflush(stdout);
325 fprintf(stderr,
326 "%s: cannot find %s or %s/%s\n", program, *f, TLIB, *f);
327 return;
333 * try all combinations of test strings as prefixes and data
335 for (i=0, t=MD5_test_data; i < MAX_MD5_TEST_DATA; ++i, ++t) {
336 MD5Init(&digest);
337 MD5Update(&digest, t->data, t->len);
338 MD5COUNT(&digest, t->len);
339 MD5Output((char *)(t->data), 1, &digest);
343 * try the files with all test strings as prefixes
345 for (i=0, f=MD5_test_file; i < MAX_MD5_TEST_FILE; ++i, ++f) {
346 MD5Init(&digest);
347 MD5File(NULL, 0, *f, 0, &digest);
348 MD5Output(*f, 0, &digest);
350 exit(0);
355 * MD5PreFileRead - read and process a prepend file
357 * given:
358 * pre_file form pre_str from file pre_file
359 * buf pointer to pre_str pointer
361 * Returns the length of pre_str, and modifies pre_str to
362 * point at the malloced prepend data.
364 static int
365 MD5PreFileRead(char *pre_file, BYTE **buf)
367 struct stat statbuf; /* stat for pre_file */
368 int pre_len; /* length of pre_file to be used */
369 int bytes; /* bytes read from pre_file */
370 FILE *pre; /* pre_file descriptor */
372 /* obtain the length that we will use */
373 if (stat(pre_file, &statbuf) < 0) {
374 fprintf(stderr, "%s: unpable to find prepend file %s\n",
375 program, pre_file);
376 exit(5);
378 pre_len = statbuf.st_size;
379 if (pre_len > MD5_MAX_PRE_FILE) {
380 /* don't use beyond MD5_MAX_PRE_FILE in size */
381 pre_len = MD5_MAX_PRE_FILE;
384 /* malloc our pre string */
385 *buf = (BYTE *)malloc(pre_len+1);
386 if (*buf == NULL) {
387 fprintf(stderr, "%s: malloc #3 failed\n", program);
388 exit(6);
391 /* open our pre_file */
392 pre = fopen(pre_file, "rb");
393 if (pre == NULL) {
394 fprintf(stderr, "%s: unable to open prepend file %s\n",
395 program, pre_file);
396 exit(7);
399 /* read our pre_file data */
400 bytes = fread((char *)(*buf), 1, pre_len, pre);
401 if (bytes != pre_len) {
402 fprintf(stderr,
403 "%s: unable to read %d bytes from prepend file %s\n",
404 program, pre_len, pre_file);
405 exit(8);
408 /* return our length */
409 return (pre_len);
414 * MD5Help - print MD5 help message and exit
416 static void
417 MD5Help(void)
419 fprintf(stderr,
420 "%s [-cdhiqtx][-p str][-P str][-s str] [file ...]\n",
421 program);
422 fprintf(stderr,
423 " -c print C style digests with a leading 0x\n");
424 fprintf(stderr,
425 " -d dual digests of even and odd indexed bytes\n");
426 fprintf(stderr,
427 " -h prints this message\n");
428 fprintf(stderr,
429 " -i process inode and filename as well as file data\n");
430 fprintf(stderr,
431 " -p str prepend str to data before digesting\n");
432 fprintf(stderr,
433 " -P str prepend the file 'str' to data before digesting\n");
434 fprintf(stderr,
435 " -q print only the digest\n");
436 fprintf(stderr,
437 " -s str prints digest and contents of string\n");
438 fprintf(stderr,
439 " -t prints time statistics for %dM chars\n", TEST_MEG);
440 fprintf(stderr,
441 " -v print version\n");
442 fprintf(stderr,
443 " -x execute an extended standard suite of test data\n");
444 fprintf(stderr,
445 " file print digest and name of file\n");
446 fprintf(stderr,
447 " (no args) print digest of stdin\n");
448 exit(0);
453 * main - MD5 main
456 main(int argc, char *argv[])
458 MD5_CTX digest; /* our current digest */
459 BYTE *pre_str = NULL; /* pre-process this data first */
460 char *pre_file = NULL; /* pre-process this file first */
461 char *data_str = NULL; /* data is this string, not a file */
462 UINT pre_str_len; /* length of pre_str or pre_file */
463 UINT data_str_len; /* length of data_str */
464 int d_flag = 0; /* 1 => dual digest mode */
465 int t_flag = 0; /* 1 => -t was given */
466 int x_flag = 0; /* 1 => -x was given */
467 extern char *optarg; /* argument to option */
468 extern int optind; /* option index */
469 int c;
472 * parse args
474 program = argv[0];
475 while ((c = getopt(argc, argv, "cdihp:P:qs:tvx")) != -1) {
476 switch (c) {
477 case 'c':
478 c_flag = 1;
479 break;
480 case 'd':
481 d_flag = 1;
482 break;
483 case 'h':
484 MD5Help();
485 /*NOTREACHED*/
486 break;
487 case 'i':
488 i_flag = 1;
489 break;
490 case 'p':
491 pre_str = (BYTE *)optarg;
492 break;
493 case 'q':
494 q_flag = 1;
495 break;
496 case 'P':
497 pre_file = optarg;
498 break;
499 case 's':
500 data_str = optarg;
501 break;
502 case 't':
503 t_flag = 1;
504 break;
505 case 'v':
506 printf("%s: version %s\n", program, MD5_VERSION);
507 exit(0);
508 case 'x':
509 x_flag = 1;
510 break;
511 default:
512 MD5Help();
513 break;
516 if (data_str && optind != argc) {
517 fprintf(stderr, "%s: -s is not compatible with digesting files\n",
518 program);
519 exit(9);
521 if (i_flag && optind == argc) {
522 fprintf(stderr, "%s: -i works only on filenames\n", program);
523 exit(10);
527 * process -x if needed
529 if (x_flag) {
530 if (d_flag) {
531 dualTest();
532 } else {
533 MD5TestSuite();
535 exit(0);
539 * process -t if needed
541 if (t_flag) {
542 MD5TimeTrial();
543 exit(0);
547 * process -P or -p if needed
549 if (pre_str && pre_file) {
550 fprintf(stderr, "%s: -p and -P conflict\n", program);
551 exit(11);
553 if (pre_file) {
554 pre_str_len = MD5PreFileRead(pre_file, &pre_str);
555 } else if (pre_str) {
556 pre_str_len = strlen((char *)pre_str);
557 } else {
558 pre_str_len = 0;
562 * if -d, perform dual digest processing instead
564 if (d_flag) {
565 dualMain(argc, argv, pre_str, pre_str_len, data_str);
568 * if no -d, process string, stdin or files
570 } else {
573 * case: digest a string
575 if (data_str != NULL) {
576 data_str_len = strlen(data_str);
577 MD5Init(&digest);
578 MD5Update(&digest, pre_str, pre_str_len);
579 MD5Update(&digest, (BYTE *)data_str, data_str_len);
580 MD5COUNT(&digest, pre_str_len + data_str_len);
581 MD5Output(data_str, 1, &digest);
584 * case: digest stdin
586 } else if (optind == argc) {
587 MD5Init(&digest);
588 MD5Stream(pre_str, pre_str_len, stdin, &digest);
589 MD5Output(NULL, 0, &digest);
592 * case: digest files
594 } else {
595 if (i_flag) {
596 dot_zero = 1;
598 for (; optind < argc; optind++) {
599 MD5Init(&digest);
600 MD5File(pre_str, pre_str_len, argv[optind], i_flag, &digest);
601 MD5Output(argv[optind], 0, &digest);
606 /* all done */
607 /* exit(0); */
608 return 0;