/*
* F, G, H and I are basic MD5 functions
*/
#define F( x, y, z ) ( ( ( x ) & ( y ) ) | ( ( ~x ) & ( z ) ) )
#define G( x, y, z ) ( ( ( x ) & ( z ) ) | ( ( y ) & ( ~z ) ) )
#define H( x, y, z ) ( ( x ) ^ ( y ) ^ ( z ) )
#define I( x, y, z ) ( ( y ) ^ ( ( x ) | ( ~z ) ) )
#define ROTATE_LEFT( x, n ) ( ( ( x ) << ( n ) ) | ( ( x ) >> ( 32 - ( n ) ) ) )
/*
* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4
* Rotation is separate from addition to prevent recomputation
*/
#define FF( a, b, c, d, x, s, ac ) \
{ \
( a ) += F( ( b ), ( c ), ( d ) ) + ( x ) + ( unsigned int )( ac ); \
( a ) = ROTATE_LEFT( ( a ), ( s ) ); \
( a ) += ( b ); \
}
#define GG( a, b, c, d, x, s, ac ) \
{ \
( a ) += G( ( b ), ( c ), ( d ) ) + ( x ) + ( unsigned int )( ac ); \
( a ) = ROTATE_LEFT( ( a ), ( s ) ); \
( a ) += ( b ); \
}
#define HH( a, b, c, d, x, s, ac ) \
{ \
( a ) += H( ( b ), ( c ), ( d ) ) + ( x ) + ( unsigned int )( ac ); \
( a ) = ROTATE_LEFT( ( a ), ( s ) ); \
( a ) += ( b ); \
}
#define II( a, b, c, d, x, s, ac ) \
{ \
( a ) += I( ( b ), ( c ), ( d ) ) + ( x ) + ( unsigned int )( ac ); \
( a ) = ROTATE_LEFT( ( a ), ( s ) ); \
( a ) += ( b ); \
}
/*
* Data structure for MD5 (Message-Digest) computation
*/
typedef struct
{
/*
* number of _bits_ handled mod 2^64
*/
unsigned int i[2];
/*
* scratch buffer
*/
unsigned int buf[4];
/*
* input buffer
*/
unsigned char in[64];
/*
* actual digest after MD5Final call
*/
unsigned char digest[16];
} MD5_CTX;
/************************************************************************
* *
* Function Prototype *
* *
************************************************************************/
/*
* save number of bits
*/
in[14] = mdContext->i[0];
in[15] = mdContext->i[1];
/*
* compute number of bytes mod 64
*/
mdi = ( int )( ( mdContext->i[0] >> 3 ) & 0x3F );
/*
* pad out to 56 mod 64
*/
padLen = ( mdi < 56 ) ? ( 56 - mdi ) : ( 120 - mdi );
MD5Update( mdContext, PADDING, padLen );
/*
* append length in bits and transform
*/
for ( i = 0, ii = 0; i < 14; i++, ii += 4 )
{
in[i] = ( ( ( unsigned int )mdContext->in[ii+3] ) << 24 ) |
( ( ( unsigned int )mdContext->in[ii+2] ) << 16 ) |
( ( ( unsigned int )mdContext->in[ii+1] ) << 8 ) |
( ( unsigned int )mdContext->in[ii] );
}
Transform ( mdContext->buf, in );
/*
* store buffer in digest
*/
for ( i = 0, ii = 0; i < 4; i++, ii += 4 )
{
mdContext->digest[ii] =
( unsigned char )( mdContext->buf[i] & 0xFF);
mdContext->digest[ii+1] =
( unsigned char )( ( mdContext->buf[i] >> 8 ) & 0xFF );
mdContext->digest[ii+2] =
( unsigned char )( ( mdContext->buf[i] >> 16 ) & 0xFF );
mdContext->digest[ii+3] =
( unsigned char )( ( mdContext->buf[i] >> 24 ) & 0xFF );
} /* end of for */
return;
} /* end of MD5Final */
/*
* MD5Init initializes the message-digest context mdContext.
* All fields are set to zero
*/
static void MD5Init ( MD5_CTX *mdContext )
{
mdContext->i[0] = mdContext->i[1] = ( unsigned int )0;
/*
* Load magic initialization constants
*/
mdContext->buf[0] = ( unsigned int )0x67452301;
mdContext->buf[1] = ( unsigned int )0xefcdab89;
mdContext->buf[2] = ( unsigned int )0x98badcfe;
mdContext->buf[3] = ( unsigned int )0x10325476;
return;
} /* end of MD5Init */
/*
* MD5Update updates the message-digest context to account for the
* presence of each of the characters inBuf[0..inLen-1] in the message
* whose digest is being computed.
*/
static void MD5Update ( MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen )
{
unsigned int in[16];
int mdi;
unsigned int i, ii;
/*
* compute number of bytes mod 64
*/
mdi = ( int )( ( mdContext->i[0] >> 3 ) & 0x3F );
if ( ( mdContext->i[0] + ( ( unsigned int )inLen << 3 ) ) < mdContext->i[0] )
{
mdContext->i[1]++;
}
mdContext->i[0] += ( ( unsigned int )inLen << 3 );
mdContext->i[1] += ( ( unsigned int )inLen >> 29 );
while ( inLen-- )
{
/*
* add new character to buffer, increment mdi
*/
mdContext->in[ mdi++ ] = *inBuf++;
/*
* transform if necessary
*/
if ( mdi == 0x40 )
{
for ( i = 0, ii = 0; i < 16; i++, ii += 4 )
{
in[i] = ( ( ( unsigned int )mdContext->in[ii+3] ) << 24 ) |
( ( ( unsigned int )mdContext->in[ii+2] ) << 16 ) |
( ( ( unsigned int )mdContext->in[ii+1] ) << 8 ) |
( ( unsigned int )mdContext->in[ii] );
} /* end of for */
Transform( mdContext->buf, in );
mdi = 0;
}
} /* end of while */
return;
} /* end of MD5Update */
/*
* Basic MD5 step. Transforms buf based on in.
*/
static void Transform ( unsigned int *buf, unsigned int *in )
{
unsigned int a = buf[0], b = buf[1], c = buf[2], d = buf[3];