]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/idlib/hashing/MD5.cpp
hello world
[icculus/iodoom3.git] / neo / idlib / hashing / MD5.cpp
1
2 #include "../precompiled.h"
3 #pragma hdrstop
4
5 /*
6    MD5 Message Digest Algorithm. (RFC1321)
7 */
8
9 /*
10
11 This code implements the MD5 message-digest algorithm.
12 The algorithm is due to Ron Rivest.  This code was
13 written by Colin Plumb in 1993, no copyright is claimed.
14 This code is in the public domain; do with it what you wish.
15
16 Equivalent code is available from RSA Data Security, Inc.
17 This code has been tested against that, and is equivalent,
18 except that you don't need to include two pages of legalese
19 with every copy.
20
21 To compute the message digest of a chunk of bytes, declare an
22 MD5Context structure, pass it to MD5Init, call MD5Update as
23 needed on buffers full of bytes, and then call MD5Final, which
24 will fill a supplied 16-byte array with the digest.
25
26 */
27
28 /* MD5 context. */
29 typedef struct
30 {
31         unsigned int    state[4];
32     unsigned int        bits[2];
33     unsigned char       in[64];
34 } MD5_CTX;
35
36 /* The four core functions - F1 is optimized somewhat */
37 /* #define F1(x, y, z) (x & y | ~x & z) */
38 #define F1(x, y, z) (z ^ (x & (y ^ z)))
39 #define F2(x, y, z) F1(z, x, y)
40 #define F3(x, y, z) (x ^ y ^ z)
41 #define F4(x, y, z) (y ^ (x | ~z))
42
43 /* This is the central step in the MD5 algorithm. */
44 #define MD5STEP(f, w, x, y, z, data, s) ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
45
46 /*
47 =================
48 MD5_Transform
49
50 The core of the MD5 algorithm, this alters an existing MD5 hash to
51 reflect the addition of 16 longwords of new data.  MD5Update blocks
52 the data and converts bytes into longwords for this routine.
53 =================
54 */
55 void MD5_Transform( unsigned int state[4], unsigned int in[16] ) {
56     register unsigned int a, b, c, d;
57
58     a = state[0];
59     b = state[1];
60     c = state[2];
61     d = state[3];
62
63         LittleRevBytes( in, sizeof(unsigned int), 16 );
64
65     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
66     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
67     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
68     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
69     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
70     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
71     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
72     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
73     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
74     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
75     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
76     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
77     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
78     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
79     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
80     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
81
82     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
83     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
84     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
85     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
86     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
87     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
88     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
89     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
90     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
91     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
92     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
93     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
94     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
95     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
96     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
97     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
98
99     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
100     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
101     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
102     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
103     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
104     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
105     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
106     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
107     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
108     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
109     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
110     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
111     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
112     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
113     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
114     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
115
116     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
117     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
118     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
119     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
120     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
121     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
122     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
123     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
124     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
125     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
126     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
127     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
128     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
129     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
130     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
131     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
132
133         LittleRevBytes( in, sizeof(unsigned int), 16 );
134
135     state[0] += a;
136     state[1] += b;
137     state[2] += c;
138     state[3] += d;
139 }
140
141 /*
142 ==================
143 MD5_Init
144
145 MD5 initialization. Begins an MD5 operation, writing a new context.
146 ==================
147 */
148 void MD5_Init( MD5_CTX *ctx ) {
149     ctx->state[0] = 0x67452301;
150     ctx->state[1] = 0xefcdab89;
151     ctx->state[2] = 0x98badcfe;
152     ctx->state[3] = 0x10325476;
153
154     ctx->bits[0] = 0;
155     ctx->bits[1] = 0;
156 }
157
158 /*
159 ===================
160 MD5_Update
161
162 MD5 block update operation. Continues an MD5 message-digest operation,
163 processing another message block, and updating the context.
164 ===================
165 */
166 void MD5_Update( MD5_CTX *ctx, unsigned char const *buf, unsigned int len ) {
167     unsigned int t;
168
169     /* Update bitcount */
170
171     t = ctx->bits[0];
172         if ( ( ctx->bits[0] = t + ( (unsigned int) len << 3 ) ) < t ) {
173         ctx->bits[1]++;         /* Carry from low to high */
174         }
175     ctx->bits[1] += len >> 29;
176
177     t = ( t >> 3 ) & 0x3f;        /* Bytes already in shsInfo->data */
178
179     /* Handle any leading odd-sized chunks */
180
181     if ( t ) {
182         unsigned char *p = (unsigned char *) ctx->in + t;
183
184         t = 64 - t;
185         if ( len < t ) {
186             memcpy( p, buf, len );
187             return;
188         }
189         memcpy( p, buf, t );
190         MD5_Transform( ctx->state, (unsigned int *) ctx->in );
191         buf += t;
192         len -= t;
193     }
194     /* Process data in 64-byte chunks */
195
196     while( len >= 64 ) {
197         memcpy( ctx->in, buf, 64 );
198         MD5_Transform( ctx->state, (unsigned int *) ctx->in );
199         buf += 64;
200         len -= 64;
201     }
202
203     /* Handle any remaining bytes of data. */
204     memcpy( ctx->in, buf, len );
205 }
206
207 /*
208 ===============
209 MD5_Final
210
211 MD5 finalization. Ends an MD5 message-digest operation,
212 writing the message digest and zeroizing the context.
213 ===============
214 */
215 void MD5_Final( MD5_CTX *ctx, unsigned char digest[16] ) {
216     unsigned count;
217     unsigned char *p;
218
219     /* Compute number of bytes mod 64 */
220     count = ( ctx->bits[0] >> 3 ) & 0x3F;
221
222     /* Set the first char of padding to 0x80.  This is safe since there is
223        always at least one byte free */
224     p = ctx->in + count;
225     *p++ = 0x80;
226
227     /* Bytes of padding needed to make 64 bytes */
228     count = 64 - 1 - count;
229
230     /* Pad out to 56 mod 64 */
231     if ( count < 8 ) {
232         /* Two lots of padding:  Pad the first block to 64 bytes */
233         memset( p, 0, count );
234         MD5_Transform( ctx->state, (unsigned int *) ctx->in );
235
236         /* Now fill the next block with 56 bytes */
237         memset( ctx->in, 0, 56 );
238     } else {
239         /* Pad block to 56 bytes */
240         memset( p, 0, count - 8 );
241     }
242
243     /* Append length in bits and transform */
244         unsigned int val0 = ctx->bits[0];
245         unsigned int val1 = ctx->bits[1];
246         
247     ((unsigned int *) ctx->in)[14] = LittleLong( val0 );
248     ((unsigned int *) ctx->in)[15] = LittleLong( val1 );
249
250     MD5_Transform( ctx->state, (unsigned int *) ctx->in );
251     memcpy( digest, ctx->state, 16 );
252     memset( ctx, 0, sizeof( ctx ) );        /* In case it's sensitive */
253 }
254
255 /*
256 ===============
257 MD5_BlockChecksum
258 ===============
259 */
260 unsigned long MD5_BlockChecksum( const void *data, int length ) {
261         unsigned long   digest[4];
262         unsigned long   val;
263         MD5_CTX                 ctx;
264
265         MD5_Init( &ctx );
266         MD5_Update( &ctx, (unsigned char *)data, length );
267         MD5_Final( &ctx, (unsigned char *)digest );
268
269         val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
270
271         return val;
272 }