1 #include "Core.h"
2 
3 namespace Upp {
4 
5 #define MD5_CTX UPP_MD5_CTX
6 
7 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
8 */
9 
10 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
11 rights reserved.
12 
13 License to copy and use this software is granted provided that it
14 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
15 Algorithm" in all material mentioning or referencing this software
16 or this function.
17 
18 License is also granted to make and use derivative works provided
19 that such works are identified as "derived from the RSA Data
20 Security, Inc. MD5 Message-Digest Algorithm" in all material
21 mentioning or referencing the derived work.
22 
23 RSA Data Security, Inc. makes no representations concerning either
24 the merchantability of this software or the suitability of this
25 software for any particular purpose. It is provided "as is"
26 without express or implied warranty of any kind.
27 
28 These notices must be retained in any copies of any part of this
29 documentation and/or software.
30 */
31 
32 /* Constants for MD5Transform routine.
33 */
34 
35 #define S11 7
36 #define S12 12
37 #define S13 17
38 #define S14 22
39 #define S21 5
40 #define S22 9
41 #define S23 14
42 #define S24 20
43 #define S31 4
44 #define S32 11
45 #define S33 16
46 #define S34 23
47 #define S41 6
48 #define S42 10
49 #define S43 15
50 #define S44 21
51 
52 static void MD5Transform (dword [4], const unsigned char [64]);
53 static void Encode (unsigned char *, const dword *, unsigned int);
54 static void Decode (dword *, const unsigned char *, unsigned int);
55 static void MD5_memcpy (void *, const void *, unsigned int);
56 static void MD5_memset (void *, int, unsigned int);
57 
58 static unsigned char PADDING[64] = {
59 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
62 };
63 
64 /* F, G, H and I are basic MD5 functions.
65 */
66 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
67 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
68 #define H(x, y, z) ((x) ^ (y) ^ (z))
69 #define I(x, y, z) ((y) ^ ((x) | (~z)))
70 
71 /* ROTATE_LEFT rotates x left n bits.
72 */
73 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
74 
75 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
76 Rotation is separate from addition to prevent recomputation.
77 */
78 #define FF(a, b, c, d, x, s, ac) { \
79 		(a) += F ((b), (c), (d)) + (x) + (dword)(ac); \
80 		(a) = ROTATE_LEFT ((a), (s)); \
81 		(a) += (b); \
82 	}
83 #define GG(a, b, c, d, x, s, ac) { \
84 		(a) += G ((b), (c), (d)) + (x) + (dword)(ac); \
85 		(a) = ROTATE_LEFT ((a), (s)); \
86 		(a) += (b); \
87 	}
88 #define HH(a, b, c, d, x, s, ac) { \
89 		(a) += H ((b), (c), (d)) + (x) + (dword)(ac); \
90 		(a) = ROTATE_LEFT ((a), (s)); \
91 		(a) += (b); \
92 	}
93 #define II(a, b, c, d, x, s, ac) { \
94 		(a) += I ((b), (c), (d)) + (x) + (dword)(ac); \
95 		(a) = ROTATE_LEFT ((a), (s)); \
96 		(a) += (b); \
97 	}
98 
99 /* MD5 initialization. Begins an MD5 operation, writing a new context.
100 */
MD5Init(MD5_CTX * context)101 void MD5Init (MD5_CTX *context)
102 {
103 	context->count[0] = context->count[1] = 0;
104 	/* Load magic initialization constants.
105 */
106 	context->state[0] = 0x67452301;
107 	context->state[1] = 0xefcdab89;
108 	context->state[2] = 0x98badcfe;
109 	context->state[3] = 0x10325476;
110 }
111 
112 /* MD5 block update operation. Continues an MD5 message-digest
113 	operation, processing another message block, and updating the
114 	context.
115 */
MD5Update(MD5_CTX * context,const unsigned char * input,dword inputLen)116 void MD5Update (MD5_CTX *context, const unsigned char *input, dword inputLen)
117 //MD5_CTX *context;                                        /* context */
118 //unsigned char *input;                                /* input block */
119 //unsigned int inputLen;                     /* length of input block */
120 {
121 	unsigned int i, index, partLen;
122 
123 	/* Compute number of bytes mod 64 */
124 	index = (unsigned int)((context->count[0] >> 3) & 0x3F);
125 
126 	/* Update number of bits */
127 	if ((context->count[0] += ((dword)inputLen << 3)) < ((dword)inputLen << 3))
128 		context->count[1]++;
129 	context->count[1] += ((dword)inputLen >> 29);
130 
131 	partLen = 64 - index;
132 
133 	/* Transform as many times as possible.
134 */
135 	if (inputLen >= partLen) {
136 		MD5_memcpy
137 			((void *)&context->buffer[index], (void *)input, partLen);
138 		MD5Transform (context->state, context->buffer);
139 
140 		for (i = partLen; i + 63 < inputLen; i += 64)
141 			MD5Transform (context->state, &input[i]);
142 
143 		index = 0;
144 	}
145 	else
146 		i = 0;
147 
148 	/* Buffer remaining input */
149 	MD5_memcpy((void *)&context->buffer[index], (void *)&input[i],
150 	inputLen-i);
151 }
152 
153 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
154 	the message digest and zeroizing the context.
155 */
MD5Final(unsigned char * digest,MD5_CTX * context)156 void MD5Final (unsigned char *digest, MD5_CTX *context)
157 {
158 	unsigned char bits[8];
159 	unsigned int index, padLen;
160 
161 	/* Save number of bits */
162 	Encode (bits, context->count, 8);
163 
164 	/* Pad out to 56 mod 64.
165 */
166 	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
167 	padLen = (index < 56) ? (56 - index) : (120 - index);
168 	MD5Update (context, PADDING, padLen);
169 
170 	/* Append length (before padding) */
171 	MD5Update (context, bits, 8);
172 
173 	/* Store state in digest */
174 	Encode (digest, context->state, 16);
175 
176 	/* Zeroize sensitive information.
177 */
178 	MD5_memset ((void *)context, 0, sizeof (*context));
179 }
180 
181 /* MD5 basic transformation. Transforms state based on block.
182 */
MD5Transform(dword state[4],const unsigned char block[64])183 static void MD5Transform (dword state[4], const unsigned char block[64])
184 {
185 	dword a = state[0], b = state[1], c = state[2], d = state[3], x[16];
186 
187 	Decode (x, block, 64);
188 
189 	/* Round 1 */
190 	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
191 	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
192 	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
193 	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
194 	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
195 	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
196 	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
197 	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
198 	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
199 	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
200 	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
201 	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
202 	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
203 	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
204 	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
205 	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
206 
207 /* Round 2 */
208 	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
209 	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
210 	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
211 	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
212 	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
213 	GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
214 	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
215 	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
216 	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
217 	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
218 	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
219 
220 	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
221 	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
222 	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
223 	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
224 	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
225 
226 	/* Round 3 */
227 	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
228 	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
229 	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
230 	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
231 	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
232 	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
233 	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
234 	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
235 	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
236 	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
237 	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
238 	HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
239 	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
240 	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
241 	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
242 	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
243 
244 	/* Round 4 */
245 	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
246 	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
247 	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
248 	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
249 	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
250 	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
251 	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
252 	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
253 	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
254 	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
255 	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
256 	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
257 	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
258 	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
259 	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
260 	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
261 
262 	state[0] += a;
263 	state[1] += b;
264 	state[2] += c;
265 	state[3] += d;
266 
267 	/* Zeroize sensitive information.
268 
269 */
270 	MD5_memset ((void *)x, 0, sizeof (x));
271 }
272 
273 /* Encodes input (dword) into output (unsigned char). Assumes len is
274 	a multiple of 4.
275 */
Encode(unsigned char * output,const dword * input,unsigned int len)276 static void Encode (unsigned char *output, const dword *input, unsigned int len)
277 {
278 	unsigned int i, j;
279 
280 	for (i = 0, j = 0; j < len; i++, j += 4) {
281 		output[j] = (unsigned char)(input[i] & 0xff);
282 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
283 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
284 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
285 	}
286 }
287 
288 /* Decodes input (unsigned char) into output (dword). Assumes len is
289 	a multiple of 4.
290 */
Decode(dword * output,const unsigned char * input,unsigned int len)291 static void Decode (dword *output, const unsigned char *input, unsigned int len)
292 {
293 	unsigned int i, j;
294 
295 	for (i = 0, j = 0; j < len; i++, j += 4)
296 		output[i] = ((dword)input[j]) | (((dword)input[j+1]) << 8) |
297 		(((dword)input[j+2]) << 16) | (((dword)input[j+3]) << 24);
298 }
299 
300 /* Note: Replace "for loop" with standard memcpy if possible.
301 */
302 
MD5_memcpy(void * output,const void * input,unsigned int len)303 static void MD5_memcpy (void * output, const void * input, unsigned int len)
304 {
305 	memcpy(output, input, len);
306 }
307 
308 /* Note: Replace "for loop" with standard memset if possible.
309 */
MD5_memset(void * output,int value,unsigned int len)310 static void MD5_memset (void * output, int value, unsigned int len)
311 {
312 	memset(output, value, len);
313 }
314 
315 // ------------------ U++ code starts here: ----------------------
316 
Out(const void * data,dword size)317 void Md5Stream::Out(const void *data, dword size)
318 {
319 	MD5Update (&context, (const unsigned char *)data, size);
320 }
321 
Finish(byte * hash16)322 void Md5Stream::Finish(byte *hash16)
323 {
324 	Flush();
325 	MD5Final(hash16, &context);
326 }
327 
FinishString()328 String Md5Stream::FinishString()
329 {
330 	byte hash[16];
331 	Finish(hash);
332 	return HexString(hash, 16);
333 }
334 
FinishStringS()335 String Md5Stream::FinishStringS()
336 {
337 	byte hash[16];
338 	Finish(hash);
339 	return HexString(hash, 16, 4);
340 }
341 
Reset()342 void Md5Stream::Reset()
343 {
344 	MD5Init (&context);
345 }
346 
Md5Stream()347 Md5Stream::Md5Stream()
348 {
349 	Reset();
350 }
351 
~Md5Stream()352 Md5Stream::~Md5Stream()
353 {
354 	memset(&context, 0, sizeof(context));
355 }
356 
MD5(byte * hash16,const void * data,dword size)357 void MD5(byte *hash16, const void *data, dword size)
358 {
359 	Md5Stream md5;
360 	md5.Put(data, size);
361 	md5.Finish(hash16);
362 }
363 
MD5String(const void * data,dword size)364 String MD5String(const void *data, dword size)
365 {
366 	Md5Stream md5;
367 	md5.Put(data, size);
368 	return md5.FinishString();
369 }
370 
MD5(byte * hash16,const String & data)371 void MD5(byte *hash16, const String& data)
372 {
373 	return MD5(hash16, ~data, data.GetCount());
374 }
375 
MD5String(const String & data)376 String MD5String(const String& data)
377 {
378 	return MD5String(~data, data.GetCount());
379 }
380 
MD5StringS(const void * data,dword size)381 String MD5StringS(const void *data, dword size)
382 {
383 	Md5Stream md5;
384 	md5.Put(data, size);
385 	return md5.FinishStringS();
386 }
387 
MD5StringS(const String & data)388 String MD5StringS(const String& data)
389 {
390 	return MD5StringS(~data, data.GetCount());
391 }
392 
393 }
394