continue with pandora port
[fceu.git] / md5.c
1 /*\r
2  * RFC 1321 compliant MD5 implementation,\r
3  * by Christophe Devine <devine@cr0.net>;\r
4  * this program is licensed under the GPL.\r
5  */\r
6 \r
7 /* Modified October 3, 2003, to remove testing code, and add\r
8    include of "types.h".\r
9  \r
10    Added simple MD5 to ASCII string conversion function.\r
11    -Xodnizel\r
12 */\r
13 \r
14 #include <string.h>\r
15 #include "types.h"\r
16 #include "md5.h"\r
17 \r
18 #define GET_UINT32(n,b,i)           \\r
19 {                 \\r
20     (n) = ( (uint32) (b)[(i) + 3] << 24 )       \\r
21         | ( (uint32) (b)[(i) + 2] << 16 )       \\r
22         | ( (uint32) (b)[(i) + 1] <<  8 )       \\r
23         | ( (uint32) (b)[(i)    ]       );      \\r
24 }\r
25 \r
26 #define PUT_UINT32(n,b,i)           \\r
27 {                 \\r
28     (b)[(i)    ] = (uint8) ( (n)       );       \\r
29     (b)[(i) + 1] = (uint8) ( (n) >>  8 );       \\r
30     (b)[(i) + 2] = (uint8) ( (n) >> 16 );       \\r
31     (b)[(i) + 3] = (uint8) ( (n) >> 24 );       \\r
32 }\r
33 \r
34 void md5_starts( struct md5_context *ctx )\r
35 {\r
36     ctx->total[0] = 0;\r
37     ctx->total[1] = 0;\r
38     ctx->state[0] = 0x67452301;\r
39     ctx->state[1] = 0xEFCDAB89;\r
40     ctx->state[2] = 0x98BADCFE;\r
41     ctx->state[3] = 0x10325476;\r
42 }\r
43 \r
44 void md5_process( struct md5_context *ctx, uint8 data[64] )\r
45 {\r
46     uint32 A, B, C, D, X[16];\r
47 \r
48     GET_UINT32( X[0],  data,  0 );\r
49     GET_UINT32( X[1],  data,  4 );\r
50     GET_UINT32( X[2],  data,  8 );\r
51     GET_UINT32( X[3],  data, 12 );\r
52     GET_UINT32( X[4],  data, 16 );\r
53     GET_UINT32( X[5],  data, 20 );\r
54     GET_UINT32( X[6],  data, 24 );\r
55     GET_UINT32( X[7],  data, 28 );\r
56     GET_UINT32( X[8],  data, 32 );\r
57     GET_UINT32( X[9],  data, 36 );\r
58     GET_UINT32( X[10], data, 40 );\r
59     GET_UINT32( X[11], data, 44 );\r
60     GET_UINT32( X[12], data, 48 );\r
61     GET_UINT32( X[13], data, 52 );\r
62     GET_UINT32( X[14], data, 56 );\r
63     GET_UINT32( X[15], data, 60 );\r
64 \r
65 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))\r
66 \r
67 #define P(a,b,c,d,k,s,t)        \\r
68 {                   \\r
69     a += F(b,c,d) + X[k] + t; a = S(a,s) + b;     \\r
70 }\r
71 \r
72     A = ctx->state[0];\r
73     B = ctx->state[1];\r
74     C = ctx->state[2];\r
75     D = ctx->state[3];\r
76 \r
77 #define F(x,y,z) (z ^ (x & (y ^ z)))\r
78 \r
79     P( A, B, C, D,  0,  7, 0xD76AA478 );\r
80     P( D, A, B, C,  1, 12, 0xE8C7B756 );\r
81     P( C, D, A, B,  2, 17, 0x242070DB );\r
82     P( B, C, D, A,  3, 22, 0xC1BDCEEE );\r
83     P( A, B, C, D,  4,  7, 0xF57C0FAF );\r
84     P( D, A, B, C,  5, 12, 0x4787C62A );\r
85     P( C, D, A, B,  6, 17, 0xA8304613 );\r
86     P( B, C, D, A,  7, 22, 0xFD469501 );\r
87     P( A, B, C, D,  8,  7, 0x698098D8 );\r
88     P( D, A, B, C,  9, 12, 0x8B44F7AF );\r
89     P( C, D, A, B, 10, 17, 0xFFFF5BB1 );\r
90     P( B, C, D, A, 11, 22, 0x895CD7BE );\r
91     P( A, B, C, D, 12,  7, 0x6B901122 );\r
92     P( D, A, B, C, 13, 12, 0xFD987193 );\r
93     P( C, D, A, B, 14, 17, 0xA679438E );\r
94     P( B, C, D, A, 15, 22, 0x49B40821 );\r
95 \r
96 #undef F\r
97 \r
98 #define F(x,y,z) (y ^ (z & (x ^ y)))\r
99 \r
100     P( A, B, C, D,  1,  5, 0xF61E2562 );\r
101     P( D, A, B, C,  6,  9, 0xC040B340 );\r
102     P( C, D, A, B, 11, 14, 0x265E5A51 );\r
103     P( B, C, D, A,  0, 20, 0xE9B6C7AA );\r
104     P( A, B, C, D,  5,  5, 0xD62F105D );\r
105     P( D, A, B, C, 10,  9, 0x02441453 );\r
106     P( C, D, A, B, 15, 14, 0xD8A1E681 );\r
107     P( B, C, D, A,  4, 20, 0xE7D3FBC8 );\r
108     P( A, B, C, D,  9,  5, 0x21E1CDE6 );\r
109     P( D, A, B, C, 14,  9, 0xC33707D6 );\r
110     P( C, D, A, B,  3, 14, 0xF4D50D87 );\r
111     P( B, C, D, A,  8, 20, 0x455A14ED );\r
112     P( A, B, C, D, 13,  5, 0xA9E3E905 );\r
113     P( D, A, B, C,  2,  9, 0xFCEFA3F8 );\r
114     P( C, D, A, B,  7, 14, 0x676F02D9 );\r
115     P( B, C, D, A, 12, 20, 0x8D2A4C8A );\r
116 \r
117 #undef F\r
118     \r
119 #define F(x,y,z) (x ^ y ^ z)\r
120 \r
121     P( A, B, C, D,  5,  4, 0xFFFA3942 );\r
122     P( D, A, B, C,  8, 11, 0x8771F681 );\r
123     P( C, D, A, B, 11, 16, 0x6D9D6122 );\r
124     P( B, C, D, A, 14, 23, 0xFDE5380C );\r
125     P( A, B, C, D,  1,  4, 0xA4BEEA44 );\r
126     P( D, A, B, C,  4, 11, 0x4BDECFA9 );\r
127     P( C, D, A, B,  7, 16, 0xF6BB4B60 );\r
128     P( B, C, D, A, 10, 23, 0xBEBFBC70 );\r
129     P( A, B, C, D, 13,  4, 0x289B7EC6 );\r
130     P( D, A, B, C,  0, 11, 0xEAA127FA );\r
131     P( C, D, A, B,  3, 16, 0xD4EF3085 );\r
132     P( B, C, D, A,  6, 23, 0x04881D05 );\r
133     P( A, B, C, D,  9,  4, 0xD9D4D039 );\r
134     P( D, A, B, C, 12, 11, 0xE6DB99E5 );\r
135     P( C, D, A, B, 15, 16, 0x1FA27CF8 );\r
136     P( B, C, D, A,  2, 23, 0xC4AC5665 );\r
137 \r
138 #undef F\r
139 \r
140 #define F(x,y,z) (y ^ (x | ~z))\r
141 \r
142     P( A, B, C, D,  0,  6, 0xF4292244 );\r
143     P( D, A, B, C,  7, 10, 0x432AFF97 );\r
144     P( C, D, A, B, 14, 15, 0xAB9423A7 );\r
145     P( B, C, D, A,  5, 21, 0xFC93A039 );\r
146     P( A, B, C, D, 12,  6, 0x655B59C3 );\r
147     P( D, A, B, C,  3, 10, 0x8F0CCC92 );\r
148     P( C, D, A, B, 10, 15, 0xFFEFF47D );\r
149     P( B, C, D, A,  1, 21, 0x85845DD1 );\r
150     P( A, B, C, D,  8,  6, 0x6FA87E4F );\r
151     P( D, A, B, C, 15, 10, 0xFE2CE6E0 );\r
152     P( C, D, A, B,  6, 15, 0xA3014314 );\r
153     P( B, C, D, A, 13, 21, 0x4E0811A1 );\r
154     P( A, B, C, D,  4,  6, 0xF7537E82 );\r
155     P( D, A, B, C, 11, 10, 0xBD3AF235 );\r
156     P( C, D, A, B,  2, 15, 0x2AD7D2BB );\r
157     P( B, C, D, A,  9, 21, 0xEB86D391 );\r
158 \r
159 #undef F\r
160 \r
161     ctx->state[0] += A;\r
162     ctx->state[1] += B;\r
163     ctx->state[2] += C;\r
164     ctx->state[3] += D;\r
165 }\r
166 \r
167 void md5_update( struct md5_context *ctx, uint8 *input, uint32 length )\r
168 {\r
169     uint32 left, fill;\r
170 \r
171     if( ! length ) return;\r
172 \r
173     left = ( ctx->total[0] >> 3 ) & 0x3F;\r
174     fill = 64 - left;\r
175 \r
176     ctx->total[0] += length <<  3;\r
177     ctx->total[1] += length >> 29;\r
178 \r
179     ctx->total[0] &= 0xFFFFFFFF;\r
180     ctx->total[1] += ctx->total[0] < ( length << 3 );\r
181 \r
182     if( left && length >= fill )\r
183     {\r
184         memcpy( (void *) (ctx->buffer + left), (void *) input, fill );\r
185         md5_process( ctx, ctx->buffer );\r
186         length -= fill;\r
187         input  += fill;\r
188         left = 0;\r
189     }\r
190 \r
191     while( length >= 64 )\r
192     {\r
193         md5_process( ctx, input );\r
194         length -= 64;\r
195         input  += 64;\r
196     }\r
197 \r
198     if( length )\r
199     {\r
200         memcpy( (void *) (ctx->buffer + left), (void *) input, length );\r
201     }\r
202 }\r
203 \r
204 static uint8 md5_padding[64] =\r
205 {\r
206  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
207     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
208     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
209     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
210 };\r
211 \r
212 void md5_finish( struct md5_context *ctx, uint8 digest[16] )\r
213 {\r
214     uint32 last, padn;\r
215     uint8 msglen[8];\r
216 \r
217     PUT_UINT32( ctx->total[0], msglen, 0 );\r
218     PUT_UINT32( ctx->total[1], msglen, 4 );\r
219 \r
220     last = ( ctx->total[0] >> 3 ) & 0x3F;\r
221     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );\r
222 \r
223     md5_update( ctx, md5_padding, padn );\r
224     md5_update( ctx, msglen, 8 );\r
225 \r
226     PUT_UINT32( ctx->state[0], digest,  0 );\r
227     PUT_UINT32( ctx->state[1], digest,  4 );\r
228     PUT_UINT32( ctx->state[2], digest,  8 );\r
229     PUT_UINT32( ctx->state[3], digest, 12 );\r
230 }\r
231 \r
232 \r
233 /* Uses a static buffer, so beware of how it's used. */\r
234 char *md5_asciistr(uint8 digest[16])\r
235 {\r
236  static char str[33];\r
237  static char trans[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};\r
238  int x;\r
239 \r
240  for(x=0;x<16;x++)\r
241  {\r
242   str[x*2]=trans[digest[x]&0x0F];\r
243   str[x*2+1]=trans[digest[x]>>4];\r
244  }\r
245  return(str);\r
246 }\r