* shs.c, sha_glue.c, hmac_sha.c: Fix to deal with LONG wider than
authorTom Yu <tlyu@mit.edu>
Tue, 28 Oct 1997 21:39:36 +0000 (21:39 +0000)
committerTom Yu <tlyu@mit.edu>
Tue, 28 Oct 1997 21:39:36 +0000 (21:39 +0000)
32 bits.

* t_shs.c: Print out the actual and expected values on error.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@10258 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/crypto/sha/ChangeLog
src/lib/crypto/sha/hmac_sha.c
src/lib/crypto/sha/sha_glue.c
src/lib/crypto/sha/shs.c
src/lib/crypto/sha/t_shs.c

index 03521a5b7863932490bbc06dc7828b20a4f2fb02..154f7b679846f3ca11bcbffc4e7d49a3c39b5d80 100644 (file)
@@ -1,3 +1,10 @@
+Tue Oct 28 16:37:18 1997  Tom Yu  <tlyu@voltage-multiplier.mit.edu>
+
+       * shs.c, sha_glue.c, hmac_sha.c: Fix to deal with LONG wider than
+       32 bits.
+
+       * t_shs.c: Print out the actual and expected values on error.
+
 Sat Feb 22 18:52:09 1997  Richard Basch  <basch@lehman.com>
 
        * Makefile.in: Use some of the new library list build rules in
index 01b00899ebf0209f074e82f67b92a230e81f6229..d57092e69a6873f2f6d32717bb42f254b3450066 100644 (file)
@@ -16,19 +16,28 @@ hmac_sha(text, text_len, key, key_len, digest)
     krb5_octet k_ipad[PAD_SZ]; /* inner padding - key XORd with ipad */
     krb5_octet k_opad[PAD_SZ]; /* outer padding - key XORd with opad */
     int i;
+    krb5_octet *cp;
+    LONG *lp;
  
     /* sanity check parameters */
     if (!text || !key || !digest)
        /* most heinous, probably should log something */
        return EINVAL;
 
-    /* if key is longer than 64 bytes reset it to key=MD5(key) */
+    /* if key is longer than 64 bytes reset it to key=SHA(key) */
     if (key_len > sizeof(k_ipad)) {
        shsInit(&context);
        shsUpdate(&context, key, key_len);
        shsFinal(&context);
 
-       memcpy(digest, context.digest, SHS_DIGESTSIZE);
+       cp = digest;
+       lp = context.digest;
+       while (cp < digest + SHS_DIGESTSIZE) {
+           *cp++ = (*lp >> 24) & 0xff;
+           *cp++ = (*lp >> 16) & 0xff;
+           *cp++ = (*lp >> 8) & 0xff;
+           *cp++ = *lp++ & 0xff;
+       }
        key = digest;
        key_len = SHS_DIGESTSIZE;
     }
@@ -62,7 +71,14 @@ hmac_sha(text, text_len, key, key_len, digest)
     shsUpdate(&context, text, text_len);
     shsFinal(&context);
 
