1 /* 2 * Copyright (c) 2001-2007, Tom St Denis 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 29 * 30 * LibTomCrypt is a library that provides various cryptographic 31 * algorithms in a highly modular and flexible manner. 32 * 33 * The library is free for all purposes without any express 34 * guarantee it works. 35 * 36 * Tom St Denis, tomstdenis@gmail.com, http://libtom.org 37 */ 38 #include "tomcrypt.h" 39 40 41 /** 42 @file md5.c 43 LTC_MD5 hash function by Tom St Denis 44 */ 45 46 #ifdef LTC_MD5 47 48 const struct ltc_hash_descriptor md5_desc = 49 { 50 "md5", 51 3, 52 16, 53 64, 54 55 /* OID */ 56 { 1, 2, 840, 113549, 2, 5, }, 57 6, 58 59 &md5_init, 60 &md5_process, 61 &md5_done, 62 &md5_test, 63 NULL 64 }; 65 66 #define F(x,y,z) (z ^ (x & (y ^ z))) 67 #define G(x,y,z) (y ^ (z & (y ^ x))) 68 #define H(x,y,z) (x^y^z) 69 #define I(x,y,z) (y^(x|(~z))) 70 71 #ifdef LTC_SMALL_CODE 72 73 #define FF(a,b,c,d,M,s,t) \ 74 a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b; 75 76 #define GG(a,b,c,d,M,s,t) \ 77 a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b; 78 79 #define HH(a,b,c,d,M,s,t) \ 80 a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b; 81 82 #define II(a,b,c,d,M,s,t) \ 83 a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b; 84 85 static const unsigned char Worder[64] = { 86 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 87 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, 88 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, 89 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 90 }; 91 92 static const unsigned char Rorder[64] = { 93 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, 94 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, 95 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, 96 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 97 }; 98 99 static const ulong32 Korder[64] = { 100 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, 101 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, 102 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, 103 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, 104 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, 105 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, 106 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, 107 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL 108 }; 109 110 #else 111 112 #define FF(a,b,c,d,M,s,t) \ 113 a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b; 114 115 #define GG(a,b,c,d,M,s,t) \ 116 a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b; 117 118 #define HH(a,b,c,d,M,s,t) \ 119 a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b; 120 121 #define II(a,b,c,d,M,s,t) \ 122 a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b; 123 124 125 #endif 126 127 #ifdef LTC_CLEAN_STACK 128 static int _md5_compress(hash_state *md, unsigned char *buf) 129 #else 130 static int md5_compress(hash_state *md, unsigned char *buf) 131 #endif 132 { 133 ulong32 i, W[16], a, b, c, d; 134 #ifdef LTC_SMALL_CODE 135 ulong32 t; 136 #endif 137 138 /* copy the state into 512-bits into W[0..15] */ 139 for (i = 0; i < 16; i++) { 140 LOAD32L(W[i], buf + (4*i)); 141 } 142 143 /* copy state */ 144 a = md->md5.state[0]; 145 b = md->md5.state[1]; 146 c = md->md5.state[2]; 147 d = md->md5.state[3]; 148 149 #ifdef LTC_SMALL_CODE 150 for (i = 0; i < 16; ++i) { 151 FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); 152 t = d; d = c; c = b; b = a; a = t; 153 } 154 155 for (; i < 32; ++i) { 156 GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); 157 t = d; d = c; c = b; b = a; a = t; 158 } 159 160 for (; i < 48; ++i) { 161 HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); 162 t = d; d = c; c = b; b = a; a = t; 163 } 164 165 for (; i < 64; ++i) { 166 II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); 167 t = d; d = c; c = b; b = a; a = t; 168 } 169 170 #else 171 FF(a,b,c,d,W[0],7,0xd76aa478UL) 172 FF(d,a,b,c,W[1],12,0xe8c7b756UL) 173 FF(c,d,a,b,W[2],17,0x242070dbUL) 174 FF(b,c,d,a,W[3],22,0xc1bdceeeUL) 175 FF(a,b,c,d,W[4],7,0xf57c0fafUL) 176 FF(d,a,b,c,W[5],12,0x4787c62aUL) 177 FF(c,d,a,b,W[6],17,0xa8304613UL) 178 FF(b,c,d,a,W[7],22,0xfd469501UL) 179 FF(a,b,c,d,W[8],7,0x698098d8UL) 180 FF(d,a,b,c,W[9],12,0x8b44f7afUL) 181 FF(c,d,a,b,W[10],17,0xffff5bb1UL) 182 FF(b,c,d,a,W[11],22,0x895cd7beUL) 183 FF(a,b,c,d,W[12],7,0x6b901122UL) 184 FF(d,a,b,c,W[13],12,0xfd987193UL) 185 FF(c,d,a,b,W[14],17,0xa679438eUL) 186 FF(b,c,d,a,W[15],22,0x49b40821UL) 187 GG(a,b,c,d,W[1],5,0xf61e2562UL) 188 GG(d,a,b,c,W[6],9,0xc040b340UL) 189 GG(c,d,a,b,W[11],14,0x265e5a51UL) 190 GG(b,c,d,a,W[0],20,0xe9b6c7aaUL) 191 GG(a,b,c,d,W[5],5,0xd62f105dUL) 192 GG(d,a,b,c,W[10],9,0x02441453UL) 193 GG(c,d,a,b,W[15],14,0xd8a1e681UL) 194 GG(b,c,d,a,W[4],20,0xe7d3fbc8UL) 195 GG(a,b,c,d,W[9],5,0x21e1cde6UL) 196 GG(d,a,b,c,W[14],9,0xc33707d6UL) 197 GG(c,d,a,b,W[3],14,0xf4d50d87UL) 198 GG(b,c,d,a,W[8],20,0x455a14edUL) 199 GG(a,b,c,d,W[13],5,0xa9e3e905UL) 200 GG(d,a,b,c,W[2],9,0xfcefa3f8UL) 201 GG(c,d,a,b,W[7],14,0x676f02d9UL) 202 GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) 203 HH(a,b,c,d,W[5],4,0xfffa3942UL) 204 HH(d,a,b,c,W[8],11,0x8771f681UL) 205 HH(c,d,a,b,W[11],16,0x6d9d6122UL) 206 HH(b,c,d,a,W[14],23,0xfde5380cUL) 207 HH(a,b,c,d,W[1],4,0xa4beea44UL) 208 HH(d,a,b,c,W[4],11,0x4bdecfa9UL) 209 HH(c,d,a,b,W[7],16,0xf6bb4b60UL) 210 HH(b,c,d,a,W[10],23,0xbebfbc70UL) 211 HH(a,b,c,d,W[13],4,0x289b7ec6UL) 212 HH(d,a,b,c,W[0],11,0xeaa127faUL) 213 HH(c,d,a,b,W[3],16,0xd4ef3085UL) 214 HH(b,c,d,a,W[6],23,0x04881d05UL) 215 HH(a,b,c,d,W[9],4,0xd9d4d039UL) 216 HH(d,a,b,c,W[12],11,0xe6db99e5UL) 217 HH(c,d,a,b,W[15],16,0x1fa27cf8UL) 218 HH(b,c,d,a,W[2],23,0xc4ac5665UL) 219 II(a,b,c,d,W[0],6,0xf4292244UL) 220 II(d,a,b,c,W[7],10,0x432aff97UL) 221 II(c,d,a,b,W[14],15,0xab9423a7UL) 222 II(b,c,d,a,W[5],21,0xfc93a039UL) 223 II(a,b,c,d,W[12],6,0x655b59c3UL) 224 II(d,a,b,c,W[3],10,0x8f0ccc92UL) 225 II(c,d,a,b,W[10],15,0xffeff47dUL) 226 II(b,c,d,a,W[1],21,0x85845dd1UL) 227 II(a,b,c,d,W[8],6,0x6fa87e4fUL) 228 II(d,a,b,c,W[15],10,0xfe2ce6e0UL) 229 II(c,d,a,b,W[6],15,0xa3014314UL) 230 II(b,c,d,a,W[13],21,0x4e0811a1UL) 231 II(a,b,c,d,W[4],6,0xf7537e82UL) 232 II(d,a,b,c,W[11],10,0xbd3af235UL) 233 II(c,d,a,b,W[2],15,0x2ad7d2bbUL) 234 II(b,c,d,a,W[9],21,0xeb86d391UL) 235 #endif 236 237 md->md5.state[0] = md->md5.state[0] + a; 238 md->md5.state[1] = md->md5.state[1] + b; 239 md->md5.state[2] = md->md5.state[2] + c; 240 md->md5.state[3] = md->md5.state[3] + d; 241 242 return CRYPT_OK; 243 } 244 245 #ifdef LTC_CLEAN_STACK 246 static int md5_compress(hash_state *md, unsigned char *buf) 247 { 248 int err; 249 err = _md5_compress(md, buf); 250 burn_stack(sizeof(ulong32) * 21); 251 return err; 252 } 253 #endif 254 255 /** 256 Initialize the hash state 257 @param md The hash state you wish to initialize 258 @return CRYPT_OK if successful 259 */ 260 int md5_init(hash_state * md) 261 { 262 LTC_ARGCHK(md != NULL); 263 md->md5.state[0] = 0x67452301UL; 264 md->md5.state[1] = 0xefcdab89UL; 265 md->md5.state[2] = 0x98badcfeUL; 266 md->md5.state[3] = 0x10325476UL; 267 md->md5.curlen = 0; 268 md->md5.length = 0; 269 return CRYPT_OK; 270 } 271 272 /** 273 Process a block of memory though the hash 274 @param md The hash state 275 @param in The data to hash 276 @param inlen The length of the data (octets) 277 @return CRYPT_OK if successful 278 */ 279 HASH_PROCESS(md5_process, md5_compress, md5, 64) 280 281 /** 282 Terminate the hash to get the digest 283 @param md The hash state 284 @param out [out] The destination of the hash (16 bytes) 285 @return CRYPT_OK if successful 286 */ 287 int md5_done(hash_state * md, unsigned char *out) 288 { 289 int i; 290 291 LTC_ARGCHK(md != NULL); 292 LTC_ARGCHK(out != NULL); 293 294 if (md->md5.curlen >= sizeof(md->md5.buf)) { 295 return CRYPT_INVALID_ARG; 296 } 297 298 299 /* increase the length of the message */ 300 md->md5.length += md->md5.curlen * 8; 301 302 /* append the '1' bit */ 303 md->md5.buf[md->md5.curlen++] = (unsigned char)0x80; 304 305 /* if the length is currently above 56 bytes we append zeros 306 * then compress. Then we can fall back to padding zeros and length 307 * encoding like normal. 308 */ 309 if (md->md5.curlen > 56) { 310 while (md->md5.curlen < 64) { 311 md->md5.buf[md->md5.curlen++] = (unsigned char)0; 312 } 313 md5_compress(md, md->md5.buf); 314 md->md5.curlen = 0; 315 } 316 317 /* pad upto 56 bytes of zeroes */ 318 while (md->md5.curlen < 56) { 319 md->md5.buf[md->md5.curlen++] = (unsigned char)0; 320 } 321 322 /* store length */ 323 STORE64L(md->md5.length, md->md5.buf+56); 324 md5_compress(md, md->md5.buf); 325 326 /* copy output */ 327 for (i = 0; i < 4; i++) { 328 STORE32L(md->md5.state[i], out+(4*i)); 329 } 330 #ifdef LTC_CLEAN_STACK 331 zeromem(md, sizeof(hash_state)); 332 #endif 333 return CRYPT_OK; 334 } 335 336 /** 337 Self-test the hash 338 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled 339 */ 340 int md5_test(void) 341 { 342 #ifndef LTC_TEST 343 return CRYPT_NOP; 344 #else 345 static const struct { 346 const char *msg; 347 unsigned char hash[16]; 348 } tests[] = { 349 { "", 350 { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 351 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, 352 { "a", 353 {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 354 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, 355 { "abc", 356 { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 357 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, 358 { "message digest", 359 { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 360 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, 361 { "abcdefghijklmnopqrstuvwxyz", 362 { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 363 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, 364 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 365 { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 366 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, 367 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 368 { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 369 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, 370 { NULL, { 0 } } 371 }; 372 373 int i; 374 unsigned char tmp[16]; 375 hash_state md; 376 377 for (i = 0; tests[i].msg != NULL; i++) { 378 md5_init(&md); 379 md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); 380 md5_done(&md, tmp); 381 if (XMEMCMP(tmp, tests[i].hash, 16) != 0) { 382 return CRYPT_FAIL_TESTVECTOR; 383 } 384 } 385 return CRYPT_OK; 386 #endif 387 } 388 389 #endif 390 391 392 393 /* $Source: /cvs/libtom/libtomcrypt/src/hashes/md5.c,v $ */ 394 /* $Revision: 1.10 $ */ 395 /* $Date: 2007/05/12 14:25:28 $ */ 396