1
2 /*
3 Christophe Devine
4 c.devine@cr0.net
5 http://www.cr0.net:8040/code/crypto/
6 */
7 /*
8 * RFC 1321 compliant MD5 implementation
9 *
10 * Copyright (C) 2001-2003 Christophe Devine
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27 #include <string.h>
28 #include "Types.hpp"
29 #include "md5.hpp"
30
31
32 #define GET_UINT32(n,b,i) \
33 { \
34 (n) = ( (uint32) (b)[(i) ] ) \
35 | ( (uint32) (b)[(i) + 1] << 8 ) \
36 | ( (uint32) (b)[(i) + 2] << 16 ) \
37 | ( (uint32) (b)[(i) + 3] << 24 ); \
38 }
39
40 #define PUT_UINT32(n,b,i) \
41 { \
42 (b)[(i) ] = (uint8) ( (n) ); \
43 (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \
44 (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \
45 (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \
46 }
47
md5_starts(md5_context * ctx)48 void md5_starts( md5_context *ctx )
49 {
50 ctx->total[0] = 0;
51 ctx->total[1] = 0;
52
53 ctx->state[0] = 0x67452301;
54 ctx->state[1] = 0xEFCDAB89;
55 ctx->state[2] = 0x98BADCFE;
56 ctx->state[3] = 0x10325476;
57 }
58
md5_process(md5_context * ctx,uint8 data[64])59 void md5_process( md5_context *ctx, uint8 data[64] )
60 {
61 uint32 X[16], A, B, C, D;
62
63 GET_UINT32( X[0], data, 0 );
64 GET_UINT32( X[1], data, 4 );
65 GET_UINT32( X[2], data, 8 );
66 GET_UINT32( X[3], data, 12 );
67 GET_UINT32( X[4], data, 16 );
68 GET_UINT32( X[5], data, 20 );
69 GET_UINT32( X[6], data, 24 );
70 GET_UINT32( X[7], data, 28 );
71 GET_UINT32( X[8], data, 32 );
72 GET_UINT32( X[9], data, 36 );
73 GET_UINT32( X[10], data, 40 );
74 GET_UINT32( X[11], data, 44 );
75 GET_UINT32( X[12], data, 48 );
76 GET_UINT32( X[13], data, 52 );
77 GET_UINT32( X[14], data, 56 );
78 GET_UINT32( X[15], data, 60 );
79
80 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
81
82 #define P(a,b,c,d,k,s,t) \
83 { \
84 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
85 }
86
87 A = ctx->state[0];
88 B = ctx->state[1];
89 C = ctx->state[2];
90 D = ctx->state[3];
91
92 #define F(x,y,z) (z ^ (x & (y ^ z)))
93
94 P( A, B, C, D, 0, 7, 0xD76AA478 );
95 P( D, A, B, C, 1, 12, 0xE8C7B756 );
96 P( C, D, A, B, 2, 17, 0x242070DB );
97 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
98 P( A, B, C, D, 4, 7, 0xF57C0FAF );
99 P( D, A, B, C, 5, 12, 0x4787C62A );
100 P( C, D, A, B, 6, 17, 0xA8304613 );
101 P( B, C, D, A, 7, 22, 0xFD469501 );
102 P( A, B, C, D, 8, 7, 0x698098D8 );
103 P( D, A, B, C, 9, 12, 0x8B44F7AF );
104 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
105 P( B, C, D, A, 11, 22, 0x895CD7BE );
106 P( A, B, C, D, 12, 7, 0x6B901122 );
107 P( D, A, B, C, 13, 12, 0xFD987193 );
108 P( C, D, A, B, 14, 17, 0xA679438E );
109 P( B, C, D, A, 15, 22, 0x49B40821 );
110
111 #undef F
112
113 #define F(x,y,z) (y ^ (z & (x ^ y)))
114
115 P( A, B, C, D, 1, 5, 0xF61E2562 );
116 P( D, A, B, C, 6, 9, 0xC040B340 );
117 P( C, D, A, B, 11, 14, 0x265E5A51 );
118 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
119 P( A, B, C, D, 5, 5, 0xD62F105D );
120 P( D, A, B, C, 10, 9, 0x02441453 );
121 P( C, D, A, B, 15, 14, 0xD8A1E681 );
122 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
123 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
124 P( D, A, B, C, 14, 9, 0xC33707D6 );
125 P( C, D, A, B, 3, 14, 0xF4D50D87 );
126 P( B, C, D, A, 8, 20, 0x455A14ED );
127 P( A, B, C, D, 13, 5, 0xA9E3E905 );
128 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
129 P( C, D, A, B, 7, 14, 0x676F02D9 );
130 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
131
132 #undef F
133
134 #define F(x,y,z) (x ^ y ^ z)
135
136 P( A, B, C, D, 5, 4, 0xFFFA3942 );
137 P( D, A, B, C, 8, 11, 0x8771F681 );
138 P( C, D, A, B, 11, 16, 0x6D9D6122 );
139 P( B, C, D, A, 14, 23, 0xFDE5380C );
140 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
141 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
142 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
143 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
144 P( A, B, C, D, 13, 4, 0x289B7EC6 );
145 P( D, A, B, C, 0, 11, 0xEAA127FA );
146 P( C, D, A, B, 3, 16, 0xD4EF3085 );
147 P( B, C, D, A, 6, 23, 0x04881D05 );
148 P( A, B, C, D, 9, 4, 0xD9D4D039 );
149 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
150 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
151 P( B, C, D, A, 2, 23, 0xC4AC5665 );
152
153 #undef F
154
155 #define F(x,y,z) (y ^ (x | ~z))
156
157 P( A, B, C, D, 0, 6, 0xF4292244 );
158 P( D, A, B, C, 7, 10, 0x432AFF97 );
159 P( C, D, A, B, 14, 15, 0xAB9423A7 );
160 P( B, C, D, A, 5, 21, 0xFC93A039 );
161 P( A, B, C, D, 12, 6, 0x655B59C3 );
162 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
163 P( C, D, A, B, 10, 15, 0xFFEFF47D );
164 P( B, C, D, A, 1, 21, 0x85845DD1 );
165 P( A, B, C, D, 8, 6, 0x6FA87E4F );
166 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
167 P( C, D, A, B, 6, 15, 0xA3014314 );
168 P( B, C, D, A, 13, 21, 0x4E0811A1 );
169 P( A, B, C, D, 4, 6, 0xF7537E82 );
170 P( D, A, B, C, 11, 10, 0xBD3AF235 );
171 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
172 P( B, C, D, A, 9, 21, 0xEB86D391 );
173
174 #undef F
175
176 ctx->state[0] += A;
177 ctx->state[1] += B;
178 ctx->state[2] += C;
179 ctx->state[3] += D;
180 }
181
md5_update(md5_context * ctx,uint8 * input,uint32 length)182 void md5_update( md5_context *ctx, uint8 *input, uint32 length )
183 {
184 uint32 left, fill;
185
186 if (!length) return;
187
188 left = ctx->total[0] & 0x3F;
189 fill = 64 - left;
190
191 ctx->total[0] += length;
192 ctx->total[0] &= 0xFFFFFFFF;
193
194 if (ctx->total[0] < length)
195 ctx->total[1]++;
196
197 if (left && length >= fill)
198 {
199 memcpy( (void *)(ctx->buffer + left),
200 (void *)input, fill );
201 md5_process( ctx, ctx->buffer );
202 length -= fill;
203 input += fill;
204 left = 0;
205 }
206
207 while (length >= 64)
208 {
209 md5_process( ctx, input );
210 length -= 64;
211 input += 64;
212 }
213
214 if (length)
215 {
216 memcpy( (void *)(ctx->buffer + left),
217 (void *)input, length );
218 }
219 }
220
221 static uint8 md5_padding[64] =
222 {
223 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
224 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
226 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
227 };
228
md5_finish(md5_context * ctx,uint8 digest[16])229 void md5_finish( md5_context *ctx, uint8 digest[16] )
230 {
231 uint32 last, padn;
232 uint32 high, low;
233 uint8 msglen[8];
234
235 high = (ctx->total[0] >> 29)
236 | (ctx->total[1] << 3);
237 low = (ctx->total[0] << 3);
238
239 PUT_UINT32( low, msglen, 0 );
240 PUT_UINT32( high, msglen, 4 );
241
242 last = ctx->total[0] & 0x3F;
243 padn = (last < 56) ? (56 - last) : (120 - last);
244
245 md5_update( ctx, md5_padding, padn );
246 md5_update( ctx, msglen, 8 );
247
248 PUT_UINT32( ctx->state[0], digest, 0 );
249 PUT_UINT32( ctx->state[1], digest, 4 );
250 PUT_UINT32( ctx->state[2], digest, 8 );
251 PUT_UINT32( ctx->state[3], digest, 12 );
252 }
253