Tomato 1.26
[tomato.git] / release / src / router / matrixssl / src / crypto / peersec / md5.c
blobe116131864cfe2d29d89bc978eee015b2834d4ba
1 /*
2 * md5.c
3 * Release $Name: MATRIXSSL_1_8_8_OPEN $
5 * MD5 hash implementation
6 */
7 /*
8 * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
9 * The latest version of this code is available at http://www.matrixssl.org
11 * This software is open source; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This General Public License does NOT permit incorporating this software
17 * into proprietary programs. If you are unable to comply with the GPL, a
18 * commercial license for this software may be purchased from PeerSec Networks
19 * at http://www.peersec.com
21 * This program is distributed in WITHOUT ANY WARRANTY; without even the
22 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 * See the GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * http://www.gnu.org/copyleft/gpl.html
30 /******************************************************************************/
32 #include "../cryptoLayer.h"
34 #define F(x,y,z) (z ^ (x & (y ^ z)))
35 #define G(x,y,z) (y ^ (z & (y ^ x)))
36 #define H(x,y,z) (x^y^z)
37 #define I(x,y,z) (y^(x|(~z)))
39 #ifdef SMALL_CODE
41 #define FF(a,b,c,d,M,s,t) \
42 a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b;
44 #define GG(a,b,c,d,M,s,t) \
45 a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b;
47 #define HH(a,b,c,d,M,s,t) \
48 a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b;
50 #define II(a,b,c,d,M,s,t) \
51 a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;
53 static const unsigned char Worder[64] = {
54 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
55 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
56 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
57 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
60 static const unsigned char Rorder[64] = {
61 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
62 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
63 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
64 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
67 static const ulong32 Korder[] = {
68 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL,
69 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
70 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL,
71 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
72 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL,
73 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
74 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL,
75 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
76 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL,
77 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
78 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL,
79 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
80 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL,
81 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
82 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL,
83 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL,
84 0xe1f27f3aUL, 0xf5710fb0UL, 0xada0e5c4UL, 0x98e4c919UL
86 #else /* SMALL_CODE */
88 #define FF(a,b,c,d,M,s,t) \
89 a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b;
91 #define GG(a,b,c,d,M,s,t) \
92 a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b;
94 #define HH(a,b,c,d,M,s,t) \
95 a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b;
97 #define II(a,b,c,d,M,s,t) \
98 a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b;
100 #endif /* SMALL_CODE */
102 #ifdef CLEAN_STACK
103 static void _md5_compress(hash_state *md)
104 #else
105 static void md5_compress(hash_state *md)
106 #endif /* CLEAN_STACK */
108 unsigned long i, W[16], a, b, c, d;
109 #ifdef SMALL_CODE
110 ulong32 t;
111 #endif
113 sslAssert(md != NULL);
116 copy the state into 512-bits into W[0..15]
118 for (i = 0; i < 16; i++) {
119 LOAD32L(W[i], md->md5.buf + (4*i));
123 copy state
125 a = md->md5.state[0];
126 b = md->md5.state[1];
127 c = md->md5.state[2];
128 d = md->md5.state[3];
130 #ifdef SMALL_CODE
131 for (i = 0; i < 16; ++i) {
132 FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
133 t = d; d = c; c = b; b = a; a = t;
136 for (; i < 32; ++i) {
137 GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
138 t = d; d = c; c = b; b = a; a = t;
141 for (; i < 48; ++i) {
142 HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
143 t = d; d = c; c = b; b = a; a = t;
146 for (; i < 64; ++i) {
147 II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
148 t = d; d = c; c = b; b = a; a = t;
151 #else /* SMALL_CODE */
153 FF(a,b,c,d,W[0],7,0xd76aa478UL)
154 FF(d,a,b,c,W[1],12,0xe8c7b756UL)
155 FF(c,d,a,b,W[2],17,0x242070dbUL)
156 FF(b,c,d,a,W[3],22,0xc1bdceeeUL)
157 FF(a,b,c,d,W[4],7,0xf57c0fafUL)
158 FF(d,a,b,c,W[5],12,0x4787c62aUL)
159 FF(c,d,a,b,W[6],17,0xa8304613UL)
160 FF(b,c,d,a,W[7],22,0xfd469501UL)
161 FF(a,b,c,d,W[8],7,0x698098d8UL)
162 FF(d,a,b,c,W[9],12,0x8b44f7afUL)
163 FF(c,d,a,b,W[10],17,0xffff5bb1UL)
164 FF(b,c,d,a,W[11],22,0x895cd7beUL)
165 FF(a,b,c,d,W[12],7,0x6b901122UL)
166 FF(d,a,b,c,W[13],12,0xfd987193UL)
167 FF(c,d,a,b,W[14],17,0xa679438eUL)
168 FF(b,c,d,a,W[15],22,0x49b40821UL)
169 GG(a,b,c,d,W[1],5,0xf61e2562UL)
170 GG(d,a,b,c,W[6],9,0xc040b340UL)
171 GG(c,d,a,b,W[11],14,0x265e5a51UL)
172 GG(b,c,d,a,W[0],20,0xe9b6c7aaUL)
173 GG(a,b,c,d,W[5],5,0xd62f105dUL)
174 GG(d,a,b,c,W[10],9,0x02441453UL)
175 GG(c,d,a,b,W[15],14,0xd8a1e681UL)
176 GG(b,c,d,a,W[4],20,0xe7d3fbc8UL)
177 GG(a,b,c,d,W[9],5,0x21e1cde6UL)
178 GG(d,a,b,c,W[14],9,0xc33707d6UL)
179 GG(c,d,a,b,W[3],14,0xf4d50d87UL)
180 GG(b,c,d,a,W[8],20,0x455a14edUL)
181 GG(a,b,c,d,W[13],5,0xa9e3e905UL)
182 GG(d,a,b,c,W[2],9,0xfcefa3f8UL)
183 GG(c,d,a,b,W[7],14,0x676f02d9UL)
184 GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
185 HH(a,b,c,d,W[5],4,0xfffa3942UL)
186 HH(d,a,b,c,W[8],11,0x8771f681UL)
187 HH(c,d,a,b,W[11],16,0x6d9d6122UL)
188 HH(b,c,d,a,W[14],23,0xfde5380cUL)
189 HH(a,b,c,d,W[1],4,0xa4beea44UL)
190 HH(d,a,b,c,W[4],11,0x4bdecfa9UL)
191 HH(c,d,a,b,W[7],16,0xf6bb4b60UL)
192 HH(b,c,d,a,W[10],23,0xbebfbc70UL)
193 HH(a,b,c,d,W[13],4,0x289b7ec6UL)
194 HH(d,a,b,c,W[0],11,0xeaa127faUL)
195 HH(c,d,a,b,W[3],16,0xd4ef3085UL)
196 HH(b,c,d,a,W[6],23,0x04881d05UL)
197 HH(a,b,c,d,W[9],4,0xd9d4d039UL)
198 HH(d,a,b,c,W[12],11,0xe6db99e5UL)
199 HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
200 HH(b,c,d,a,W[2],23,0xc4ac5665UL)
201 II(a,b,c,d,W[0],6,0xf4292244UL)
202 II(d,a,b,c,W[7],10,0x432aff97UL)
203 II(c,d,a,b,W[14],15,0xab9423a7UL)
204 II(b,c,d,a,W[5],21,0xfc93a039UL)
205 II(a,b,c,d,W[12],6,0x655b59c3UL)
206 II(d,a,b,c,W[3],10,0x8f0ccc92UL)
207 II(c,d,a,b,W[10],15,0xffeff47dUL)
208 II(b,c,d,a,W[1],21,0x85845dd1UL)
209 II(a,b,c,d,W[8],6,0x6fa87e4fUL)
210 II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
211 II(c,d,a,b,W[6],15,0xa3014314UL)
212 II(b,c,d,a,W[13],21,0x4e0811a1UL)
213 II(a,b,c,d,W[4],6,0xf7537e82UL)
214 II(d,a,b,c,W[11],10,0xbd3af235UL)
215 II(c,d,a,b,W[2],15,0x2ad7d2bbUL)
216 II(b,c,d,a,W[9],21,0xeb86d391UL)
217 #endif /* SMALL_CODE */
219 md->md5.state[0] = md->md5.state[0] + a;
220 md->md5.state[1] = md->md5.state[1] + b;
221 md->md5.state[2] = md->md5.state[2] + c;
222 md->md5.state[3] = md->md5.state[3] + d;
225 #ifdef CLEAN_STACK
226 static void md5_compress(hash_state *md)
228 _md5_compress(md);
229 psBurnStack(sizeof(unsigned long) * 21);
231 #endif /* CLEAN_STACK */
233 void matrixMd5Init(hash_state * md)
235 sslAssert(md != NULL);
236 md->md5.state[0] = 0x67452301UL;
237 md->md5.state[1] = 0xefcdab89UL;
238 md->md5.state[2] = 0x98badcfeUL;
239 md->md5.state[3] = 0x10325476UL;
240 md->md5.curlen = 0;
241 #ifdef USE_INT64
242 md->md5.length = 0;
243 #else
244 md->md5.lengthHi = 0;
245 md->md5.lengthLo = 0;
246 #endif /* USE_INT64 */
249 void matrixMd5Update(hash_state * md, const unsigned char *buf, unsigned long len)
251 unsigned long n;
253 sslAssert(md != NULL);
254 sslAssert(buf != NULL);
255 while (len > 0) {
256 n = MIN(len, (64 - md->md5.curlen));
257 memcpy(md->md5.buf + md->md5.curlen, buf, (size_t)n);
258 md->md5.curlen += n;
259 buf += n;
260 len -= n;
263 is 64 bytes full?
265 if (md->md5.curlen == 64) {
266 md5_compress(md);
267 #ifdef USE_INT64
268 md->md5.length += 512;
269 #else
270 n = (md->md5.lengthLo + 512) & 0xFFFFFFFFL;
271 if (n < md->md5.lengthLo) {
272 md->md5.lengthHi++;
274 md->md5.lengthLo = n;
275 #endif /* USE_INT64 */
276 md->md5.curlen = 0;
281 int32 matrixMd5Final(hash_state * md, unsigned char *hash)
283 int32 i;
284 #ifndef USE_INT64
285 unsigned long n;
286 #endif
288 sslAssert(md != NULL);
289 if (hash == NULL) {
290 return -1;
294 increase the length of the message
296 #ifdef USE_INT64
297 md->md5.length += md->md5.curlen << 3;
298 #else
299 n = (md->md5.lengthLo + (md->md5.curlen << 3)) & 0xFFFFFFFFL;
300 if (n < md->md5.lengthLo) {
301 md->md5.lengthHi++;
303 md->md5.lengthHi += (md->md5.curlen >> 29);
304 md->md5.lengthLo = n;
305 #endif /* USE_INT64 */
308 append the '1' bit
310 md->md5.buf[md->md5.curlen++] = (unsigned char)0x80;
313 if the length is currently above 56 bytes we append zeros then compress.
314 Then we can fall back to padding zeros and length encoding like normal.
316 if (md->md5.curlen > 56) {
317 while (md->md5.curlen < 64) {
318 md->md5.buf[md->md5.curlen++] = (unsigned char)0;
320 md5_compress(md);
321 md->md5.curlen = 0;
325 pad upto 56 bytes of zeroes
327 while (md->md5.curlen < 56) {
328 md->md5.buf[md->md5.curlen++] = (unsigned char)0;
331 store length
333 #ifdef USE_INT64
334 STORE64L(md->md5.length, md->md5.buf+56);
335 #else
336 STORE32L(md->md5.lengthLo, md->md5.buf+56);
337 STORE32L(md->md5.lengthHi, md->md5.buf+60);
338 #endif /* USE_INT64 */
339 md5_compress(md);
342 copy output
344 for (i = 0; i < 4; i++) {
345 STORE32L(md->md5.state[i], hash+(4*i));
347 #ifdef CLEAN_STACK
348 psZeromem(md, sizeof(hash_state));
349 #endif /* CLEAN_STACK */
350 return 16;
353 #ifdef PEERSEC_TEST
355 int32 matrixMd5Test()
357 static const struct {
358 char *msg;
359 unsigned char hash[16];
360 } tests[] = {
361 { "",
362 { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
363 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
364 { "a",
365 {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
366 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
367 { "abc",
368 { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
369 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
370 { "message digest",
371 { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
372 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
373 { "abcdefghijklmnopqrstuvwxyz",
374 { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
375 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
376 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
377 { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
378 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
379 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
380 { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
381 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } },
382 { NULL, { 0 } }
385 int32 i;
386 unsigned char tmp[16];
387 hash_state md;
389 for (i = 0; tests[i].msg != NULL; i++) {
390 matrixMd5Init(&md);
391 matrixMd5Update(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
392 matrixMd5Final(&md, tmp);
393 if (memcmp(tmp, tests[i].hash, 16) != 0) {
394 return CRYPT_FAIL_TESTVECTOR;
397 return CRYPT_OK;
399 #endif /* PEERSEC_TEST */
401 /******************************************************************************/