1 /*
2  *
3  */
4 
5 #include "beecrypt/md4.h"
6 #include "beecrypt/endianness.h"
7 
8 /*@unchecked@*/ /*@observer@*/
9 static uint32_t md4hinit[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };
10 
11 /*@-sizeoftype@*/
12 /*@unchecked@*/ /*@observer@*/
13 const hashFunction md4 = {
14 	.name = "MD4",
15 	.paramsize = sizeof(md4Param),
16 	.blocksize = 64,
17 	.digestsize = 16,
18 	.reset = (hashFunctionReset) md4Reset,
19 	.update = (hashFunctionUpdate) md4Update,
20 	.digest = (hashFunctionDigest) md4Digest,
21 };
22 /*@=sizeoftype@*/
23 
md4Reset(md4Param * mp)24 int md4Reset(md4Param* mp)
25 {
26 /*@-sizeoftype@*/
27 	memcpy(mp->h, md4hinit, 4 * sizeof(uint32_t));
28 	memset(mp->data, 0, 16 * sizeof(uint32_t));
29 /*@=sizeoftype@*/
30 	#if (MP_WBITS == 64)
31 	mpzero(1, mp->length);
32 	#elif (MP_WBITS == 32)
33 	mpzero(2, mp->length);
34 	#else
35 	# error
36 	#endif
37 	mp->offset  = 0;
38 	return 0;
39 }
40 
41 #define F(x, y, z) (z ^ (x & (y ^ z)))
42 #define G(x, y, z) ((x & y) | (z & (x | y)))
43 #define H(x, y, z) ((x) ^ (y) ^ (z))
44 
45 #define FF(a, b, c, d, w, s) \
46     a = ROTL32((d^(b&(c^d))) + a + w, s);
47 
48 #define GG(a, b, c, d, w, s) \
49     a = ROTL32(((b&c)|(d&(b|c))) + a + w + 0x5a827999U, s);
50 
51 #define HH(a, b, c, d, w, s) \
52     a = ROTL32((b^c^d) + a + w + 0x6ed9eba1U, s);
53 
54 #ifndef ASM_MD4PROCESS
md4Process(md4Param * mp)55 void md4Process(md4Param *mp)
56 	/*@modifies mp @*/
57 {
58 	uint32_t a, b, c, d;
59 
60 	register uint32_t* w;
61 	#ifdef WORDS_BIGENDIAN
62 	register byte t;
63 	#endif
64 
65 	w = mp->data;
66 	#ifdef WORDS_BIGENDIAN
67 	t = 16;
68 	while (t--)
69 	{
70 		register uint32_t temp = swapu32(*w);
71 		*(w++) = temp;
72 	}
73 	w = mp->data;
74 	#endif
75 
76 	a = mp->h[0]; b = mp->h[1]; c = mp->h[2]; d = mp->h[3];
77 
78 	FF (a, b, c, d, w[ 0],  3);
79 	FF (d, a, b, c, w[ 1],  7);
80 	FF (c, d, a, b, w[ 2], 11);
81 	FF (b, c, d, a, w[ 3], 19);
82 	FF (a, b, c, d, w[ 4],  3);
83 	FF (d, a, b, c, w[ 5],  7);
84 	FF (c, d, a, b, w[ 6], 11);
85 	FF (b, c, d, a, w[ 7], 19);
86 	FF (a, b, c, d, w[ 8],  3);
87 	FF (d, a, b, c, w[ 9],  7);
88 	FF (c, d, a, b, w[10], 11);
89 	FF (b, c, d, a, w[11], 19);
90 	FF (a, b, c, d, w[12],  3);
91 	FF (d, a, b, c, w[13],  7);
92 	FF (c, d, a, b, w[14], 11);
93 	FF (b, c, d, a, w[15], 19);
94 
95 	GG (a, b, c, d, w[ 0],  3);
96 	GG (d, a, b, c, w[ 4],  5);
97 	GG (c, d, a, b, w[ 8],  9);
98 	GG (b, c, d, a, w[12], 13);
99 	GG (a, b, c, d, w[ 1],  3);
100 	GG (d, a, b, c, w[ 5],  5);
101 	GG (c, d, a, b, w[ 9],  9);
102 	GG (b, c, d, a, w[13], 13);
103 	GG (a, b, c, d, w[ 2],  3);
104 	GG (d, a, b, c, w[ 6],  5);
105 	GG (c, d, a, b, w[10],  9);
106 	GG (b, c, d, a, w[14], 13);
107 	GG (a, b, c, d, w[ 3],  3);
108 	GG (d, a, b, c, w[ 7],  5);
109 	GG (c, d, a, b, w[11],  9);
110 	GG (b, c, d, a, w[15], 13);
111 
112 	HH (a, b, c, d, w[ 0],  3);
113 	HH (d, a, b, c, w[ 8],  9);
114 	HH (c, d, a, b, w[ 4], 11);
115 	HH (b, c, d, a, w[12], 15);
116 	HH (a, b, c, d, w[ 2],  3);
117 	HH (d, a, b, c, w[10],  9);
118 	HH (c, d, a, b, w[ 6], 11);
119 	HH (b, c, d, a, w[14], 15);
120 	HH (a, b, c, d, w[ 1],  3);
121 	HH (d, a, b, c, w[ 9],  9);
122 	HH (c, d, a, b, w[ 5], 11);
123 	HH (b, c, d, a, w[13], 15);
124 	HH (a, b, c, d, w[ 3],  3);
125 	HH (d, a, b, c, w[11],  9);
126 	HH (c, d, a, b, w[ 7], 11);
127 	HH (b, c, d, a, w[15], 15);
128 
129 	mp->h[0] +=  a;
130 	mp->h[1] +=  b;
131 	mp->h[2] +=  c;
132 	mp->h[3] +=  d;
133 }
134 #endif
135 
md4Update(md4Param * mp,const byte * data,size_t size)136 int md4Update(md4Param* mp, const byte* data, size_t size)
137 {
138 	register uint32_t proclength;
139 
140 	#if (MP_WBITS == 64)
141 	mpw add[1];
142 	mpsetw(1, add, size);
143 	mplshift(1, add, 3);
144 	(void) mpadd(1, mp->length, add);
145 	#elif (MP_WBITS == 32)
146 	mpw add[2];
147 	mpsetw(2, add, size);
148 	mplshift(2, add, 3);
149 	(void) mpadd(2, mp->length, add);
150 	#else
151 	# error
152 	#endif
153 
154 	while (size > 0)
155 	{
156 		proclength = ((mp->offset + size) > 64U) ? (64U - mp->offset) : size;
157 /*@-mayaliasunique@*/
158 		memcpy(((byte *) mp->data) + mp->offset, data, proclength);
159 /*@=mayaliasunique@*/
160 		size -= proclength;
161 		data += proclength;
162 		mp->offset += proclength;
163 
164 		if (mp->offset == 64U)
165 		{
166 			md4Process(mp);
167 			mp->offset = 0;
168 		}
169 	}
170 	return 0;
171 }
172 
md4Finish(md4Param * mp)173 static void md4Finish(md4Param* mp)
174 	/*@modifies mp @*/
175 {
176 	register byte *ptr = ((byte *) mp->data) + mp->offset++;
177 
178 	*(ptr++) = 0x80;
179 
180 	if (mp->offset > 56)
181 	{
182 		while (mp->offset++ < 64)
183 			*(ptr++) = 0;
184 
185 		md4Process(mp);
186 		mp->offset = 0;
187 	}
188 
189 	ptr = ((byte *) mp->data) + mp->offset;
190 	while (mp->offset++ < 56)
191 		*(ptr++) = 0;
192 
193 	#if (MP_WBITS == 64)
194 	ptr[0] = (byte)(mp->length[0]      );
195 	ptr[1] = (byte)(mp->length[0] >>  8);
196 	ptr[2] = (byte)(mp->length[0] >> 16);
197 	ptr[3] = (byte)(mp->length[0] >> 24);
198 	ptr[4] = (byte)(mp->length[0] >> 32);
199 	ptr[5] = (byte)(mp->length[0] >> 40);
200 	ptr[6] = (byte)(mp->length[0] >> 48);
201 	ptr[7] = (byte)(mp->length[0] >> 56);
202 	#elif (MP_WBITS == 32)
203 	ptr[0] = (byte)(mp->length[1]      );
204 	ptr[1] = (byte)(mp->length[1] >>  8);
205 	ptr[2] = (byte)(mp->length[1] >> 16);
206 	ptr[3] = (byte)(mp->length[1] >> 24);
207 	ptr[4] = (byte)(mp->length[0]      );
208 	ptr[5] = (byte)(mp->length[0] >>  8);
209 	ptr[6] = (byte)(mp->length[0] >> 16);
210 	ptr[7] = (byte)(mp->length[0] >> 24);
211 	#else
212 	# error
213 	#endif
214 
215 	md4Process(mp);
216 
217 	mp->offset = 0;
218 }
219 
220 /*@-protoparammatch@*/
md4Digest(md4Param * mp,byte * data)221 int md4Digest(md4Param* mp, byte* data)
222 {
223 	md4Finish(mp);
224 
225 	/* encode 4 integers little-endian style */
226 	data[ 0] = (byte)(mp->h[0]      );
227 	data[ 1] = (byte)(mp->h[0] >>  8);
228 	data[ 2] = (byte)(mp->h[0] >> 16);
229 	data[ 3] = (byte)(mp->h[0] >> 24);
230 	data[ 4] = (byte)(mp->h[1]      );
231 	data[ 5] = (byte)(mp->h[1] >>  8);
232 	data[ 6] = (byte)(mp->h[1] >> 16);
233 	data[ 7] = (byte)(mp->h[1] >> 24);
234 	data[ 8] = (byte)(mp->h[2]      );
235 	data[ 9] = (byte)(mp->h[2] >>  8);
236 	data[10] = (byte)(mp->h[2] >> 16);
237 	data[11] = (byte)(mp->h[2] >> 24);
238 	data[12] = (byte)(mp->h[3]      );
239 	data[13] = (byte)(mp->h[3] >>  8);
240 	data[14] = (byte)(mp->h[3] >> 16);
241 	data[15] = (byte)(mp->h[3] >> 24);
242 
243 	(void) md4Reset(mp);
244 	return 0;
245 }
246 /*@=protoparammatch@*/
247