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;
}
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
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;
}
krb5_checksum FAR *outcksum;
{
krb5_octet *input = (krb5_octet *)in;
+ krb5_octet *cp;
+ LONG *lp;
SHS_INFO working;
if (outcksum->length < SHS_DIGESTSIZE)
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;
}
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;
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;
}
/* 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
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 */
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 ] );
/* 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
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
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);
}