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  */
9 typedef 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 }
18 md5_context;
19 
20 /**
21  * \brief          MD5 context setup
22  *
23  * \param ctx      context to be initialized
24  */
25 void 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  */
34 void 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  */
42 void 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  */
51 void 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  */
62 int 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  */
71 void 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  */
80 void 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  */
88 void 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  */
99 void 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  */
108 int 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  */
md5_starts(md5_context * ctx)136 void 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 
md5_process(md5_context * ctx,unsigned char data[64])147 static 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  */
md5_update(md5_context * ctx,unsigned char * input,int ilen)273 void 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 
314 static 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  */
md5_finish(md5_context * ctx,unsigned char output[16])325 void 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  */
md5(unsigned char * input,int ilen,unsigned char output[16])353 void 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 
md5hash(const void * input,int len,unsigned int)364 unsigned 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 
md5_32(const void * key,int len,uint32_t,void * out)375 void 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 }