undocumented opcodes added to ncpu
[fceu.git] / md5.c
CommitLineData
d97315ac 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
34void 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
44void 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
167void 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
204static 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
212void 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
234char *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