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