md5c.c revision 1802
11802Sphk/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
21802Sphk * $FreeBSD: cvs2svn/branches/ORIG/sys/kern/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