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