limit fstBC to 30bp in Python3 ver.
[GalaxyCodeBases.git] / c_cpp / etc / md5_sha / shsdual.c
blob65965799717f55d0a903515d81dc841e3710fbf4
1 /*
2 * shsdual - old shs dual digest code
4 * @(#) $Revision: 13.2 $
5 * @(#) $Id: shsdual.c,v 13.2 2006/08/14 10:09:23 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/hash/RCS/shsdual.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 * Split our data into multiple byte index streams, digest them all
15 * and output the digests on a line.
17 * This file was written by Landon Curt Noll.
19 * This code has been placed in the public domain. Please do not
20 * copyright this code.
22 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO
23 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MER-
24 * CHANTABILITY AND FITNESS. IN NO EVENT SHALL LANDON CURT
25 * NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
26 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
27 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
28 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 * chongo (was here) /\oo/\
32 * http://www.isthe.com/chongo/index.html
34 * Share and enjoy! :-)
36 * See shsdrvr.c for version and modification history.
39 char *shsdual_what="@(#)"; /* #(@) if checked in */
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include "shs.h"
47 /* static declarations */
48 static void multiData(BYTE*, UINT, BYTE*, UINT, UINT, SHS_INFO*);
49 static void multiStream(BYTE*, UINT, FILE*, UINT, SHS_INFO*);
50 static void multiFile(BYTE*, UINT, char*, UINT, SHS_INFO*);
51 static void multiOutput(char*, int, int, UINT, SHS_INFO*);
53 /* dual test suite strings */
54 #define ENTRY(str) {(BYTE *)str, sizeof(str)-1}
55 struct dual_test {
56 BYTE *data; /* data or NULL to test */
57 int len; /* length of data */
58 } dual_test_data[] = {
59 {NULL, 0},
60 ENTRY(""),
61 ENTRY("a"),
62 ENTRY("aa"),
63 ENTRY("aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz"),
64 ENTRY("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
65 ENTRY("chongo <Ich bin, du bist, aber ein Yit ist nicht!!! :-)> /\\../\\"),
66 ENTRY("123456789 123456789 123456789 123456789 123456789 123456789 1234"),
67 ENTRY("a123456789 123456789 123456789 123456789 123456789 123456789 1234")
69 #define MAX_DUAL_TEST_DATA (sizeof(dual_test_data)/sizeof(dual_test_data[0]))
71 /* dual test filenames */
72 char *dual_test_file[] = {
73 "file1",
74 "file2",
75 "shs.data",
76 "/dev/null"
78 #define MAX_DUAL_TEST_FILE (sizeof(dual_test_file)/sizeof(dual_test_file[0]))
80 /* where the test files are located by default */
81 #if !defined(TLIB)
82 #define TLIB "."
83 #endif
87 * multiData - divide data into multiple sections
89 * given:
90 * pre_str string prefix or NULL
91 * pre_len length of pre_str
92 * inString string to digest
93 * in_len length of inString
94 * cnt number of digests
95 * digs array of digests, cnt elements long
97 static void
98 multiData(BYTE *pre_str, UINT pre_len, BYTE *inString, UINT in_len,
99 UINT cnt, SHS_INFO *digs)
101 BYTE **bufs; /* byte arrays for digests */
102 UINT *buflen; /* bytes stored in bufs[i] */
103 int len; /* total length of pre_str and inString */
104 UINT indx; /* byte stream index */
105 BYTE **n; /* n[i] is next byte to use in bufs[i] */
106 BYTE *p;
107 UINT i;
110 * determine lengths
112 len = (pre_str == NULL) ? 0 : pre_len;
113 len += (inString == NULL) ? 0 : in_len;
114 /* no strings, quick return */
115 if (len == 0 || cnt <= 0) {
116 return;
120 * malloc string arrays
122 bufs = (BYTE **)malloc(sizeof(BYTE *)*cnt);
123 if (bufs == NULL) {
124 fprintf(stderr, "%s: bad malloc #1\n", program);
125 exit(51);
127 buflen = (UINT *)malloc(sizeof(UINT)*cnt);
128 if (buflen == NULL) {
129 fprintf(stderr, "%s: bad malloc #2\n", program);
130 exit(52);
132 n = (BYTE **)malloc(sizeof(BYTE *)*cnt);
133 if (n == NULL) {
134 fprintf(stderr, "%s: bad malloc #3\n", program);
135 exit(53);
137 for (i=0; i < cnt; ++i) {
138 bufs[i] = (BYTE *)malloc(1+(len/cnt));
139 if (bufs[i] == NULL) {
140 fprintf(stderr, "%s: bad malloc #4\n", program);
141 exit(54);
143 buflen[i] = 0;
144 n[i] = bufs[i];
148 * divide the pre-string
150 indx = 0;
151 if (pre_str != NULL) {
152 for (p=pre_str, i=0; i < pre_len; ++i, ++p, indx++) {
153 *(n[(indx = ((indx >= cnt) ? 0 : indx))]++) = *p;
154 ++buflen[indx];
159 * divide the string
161 if (inString != NULL) {
162 for (p=inString, i=0; i < in_len; ++indx, ++i, ++p) {
163 *(n[(indx = ((indx >= cnt) ? 0 : indx))]++) = *p;
164 ++buflen[indx];
169 * update arrays
171 for (i=0; i < cnt; ++i) {
172 shsUpdate(digs+i, bufs[i], buflen[i]);
176 * cleanup
178 free(buflen);
179 free(n);
180 for (i=0; i < cnt; ++i) {
181 free(bufs[i]);
183 free(bufs);
188 * multiStream - divide a Stream into multiple sections
190 * given:
191 * pre_str data prefix or NULL
192 * pre_len length of pre_str
193 * stream the stream to process
194 * cnt number of digests
195 * digs array of digests, cnt elements long
197 static void
198 multiStream(BYTE *pre_str, UINT pre_len, FILE *stream, UINT cnt, SHS_INFO *digs)
200 BYTE data[SHS_READSIZE]; /* our read buffer */
201 int bytes; /* bytes last read */
202 BYTE **bufs; /* byte arrays for digests */
203 UINT *buflen; /* bytes stored in bufs[i] */
204 UINT indx; /* byte stream index */
205 BYTE *pbeyond; /* beyond end of used data or pre_str */
206 BYTE **n; /* n[i] is next byte to use in bufs[i] */
207 BYTE *p;
208 UINT i;
211 * no sets, quick return
213 if (cnt <= 0) {
214 return;
218 * malloc string arrays
220 bufs = (BYTE **)malloc(sizeof(BYTE *)*cnt);
221 if (bufs == NULL) {
222 fprintf(stderr, "%s: bad malloc #5\n", program);
223 exit(55);
225 buflen = (UINT *)malloc(sizeof(UINT)*cnt);
226 if (buflen == NULL) {
227 fprintf(stderr, "%s: bad malloc #6\n", program);
228 exit(56);
230 n = (BYTE **)malloc(sizeof(BYTE *)*cnt);
231 if (n == NULL) {
232 fprintf(stderr, "%s: bad malloc #7\n", program);
233 exit(57);
235 for (i=0; i < cnt; ++i) {
236 bufs[i] = (BYTE *)malloc(SHS_BLOCKSIZE);
237 if (bufs[i] == NULL) {
238 fprintf(stderr, "%s: bad malloc #8\n", program);
239 exit(58);
241 buflen[i] = 0;
242 n[i] = bufs[i];
246 * divide the pre-string
248 indx = 0;
249 if (pre_str != NULL && pre_len > 0) {
250 for (p=pre_str, pbeyond=pre_str+pre_len; p < pbeyond; ++p, ++indx) {
251 *(n[(indx = ((indx >= cnt) ? 0 : indx))]++) = *p;
252 if (++buflen[indx] >= SHS_BLOCKSIZE) {
253 shsUpdate(digs+indx, bufs[indx], SHS_BLOCKSIZE);
254 buflen[indx] = 0;
255 n[indx] = bufs[indx];
261 * process the contents of the file
263 while ((bytes = fread((char *)data, 1, SHS_READSIZE, stream)) > 0) {
266 * load the bytes into the bufs
268 for (p=data, pbeyond=data+bytes; p < pbeyond; ++p, ++indx) {
269 *(n[(indx = ((indx >= cnt) ? 0 : indx))]++) = *p;
270 if (++buflen[indx] >= SHS_BLOCKSIZE) {
271 shsUpdate(digs+indx, bufs[indx], SHS_BLOCKSIZE);
272 buflen[indx] = 0;
273 n[indx] = bufs[indx];
279 * process any partial buffers
281 for (i=0; i < cnt; ++i) {
282 if (buflen[i] > 0) {
283 shsUpdate(digs+i, bufs[i], buflen[i]);
288 * cleanup
290 free(buflen);
291 free(n);
292 for (i=0; i < cnt; ++i) {
293 free(bufs[i]);
295 free(bufs);
300 * multiFile - divide a file into alternating bytes and digest both halves
302 * given:
303 * pre_str string prefix or NULL
304 * pre_len length of pre_str
305 * filename the filename to process
306 * cnt number of digests
307 * digs array of digests, cnt elements long
309 static void
310 multiFile(BYTE *pre_str, UINT pre_len, char *filename, UINT cnt, SHS_INFO *digs)
312 FILE *inFile; /* the open file stream */
313 struct stat buf; /* stat or lstat of file */
314 struct shs_stat hashbuf; /* stat data to digest */
315 struct shs_stat hashlbuf; /* lstat data to digest */
316 UINT i;
319 * firewall
321 if (cnt <= 0) {
322 return;
326 * open the file
328 inFile = fopen(filename, "rb");
329 if (inFile == NULL) {
330 fprintf(stderr, "%s: cannot open %s: ", program, filename);
331 perror("");
332 return;
336 * pre-process prefix if needed
338 if (pre_str == NULL || pre_len <= 0) {
339 if (i_flag) {
340 multiData(NULL, 0, (BYTE *)filename, strlen(filename), cnt, digs);
342 } else {
343 if (i_flag) {
344 multiData(pre_str, pre_len, (BYTE *)filename, strlen(filename),
345 cnt, digs);
346 } else {
347 multiData(pre_str, pre_len, NULL, 0, cnt, digs);
352 * digest file stat and lstat
354 if (i_flag) {
355 if (fstat(fileno(inFile), &buf) < 0) {
356 printf("%s can't be stated.\n", filename);
357 return;
359 hashbuf.stat_dev = buf.st_dev;
360 hashbuf.stat_ino = buf.st_ino;
361 hashbuf.stat_mode = buf.st_mode;
362 hashbuf.stat_nlink = buf.st_nlink;
363 hashbuf.stat_uid = buf.st_uid;
364 hashbuf.stat_gid = buf.st_gid;
365 hashbuf.stat_size = buf.st_size;
366 hashbuf.stat_mtime = buf.st_mtime;
367 hashbuf.stat_ctime = buf.st_ctime;
368 if (lstat(filename, &buf) < 0) {
369 printf("%s can't be lstated.\n", filename);
370 return;
372 hashlbuf.stat_dev = buf.st_dev;
373 hashlbuf.stat_ino = buf.st_ino;
374 hashlbuf.stat_mode = buf.st_mode;
375 hashlbuf.stat_nlink = buf.st_nlink;
376 hashlbuf.stat_uid = buf.st_uid;
377 hashlbuf.stat_gid = buf.st_gid;
378 hashlbuf.stat_size = buf.st_size;
379 hashlbuf.stat_mtime = buf.st_mtime;
380 hashlbuf.stat_ctime = buf.st_ctime;
381 multiData((BYTE *)&hashbuf, sizeof(hashbuf), (BYTE *)&hashlbuf,
382 sizeof(hashlbuf), cnt, digs);
385 * pad sections with zeros to process file data faster
387 for (i=0; i < cnt; ++i) {
388 if (digs[i].datalen > 0) {
389 shsUpdate(digs+i, (BYTE *)shs_zero,
390 SHS_CHUNKSIZE - digs[i].datalen);
396 * process the data stream
398 multiStream(NULL, 0, inFile, cnt, digs);
399 fclose(inFile);
404 * multiOutput - output the multiple digests
406 * given:
407 * str print string after digest, NULL => none
408 * quot 1 => surround str with a double quotes
409 * nospace 1 => don't space seperate multi digests
410 * cnt number of digests
411 * digs array of digests, cnt elements long
413 static void
414 multiOutput(str, quot, nospace, cnt, digs)
415 char *str; /* print string after digest, NULL => none */
416 int quot; /* 1 => surround str with a double quotes */
417 int nospace; /* 1 => don't space seperate multi digests */
418 UINT cnt; /* number of digests */
419 SHS_INFO *digs; /* array of digests, cnt elements long */
421 UINT i;
424 * firewall
426 if (cnt <= 0) {
427 return;
431 * finalize the sets
433 for (i=0; i < cnt; ++i) {
434 shsFinal(digs+i);
438 * print the digests
440 shsPrint(c_flag, 0, digs);
441 for (i=1; i < cnt-1; ++i) {
442 if (nospace == 0) {
443 putchar(' ');
444 shsPrint(c_flag, 0, digs+i);
445 } else {
446 shsPrint(0, 0, digs+i);
449 if (i < cnt) {
450 if (nospace == 0) {
451 putchar(' ');
452 shsPrint(c_flag, i_flag, digs+cnt-1);
453 } else {
454 shsPrint(0, i_flag, digs+cnt-1);
457 if (str && !q_flag) {
458 if (quot) {
459 printf(" \"%s\"\n", str);
460 } else {
461 printf(" %s\n", str);
463 } else {
464 putchar('\n');
470 * multiTest - shs dual test suite
472 void
473 multiTest(void)
475 struct dual_test *t; /* current dual test */
476 struct dual_test *p; /* current dual pre-string test */
477 struct stat buf; /* stat of a test file */
478 SHS_INFO digs[2]; /* even byte digest */
479 char **f; /* current file being tested */
480 unsigned int i;
481 unsigned int j;
484 * find all of the test files
486 for (i=0, f=dual_test_file; i < MAX_DUAL_TEST_FILE; ++i, ++f) {
487 if (stat(*f, &buf) < 0) {
488 /* no file1 in this directory, cd to the test suite directory */
489 if (chdir(TLIB) < 0) {
490 fflush(stdout);
491 fprintf(stderr,
492 "%s: cannot find %s or %s/%s\n", program, *f, TLIB, *f);
493 return;
499 * try all combinations of test strings as prefixes and data
501 for (i=0, t=dual_test_data; i < MAX_DUAL_TEST_DATA; ++i, ++t) {
502 for (j=1, p=dual_test_data+1; j < MAX_DUAL_TEST_DATA; ++j, ++p) {
503 printf("pre:%u data:%u\n", i, j);
504 shsInit(digs+0);
505 shsInit(digs+1);
506 multiData(p->data, p->len, t->data, t->len, 2, digs);
507 multiOutput(NULL, 0, 0, 2, digs);
512 * try the files with all test strings as prefixes
514 for (i=0, p=dual_test_data; i < MAX_DUAL_TEST_DATA; ++i, ++p) {
515 for (j=0, f=dual_test_file; j < MAX_DUAL_TEST_FILE; ++j, ++f) {
516 printf("pre:%d file:%s\n", i, *f);
517 shsInit(digs+0);
518 shsInit(digs+1);
519 multiFile(p->data, p->len, *f, 2, digs);
520 multiOutput(NULL, 0, 0, 2, digs);
523 exit(0);
528 * multiMain - main driver of shs dual routines
530 * given:
531 * c arg count left after getopt
532 * argv args left after getopt
533 * pre_str pre-process this data first
534 * pre_len length of pre_str
535 * data_str data is this string, not a file
536 * nospace 1 => don't space seperate multi digests
537 * cnt number of digests to perform
539 void
540 multiMain(int argc, char **argv, BYTE *pre_str, UINT pre_len,
541 char *data_str, int nospace, UINT cnt)
543 extern int optind; /* option index */
544 SHS_INFO *digs; /* multiple digest */
545 unsigned int i;
548 * firewall
550 if (cnt <= 0) {
551 return;
555 * initialize multiple digests
557 digs = (SHS_INFO *)malloc(sizeof(SHS_INFO)*cnt);
558 if (digs == NULL) {
559 fprintf(stderr, "%s: bad malloc #1\n", program);
560 exit(60);
562 for (i=0; i < cnt; ++i) {
563 shsInit(digs+i);
567 * digest a string
569 if (data_str != NULL) {
570 multiData(pre_str, pre_len, (BYTE*)data_str, strlen(data_str),
571 cnt, digs);
572 multiOutput(data_str, 1, nospace, cnt, digs);
575 * case: digest stdin
577 } else if (optind == argc) {
578 multiStream(pre_str, pre_len, stdin, cnt, digs);
579 multiOutput(NULL, 0, nospace, cnt, digs);
582 * case: digest files
584 } else {
585 for (; optind < argc; optind++) {
586 multiFile(pre_str, pre_len, argv[optind], cnt, digs);
587 multiOutput(argv[optind], 0, nospace, cnt, digs);