11e72d8d2Sderaadt /*
21e72d8d2Sderaadt * This code implements the MD5 message-digest algorithm.
31e72d8d2Sderaadt * The algorithm is due to Ron Rivest. This code was
41e72d8d2Sderaadt * written by Colin Plumb in 1993, no copyright is claimed.
51e72d8d2Sderaadt * This code is in the public domain; do with it what you wish.
61e72d8d2Sderaadt *
71e72d8d2Sderaadt * Equivalent code is available from RSA Data Security, Inc.
81e72d8d2Sderaadt * This code has been tested against that, and is equivalent,
91e72d8d2Sderaadt * except that you don't need to include two pages of legalese
101e72d8d2Sderaadt * with every copy.
111e72d8d2Sderaadt *
121e72d8d2Sderaadt * To compute the message digest of a chunk of bytes, declare an
131e72d8d2Sderaadt * MD5Context structure, pass it to MD5Init, call MD5Update as
141e72d8d2Sderaadt * needed on buffers full of bytes, and then call MD5Final, which
151e72d8d2Sderaadt * will fill a supplied 16-byte array with the digest.
161e72d8d2Sderaadt */
171e72d8d2Sderaadt
18780d15dfStholo /* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
19780d15dfStholo not require an integer type which is exactly 32 bits. This work
20780d15dfStholo draws on the changes for the same purpose by Tatu Ylonen
21780d15dfStholo <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
22780d15dfStholo that code, there is no copyright issue. I hereby disclaim
23780d15dfStholo copyright in any changes I have made; this code remains in the
24780d15dfStholo public domain. */
25780d15dfStholo
26c71bc7e2Stholo /* Note regarding cvs_* namespace: this avoids potential conflicts
27c71bc7e2Stholo with libraries such as some versions of Kerberos. No particular
28c71bc7e2Stholo need to worry about whether the system supplies an MD5 library, as
29c71bc7e2Stholo this file is only about 3k of object code. */
30c71bc7e2Stholo
31780d15dfStholo #ifdef HAVE_CONFIG_H
321e72d8d2Sderaadt #include "config.h"
33780d15dfStholo #endif
341e72d8d2Sderaadt
35c71bc7e2Stholo #include <string.h> /* for memcpy() and memset() */
361e72d8d2Sderaadt
371e72d8d2Sderaadt /* Add prototype support. */
381e72d8d2Sderaadt #ifndef PROTO
391e72d8d2Sderaadt #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
401e72d8d2Sderaadt #define PROTO(ARGS) ARGS
411e72d8d2Sderaadt #else
421e72d8d2Sderaadt #define PROTO(ARGS) ()
431e72d8d2Sderaadt #endif
441e72d8d2Sderaadt #endif
451e72d8d2Sderaadt
461e72d8d2Sderaadt #include "md5.h"
471e72d8d2Sderaadt
48780d15dfStholo /* Little-endian byte-swapping routines. Note that these do not
49c71bc7e2Stholo depend on the size of datatypes such as cvs_uint32, nor do they require
50780d15dfStholo us to detect the endianness of the machine we are running on. It
51780d15dfStholo is possible they should be macros for speed, but I would be
52780d15dfStholo surprised if they were a performance bottleneck for MD5. */
531e72d8d2Sderaadt
54c71bc7e2Stholo static cvs_uint32
getu32(addr)55780d15dfStholo getu32 (addr)
56780d15dfStholo const unsigned char *addr;
571e72d8d2Sderaadt {
58780d15dfStholo return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
59780d15dfStholo | addr[1]) << 8 | addr[0];
601e72d8d2Sderaadt }
61780d15dfStholo
62780d15dfStholo static void
putu32(data,addr)63780d15dfStholo putu32 (data, addr)
64c71bc7e2Stholo cvs_uint32 data;
65780d15dfStholo unsigned char *addr;
66780d15dfStholo {
67780d15dfStholo addr[0] = (unsigned char)data;
68780d15dfStholo addr[1] = (unsigned char)(data >> 8);
69780d15dfStholo addr[2] = (unsigned char)(data >> 16);
70780d15dfStholo addr[3] = (unsigned char)(data >> 24);
71780d15dfStholo }
721e72d8d2Sderaadt
731e72d8d2Sderaadt /*
741e72d8d2Sderaadt * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
751e72d8d2Sderaadt * initialization constants.
761e72d8d2Sderaadt */
771e72d8d2Sderaadt void
cvs_MD5Init(ctx)78c71bc7e2Stholo cvs_MD5Init (ctx)
79c71bc7e2Stholo struct cvs_MD5Context *ctx;
801e72d8d2Sderaadt {
811e72d8d2Sderaadt ctx->buf[0] = 0x67452301;
821e72d8d2Sderaadt ctx->buf[1] = 0xefcdab89;
831e72d8d2Sderaadt ctx->buf[2] = 0x98badcfe;
841e72d8d2Sderaadt ctx->buf[3] = 0x10325476;
851e72d8d2Sderaadt
861e72d8d2Sderaadt ctx->bits[0] = 0;
871e72d8d2Sderaadt ctx->bits[1] = 0;
881e72d8d2Sderaadt }
891e72d8d2Sderaadt
901e72d8d2Sderaadt /*
911e72d8d2Sderaadt * Update context to reflect the concatenation of another buffer full
921e72d8d2Sderaadt * of bytes.
931e72d8d2Sderaadt */
941e72d8d2Sderaadt void
cvs_MD5Update(ctx,buf,len)95c71bc7e2Stholo cvs_MD5Update (ctx, buf, len)
96c71bc7e2Stholo struct cvs_MD5Context *ctx;
971e72d8d2Sderaadt unsigned char const *buf;
981e72d8d2Sderaadt unsigned len;
991e72d8d2Sderaadt {
100c71bc7e2Stholo cvs_uint32 t;
1011e72d8d2Sderaadt
1021e72d8d2Sderaadt /* Update bitcount */
1031e72d8d2Sderaadt
1041e72d8d2Sderaadt t = ctx->bits[0];
105c71bc7e2Stholo if ((ctx->bits[0] = (t + ((cvs_uint32)len << 3)) & 0xffffffff) < t)
1061e72d8d2Sderaadt ctx->bits[1]++; /* Carry from low to high */
1071e72d8d2Sderaadt ctx->bits[1] += len >> 29;
1081e72d8d2Sderaadt
1091e72d8d2Sderaadt t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
1101e72d8d2Sderaadt
1111e72d8d2Sderaadt /* Handle any leading odd-sized chunks */
1121e72d8d2Sderaadt
1131e72d8d2Sderaadt if ( t ) {
114780d15dfStholo unsigned char *p = ctx->in + t;
1151e72d8d2Sderaadt
1161e72d8d2Sderaadt t = 64-t;
1171e72d8d2Sderaadt if (len < t) {
1181e72d8d2Sderaadt memcpy(p, buf, len);
1191e72d8d2Sderaadt return;
1201e72d8d2Sderaadt }
1211e72d8d2Sderaadt memcpy(p, buf, t);
122c71bc7e2Stholo cvs_MD5Transform (ctx->buf, ctx->in);
1231e72d8d2Sderaadt buf += t;
1241e72d8d2Sderaadt len -= t;
1251e72d8d2Sderaadt }
1261e72d8d2Sderaadt
1271e72d8d2Sderaadt /* Process data in 64-byte chunks */
1281e72d8d2Sderaadt
1291e72d8d2Sderaadt while (len >= 64) {
1301e72d8d2Sderaadt memcpy(ctx->in, buf, 64);
131c71bc7e2Stholo cvs_MD5Transform (ctx->buf, ctx->in);
1321e72d8d2Sderaadt buf += 64;
1331e72d8d2Sderaadt len -= 64;
1341e72d8d2Sderaadt }
1351e72d8d2Sderaadt
1361e72d8d2Sderaadt /* Handle any remaining bytes of data. */
1371e72d8d2Sderaadt
1381e72d8d2Sderaadt memcpy(ctx->in, buf, len);
1391e72d8d2Sderaadt }
1401e72d8d2Sderaadt
1411e72d8d2Sderaadt /*
1421e72d8d2Sderaadt * Final wrapup - pad to 64-byte boundary with the bit pattern
1431e72d8d2Sderaadt * 1 0* (64-bit count of bits processed, MSB-first)
1441e72d8d2Sderaadt */
1451e72d8d2Sderaadt void
cvs_MD5Final(digest,ctx)146c71bc7e2Stholo cvs_MD5Final (digest, ctx)
1471e72d8d2Sderaadt unsigned char digest[16];
148c71bc7e2Stholo struct cvs_MD5Context *ctx;
1491e72d8d2Sderaadt {
1501e72d8d2Sderaadt unsigned count;
1511e72d8d2Sderaadt unsigned char *p;
1521e72d8d2Sderaadt
1531e72d8d2Sderaadt /* Compute number of bytes mod 64 */
1541e72d8d2Sderaadt count = (ctx->bits[0] >> 3) & 0x3F;
1551e72d8d2Sderaadt
1561e72d8d2Sderaadt /* Set the first char of padding to 0x80. This is safe since there is
1571e72d8d2Sderaadt always at least one byte free */
1581e72d8d2Sderaadt p = ctx->in + count;
1591e72d8d2Sderaadt *p++ = 0x80;
1601e72d8d2Sderaadt
1611e72d8d2Sderaadt /* Bytes of padding needed to make 64 bytes */
1621e72d8d2Sderaadt count = 64 - 1 - count;
1631e72d8d2Sderaadt
1641e72d8d2Sderaadt /* Pad out to 56 mod 64 */
1651e72d8d2Sderaadt if (count < 8) {
1661e72d8d2Sderaadt /* Two lots of padding: Pad the first block to 64 bytes */
1671e72d8d2Sderaadt memset(p, 0, count);
168c71bc7e2Stholo cvs_MD5Transform (ctx->buf, ctx->in);
1691e72d8d2Sderaadt
1701e72d8d2Sderaadt /* Now fill the next block with 56 bytes */
1711e72d8d2Sderaadt memset(ctx->in, 0, 56);
1721e72d8d2Sderaadt } else {
1731e72d8d2Sderaadt /* Pad block to 56 bytes */
1741e72d8d2Sderaadt memset(p, 0, count-8);
1751e72d8d2Sderaadt }
1761e72d8d2Sderaadt
1771e72d8d2Sderaadt /* Append length in bits and transform */
178780d15dfStholo putu32(ctx->bits[0], ctx->in + 56);
179780d15dfStholo putu32(ctx->bits[1], ctx->in + 60);
1801e72d8d2Sderaadt
181c71bc7e2Stholo cvs_MD5Transform (ctx->buf, ctx->in);
182780d15dfStholo putu32(ctx->buf[0], digest);
183780d15dfStholo putu32(ctx->buf[1], digest + 4);
184780d15dfStholo putu32(ctx->buf[2], digest + 8);
185780d15dfStholo putu32(ctx->buf[3], digest + 12);
186*319d553eSotto memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
1871e72d8d2Sderaadt }
1881e72d8d2Sderaadt
1891e72d8d2Sderaadt #ifndef ASM_MD5
1901e72d8d2Sderaadt
1911e72d8d2Sderaadt /* The four core functions - F1 is optimized somewhat */
1921e72d8d2Sderaadt
1931e72d8d2Sderaadt /* #define F1(x, y, z) (x & y | ~x & z) */
1941e72d8d2Sderaadt #define F1(x, y, z) (z ^ (x & (y ^ z)))
1951e72d8d2Sderaadt #define F2(x, y, z) F1(z, x, y)
1961e72d8d2Sderaadt #define F3(x, y, z) (x ^ y ^ z)
1971e72d8d2Sderaadt #define F4(x, y, z) (y ^ (x | ~z))
1981e72d8d2Sderaadt
1991e72d8d2Sderaadt /* This is the central step in the MD5 algorithm. */
2001e72d8d2Sderaadt #define MD5STEP(f, w, x, y, z, data, s) \
201780d15dfStholo ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
2021e72d8d2Sderaadt
2031e72d8d2Sderaadt /*
2041e72d8d2Sderaadt * The core of the MD5 algorithm, this alters an existing MD5 hash to
2051e72d8d2Sderaadt * reflect the addition of 16 longwords of new data. MD5Update blocks
2061e72d8d2Sderaadt * the data and converts bytes into longwords for this routine.
2071e72d8d2Sderaadt */
2081e72d8d2Sderaadt void
cvs_MD5Transform(buf,inraw)209c71bc7e2Stholo cvs_MD5Transform (buf, inraw)
210c71bc7e2Stholo cvs_uint32 buf[4];
211780d15dfStholo const unsigned char inraw[64];
2121e72d8d2Sderaadt {
213c71bc7e2Stholo register cvs_uint32 a, b, c, d;
214c71bc7e2Stholo cvs_uint32 in[16];
215780d15dfStholo int i;
216780d15dfStholo
217780d15dfStholo for (i = 0; i < 16; ++i)
218780d15dfStholo in[i] = getu32 (inraw + 4 * i);
2191e72d8d2Sderaadt
2201e72d8d2Sderaadt a = buf[0];
2211e72d8d2Sderaadt b = buf[1];
2221e72d8d2Sderaadt c = buf[2];
2231e72d8d2Sderaadt d = buf[3];
2241e72d8d2Sderaadt
2251e72d8d2Sderaadt MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
2261e72d8d2Sderaadt MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
2271e72d8d2Sderaadt MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
2281e72d8d2Sderaadt MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
2291e72d8d2Sderaadt MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
2301e72d8d2Sderaadt MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
2311e72d8d2Sderaadt MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
2321e72d8d2Sderaadt MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
2331e72d8d2Sderaadt MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
2341e72d8d2Sderaadt MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
2351e72d8d2Sderaadt MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
2361e72d8d2Sderaadt MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
2371e72d8d2Sderaadt MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
2381e72d8d2Sderaadt MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
2391e72d8d2Sderaadt MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
2401e72d8d2Sderaadt MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
2411e72d8d2Sderaadt
2421e72d8d2Sderaadt MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
2431e72d8d2Sderaadt MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
2441e72d8d2Sderaadt MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
2451e72d8d2Sderaadt MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
2461e72d8d2Sderaadt MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
2471e72d8d2Sderaadt MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
2481e72d8d2Sderaadt MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
2491e72d8d2Sderaadt MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
2501e72d8d2Sderaadt MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
2511e72d8d2Sderaadt MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
2521e72d8d2Sderaadt MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
2531e72d8d2Sderaadt MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
2541e72d8d2Sderaadt MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
2551e72d8d2Sderaadt MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
2561e72d8d2Sderaadt MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
2571e72d8d2Sderaadt MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
2581e72d8d2Sderaadt
2591e72d8d2Sderaadt MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
2601e72d8d2Sderaadt MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
2611e72d8d2Sderaadt MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
2621e72d8d2Sderaadt MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
2631e72d8d2Sderaadt MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
2641e72d8d2Sderaadt MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
2651e72d8d2Sderaadt MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
2661e72d8d2Sderaadt MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
2671e72d8d2Sderaadt MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
2681e72d8d2Sderaadt MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
2691e72d8d2Sderaadt MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
2701e72d8d2Sderaadt MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
2711e72d8d2Sderaadt MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
2721e72d8d2Sderaadt MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
2731e72d8d2Sderaadt MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
2741e72d8d2Sderaadt MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
2751e72d8d2Sderaadt
2761e72d8d2Sderaadt MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
2771e72d8d2Sderaadt MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
2781e72d8d2Sderaadt MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
2791e72d8d2Sderaadt MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
2801e72d8d2Sderaadt MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
2811e72d8d2Sderaadt MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
2821e72d8d2Sderaadt MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
2831e72d8d2Sderaadt MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
2841e72d8d2Sderaadt MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
2851e72d8d2Sderaadt MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
2861e72d8d2Sderaadt MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
2871e72d8d2Sderaadt MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
2881e72d8d2Sderaadt MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
2891e72d8d2Sderaadt MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
2901e72d8d2Sderaadt MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
2911e72d8d2Sderaadt MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
2921e72d8d2Sderaadt
2931e72d8d2Sderaadt buf[0] += a;
2941e72d8d2Sderaadt buf[1] += b;
2951e72d8d2Sderaadt buf[2] += c;
2961e72d8d2Sderaadt buf[3] += d;
2971e72d8d2Sderaadt }
2981e72d8d2Sderaadt #endif
299780d15dfStholo
300780d15dfStholo #ifdef TEST
301780d15dfStholo /* Simple test program. Can use it to manually run the tests from
302780d15dfStholo RFC1321 for example. */
303780d15dfStholo #include <stdio.h>
304780d15dfStholo
305780d15dfStholo int
main(int argc,char ** argv)306780d15dfStholo main (int argc, char **argv)
307780d15dfStholo {
308c71bc7e2Stholo struct cvs_MD5Context context;
309780d15dfStholo unsigned char checksum[16];
310780d15dfStholo int i;
311780d15dfStholo int j;
312780d15dfStholo
313780d15dfStholo if (argc < 2)
314780d15dfStholo {
315780d15dfStholo fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
316780d15dfStholo exit (1);
317780d15dfStholo }
318780d15dfStholo for (j = 1; j < argc; ++j)
319780d15dfStholo {
320780d15dfStholo printf ("MD5 (\"%s\") = ", argv[j]);
321c71bc7e2Stholo cvs_MD5Init (&context);
322c71bc7e2Stholo cvs_MD5Update (&context, argv[j], strlen (argv[j]));
323c71bc7e2Stholo cvs_MD5Final (checksum, &context);
324780d15dfStholo for (i = 0; i < 16; i++)
325780d15dfStholo {
326780d15dfStholo printf ("%02x", (unsigned int) checksum[i]);
327780d15dfStholo }
328780d15dfStholo printf ("\n");
329780d15dfStholo }
330780d15dfStholo return 0;
331780d15dfStholo }
332780d15dfStholo #endif /* TEST */
333