blob: a91337f28287606afeb4271c99499e7b22d445aa [file] [log] [blame]
Andy Greenff95d7a2010-10-28 22:36:01 +01001/*
2 * Originally from Polarssl here
3 * http://polarssl.org/show_source?file=md5
4 * under GPL2 or later
5 * truncated to remove hmac support
6 */
7
8
9#include <string.h>
10#include <stdio.h>
11
12
13typedef struct
14{
15 unsigned long total[2]; /*!< number of bytes processed */
16 unsigned long state[4]; /*!< intermediate digest state */
17 unsigned char buffer[64]; /*!< data block being processed */
18}
19md5_context;
20
21
22/**
23 * \brief MD5 context setup
24 *
25 * \param ctx context to be initialized
26 */
27void md5_starts( md5_context *ctx );
28
29/**
30 * \brief MD5 process buffer
31 *
32 * \param ctx MD5 context
33 * \param input buffer holding the data
34 * \param ilen length of the input data
35 */
36void md5_update( md5_context *ctx, const unsigned char *input, int ilen );
37
38/**
39 * \brief MD5 final digest
40 *
41 * \param ctx MD5 context
42 * \param output MD5 checksum result
43 */
44void md5_finish( md5_context *ctx, unsigned char output[16] );
45
46/**
47 * \brief Output = MD5( input buffer )
48 *
49 * \param input buffer holding the data
50 * \param ilen length of the input data
51 * \param output MD5 checksum result
52 */
53void md5( const unsigned char *input, int ilen, unsigned char output[16] );
54
55/**
56 * \brief Output = MD5( file contents )
57 *
58 * \param path input file name
59 * \param output MD5 checksum result
60 *
61 * \return 0 if successful, 1 if fopen failed,
62 * or 2 if fread failed
63 */
64int md5_file( const char *path, unsigned char output[16] );
65
66
67
68/*
69 * 32-bit integer manipulation macros (little endian)
70 */
71#ifndef GET_ULONG_LE
72#define GET_ULONG_LE(n,b,i) \
73{ \
74 (n) = ( (unsigned long) (b)[(i) ] ) \
75 | ( (unsigned long) (b)[(i) + 1] << 8 ) \
76 | ( (unsigned long) (b)[(i) + 2] << 16 ) \
77 | ( (unsigned long) (b)[(i) + 3] << 24 ); \
78}
79#endif
80
81#ifndef PUT_ULONG_LE
82#define PUT_ULONG_LE(n,b,i) \
83{ \
84 (b)[(i) ] = (unsigned char) ( (n) ); \
85 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
86 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
87 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
88}
89#endif
90
91/*
92 * MD5 context setup
93 */
94void md5_starts( md5_context *ctx )
95{
96 ctx->total[0] = 0;
97 ctx->total[1] = 0;
98
99 ctx->state[0] = 0x67452301;
100 ctx->state[1] = 0xEFCDAB89;
101 ctx->state[2] = 0x98BADCFE;
102 ctx->state[3] = 0x10325476;
103}
104
105static void md5_process( md5_context *ctx, const unsigned char data[64] )
106{
107 unsigned long X[16], A, B, C, D;
108
109 GET_ULONG_LE( X[ 0], data, 0 );
110 GET_ULONG_LE( X[ 1], data, 4 );
111 GET_ULONG_LE( X[ 2], data, 8 );
112 GET_ULONG_LE( X[ 3], data, 12 );
113 GET_ULONG_LE( X[ 4], data, 16 );
114 GET_ULONG_LE( X[ 5], data, 20 );
115 GET_ULONG_LE( X[ 6], data, 24 );
116 GET_ULONG_LE( X[ 7], data, 28 );
117 GET_ULONG_LE( X[ 8], data, 32 );
118 GET_ULONG_LE( X[ 9], data, 36 );
119 GET_ULONG_LE( X[10], data, 40 );
120 GET_ULONG_LE( X[11], data, 44 );
121 GET_ULONG_LE( X[12], data, 48 );
122 GET_ULONG_LE( X[13], data, 52 );
123 GET_ULONG_LE( X[14], data, 56 );
124 GET_ULONG_LE( X[15], data, 60 );
125
126#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
127
128#define P(a,b,c,d,k,s,t) \
129{ \
130 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
131}
132
133 A = ctx->state[0];
134 B = ctx->state[1];
135 C = ctx->state[2];
136 D = ctx->state[3];
137
138#define F(x,y,z) (z ^ (x & (y ^ z)))
139
140 P( A, B, C, D, 0, 7, 0xD76AA478 );
141 P( D, A, B, C, 1, 12, 0xE8C7B756 );
142 P( C, D, A, B, 2, 17, 0x242070DB );
143 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
144 P( A, B, C, D, 4, 7, 0xF57C0FAF );
145 P( D, A, B, C, 5, 12, 0x4787C62A );
146 P( C, D, A, B, 6, 17, 0xA8304613 );
147 P( B, C, D, A, 7, 22, 0xFD469501 );
148 P( A, B, C, D, 8, 7, 0x698098D8 );
149 P( D, A, B, C, 9, 12, 0x8B44F7AF );
150 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
151 P( B, C, D, A, 11, 22, 0x895CD7BE );
152 P( A, B, C, D, 12, 7, 0x6B901122 );
153 P( D, A, B, C, 13, 12, 0xFD987193 );
154 P( C, D, A, B, 14, 17, 0xA679438E );
155 P( B, C, D, A, 15, 22, 0x49B40821 );
156
157#undef F
158
159#define F(x,y,z) (y ^ (z & (x ^ y)))
160
161 P( A, B, C, D, 1, 5, 0xF61E2562 );
162 P( D, A, B, C, 6, 9, 0xC040B340 );
163 P( C, D, A, B, 11, 14, 0x265E5A51 );
164 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
165 P( A, B, C, D, 5, 5, 0xD62F105D );
166 P( D, A, B, C, 10, 9, 0x02441453 );
167 P( C, D, A, B, 15, 14, 0xD8A1E681 );
168 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
169 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
170 P( D, A, B, C, 14, 9, 0xC33707D6 );
171 P( C, D, A, B, 3, 14, 0xF4D50D87 );
172 P( B, C, D, A, 8, 20, 0x455A14ED );
173 P( A, B, C, D, 13, 5, 0xA9E3E905 );
174 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
175 P( C, D, A, B, 7, 14, 0x676F02D9 );
176 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
177
178#undef F
179
180#define F(x,y,z) (x ^ y ^ z)
181
182 P( A, B, C, D, 5, 4, 0xFFFA3942 );
183 P( D, A, B, C, 8, 11, 0x8771F681 );
184 P( C, D, A, B, 11, 16, 0x6D9D6122 );
185 P( B, C, D, A, 14, 23, 0xFDE5380C );
186 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
187 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
188 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
189 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
190 P( A, B, C, D, 13, 4, 0x289B7EC6 );
191 P( D, A, B, C, 0, 11, 0xEAA127FA );
192 P( C, D, A, B, 3, 16, 0xD4EF3085 );
193 P( B, C, D, A, 6, 23, 0x04881D05 );
194 P( A, B, C, D, 9, 4, 0xD9D4D039 );
195 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
196 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
197 P( B, C, D, A, 2, 23, 0xC4AC5665 );
198
199#undef F
200
201#define F(x,y,z) (y ^ (x | ~z))
202
203 P( A, B, C, D, 0, 6, 0xF4292244 );
204 P( D, A, B, C, 7, 10, 0x432AFF97 );
205 P( C, D, A, B, 14, 15, 0xAB9423A7 );
206 P( B, C, D, A, 5, 21, 0xFC93A039 );
207 P( A, B, C, D, 12, 6, 0x655B59C3 );
208 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
209 P( C, D, A, B, 10, 15, 0xFFEFF47D );
210 P( B, C, D, A, 1, 21, 0x85845DD1 );
211 P( A, B, C, D, 8, 6, 0x6FA87E4F );
212 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
213 P( C, D, A, B, 6, 15, 0xA3014314 );
214 P( B, C, D, A, 13, 21, 0x4E0811A1 );
215 P( A, B, C, D, 4, 6, 0xF7537E82 );
216 P( D, A, B, C, 11, 10, 0xBD3AF235 );
217 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
218 P( B, C, D, A, 9, 21, 0xEB86D391 );
219
220#undef F
221
222 ctx->state[0] += A;
223 ctx->state[1] += B;
224 ctx->state[2] += C;
225 ctx->state[3] += D;
226}
227
228/*
229 * MD5 process buffer
230 */
231void md5_update( md5_context *ctx, const unsigned char *input, int ilen )
232{
233 int fill;
234 unsigned long left;
235
236 if( ilen <= 0 )
237 return;
238
239 left = ctx->total[0] & 0x3F;
240 fill = 64 - left;
241
242 ctx->total[0] += ilen;
243 ctx->total[0] &= 0xFFFFFFFF;
244
245 if( ctx->total[0] < (unsigned long) ilen )
246 ctx->total[1]++;
247
248 if( left && ilen >= fill )
249 {
250 memcpy( (void *) (ctx->buffer + left),
251 (void *) input, fill );
252 md5_process( ctx, ctx->buffer );
253 input += fill;
254 ilen -= fill;
255 left = 0;
256 }
257
258 while( ilen >= 64 )
259 {
260 md5_process( ctx, input );
261 input += 64;
262 ilen -= 64;
263 }
264
265 if( ilen > 0 )
266 {
267 memcpy( (void *) (ctx->buffer + left),
268 (void *) input, ilen );
269 }
270}
271
272static const unsigned char md5_padding[64] =
273{
274 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
275 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
276 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
277 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
278};
279
280/*
281 * MD5 final digest
282 */
283void md5_finish( md5_context *ctx, unsigned char output[16] )
284{
285 unsigned long last, padn;
286 unsigned long high, low;
287 unsigned char msglen[8];
288
289 high = ( ctx->total[0] >> 29 )
290 | ( ctx->total[1] << 3 );
291 low = ( ctx->total[0] << 3 );
292
293 PUT_ULONG_LE( low, msglen, 0 );
294 PUT_ULONG_LE( high, msglen, 4 );
295
296 last = ctx->total[0] & 0x3F;
297 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
298
299 md5_update( ctx, (unsigned char *) md5_padding, padn );
300 md5_update( ctx, msglen, 8 );
301
302 PUT_ULONG_LE( ctx->state[0], output, 0 );
303 PUT_ULONG_LE( ctx->state[1], output, 4 );
304 PUT_ULONG_LE( ctx->state[2], output, 8 );
305 PUT_ULONG_LE( ctx->state[3], output, 12 );
306}
307
308/*
309 * output = MD5( input buffer )
310 */
311void md5( const unsigned char *input, int ilen, unsigned char output[16] )
312{
313 md5_context ctx;
314
315 md5_starts( &ctx );
316 md5_update( &ctx, input, ilen );
317 md5_finish( &ctx, output );
318
319 memset( &ctx, 0, sizeof( md5_context ) );
320}
321
322/*
323 * output = MD5( file contents )
324 */
325int md5_file( const char *path, unsigned char output[16] )
326{
327 FILE *f;
328 size_t n;
329 md5_context ctx;
330 unsigned char buf[1024];
331
332 if( ( f = fopen( path, "rb" ) ) == NULL )
333 return( 1 );
334
335 md5_starts( &ctx );
336
337 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
338 md5_update( &ctx, buf, (int) n );
339
340 md5_finish( &ctx, output );
341
342 memset( &ctx, 0, sizeof( md5_context ) );
343
344 if( ferror( f ) != 0 )
345 {
346 fclose( f );
347 return( 2 );
348 }
349
350 fclose( f );
351 return( 0 );
352}
353