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