md4.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: md4.cc,v 1.4 1999/11/17 05:59:29 jgg Exp $
  4. /* ######################################################################
  5. MD4Sum - MD4 Message Digest Algorithm.
  6. This code implements the MD4 message-digest algorithm. See RFC 1186.
  7. Ripped shamelessly from RSync which ripped it shamelessly from Samba.
  8. Code is covered under the GPL >=2 and has been changed to have a C++
  9. interface and use the local configuration stuff.
  10. Copyright (C) Andrew Tridgell 1997-1998.
  11. This program is free software; you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation; either version 2 of the License, or
  14. (at your option) any later version.
  15. This program is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU General Public License for more details.
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. ##################################################################### */
  23. /*}}}*/
  24. // Include Files /*{{{*/
  25. #include <dsync/md4.h>
  26. #include <string.h>
  27. #include <inttypes.h>
  28. #include <config.h>
  29. /*}}}*/
  30. // byteSwap - Swap bytes in a buffer /*{{{*/
  31. // ---------------------------------------------------------------------
  32. /* Swap n 32 bit longs in given buffer */
  33. #ifdef WORDS_BIGENDIAN
  34. static void byteSwap(uint32_t *buf, unsigned words)
  35. {
  36. uint8_t *p = (uint8_t *)buf;
  37. do
  38. {
  39. *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
  40. ((unsigned)p[1] << 8 | p[0]);
  41. p += 4;
  42. } while (--words);
  43. }
  44. #else
  45. #define byteSwap(buf,words)
  46. #endif
  47. /*}}}*/
  48. // InitMD4 - Init the MD4 buffer /*{{{*/
  49. // ---------------------------------------------------------------------
  50. /* */
  51. void InitMD4(unsigned char MD4[16])
  52. {
  53. uint32_t X[4] = {0x67452301,0xefcdab89,0x98badcfe,0x10325476};
  54. byteSwap(X,4);
  55. memcpy(MD4,X,16);
  56. }
  57. /*}}}*/
  58. // ComputeMD4 - Compute the MD4 hash of a buffer /*{{{*/
  59. // ---------------------------------------------------------------------
  60. /* The buffer *must* be an even multiple of 64 bytes long. The resulting
  61. hash is placed in the output buffer in */
  62. #define F(X,Y,Z) (((X)&(Y)) | ((~(X))&(Z)))
  63. #define G(X,Y,Z) (((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)))
  64. #define H(X,Y,Z) ((X)^(Y)^(Z))
  65. #define lshift(x,s) (((x)<<(s)) | ((x)>>(32-(s))))
  66. #define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
  67. #define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + 0x5A827999,s)
  68. #define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + 0x6ED9EBA1,s)
  69. void ComputeMD4(unsigned char MD4[16],unsigned char const *Start,
  70. unsigned const char *End)
  71. {
  72. uint32_t X[16];
  73. uint32_t A,B,C,D;
  74. // Prepare the sum state
  75. memcpy(X,MD4,16);
  76. byteSwap(X,4);
  77. A = X[0];
  78. B = X[1];
  79. C = X[2];
  80. D = X[3];
  81. for (; End - Start >= 64; Start += 64)
  82. {
  83. uint32_t AA, BB, CC, DD;
  84. memcpy(X,Start,sizeof(X));
  85. byteSwap(X,16);
  86. AA = A; BB = B; CC = C; DD = D;
  87. ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
  88. ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
  89. ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
  90. ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
  91. ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
  92. ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
  93. ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
  94. ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
  95. ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
  96. ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
  97. ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
  98. ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
  99. ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
  100. ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
  101. ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
  102. ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
  103. ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
  104. ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
  105. ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
  106. ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
  107. ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
  108. ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
  109. ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
  110. ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
  111. A += AA;
  112. B += BB;
  113. C += CC;
  114. D += DD;
  115. }
  116. X[0] = A;
  117. X[1] = B;
  118. X[2] = C;
  119. X[3] = D;
  120. byteSwap(X,4);
  121. memcpy(MD4,X,16);
  122. }
  123. /*}}}*/
  124. // ComputeMD4Final - Finalize the MD4, length and pad /*{{{*/
  125. // ---------------------------------------------------------------------
  126. /* This does the final round of MD4, Start->End will be padded to be
  127. congruent to 0 mod 64 and TotalLen appended. */
  128. void ComputeMD4Final(unsigned char MD4[16],unsigned char const *Start,
  129. unsigned char const *End,unsigned long TotalLen)
  130. {
  131. if (End - Start >= 64)
  132. {
  133. ComputeMD4(MD4,Start,End - ((End - Start)%64));
  134. Start = End - ((End - Start)%64);
  135. }
  136. uint8_t Buf[128];
  137. uint32_t Len = TotalLen*8;
  138. // Create the partial end buffer, padded to be 448%512 bits long
  139. memset(Buf,0,128);
  140. if (Start != End)
  141. memcpy(Buf,Start,End - Start);
  142. Buf[End-Start] = 0x80;
  143. // Append the 32 bit length into the 64 bit field
  144. if (End-Start <= 55)
  145. {
  146. memcpy(Buf+56,&Len,sizeof(Len));
  147. byteSwap((uint32_t *)(Buf+56),1);
  148. ComputeMD4(MD4,Buf,Buf+64);
  149. }
  150. else
  151. {
  152. memcpy(Buf+120,&Len,sizeof(Len));
  153. byteSwap((uint32_t *)(Buf+120),1);
  154. ComputeMD4(MD4,Buf,Buf+128);
  155. }
  156. }
  157. /*}}}*/