limit fstBC to 30bp in Python3 ver.
[GalaxyCodeBases.git] / c_cpp / etc / md5_sha / shs1dual.c
blobae8b9f11be1ec3adc9c23cbac97b195d8384ebd3
1 /*
2 * shs1dual - multi digest code that works with NIST Secure Hash Standard-1
4 * @(#) $Revision: 13.2 $
5 * @(#) $Id: shs1dual.c,v 13.2 2006/08/14 10:09:23 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/hash/RCS/shs1dual.c,v $
8 * Split our data into multiple byte index streams, digest them all
9 * and output the digests on a line.
11 * This file was written by Landon Curt Noll.
13 * This code has been placed in the public domain. Please do not
14 * copyright this code.
16 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO
17 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MER-
18 * CHANTABILITY AND FITNESS. IN NO EVENT SHALL LANDON CURT
19 * NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
21 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
22 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 * chongo (was here) /\oo/\
26 * http://www.isthe.com/chongo/index.html
28 * Share and enjoy! :-)
30 * See shs1drvr.c for version and modification history.
33 char *shs1dual_what="@(#)"; /* #(@) if checked in */
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include "shs1.h"
41 /* static declarations */
42 static void multiData(BYTE*, UINT, BYTE*, UINT, UINT, SHS1_INFO*);
43 static void multiStream(BYTE*, UINT, FILE*, UINT, SHS1_INFO*);
44 static void multiFile(BYTE*, UINT, char*, UINT, SHS1_INFO*);
45 static void multiOutput(char*, int, int, UINT, SHS1_INFO*);
47 /* dual test suite strings */
48 #define ENTRY(str) {(BYTE *)str, sizeof(str)-1}
49 struct dual_test {
50 BYTE *data; /* data or NULL to test */
51 int len; /* length of data */
52 } dual_test_data[] = {
53 {NULL, 0},
54 ENTRY(""),
55 ENTRY("a"),
56 ENTRY("aa"),
57 ENTRY("aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz"),
58 ENTRY("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
59 ENTRY("chongo <Ich bin, du bist, aber ein Yit ist nicht!!! :-)> /\\../\\"),
60 ENTRY("123456789 123456789 123456789 123456789 123456789 123456789 1234"),
61 ENTRY("a123456789 123456789 123456789 123456789 123456789 123456789 1234")
63 #define MAX_DUAL_TEST_DATA (sizeof(dual_test_data)/sizeof(dual_test_data[0]))
65 /* dual test filenames */
66 char *dual_test_file[] = {
67 "file1",
68 "file2",
69 "shs1.data",
70 "/dev/null"
72 #define MAX_DUAL_TEST_FILE (sizeof(dual_test_file)/sizeof(dual_test_file[0]))
74 /* where the test files are located by default */
75 #if !defined(TLIB)
76 #define TLIB "."
77 #endif
81 * multiData - divide data into multiple sections
83 * given:
84 * pre_str string prefix or NULL
85 * pre_len length of pre_str
86 * inString string to digest
87 * in_len length of inString
88 * cnt number of digests
89 * digs array of digests, cnt elements long
91 static void
92 multiData(BYTE *pre_str, UINT pre_len, BYTE *inString,
93 UINT in_len, UINT cnt, SHS1_INFO *digs)
95 BYTE **bufs; /* byte arrays for digests */
96 UINT *buflen; /* bytes stored in bufs[i] */
97 int len; /* total length of pre_str and inString */
98 UINT indx; /* byte stream index */
99 BYTE **n; /* n[i] is next byte to use in bufs[i] */
100 BYTE *p;
101 UINT i;
104 * determine lengths
106 len = (pre_str == NULL) ? 0 : pre_len;
107 len += (inString == NULL) ? 0 : in_len;
108 /* no strings, quick return */
109 if (len == 0 || cnt <= 0) {
110 return;
114 * malloc string arrays
116 bufs = (BYTE **)malloc(sizeof(BYTE *)*cnt);
117 if (bufs == NULL) {
118 fprintf(stderr, "%s: bad malloc #1\n", program);
119 exit(51);
121 buflen = (UINT *)malloc(sizeof(UINT)*cnt);
122 if (buflen == NULL) {
123 fprintf(stderr, "%s: bad malloc #2\n", program);
124 exit(52);
126 n = (BYTE **)malloc(sizeof(BYTE *)*cnt);
127 if (n == NULL) {
128 fprintf(stderr, "%s: bad malloc #3\n", program);
129 exit(53);
131 for (i=0; i < cnt; ++i) {
132 bufs[i] = (BYTE *)malloc(1+(len/cnt));
133 if (bufs[i] == NULL) {
134 fprintf(stderr, "%s: bad malloc #4\n", program);
135 exit(54);
137 buflen[i] = 0;
138 n[i] = bufs[i];
142 * divide the pre-string
144 indx = 0;
145 if (pre_str != NULL) {
146 for (p=pre_str, i=0; i < pre_len; ++i, ++p, indx++) {
147 *(n[(indx = ((indx >= cnt) ? 0 : indx))]++) = *p;
148 ++buflen[indx];
153 * divide the string
155 if (inString != NULL) {
156 for (p=inString, i=0; i < in_len; ++indx, ++i, ++p) {
157 *(n[(indx = ((indx >= cnt) ? 0 : indx))]++) = *p;
158 ++buflen[indx];
163 * update arrays
165 for (i=0; i < cnt; ++i) {
166 shs1Update(digs+i, bufs[i], buflen[i]);
170 * cleanup
172 free(buflen);
173 free(n);
174 for (i=0; i < cnt; ++i) {
175 free(bufs[i]);
177 free(bufs);
182 * multiStream - divide a Stream into multiple sections
184 * given:
185 * pre_str data prefix or NULL
186 * pre_len length of pre_str
187 * stream the stream to process
188 * cnt number of digests
189 * digs array of digests, cnt elements long
191 static void
192 multiStream(BYTE *pre_str, UINT pre_len, FILE *stream,
193 UINT cnt, SHS1_INFO *digs)
195 BYTE data[SHS1_READSIZE]; /* our read buffer */
196 int bytes; /* bytes last read */
197 BYTE **bufs; /* byte arrays for digests */
198 UINT *buflen; /* bytes stored in bufs[i] */
199 UINT indx; /* byte stream index */
200 BYTE *pbeyond; /* beyond end of used data or pre_str */
201 BYTE **n; /* n[i] is next byte to use in bufs[i] */
202 BYTE *p;
203 UINT i;
206 * no sets, quick return
208 if (cnt <= 0) {
209 return;
213 * malloc string arrays
215 bufs = (BYTE **)malloc(sizeof(BYTE *)*cnt);
216 if (bufs == NULL) {
217 fprintf(stderr, "%s: bad malloc #5\n", program);
218 exit(55);
220 buflen = (UINT *)malloc(sizeof(UINT)*cnt);
221 if (buflen == NULL) {
222 fprintf(stderr, "%s: bad malloc #6\n", program);
223 exit(56);
225 n = (BYTE **)malloc(sizeof(BYTE *)*cnt);
226 if (n == NULL) {
227 fprintf(stderr, "%s: bad malloc #7\n", program);
228 exit(57);
230 for (i=0; i < cnt; ++i) {
231 bufs[i] = (BYTE *)malloc(SHS1_BLOCKSIZE);
232 if (bufs[i] == NULL) {
233 fprintf(stderr, "%s: bad malloc #8\n", program);
234 exit(58);
236 buflen[i] = 0;
237 n[i] = bufs[i];
241 * divide the pre-string
243 indx = 0;
244 if (pre_str != NULL && pre_len > 0) {
245 for (p=pre_str, pbeyond=pre_str+pre_len; p < pbeyond; ++p, ++indx) {
246 *(n[(indx = ((indx >= cnt) ? 0 : indx))]++) = *p;
247 if (++buflen[indx] >= SHS1_BLOCKSIZE) {
248 shs1Update(digs+indx, bufs[indx], SHS1_BLOCKSIZE);
249 buflen[indx] = 0;
250 n[indx] = bufs[indx];
256 * process the contents of the file
258 while ((bytes = fread((char *)data, 1, SHS1_READSIZE, stream)) > 0) {
261 * load the bytes into the bufs
263 for (p=data, pbeyond=data+bytes; p < pbeyond; ++p, ++indx) {
264 *(n[(indx = ((indx >= cnt) ? 0 : indx))]++) = *p;
265 if (++buflen[indx] >= SHS1_BLOCKSIZE) {
266 shs1Update(digs+indx, bufs[indx], SHS1_BLOCKSIZE);
267 buflen[indx] = 0;
268 n[indx] = bufs[indx];
274 * process any partial buffers
276 for (i=0; i < cnt; ++i) {
277 if (buflen[i] > 0) {
278 shs1Update(digs+i, bufs[i], buflen[i]);
283 * cleanup
285 free(buflen);
286 free(n);
287 for (i=0; i < cnt; ++i) {
288 free(bufs[i]);
290 free(bufs);
295 * multiFile - divide a file into alternating bytes and digest both halves
297 * given:
298 * pre_str string prefix or NULL
299 * pre_len length of pre_str
300 * filename the filename to process
301 * cnt number of digests
302 * digs array of digests, cnt elements long
304 static void
305 multiFile(BYTE *pre_str, UINT pre_len, char *filename,
306 UINT cnt, SHS1_INFO *digs)
308 FILE *inFile; /* the open file stream */
309 struct stat buf; /* stat or lstat of file */
310 struct shs1_stat hashbuf; /* stat data to digest */
311 struct shs1_stat hashlbuf; /* lstat data to digest */
312 UINT i;
315 * firewall
317 if (cnt <= 0) {
318 return;
322 * open the file
324 inFile = fopen(filename, "rb");
325 if (inFile == NULL) {
326 fprintf(stderr, "%s: cannot open %s: ", program, filename);
327 perror("");
328 return;
332 * pre-process prefix if needed
334 if (pre_str == NULL || pre_len <= 0) {
335 if (i_flag) {
336 multiData(NULL, 0, (BYTE *)filename, strlen(filename), cnt, digs);
338 } else {
339 if (i_flag) {
340 multiData(pre_str, pre_len, (BYTE *)filename, strlen(filename),
341 cnt, digs);
342 } else {
343 multiData(pre_str, pre_len, NULL, 0, cnt, digs);
348 * digest file stat and lstat
350 if (i_flag) {
351 if (fstat(fileno(inFile), &buf) < 0) {
352 printf("%s can't be stated.\n", filename);
353 return;
355 hashbuf.stat_dev = buf.st_dev;
356 hashbuf.stat_ino = buf.st_ino;
357 hashbuf.stat_mode = buf.st_mode;
358 hashbuf.stat_nlink = buf.st_nlink;
359 hashbuf.stat_uid = buf.st_uid;
360 hashbuf.stat_gid = buf.st_gid;
361 hashbuf.stat_size = buf.st_size;
362 hashbuf.stat_mtime = buf.st_mtime;
363 hashbuf.stat_ctime = buf.st_ctime;
364 if (lstat(filename, &buf) < 0) {
365 printf("%s can't be lstated.\n", filename);
366 return;
368 hashlbuf.stat_dev = buf.st_dev;
369 hashlbuf.stat_ino = buf.st_ino;
370 hashlbuf.stat_mode = buf.st_mode;
371 hashlbuf.stat_nlink = buf.st_nlink;
372 hashlbuf.stat_uid = buf.st_uid;
373 hashlbuf.stat_gid = buf.st_gid;
374 hashlbuf.stat_size = buf.st_size;
375 hashlbuf.stat_mtime = buf.st_mtime;
376 hashlbuf.stat_ctime = buf.st_ctime;
377 multiData((BYTE *)&hashbuf, sizeof(hashbuf), (BYTE *)&hashlbuf,
378 sizeof(hashlbuf), cnt, digs);
381 * pad sections with zeros to process file data faster
383 for (i=0; i < cnt; ++i) {
384 if (digs[i].datalen > 0) {
385 shs1Update(digs+i, (BYTE *)shs1_zero,
386 SHS1_CHUNKSIZE - digs[i].datalen);
392 * process the data stream
394 multiStream(NULL, 0, inFile, cnt, digs);
395 fclose(inFile);
400 * multiOutput - output the multiple digests
402 * given:
403 * str print string after digest, NULL => none
404 * quot 1 => surround str with a double quotes
405 * nospace 1 => don't space seperate multi digests
406 * cnt number of digests
407 * digs array of digests, cnt elements long
409 static void
410 multiOutput(char *str, int quot, int nospace, UINT cnt, SHS1_INFO *digs)
412 UINT i;
415 * firewall
417 if (cnt <= 0) {
418 return;
422 * finalize the sets
424 for (i=0; i < cnt; ++i) {
425 shs1Final(digs+i);
429 * print the digests
431 shs1Print(c_flag, 0, digs);
432 for (i=1; i < cnt-1; ++i) {
433 if (nospace == 0) {
434 putchar(' ');
435 shs1Print(c_flag, 0, digs+i);
436 } else {
437 shs1Print(0, 0, digs+i);
440 if (i < cnt) {
441 if (nospace == 0) {
442 putchar(' ');
443 shs1Print(c_flag, i_flag, digs+cnt-1);
444 } else {
445 shs1Print(0, i_flag, digs+cnt-1);
448 if (str && !q_flag) {
449 if (quot) {
450 printf(" \"%s\"\n", str);
451 } else {
452 printf(" %s\n", str);
454 } else {
455 putchar('\n');
461 * multiTest - shs1 dual test suite
463 void
464 multiTest(void)
466 struct dual_test *t; /* current dual test */
467 struct dual_test *p; /* current dual pre-string test */
468 struct stat buf; /* stat of a test file */
469 SHS1_INFO digs[2]; /* even byte digest */
470 char **f; /* current file being tested */
471 unsigned int i;
472 unsigned int j;
475 * find all of the test files
477 for (i=0, f=dual_test_file; i < MAX_DUAL_TEST_FILE; ++i, ++f) {
478 if (stat(*f, &buf) < 0) {
479 /* no file1 in this directory, cd to the test suite directory */
480 if (chdir(TLIB) < 0) {
481 fflush(stdout);
482 fprintf(stderr,
483 "%s: cannot find %s or %s/%s\n", program, *f, TLIB, *f);
484 return;
490 * try all combinations of test strings as prefixes and data
492 for (i=0, t=dual_test_data; i < MAX_DUAL_TEST_DATA; ++i, ++t) {
493 for (j=1, p=dual_test_data+1; j < MAX_DUAL_TEST_DATA; ++j, ++p) {
494 printf("pre:%u data:%u\n", i, j);
495 shs1Init(digs+0);
496 shs1Init(digs+1);
497 multiData(p->data, p->len, t->data, t->len, 2, digs);
498 multiOutput(NULL, 0, 0, 2, digs);
503 * try the files with all test strings as prefixes
505 for (i=0, p=dual_test_data; i < MAX_DUAL_TEST_DATA; ++i, ++p) {
506 for (j=0, f=dual_test_file; j < MAX_DUAL_TEST_FILE; ++j, ++f) {
507 printf("pre:%d file:%s\n", i, *f);
508 shs1Init(digs+0);
509 shs1Init(digs+1);
510 multiFile(p->data, p->len, *f, 2, digs);
511 multiOutput(NULL, 0, 0, 2, digs);
514 exit(0);
519 * multiMain - main driver of shs1 dual routines
521 * given:
522 * argc arg count left after getopt
523 * argv args left after getopt
524 * pre_str pre-process this data first
525 * pre_len length of pre_str
526 * data_str data is this string, not a file
527 * nospace 1 => don't space seperate multi digests
528 * cnt number of digests to perform
530 void
531 multiMain(int argc, char **argv, BYTE *pre_str, UINT pre_len,
532 char *data_str, int nospace, UINT cnt)
534 extern int optind; /* option index */
535 SHS1_INFO *digs; /* multiple digest */
536 unsigned int i;
539 * firewall
541 if (cnt <= 0) {
542 return;
546 * initialize multiple digests
548 digs = (SHS1_INFO *)malloc(sizeof(SHS1_INFO)*cnt);
549 if (digs == NULL) {
550 fprintf(stderr, "%s: bad malloc #1\n", program);
551 exit(60);
553 for (i=0; i < cnt; ++i) {
554 shs1Init(digs+i);
558 * digest a string
560 if (data_str != NULL) {
561 multiData(pre_str, pre_len, (BYTE*)data_str, strlen(data_str),
562 cnt, digs);
563 multiOutput(data_str, 1, nospace, cnt, digs);
566 * case: digest stdin
568 } else if (optind == argc) {
569 multiStream(pre_str, pre_len, stdin, cnt, digs);
570 multiOutput(NULL, 0, nospace, cnt, digs);
573 * case: digest files
575 } else {
576 for (; optind < argc; optind++) {
577 multiFile(pre_str, pre_len, argv[optind], cnt, digs);
578 multiOutput(argv[optind], 0, nospace, cnt, digs);