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