md5.cpp

Go to the documentation of this file.
00001 /* $Id: md5.cpp 12971 2008-05-06 15:11:33Z rubidium $ */
00002 
00005 /*
00006   Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
00007 
00008   This software is provided 'as-is', without any express or implied
00009   warranty.  In no event will the authors be held liable for any damages
00010   arising from the use of this software.
00011 
00012   Permission is granted to anyone to use this software for any purpose,
00013   including commercial applications, and to alter it and redistribute it
00014   freely, subject to the following restrictions:
00015 
00016   1. The origin of this software must not be misrepresented; you must not
00017      claim that you wrote the original software. If you use this software
00018      in a product, an acknowledgment in the product documentation would be
00019      appreciated but is not required.
00020   2. Altered source versions must be plainly marked as such, and must not be
00021      misrepresented as being the original software.
00022   3. This notice may not be removed or altered from any source distribution.
00023 
00024   L. Peter Deutsch
00025   ghost@aladdin.com
00026 
00027  */
00028 
00029 /*
00030   Independent implementation of MD5 (RFC 1321).
00031 
00032   This code implements the MD5 Algorithm defined in RFC 1321, whose
00033   text is available at
00034   http://www.ietf.org/rfc/rfc1321.txt
00035   The code is derived from the text of the RFC, including the test suite
00036   (section A.5) but excluding the rest of Appendix A.  It does not include
00037   any code or documentation that is identified in the RFC as being
00038   copyrighted.
00039 
00040   The original and principal author of md5.c is L. Peter Deutsch
00041   <ghost@aladdin.com>.  Other authors are noted in the change history
00042   that follows (in reverse chronological order):
00043 
00044   2007-12-24 Changed to C++ and adapted to OpenTTD source
00045   2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
00046              either statically or dynamically; added missing #include <string.h>
00047              in library.
00048   2002-03-11 lpd Corrected argument list for main(), and added int return
00049              type, in test program and T value program.
00050   2002-02-21 lpd Added missing #include <stdio.h> in test program.
00051   2000-07-03 lpd Patched to eliminate warnings about "constant is
00052              unsigned in ANSI C, signed in traditional"; made test program
00053              self-checking.
00054   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
00055   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
00056   1999-05-03 lpd Original version.
00057  */
00058 
00059 #include "stdafx.h"
00060 #include "core/bitmath_func.hpp"
00061 #include "core/endian_func.hpp"
00062 #include "md5.h"
00063 
00064 #define T_MASK ((uint32)~0)
00065 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
00066 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
00067 #define T3    0x242070db
00068 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
00069 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
00070 #define T6    0x4787c62a
00071 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
00072 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
00073 #define T9    0x698098d8
00074 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
00075 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
00076 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
00077 #define T13    0x6b901122
00078 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
00079 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
00080 #define T16    0x49b40821
00081 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
00082 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
00083 #define T19    0x265e5a51
00084 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
00085 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
00086 #define T22    0x02441453
00087 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
00088 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
00089 #define T25    0x21e1cde6
00090 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
00091 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
00092 #define T28    0x455a14ed
00093 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
00094 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
00095 #define T31    0x676f02d9
00096 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
00097 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
00098 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
00099 #define T35    0x6d9d6122
00100 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
00101 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
00102 #define T38    0x4bdecfa9
00103 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
00104 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
00105 #define T41    0x289b7ec6
00106 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
00107 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
00108 #define T44    0x04881d05
00109 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
00110 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
00111 #define T47    0x1fa27cf8
00112 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
00113 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
00114 #define T50    0x432aff97
00115 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
00116 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
00117 #define T53    0x655b59c3
00118 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
00119 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
00120 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
00121 #define T57    0x6fa87e4f
00122 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
00123 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
00124 #define T60    0x4e0811a1
00125 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
00126 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
00127 #define T63    0x2ad7d2bb
00128 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
00129 
00130 static inline void Md5Set1(const uint32 *X, uint32 *a, const uint32 *b, const uint32 *c, const uint32 *d, const uint8 k, const uint8 s, const uint32 Ti)
00131 {
00132   uint32 t = (*b & *c) | (~*b & *d);
00133   t += *a + X[k] + Ti;
00134   *a = ROL(t, s) + *b;
00135 }
00136 
00137 static inline void Md5Set2(const uint32 *X, uint32 *a, const uint32 *b, const uint32 *c, const uint32 *d, const uint8 k, const uint8 s, const uint32 Ti)
00138 {
00139   uint32 t = (*b & *d) | (*c & ~*d);
00140   t += *a + X[k] + Ti;
00141   *a = ROL(t, s) + *b;
00142 }
00143 
00144 
00145 static inline void Md5Set3(const uint32 *X, uint32 *a, const uint32 *b, const uint32 *c, const uint32 *d, const uint8 k, const uint8 s, const uint32 Ti)
00146 {
00147   uint32 t = *b ^ *c ^ *d;
00148   t += *a + X[k] + Ti;
00149   *a = ROL(t, s) + *b;
00150 }
00151 
00152 static inline void Md5Set4(const uint32 *X, uint32 *a, const uint32 *b, const uint32 *c, const uint32 *d, const uint8 k, const uint8 s, const uint32 Ti)
00153 {
00154   uint32 t = *c ^ (*b | ~*d);
00155   t += *a + X[k] + Ti;
00156   *a = ROL(t, s) + *b;
00157 }
00158 
00159 Md5::Md5()
00160 {
00161   count[0] = 0;
00162   count[1] = 0;
00163   abcd[0] = 0x67452301;
00164   abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
00165   abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
00166   abcd[3] = 0x10325476;
00167 }
00168 
00169 void Md5::Process(const uint8 *data /*[64]*/)
00170 {
00171   uint32 a = this->abcd[0];
00172   uint32 b = this->abcd[1];
00173   uint32 c = this->abcd[2];
00174   uint32 d = this->abcd[3];
00175 
00176   uint32 X[16];
00177 
00178   /* Convert the uint8 data to uint32 LE */
00179   uint32 *px = (uint32 *)data;
00180   for (uint i = 0; i < 16; i++) {
00181     X[i] = TO_LE32(*px);
00182     px++;
00183   }
00184 
00185   /* Round 1. */
00186   Md5Set1(X, &a, &b, &c, &d,  0,  7,  T1);
00187   Md5Set1(X, &d, &a, &b, &c,  1, 12,  T2);
00188   Md5Set1(X, &c, &d, &a, &b,  2, 17,  T3);
00189   Md5Set1(X, &b, &c, &d, &a,  3, 22,  T4);
00190   Md5Set1(X, &a, &b, &c, &d,  4,  7,  T5);
00191   Md5Set1(X, &d, &a, &b, &c,  5, 12,  T6);
00192   Md5Set1(X, &c, &d, &a, &b,  6, 17,  T7);
00193   Md5Set1(X, &b, &c, &d, &a,  7, 22,  T8);
00194   Md5Set1(X, &a, &b, &c, &d,  8,  7,  T9);
00195   Md5Set1(X, &d, &a, &b, &c,  9, 12, T10);
00196   Md5Set1(X, &c, &d, &a, &b, 10, 17, T11);
00197   Md5Set1(X, &b, &c, &d, &a, 11, 22, T12);
00198   Md5Set1(X, &a, &b, &c, &d, 12,  7, T13);
00199   Md5Set1(X, &d, &a, &b, &c, 13, 12, T14);
00200   Md5Set1(X, &c, &d, &a, &b, 14, 17, T15);
00201   Md5Set1(X, &b, &c, &d, &a, 15, 22, T16);
00202 
00203   /* Round 2. */
00204   Md5Set2(X, &a, &b, &c, &d,  1,  5, T17);
00205   Md5Set2(X, &d, &a, &b, &c,  6,  9, T18);
00206   Md5Set2(X, &c, &d, &a, &b, 11, 14, T19);
00207   Md5Set2(X, &b, &c, &d, &a,  0, 20, T20);
00208   Md5Set2(X, &a, &b, &c, &d,  5,  5, T21);
00209   Md5Set2(X, &d, &a, &b, &c, 10,  9, T22);
00210   Md5Set2(X, &c, &d, &a, &b, 15, 14, T23);
00211   Md5Set2(X, &b, &c, &d, &a,  4, 20, T24);
00212   Md5Set2(X, &a, &b, &c, &d,  9,  5, T25);
00213   Md5Set2(X, &d, &a, &b, &c, 14,  9, T26);
00214   Md5Set2(X, &c, &d, &a, &b,  3, 14, T27);
00215   Md5Set2(X, &b, &c, &d, &a,  8, 20, T28);
00216   Md5Set2(X, &a, &b, &c, &d, 13,  5, T29);
00217   Md5Set2(X, &d, &a, &b, &c,  2,  9, T30);
00218   Md5Set2(X, &c, &d, &a, &b,  7, 14, T31);
00219   Md5Set2(X, &b, &c, &d, &a, 12, 20, T32);
00220 
00221   /* Round 3. */
00222   Md5Set3(X, &a, &b, &c, &d,  5,  4, T33);
00223   Md5Set3(X, &d, &a, &b, &c,  8, 11, T34);
00224   Md5Set3(X, &c, &d, &a, &b, 11, 16, T35);
00225   Md5Set3(X, &b, &c, &d, &a, 14, 23, T36);
00226   Md5Set3(X, &a, &b, &c, &d,  1,  4, T37);
00227   Md5Set3(X, &d, &a, &b, &c,  4, 11, T38);
00228   Md5Set3(X, &c, &d, &a, &b,  7, 16, T39);
00229   Md5Set3(X, &b, &c, &d, &a, 10, 23, T40);
00230   Md5Set3(X, &a, &b, &c, &d, 13,  4, T41);
00231   Md5Set3(X, &d, &a, &b, &c,  0, 11, T42);
00232   Md5Set3(X, &c, &d, &a, &b,  3, 16, T43);
00233   Md5Set3(X, &b, &c, &d, &a,  6, 23, T44);
00234   Md5Set3(X, &a, &b, &c, &d,  9,  4, T45);
00235   Md5Set3(X, &d, &a, &b, &c, 12, 11, T46);
00236   Md5Set3(X, &c, &d, &a, &b, 15, 16, T47);
00237   Md5Set3(X, &b, &c, &d, &a,  2, 23, T48);
00238 
00239   /* Round 4. */
00240   Md5Set4(X, &a, &b, &c, &d,  0,  6, T49);
00241   Md5Set4(X, &d, &a, &b, &c,  7, 10, T50);
00242   Md5Set4(X, &c, &d, &a, &b, 14, 15, T51);
00243   Md5Set4(X, &b, &c, &d, &a,  5, 21, T52);
00244   Md5Set4(X, &a, &b, &c, &d, 12,  6, T53);
00245   Md5Set4(X, &d, &a, &b, &c,  3, 10, T54);
00246   Md5Set4(X, &c, &d, &a, &b, 10, 15, T55);
00247   Md5Set4(X, &b, &c, &d, &a,  1, 21, T56);
00248   Md5Set4(X, &a, &b, &c, &d,  8,  6, T57);
00249   Md5Set4(X, &d, &a, &b, &c, 15, 10, T58);
00250   Md5Set4(X, &c, &d, &a, &b,  6, 15, T59);
00251   Md5Set4(X, &b, &c, &d, &a, 13, 21, T60);
00252   Md5Set4(X, &a, &b, &c, &d,  4,  6, T61);
00253   Md5Set4(X, &d, &a, &b, &c, 11, 10, T62);
00254   Md5Set4(X, &c, &d, &a, &b,  2, 15, T63);
00255   Md5Set4(X, &b, &c, &d, &a,  9, 21, T64);
00256 
00257   /* Then perform the following additions. (That is increment each
00258    * of the four registers by the value it had before this block
00259    * was started.) */
00260   this->abcd[0] += a;
00261   this->abcd[1] += b;
00262   this->abcd[2] += c;
00263   this->abcd[3] += d;
00264 }
00265 
00266 void Md5::Append(const void *data, const size_t nbytes)
00267 {
00268   const uint8 *p = (const uint8 *)data;
00269   size_t left = nbytes;
00270   const size_t offset = (this->count[0] >> 3) & 63;
00271   const uint32 nbits = (uint32)(nbytes << 3);
00272 
00273   if (nbytes <= 0) return;
00274 
00275   /* Update the message length. */
00276   this->count[1] += (uint32)(nbytes >> 29);
00277   this->count[0] += nbits;
00278 
00279   if (this->count[0] < nbits) this->count[1]++;
00280 
00281   /* Process an initial partial block. */
00282   if (offset) {
00283     size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
00284 
00285     memcpy(this->buf + offset, p, copy);
00286 
00287     if (offset + copy < 64) return;
00288 
00289     p += copy;
00290     left -= copy;
00291     this->Process(this->buf);
00292   }
00293 
00294   /* Process full blocks. */
00295   for (; left >= 64; p += 64, left -= 64) this->Process(p);
00296 
00297   /* Process a final partial block. */
00298   if (left) memcpy(this->buf, p, left);
00299 }
00300 
00301 void Md5::Finish(uint8 digest[16])
00302 {
00303   static const uint8 pad[64] = {
00304     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00305     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00306     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00307     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00308   };
00309   uint8 data[8];
00310   uint i;
00311 
00312   /* Save the length before padding. */
00313   for (i = 0; i < 8; ++i)
00314     data[i] = (uint8)(this->count[i >> 2] >> ((i & 3) << 3));
00315 
00316   /* Pad to 56 bytes mod 64. */
00317   this->Append(pad, ((55 - (this->count[0] >> 3)) & 63) + 1);
00318   /* Append the length. */
00319   this->Append(data, 8);
00320 
00321   for (i = 0; i < 16; ++i)
00322     digest[i] = (uint8)(this->abcd[i >> 2] >> ((i & 3) << 3));
00323 }

Generated on Mon Feb 16 23:12:07 2009 for openttd by  doxygen 1.5.6