-    memcpy(digest, context.digest, SHS_DIGESTSIZE);
+    cp = digest;
+    lp = context.digest;
+    while (cp < digest + SHS_DIGESTSIZE) {
+       *cp++ = (*lp >> 24) & 0xff;
+       *cp++ = (*lp >> 16) & 0xff;
+       *cp++ = (*lp >> 8) & 0xff;
+       *cp++ = *lp++ & 0xff;
+    }
     
     /*
      * perform outer SHA
@@ -72,7 +88,14 @@ hmac_sha(text, text_len, key, key_len, digest)
     shsUpdate(&context, digest, SHS_DIGESTSIZE);
     shsFinal(&context);
 
-    memcpy(digest, context.digest, SHS_DIGESTSIZE);
+    cp = digest;
+    lp = context.digest;
+    while (cp < digest + SHS_DIGESTSIZE) {
+       *cp++ = (*lp >> 24) & 0xff;
+       *cp++ = (*lp >> 16) & 0xff;
+       *cp++ = (*lp >> 8) & 0xff;
+       *cp++ = *lp++ & 0xff;
+    }
 
     return 0;
 }
index 3a57e01821838397bcb47fb1dd4d0acfdc431644..58a93b72309e98c2d86c776280c1bcdbf6d946e5 100644 (file)
@@ -25,6 +25,8 @@ krb5_sha_sum_func(in, in_length, seed, seed_length, outcksum)
        krb5_checksum           FAR *outcksum;
 {
     krb5_octet *input = (krb5_octet *)in;
+    krb5_octet *cp;
+    LONG *lp;
     SHS_INFO working;
 
     if (outcksum->length < SHS_DIGESTSIZE)
@@ -37,9 +39,14 @@ krb5_sha_sum_func(in, in_length, seed, seed_length, outcksum)
     outcksum->checksum_type = CKSUMTYPE_NIST_SHA;
     outcksum->length = SHS_DIGESTSIZE;
 
-    memcpy((char *)outcksum->contents,
-          (char *)&working.digest[0],
-          outcksum->length);
+    cp = outcksum->contents;
+    lp = working.digest;
+    while (lp < working.digest + 16) {
+       *cp++ = (*lp >> 24) & 0xff;
+       *cp++ = (*lp >> 16) & 0xff;
+       *cp++ = (*lp >> 8) & 0xff;
+       *cp++ = (*lp++) & 0xff;
+    }
     memset((char *)&working, 0, sizeof(working));
     return 0;
 }
@@ -55,6 +62,8 @@ krb5_sha_verify_func(cksum, in, in_length, seed, seed_length)
     krb5_octet *input = (krb5_octet *)in;
     SHS_INFO working;
     krb5_error_code retval;
+    int i;
+    krb5_octet *cp;
 
     if (cksum->checksum_type != CKSUMTYPE_NIST_SHA)
        return KRB5KRB_AP_ERR_INAPP_CKSUM;
@@ -66,10 +75,14 @@ krb5_sha_verify_func(cksum, in, in_length, seed, seed_length)
     shsFinal(&working);
 
     retval = 0;
-    if (memcmp((char *) cksum->contents,
-              (char *) &working.digest[0],
-              cksum->length))
-       retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+    for (i = 0, cp = cksum->contents; i < 5; i++, cp += 4) {
+       if (working.digest[i] !=
+           (LONG) cp[0] << 24 | (LONG) cp[1] << 16 |
+           (LONG) cp[2] << 8 | (LONG) cp[3]) {
+           retval = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+           break;
+       }
+    }
     memset((char *) &working, 0, sizeof(working));
     return retval;
 }
index ee4965036140c236591035b79bc7f70dfedaae3d..e18f3af9e29bb61a9558389dc2a22d4fbf186927 100644 (file)
@@ -33,7 +33,7 @@
 
 /* 32-bit rotate left - kludged with shifts */
 
-#define ROTL(n,X)  ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
+#define ROTL(n,X)  (((X) << (n)) & 0xffffffff | ((X) >> (32 - n)))
 
 /* The initial expanding function.  The hash function is defined over an
    80-word expanded input array W, where the first 16 are copies of the input
@@ -71,7 +71,8 @@
    the next 20 values from the W[] array each time */
 
 #define subRound(a, b, c, d, e, f, k, data) \
-    ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
+    ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, \
+      e &= 0xffffffff, b = ROTL( 30, b ) )
 
 /* Initialize the SHS values */
 
@@ -112,7 +113,7 @@ void SHSTransform(digest, data)
     C = digest[ 2 ];
     D = digest[ 3 ];
     E = digest[ 4 ];
-    memcpy( eData, data, SHS_DATASIZE );
+    memcpy(eData, data, sizeof (eData));
 
     /* Heavy mangling, in 4 sub-rounds of 20 interations each. */
     subRound( A, B, C, D, E, f1, K1, eData[  0 ] );
@@ -201,10 +202,15 @@ void SHSTransform(digest, data)
 
     /* Build message digest */
     digest[ 0 ] += A;
+    digest[ 0 ] &= 0xffffffff;
     digest[ 1 ] += B;
+    digest[ 1 ] &= 0xffffffff;
     digest[ 2 ] += C;
+    digest[ 2 ] &= 0xffffffff;
     digest[ 3 ] += D;
+    digest[ 3 ] &= 0xffffffff;
     digest[ 4 ] += E;
