Annotation of OpenXM_contrib2/asir2000/builtin/sha1.c, Revision 1.1.1.1
1.1 noro 1: /* $OpenXM: OpenXM/src/asir99/builtin/sha1.c,v 1.1.1.1 1999/11/10 08:12:26 noro Exp $ */
2: /* Implementation of NIST's Secure Hash Algorithm (FIPS 180)
3: * Lightly bummed for execution efficiency.
4: *
5: * Jim Gillogly 3 May 1993
6: *
7: * 27 Aug 93: imported LITTLE_ENDIAN mods from Peter Gutmann's implementation
8: * 5 Jul 94: Modified for NSA fix
9: *
10: * Compile: cc -O -o sha sha.c
11: *
12: * To remove the test wrapper and use just the nist_hash() routine,
13: * compile with -DONT_WRAP
14: *
15: * To reverse byte order for little-endian machines, use -DLITTLE_ENDIAN
16: *
17: * To get the original SHA definition before the 1994 fix, use -DVERSION_0
18: *
19: * Usage: sha [-vt] [filename ...]
20: *
21: * -v switch: output the filename as well
22: * -t switch: suppress spaces between 32-bit blocks
23: *
24: * If no input files are specified, process standard input.
25: *
26: * Output: 40-hex-digit digest of each file specified (160 bits)
27: *
28: * Synopsis of the function calls:
29: *
30: * sha_file(char *filename, unsigned int *buffer)
31: * Filename is a file to be opened and processed.
32: * buffer is a user-supplied array of 5 or more ints.
33: * The 5-word buffer is filled with 160 bits of non-terminated hash.
34: * Returns 0 if successful, non-zero if bad file.
35: *
36: * void sha_stream(FILE *stream, unsigned int *buffer)
37: * Input is from already-opened stream, not file.
38: *
39: * void sha_memory(char *mem, int length, unsigned int *buffer)
40: * Input is a memory block "length" bytes int.
41: *
42: * Caveat:
43: * Not tested for case that requires the high word of the length,
44: * which would be files larger than 1/2 gig or so.
45: *
46: * Limitation:
47: * sha_memory (the memory block function) will deal with blocks no inter
48: * than 4 gigabytes; for inter samples, the stream version will
49: * probably be most convenient (e.g. perl moby_data.pl | sha).
50: *
51: * Bugs:
52: * The standard is defined for bit strings; I assume bytes.
53: *
54: * Copyright 1993, Dr. James J. Gillogly
55: * This code may be freely used in any application.
56: */
57:
58: #define ONT_WRAP /* Using just the hash routine itself */
59:
60: /* #define VERSION_0 */ /* Define this to get the original SHA definition */
61:
62: #include <stdio.h>
63: #include <memory.h>
64:
65: #define VERBOSE
66:
67: #define TRUE 1
68: #define FALSE 0
69:
70: #define SUCCESS 0
71: #define FAILURE -1
72:
73: int sha_file(char* filename, unsigned int *buffer);
74: void sha_stream(FILE *stream, unsigned int *buffer);
75: void sha_memory(char *mem, unsigned int length, unsigned int *buffer);
76:
77: static void nist_guts(int file_flag, /* Input from memory, or from stream? */
78: FILE *stream,
79: char *mem,
80: unsigned int length,
81: unsigned int *buf);
82:
83: #ifndef ONT_WRAP /* Using just the hash routine itself */
84:
85: #define HASH_SIZE 5 /* Produces 160-bit digest of the message */
86:
87: int main(int argc, char **argv)
88: {
89: unsigned int hbuf[HASH_SIZE];
90: char *s;
91: int file_args = FALSE; /* If no files, take it from stdin */
92: int verbose = FALSE;
93: int terse = FALSE;
94:
95: #ifdef MEMTEST
96: sha_memory("abc", 3l, hbuf); /* NIST test value from appendix A */
97: if (verbose) printf("Memory:");
98: if (terse) printf("%08lx%08lx%08lx%08lx%08lx\n",
99: hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
100: else printf("%08lx %08lx %08lx %08lx %08lx\n",
101: hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
102: #endif
103:
104: for (++argv; --argc; ++argv) /* March down the arg list */
105: {
106: if (**argv == '-') /* Process one or more flags */
107: for (s = &(*argv)[1]; *s; s++) /* Obfuscated C contest entry */
108: switch(*s)
109: {
110: case 'v': case 'V':
111: verbose = TRUE;
112: break;
113: case 't': case 'T':
114: terse = TRUE;
115: break;
116: default:
117: fprintf(stderr, "Unrecognized flag: %c\n", *s);
118: return FALSE;
119: }
120: else /* Process a file */
121: {
122: if (verbose) printf("%s:", *argv);
123: file_args = TRUE; /* Whether or not we could read it */
124:
125: if (sha_file(*argv, hbuf) == FAILURE)
126: printf("Can't open file %s.\n", *argv);
127: else
128: if (terse) printf("%08lx%08lx%08lx%08lx%08lx\n",
129: hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
130: else printf("%08lx %08lx %08lx %08lx %08lx\n",
131: hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
132: }
133: }
134: if (! file_args) /* No file specified */
135: {
136: if (verbose) printf("%s:", *argv);
137: sha_stream(stdin, hbuf);
138:
139: if (terse) printf("%08lx%08lx%08lx%08lx%08lx\n",
140: hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
141: else printf("%08lx %08lx %08lx %08lx %08lx\n",
142: hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
143: }
144: return TRUE;
145: }
146:
147: #endif ONT_WRAP
148:
149: /* #ifdef LITTLE_ENDIAN */ /* Imported from Peter Gutmann's implementation */
150:
151: /* When run on a little-endian CPU we need to perform byte reversal on an
152: array of intwords. It is possible to make the code endianness-
153: independant by fiddling around with data at the byte level, but this
154: makes for very slow code, so we rely on the user to sort out endianness
155: at compile time */
156:
157: static void byteReverse( unsigned int *buffer, int byteCount )
158: {
159: unsigned int value;
160: int count;
161: extern int little_endian;
162:
163: if ( !little_endian )
164: return;
165:
166: byteCount /= sizeof( unsigned int );
167: for( count = 0; count < byteCount; count++ )
168: {
169: value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 );
170: buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 );
171: }
172: }
173: /* #endif */ /* LITTLE_ENDIAN */
174:
175: union intbyte
176: {
177: unsigned int W[80]; /* Process 16 32-bit words at a time */
178: char B[320]; /* But read them as bytes for counting */
179: };
180:
181: int sha_file(char* filename, unsigned int *buffer) /* Hash a file */
182: {
183: FILE *infile;
184:
185: if ((infile = fopen(filename, "rb")) == NULL)
186: {
187: int i;
188:
189: for (i = 0; i < 5; i++)
190: buffer[i] = 0xdeadbeef;
191: return FAILURE;
192: }
193: (void) sha_stream(infile, buffer);
194: fclose(infile);
195: return SUCCESS;
196: }
197:
198: void sha_memory(char *mem, unsigned int length, unsigned int *buffer)
199: {
200: nist_guts(FALSE, (FILE *) NULL, mem, length, buffer);
201: }
202:
203: void sha_stream(FILE *stream, unsigned int *buffer)
204: {
205: nist_guts(TRUE, stream, (char *) NULL, 0l, buffer);
206: }
207:
208: #define f0(x,y,z) (z ^ (x & (y ^ z))) /* Magic functions */
209: #define f1(x,y,z) (x ^ y ^ z)
210: #define f2(x,y,z) ((x & y) | (z & (x | y)))
211: #define f3(x,y,z) (x ^ y ^ z)
212:
213: #define K0 0x5a827999 /* Magic constants */
214: #define K1 0x6ed9eba1
215: #define K2 0x8f1bbcdc
216: #define K3 0xca62c1d6
217:
218: #define S(n, X) ((X << n) | (X >> (32 - n))) /* Barrel roll */
219:
220: #define r0(f, K) \
221: temp = S(5, A) + f(B, C, D) + E + *p0++ + K; \
222: E = D; \
223: D = C; \
224: C = S(30, B); \
225: B = A; \
226: A = temp
227:
228: #ifdef VERSION_0
229: #define r1(f, K) \
230: temp = S(5, A) + f(B, C, D) + E + \
231: (*p0++ = *p1++ ^ *p2++ ^ *p3++ ^ *p4++) + K; \
232: E = D; \
233: D = C; \
234: C = S(30, B); \
235: B = A; \
236: A = temp
237: #else /* Version 1: Summer '94 update */
238: #define r1(f, K) \
239: temp = *p1++ ^ *p2++ ^ *p3++ ^ *p4++; \
240: temp = S(5, A) + f(B, C, D) + E + (*p0++ = S(1,temp)) + K; \
241: E = D; \
242: D = C; \
243: C = S(30, B); \
244: B = A; \
245: A = temp
246: #endif
247:
248: static void nist_guts(int file_flag, /* Input from memory, or from stream? */
249: FILE *stream,
250: char *mem,
251: unsigned int length,
252: unsigned int *buf)
253: {
254: int i, nread, nbits;
255: union intbyte d;
256: unsigned int hi_length, lo_length;
257: int padded;
258: char *s;
259:
260: register unsigned int *p0, *p1, *p2, *p3, *p4;
261: unsigned int A, B, C, D, E, temp;
262:
263: unsigned int h0, h1, h2, h3, h4;
264:
265: h0 = 0x67452301; /* Accumulators */
266: h1 = 0xefcdab89;
267: h2 = 0x98badcfe;
268: h3 = 0x10325476;
269: h4 = 0xc3d2e1f0;
270:
271: padded = FALSE;
272: s = mem;
273: for (hi_length = lo_length = 0; ;) /* Process 16 ints at a time */
274: {
275: if (file_flag)
276: {
277: nread = fread(d.B, 1, 64, stream); /* Read as 64 bytes */
278: }
279: else
280: {
281: if (length < 64) nread = length;
282: else nread = 64;
283: length -= nread;
284: memcpy(d.B, s, nread);
285: s += nread;
286: }
287: if (nread < 64) /* Partial block? */
288: {
289: nbits = nread << 3; /* Length: bits */
290: if ((lo_length += nbits) < nbits)
291: hi_length++; /* 64-bit integer */
292:
293: if (nread < 64 && ! padded) /* Append a single bit */
294: {
295: d.B[nread++] = 0x80; /* Using up next byte */
296: padded = TRUE; /* Single bit once */
297: }
298: for (i = nread; i < 64; i++) /* Pad with nulls */
299: d.B[i] = 0;
300: if (nread <= 56) /* Room for length in this block */
301: {
302: d.W[14] = hi_length;
303: d.W[15] = lo_length;
304: /* #ifdef LITTLE_ENDIAN */
305: byteReverse(d.W, 56 );
306: /* #endif */ /* LITTLE_ENDIAN */
307: }
308: /* #ifdef LITTLE_ENDIAN */
309: else
310: byteReverse(d.W, 64 );
311: /* #endif */ /* LITTLE_ENDIAN */
312: }
313: else /* Full block -- get efficient */
314: {
315: if ((lo_length += 512) < 512)
316: hi_length++; /* 64-bit integer */
317: /* #ifdef LITTLE_ENDIAN */
318: byteReverse(d.W, 64 );
319: /* #endif */ /* LITTLE_ENDIAN */
320: }
321:
322: p0 = d.W;
323: A = h0; B = h1; C = h2; D = h3; E = h4;
324:
325: r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
326: r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
327: r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
328: r0(f0,K0);
329:
330: p1 = &d.W[13]; p2 = &d.W[8]; p3 = &d.W[2]; p4 = &d.W[0];
331:
332: r1(f0,K0); r1(f0,K0); r1(f0,K0); r1(f0,K0);
333: r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
334: r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
335: r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
336: r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
337: r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
338: r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
339: r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
340: r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
341: r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
342: r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
343: r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
344: r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
345:
346: h0 += A; h1 += B; h2 += C; h3 += D; h4 += E;
347:
348: if (nread <= 56) break; /* If it's greater, length in next block */
349: }
350: buf[0] = h0; buf[1] = h1; buf[2] = h2; buf[3] = h3; buf[4] = h4;
351: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>