F(x,y,z)1 /*
2  * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska H�gskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by the Kungliga Tekniska
20  *      H�gskolan and its contributors.
21  *
22  * 4. Neither the name of the Institute nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 
42 RCSID("$Id: md4.c,v 1.2 2001/12/04 02:06:29 rjs3 Exp $");
43 #endif
44 
45 #include <stdlib.h>
46 #include <string.h>
47 
48 #include "md4.h"
49 
50 #ifndef min
51 #define min(a,b) (((a)>(b))?(b):(a))
52 #endif
53 
54 #define A m->counter[0]
55 #define B m->counter[1]
56 #define C m->counter[2]
57 #define D m->counter[3]
58 #define X data
59 
60 void
61 md4_init (struct md4 *m)
62 {
63   m->offset = 0;
64   m->sz = 0;
65   D = 0x10325476;
66   C = 0x98badcfe;
67   B = 0xefcdab89;
68   A = 0x67452301;
69 }
70 
71 static inline u_int32_t
72 cshift (u_int32_t x, unsigned int n)
73 {
74   return (x << n) | (x >> (32 - n));
75 }
76 
77 #define F(x,y,z) ((x & y) | (~x & z))
78 #define G(x,y,z) ((x & y) | (x & z) | (y & z))
79 #define H(x,y,z) (x ^ y ^ z)
80 
81 #define DOIT(a,b,c,d,k,s,i,OP) \
82 a = cshift(a + OP(b,c,d) + X[k] + i, s)
83 
84 #define DO1(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,F)
85 #define DO2(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,G)
86 #define DO3(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,H)
87 
88 static inline void
89 calc (struct md4 *m, u_int32_t *data)
90 {
91   u_int32_t AA, BB, CC, DD;
92 
93   AA = A;
94   BB = B;
95   CC = C;
96   DD = D;
97 
98   /* Round 1 */
99 
100   DO1(A,B,C,D,0,3,0);
101   DO1(D,A,B,C,1,7,0);
102   DO1(C,D,A,B,2,11,0);
103   DO1(B,C,D,A,3,19,0);
104 
105   DO1(A,B,C,D,4,3,0);
106   DO1(D,A,B,C,5,7,0);
107   DO1(C,D,A,B,6,11,0);
108   DO1(B,C,D,A,7,19,0);
109 
110   DO1(A,B,C,D,8,3,0);
111   DO1(D,A,B,C,9,7,0);
112   DO1(C,D,A,B,10,11,0);
113   DO1(B,C,D,A,11,19,0);
114 
115   DO1(A,B,C,D,12,3,0);
116   DO1(D,A,B,C,13,7,0);
117   DO1(C,D,A,B,14,11,0);
118   DO1(B,C,D,A,15,19,0);
119 
120   /* Round 2 */
121 
122   DO2(A,B,C,D,0,3,0x5A827999);
123   DO2(D,A,B,C,4,5,0x5A827999);
124   DO2(C,D,A,B,8,9,0x5A827999);
125   DO2(B,C,D,A,12,13,0x5A827999);
126 
127   DO2(A,B,C,D,1,3,0x5A827999);
128   DO2(D,A,B,C,5,5,0x5A827999);
129   DO2(C,D,A,B,9,9,0x5A827999);
130   DO2(B,C,D,A,13,13,0x5A827999);
131 
132   DO2(A,B,C,D,2,3,0x5A827999);
133   DO2(D,A,B,C,6,5,0x5A827999);
134   DO2(C,D,A,B,10,9,0x5A827999);
135   DO2(B,C,D,A,14,13,0x5A827999);
136 
137   DO2(A,B,C,D,3,3,0x5A827999);
138   DO2(D,A,B,C,7,5,0x5A827999);
139   DO2(C,D,A,B,11,9,0x5A827999);
140   DO2(B,C,D,A,15,13,0x5A827999);
141 
142   /* Round 3 */
143 
144   DO3(A,B,C,D,0,3,0x6ED9EBA1);
145   DO3(D,A,B,C,8,9,0x6ED9EBA1);
146   DO3(C,D,A,B,4,11,0x6ED9EBA1);
147   DO3(B,C,D,A,12,15,0x6ED9EBA1);
148 
149   DO3(A,B,C,D,2,3,0x6ED9EBA1);
150   DO3(D,A,B,C,10,9,0x6ED9EBA1);
151   DO3(C,D,A,B,6,11,0x6ED9EBA1);
152   DO3(B,C,D,A,14,15,0x6ED9EBA1);
153 
154   DO3(A,B,C,D,1,3,0x6ED9EBA1);
155   DO3(D,A,B,C,9,9,0x6ED9EBA1);
156   DO3(C,D,A,B,5,11,0x6ED9EBA1);
157   DO3(B,C,D,A,13,15,0x6ED9EBA1);
158 
159   DO3(A,B,C,D,3,3,0x6ED9EBA1);
160   DO3(D,A,B,C,11,9,0x6ED9EBA1);
161   DO3(C,D,A,B,7,11,0x6ED9EBA1);
162   DO3(B,C,D,A,15,15,0x6ED9EBA1);
163 
164   A += AA;
165   B += BB;
166   C += CC;
167   D += DD;
168 }
169 
170 /*
171  * From `Performance analysis of MD5' by Joseph D. Touch <touch@isi.edu>
172  */
173 
174 static inline u_int32_t
175 swap_u_int32_t (u_int32_t t)
176 {
177 #if defined(WORDS_BIGENDIAN)
178 #define ROL(x,n) ((x)<<(n))|((x)>>(32-(n)))
179   u_int32_t temp1, temp2;
180 
181   temp1   = ROL(t,16);
182   temp2   = temp1 >> 8;
183   temp1  &= 0x00ff00ff;
184   temp2  &= 0x00ff00ff;
185   temp1 <<= 8;
186   return temp1 | temp2;
187 #else
188   return t;
189 #endif
190 }
191 
192 struct x32{
193   unsigned int a:32;
194   unsigned int b:32;
195 };
196 
197 void
198 md4_update (struct md4 *m, const void *v, size_t len)
199 {
200   const unsigned char *p = v;
201   m->sz += len;
202   while(len > 0){
203     size_t l = min(len, 64 - m->offset);
204     memcpy(m->save + m->offset, p, l);
205     m->offset += l;
206     p += l;
207     len -= l;
208     if(m->offset == 64){
209 #if defined(WORDS_BIGENDIAN)
210       int i;
211       u_int32_t current[16];
212       struct x32 *u = (struct x32*)m->save;
213       for(i = 0; i < 8; i++){
214 	current[2*i+0] = swap_u_int32_t(u[i].a);
215 	current[2*i+1] = swap_u_int32_t(u[i].b);
216       }
217       calc(m, current);
218 #else
219       calc(m, (u_int32_t*)m->save);
220 #endif
221       m->offset = 0;
222     }
223   }
224 }
225 
226 void
227 md4_finito (struct md4 *m, void *res)
228 {
229   static unsigned char zeros[72];
230   u_int32_t len;
231   unsigned int dstart = (120 - m->offset - 1) % 64 + 1;
232 
233   *zeros = 0x80;
234   memset (zeros + 1, 0, sizeof(zeros) - 1);
235   len = 8 * m->sz;
236   zeros[dstart+0] = (len >> 0) & 0xff;
237   zeros[dstart+1] = (len >> 8) & 0xff;
238   zeros[dstart+2] = (len >> 16) & 0xff;
239   zeros[dstart+3] = (len >> 24) & 0xff;
240   md4_update (m, zeros, dstart + 8);
241   {
242       int i;
243       unsigned char *r = (unsigned char *)res;
244 
245       for (i = 0; i < 4; ++i) {
246 	  r[4*i]   = m->counter[i] & 0xFF;
247 	  r[4*i+1] = (m->counter[i] >> 8) & 0xFF;
248 	  r[4*i+2] = (m->counter[i] >> 16) & 0xFF;
249 	  r[4*i+3] = (m->counter[i] >> 24) & 0xFF;
250       }
251   }
252 #if 0
253   {
254     int i;
255     u_int32_t *r = (u_int32_t *)res;
256 
257     for (i = 0; i < 4; ++i)
258       r[i] = swap_u_int32_t (m->counter[i]);
259   }
260 #endif
261 }
262