1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 // Disable symbol overrides so that we can use system headers.
24 #define FORBIDDEN_SYMBOL_ALLOW_ALL
25
26 #include "md5.h"
27
28 #define GET_UINT32(n, b, i) (n) = READ_LE_UINT32(b + i)
29 #define PUT_UINT32(n, b, i) WRITE_LE_UINT32(b + i, n)
30
md5_starts(md5_context * ctx)31 void md5_starts(md5_context *ctx) {
32 ctx->total[0] = 0;
33 ctx->total[1] = 0;
34
35 ctx->state[0] = 0x67452301;
36 ctx->state[1] = 0xEFCDAB89;
37 ctx->state[2] = 0x98BADCFE;
38 ctx->state[3] = 0x10325476;
39 }
40
md5_process(md5_context * ctx,const uint8 data[64])41 static void md5_process(md5_context *ctx, const uint8 data[64]) {
42 uint32 X[16], A, B, C, D;
43
44 GET_UINT32(X[0], data, 0);
45 GET_UINT32(X[1], data, 4);
46 GET_UINT32(X[2], data, 8);
47 GET_UINT32(X[3], data, 12);
48 GET_UINT32(X[4], data, 16);
49 GET_UINT32(X[5], data, 20);
50 GET_UINT32(X[6], data, 24);
51 GET_UINT32(X[7], data, 28);
52 GET_UINT32(X[8], data, 32);
53 GET_UINT32(X[9], data, 36);
54 GET_UINT32(X[10], data, 40);
55 GET_UINT32(X[11], data, 44);
56 GET_UINT32(X[12], data, 48);
57 GET_UINT32(X[13], data, 52);
58 GET_UINT32(X[14], data, 56);
59 GET_UINT32(X[15], data, 60);
60
61 #define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
62
63 #define P(a, b, c, d, k, s, t) \
64 { \
65 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
66 }
67
68 A = ctx->state[0];
69 B = ctx->state[1];
70 C = ctx->state[2];
71 D = ctx->state[3];
72
73 #define F(x, y, z) (z ^ (x & (y ^ z)))
74
75 P(A, B, C, D, 0, 7, 0xD76AA478);
76 P(D, A, B, C, 1, 12, 0xE8C7B756);
77 P(C, D, A, B, 2, 17, 0x242070DB);
78 P(B, C, D, A, 3, 22, 0xC1BDCEEE);
79 P(A, B, C, D, 4, 7, 0xF57C0FAF);
80 P(D, A, B, C, 5, 12, 0x4787C62A);
81 P(C, D, A, B, 6, 17, 0xA8304613);
82 P(B, C, D, A, 7, 22, 0xFD469501);
83 P(A, B, C, D, 8, 7, 0x698098D8);
84 P(D, A, B, C, 9, 12, 0x8B44F7AF);
85 P(C, D, A, B, 10, 17, 0xFFFF5BB1);
86 P(B, C, D, A, 11, 22, 0x895CD7BE);
87 P(A, B, C, D, 12, 7, 0x6B901122);
88 P(D, A, B, C, 13, 12, 0xFD987193);
89 P(C, D, A, B, 14, 17, 0xA679438E);
90 P(B, C, D, A, 15, 22, 0x49B40821);
91
92 #undef F
93
94 #define F(x, y, z) (y ^ (z & (x ^ y)))
95
96 P(A, B, C, D, 1, 5, 0xF61E2562);
97 P(D, A, B, C, 6, 9, 0xC040B340);
98 P(C, D, A, B, 11, 14, 0x265E5A51);
99 P(B, C, D, A, 0, 20, 0xE9B6C7AA);
100 P(A, B, C, D, 5, 5, 0xD62F105D);
101 P(D, A, B, C, 10, 9, 0x02441453);
102 P(C, D, A, B, 15, 14, 0xD8A1E681);
103 P(B, C, D, A, 4, 20, 0xE7D3FBC8);
104 P(A, B, C, D, 9, 5, 0x21E1CDE6);
105 P(D, A, B, C, 14, 9, 0xC33707D6);
106 P(C, D, A, B, 3, 14, 0xF4D50D87);
107 P(B, C, D, A, 8, 20, 0x455A14ED);
108 P(A, B, C, D, 13, 5, 0xA9E3E905);
109 P(D, A, B, C, 2, 9, 0xFCEFA3F8);
110 P(C, D, A, B, 7, 14, 0x676F02D9);
111 P(B, C, D, A, 12, 20, 0x8D2A4C8A);
112
113 #undef F
114
115 #define F(x, y, z) (x ^ y ^ z)
116
117 P(A, B, C, D, 5, 4, 0xFFFA3942);
118 P(D, A, B, C, 8, 11, 0x8771F681);
119 P(C, D, A, B, 11, 16, 0x6D9D6122);
120 P(B, C, D, A, 14, 23, 0xFDE5380C);
121 P(A, B, C, D, 1, 4, 0xA4BEEA44);
122 P(D, A, B, C, 4, 11, 0x4BDECFA9);
123 P(C, D, A, B, 7, 16, 0xF6BB4B60);
124 P(B, C, D, A, 10, 23, 0xBEBFBC70);
125 P(A, B, C, D, 13, 4, 0x289B7EC6);
126 P(D, A, B, C, 0, 11, 0xEAA127FA);
127 P(C, D, A, B, 3, 16, 0xD4EF3085);
128 P(B, C, D, A, 6, 23, 0x04881D05);
129 P(A, B, C, D, 9, 4, 0xD9D4D039);
130 P(D, A, B, C, 12, 11, 0xE6DB99E5);
131 P(C, D, A, B, 15, 16, 0x1FA27CF8);
132 P(B, C, D, A, 2, 23, 0xC4AC5665);
133
134 #undef F
135
136 #define F(x, y, z) (y ^ (x | ~z))
137
138 P(A, B, C, D, 0, 6, 0xF4292244);
139 P(D, A, B, C, 7, 10, 0x432AFF97);
140 P(C, D, A, B, 14, 15, 0xAB9423A7);
141 P(B, C, D, A, 5, 21, 0xFC93A039);
142 P(A, B, C, D, 12, 6, 0x655B59C3);
143 P(D, A, B, C, 3, 10, 0x8F0CCC92);
144 P(C, D, A, B, 10, 15, 0xFFEFF47D);
145 P(B, C, D, A, 1, 21, 0x85845DD1);
146 P(A, B, C, D, 8, 6, 0x6FA87E4F);
147 P(D, A, B, C, 15, 10, 0xFE2CE6E0);
148 P(C, D, A, B, 6, 15, 0xA3014314);
149 P(B, C, D, A, 13, 21, 0x4E0811A1);
150 P(A, B, C, D, 4, 6, 0xF7537E82);
151 P(D, A, B, C, 11, 10, 0xBD3AF235);
152 P(C, D, A, B, 2, 15, 0x2AD7D2BB);
153 P(B, C, D, A, 9, 21, 0xEB86D391);
154
155 #undef F
156
157 ctx->state[0] += A;
158 ctx->state[1] += B;
159 ctx->state[2] += C;
160 ctx->state[3] += D;
161 }
162
md5_update(md5_context * ctx,const uint8 * input,uint32 length)163 void md5_update(md5_context *ctx, const uint8 *input, uint32 length) {
164 uint32 left, fill;
165
166 if (!length)
167 return;
168
169 left = ctx->total[0] & 0x3F;
170 fill = 64 - left;
171
172 ctx->total[0] += length;
173 ctx->total[0] &= 0xFFFFFFFF;
174
175 if (ctx->total[0] < length)
176 ctx->total[1]++;
177
178 if (left && length >= fill) {
179 memcpy((void *)(ctx->buffer + left), (const void *)input, fill);
180 md5_process(ctx, ctx->buffer);
181 length -= fill;
182 input += fill;
183 left = 0;
184 }
185
186 while (length >= 64) {
187 md5_process(ctx, input);
188 length -= 64;
189 input += 64;
190 }
191
192 if (length) {
193 memcpy((void *)(ctx->buffer + left), (const void *)input, length);
194 }
195 }
196
197 static const uint8 md5_padding[64] = {
198 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
202 };
203
md5_finish(md5_context * ctx,uint8 digest[16])204 void md5_finish(md5_context *ctx, uint8 digest[16]) {
205 uint32 last, padn;
206 uint32 high, low;
207 uint8 msglen[8];
208
209 high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
210 low = (ctx->total[0] << 3);
211
212 PUT_UINT32(low, msglen, 0);
213 PUT_UINT32(high, msglen, 4);
214
215 last = ctx->total[0] & 0x3F;
216 padn = (last < 56) ? (56 - last) : (120 - last);
217
218 md5_update(ctx, md5_padding, padn);
219 md5_update(ctx, msglen, 8);
220
221 PUT_UINT32(ctx->state[0], digest, 0);
222 PUT_UINT32(ctx->state[1], digest, 4);
223 PUT_UINT32(ctx->state[2], digest, 8);
224 PUT_UINT32(ctx->state[3], digest, 12);
225 }
226
md5_file(const char * name,uint8 digest[16],uint32 length)227 bool md5_file(const char *name, uint8 digest[16], uint32 length) {
228 FILE *f;
229
230 f = fopen(name, "rb");
231 if (f == NULL) {
232 printf("md5_file couldn't open '%s'\n", name);
233 return false;
234 }
235
236 md5_context ctx;
237 uint32 i;
238 unsigned char buf[1000];
239 bool restricted = (length != 0);
240 int readlen;
241
242 if (!restricted || sizeof(buf) <= length)
243 readlen = sizeof(buf);
244 else
245 readlen = length;
246
247 md5_starts(&ctx);
248
249
250 while ((i = (uint32)fread(buf, 1, readlen, f)) > 0) {
251 md5_update(&ctx, buf, i);
252
253 length -= i;
254 if (restricted && length == 0)
255 break;
256
257 if (restricted && sizeof(buf) > length)
258 readlen = length;
259 }
260
261 md5_finish(&ctx, digest);
262 fclose(f);
263 return true;
264 }
265