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