]> git.decadent.org.uk Git - dak.git/blob - tools/dsync-0.0/libdsync/contrib/md4.cc
Merged from ftpmaster
[dak.git] / tools / dsync-0.0 / libdsync / contrib / md4.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: md4.cc,v 1.4 1999/11/17 05:59:29 jgg Exp $
4 /* ######################################################################
5    
6    MD4Sum - MD4 Message Digest Algorithm.
7
8    This code implements the MD4 message-digest algorithm. See RFC 1186.
9
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.
13
14    Copyright (C) Andrew Tridgell 1997-1998.
15    
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.
20    
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.
25    
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.
29    
30    ##################################################################### */
31                                                                         /*}}}*/
32 // Include Files                                                        /*{{{*/
33 #include <dsync/md4.h>
34
35 #include <string.h>
36 #include <inttypes.h>
37 #include <config.h>
38                                                                         /*}}}*/
39
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)
45 {
46    uint8_t *p = (uint8_t *)buf;
47    
48    do 
49    {
50       *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
51          ((unsigned)p[1] << 8 | p[0]);
52       p += 4;
53    } while (--words);
54 }
55 #else
56 #define byteSwap(buf,words)
57 #endif
58                                                                         /*}}}*/
59 // InitMD4 - Init the MD4 buffer                                        /*{{{*/
60 // ---------------------------------------------------------------------
61 /* */
62 void InitMD4(unsigned char MD4[16])
63 {
64    uint32_t X[4] = {0x67452301,0xefcdab89,0x98badcfe,0x10325476};
65    byteSwap(X,4);
66    memcpy(MD4,X,16);
67 }
68                                                                         /*}}}*/
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))))
77
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)
81
82 void ComputeMD4(unsigned char MD4[16],unsigned char const *Start,
83                 unsigned const char *End)
84 {
85    uint32_t X[16];
86    uint32_t A,B,C,D;
87
88    // Prepare the sum state
89    memcpy(X,MD4,16);
90    byteSwap(X,4);
91    A = X[0];
92    B = X[1];
93    C = X[2];
94    D = X[3];
95    
96    for (; End - Start >= 64; Start += 64)
97    {      
98       uint32_t AA, BB, CC, DD;
99       
100       memcpy(X,Start,sizeof(X));
101       byteSwap(X,16);
102          
103       AA = A; BB = B; CC = C; DD = D;
104       
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);        
113       
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);
122       
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);
131       
132       A += AA; 
133       B += BB; 
134       C += CC; 
135       D += DD;
136    }
137    X[0] = A;
138    X[1] = B;
139    X[2] = C;
140    X[3] = D;
141    
142    byteSwap(X,4);
143    memcpy(MD4,X,16);
144 }
145                                                                         /*}}}*/
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)
152 {
153    if (End - Start >= 64)
154    {
155       ComputeMD4(MD4,Start,End - ((End - Start)%64));
156       Start = End - ((End - Start)%64);
157    }
158    
159    uint8_t Buf[128];
160    uint32_t Len = TotalLen*8;
161    
162    // Create the partial end buffer, padded to be 448%512 bits long
163    memset(Buf,0,128);
164    if (Start != End) 
165       memcpy(Buf,Start,End - Start);   
166    Buf[End-Start] = 0x80;
167    
168    // Append the 32 bit length into the 64 bit field
169    if (End-Start <= 55) 
170    {      
171       memcpy(Buf+56,&Len,sizeof(Len));
172       byteSwap((uint32_t *)(Buf+56),1);
173       ComputeMD4(MD4,Buf,Buf+64);
174    }
175    else 
176    {
177       memcpy(Buf+120,&Len,sizeof(Len));
178       byteSwap((uint32_t *)(Buf+120),1);
179       ComputeMD4(MD4,Buf,Buf+128);
180    }   
181 }
182                                                                         /*}}}*/