reSIProcate/rutil  9694
vmd5.cxx
Go to the documentation of this file.
00001 /*
00002  * This code implements the MD5 message-digest algorithm.
00003  * The algorithm is due to Ron Rivest.  This code was
00004  * written by Colin Plumb in 1993, no copyright is claimed.
00005  * This code is in the public domain; do with it what you wish.
00006  *
00007  * Equivalent code is available from RSA Data Security, Inc.
00008  * This code has been tested against that, and is equivalent,
00009  * except that you don't need to include two pages of legalese
00010  * with every copy.
00011  *
00012  * To compute the message digest of a chunk of bytes, declare an
00013  * MD5Context structure, pass it to MD5Init, call MD5Update as
00014  * needed on buffers full of bytes, and then call MD5Final, which
00015  * will fill a supplied 16-byte array with the digest.
00016  *
00017  * Changed so as no longer to depend on Colin Plumb's `usual.h' header
00018  * definitions; now uses stuff from dpkg's config.h.
00019  *  - Ian Jackson <ijackson@nyx.cs.du.edu>.
00020  * Still in the public domain.
00021  */
00022 
00023 #include <string.h>             /* for memcpy() */
00024 #include <sys/types.h>          /* for stupid systems */
00025 
00026 #ifndef WIN32
00027 #include <netinet/in.h>         /* for ntohl() */
00028 #endif
00029 
00030 #include "rutil/vmd5.hxx"
00031 
00032 /* Add _BIG_ENDIAN for Solaris */
00033 /* Add _BIG_ENDIAN__ for MAC OSX */
00034 #if defined(WORDS_BIGENDIAN) || defined(_BIG_ENDIAN) || defined( __BIG_ENDIAN__ )
00035 void
00036 resip::byteSwap(u_int32_t *buf, unsigned words)
00037 {
00038    md5byte *p = (md5byte *)buf;
00039 
00040    do
00041    {
00042       *buf++ = (u_int32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
00043          ((unsigned)p[1] << 8 | p[0]);
00044       p += 4;
00045    }
00046    while (--words);
00047 }
00048 #else
00049 #define byteSwap(buf,words)
00050 #endif
00051 
00052 
00053 /*
00054  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
00055  * initialization constants.
00056  */
00057 void
00058 resip::MD5Init(struct MD5Context *ctx)
00059 {
00060    ctx->buf[0] = 0x67452301;
00061    ctx->buf[1] = 0xefcdab89;
00062    ctx->buf[2] = 0x98badcfe;
00063    ctx->buf[3] = 0x10325476;
00064 
00065    ctx->bytes[0] = 0;
00066    ctx->bytes[1] = 0;
00067 }
00068 
00069 /*
00070  * Update context to reflect the concatenation of another buffer full
00071  * of bytes.
00072  */
00073 void
00074 resip::MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len)
00075 {
00076    u_int32_t t;
00077 
00078    /* Update byte count */
00079 
00080    t = ctx->bytes[0];
00081    if ((ctx->bytes[0] = t + len) < t)
00082       ctx->bytes[1]++;  /* Carry from low to high */
00083 
00084    t = 64 - (t & 0x3f);         /* Space available in ctx->in (at least 1) */
00085    if (t > len)
00086    {
00087       memcpy((md5byte *)ctx->in + 64 - t, buf, len);
00088       return ;
00089    }
00090    /* First chunk is an odd size */
00091    memcpy((md5byte *)ctx->in + 64 - t, buf, t);
00092    byteSwap(ctx->in, 16);
00093    MD5Transform(ctx->buf, ctx->in);
00094    buf += t;
00095    len -= t;
00096 
00097    /* Process data in 64-byte chunks */
00098    while (len >= 64)
00099    {
00100       memcpy(ctx->in, buf, 64);
00101       byteSwap(ctx->in, 16);
00102       MD5Transform(ctx->buf, ctx->in);
00103       buf += 64;
00104       len -= 64;
00105    }
00106 
00107    /* Handle any remaining bytes of data. */
00108    memcpy(ctx->in, buf, len);
00109 }
00110 
00111 /*
00112  * Final wrapup - pad to 64-byte boundary with the bit pattern 
00113  * 1 0* (64-bit count of bits processed, MSB-first)
00114  */
00115 void
00116 resip::MD5Final(md5byte digest[16], struct MD5Context *ctx)
00117 {
00118    int count = ctx->bytes[0] & 0x3f;    /* Number of bytes in ctx->in */
00119    md5byte *p = (md5byte *)ctx->in + count;
00120 
00121    /* Set the first char of padding to 0x80.  There is always room. */
00122    *p++ = 0x80;
00123 
00124    /* Bytes of padding needed to make 56 bytes (-8..55) */
00125    count = 56 - 1 - count;
00126 
00127    if (count < 0)
00128    {    /* Padding forces an extra block */
00129       memset(p, 0, count + 8);
00130       byteSwap(ctx->in, 16);
00131       MD5Transform(ctx->buf, ctx->in);
00132       p = (md5byte *)ctx->in;
00133       count = 56;
00134    }
00135    memset(p, 0, count);
00136    byteSwap(ctx->in, 14);
00137 
00138    /* Append length in bits and transform */
00139    ctx->in[14] = ctx->bytes[0] << 3;
00140    ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
00141    MD5Transform(ctx->buf, ctx->in);
00142 
00143    byteSwap(ctx->buf, 4);
00144    memcpy(digest, ctx->buf, 16);
00145    memset(ctx, 0, sizeof(*ctx));        /* In case it's sensitive */
00146 }
00147 
00148 #ifndef ASM_MD5
00149 
00150 /* The four core functions - F1 is optimized somewhat */
00151 
00152 /* #define F1(x, y, z) (x & y | ~x & z) */
00153 #define F1(x, y, z) (z ^ (x & (y ^ z)))
00154 #define F2(x, y, z) F1(z, x, y)
00155 #define F3(x, y, z) (x ^ y ^ z)
00156 #define F4(x, y, z) (y ^ (x | ~z))
00157 
00158 /* This is the central step in the MD5 algorithm. */
00159 #define MD5STEP(f,w,x,y,z,in,s) \
00160 (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
00161 
00162 /*
00163  * The core of the MD5 algorithm, this alters an existing MD5 hash to
00164  * reflect the addition of 16 longwords of new data.  MD5Update blocks
00165  * the data and converts bytes into longwords for this routine.
00166  */
00167 void
00168 resip::MD5Transform(u_int32_t buf[4], u_int32_t const in[16])
00169 {
00170    register u_int32_t a, b, c, d;
00171 
00172    a = buf[0];
00173    b = buf[1];
00174    c = buf[2];
00175    d = buf[3];
00176 
00177    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
00178    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
00179    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
00180    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
00181    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
00182    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
00183    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
00184    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
00185    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
00186    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
00187    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
00188    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
00189    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
00190    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
00191    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
00192    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
00193 
00194    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
00195    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
00196    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
00197    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
00198    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
00199    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
00200    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
00201    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
00202    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
00203    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
00204    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
00205    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
00206    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
00207    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
00208    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
00209    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
00210 
00211    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
00212    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
00213    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
00214    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
00215    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
00216    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
00217    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
00218    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
00219    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
00220    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
00221    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
00222    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
00223    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
00224    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
00225    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
00226    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
00227 
00228    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
00229    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
00230    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
00231    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
00232    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
00233    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
00234    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
00235    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
00236    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
00237    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
00238    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
00239    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
00240    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
00241    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
00242    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
00243    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
00244 
00245    buf[0] += a;
00246    buf[1] += b;
00247    buf[2] += c;
00248    buf[3] += d;
00249 }
00250 
00251 #endif
00252 
00253 /* ====================================================================
00254  * The Vovida Software License, Version 1.0 
00255  * 
00256  * Copyright (c) 2000-2005 Vovida Networks, Inc.  All rights reserved.
00257  * 
00258  * Redistribution and use in source and binary forms, with or without
00259  * modification, are permitted provided that the following conditions
00260  * are met:
00261  * 
00262  * 1. Redistributions of source code must retain the above copyright
00263  *    notice, this list of conditions and the following disclaimer.
00264  * 
00265  * 2. Redistributions in binary form must reproduce the above copyright
00266  *    notice, this list of conditions and the following disclaimer in
00267  *    the documentation and/or other materials provided with the
00268  *    distribution.
00269  * 
00270  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00271  *    and "Vovida Open Communication Application Library (VOCAL)" must
00272  *    not be used to endorse or promote products derived from this
00273  *    software without prior written permission. For written
00274  *    permission, please contact vocal@vovida.org.
00275  *
00276  * 4. Products derived from this software may not be called "VOCAL", nor
00277  *    may "VOCAL" appear in their name, without prior written
00278  *    permission of Vovida Networks, Inc.
00279  * 
00280  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00281  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00282  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00283  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00284  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00285  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00286  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00287  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00288  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00289  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00290  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00291  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00292  * DAMAGE.
00293  * 
00294  * ====================================================================
00295  * 
00296  * This software consists of voluntary contributions made by Vovida
00297  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00298  * Inc.  For more information on Vovida Networks, Inc., please see
00299  * <http://www.vovida.org/>.
00300  *
00301  */