22 #include "runtime.hpp"
27 #include "algorithm.hpp"
31 namespace STL = STL_NAMESPACE;
39 digest_[0] = 0x67452301L;
40 digest_[1] = 0xefcdab89L;
41 digest_[2] = 0x98badcfeL;
42 digest_[3] = 0x10325476L;
50 MD5::MD5(
const MD5& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
53 buffLen_ = that.buffLen_;
57 memcpy(digest_, that.digest_, DIGEST_SIZE);
58 memcpy(buffer_, that.buffer_, BLOCK_SIZE);
61 MD5& MD5::operator= (
const MD5& that)
70 void MD5::Swap(MD5& other)
72 STL::swap(loLen_, other.loLen_);
73 STL::swap(hiLen_, other.hiLen_);
74 STL::swap(buffLen_, other.buffLen_);
76 memcpy(digest_, other.digest_, DIGEST_SIZE);
77 memcpy(buffer_, other.buffer_, BLOCK_SIZE);
84 void MD5::Update(
const byte* data, word32 len)
87 HASHwithTransform::Update(data, len);
91 byte* local =
reinterpret_cast<byte*
>(buffer_);
95 word32 add = min(len, BLOCK_SIZE - buffLen_);
96 memcpy(&local[buffLen_], data, add);
102 if (buffLen_ == BLOCK_SIZE) {
104 AddLength(BLOCK_SIZE);
111 word32 times = len / BLOCK_SIZE;
113 AsmTransform(data, times);
114 const word32 add = BLOCK_SIZE * times;
123 memcpy(&local[buffLen_], data, len);
178 #define MD5STEP1(w, x, y, z, index, data, s) \
181 AS2( lea w, [ebp + w + data] ) \
186 AS2( mov ebp, [edi + index * 4] ) \
189 #define MD5STEP2(w, x, y, z, index, data, s) \
192 AS2( lea w, [ebp + w + data] ) \
197 AS2( mov ebp, [edi + index * 4] ) \
201 #define MD5STEP3(w, x, y, z, index, data, s) \
203 AS2( lea w, [ebp + w + data] ) \
208 AS2( mov ebp, [edi + index * 4] ) \
212 #define MD5STEP4(w, x, y, z, index, data, s) \
214 AS2( lea w, [ebp + w + data] ) \
220 AS2( mov ebp, [edi + index * 4] ) \
228 void MD5::AsmTransform(
const byte* data, word32 times)
231 #define AS1(x) asm(#x);
232 #define AS2(x, y) asm(#x ", " #y);
235 asm(".intel_syntax noprefix"); \
236 AS2( movd mm3, edi ) \
237 AS2( movd mm4, ebx ) \
238 AS2( movd mm5, esi ) \
239 AS2( movd mm6, ebp ) \
240 AS2( mov ecx, DWORD PTR [ebp + 8] ) \
241 AS2( mov edi, DWORD PTR [ebp + 12] ) \
242 AS2( mov eax, DWORD PTR [ebp + 16] )
245 AS2( movd ebp, mm6 ) \
246 AS2( movd esi, mm5 ) \
247 AS2( movd ebx, mm4 ) \
248 AS2( mov esp, ebp ) \
249 AS2( movd edi, mm3 ) \
253 #define AS1(x) __asm x
254 #define AS2(x, y) __asm x, y
258 AS2( mov ebp, esp ) \
259 AS2( movd mm3, edi ) \
260 AS2( movd mm4, ebx ) \
261 AS2( movd mm5, esi ) \
262 AS2( movd mm6, ebp ) \
263 AS2( mov edi, DWORD PTR [ebp + 8] ) \
264 AS2( mov eax, DWORD PTR [ebp + 12] )
267 AS2( movd ebp, mm6 ) \
268 AS2( movd esi, mm5 ) \
269 AS2( movd ebx, mm4 ) \
270 AS2( movd edi, mm3 ) \
271 AS2( mov esp, ebp ) \
283 #ifdef OLD_GCC_OFFSET
292 AS2( mov eax, [esi] )
293 AS2( mov ebx, [esi + 4] )
294 AS2( mov ecx, [esi + 8] )
295 AS2( mov edx, [esi + 12] )
301 AS2( mov ebp, [edi] )
303 MD5STEP1( eax, ebx, ecx, edx, 1, 0xd76aa478, 7)
304 MD5STEP1( edx, eax, ebx, ecx, 2, 0xe8c7b756, 12)
305 MD5STEP1( ecx, edx, eax, ebx, 3, 0x242070db, 17)
306 MD5STEP1( ebx, ecx, edx, eax, 4, 0xc1bdceee, 22)
307 MD5STEP1( eax, ebx, ecx, edx, 5, 0xf57c0faf, 7)
308 MD5STEP1( edx, eax, ebx, ecx, 6, 0x4787c62a, 12)
309 MD5STEP1( ecx, edx, eax, ebx, 7, 0xa8304613, 17)
310 MD5STEP1( ebx, ecx, edx, eax, 8, 0xfd469501, 22)
311 MD5STEP1( eax, ebx, ecx, edx, 9, 0x698098d8, 7)
312 MD5STEP1( edx, eax, ebx, ecx, 10, 0x8b44f7af, 12)
313 MD5STEP1( ecx, edx, eax, ebx, 11, 0xffff5bb1, 17)
314 MD5STEP1( ebx, ecx, edx, eax, 12, 0x895cd7be, 22)
315 MD5STEP1( eax, ebx, ecx, edx, 13, 0x6b901122, 7)
316 MD5STEP1( edx, eax, ebx, ecx, 14, 0xfd987193, 12)
317 MD5STEP1( ecx, edx, eax, ebx, 15, 0xa679438e, 17)
318 MD5STEP1( ebx, ecx, edx, eax, 1, 0x49b40821, 22)
320 MD5STEP2( eax, ebx, ecx, edx, 6, 0xf61e2562, 5)
321 MD5STEP2( edx, eax, ebx, ecx, 11, 0xc040b340, 9)
322 MD5STEP2( ecx, edx, eax, ebx, 0, 0x265e5a51, 14)
323 MD5STEP2( ebx, ecx, edx, eax, 5, 0xe9b6c7aa, 20)
324 MD5STEP2( eax, ebx, ecx, edx, 10, 0xd62f105d, 5)
325 MD5STEP2( edx, eax, ebx, ecx, 15, 0x02441453, 9)
326 MD5STEP2( ecx, edx, eax, ebx, 4, 0xd8a1e681, 14)
327 MD5STEP2( ebx, ecx, edx, eax, 9, 0xe7d3fbc8, 20)
328 MD5STEP2( eax, ebx, ecx, edx, 14, 0x21e1cde6, 5)
329 MD5STEP2( edx, eax, ebx, ecx, 3, 0xc33707d6, 9)
330 MD5STEP2( ecx, edx, eax, ebx, 8, 0xf4d50d87, 14)
331 MD5STEP2( ebx, ecx, edx, eax, 13, 0x455a14ed, 20)
332 MD5STEP2( eax, ebx, ecx, edx, 2, 0xa9e3e905, 5)
333 MD5STEP2( edx, eax, ebx, ecx, 7, 0xfcefa3f8, 9)
334 MD5STEP2( ecx, edx, eax, ebx, 12, 0x676f02d9, 14)
335 MD5STEP2( ebx, ecx, edx, eax, 5, 0x8d2a4c8a, 20)
337 MD5STEP3( eax, ebx, ecx, edx, 8, 0xfffa3942, 4)
338 MD5STEP3( edx, eax, ebx, ecx, 11, 0x8771f681, 11)
339 MD5STEP3( ecx, edx, eax, ebx, 14, 0x6d9d6122, 16)
340 MD5STEP3( ebx, ecx, edx, eax, 1, 0xfde5380c, 23)
341 MD5STEP3( eax, ebx, ecx, edx, 4, 0xa4beea44, 4)
342 MD5STEP3( edx, eax, ebx, ecx, 7, 0x4bdecfa9, 11)
343 MD5STEP3( ecx, edx, eax, ebx, 10, 0xf6bb4b60, 16)
344 MD5STEP3( ebx, ecx, edx, eax, 13, 0xbebfbc70, 23)
345 MD5STEP3( eax, ebx, ecx, edx, 0, 0x289b7ec6, 4)
346 MD5STEP3( edx, eax, ebx, ecx, 3, 0xeaa127fa, 11)
347 MD5STEP3( ecx, edx, eax, ebx, 6, 0xd4ef3085, 16)
348 MD5STEP3( ebx, ecx, edx, eax, 9, 0x04881d05, 23)
349 MD5STEP3( eax, ebx, ecx, edx, 12, 0xd9d4d039, 4)
350 MD5STEP3( edx, eax, ebx, ecx, 15, 0xe6db99e5, 11)
351 MD5STEP3( ecx, edx, eax, ebx, 2, 0x1fa27cf8, 16)
352 MD5STEP3( ebx, ecx, edx, eax, 0, 0xc4ac5665, 23)
358 MD5STEP4( eax, ebx, ecx, edx, 7, 0xf4292244, 6)
359 MD5STEP4( edx, eax, ebx, ecx, 14, 0x432aff97, 10)
360 MD5STEP4( ecx, edx, eax, ebx, 5, 0xab9423a7, 15)
361 MD5STEP4( ebx, ecx, edx, eax, 12, 0xfc93a039, 21)
362 MD5STEP4( eax, ebx, ecx, edx, 3, 0x655b59c3, 6)
363 MD5STEP4( edx, eax, ebx, ecx, 10, 0x8f0ccc92, 10)
364 MD5STEP4( ecx, edx, eax, ebx, 1, 0xffeff47d, 15)
365 MD5STEP4( ebx, ecx, edx, eax, 8, 0x85845dd1, 21)
366 MD5STEP4( eax, ebx, ecx, edx, 15, 0x6fa87e4f, 6)
367 MD5STEP4( edx, eax, ebx, ecx, 6, 0xfe2ce6e0, 10)
368 MD5STEP4( ecx, edx, eax, ebx, 13, 0xa3014314, 15)
369 MD5STEP4( ebx, ecx, edx, eax, 4, 0x4e0811a1, 21)
370 MD5STEP4( eax, ebx, ecx, edx, 11, 0xf7537e82, 6)
371 MD5STEP4( edx, eax, ebx, ecx, 2, 0xbd3af235, 10)
372 MD5STEP4( ecx, edx, eax, ebx, 9, 0x2ad7d2bb, 15)
373 MD5STEP4( ebx, ecx, edx, eax, 9, 0xeb86d391, 21)
377 AS2( add [esi], eax )
378 AS2( add [esi + 4], ebx )
379 AS2( add [esi + 8], ecx )
380 AS2( add [esi + 12], edx )
384 AS2( mov eax, [esi] )
385 AS2( mov ebx, [esi + 4] )
386 AS2( mov ecx, [esi + 8] )
387 AS2( mov edx, [esi + 12] )
402 void MD5::Transform()
404 #define F1(x, y, z) (z ^ (x & (y ^ z)))
405 #define F2(x, y, z) F1(z, x, y)
406 #define F3(x, y, z) (x ^ y ^ z)
407 #define F4(x, y, z) (y ^ (x | ~z))
409 #define MD5STEP(f, w, x, y, z, data, s) \
410 w = rotlFixed(w + f(x, y, z) + data, s) + x
413 word32 a = digest_[0];
414 word32 b = digest_[1];
415 word32 c = digest_[2];
416 word32 d = digest_[3];
418 MD5STEP(F1, a, b, c, d, buffer_[0] + 0xd76aa478, 7);
419 MD5STEP(F1, d, a, b, c, buffer_[1] + 0xe8c7b756, 12);
420 MD5STEP(F1, c, d, a, b, buffer_[2] + 0x242070db, 17);
421 MD5STEP(F1, b, c, d, a, buffer_[3] + 0xc1bdceee, 22);
422 MD5STEP(F1, a, b, c, d, buffer_[4] + 0xf57c0faf, 7);
423 MD5STEP(F1, d, a, b, c, buffer_[5] + 0x4787c62a, 12);
424 MD5STEP(F1, c, d, a, b, buffer_[6] + 0xa8304613, 17);
425 MD5STEP(F1, b, c, d, a, buffer_[7] + 0xfd469501, 22);
426 MD5STEP(F1, a, b, c, d, buffer_[8] + 0x698098d8, 7);
427 MD5STEP(F1, d, a, b, c, buffer_[9] + 0x8b44f7af, 12);
428 MD5STEP(F1, c, d, a, b, buffer_[10] + 0xffff5bb1, 17);
429 MD5STEP(F1, b, c, d, a, buffer_[11] + 0x895cd7be, 22);
430 MD5STEP(F1, a, b, c, d, buffer_[12] + 0x6b901122, 7);
431 MD5STEP(F1, d, a, b, c, buffer_[13] + 0xfd987193, 12);
432 MD5STEP(F1, c, d, a, b, buffer_[14] + 0xa679438e, 17);
433 MD5STEP(F1, b, c, d, a, buffer_[15] + 0x49b40821, 22);
435 MD5STEP(F2, a, b, c, d, buffer_[1] + 0xf61e2562, 5);
436 MD5STEP(F2, d, a, b, c, buffer_[6] + 0xc040b340, 9);
437 MD5STEP(F2, c, d, a, b, buffer_[11] + 0x265e5a51, 14);
438 MD5STEP(F2, b, c, d, a, buffer_[0] + 0xe9b6c7aa, 20);
439 MD5STEP(F2, a, b, c, d, buffer_[5] + 0xd62f105d, 5);
440 MD5STEP(F2, d, a, b, c, buffer_[10] + 0x02441453, 9);
441 MD5STEP(F2, c, d, a, b, buffer_[15] + 0xd8a1e681, 14);
442 MD5STEP(F2, b, c, d, a, buffer_[4] + 0xe7d3fbc8, 20);
443 MD5STEP(F2, a, b, c, d, buffer_[9] + 0x21e1cde6, 5);
444 MD5STEP(F2, d, a, b, c, buffer_[14] + 0xc33707d6, 9);
445 MD5STEP(F2, c, d, a, b, buffer_[3] + 0xf4d50d87, 14);
446 MD5STEP(F2, b, c, d, a, buffer_[8] + 0x455a14ed, 20);
447 MD5STEP(F2, a, b, c, d, buffer_[13] + 0xa9e3e905, 5);
448 MD5STEP(F2, d, a, b, c, buffer_[2] + 0xfcefa3f8, 9);
449 MD5STEP(F2, c, d, a, b, buffer_[7] + 0x676f02d9, 14);
450 MD5STEP(F2, b, c, d, a, buffer_[12] + 0x8d2a4c8a, 20);
452 MD5STEP(F3, a, b, c, d, buffer_[5] + 0xfffa3942, 4);
453 MD5STEP(F3, d, a, b, c, buffer_[8] + 0x8771f681, 11);
454 MD5STEP(F3, c, d, a, b, buffer_[11] + 0x6d9d6122, 16);
455 MD5STEP(F3, b, c, d, a, buffer_[14] + 0xfde5380c, 23);
456 MD5STEP(F3, a, b, c, d, buffer_[1] + 0xa4beea44, 4);
457 MD5STEP(F3, d, a, b, c, buffer_[4] + 0x4bdecfa9, 11);
458 MD5STEP(F3, c, d, a, b, buffer_[7] + 0xf6bb4b60, 16);
459 MD5STEP(F3, b, c, d, a, buffer_[10] + 0xbebfbc70, 23);
460 MD5STEP(F3, a, b, c, d, buffer_[13] + 0x289b7ec6, 4);
461 MD5STEP(F3, d, a, b, c, buffer_[0] + 0xeaa127fa, 11);
462 MD5STEP(F3, c, d, a, b, buffer_[3] + 0xd4ef3085, 16);
463 MD5STEP(F3, b, c, d, a, buffer_[6] + 0x04881d05, 23);
464 MD5STEP(F3, a, b, c, d, buffer_[9] + 0xd9d4d039, 4);
465 MD5STEP(F3, d, a, b, c, buffer_[12] + 0xe6db99e5, 11);
466 MD5STEP(F3, c, d, a, b, buffer_[15] + 0x1fa27cf8, 16);
467 MD5STEP(F3, b, c, d, a, buffer_[2] + 0xc4ac5665, 23);
469 MD5STEP(F4, a, b, c, d, buffer_[0] + 0xf4292244, 6);
470 MD5STEP(F4, d, a, b, c, buffer_[7] + 0x432aff97, 10);
471 MD5STEP(F4, c, d, a, b, buffer_[14] + 0xab9423a7, 15);
472 MD5STEP(F4, b, c, d, a, buffer_[5] + 0xfc93a039, 21);
473 MD5STEP(F4, a, b, c, d, buffer_[12] + 0x655b59c3, 6);
474 MD5STEP(F4, d, a, b, c, buffer_[3] + 0x8f0ccc92, 10);
475 MD5STEP(F4, c, d, a, b, buffer_[10] + 0xffeff47d, 15);
476 MD5STEP(F4, b, c, d, a, buffer_[1] + 0x85845dd1, 21);
477 MD5STEP(F4, a, b, c, d, buffer_[8] + 0x6fa87e4f, 6);
478 MD5STEP(F4, d, a, b, c, buffer_[15] + 0xfe2ce6e0, 10);
479 MD5STEP(F4, c, d, a, b, buffer_[6] + 0xa3014314, 15);
480 MD5STEP(F4, b, c, d, a, buffer_[13] + 0x4e0811a1, 21);
481 MD5STEP(F4, a, b, c, d, buffer_[4] + 0xf7537e82, 6);
482 MD5STEP(F4, d, a, b, c, buffer_[11] + 0xbd3af235, 10);
483 MD5STEP(F4, c, d, a, b, buffer_[2] + 0x2ad7d2bb, 15);
484 MD5STEP(F4, b, c, d, a, buffer_[9] + 0xeb86d391, 21);