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

File: [local] / OpenXM_contrib2 / asir2018 / builtin / sha1.c (download)

Revision 1.1, Wed Sep 19 05:45:06 2018 UTC (5 years, 6 months ago) by noro
Branch: MAIN
CVS Tags: HEAD

Added asir2018 for implementing full-gmp asir.

/*
 * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED 
 * All rights reserved.
 * 
 * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
 * non-exclusive and royalty-free license to use, copy, modify and
 * redistribute, solely for non-commercial and non-profit purposes, the
 * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
 * conditions of this Agreement. For the avoidance of doubt, you acquire
 * only a limited right to use the SOFTWARE hereunder, and FLL or any
 * third party developer retains all rights, including but not limited to
 * copyrights, in and to the SOFTWARE.
 * 
 * (1) FLL does not grant you a license in any way for commercial
 * purposes. You may use the SOFTWARE only for non-commercial and
 * non-profit purposes only, such as academic, research and internal
 * business use.
 * (2) The SOFTWARE is protected by the Copyright Law of Japan and
 * international copyright treaties. If you make copies of the SOFTWARE,
 * with or without modification, as permitted hereunder, you shall affix
 * to all such copies of the SOFTWARE the above copyright notice.
 * (3) An explicit reference to this SOFTWARE and its copyright owner
 * shall be made on your publication or presentation in any form of the
 * results obtained by use of the SOFTWARE.
 * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
 * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
 * for such modification or the source code of the modified part of the
 * SOFTWARE.
 * 
 * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
 * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
 * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
 * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
 * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
 * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
 * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
 * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
 * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
 * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
 * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
 * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
 * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
 * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
 * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
 *
 * $OpenXM: OpenXM_contrib2/asir2018/builtin/sha1.c,v 1.1 2018/09/19 05:45:06 noro Exp $
*/
/* Implementation of NIST's Secure Hash Algorithm (FIPS 180)
* Lightly bummed for execution efficiency.
*
* Jim Gillogly 3 May 1993
*
* 27 Aug 93: imported LITTLE_ENDIAN mods from Peter Gutmann's implementation
* 5 Jul 94: Modified for NSA fix
*
* Compile: cc -O -o sha sha.c
*
* To remove the test wrapper and use just the nist_hash() routine,
*      compile with -DONT_WRAP
*
* To reverse byte order for little-endian machines, use -DLITTLE_ENDIAN
*
* To get the original SHA definition before the 1994 fix, use -DVERSION_0
*
* Usage: sha [-vt] [filename ...]
*
*      -v switch: output the filename as well
*      -t switch: suppress spaces between 32-bit blocks
*
*      If no input files are specified, process standard input.
*
* Output: 40-hex-digit digest of each file specified (160 bits)
*
* Synopsis of the function calls:
*
*   sha_file(char *filename, unsigned int *buffer)
*      Filename is a file to be opened and processed.
*      buffer is a user-supplied array of 5 or more ints.
*      The 5-word buffer is filled with 160 bits of non-terminated hash.
*      Returns 0 if successful, non-zero if bad file.
*
*   void sha_stream(FILE *stream, unsigned int *buffer)
*      Input is from already-opened stream, not file.
*
*   void sha_memory(char *mem, int length, unsigned int *buffer)
*      Input is a memory block "length" bytes int.
*
* Caveat:
*      Not tested for case that requires the high word of the length,
*      which would be files larger than 1/2 gig or so.
*
* Limitation:
*      sha_memory (the memory block function) will deal with blocks no inter
*      than 4 gigabytes; for inter samples, the stream version will
*      probably be most convenient (e.g. perl moby_data.pl | sha).
*
* Bugs:
*      The standard is defined for bit strings; I assume bytes.
*
* Copyright 1993, Dr. James J. Gillogly
* This code may be freely used in any application.
*/

#define ONT_WRAP    /* Using just the hash routine itself */

/* #define VERSION_0 */  /* Define this to get the original SHA definition */

#include <stdio.h>
#include <memory.h>

#define VERBOSE

#define TRUE  1
#define FALSE 0

#define SUCCESS 0
#define FAILURE -1

int sha_file(char* filename, unsigned int *buffer);
void sha_stream(FILE *stream, unsigned int *buffer);
void sha_memory(char *mem, unsigned int length, unsigned int *buffer);

