[BACK]Return to sha1.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / builtin

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>