1 /*
2  * Copyright (c) 2000, 2002 X-Way Rights BV
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  */
19 
20 /*!\file md5.c
21  * \brief MD5 hash function
22  * \author Bob Deblier <bob.deblier@telenet.be>
23  * \ingroup HASH_m HASH_md5_m
24  */
25 
26 #define BEECRYPT_DLL_EXPORT
27 
28 #if HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31 
32 #include "beecrypt/md5.h"
33 #include "beecrypt/endianness.h"
34 
35 /*!\addtogroup HASH_md5_m
36  * \{
37  */
38 
39 static uint32_t md5hinit[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };
40 
41 const hashFunction md5 = {
42 	.name = "MD5",
43 	.paramsize = sizeof(md5Param),
44 	.blocksize = 64,
45 	.digestsize = 16,
46 	.reset = (hashFunctionReset) md5Reset,
47 	.update = (hashFunctionUpdate) md5Update,
48 	.digest = (hashFunctionDigest) md5Digest
49 };
50 
md5Reset(register md5Param * mp)51 int md5Reset(register md5Param* mp)
52 {
53 	memcpy(mp->h, md5hinit, 4 * sizeof(uint32_t));
54 	memset(mp->data, 0, 16 * sizeof(uint32_t));
55 	#if (MP_WBITS == 64)
56 	mpzero(1, mp->length);
57 	#elif (MP_WBITS == 32)
58 	mpzero(2, mp->length);
59 	#else
60 	# error
61 	#endif
62 	mp->offset = 0;
63 	return 0;
64 }
65 
66 #define FF(a, b, c, d, w, s, t)	\
67 	a = ROTL32(((b&(c^d))^d) + a + w + t, s) + b;
68 
69 #define GG(a, b, c, d, w, s, t)	\
70 	a = ROTL32(((d&(b^c))^c) + a + w + t, s) + b;
71 
72 #define HH(a, b, c, d, w, s, t)	\
73 	a = ROTL32((b^c^d) + a + w + t, s) + b;
74 
75 #define II(a, b, c, d, w, s, t)	\
76 	a = ROTL32((c^(b|~d)) + a + w + t, s) + b;
77 
78 #ifndef ASM_MD5PROCESS
md5Process(md5Param * mp)79 void md5Process(md5Param* mp)
80 {
81 	register uint32_t a,b,c,d;
82 	register uint32_t* w;
83 	#if WORDS_BIGENDIAN
84 	register byte t;
85 	#endif
86 
87 	w = mp->data;
88 	#if WORDS_BIGENDIAN
89 	t = 16;
90 	while (t--)
91 	{
92 		register uint32_t temp = swapu32(*w);
93 		*(w++) = temp;
94 	}
95 	w = mp->data;
96 	#endif
97 
98 	a = mp->h[0]; b = mp->h[1]; c = mp->h[2]; d = mp->h[3];
99 
100 	FF(a, b, c, d, w[ 0],  7, 0xd76aa478);
101 	FF(d, a, b, c, w[ 1], 12, 0xe8c7b756);
102 	FF(c, d, a, b, w[ 2], 17, 0x242070db);
103 	FF(b, c, d, a, w[ 3], 22, 0xc1bdceee);
104 	FF(a, b, c, d, w[ 4],  7, 0xf57c0faf);
105 	FF(d, a, b, c, w[ 5], 12, 0x4787c62a);
106 	FF(c, d, a, b, w[ 6], 17, 0xa8304613);
107 	FF(b, c, d, a, w[ 7], 22, 0xfd469501);
108 	FF(a, b, c, d, w[ 8],  7, 0x698098d8);
109 	FF(d, a, b, c, w[ 9], 12, 0x8b44f7af);
110 	FF(c, d, a, b, w[10], 17, 0xffff5bb1);
111 	FF(b, c, d, a, w[11], 22, 0x895cd7be);
112 	FF(a, b, c, d, w[12],  7, 0x6b901122);
113 	FF(d, a, b, c, w[13], 12, 0xfd987193);
114 	FF(c, d, a, b, w[14], 17, 0xa679438e);
115 	FF(b, c, d, a, w[15], 22, 0x49b40821);
116 
117 	GG(a, b, c, d, w[ 1],  5, 0xf61e2562);
118 	GG(d, a, b, c, w[ 6],  9, 0xc040b340);
119 	GG(c, d, a, b, w[11], 14, 0x265e5a51);
120 	GG(b, c, d, a, w[ 0], 20, 0xe9b6c7aa);
121 	GG(a, b, c, d, w[ 5],  5, 0xd62f105d);
122 	GG(d, a, b, c, w[10],  9, 0x02441453);
123 	GG(c, d, a, b, w[15], 14, 0xd8a1e681);
124 	GG(b, c, d, a, w[ 4], 20, 0xe7d3fbc8);
125 	GG(a, b, c, d, w[ 9],  5, 0x21e1cde6);
126 	GG(d, a, b, c, w[14],  9, 0xc33707d6);
127 	GG(c, d, a, b, w[ 3], 14, 0xf4d50d87);
128 	GG(b, c, d, a, w[ 8], 20, 0x455a14ed);
129 	GG(a, b, c, d, w[13],  5, 0xa9e3e905);
130 	GG(d, a, b, c, w[ 2],  9, 0xfcefa3f8);
131 	GG(c, d, a, b, w[ 7], 14, 0x676f02d9);
132 	GG(b, c, d, a, w[12], 20, 0x8d2a4c8a);
133 
134 	HH(a, b, c, d, w[ 5],  4, 0xfffa3942);
135 	HH(d, a, b, c, w[ 8], 11, 0x8771f681);
136 	HH(c, d, a, b, w[11], 16, 0x6d9d6122);
137 	HH(b, c, d, a, w[14], 23, 0xfde5380c);
138 	HH(a, b, c, d, w[ 1],  4, 0xa4beea44);
139 	HH(d, a, b, c, w[ 4], 11, 0x4bdecfa9);
140 	HH(c, d, a, b, w[ 7], 16, 0xf6bb4b60);
141 	HH(b, c, d, a, w[10], 23, 0xbebfbc70);
142 	HH(a, b, c, d, w[13],  4, 0x289b7ec6);
143 	HH(d, a, b, c, w[ 0], 11, 0xeaa127fa);
144 	HH(c, d, a, b, w[ 3], 16, 0xd4ef3085);
145 	HH(b, c, d, a, w[ 6], 23, 0x04881d05);
146 	HH(a, b, c, d, w[ 9],  4, 0xd9d4d039);
147 	HH(d, a, b, c, w[12], 11, 0xe6db99e5);
148 	HH(c, d, a, b, w[15], 16, 0x1fa27cf8);
149 	HH(b, c, d, a, w[ 2], 23, 0xc4ac5665);
150 
151 	II(a, b, c, d, w[ 0],  6, 0xf4292244);
152 	II(d, a, b, c, w[ 7], 10, 0x432aff97);
153 	II(c, d, a, b, w[14], 15, 0xab9423a7);
154 	II(b, c, d, a, w[ 5], 21, 0xfc93a039);
155 	II(a, b, c, d, w[12],  6, 0x655b59c3);
156 	II(d, a, b, c, w[ 3], 10, 0x8f0ccc92);
157 	II(c, d, a, b, w[10], 15, 0xffeff47d);
158 	II(b, c, d, a, w[ 1], 21, 0x85845dd1);
159 	II(a, b, c, d, w[ 8],  6, 0x6fa87e4f);
160 	II(d, a, b, c, w[15], 10, 0xfe2ce6e0);
161 	II(c, d, a, b, w[ 6], 15, 0xa3014314);
162 	II(b, c, d, a, w[13], 21, 0x4e0811a1);
163 	II(a, b, c, d, w[ 4],  6, 0xf7537e82);
164 	II(d, a, b, c, w[11], 10, 0xbd3af235);
165 	II(c, d, a, b, w[ 2], 15, 0x2ad7d2bb);
166 	II(b, c, d, a, w[ 9], 21, 0xeb86d391);
167 
168 	mp->h[0] += a;
169 	mp->h[1] += b;
170 	mp->h[2] += c;
171 	mp->h[3] += d;
172 }
173 #endif
174 
md5Update(md5Param * mp,const byte * data,size_t size)175 int md5Update(md5Param* mp, const byte* data, size_t size)
176 {
177 	register uint32_t proclength;
178 
179 	#if (MP_WBITS == 64)
180 	mpw add[1];
181 	mpsetw(1, add, size);
182 	mplshift(1, add, 3);
183 	mpadd(1, mp->length, add);
184 	#elif (MP_WBITS == 32)
185 	mpw add[2];
186 	mpsetws(2, add, size);
187 	mplshift(2, add, 3);
188 	mpadd(2, mp->length, add);
189 	#else
190 	# error
191 	#endif
192 
193 	while (size > 0)
194 	{
195 		/* no truncation of data is possible here: maximum value returned is 64! */
196 		proclength = (uint32_t) ((mp->offset + size) > 64U) ? (64U - mp->offset) : size;
197 		memcpy(((byte *) mp->data) + mp->offset, data, proclength);
198 		size -= proclength;
199 		data += proclength;
200 		mp->offset += proclength;
201 
202 		if (mp->offset == 64U)
203 		{
204 			md5Process(mp);
205 			mp->offset = 0;
206 		}
207 	}
208 	return 0;
209 }
210 
md5Finish(md5Param * mp)211 static void md5Finish(md5Param* mp)
212 {
213 	register byte *ptr = ((byte *) mp->data) + mp->offset++;
214 
215 	*(ptr++) = 0x80;
216 
217 	if (mp->offset > 56)
218 	{
219 		while (mp->offset++ < 64)
220 			*(ptr++) = 0;
221 
222 		md5Process(mp);
223 		mp->offset = 0;
224 	}
225 
226 	ptr = ((byte *) mp->data) + mp->offset;
227 	while (mp->offset++ < 56)
228 		*(ptr++) = 0;
229 
230 	#if (MP_WBITS == 64)
231 	ptr[0] = (byte)(mp->length[0]      );
232 	ptr[1] = (byte)(mp->length[0] >>  8);
233 	ptr[2] = (byte)(mp->length[0] >> 16);
234 	ptr[3] = (byte)(mp->length[0] >> 24);
235 	ptr[4] = (byte)(mp->length[0] >> 32);
236 	ptr[5] = (byte)(mp->length[0] >> 40);
237 	ptr[6] = (byte)(mp->length[0] >> 48);
238 	ptr[7] = (byte)(mp->length[0] >> 56);
239 	#elif (MP_WBITS == 32)
240 	ptr[0] = (byte)(mp->length[1]      );
241 	ptr[1] = (byte)(mp->length[1] >>  8);
242 	ptr[2] = (byte)(mp->length[1] >> 16);
243 	ptr[3] = (byte)(mp->length[1] >> 24);
244 	ptr[4] = (byte)(mp->length[0]      );
245 	ptr[5] = (byte)(mp->length[0] >>  8);
246 	ptr[6] = (byte)(mp->length[0] >> 16);
247 	ptr[7] = (byte)(mp->length[0] >> 24);
248 	#else
249 	# error
250 	#endif
251 
252 	md5Process(mp);
253 
254 	mp->offset = 0;
255 }
256 
md5Digest(md5Param * mp,byte * data)257 int md5Digest(md5Param* mp, byte* data)
258 {
259 	md5Finish(mp);
260 
261 	/* encode 4 integers little-endian style */
262 	data[ 0] = (byte)(mp->h[0]      );
263 	data[ 1] = (byte)(mp->h[0] >>  8);
264 	data[ 2] = (byte)(mp->h[0] >> 16);
265 	data[ 3] = (byte)(mp->h[0] >> 24);
266 	data[ 4] = (byte)(mp->h[1]      );
267 	data[ 5] = (byte)(mp->h[1] >>  8);
268 	data[ 6] = (byte)(mp->h[1] >> 16);
269 	data[ 7] = (byte)(mp->h[1] >> 24);
270 	data[ 8] = (byte)(mp->h[2]      );
271 	data[ 9] = (byte)(mp->h[2] >>  8);
272 	data[10] = (byte)(mp->h[2] >> 16);
273 	data[11] = (byte)(mp->h[2] >> 24);
274 	data[12] = (byte)(mp->h[3]      );
275 	data[13] = (byte)(mp->h[3] >>  8);
276 	data[14] = (byte)(mp->h[3] >> 16);
277 	data[15] = (byte)(mp->h[3] >> 24);
278 
279 	md5Reset(mp);
280 	return 0;
281 }
282 
283 /*!\}
284  */
285