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