DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

MD4.cpp (8305B)


      1 
      2 #pragma hdrstop
      3 #include "../precompiled.h"
      4 
      5 /*
      6    RSA Data Security, Inc., MD4 message-digest algorithm. (RFC1320)
      7 */
      8 
      9 /*
     10 
     11 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
     12 rights reserved.
     13 
     14 License to copy and use this software is granted provided that it
     15 is identified as the "RSA Data Security, Inc. MD4 Message-Digest
     16 Algorithm" in all material mentioning or referencing this software
     17 or this function.
     18 
     19 License is also granted to make and use derivative works provided
     20 that such works are identified as "derived from the RSA Data
     21 Security, Inc. MD4 Message-Digest Algorithm" in all material
     22 mentioning or referencing the derived work.
     23 
     24 RSA Data Security, Inc. makes no representations concerning either
     25 the merchantability of this software or the suitability of this
     26 software for any particular purpose. It is provided "as is"
     27 without express or implied warranty of any kind.
     28 
     29 These notices must be retained in any copies of any part of this
     30 documentation and/or software.
     31 
     32 */
     33 
     34 /* POINTER defines a generic pointer type */
     35 typedef unsigned char *POINTER;
     36 
     37 /* UINT2 defines a two byte word */
     38 typedef unsigned short int UINT2;
     39 
     40 /* UINT4 defines a four byte word */
     41 typedef unsigned long int UINT4;
     42 
     43 /* MD4 context. */
     44 typedef struct {
     45 	UINT4 state[4];				/* state (ABCD) */
     46 	UINT4 count[2];				/* number of bits, modulo 2^64 (lsb first) */
     47 	unsigned char buffer[64]; 	/* input buffer */
     48 } MD4_CTX;
     49 
     50 /* Constants for MD4Transform routine.  */
     51 #define S11 3
     52 #define S12 7
     53 #define S13 11
     54 #define S14 19
     55 #define S21 3
     56 #define S22 5
     57 #define S23 9
     58 #define S24 13
     59 #define S31 3
     60 #define S32 9
     61 #define S33 11
     62 #define S34 15
     63 
     64 static unsigned char PADDING[64] = {
     65 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     66 };
     67 
     68 /* F, G and H are basic MD4 functions. */
     69 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
     70 #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
     71 #define H(x, y, z) ((x) ^ (y) ^ (z))
     72 
     73 /* ROTATE_LEFT rotates x left n bits. */
     74 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
     75 
     76 /* FF, GG and HH are transformations for rounds 1, 2 and 3 */
     77 /* Rotation is separate from addition to prevent recomputation */
     78 #define FF(a, b, c, d, x, s) {(a) += F ((b), (c), (d)) + (x); (a) = ROTATE_LEFT ((a), (s));}
     79 
     80 #define GG(a, b, c, d, x, s) {(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; (a) = ROTATE_LEFT ((a), (s));}
     81 
     82 #define HH(a, b, c, d, x, s) {(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; (a) = ROTATE_LEFT ((a), (s));}
     83 
     84 /* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */
     85 static void Encode( unsigned char *output, UINT4 *input, unsigned int len ) {
     86 	unsigned int i, j;
     87 
     88 	for ( i = 0, j = 0; j < len; i++, j += 4 ) {
     89  		output[j] = (unsigned char)(input[i] & 0xff);
     90  		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
     91  		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
     92  		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
     93 	}
     94 }
     95 
     96 /* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */
     97 static void Decode( UINT4 *output, const unsigned char *input, unsigned int len ) {
     98 	unsigned int i, j;
     99 
    100 	for ( i = 0, j = 0; j < len; i++, j += 4 ) {
    101  		output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
    102 	}
    103 }
    104 
    105 /* MD4 basic transformation. Transforms state based on block. */
    106 static void MD4_Transform( UINT4 state[4], const unsigned char block[64] ) {
    107 	UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
    108 
    109 	Decode (x, block, 64);
    110 
    111 	/* Round 1 */
    112 	FF (a, b, c, d, x[ 0], S11); 			/* 1 */
    113 	FF (d, a, b, c, x[ 1], S12); 			/* 2 */
    114 	FF (c, d, a, b, x[ 2], S13); 			/* 3 */
    115 	FF (b, c, d, a, x[ 3], S14); 			/* 4 */
    116 	FF (a, b, c, d, x[ 4], S11); 			/* 5 */
    117 	FF (d, a, b, c, x[ 5], S12); 			/* 6 */
    118 	FF (c, d, a, b, x[ 6], S13); 			/* 7 */
    119 	FF (b, c, d, a, x[ 7], S14); 			/* 8 */
    120 	FF (a, b, c, d, x[ 8], S11); 			/* 9 */
    121 	FF (d, a, b, c, x[ 9], S12); 			/* 10 */
    122 	FF (c, d, a, b, x[10], S13); 			/* 11 */
    123 	FF (b, c, d, a, x[11], S14); 			/* 12 */
    124 	FF (a, b, c, d, x[12], S11); 			/* 13 */
    125 	FF (d, a, b, c, x[13], S12); 			/* 14 */
    126 	FF (c, d, a, b, x[14], S13); 			/* 15 */
    127 	FF (b, c, d, a, x[15], S14); 			/* 16 */
    128 
    129 	/* Round 2 */
    130 	GG (a, b, c, d, x[ 0], S21); 			/* 17 */
    131 	GG (d, a, b, c, x[ 4], S22); 			/* 18 */
    132 	GG (c, d, a, b, x[ 8], S23); 			/* 19 */
    133 	GG (b, c, d, a, x[12], S24); 			/* 20 */
    134 	GG (a, b, c, d, x[ 1], S21); 			/* 21 */
    135 	GG (d, a, b, c, x[ 5], S22); 			/* 22 */
    136 	GG (c, d, a, b, x[ 9], S23); 			/* 23 */
    137 	GG (b, c, d, a, x[13], S24); 			/* 24 */
    138 	GG (a, b, c, d, x[ 2], S21); 			/* 25 */
    139 	GG (d, a, b, c, x[ 6], S22); 			/* 26 */
    140 	GG (c, d, a, b, x[10], S23); 			/* 27 */
    141 	GG (b, c, d, a, x[14], S24); 			/* 28 */
    142 	GG (a, b, c, d, x[ 3], S21); 			/* 29 */
    143 	GG (d, a, b, c, x[ 7], S22); 			/* 30 */
    144 	GG (c, d, a, b, x[11], S23); 			/* 31 */
    145 	GG (b, c, d, a, x[15], S24); 			/* 32 */
    146 
    147 	/* Round 3 */
    148 	HH (a, b, c, d, x[ 0], S31);			/* 33 */
    149 	HH (d, a, b, c, x[ 8], S32); 			/* 34 */
    150 	HH (c, d, a, b, x[ 4], S33); 			/* 35 */
    151 	HH (b, c, d, a, x[12], S34); 			/* 36 */
    152 	HH (a, b, c, d, x[ 2], S31); 			/* 37 */
    153 	HH (d, a, b, c, x[10], S32); 			/* 38 */
    154 	HH (c, d, a, b, x[ 6], S33); 			/* 39 */
    155 	HH (b, c, d, a, x[14], S34); 			/* 40 */
    156 	HH (a, b, c, d, x[ 1], S31); 			/* 41 */
    157 	HH (d, a, b, c, x[ 9], S32); 			/* 42 */
    158 	HH (c, d, a, b, x[ 5], S33); 			/* 43 */
    159 	HH (b, c, d, a, x[13], S34); 			/* 44 */
    160 	HH (a, b, c, d, x[ 3], S31); 			/* 45 */
    161 	HH (d, a, b, c, x[11], S32); 			/* 46 */
    162 	HH (c, d, a, b, x[ 7], S33); 			/* 47 */
    163 	HH (b, c, d, a, x[15], S34);			/* 48 */
    164 
    165 	state[0] += a;
    166 	state[1] += b;
    167 	state[2] += c;
    168 	state[3] += d;
    169 
    170 	/* Zeroize sensitive information.*/
    171 	memset ((POINTER)x, 0, sizeof (x));
    172 }
    173 
    174 /* MD4 initialization. Begins an MD4 operation, writing a new context. */
    175 void MD4_Init( MD4_CTX *context ) {
    176 	context->count[0] = context->count[1] = 0;
    177 
    178 	/* Load magic initialization constants.*/
    179 	context->state[0] = 0x67452301;
    180 	context->state[1] = 0xefcdab89;
    181 	context->state[2] = 0x98badcfe;
    182 	context->state[3] = 0x10325476;
    183 }
    184 
    185 /* MD4 block update operation. Continues an MD4 message-digest operation, processing another message block, and updating the context. */
    186 void MD4_Update( MD4_CTX *context, const unsigned char *input, unsigned int inputLen ) {
    187 	unsigned int i, index, partLen;
    188 
    189 	/* Compute number of bytes mod 64 */
    190 	index = (unsigned int)((context->count[0] >> 3) & 0x3F);
    191 
    192 	/* Update number of bits */
    193 	if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3)) {
    194 		context->count[1]++;
    195 	}
    196 
    197 	context->count[1] += ((UINT4)inputLen >> 29);
    198 
    199 	partLen = 64 - index;
    200 
    201 	/* Transform as many times as possible.*/
    202 	if ( inputLen >= partLen ) {
    203  		memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
    204  		MD4_Transform (context->state, context->buffer);
    205 
    206 		for ( i = partLen; i + 63 < inputLen; i += 64 ) {
    207  			MD4_Transform (context->state, &input[i]);
    208 		}
    209 
    210  		index = 0;
    211 	} else {
    212  		i = 0;
    213 	}
    214 
    215 	/* Buffer remaining input */
    216 	memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
    217 }
    218 
    219 /* MD4 finalization. Ends an MD4 message-digest operation, writing the message digest and zeroizing the context. */
    220 void MD4_Final( MD4_CTX *context, unsigned char digest[16] ) {
    221 	unsigned char bits[8];
    222 	unsigned int index, padLen;
    223 
    224 	/* Save number of bits */
    225 	Encode( bits, context->count, 8 );
    226 
    227 	/* Pad out to 56 mod 64.*/
    228 	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
    229 	padLen = (index < 56) ? (56 - index) : (120 - index);
    230 	MD4_Update (context, PADDING, padLen);
    231 
    232 	/* Append length (before padding) */
    233 	MD4_Update( context, bits, 8 );
    234 	
    235 	/* Store state in digest */
    236 	Encode( digest, context->state, 16 );
    237 
    238 	/* Zeroize sensitive information.*/
    239 	memset ((POINTER)context, 0, sizeof (*context));
    240 }
    241 
    242 /*
    243 ===============
    244 MD4_BlockChecksum
    245 ===============
    246 */
    247 unsigned long MD4_BlockChecksum( const void *data, int length ) {
    248 	unsigned long	digest[4];
    249 	unsigned long	val;
    250 	MD4_CTX			ctx;
    251 
    252 	MD4_Init( &ctx );
    253 	MD4_Update( &ctx, (unsigned char *)data, length );
    254 	MD4_Final( &ctx, (unsigned char *)digest );
    255 
    256 	val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
    257 
    258 	return val;
    259 }