+    digest[ 4 ] &= 0xffffffff;
 }
 
 /* When run on a little-endian CPU we need to perform byte reversal on an
@@ -250,47 +256,93 @@ void shsUpdate(shsInfo, buffer, count)
     int count;
 {
     LONG tmp;
-    int dataCount;
+    int dataCount, canfill;
+    LONG *lp;
 
     /* Update bitcount */
     tmp = shsInfo->countLo;
-    if ( ( shsInfo->countLo = tmp + ( ( LONG ) count << 3 ) ) < tmp )
-        shsInfo->countHi++;             /* Carry from low to high */
+    shsInfo->countLo = tmp + (((LONG) count) << 3 );
+    if ((shsInfo->countLo &= 0xffffffff) < tmp)
+        shsInfo->countHi++;    /* Carry from low to high */
     shsInfo->countHi += count >> 29;
 
     /* Get count of bytes already in data */
-    dataCount = ( int ) ( tmp >> 3 ) & 0x3F;
+    dataCount = (int) (tmp >> 3) & 0x3F;
 
     /* Handle any leading odd-sized chunks */
-    if( dataCount )
-        {
-        BYTE *p = ( BYTE * ) shsInfo->data + dataCount;
-
-        dataCount = SHS_DATASIZE - dataCount;
-        if( count < dataCount )
-            {
-            memcpy( p, buffer, count );
-            return;
-            }
-        memcpy( p, buffer, dataCount );
-        longReverse( shsInfo->data, SHS_DATASIZE );
-        SHSTransform( shsInfo->digest, shsInfo->data );
-        buffer += dataCount;
-        count -= dataCount;
-        }
+    if (dataCount) {
+       lp = shsInfo->data + dataCount / 4;
+       canfill = (count >= dataCount);
+       dataCount = SHS_DATASIZE - dataCount;
+
+       if (dataCount % 4) {
+           /* Fill out a full 32 bit word first if needed -- this
+              is not very efficient (computed shift amount),
+              but it shouldn't happen often. */
+           while (dataCount % 4 && count > 0) {
+               *lp |= (LONG) *buffer++ << ((3 - dataCount++ % 4) * 8);
+               count--;
+           }
+           lp++;
+       }
+       while (lp < shsInfo->data + 16) {
+           *lp = (LONG) *buffer++ << 24;
+           *lp |= (LONG) *buffer++ << 16;
+           *lp |= (LONG) *buffer++ << 8;
+           *lp++ |= (LONG) *buffer++;
+           if ((count -= 4) < 4 && lp < shsInfo->data + 16) {
+               *lp = 0;
+               switch (count % 4) {
+               case 3:
+                   *lp |= (LONG) buffer[2] << 8;
+               case 2:
+                   *lp |= (LONG) buffer[1] << 16;
+               case 1:
+                   *lp |= (LONG) buffer[0] << 24;
+               }
+               break;
+               count = 0;
+           }
+       }
+       if (canfill) {
+           SHSTransform(shsInfo->digest, shsInfo->data);
+       }
+    }
 
     /* Process data in SHS_DATASIZE chunks */
-    while( count >= SHS_DATASIZE )
-        {
-        memcpy( shsInfo->data, buffer, SHS_DATASIZE );
-        longReverse( shsInfo->data, SHS_DATASIZE );
-        SHSTransform( shsInfo->digest, shsInfo->data );
-        buffer += SHS_DATASIZE;
-        count -= SHS_DATASIZE;
-        }
-
-    /* Handle any remaining bytes of data. */
-    memcpy( shsInfo->data, buffer, count );
+    while (count >= SHS_DATASIZE) {
+       lp = shsInfo->data;
+       while (lp < shsInfo->data + 16) {
+           *lp = ((LONG) *buffer++) << 24;
+           *lp |= ((LONG) *buffer++) << 16;
+           *lp |= ((LONG) *buffer++) << 8;
+           *lp++ |= (LONG) *buffer++;
+       }
+       SHSTransform(shsInfo->digest, shsInfo->data);
+       count -= SHS_DATASIZE;
+    }
+
+    if (count > 0) {
+       lp = shsInfo->data;
+       while (count > 4) {
+           *lp = ((LONG) *buffer++) << 24;
+           *lp |= ((LONG) *buffer++) << 16;
+           *lp |= ((LONG) *buffer++) << 8;
+           *lp++ |= (LONG) *buffer++;
+           count -= 4;
+       }
+       *lp = 0;
+       switch (count % 4) {
+       case 0:
+           *lp |= ((LONG) buffer[3]);
+       case 3:
+           *lp |= ((LONG) buffer[2]) << 8;
+       case 2:
+           *lp |= ((LONG) buffer[1]) << 16;
+       case 1:
+           *lp |= ((LONG) buffer[0]) << 24;
+       }
+    }
 }
 
 /* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bit pattern
@@ -300,39 +352,41 @@ void shsFinal(shsInfo)
     SHS_INFO *shsInfo;
 {
     int count;
+    LONG *lp;
     BYTE *dataPtr;
 
     /* Compute number of bytes mod 64 */