static void nist_guts(int file_flag, /* Input from memory, or from stream? */
            FILE *stream,
            char *mem,
            unsigned int length,
            unsigned int *buf);

#ifndef ONT_WRAP    /* Using just the hash routine itself */

#define HASH_SIZE 5   /* Produces 160-bit digest of the message */

int main(int argc, char **argv)
{
  unsigned int hbuf[HASH_SIZE];
  char *s;
  int file_args = FALSE;  /* If no files, take it from stdin */
  int verbose = FALSE;
  int terse = FALSE;

#ifdef MEMTEST
  sha_memory("abc", 3l, hbuf);     /* NIST test value from appendix A */
  if (verbose) printf("Memory:");
  if (terse) printf("%08lx%08lx%08lx%08lx%08lx\n",
    hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
  else printf("%08lx %08lx %08lx %08lx %08lx\n",
    hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
#endif

  for (++argv; --argc; ++argv)       /* March down the arg list */
    {
      if (**argv == '-')         /* Process one or more flags */
        for (s = &(*argv)[1]; *s; s++) /* Obfuscated C contest entry */
          switch(*s)
            {
              case 'v': case 'V':
                verbose = TRUE;
                break;
              case 't': case 'T':
                terse = TRUE;
                break;
              default:
                fprintf(stderr, "Unrecognized flag: %c\n", *s);
                return FALSE;
            }
      else              /* Process a file */
        {
          if (verbose) printf("%s:", *argv);
          file_args = TRUE;       /* Whether or not we could read it */

          if (sha_file(*argv, hbuf) == FAILURE)
            printf("Can't open file %s.\n", *argv);
          else
            if (terse) printf("%08lx%08lx%08lx%08lx%08lx\n",
              hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
            else printf("%08lx %08lx %08lx %08lx %08lx\n",
              hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
        }
    }
  if (! file_args)  /* No file specified */
    {
      if (verbose) printf("%s:", *argv);
      sha_stream(stdin, hbuf);

      if (terse) printf("%08lx%08lx%08lx%08lx%08lx\n",
        hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
      else printf("%08lx %08lx %08lx %08lx %08lx\n",
        hbuf[0], hbuf[1], hbuf[2], hbuf[3], hbuf[4]);
    }
  return TRUE;
}

#endif

/* #ifdef LITTLE_ENDIAN */ /* Imported from Peter Gutmann's implementation */

/* When run on a little-endian CPU we need to perform byte reversal on an
  array of intwords.  It is possible to make the code endianness-
  independant by fiddling around with data at the byte level, but this
  makes for very slow code, so we rely on the user to sort out endianness
  at compile time */

static void byteReverse( unsigned int *buffer, int byteCount )
{
  unsigned int value;
  int count;
  extern int little_endian;

  if ( !little_endian )
  return;

  byteCount /= sizeof( unsigned int );
  for( count = 0; count < byteCount; count++ )
    {
      value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 );
      buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 );
    }
}
/* #endif */ /* LITTLE_ENDIAN */

union intbyte
{
  unsigned int W[80];    /* Process 16 32-bit words at a time */
  char B[320];        /* But read them as bytes for counting */
};

int sha_file(char* filename, unsigned int *buffer)    /* Hash a file */
{
  FILE *infile;

  if ((infile = fopen(filename, "rb")) == NULL)
    {
      int i;

      for (i = 0; i < 5; i++)
        buffer[i] = 0xdeadbeef;
      return FAILURE;
    }
  (void) sha_stream(infile, buffer);
  fclose(infile);
  return SUCCESS;
}

void sha_memory(char *mem, unsigned int length, unsigned int *buffer)
{
  nist_guts(FALSE, (FILE *) NULL, mem, length, buffer);
}

void sha_stream(FILE *stream, unsigned int *buffer)
{
  nist_guts(TRUE, stream, (char *) NULL, 0l, buffer);
}

#define f0(x,y,z) (z ^ (x & (y ^ z)))       /* Magic functions */
#define f1(x,y,z) (x ^ y ^ z)
#define f2(x,y,z) ((x & y) | (z & (x | y)))
#define f3(x,y,z) (x ^ y ^ z)

#define K0 0x5a827999               /* Magic constants */
#define K1 0x6ed9eba1
#define K2 0x8f1bbcdc
#define K3 0xca62c1d6

#define S(n, X) ((X << n) | (X >> (32 - n)))  /* Barrel roll */

#define r0(f, K) \
  temp = S(5, A) + f(B, C, D) + E + *p0++ + K; \
  E = D;  \
  D = C;  \
  C = S(30, B); \
  B = A;  \
  A = temp

#ifdef VERSION_0
#define r1(f, K) \
  temp = S(5, A) + f(B, C, D) + E + \
      (*p0++ = *p1++ ^ *p2++ ^ *p3++ ^ *p4++) + K; \
  E = D;  \
  D = C;  \
  C = S(30, B); \
  B = A;  \
  A = temp
#else           /* Version 1: Summer '94 update */
#define r1(f, K) \
  temp = *p1++ ^ *p2++ ^ *p3++ ^ *p4++; \
  temp = S(5, A) + f(B, C, D) + E + (*p0++ = S(1,temp)) + K; \
  E = D;  \
  D = C;  \
  C = S(30, B); \
  B = A;  \
  A = temp
#endif

static void nist_guts(int file_flag, /* Input from memory, or from stream? */
            FILE *stream,
            char *mem,
            unsigned int length,
            unsigned int *buf)
{
  int i, nread, nbits;
  union intbyte d;
  unsigned int hi_length, lo_length;
  int padded;
  char *s;

  register unsigned int *p0, *p1, *p2, *p3, *p4;
  unsigned int A, B, C, D, E, temp;

  unsigned int h0, h1, h2, h3, h4;

  h0 = 0x67452301;              /* Accumulators */
  h1 = 0xefcdab89;
  h2 = 0x98badcfe;
  h3 = 0x10325476;
  h4 = 0xc3d2e1f0;

  padded = FALSE;
  s = mem;
  for (hi_length = lo_length = 0; ;)  /* Process 16 ints at a time */
    {
      if (file_flag)
        {
          nread = fread(d.B, 1, 64, stream);  /* Read as 64 bytes */
        }
      else
        {
          if (length < 64) nread = length;
          else       nread = 64;
          length -= nread;
          memcpy(d.B, s, nread);
          s += nread;
        }
      if (nread < 64)   /* Partial block? */
        {
          nbits = nread << 3;         /* Length: bits */
          if ((int)(lo_length += nbits) < nbits)
            hi_length++;        /* 64-bit integer */

          if (nread < 64 && ! padded)  /* Append a single bit */
            {
              d.B[nread++] = (char)0x80; /* Using up next byte */
              padded = TRUE;     /* Single bit once */
            }
          for (i = nread; i < 64; i++) /* Pad with nulls */
            d.B[i] = 0;
          if (nread <= 56)   /* Room for length in this block */
            {
              d.W[14] = hi_length;
              d.W[15] = lo_length;
/* #ifdef LITTLE_ENDIAN */
              byteReverse(d.W, 56 );
/* #endif */ /* LITTLE_ENDIAN */
            }
/* #ifdef LITTLE_ENDIAN */
          else
            byteReverse(d.W, 64 );
/* #endif */ /* LITTLE_ENDIAN */
        }
      else  /* Full block -- get efficient */
        {
          if ((lo_length += 512) < 512)
            hi_length++;  /* 64-bit integer */
/* #ifdef LITTLE_ENDIAN */
          byteReverse(d.W, 64 );
/* #endif */ /* LITTLE_ENDIAN */
        }

      p0 = d.W;
      A = h0; B = h1; C = h2; D = h3; E = h4;

      r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
      r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
      r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0); r0(f0,K0);
      r0(f0,K0);

      p1 = &d.W[13]; p2 = &d.W[8]; p3 = &d.W[2]; p4 = &d.W[0];

      r1(f0,K0); r1(f0,K0); r1(f0,K0); r1(f0,K0);
      r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
      r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
      r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
      r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1); r1(f1,K1);
      r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
      r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
      r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
      r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2); r1(f2,K2);
      r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
      r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
      r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);
      r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3); r1(f3,K3);

      h0 += A; h1 += B; h2 += C; h3 += D; h4 += E;

      if (nread <= 56) break; /* If it's greater, length in next block */
    }
  buf[0] = h0; buf[1] = h1; buf[2] = h2; buf[3] = h3; buf[4] = h4;
}