Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages | Examples

md5.cpp

Go to the documentation of this file.
00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 /*
00027   MPL (ActivMedia) renamed to a cpp file
00028 
00029 */
00030 
00031 /* RH (ActivMedia/MobileRobots) including header from ARIA which defines AREXPORT to export
00032    functions from Windows DLLs, and added AREXPORT to functions defined below:
00033 */
00034 #include "ArExport.h"
00035 
00036 /*
00037   Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
00038 
00039   This software is provided 'as-is', without any express or implied
00040   warranty.  In no event will the authors be held liable for any damages
00041   arising from the use of this software.
00042 
00043   Permission is granted to anyone to use this software for any purpose,
00044   including commercial applications, and to alter it and redistribute it
00045   freely, subject to the following restrictions:
00046 
00047   1. The origin of this software must not be misrepresented; you must not
00048      claim that you wrote the original software. If you use this software
00049      in a product, an acknowledgment in the product documentation would be
00050      appreciated but is not required.
00051   2. Altered source versions must be plainly marked as such, and must not be
00052      misrepresented as being the original software.
00053   3. This notice may not be removed or altered from any source distribution.
00054 
00055   L. Peter Deutsch
00056   ghost@aladdin.com
00057 
00058  */
00059 /*
00060   Independent implementation of MD5 (RFC 1321).
00061 
00062   This code implements the MD5 Algorithm defined in RFC 1321, whose
00063   text is available at
00064         http://www.ietf.org/rfc/rfc1321.txt
00065   The code is derived from the text of the RFC, including the test suite
00066   (section A.5) but excluding the rest of Appendix A.  It does not include
00067   any code or documentation that is identified in the RFC as being
00068   copyrighted.
00069 
00070   The original and principal author of md5.c is L. Peter Deutsch
00071   <ghost@aladdin.com>.  Other authors are noted in the change history
00072   that follows (in reverse chronological order):
00073 
00074   2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
00075         either statically or dynamically; added missing #include <string.h>
00076         in library.
00077   2002-03-11 lpd Corrected argument list for main(), and added int return
00078         type, in test program and T value program.
00079   2002-02-21 lpd Added missing #include <stdio.h> in test program.
00080   2000-07-03 lpd Patched to eliminate warnings about "constant is
00081         unsigned in ANSI C, signed in traditional"; made test program
00082         self-checking.
00083   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
00084   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
00085   1999-05-03 lpd Original version.
00086  */
00087 
00088 #include "md5.h"
00089 #include <string.h>
00090 
00091 #undef BYTE_ORDER       /* 1 = big-endian, -1 = little-endian, 0 = unknown */
00092 #ifdef ARCH_IS_BIG_ENDIAN
00093 #  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
00094 #else
00095 #  define BYTE_ORDER 0
00096 #endif
00097 
00098 #define T_MASK ((md5_word_t)~0)
00099 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
00100 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
00101 #define T3    0x242070db
00102 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
00103 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
00104 #define T6    0x4787c62a
00105 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
00106 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
00107 #define T9    0x698098d8
00108 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
00109 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
00110 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
00111 #define T13    0x6b901122
00112 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
00113 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
00114 #define T16    0x49b40821
00115 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
00116 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
00117 #define T19    0x265e5a51
00118 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
00119 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
00120 #define T22    0x02441453
00121 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
00122 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
00123 #define T25    0x21e1cde6
00124 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
00125 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
00126 #define T28    0x455a14ed
00127 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
00128 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
00129 #define T31    0x676f02d9
00130 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
00131 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
00132 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
00133 #define T35    0x6d9d6122
00134 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
00135 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
00136 #define T38    0x4bdecfa9
00137 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
00138 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
00139 #define T41    0x289b7ec6
00140 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
00141 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
00142 #define T44    0x04881d05
00143 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
00144 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
00145 #define T47    0x1fa27cf8
00146 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
00147 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
00148 #define T50    0x432aff97
00149 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
00150 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
00151 #define T53    0x655b59c3
00152 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
00153 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
00154 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
00155 #define T57    0x6fa87e4f
00156 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
00157 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
00158 #define T60    0x4e0811a1
00159 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
00160 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
00161 #define T63    0x2ad7d2bb
00162 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
00163 
00164 
00165 static void
00166 md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
00167 {
00168     md5_word_t
00169         a = pms->abcd[0], b = pms->abcd[1],
00170         c = pms->abcd[2], d = pms->abcd[3];
00171     md5_word_t t;
00172 #if BYTE_ORDER > 0
00173     /* Define storage only for big-endian CPUs. */
00174     md5_word_t X[16];
00175 #else
00176     /* Define storage for little-endian or both types of CPUs. */
00177     md5_word_t xbuf[16];
00178     const md5_word_t *X;
00179 #endif
00180 
00181     {
00182 #if BYTE_ORDER == 0
00183         /*
00184          * Determine dynamically whether this is a big-endian or
00185          * little-endian machine, since we can use a more efficient
00186          * algorithm on the latter.
00187          */
00188         static const int w = 1;
00189 
00190         if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
00191 #endif
00192 #if BYTE_ORDER <= 0             /* little-endian */
00193         {
00194             /*
00195              * On little-endian machines, we can process properly aligned
00196              * data without copying it.
00197              */
00198             if (!((data - (const md5_byte_t *)0) & 3)) {
00199                 /* data are properly aligned */
00200                 X = (const md5_word_t *)data;
00201             } else {
00202                 /* not aligned */
00203                 memcpy(xbuf, data, 64);
00204                 X = xbuf;
00205             }
00206         }
00207 #endif
00208 #if BYTE_ORDER == 0
00209         else                    /* dynamic big-endian */
00210 #endif
00211 #if BYTE_ORDER >= 0             /* big-endian */
00212         {
00213             /*
00214              * On big-endian machines, we must arrange the bytes in the
00215              * right order.
00216              */
00217             const md5_byte_t *xp = data;
00218             int i;
00219 
00220 #  if BYTE_ORDER == 0
00221             X = xbuf;           /* (dynamic only) */
00222 #  else
00223 #    define xbuf X              /* (static only) */
00224 #  endif
00225             for (i = 0; i < 16; ++i, xp += 4)
00226                 xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
00227         }
00228 #endif
00229     }
00230 
00231 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00232 
00233     /* Round 1. */
00234     /* Let [abcd k s i] denote the operation
00235        a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
00236 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00237 #define SET(a, b, c, d, k, s, Ti)\
00238   t = a + F(b,c,d) + X[k] + Ti;\
00239   a = ROTATE_LEFT(t, s) + b
00240     /* Do the following 16 operations. */
00241     SET(a, b, c, d,  0,  7,  T1);
00242     SET(d, a, b, c,  1, 12,  T2);
00243     SET(c, d, a, b,  2, 17,  T3);
00244     SET(b, c, d, a,  3, 22,  T4);
00245     SET(a, b, c, d,  4,  7,  T5);
00246     SET(d, a, b, c,  5, 12,  T6);
00247     SET(c, d, a, b,  6, 17,  T7);
00248     SET(b, c, d, a,  7, 22,  T8);
00249     SET(a, b, c, d,  8,  7,  T9);
00250     SET(d, a, b, c,  9, 12, T10);
00251     SET(c, d, a, b, 10, 17, T11);
00252     SET(b, c, d, a, 11, 22, T12);
00253     SET(a, b, c, d, 12,  7, T13);
00254     SET(d, a, b, c, 13, 12, T14);
00255     SET(c, d, a, b, 14, 17, T15);
00256     SET(b, c, d, a, 15, 22, T16);
00257 #undef SET
00258 
00259      /* Round 2. */
00260      /* Let [abcd k s i] denote the operation
00261           a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
00262 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00263 #define SET(a, b, c, d, k, s, Ti)\
00264   t = a + G(b,c,d) + X[k] + Ti;\
00265   a = ROTATE_LEFT(t, s) + b
00266      /* Do the following 16 operations. */
00267     SET(a, b, c, d,  1,  5, T17);
00268     SET(d, a, b, c,  6,  9, T18);
00269     SET(c, d, a, b, 11, 14, T19);
00270     SET(b, c, d, a,  0, 20, T20);
00271     SET(a, b, c, d,  5,  5, T21);
00272     SET(d, a, b, c, 10,  9, T22);
00273     SET(c, d, a, b, 15, 14, T23);
00274     SET(b, c, d, a,  4, 20, T24);
00275     SET(a, b, c, d,  9,  5, T25);
00276     SET(d, a, b, c, 14,  9, T26);
00277     SET(c, d, a, b,  3, 14, T27);
00278     SET(b, c, d, a,  8, 20, T28);
00279     SET(a, b, c, d, 13,  5, T29);
00280     SET(d, a, b, c,  2,  9, T30);
00281     SET(c, d, a, b,  7, 14, T31);
00282     SET(b, c, d, a, 12, 20, T32);
00283 #undef SET
00284 
00285      /* Round 3. */
00286      /* Let [abcd k s t] denote the operation
00287           a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
00288 #define H(x, y, z) ((x) ^ (y) ^ (z))
00289 #define SET(a, b, c, d, k, s, Ti)\
00290   t = a + H(b,c,d) + X[k] + Ti;\
00291   a = ROTATE_LEFT(t, s) + b
00292      /* Do the following 16 operations. */
00293     SET(a, b, c, d,  5,  4, T33);
00294     SET(d, a, b, c,  8, 11, T34);
00295     SET(c, d, a, b, 11, 16, T35);
00296     SET(b, c, d, a, 14, 23, T36);
00297     SET(a, b, c, d,  1,  4, T37);
00298     SET(d, a, b, c,  4, 11, T38);
00299     SET(c, d, a, b,  7, 16, T39);
00300     SET(b, c, d, a, 10, 23, T40);
00301     SET(a, b, c, d, 13,  4, T41);
00302     SET(d, a, b, c,  0, 11, T42);
00303     SET(c, d, a, b,  3, 16, T43);
00304     SET(b, c, d, a,  6, 23, T44);
00305     SET(a, b, c, d,  9,  4, T45);
00306     SET(d, a, b, c, 12, 11, T46);
00307     SET(c, d, a, b, 15, 16, T47);
00308     SET(b, c, d, a,  2, 23, T48);
00309 #undef SET
00310 
00311      /* Round 4. */
00312      /* Let [abcd k s t] denote the operation
00313           a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
00314 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00315 #define SET(a, b, c, d, k, s, Ti)\
00316   t = a + I(b,c,d) + X[k] + Ti;\
00317   a = ROTATE_LEFT(t, s) + b
00318      /* Do the following 16 operations. */
00319     SET(a, b, c, d,  0,  6, T49);
00320     SET(d, a, b, c,  7, 10, T50);
00321     SET(c, d, a, b, 14, 15, T51);
00322     SET(b, c, d, a,  5, 21, T52);
00323     SET(a, b, c, d, 12,  6, T53);
00324     SET(d, a, b, c,  3, 10, T54);
00325     SET(c, d, a, b, 10, 15, T55);
00326     SET(b, c, d, a,  1, 21, T56);
00327     SET(a, b, c, d,  8,  6, T57);
00328     SET(d, a, b, c, 15, 10, T58);
00329     SET(c, d, a, b,  6, 15, T59);
00330     SET(b, c, d, a, 13, 21, T60);
00331     SET(a, b, c, d,  4,  6, T61);
00332     SET(d, a, b, c, 11, 10, T62);
00333     SET(c, d, a, b,  2, 15, T63);
00334     SET(b, c, d, a,  9, 21, T64);
00335 #undef SET
00336 
00337      /* Then perform the following additions. (That is increment each
00338         of the four registers by the value it had before this block
00339         was started.) */
00340     pms->abcd[0] += a;
00341     pms->abcd[1] += b;
00342     pms->abcd[2] += c;
00343     pms->abcd[3] += d;
00344 }
00345 
00346 AREXPORT void
00347 md5_init(md5_state_t *pms)
00348 {
00349     pms->count[0] = pms->count[1] = 0;
00350     pms->abcd[0] = 0x67452301;
00351     pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
00352     pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
00353     pms->abcd[3] = 0x10325476;
00354 }
00355 
00356 AREXPORT void
00357 md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
00358 {
00359     const md5_byte_t *p = data;
00360     int left = nbytes;
00361     int offset = (pms->count[0] >> 3) & 63;
00362     md5_word_t nbits = (md5_word_t)(nbytes << 3);
00363 
00364     if (nbytes <= 0)
00365         return;
00366 
00367     /* Update the message length. */
00368     pms->count[1] += nbytes >> 29;
00369     pms->count[0] += nbits;
00370     if (pms->count[0] < nbits)
00371         pms->count[1]++;
00372 
00373     /* Process an initial partial block. */
00374     if (offset) {
00375         int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
00376 
00377         memcpy(pms->buf + offset, p, copy);
00378         if (offset + copy < 64)
00379             return;
00380         p += copy;
00381         left -= copy;
00382         md5_process(pms, pms->buf);
00383     }
00384 
00385     /* Process full blocks. */
00386     for (; left >= 64; p += 64, left -= 64)
00387         md5_process(pms, p);
00388 
00389     /* Process a final partial block. */
00390     if (left)
00391         memcpy(pms->buf, p, left);
00392 }
00393 
00394 AREXPORT void
00395 md5_finish(md5_state_t *pms, md5_byte_t digest[16])
00396 {
00397     static const md5_byte_t pad[64] = {
00398         0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00399         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00400         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00401         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00402     };
00403     md5_byte_t data[8];
00404     int i;
00405 
00406     /* Save the length before padding. */
00407     for (i = 0; i < 8; ++i)
00408         data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
00409     /* Pad to 56 bytes mod 64. */
00410     md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
00411     /* Append the length. */
00412     md5_append(pms, data, 8);
00413     for (i = 0; i < 16; ++i)
00414         digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
00415 }

Generated on Tue Feb 20 10:51:50 2007 for ArNetworking by  doxygen 1.4.0