-    count = ( int ) shsInfo->countLo;
-    count = ( count >> 3 ) & 0x3F;
+    count = (int) shsInfo->countLo;
+    count = (count >> 3) & 0x3F;
 
     /* Set the first char of padding to 0x80.  This is safe since there is
        always at least one byte free */
-    dataPtr = ( BYTE * ) shsInfo->data + count;
-    *dataPtr++ = 0x80;
-
-    /* Bytes of padding needed to make 64 bytes */
-    count = SHS_DATASIZE - 1 - count;
-
-    /* Pad out to 56 mod 64 */
-    if( count < 8 )
-        {
-        /* Two lots of padding:  Pad the first block to 64 bytes */
-        memset( dataPtr, 0, count );
-        longReverse( shsInfo->data, SHS_DATASIZE );
-        SHSTransform( shsInfo->digest, shsInfo->data );
-
-        /* Now fill the next block with 56 bytes */
-        memset( shsInfo->data, 0, SHS_DATASIZE - 8 );
-        }
-    else
-        /* Pad block to 56 bytes */
-        memset( dataPtr, 0, count - 8 );
+    lp = shsInfo->data + count / 4;
+    switch (count % 4) {
+    case 3:
+       *lp++ |= (LONG) 0x80;
+       break;
+    case 2:
+       *lp++ |= (LONG) 0x80 << 8;
+       break;
+    case 1:
+       *lp++ |= (LONG) 0x80 << 16;
+       break;
+    case 0:
+       *lp++ = (LONG) 0x80 << 24;
+    }
 
+    if (lp > shsInfo->data + 14) {
+       /* Pad out to 64 bytes if not enough room for length words */
+       *lp = 0;
+       SHSTransform(shsInfo->digest, shsInfo->data);
+       lp = shsInfo->data;
+    }
+    /* Pad out to 56 bytes */
+    while (lp < shsInfo->data + 14)
+       *lp++ = 0;
     /* Append length in bits and transform */
-    shsInfo->data[ 14 ] = shsInfo->countHi;
-    shsInfo->data[ 15 ] = shsInfo->countLo;
-
-    longReverse( shsInfo->data, SHS_DATASIZE - 8 );
-    SHSTransform( shsInfo->digest, shsInfo->data );
+    *lp++ = shsInfo->countHi;
+    *lp++ = shsInfo->countLo;
+    SHSTransform(shsInfo->digest, shsInfo->data);
 }
index 87d8a0f9dab9e823dbed352a0d5a77683a5b1335..da55992ec9fcd6549aec5e6573218a70c87122dc 100644 (file)
@@ -32,12 +32,24 @@ static int compareSHSresults(shsInfo, shsTestLevel)
 SHS_INFO *shsInfo;
 int shsTestLevel;
 {
-    int i;
+    int i, fail = 0;
 
     /* Compare the returned digest and required values */
     for( i = 0; i < 5; i++ )
         if( shsInfo->digest[ i ] != shsTestResults[ shsTestLevel ][ i ] )
-            return( -1 );
+           fail = 1;
+    if (fail) {
+       printf("\nExpected: ");
+       for (i = 0; i < 5; i++) {
+           printf("%8.8lx ", shsTestResults[shsTestLevel][i]);
+       }
+       printf("\nGot:      ");
+       for (i = 0; i < 5; i++) {
+           printf("%8.8lx ", shsInfo->digest[i]);
+       }
+       printf("\n");
+       return( -1 );
+    }
     return( 0 );
 }