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