3 * Release $Name: MATRIXSSL_1_8_8_OPEN $
5 * MD5 hash implementation
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)))
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 */
103 static void _md5_compress(hash_state
*md
)
105 static void md5_compress(hash_state
*md
)
106 #endif /* CLEAN_STACK */
108 unsigned long i
, W
[16], a
, b
, c
, d
;
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
));
125 a
= md
->md5
.state
[0];
126 b
= md
->md5
.state
[1];
127 c
= md
->md5
.state
[2];
128 d
= md
->md5
.state
[3];
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
;
226 static void md5_compress(hash_state
*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
;
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
)
253 sslAssert(md
!= NULL
);
254 sslAssert(buf
!= NULL
);
256 n
= MIN(len
, (64 - md
->md5
.curlen
));
257 memcpy(md
->md5
.buf
+ md
->md5
.curlen
, buf
, (size_t)n
);
265 if (md
->md5
.curlen
== 64) {
268 md
->md5
.length
+= 512;
270 n
= (md
->md5
.lengthLo
+ 512) & 0xFFFFFFFFL
;
271 if (n
< md
->md5
.lengthLo
) {
274 md
->md5
.lengthLo
= n
;
275 #endif /* USE_INT64 */
281 int32
matrixMd5Final(hash_state
* md
, unsigned char *hash
)
288 sslAssert(md
!= NULL
);
294 increase the length of the message
297 md
->md5
.length
+= md
->md5
.curlen
<< 3;
299 n
= (md
->md5
.lengthLo
+ (md
->md5
.curlen
<< 3)) & 0xFFFFFFFFL
;
300 if (n
< md
->md5
.lengthLo
) {
303 md
->md5
.lengthHi
+= (md
->md5
.curlen
>> 29);
304 md
->md5
.lengthLo
= n
;
305 #endif /* USE_INT64 */
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;
325 pad upto 56 bytes of zeroes
327 while (md
->md5
.curlen
< 56) {
328 md
->md5
.buf
[md
->md5
.curlen
++] = (unsigned char)0;
334 STORE64L(md
->md5
.length
, md
->md5
.buf
+56);
336 STORE32L(md
->md5
.lengthLo
, md
->md5
.buf
+56);
337 STORE32L(md
->md5
.lengthHi
, md
->md5
.buf
+60);
338 #endif /* USE_INT64 */
344 for (i
= 0; i
< 4; i
++) {
345 STORE32L(md
->md5
.state
[i
], hash
+(4*i
));
348 psZeromem(md
, sizeof(hash_state
));
349 #endif /* CLEAN_STACK */
355 int32
matrixMd5Test()
357 static const struct {
359 unsigned char hash
[16];
362 { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
363 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
365 {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
366 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
368 { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
369 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
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 } },
386 unsigned char tmp
[16];
389 for (i
= 0; tests
[i
].msg
!= NULL
; i
++) {
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
;
399 #endif /* PEERSEC_TEST */
401 /******************************************************************************/