]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/idlib/hashing/MD4.cpp
hello world
[icculus/iodoom3.git] / neo / idlib / hashing / MD4.cpp
1
2 #include "../precompiled.h"
3 #pragma hdrstop
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 }