Back to index

openldap  2.4.31
md5.c
Go to the documentation of this file.
00001 /* md5.c -- MD5 message-digest algorithm */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* This work was adapted for inclusion in OpenLDAP Software by
00017  * Kurt D. Zeilenga based upon code developed by Colin Plumb
00018  * and subsequently modified by Jim Kingdon. 
00019  */
00020 
00021 /*
00022  * This code implements the MD5 message-digest algorithm.
00023  * The algorithm is due to Ron Rivest.  This code was
00024  * written by Colin Plumb in 1993, no copyright is claimed.
00025  * This code is in the public domain; do with it what you wish.
00026  *
00027  * Equivalent code is available from RSA Data Security, Inc.
00028  * This code has been tested against that, and is equivalent,
00029  * except that you don't need to include two pages of legalese
00030  * with every copy.
00031  *
00032  * To compute the message digest of a chunk of bytes, declare an
00033  * MD5Context structure, pass it to MD5Init, call MD5Update as
00034  * needed on buffers full of bytes, and then call MD5Final, which
00035  * will fill a supplied 16-byte array with the digest.
00036  */
00037 
00038 /* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
00039    not require an integer type which is exactly 32 bits.  This work
00040    draws on the changes for the same purpose by Tatu Ylonen
00041    <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
00042    that code, there is no copyright issue.  I hereby disclaim
00043    copyright in any changes I have made; this code remains in the
00044    public domain.  */
00045 
00046 #include "portable.h"
00047 
00048 #include <ac/string.h>
00049 
00050 /* include socket.h to get sys/types.h and/or winsock2.h */
00051 #include <ac/socket.h>
00052 
00053 #include <lutil_md5.h>
00054 
00055 /* Little-endian byte-swapping routines.  Note that these do not
00056    depend on the size of datatypes such as ber_uint_t, nor do they require
00057    us to detect the endianness of the machine we are running on.  It
00058    is possible they should be macros for speed, but I would be
00059    surprised if they were a performance bottleneck for MD5.  */
00060 
00061 static ber_uint_t
00062 getu32( const unsigned char *addr )
00063 {
00064        return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
00065               | addr[1]) << 8 | addr[0];
00066 }
00067 
00068 static void
00069 putu32( ber_uint_t data, unsigned char *addr )
00070 {
00071        addr[0] = (unsigned char)data;
00072        addr[1] = (unsigned char)(data >> 8);
00073        addr[2] = (unsigned char)(data >> 16);
00074        addr[3] = (unsigned char)(data >> 24);
00075 }
00076 
00077 /*
00078  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
00079  * initialization constants.
00080  */
00081 void
00082 lutil_MD5Init( struct lutil_MD5Context *ctx )
00083 {
00084        ctx->buf[0] = 0x67452301;
00085        ctx->buf[1] = 0xefcdab89;
00086        ctx->buf[2] = 0x98badcfe;
00087        ctx->buf[3] = 0x10325476;
00088 
00089        ctx->bits[0] = 0;
00090        ctx->bits[1] = 0;
00091 }
00092 
00093 /*
00094  * Update context to reflect the concatenation of another buffer full
00095  * of bytes.
00096  */
00097 void
00098 lutil_MD5Update(
00099     struct lutil_MD5Context *ctx,
00100     const unsigned char            *buf,
00101     ber_len_t        len
00102 )
00103 {
00104        ber_uint_t t;
00105 
00106        /* Update bitcount */
00107 
00108        t = ctx->bits[0];
00109        if ((ctx->bits[0] = (t + ((ber_uint_t)len << 3)) & 0xffffffff) < t)
00110               ctx->bits[1]++;      /* Carry from low to high */
00111        ctx->bits[1] += len >> 29;
00112 
00113        t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
00114 
00115        /* Handle any leading odd-sized chunks */
00116 
00117        if ( t ) {
00118               unsigned char *p = ctx->in + t;
00119 
00120               t = 64-t;
00121               if (len < t) {
00122                      AC_MEMCPY(p, buf, len);
00123                      return;
00124               }
00125               AC_MEMCPY(p, buf, t);
00126               lutil_MD5Transform(ctx->buf, ctx->in);
00127               buf += t;
00128               len -= t;
00129        }
00130 
00131        /* Process data in 64-byte chunks */
00132 
00133        while (len >= 64) {
00134               AC_MEMCPY(ctx->in, buf, 64);
00135               lutil_MD5Transform(ctx->buf, ctx->in);
00136               buf += 64;
00137               len -= 64;
00138        }
00139 
00140        /* Handle any remaining bytes of data. */
00141 
00142        AC_MEMCPY(ctx->in, buf, len);
00143 }
00144 
00145 /*
00146  * Final wrapup - pad to 64-byte boundary with the bit pattern 
00147  * 1 0* (64-bit count of bits processed, MSB-first)
00148  */
00149 void
00150 lutil_MD5Final( unsigned char *digest, struct lutil_MD5Context *ctx )
00151 {
00152        unsigned count;
00153        unsigned char *p;
00154 
00155        /* Compute number of bytes mod 64 */
00156        count = (ctx->bits[0] >> 3) & 0x3F;
00157 
00158        /* Set the first char of padding to 0x80.  This is safe since there is
00159           always at least one byte free */
00160        p = ctx->in + count;
00161        *p++ = 0x80;
00162 
00163        /* Bytes of padding needed to make 64 bytes */
00164        count = 64 - 1 - count;
00165 
00166        /* Pad out to 56 mod 64 */
00167        if (count < 8) {
00168               /* Two lots of padding:  Pad the first block to 64 bytes */
00169               memset(p, '\0', count);
00170               lutil_MD5Transform(ctx->buf, ctx->in);
00171 
00172               /* Now fill the next block with 56 bytes */
00173               memset(ctx->in, '\0', 56);
00174        } else {
00175               /* Pad block to 56 bytes */
00176               memset(p, '\0', count-8);
00177        }
00178 
00179        /* Append length in bits and transform */
00180        putu32(ctx->bits[0], ctx->in + 56);
00181        putu32(ctx->bits[1], ctx->in + 60);
00182 
00183        lutil_MD5Transform(ctx->buf, ctx->in);
00184        putu32(ctx->buf[0], digest);
00185        putu32(ctx->buf[1], digest + 4);
00186        putu32(ctx->buf[2], digest + 8);
00187        putu32(ctx->buf[3], digest + 12);
00188        memset(ctx, '\0', sizeof(*ctx));   /* In case it's sensitive */
00189 }
00190 
00191 #ifndef ASM_MD5
00192 
00193 /* The four core functions - F1 is optimized somewhat */
00194 
00195 /* #define F1(x, y, z) (x & y | ~x & z) */
00196 #define F1(x, y, z) (z ^ (x & (y ^ z)))
00197 #define F2(x, y, z) F1(z, x, y)
00198 #define F3(x, y, z) (x ^ y ^ z)
00199 #define F4(x, y, z) (y ^ (x | ~z))
00200 
00201 /* This is the central step in the MD5 algorithm. */
00202 #define MD5STEP(f, w, x, y, z, data, s) \
00203        ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
00204 
00205 /*
00206  * The core of the MD5 algorithm, this alters an existing MD5 hash to
00207  * reflect the addition of 16 longwords of new data.  MD5Update blocks
00208  * the data and converts bytes into longwords for this routine.
00209  */
00210 void
00211 lutil_MD5Transform( ber_uint_t *buf, const unsigned char *inraw )
00212 {
00213        register ber_uint_t a, b, c, d;
00214        ber_uint_t in[16];
00215        int i;
00216 
00217        for (i = 0; i < 16; ++i)
00218               in[i] = getu32 (inraw + 4 * i);
00219 
00220        a = buf[0];
00221        b = buf[1];
00222        c = buf[2];
00223        d = buf[3];
00224 
00225        MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
00226        MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
00227        MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
00228        MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
00229        MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
00230        MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
00231        MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
00232        MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
00233        MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
00234        MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
00235        MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
00236        MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
00237        MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
00238        MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
00239        MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
00240        MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
00241 
00242        MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
00243        MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
00244        MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
00245        MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
00246        MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
00247        MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
00248        MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
00249        MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
00250        MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
00251        MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
00252        MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
00253        MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
00254        MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
00255        MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
00256        MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
00257        MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
00258 
00259        MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
00260        MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
00261        MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
00262        MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
00263        MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
00264        MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
00265        MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
00266        MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
00267        MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
00268        MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
00269        MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
00270        MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
00271        MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
00272        MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
00273        MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
00274        MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
00275 
00276        MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
00277        MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
00278        MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
00279        MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
00280        MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
00281        MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
00282        MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
00283        MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
00284        MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
00285        MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
00286        MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
00287        MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
00288        MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
00289        MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
00290        MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
00291        MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
00292 
00293        buf[0] += a;
00294        buf[1] += b;
00295        buf[2] += c;
00296        buf[3] += d;
00297 }
00298 #endif
00299 
00300 #ifdef TEST
00301 /* Simple test program.  Can use it to manually run the tests from
00302    RFC1321 for example.  */
00303 #include <stdio.h>
00304 
00305 int
00306 main (int  argc, char **argv )
00307 {
00308        struct lutil_MD5Context context;
00309        unsigned char checksum[LUTIL_MD5_BYTES];
00310        int i;
00311        int j;
00312 
00313        if (argc < 2)
00314        {
00315               fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
00316               return EXIT_FAILURE;
00317        }
00318        for (j = 1; j < argc; ++j)
00319        {
00320               printf ("MD5 (\"%s\") = ", argv[j]);
00321               lutil_MD5Init (&context);
00322               lutil_MD5Update (&context, argv[j], strlen (argv[j]));
00323               lutil_MD5Final (checksum, &context);
00324               for (i = 0; i < LUTIL_MD5_BYTES; i++)
00325               {
00326                      printf ("%02x", (unsigned int) checksum[i]);
00327               }
00328               printf ("\n");
00329        }
00330        return EXIT_SUCCESS;
00331 }
00332 #endif /* TEST */