md5c.c revision 1802
11802Sphk/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm 21802Sphk * $FreeBSD: cvs2svn/branches/ORIG/lib/libmd/md5c.c 1802 1994-07-24 03:29:56Z phk $ 31802Sphk */ 41802Sphk 51802Sphk/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 61802Sphkrights reserved. 71802Sphk 81802SphkLicense to copy and use this software is granted provided that it 91802Sphkis identified as the "RSA Data Security, Inc. MD5 Message-Digest 101802SphkAlgorithm" in all material mentioning or referencing this software 111802Sphkor this function. 121802Sphk 131802SphkLicense is also granted to make and use derivative works provided 141802Sphkthat such works are identified as "derived from the RSA Data 151802SphkSecurity, Inc. MD5 Message-Digest Algorithm" in all material 161802Sphkmentioning or referencing the derived work. 171802Sphk 181802SphkRSA Data Security, Inc. makes no representations concerning either 191802Sphkthe merchantability of this software or the suitability of this 201802Sphksoftware for any particular purpose. It is provided "as is" 211802Sphkwithout express or implied warranty of any kind. 221802Sphk 231802SphkThese notices must be retained in any copies of any part of this 241802Sphkdocumentation and/or software. 251802Sphk */ 261802Sphk 271802Sphk#include "md5.h" 281802Sphk 291802Sphktypedef unsigned char *POINTER; 301802Sphktypedef unsigned short int UINT2; 311802Sphktypedef unsigned long int UINT4; 321802Sphk 331802Sphk#define PROTO_LIST(list) list 341802Sphk 351802Sphk/* Constants for MD5Transform routine. 361802Sphk */ 371802Sphk#define S11 7 381802Sphk#define S12 12 391802Sphk#define S13 17 401802Sphk#define S14 22 411802Sphk#define S21 5 421802Sphk#define S22 9 431802Sphk#define S23 14 441802Sphk#define S24 20 451802Sphk#define S31 4 461802Sphk#define S32 11 471802Sphk#define S33 16 481802Sphk#define S34 23 491802Sphk#define S41 6 501802Sphk#define S42 10 511802Sphk#define S43 15 521802Sphk#define S44 21 531802Sphk 541802Sphkstatic void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); 551802Sphkstatic void Encode PROTO_LIST 561802Sphk ((unsigned char *, UINT4 *, unsigned int)); 571802Sphkstatic void Decode PROTO_LIST 581802Sphk ((UINT4 *, unsigned char *, unsigned int)); 591802Sphk 601802Sphkstatic unsigned char PADDING[64] = { 611802Sphk 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 621802Sphk 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 631802Sphk 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 641802Sphk}; 651802Sphk 661802Sphk/* F, G, H and I are basic MD5 functions. 671802Sphk */ 681802Sphk#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 691802Sphk#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) 701802Sphk#define H(x, y, z) ((x) ^ (y) ^ (z)) 711802Sphk#define I(x, y, z) ((y) ^ ((x) | (~z))) 721802Sphk 731802Sphk/* ROTATE_LEFT rotates x left n bits. 741802Sphk */ 751802Sphk#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 761802Sphk 771802Sphk/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 781802SphkRotation is separate from addition to prevent recomputation. 791802Sphk */ 801802Sphk#define FF(a, b, c, d, x, s, ac) { \ 811802Sphk (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ 821802Sphk (a) = ROTATE_LEFT ((a), (s)); \ 831802Sphk (a) += (b); \ 841802Sphk } 851802Sphk#define GG(a, b, c, d, x, s, ac) { \ 861802Sphk (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ 871802Sphk (a) = ROTATE_LEFT ((a), (s)); \ 881802Sphk (a) += (b); \ 891802Sphk } 901802Sphk#define HH(a, b, c, d, x, s, ac) { \ 911802Sphk (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ 921802Sphk (a) = ROTATE_LEFT ((a), (s)); \ 931802Sphk (a) += (b); \ 941802Sphk } 951802Sphk#define II(a, b, c, d, x, s, ac) { \ 961802Sphk (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ 971802Sphk (a) = ROTATE_LEFT ((a), (s)); \ 981802Sphk (a) += (b); \ 991802Sphk } 1001802Sphk 1011802Sphk/* MD5 initialization. Begins an MD5 operation, writing a new context. 1021802Sphk */ 1031802Sphkvoid MD5Init (context) 1041802SphkMD5_CTX *context; /* context */ 1051802Sphk{ 1061802Sphk context->count[0] = context->count[1] = 0; 1071802Sphk /* Load magic initialization constants. 1081802Sphk*/ 1091802Sphk context->state[0] = 0x67452301; 1101802Sphk context->state[1] = 0xefcdab89; 1111802Sphk context->state[2] = 0x98badcfe; 1121802Sphk context->state[3] = 0x10325476; 1131802Sphk} 1141802Sphk 1151802Sphk/* MD5 block update operation. Continues an MD5 message-digest 1161802Sphk operation, processing another message block, and updating the 1171802Sphk context. 1181802Sphk */ 1191802Sphkvoid MD5Update (context, input, inputLen) 1201802SphkMD5_CTX *context; /* context */ 1211802Sphkunsigned char *input; /* input block */ 1221802Sphkunsigned int inputLen; /* length of input block */ 1231802Sphk{ 1241802Sphk unsigned int i, index, partLen; 1251802Sphk 1261802Sphk /* Compute number of bytes mod 64 */ 1271802Sphk index = (unsigned int)((context->count[0] >> 3) & 0x3F); 1281802Sphk 1291802Sphk /* Update number of bits */ 1301802Sphk if ((context->count[0] += ((UINT4)inputLen << 3)) 1311802Sphk < ((UINT4)inputLen << 3)) 1321802Sphk context->count[1]++; 1331802Sphk context->count[1] += ((UINT4)inputLen >> 29); 1341802Sphk 1351802Sphk partLen = 64 - index; 1361802Sphk 1371802Sphk /* Transform as many times as possible. 1381802Sphk*/ 1391802Sphk if (inputLen >= partLen) { 1401802Sphk memcpy 1411802Sphk ((POINTER)&context->buffer[index], (POINTER)input, partLen); 1421802Sphk MD5Transform (context->state, context->buffer); 1431802Sphk 1441802Sphk for (i = partLen; i + 63 < inputLen; i += 64) 1451802Sphk MD5Transform (context->state, &input[i]); 1461802Sphk 1471802Sphk index = 0; 1481802Sphk } 1491802Sphk else 1501802Sphk i = 0; 1511802Sphk 1521802Sphk /* Buffer remaining input */ 1531802Sphk memcpy 1541802Sphk ((POINTER)&context->buffer[index], (POINTER)&input[i], 1551802Sphk inputLen-i); 1561802Sphk} 1571802Sphk 1581802Sphk/* MD5 finalization. Ends an MD5 message-digest operation, writing the 1591802Sphk the message digest and zeroizing the context. 1601802Sphk */ 1611802Sphkvoid MD5Final (digest, context) 1621802Sphkunsigned char digest[16]; /* message digest */ 1631802SphkMD5_CTX *context; /* context */ 1641802Sphk{ 1651802Sphk unsigned char bits[8]; 1661802Sphk unsigned int index, padLen; 1671802Sphk 1681802Sphk /* Save number of bits */ 1691802Sphk Encode (bits, context->count, 8); 1701802Sphk 1711802Sphk /* Pad out to 56 mod 64. 1721802Sphk*/ 1731802Sphk index = (unsigned int)((context->count[0] >> 3) & 0x3f); 1741802Sphk padLen = (index < 56) ? (56 - index) : (120 - index); 1751802Sphk MD5Update (context, PADDING, padLen); 1761802Sphk 1771802Sphk /* Append length (before padding) */ 1781802Sphk MD5Update (context, bits, 8); 1791802Sphk /* Store state in digest */ 1801802Sphk Encode (digest, context->state, 16); 1811802Sphk 1821802Sphk /* Zeroize sensitive information. 1831802Sphk*/ 1841802Sphk memset ((POINTER)context, 0, sizeof (*context)); 1851802Sphk} 1861802Sphk 1871802Sphk/* MD5 basic transformation. Transforms state based on block. 1881802Sphk */ 1891802Sphkstatic void MD5Transform (state, block) 1901802SphkUINT4 state[4]; 1911802Sphkunsigned char block[64]; 1921802Sphk{ 1931802Sphk UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 1941802Sphk 1951802Sphk Decode (x, block, 64); 1961802Sphk 1971802Sphk /* Round 1 */ 1981802Sphk FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ 1991802Sphk FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ 2001802Sphk FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ 2011802Sphk FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ 2021802Sphk FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ 2031802Sphk FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ 2041802Sphk FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ 2051802Sphk FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ 2061802Sphk FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ 2071802Sphk FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ 2081802Sphk FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 2091802Sphk FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 2101802Sphk FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 2111802Sphk FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 2121802Sphk FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 2131802Sphk FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 2141802Sphk 2151802Sphk /* Round 2 */ 2161802Sphk GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ 2171802Sphk GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ 2181802Sphk GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 2191802Sphk GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ 2201802Sphk GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ 2211802Sphk GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ 2221802Sphk GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 2231802Sphk GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ 2241802Sphk GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ 2251802Sphk GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 2261802Sphk GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ 2271802Sphk GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ 2281802Sphk GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 2291802Sphk GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ 2301802Sphk GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ 2311802Sphk GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 2321802Sphk 2331802Sphk /* Round 3 */ 2341802Sphk HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ 2351802Sphk HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ 2361802Sphk HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 2371802Sphk HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 2381802Sphk HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ 2391802Sphk HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ 2401802Sphk HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ 2411802Sphk HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 2421802Sphk HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 2431802Sphk HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ 2441802Sphk HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ 2451802Sphk HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ 2461802Sphk HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ 2471802Sphk HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 2481802Sphk HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 2491802Sphk HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ 2501802Sphk 2511802Sphk /* Round 4 */ 2521802Sphk II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ 2531802Sphk II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ 2541802Sphk II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 2551802Sphk II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ 2561802Sphk II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 2571802Sphk II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ 2581802Sphk II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 2591802Sphk II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ 2601802Sphk II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ 2611802Sphk II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 2621802Sphk II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ 2631802Sphk II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 2641802Sphk II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ 2651802Sphk II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 2661802Sphk II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ 2671802Sphk II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ 2681802Sphk 2691802Sphk state[0] += a; 2701802Sphk state[1] += b; 2711802Sphk state[2] += c; 2721802Sphk state[3] += d; 2731802Sphk 2741802Sphk /* Zeroize sensitive information. 2751802Sphk*/ 2761802Sphk memset ((POINTER)x, 0, sizeof (x)); 2771802Sphk} 2781802Sphk 2791802Sphk/* Encodes input (UINT4) into output (unsigned char). Assumes len is 2801802Sphk a multiple of 4. 2811802Sphk */ 2821802Sphkstatic void Encode (output, input, len) 2831802Sphkunsigned char *output; 2841802SphkUINT4 *input; 2851802Sphkunsigned int len; 2861802Sphk{ 2871802Sphk unsigned int i, j; 2881802Sphk 2891802Sphk for (i = 0, j = 0; j < len; i++, j += 4) { 2901802Sphk output[j] = (unsigned char)(input[i] & 0xff); 2911802Sphk output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 2921802Sphk output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 2931802Sphk output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 2941802Sphk } 2951802Sphk} 2961802Sphk 2971802Sphk/* Decodes input (unsigned char) into output (UINT4). Assumes len is 2981802Sphk a multiple of 4. 2991802Sphk */ 3001802Sphkstatic void Decode (output, input, len) 3011802SphkUINT4 *output; 3021802Sphkunsigned char *input; 3031802Sphkunsigned int len; 3041802Sphk{ 3051802Sphk unsigned int i, j; 3061802Sphk 3071802Sphk for (i = 0, j = 0; j < len; i++, j += 4) 3081802Sphk output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | 3091802Sphk (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); 3101802Sphk} 311