"Fossies" - the Fresh Open Source Software Archive

Member "apg-2.2.3/sha/sha.c" (7 Aug 2003, 10410 Bytes) of package /linux/privat/old/apg-2.2.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /***************************************************************************/
    2 /* sha.c                                   */
    3 /*                                     */
    4 /* Public domain SHA-1 implementation.                     */
    5 /*                                     */
    6 /* Taken from the SHA implementation by Peter C. Gutmann of 9/2/1992       */
    7 /* and modified by Carl Ellison to be SHA-1.                   */
    8 /***************************************************************************/
    9 
   10 /*
   11 ** Note regarding apg_* namespace: this avoids potential conflicts
   12 ** with libraries.
   13 */
   14 
   15 #include <string.h>
   16 #include "sha.h"
   17 
   18 /* The SHA f()-functions */
   19 
   20 #define f1(x,y,z)   ( ( x & y ) | ( ~x & z ) )              /* Rounds  0-19 */
   21 #define f2(x,y,z)   ( x ^ y ^ z )                           /* Rounds 20-39 */
   22 #define f3(x,y,z)   ( ( x & y ) | ( x & z ) | ( y & z ) )   /* Rounds 40-59 */
   23 #define f4(x,y,z)   ( x ^ y ^ z )                           /* Rounds 60-79 */
   24 
   25 /* The SHA Mysterious Constants */
   26 
   27 #define K1  0x5A827999L     /* Rounds  0-19 */
   28 #define K2  0x6ED9EBA1L     /* Rounds 20-39 */
   29 #define K3  0x8F1BBCDCL     /* Rounds 40-59 */
   30 #define K4  0xCA62C1D6L     /* Rounds 60-79 */
   31 
   32 /* SHA initial values */
   33 
   34 #define h0init  0x67452301L
   35 #define h1init  0xEFCDAB89L
   36 #define h2init  0x98BADCFEL
   37 #define h3init  0x10325476L
   38 #define h4init  0xC3D2E1F0L
   39 
   40 /* 32-bit rotate - kludged with shifts */
   41 
   42 typedef unsigned long UL ;  /* to save space */
   43 
   44 #define S(n,X)  ( ( ((UL)X) << n ) | ( ((UL)X) >> ( 32 - n ) ) )
   45 
   46 /* The initial expanding function */
   47 
   48 #define expand(count)   W[ count ] = S(1,(W[ count - 3 ] ^ W[ count - 8 ] ^ W[ count - 14 ] ^ W[ count - 16 ])) /* to make this SHA-1 */
   49 
   50 /* The four SHA sub-rounds */
   51 
   52 #define subRound1(count)    \
   53 { \
   54     temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \
   55     E = D; \
   56     D = C; \
   57     C = S( 30, B ); \
   58     B = A; \
   59     A = temp; \
   60 }
   61 
   62 #define subRound2(count)    \
   63 { \
   64     temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \
   65     E = D; \
   66     D = C; \
   67     C = S( 30, B ); \
   68     B = A; \
   69     A = temp; \
   70 }
   71 
   72 #define subRound3(count)    \
   73 { \
   74     temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \
   75     E = D; \
   76     D = C; \
   77     C = S( 30, B ); \
   78     B = A; \
   79     A = temp; \
   80 }
   81 
   82 #define subRound4(count)    \
   83 { \
   84     temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \
   85     E = D; \
   86     D = C; \
   87     C = S( 30, B ); \
   88     B = A; \
   89     A = temp; \
   90 }
   91 
   92 /* The two buffers of 5 32-bit words */
   93 
   94 LONG h0, h1, h2, h3, h4;
   95 LONG A, B, C, D, E;
   96 
   97 /***************************************************************************/
   98 /* apg_shaInit                                 */
   99 /*                                     */
  100 /* Initialize the SHA values                           */
  101 /***************************************************************************/
  102 
  103 void apg_shaInit( apg_SHA_INFO *shaInfo )
  104 {
  105   /* Set the h-vars to their initial values */
  106   shaInfo->digest[ 0 ] = h0init;
  107   shaInfo->digest[ 1 ] = h1init;
  108   shaInfo->digest[ 2 ] = h2init;
  109   shaInfo->digest[ 3 ] = h3init;
  110   shaInfo->digest[ 4 ] = h4init;
  111 
  112   /* Initialise bit count */
  113   shaInfo->countLo = shaInfo->countHi = 0L;
  114   shaInfo->slop = 0 ;       /* no data saved yet in data[] */
  115 } /* apg_shaInit */
  116 
  117 /***************************************************************************/
  118 /* shaTransform                                */
  119 /*                                     */
  120 /* Perform the SHA transformation over one input block.            */
  121 /***************************************************************************/
  122 
  123 static void shaTransform( apg_SHA_INFO *shaInfo )
  124 {
  125   LONG W[ 80 ], temp;
  126   int i;
  127 
  128   /* Step A.  Copy the data buffer into the local work buffer */
  129   for( i = 0; i < 16; i++ )
  130     W[ i ] = shaInfo->data[ i ];
  131 
  132   /* Step B.  Expand the 16 words into 64 temporary data words */
  133   expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 );
  134   expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 );
  135   expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 );
  136   expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 );
  137   expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 );
  138   expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 );
  139   expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 );
  140   expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 );
  141   expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 );
  142   expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 );
  143   expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 );
  144   expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 );
  145   expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 );
  146 
  147   /* Step C.  Set up first buffer */
  148   A = shaInfo->digest[ 0 ];
  149   B = shaInfo->digest[ 1 ];
  150   C = shaInfo->digest[ 2 ];
  151   D = shaInfo->digest[ 3 ];
  152   E = shaInfo->digest[ 4 ];
  153 
  154   /* Step D.  Serious mangling, divided into four sub-rounds */
  155   subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 );
  156   subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 );
  157   subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 );
  158   subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 );
  159   subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 );
  160   subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 );
  161   subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 );
  162   subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 );
  163   subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 );
  164   subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 );
  165   subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 );
  166   subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 );
  167   subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 );
  168   subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 );
  169   subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 );
  170   subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 );
  171   subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 );
  172   subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 );
  173   subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 );
  174   subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 );
  175 
  176   /* Step E.  Build message digest */
  177   shaInfo->digest[ 0 ] += A;
  178   shaInfo->digest[ 1 ] += B;
  179   shaInfo->digest[ 2 ] += C;
  180   shaInfo->digest[ 3 ] += D;
  181   shaInfo->digest[ 4 ] += E;
  182 } /* shaTransform */
  183 
  184 #ifdef APG_LITTLE_ENDIAN
  185 
  186 /***************************************************************************/
  187 /* byteReverse                                 */
  188 /*                                     */
  189 /* When run on a little-endian CPU we need to perform byte reversal on an  */
  190 /* array of longwords.  It is possible to make the code endianness-    */
  191 /* independant by fiddling around with data at the byte level, but this    */
  192 /* makes for very slow code, so we rely on the user to sort out endianness */
  193 /* at compile time.                            */
  194 /***************************************************************************/
  195 
  196 static void byteReverse( LONG *buffer, int byteCount )
  197 {
  198   LONG value;
  199   int count;
  200 
  201   byteCount /= sizeof( LONG );
  202   for( count = 0; count < byteCount; count++ )
  203     {
  204       value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 );
  205       buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 );
  206     } /* for */
  207 } /* byteReverse */
  208 #endif /* APG_LITTLE_ENDIAN */
  209 
  210 /***************************************************************************/
  211 /* apg_shaUpdate                                   */
  212 /*                                     */
  213 /* Update SHA for a block of data.                     */
  214 /* Use any data already in the SHA_INFO structure and leave any partial    */
  215 /* data block there.                               */
  216 /***************************************************************************/
  217 
  218 void apg_shaUpdate( apg_SHA_INFO *shaInfo, BYTE *buffer, int count )
  219 {
  220   BYTE *db ;
  221    
  222   db = (BYTE *) &(shaInfo->data[0]) ;
  223 
  224   /* Update bitcount */
  225   if( ( shaInfo->countLo + ( ( LONG ) count << 3 ) ) < shaInfo->countLo )
  226     shaInfo->countHi++; /* Carry from low to high bitCount */
  227   shaInfo->countLo += ( ( LONG ) count << 3 );
  228   shaInfo->countHi += ( ( LONG ) count >> 29 );
  229 
  230   /* Process data in SHA_BLOCKSIZE chunks */
  231   while ( count-- > 0 )
  232     {
  233       db[ shaInfo->slop++ ] = *(buffer++) ;
  234       if (shaInfo->slop == SHA_BLOCKSIZE)
  235     { /* transform this one block */
  236 #ifdef APG_LITTLE_ENDIAN
  237       byteReverse( shaInfo->data, SHA_BLOCKSIZE );
  238 #endif /* APG_LITTLE_ENDIAN */
  239       shaTransform( shaInfo );
  240       shaInfo->slop = 0 ;   /* no slop left */
  241     } /* if */
  242     } /* while */
  243 } /* apg_shaUpdate */
  244 
  245 /***************************************************************************/
  246 /* apg_shaFinal                                */
  247 /*                                     */
  248 /* Handle the last piece of data -- if any is left over in the data    */
  249 /* buffer -- and append padding and a bit count for the last block     */
  250 /* to process.  Having transformed that block, pull the digest out     */
  251 /* as a byte array.                            */
  252 /***************************************************************************/
  253 
  254 void apg_shaFinal( apg_SHA_INFO *shaInfo, BYTE hash[SHA_DIGESTSIZE] )
  255 {
  256   int count;
  257   LONG lowBitcount = shaInfo->countLo, highBitcount = shaInfo->countHi;
  258 
  259   /* Compute number of bytes mod 64 */
  260   count = ( int ) ( ( shaInfo->countLo >> 3 ) & 0x3F );
  261 
  262   /* Set the first char of padding to 0x80.  This is safe since there is
  263      always at least one byte free */
  264   ( ( BYTE * ) shaInfo->data )[ count++ ] = 0x80;
  265 
  266   /* Pad out to 56 mod 64 */
  267   if( count > 56 )
  268     {
  269       /* Two lots of padding:  Pad the first block to 64 bytes */
  270       memset( ( BYTE * ) &shaInfo->data + count, 0, 64 - count );
  271 #ifdef APG_LITTLE_ENDIAN
  272       byteReverse( shaInfo->data, SHA_BLOCKSIZE );
  273 #endif /* APG_LITTLE_ENDIAN */
  274       shaTransform( shaInfo );
  275 
  276       /* Now fill the next block with 56 bytes */
  277       memset( &shaInfo->data, 0, 56 );
  278     }
  279   else
  280     /* Pad block to 56 bytes */
  281     memset( ( BYTE * ) &shaInfo->data + count, 0, 56 - count );
  282 #ifdef APG_LITTLE_ENDIAN
  283   byteReverse( shaInfo->data, SHA_BLOCKSIZE );
  284 #endif /* APG_LITTLE_ENDIAN */
  285 
  286   /* Append length in bits and transform */
  287   shaInfo->data[ 14 ] = highBitcount;
  288   shaInfo->data[ 15 ] = lowBitcount;
  289 
  290   shaTransform( shaInfo );
  291 #ifdef APG_LITTLE_ENDIAN
  292   byteReverse( shaInfo->data, SHA_DIGESTSIZE );
  293 #endif /* APG_LITTLE_ENDIAN */
  294 
  295   for (count=0; count<SHA_DIGESTSIZE; count++)
  296     hash[count] = (BYTE) ((shaInfo->digest[count>>2]) >> (8*(3-(count & 0x3)))) & 0xff ;
  297 } /* apg_shaFinal */