home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / libraries / liblutil / md5.c < prev    next >
C/C++ Source or Header  |  2000-07-29  |  10KB  |  324 lines

  1. /* $OpenLDAP: pkg/ldap/libraries/liblutil/md5.c,v 1.5.8.4 2000/07/29 01:53:11 kurt Exp $ */
  2. /*
  3.  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
  4.  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  5.  */
  6. /*
  7.  * Modified by Kurt D. Zeilenga for inclusion into OpenLDAP
  8.  * I hereby disclaim copyright in any changes I have made; this
  9.  * code remains in the public domain.
  10.  */
  11.  
  12. /*
  13.  * This code implements the MD5 message-digest algorithm.
  14.  * The algorithm is due to Ron Rivest.  This code was
  15.  * written by Colin Plumb in 1993, no copyright is claimed.
  16.  * This code is in the public domain; do with it what you wish.
  17.  *
  18.  * Equivalent code is available from RSA Data Security, Inc.
  19.  * This code has been tested against that, and is equivalent,
  20.  * except that you don't need to include two pages of legalese
  21.  * with every copy.
  22.  *
  23.  * To compute the message digest of a chunk of bytes, declare an
  24.  * MD5Context structure, pass it to MD5Init, call MD5Update as
  25.  * needed on buffers full of bytes, and then call MD5Final, which
  26.  * will fill a supplied 16-byte array with the digest.
  27.  */
  28.  
  29. /* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
  30.    not require an integer type which is exactly 32 bits.  This work
  31.    draws on the changes for the same purpose by Tatu Ylonen
  32.    <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
  33.    that code, there is no copyright issue.  I hereby disclaim
  34.    copyright in any changes I have made; this code remains in the
  35.    public domain.  */
  36.  
  37. #include "portable.h"
  38.  
  39. #include <ac/string.h>
  40.  
  41. /* include socket.h to get sys/types.h and/or winsock2.h */
  42. #include <ac/socket.h>
  43.  
  44. #include <lutil_md5.h>
  45.  
  46. /* Little-endian byte-swapping routines.  Note that these do not
  47.    depend on the size of datatypes such as ber_uint_t, nor do they require
  48.    us to detect the endianness of the machine we are running on.  It
  49.    is possible they should be macros for speed, but I would be
  50.    surprised if they were a performance bottleneck for MD5.  */
  51.  
  52. static ber_uint_t
  53. getu32( const unsigned char *addr )
  54. {
  55.     return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
  56.         | addr[1]) << 8 | addr[0];
  57. }
  58.  
  59. static void
  60. putu32( ber_uint_t data, unsigned char *addr )
  61. {
  62.     addr[0] = (unsigned char)data;
  63.     addr[1] = (unsigned char)(data >> 8);
  64.     addr[2] = (unsigned char)(data >> 16);
  65.     addr[3] = (unsigned char)(data >> 24);
  66. }
  67.  
  68. /*
  69.  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  70.  * initialization constants.
  71.  */
  72. void
  73. lutil_MD5Init( struct lutil_MD5Context *ctx )
  74. {
  75.     ctx->buf[0] = 0x67452301;
  76.     ctx->buf[1] = 0xefcdab89;
  77.     ctx->buf[2] = 0x98badcfe;
  78.     ctx->buf[3] = 0x10325476;
  79.  
  80.     ctx->bits[0] = 0;
  81.     ctx->bits[1] = 0;
  82. }
  83.  
  84. /*
  85.  * Update context to reflect the concatenation of another buffer full
  86.  * of bytes.
  87.  */
  88. void
  89. lutil_MD5Update(
  90.     struct lutil_MD5Context    *ctx,
  91.     const unsigned char        *buf,
  92.     ber_len_t        len
  93. )
  94. {
  95.     ber_uint_t t;
  96.  
  97.     /* Update bitcount */
  98.  
  99.     t = ctx->bits[0];
  100.     if ((ctx->bits[0] = (t + ((ber_uint_t)len << 3)) & 0xffffffff) < t)
  101.         ctx->bits[1]++;    /* Carry from low to high */
  102.     ctx->bits[1] += len >> 29;
  103.  
  104.     t = (t >> 3) & 0x3f;    /* Bytes already in shsInfo->data */
  105.  
  106.     /* Handle any leading odd-sized chunks */
  107.  
  108.     if ( t ) {
  109.         unsigned char *p = ctx->in + t;
  110.  
  111.         t = 64-t;
  112.         if (len < t) {
  113.             AC_MEMCPY(p, buf, len);
  114.             return;
  115.         }
  116.         AC_MEMCPY(p, buf, t);
  117.         lutil_MD5Transform(ctx->buf, ctx->in);
  118.         buf += t;
  119.         len -= t;
  120.     }
  121.  
  122.     /* Process data in 64-byte chunks */
  123.  
  124.     while (len >= 64) {
  125.         AC_MEMCPY(ctx->in, buf, 64);
  126.         lutil_MD5Transform(ctx->buf, ctx->in);
  127.         buf += 64;
  128.         len -= 64;
  129.     }
  130.  
  131.     /* Handle any remaining bytes of data. */
  132.  
  133.     AC_MEMCPY(ctx->in, buf, len);
  134. }
  135.  
  136. /*
  137.  * Final wrapup - pad to 64-byte boundary with the bit pattern 
  138.  * 1 0* (64-bit count of bits processed, MSB-first)
  139.  */
  140. void
  141. lutil_MD5Final( unsigned char *digest, struct lutil_MD5Context *ctx )
  142. {
  143.     unsigned count;
  144.     unsigned char *p;
  145.  
  146.     /* Compute number of bytes mod 64 */
  147.     count = (ctx->bits[0] >> 3) & 0x3F;
  148.  
  149.     /* Set the first char of padding to 0x80.  This is safe since there is
  150.        always at least one byte free */
  151.     p = ctx->in + count;
  152.     *p++ = 0x80;
  153.  
  154.     /* Bytes of padding needed to make 64 bytes */
  155.     count = 64 - 1 - count;
  156.  
  157.     /* Pad out to 56 mod 64 */
  158.     if (count < 8) {
  159.         /* Two lots of padding:  Pad the first block to 64 bytes */
  160.         memset(p, '\0', count);
  161.         lutil_MD5Transform(ctx->buf, ctx->in);
  162.  
  163.         /* Now fill the next block with 56 bytes */
  164.         memset(ctx->in, '\0', 56);
  165.     } else {
  166.         /* Pad block to 56 bytes */
  167.         memset(p, '\0', count-8);
  168.     }
  169.  
  170.     /* Append length in bits and transform */
  171.     putu32(ctx->bits[0], ctx->in + 56);
  172.     putu32(ctx->bits[1], ctx->in + 60);
  173.  
  174.     lutil_MD5Transform(ctx->buf, ctx->in);
  175.     putu32(ctx->buf[0], digest);
  176.     putu32(ctx->buf[1], digest + 4);
  177.     putu32(ctx->buf[2], digest + 8);
  178.     putu32(ctx->buf[3], digest + 12);
  179.     memset(ctx, '\0', sizeof(ctx));    /* In case it's sensitive */
  180. }
  181.  
  182. #ifndef ASM_MD5
  183.  
  184. /* The four core functions - F1 is optimized somewhat */
  185.  
  186. /* #define F1(x, y, z) (x & y | ~x & z) */
  187. #define F1(x, y, z) (z ^ (x & (y ^ z)))
  188. #define F2(x, y, z) F1(z, x, y)
  189. #define F3(x, y, z) (x ^ y ^ z)
  190. #define F4(x, y, z) (y ^ (x | ~z))
  191.  
  192. /* This is the central step in the MD5 algorithm. */
  193. #define MD5STEP(f, w, x, y, z, data, s) \
  194.     ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
  195.  
  196. /*
  197.  * The core of the MD5 algorithm, this alters an existing MD5 hash to
  198.  * reflect the addition of 16 longwords of new data.  MD5Update blocks
  199.  * the data and converts bytes into longwords for this routine.
  200.  */
  201. void
  202. lutil_MD5Transform( ber_uint_t *buf, const unsigned char *inraw )
  203. {
  204.     register ber_uint_t a, b, c, d;
  205.     ber_uint_t in[16];
  206.     int i;
  207.  
  208.     for (i = 0; i < 16; ++i)
  209.         in[i] = getu32 (inraw + 4 * i);
  210.  
  211.     a = buf[0];
  212.     b = buf[1];
  213.     c = buf[2];
  214.     d = buf[3];
  215.  
  216.     MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
  217.     MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
  218.     MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
  219.     MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
  220.     MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
  221.     MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
  222.     MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
  223.     MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
  224.     MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
  225.     MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
  226.     MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
  227.     MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
  228.     MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
  229.     MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
  230.     MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
  231.     MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
  232.  
  233.     MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
  234.     MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
  235.     MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
  236.     MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
  237.     MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
  238.     MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
  239.     MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
  240.     MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
  241.     MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
  242.     MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
  243.     MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
  244.     MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
  245.     MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
  246.     MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
  247.     MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
  248.     MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
  249.  
  250.     MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
  251.     MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
  252.     MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
  253.     MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
  254.     MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
  255.     MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
  256.     MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
  257.     MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
  258.     MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
  259.     MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
  260.     MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
  261.     MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
  262.     MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
  263.     MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
  264.     MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
  265.     MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
  266.  
  267.     MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
  268.     MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
  269.     MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
  270.     MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
  271.     MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
  272.     MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
  273.     MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
  274.     MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
  275.     MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
  276.     MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
  277.     MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
  278.     MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
  279.     MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
  280.     MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
  281.     MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
  282.     MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
  283.  
  284.     buf[0] += a;
  285.     buf[1] += b;
  286.     buf[2] += c;
  287.     buf[3] += d;
  288. }
  289. #endif
  290.  
  291. #ifdef TEST
  292. /* Simple test program.  Can use it to manually run the tests from
  293.    RFC1321 for example.  */
  294. #include <stdio.h>
  295.  
  296. int
  297. main (int  argc, char **argv )
  298. {
  299.     struct lutil_MD5Context context;
  300.     unsigned char checksum[LUTIL_MD5_BYTES];
  301.     int i;
  302.     int j;
  303.  
  304.     if (argc < 2)
  305.     {
  306.         fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
  307.         return EXIT_FAILURE;
  308.     }
  309.     for (j = 1; j < argc; ++j)
  310.     {
  311.         printf ("MD5 (\"%s\") = ", argv[j]);
  312.         lutil_MD5Init (&context);
  313.         lutil_MD5Update (&context, argv[j], strlen (argv[j]));
  314.         lutil_MD5Final (checksum, &context);
  315.         for (i = 0; i < LUTIL_MD5_BYTES; i++)
  316.         {
  317.             printf ("%02x", (unsigned int) checksum[i]);
  318.         }
  319.         printf ("\n");
  320.     }
  321.     return EXIT_SUCCESS;
  322. }
  323. #endif /* TEST */
  324.