[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.2

1.2     ! noro        1: /*
        !             2:  * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
        !             6:  * non-exclusive and royalty-free license to use, copy, modify and
        !             7:  * redistribute, solely for non-commercial and non-profit purposes, the
        !             8:  * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
        !             9:  * conditions of this Agreement. For the avoidance of doubt, you acquire
        !            10:  * only a limited right to use the SOFTWARE hereunder, and FLL or any
        !            11:  * third party developer retains all rights, including but not limited to
        !            12:  * copyrights, in and to the SOFTWARE.
        !            13:  *
        !            14:  * (1) FLL does not grant you a license in any way for commercial
        !            15:  * purposes. You may use the SOFTWARE only for non-commercial and
        !            16:  * non-profit purposes only, such as academic, research and internal
        !            17:  * business use.
        !            18:  * (2) The SOFTWARE is protected by the Copyright Law of Japan and
        !            19:  * international copyright treaties. If you make copies of the SOFTWARE,
        !            20:  * with or without modification, as permitted hereunder, you shall affix
        !            21:  * to all such copies of the SOFTWARE the above copyright notice.
        !            22:  * (3) An explicit reference to this SOFTWARE and its copyright owner
        !            23:  * shall be made on your publication or presentation in any form of the
        !            24:  * results obtained by use of the SOFTWARE.
        !            25:  * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
        !            26:  * e-mail at risa-admin@flab.fujitsu.co.jp of the detailed specification
        !            27:  * for such modification or the source code of the modified part of the
        !            28:  * SOFTWARE.
        !            29:  *
        !            30:  * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
        !            31:  * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
        !            32:  * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
        !            33:  * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
        !            34:  * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
        !            35:  * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
        !            36:  * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
        !            37:  * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
        !            38:  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
        !            39:  * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
        !            40:  * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
        !            41:  * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
        !            42:  * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
        !            43:  * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
        !            44:  * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
        !            45:  * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
        !            46:  * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
        !            47:  *
        !            48:  * $OpenXM: OpenXM_contrib2/asir2000/builtin/sha1.c,v 1.1.1.1 1999/12/03 07:39:07 noro Exp $
        !            49: */
1.1       noro       50: /* Implementation of NIST's Secure Hash Algorithm (FIPS 180)
                     51: * Lightly bummed for execution efficiency.
                     52: *
                     53: * Jim Gillogly 3 May 1993
                     54: *
                     55: * 27 Aug 93: imported LITTLE_ENDIAN mods from Peter Gutmann's implementation
                     56: * 5 Jul 94: Modified for NSA fix
                     57: *
                     58: * Compile: cc -O -o sha sha.c
                     59: *
                     60: * To remove the test wrapper and use just the nist_hash() routine,
                     61: *      compile with -DONT_WRAP
                     62: *
                     63: * To reverse byte order for little-endian machines, use -DLITTLE_ENDIAN
                     64: *
                     65: * To get the original SHA definition before the 1994 fix, use -DVERSION_0
                     66: *
                     67: * Usage: sha [-vt] [filename ...]
                     68: *
                     69: *      -v switch: output the filename as well
                     70: *      -t switch: suppress spaces between 32-bit blocks
                     71: *
                     72: *      If no input files are specified, process standard input.
                     73: *
                     74: * Output: 40-hex-digit digest of each file specified (160 bits)
                     75: *
                     76: * Synopsis of the function calls:
                     77: *
                     78: *   sha_file(char *filename, unsigned int *buffer)
                     79: *      Filename is a file to be opened and processed.
                     80: *      buffer is a user-supplied array of 5 or more ints.
                     81: *      The 5-word buffer is filled with 160 bits of non-terminated hash.
                     82: *      Returns 0 if successful, non-zero if bad file.
                     83: *
                     84: *   void sha_stream(FILE *stream, unsigned int *buffer)
                     85: *      Input is from already-opened stream, not file.
                     86: *
                     87: *   void sha_memory(char *mem, int length, unsigned int *buffer)
                     88: *      Input is a memory block "length" bytes int.
                     89: *
                     90: * Caveat:
                     91: *      Not tested for case that requires the high word of the length,
                     92: *      which would be files larger than 1/2 gig or so.
                     93: *
                     94: * Limitation:
                     95: *      sha_memory (the memory block function) will deal with blocks no inter
                     96: *      than 4 gigabytes; for inter samples, the stream version will
                     97: *      probably be most convenient (e.g. perl moby_data.pl | sha).
                     98: *
                     99: * Bugs:
                    100: *      The standard is defined for bit strings; I assume bytes.
                    101: *
                    102: * Copyright 1993, Dr. James J. Gillogly
                    103: * This code may be freely used in any application.
                    104: */
                    105:
                    106: #define ONT_WRAP    /* Using just the hash routine itself */
                    107:
                    108: /* #define VERSION_0 */  /* Define this to get the original SHA definition */
                    109:
                    110: #include <stdio.h>
                    111: #include <memory.h>
                    112:
                    113: #define VERBOSE
                    114:
                    115: #define TRUE  1
                    116: #define FALSE 0
                    117:
                    118: #define SUCCESS 0
                    119: #define FAILURE -1
                    120:
                    121: int sha_file(char* filename, unsigned int *buffer);
                    122: void sha_stream(FILE *stream, unsigned int *buffer);
                    123: void sha_memory(char *mem, unsigned int length, unsigned int *buffer);
                    124:
                    125: static void nist_guts(int file_flag, /* Input from memory, or from stream? */
                    126:             FILE *stream,
                    127:             char *mem,
                    128:             unsigned int length,
                    129:             unsigned int *buf);
                    130:
                    131: #ifndef ONT_WRAP    /* Using just the hash routine itself */
                    132:
                    133: #define HASH_SIZE 5   /* Produces 160-bit digest of the message */
                    134:
                    135: int main(int argc, char **argv)
                    136: {
                    137:   unsigned int hbuf[HASH_SIZE];
                    138:   char *s;
                    139:   int file_args = FALSE;  /* If no files, take it from stdin */
                    140:   int verbose = FALSE;
                    141:   int terse = FALSE;
                    142:
                    143: #ifdef MEMTEST
                    144:   sha_memory("abc", 3l, hbuf);     /* NIST test value from appendix A */
                    145:   if (verbose) printf("Memory:");
                    146:   if (terse) printf("%08lx%08lx%08lx%08lx%08lx\n",
                    147:     hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
                    148:   else printf("%08lx %08lx %08lx %08lx %08lx\n",
                    149:     hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
                    150: #endif
                    151:
                    152:   for (++argv; --argc; ++argv)       /* March down the arg list */
                    153:     {
                    154:       if (**argv == '-')         /* Process one or more flags */
                    155:         for (s = &(*argv)[1]; *s; s++) /* Obfuscated C contest entry */
                    156:           switch(*s)
                    157:             {
                    158:               case 'v': case 'V':
                    159:                 verbose = TRUE;
                    160:                 break;
                    161:               case 't': case 'T':
                    162:                 terse = TRUE;
                    163:                 break;
                    164:               default:
                    165:                 fprintf(stderr, "Unrecognized flag: %c\n", *s);
                    166:                 return FALSE;
                    167:             }
                    168:       else              /* Process a file */
                    169:         {
                    170:           if (verbose) printf("%s:", *argv);
                    171:           file_args = TRUE;       /* Whether or not we could read it */
                    172:
                    173:           if (sha_file(*argv, hbuf) == FAILURE)
                    174:             printf("Can't open file %s.\n", *argv);
                    175:           else
                    176:             if (terse) printf("%08lx%08lx%08lx%08lx%08lx\n",
                    177:               hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
                    178:             else printf("%08lx %08lx %08lx %08lx %08lx\n",
                    179:               hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
                    180:         }
                    181:     }
                    182:   if (! file_args)  /* No file specified */
                    183:     {
                    184:       if (verbose) printf("%s:", *argv);
                    185:       sha_stream(stdin, hbuf);
                    186:
                    187:       if (terse) printf("%08lx%08lx%08lx%08lx%08lx\n",
                    188:         hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
                    189:       else printf("%08lx %08lx %08lx %08lx %08lx\n",
                    190:         hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
                    191:     }
                    192:   return TRUE;
                    193: }
                    194:
                    195: #endif ONT_WRAP
                    196:
                    197: /* #ifdef LITTLE_ENDIAN */ /* Imported from Peter Gutmann's implementation */
                    198:
                    199: /* When run on a little-endian CPU we need to perform byte reversal on an
                    200:   array of intwords.  It is possible to make the code endianness-
                    201:   independant by fiddling around with data at the byte level, but this
                    202:   makes for very slow code, so we rely on the user to sort out endianness
                    203:   at compile time */
                    204:
                    205: static void byteReverse( unsigned int *buffer, int byteCount )
                    206: {
                    207:   unsigned int value;
                    208:   int count;
                    209:   extern int little_endian;
                    210:
                    211:   if ( !little_endian )
                    212:        return;
                    213:
                    214:   byteCount /= sizeof( unsigned int );
                    215:   for( count = 0; count < byteCount; count++ )
                    216:     {
                    217:       value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 );
                    218:       buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 );
                    219:     }
                    220: }
                    221: /* #endif */ /* LITTLE_ENDIAN */
                    222:
                    223: union intbyte
                    224: {
                    225:   unsigned int W[80];    /* Process 16 32-bit words at a time */
                    226:   char B[320];        /* But read them as bytes for counting */
                    227: };
                    228:
                    229: int sha_file(char* filename, unsigned int *buffer)    /* Hash a file */
                    230: {
                    231:   FILE *infile;
                    232:
                    233:   if ((infile = fopen(filename, "rb")) == NULL)
                    234:     {
                    235:       int i;
                    236:
                    237:       for (i = 0; i < 5; i++)
                    238:         buffer[i] = 0xdeadbeef;
                    239:       return FAILURE;
                    240:     }
                    241:   (void) sha_stream(infile, buffer);
                    242:   fclose(infile);
                    243:   return SUCCESS;
                    244: }
                    245:
                    246: void sha_memory(char *mem, unsigned int length, unsigned int *buffer)
                    247: {
                    248:   nist_guts(FALSE, (FILE *) NULL, mem, length, buffer);
                    249: }
                    250:
                    251: void sha_stream(FILE *stream, unsigned int *buffer)
                    252: {
                    253:   nist_guts(TRUE, stream, (char *) NULL, 0l, buffer);
                    254: }
                    255:
                    256: #define f0(x,y,z) (z ^ (x & (y ^ z)))       /* Magic functions */
                    257: #define f1(x,y,z) (x ^ y ^ z)
                    258: #define f2(x,y,z) ((x & y) | (z & (x | y)))
                    259: #define f3(x,y,z) (x ^ y ^ z)
                    260:
                    261: #define K0 0x5a827999               /* Magic constants */
                    262: #define K1 0x6ed9eba1
                    263: #define K2 0x8f1bbcdc
                    264: #define K3 0xca62c1d6
                    265:
                    266: #define S(n, X) ((X << n) | (X >> (32 - n)))  /* Barrel roll */
                    267:
                    268: #define r0(f, K) \
                    269:   temp = S(5, A) + f(B, C, D) + E + *p0++ + K; \
                    270:   E = D;  \
                    271:   D = C;  \
                    272:   C = S(30, B); \
                    273:   B = A;  \
                    274:   A = temp
                    275:
                    276: #ifdef VERSION_0
                    277: #define r1(f, K) \
                    278:   temp = S(5, A) + f(B, C, D) + E + \
                    279:       (*p0++ = *p1++ ^ *p2++ ^ *p3++ ^ *p4++) + K; \
                    280:   E = D;  \
                    281:   D = C;  \
                    282:   C = S(30, B); \
                    283:   B = A;  \
                    284:   A = temp
                    285: #else           /* Version 1: Summer '94 update */
                    286: #define r1(f, K) \
                    287:   temp = *p1++ ^ *p2++ ^ *p3++ ^ *p4++; \
                    288:   temp = S(5, A) + f(B, C, D) + E + (*p0++ = S(1,temp)) + K; \
                    289:   E = D;  \
                    290:   D = C;  \
                    291:   C = S(30, B); \
                    292:   B = A;  \
                    293:   A = temp
                    294: #endif
                    295:
                    296: static void nist_guts(int file_flag, /* Input from memory, or from stream? */
                    297:             FILE *stream,
                    298:             char *mem,
                    299:             unsigned int length,
                    300:             unsigned int *buf)
                    301: {
                    302:   int i, nread, nbits;
                    303:   union intbyte d;
                    304:   unsigned int hi_length, lo_length;
                    305:   int padded;
                    306:   char *s;
                    307:
                    308:   register unsigned int *p0, *p1, *p2, *p3, *p4;
                    309:   unsigned int A, B, C, D, E, temp;
                    310:
                    311:   unsigned int h0, h1, h2, h3, h4;
                    312:
                    313:   h0 = 0x67452301;              /* Accumulators */
                    314:   h1 = 0xefcdab89;
                    315:   h2 = 0x98badcfe;
                    316:   h3 = 0x10325476;
                    317:   h4 = 0xc3d2e1f0;
                    318:
                    319:   padded = FALSE;
                    320:   s = mem;
                    321:   for (hi_length = lo_length = 0; ;)  /* Process 16 ints at a time */
                    322:     {
                    323:       if (file_flag)
                    324:         {
                    325:           nread = fread(d.B, 1, 64, stream);  /* Read as 64 bytes */
                    326:         }
                    327:       else
                    328:         {
                    329:           if (length < 64) nread = length;
                    330:           else       nread = 64;
                    331:           length -= nread;
                    332:           memcpy(d.B, s, nread);
                    333:           s += nread;
                    334:         }
                    335:       if (nread < 64)   /* Partial block? */
                    336:         {
                    337:           nbits = nread << 3;         /* Length: bits */
                    338:           if ((lo_length += nbits) < nbits)
                    339:             hi_length++;        /* 64-bit integer */
                    340:
                    341:           if (nread < 64 && ! padded)  /* Append a single bit */
                    342:             {
                    343:               d.B[nread++] = 0x80; /* Using up next byte */
                    344:               padded = TRUE;     /* Single bit once */
                    345:             }
                    346:           for (i = nread; i < 64; i++) /* Pad with nulls */
                    347:             d.B[i] = 0;
                    348:           if (nread <= 56)   /* Room for length in this block */
                    349:             {
                    350:               d.W[14] = hi_length;
                    351:               d.W[15] = lo_length;
                    352: /* #ifdef LITTLE_ENDIAN */
                    353:               byteReverse(d.W, 56 );
                    354: /* #endif */ /* LITTLE_ENDIAN */
                    355:             }
                    356: /* #ifdef LITTLE_ENDIAN */
                    357:           else
                    358:             byteReverse(d.W, 64 );
                    359: /* #endif */ /* LITTLE_ENDIAN */
                    360:         }
                    361:       else  /* Full block -- get efficient */
                    362:         {
                    363:           if ((lo_length += 512) < 512)
                    364:             hi_length++;  /* 64-bit integer */
                    365: /* #ifdef LITTLE_ENDIAN */
                    366:           byteReverse(d.W, 64 );
                    367: /* #endif */ /* LITTLE_ENDIAN */
                    368:         }
                    369:
                    370:       p0 = d.W;
                    371:       A = h0; B = h1; C = h2; D = h3; E = h4;
                    372:
                    373:       r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
                    374:       r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
                    375:       r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
                    376:       r0(f0,K0);
                    377:
                    378:       p1 = &d.W[13]; p2 = &d.W[8]; p3 = &d.W[2]; p4 = &d.W[0];
                    379:
                    380:       r1(f0,K0); r1(f0,K0); r1(f0,K0); r1(f0,K0);
                    381:       r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
                    382:       r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
                    383:       r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
                    384:       r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
                    385:       r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
                    386:       r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
                    387:       r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
                    388:       r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
                    389:       r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
                    390:       r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
                    391:       r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
                    392:       r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
                    393:
                    394:       h0 += A; h1 += B; h2 += C; h3 += D; h4 += E;
                    395:
                    396:       if (nread <= 56) break; /* If it's greater, length in next block */
                    397:     }
                    398:   buf[0] = h0; buf[1] = h1; buf[2] = h2; buf[3] = h3; buf[4] = h4;
                    399: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>