1/* 2 File: MD5.c 3 4 Written by: Colin Plumb 5 6 Copyright: Copyright (c) 1998,2004-2005 Apple Computer, Inc. All Rights Reserved. 7 8 Change History (most recent first): 9 10 <7> 10/06/98 ap Changed to compile with C++. 11 12 To Do: 13*/ 14 15/* Copyright (c) 1998,2004-2005 Apple Computer, Inc. All Rights Reserved. 16 * 17 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT 18 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE 19 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE 20 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, 21 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL 22 * EXPOSE YOU TO LIABILITY. 23 *************************************************************************** 24 * 25 * MD5.c 26 */ 27 28/* 29 * This code implements the MD5 message-digest algorithm. 30 * The algorithm is due to Ron Rivest. This code was 31 * written by Colin Plumb in 1993, no copyright is claimed. 32 * This code is in the public domain; do with it what you wish. 33 * 34 * Equivalent code is available from RSA Data Security, Inc. 35 * This code has been tested against that, and is equivalent, 36 * except that you don't need to include two pages of legalese 37 * with every copy. 38 * 39 * To compute the message digest of a chunk of bytes, declare an 40 * MD5Context structure, pass it to MD5Init, call MD5Update as 41 * needed on buffers full of bytes, and then call MD5Final, which 42 * will fill a supplied 16-byte array with the digest. 43 */ 44 45/* 46 * Revision History 47 * ---------------- 48 * 06 Feb 1997 Doug Mitchell at Apple 49 * Fixed endian-dependent cast in MD5Final() 50 * Made byteReverse() tolerant of platform-dependent alignment 51 * restrictions 52 */ 53 54#include "MD5.h" 55//#include "platform.h" 56#undef __LITTLE_ENDIAN__ 57#undef __BIG_ENDIAN__ 58#define __BIG_ENDIAN__ 59 60#include <stdlib.h> 61#include <strings.h> 62 63static inline void intToByteRep(int i, unsigned char *buf) 64{ 65 *buf++ = (unsigned char)((i >> 24) & 0xff); 66 *buf++ = (unsigned char)((i >> 16) & 0xff); 67 *buf++ = (unsigned char)((i >> 8) & 0xff); 68 *buf = (unsigned char)(i & 0xff); 69} 70 71#define MD5_DEBUG 0 72 73#if MD5_DEBUG 74static inline void dumpCtx(struct MD5Context *ctx, char *label) 75{ 76 int i; 77 78 printf("%s\n", label); 79 printf("buf = "); 80 for(i=0; i<4; i++) { 81 printf("%x:", ctx->buf[i]); 82 } 83 printf("\nbits: %d:%d\n", ctx->bits[0], ctx->bits[1]); 84 printf("in[]:\n "); 85 for(i=0; i<64; i++) { 86 printf("%02x:", ctx->in[i]); 87 if((i % 16) == 15) { 88 printf("\n "); 89 } 90 } 91 printf("\n"); 92} 93#else // MD5_DEBUG 94#define dumpCtx(ctx, label) 95#endif // MD5_DEBUG 96 97static void MD5Transform(uint32 buf[4], uint32 const in[16]); 98 99#ifdef __LITTLE_ENDIAN__ 100#define byteReverse(buf, len) /* Nothing */ 101#else 102static void byteReverse(unsigned char *buf, unsigned longs); 103 104#ifndef ASM_MD5 105/* 106 * Note: this code is harmless on little-endian machines. 107 */ 108static void byteReverse(unsigned char *buf, unsigned longs) 109{ 110#if old_way 111 /* 112 * this code is NOT harmless on big-endian machine which require 113 * natural alignment. 114 */ 115 uint32 t; 116 do { 117 t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | 118 ((unsigned) buf[1] << 8 | buf[0]); 119 *(uint32 *) buf = t; 120 buf += 4; 121 } while (--longs); 122#else // new_way 123 124 unsigned char t; 125 do { 126 t = buf[0]; 127 buf[0] = buf[3]; 128 buf[3] = t; 129 t = buf[1]; 130 buf[1] = buf[2]; 131 buf[2] = t; 132 buf += 4; 133 } while (--longs); 134#endif // old_way 135} 136#endif // ASM_MD5 137#endif // __LITTLE_ENDIAN__ 138 139/* 140 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious 141 * initialization constants. 142 */ 143void MD5Init(struct MD5Context *ctx) 144{ 145 ctx->buf[0] = 0x67452301; 146 ctx->buf[1] = 0xefcdab89; 147 ctx->buf[2] = 0x98badcfe; 148 ctx->buf[3] = 0x10325476; 149 150 ctx->bits[0] = 0; 151 ctx->bits[1] = 0; 152} 153 154/* 155 * Update context to reflect the concatenation of another buffer full 156 * of bytes. 157 */ 158void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) 159{ 160 uint32 t; 161 162 dumpCtx(ctx, "MD5.c update top"); 163 /* Update bitcount */ 164 165 t = ctx->bits[0]; 166 if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) 167 ctx->bits[1]++; /* Carry from low to high */ 168 ctx->bits[1] += len >> 29; 169 170 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ 171 172 /* Handle any leading odd-sized chunks */ 173 174 if (t) { 175 unsigned char *p = (unsigned char *) ctx->in + t; 176 177 t = 64 - t; 178 if (len < t) { 179 memcpy(p, buf, len); 180 return; 181 } 182 memcpy(p, buf, t); 183 byteReverse(ctx->in, 16); 184 MD5Transform(ctx->buf, (uint32 *) ctx->in); 185 dumpCtx(ctx, "update - return from transform (1)"); 186 buf += t; 187 len -= t; 188 } 189 /* Process data in 64-byte chunks */ 190 191 while (len >= 64) { 192 memcpy(ctx->in, buf, 64); 193 byteReverse(ctx->in, 16); 194 MD5Transform(ctx->buf, (uint32 *) ctx->in); 195 dumpCtx(ctx, "update - return from transform (2)"); 196 buf += 64; 197 len -= 64; 198 } 199 200 /* Handle any remaining bytes of data. */ 201 202 memcpy(ctx->in, buf, len); 203} 204 205/* 206 * Final wrapup - pad to 64-byte boundary with the bit pattern 207 * 1 0* (64-bit count of bits processed, MSB-first) 208 */ 209void MD5Final(struct MD5Context *ctx, unsigned char *digest) 210{ 211 unsigned count; 212 unsigned char *p; 213 214 dumpCtx(ctx, "final top"); 215 216 /* Compute number of bytes mod 64 */ 217 count = (ctx->bits[0] >> 3) & 0x3F; 218 219 /* Set the first char of padding to 0x80. This is safe since there is 220 always at least one byte free */ 221 p = ctx->in + count; 222 *p++ = 0x80; 223 #if MD5_DEBUG 224 printf("in[%d] = %x\n", count, ctx->in[count]); 225 #endif 226 /* Bytes of padding needed to make 64 bytes */ 227 count = 64 - 1 - count; 228 229 /* Pad out to 56 mod 64 */ 230 dumpCtx(ctx, "final, before pad"); 231 if (count < 8) { 232 /* Two lots of padding: Pad the first block to 64 bytes */ 233 bzero(p, count); 234 byteReverse(ctx->in, 16); 235 MD5Transform(ctx->buf, (uint32 *) ctx->in); 236 237 /* Now fill the next block with 56 bytes */ 238 bzero(ctx->in, 56); 239 } else { 240 /* Pad block to 56 bytes */ 241 bzero(p, count - 8); 242 } 243 byteReverse(ctx->in, 14); 244 245 /* Append length in bits and transform */ 246 #ifdef __LITTLE_ENDIAN__ 247 /* l.s. byte of bits[0] --> in[56] */ 248 ((uint32 *) ctx->in)[14] = ctx->bits[0]; 249 ((uint32 *) ctx->in)[15] = ctx->bits[1]; 250 #else 251 /* l.s. byte of bits[0] --> in[60] */ 252 intToByteRep(ctx->bits[0], &ctx->in[56]); 253 intToByteRep(ctx->bits[1], &ctx->in[60]); 254 #endif 255 256 dumpCtx(ctx, "last transform"); 257 MD5Transform(ctx->buf, (uint32 *) ctx->in); 258 byteReverse((unsigned char *) ctx->buf, 4); 259 memcpy(digest, ctx->buf, MD5_DIGEST_SIZE); 260 dumpCtx(ctx, "final end"); 261 262 bzero(ctx, sizeof(*ctx)); /* In case it's sensitive */ 263} 264 265#ifndef ASM_MD5 266 267/* The four core functions - F1 is optimized somewhat */ 268 269/* #define F1(x, y, z) (x & y | ~x & z) */ 270#define F1(x, y, z) (z ^ (x & (y ^ z))) 271#define F2(x, y, z) F1(z, x, y) 272#define F3(x, y, z) (x ^ y ^ z) 273#define F4(x, y, z) (y ^ (x | ~z)) 274 275/* This is the central step in the MD5 algorithm. */ 276#define MD5STEP(f, w, x, y, z, data, s) \ 277 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) 278 279/* 280 * The core of the MD5 algorithm, this alters an existing MD5 hash to 281 * reflect the addition of 16 longwords of new data. MD5Update blocks 282 * the data and converts bytes into longwords for this routine. 283 */ 284static void MD5Transform(uint32 buf[4], uint32 const in[16]) 285{ 286 register uint32 a, b, c, d; 287 288 a = buf[0]; 289 b = buf[1]; 290 c = buf[2]; 291 d = buf[3]; 292 293 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); 294 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); 295 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); 296 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); 297 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); 298 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); 299 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); 300 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); 301 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); 302 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); 303 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); 304 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); 305 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); 306 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); 307 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); 308 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); 309 310 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); 311 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); 312 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); 313 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); 314 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); 315 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); 316 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); 317 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); 318 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); 319 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); 320 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); 321 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); 322 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); 323 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); 324 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); 325 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); 326 327 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); 328 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); 329 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); 330 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); 331 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); 332 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); 333 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); 334 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); 335 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); 336 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); 337 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); 338 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); 339 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); 340 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); 341 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); 342 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); 343 344 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); 345 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); 346 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); 347 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); 348 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); 349 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); 350 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); 351 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); 352 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); 353 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); 354 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); 355 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); 356 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); 357 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); 358 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); 359 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); 360 361 buf[0] += a; 362 buf[1] += b; 363 buf[2] += c; 364 buf[3] += d; 365} 366 367#endif // ASM_MD5 368