llmd5.cpp

Go to the documentation of this file.
00001 
00031 // llMD5.CC - source code for the C++/object oriented translation and 
00032 //          modification of MD5.
00033 //
00034 // Adapted to Linden Lab by Frank Filipanits, 6/25/2002
00035 // Fixed potential memory leak, James Cook, 6/27/2002
00036 
00037 // Translation and modification (c) 1995 by Mordechai T. Abzug 
00038 
00039 // This translation/ modification is provided "as is," without express or 
00040 // implied warranty of any kind.
00041 
00042 // The translator/ modifier does not claim (1) that MD5 will do what you think 
00043 // it does; (2) that this translation/ modification is accurate; or (3) that 
00044 // this software is "merchantible."  (Language for this disclaimer partially 
00045 // copied from the disclaimer below).
00046 
00047 /* based on:
00048 
00049    MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
00050    MDDRIVER.C - test driver for MD2, MD4 and MD5
00051 
00052 
00053    Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
00054 rights reserved.
00055 
00056 License to copy and use this software is granted provided that it
00057 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00058 Algorithm" in all material mentioning or referencing this software
00059 or this function.
00060 
00061 License is also granted to make and use derivative works provided
00062 that such works are identified as "derived from the RSA Data
00063 Security, Inc. MD5 Message-Digest Algorithm" in all material
00064 mentioning or referencing the derived work.
00065 
00066 RSA Data Security, Inc. makes no representations concerning either
00067 the merchantability of this software or the suitability of this
00068 software for any particular purpose. It is provided "as is"
00069 without express or implied warranty of any kind.
00070 
00071 These notices must be retained in any copies of any part of this
00072 documentation and/or software.
00073 
00074  */
00075 
00076 
00077 
00078 
00079 
00080 #include "linden_common.h"
00081 
00082 #include "llmd5.h"
00083 
00084 #include <cassert>
00085 
00086 // how many bytes to grab at a time when checking files
00087 const int LLMD5::BLOCK_LEN = 4096;
00088 
00089 
00090 // LLMD5 simple initialization method
00091 
00092 LLMD5::LLMD5()
00093 {
00094   init();
00095 }
00096 
00097 
00098 
00099 
00100 // MD5 block update operation. Continues an MD5 message-digest
00101 // operation, processing another message block, and updating the
00102 // context.
00103 
00104 void LLMD5::update (const uint1 *input, const uint4 input_length) {
00105 
00106   uint4 input_index, buffer_index;
00107   uint4 buffer_space;                // how much space is left in buffer
00108 
00109   if (finalized){  // so we can't update!
00110           std::cerr << "LLMD5::update:  Can't update a finalized digest!" << std::endl;
00111     return;
00112   }
00113 
00114   // Compute number of bytes mod 64
00115   buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
00116 
00117   // Update number of bits
00118   if (  (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
00119     count[1]++;
00120 
00121   count[1] += ((uint4)input_length >> 29);
00122 
00123 
00124   buffer_space = 64 - buffer_index;  // how much space is left in buffer
00125 
00126   // Transform as many times as possible.
00127   if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
00128     // fill the rest of the buffer and transform
00129     memcpy(     /* Flawfinder: ignore */
00130                 buffer + buffer_index,
00131                 input,
00132                 buffer_space);
00133     transform (buffer);
00134 
00135     // now, transform each 64-byte piece of the input, bypassing the buffer
00136   if (input == NULL || input_length == 0){
00137         std::cerr << "LLMD5::update:  Invalid input!" << std::endl;
00138         return;
00139   }
00140 
00141     for (input_index = buffer_space; input_index + 63 < input_length; 
00142          input_index += 64)
00143       transform (input+input_index);
00144 
00145     buffer_index = 0;  // so we can buffer remaining
00146   }
00147   else
00148     input_index=0;     // so we can buffer the whole input
00149 
00150 
00151   // and here we do the buffering:
00152   memcpy(buffer+buffer_index, input+input_index, input_length-input_index);             /* Flawfinder: ignore */
00153 }
00154 
00155 
00156 
00157 // MD5 update for files.
00158 // Like above, except that it works on files (and uses above as a primitive.)
00159 
00160 void LLMD5::update(FILE* file){
00161 
00162   unsigned char buffer[BLOCK_LEN];              /* Flawfinder: ignore */
00163   int len;
00164 
00165   while ( (len=(int)fread(buffer, 1, BLOCK_LEN, file)) )
00166     update(buffer, len);
00167 
00168   fclose (file);
00169 
00170 }
00171 
00172 
00173 
00174 
00175 
00176 
00177 // MD5 update for istreams.
00178 // Like update for files; see above.
00179 
00180 void LLMD5::update(std::istream& stream){
00181 
00182   unsigned char buffer[BLOCK_LEN];              /* Flawfinder: ignore */
00183   int len;
00184 
00185   while (stream.good()){
00186     stream.read( (char*)buffer, BLOCK_LEN);     /* Flawfinder: ignore */                // note that return value of read is unusable.
00187     len=stream.gcount();
00188     update(buffer, len);
00189   }
00190 
00191 }
00192 
00193 
00194 
00195 
00196 
00197 // MD5 finalization. Ends an MD5 message-digest operation, writing the
00198 // the message digest and zeroizing the context.
00199 
00200 
00201 void LLMD5::finalize (){
00202 
00203   unsigned char bits[8];                /* Flawfinder: ignore */
00204   unsigned int index, padLen;
00205   static uint1 PADDING[64]={
00206     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00207     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00208     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00209     };
00210 
00211   if (finalized){
00212     std::cerr << "LLMD5::finalize:  Already finalized this digest!" << std::endl;
00213     return;
00214   }
00215 
00216   // Save number of bits
00217   encode (bits, count, 8);
00218 
00219   // Pad out to 56 mod 64.
00220   index = (uint4) ((count[0] >> 3) & 0x3f);
00221   padLen = (index < 56) ? (56 - index) : (120 - index);
00222   update (PADDING, padLen);
00223 
00224   // Append length (before padding)
00225   update (bits, 8);
00226 
00227   // Store state in digest
00228   encode (digest, state, 16);
00229 
00230   // Zeroize sensitive information
00231   memset (buffer, 0, sizeof(*buffer));
00232 
00233   finalized=1;
00234 
00235 }
00236 
00237 
00238 
00239 
00240 LLMD5::LLMD5(FILE *file){
00241 
00242   init();  // must be called be all constructors
00243   update(file);
00244   finalize ();
00245 }
00246 
00247 
00248 
00249 
00250 LLMD5::LLMD5(std::istream& stream){
00251 
00252   init();  // must called by all constructors
00253   update (stream);
00254   finalize();
00255 }
00256 
00257 // Digest a string of the format ("%s:%i" % (s, number))
00258 LLMD5::LLMD5(const unsigned char *string, const unsigned int number)
00259 {
00260         const char *colon = ":";
00261         char tbuf[16];          /* Flawfinder: ignore */
00262         init();
00263         update(string, (U32)strlen((const char *) string));             /* Flawfinder: ignore */
00264         update((const unsigned char *) colon, (U32)strlen(colon));              /* Flawfinder: ignore */
00265         snprintf(tbuf, sizeof(tbuf), "%i", number);     /* Flawfinder: ignore */
00266         update((const unsigned char *) tbuf, (U32)strlen(tbuf));        /* Flawfinder: ignore */
00267         finalize();
00268 }
00269 
00270 // Digest a string
00271 LLMD5::LLMD5(const unsigned char *s)
00272 {
00273         init();
00274         update(s, (U32)strlen((const char *) s));               /* Flawfinder: ignore */
00275         finalize();
00276 }
00277 
00278 void LLMD5::raw_digest(unsigned char *s)
00279 {
00280         if (!finalized)
00281         {
00282                 std::cerr << "LLMD5::raw_digest:  Can't get digest if you haven't "<<
00283                         "finalized the digest!" << std::endl;
00284                 s[0] = '\0';
00285                 return;
00286         }
00287 
00288         memcpy(s, digest, 16);          /* Flawfinder: ignore */
00289         return;
00290 }
00291 
00292 
00293 
00294 void LLMD5::hex_digest(char *s)
00295 {
00296         int i;
00297 
00298         if (!finalized)
00299         {
00300                 std::cerr << "LLMD5::hex_digest:  Can't get digest if you haven't "<<
00301                   "finalized the digest!" <<std::endl;
00302                 s[0] = '\0';
00303                 return;
00304         }
00305 
00306         for (i=0; i<16; i++)
00307         {
00308                 sprintf(s+i*2, "%02x", digest[i]);              /* Flawfinder: ignore */
00309         }
00310 
00311         s[32]='\0';
00312 
00313         return;
00314 }
00315 
00316 
00317 
00318 
00319 
00320 std::ostream& operator<<(std::ostream &stream, LLMD5 context)
00321 {
00322         char s[33];             /* Flawfinder: ignore */
00323         context.hex_digest(s);
00324         stream << s;
00325         return stream;
00326 }
00327 
00328 
00329 
00330 
00331 // PRIVATE METHODS:
00332 
00333 
00334 
00335 void LLMD5::init(){
00336   finalized=0;  // we just started!
00337 
00338   // Nothing counted, so count=0
00339   count[0] = 0;
00340   count[1] = 0;
00341 
00342   // Load magic initialization constants.
00343   state[0] = 0x67452301;
00344   state[1] = 0xefcdab89;
00345   state[2] = 0x98badcfe;
00346   state[3] = 0x10325476;
00347 }
00348 
00349 
00350 
00351 // Constants for MD5Transform routine.
00352 // Although we could use C++ style constants, defines are actually better,
00353 // since they let us easily evade scope clashes.
00354 
00355 #define S11 7
00356 #define S12 12
00357 #define S13 17
00358 #define S14 22
00359 #define S21 5
00360 #define S22 9
00361 #define S23 14
00362 #define S24 20
00363 #define S31 4
00364 #define S32 11
00365 #define S33 16
00366 #define S34 23
00367 #define S41 6
00368 #define S42 10
00369 #define S43 15
00370 #define S44 21
00371 
00372 // #defines are faster then inline, etc because the compiler is not required to inline.
00373 // Timing tests prove that this works ~40% faster on win with msvc++2k3 over using static inline.
00374 
00375 /* F, G, H and I are basic MD5 functions.
00376  */
00377 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
00378 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
00379 #define H(x, y, z) ((x) ^ (y) ^ (z))
00380 #define I(x, y, z) ((y) ^ ((x) | (~z)))
00381 
00382 /* ROTATE_LEFT rotates x left n bits.
00383  */
00384 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
00385 
00386 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00387 Rotation is separate from addition to prevent recomputation.
00388  */
00389 #define FF(a, b, c, d, x, s, ac) { \
00390  (a) += F ((b), (c), (d)) + (x) + (U32)(ac); \
00391  (a) = ROTATE_LEFT ((a), (s)); \
00392  (a) += (b); \
00393   }
00394 #define GG(a, b, c, d, x, s, ac) { \
00395  (a) += G ((b), (c), (d)) + (x) + (U32)(ac); \
00396  (a) = ROTATE_LEFT ((a), (s)); \
00397  (a) += (b); \
00398   }
00399 #define HH(a, b, c, d, x, s, ac) { \
00400  (a) += H ((b), (c), (d)) + (x) + (U32)(ac); \
00401  (a) = ROTATE_LEFT ((a), (s)); \
00402  (a) += (b); \
00403   }
00404 #define II(a, b, c, d, x, s, ac) { \
00405  (a) += I ((b), (c), (d)) + (x) + (U32)(ac); \
00406  (a) = ROTATE_LEFT ((a), (s)); \
00407  (a) += (b); \
00408   }
00409 
00410 
00411 
00412 // LLMD5 basic transformation. Transforms state based on block.
00413 void LLMD5::transform (const U8 block[64]){
00414 
00415   uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00416 
00417   decode (x, block, 64);
00418 
00419   assert(!finalized);  // not just a user error, since the method is private
00420 
00421   /* Round 1 */
00422   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
00423   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
00424   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
00425   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
00426   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
00427   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
00428   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
00429   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
00430   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
00431   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00432   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00433   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00434   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00435   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00436   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00437   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00438 
00439  /* Round 2 */
00440   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00441   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00442   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00443   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00444   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00445   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00446   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00447   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00448   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00449   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00450   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00451   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00452   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00453   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00454   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00455   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00456 
00457   /* Round 3 */
00458   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00459   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00460   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00461   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00462   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00463   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00464   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00465   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00466   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00467   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00468   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00469   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00470   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00471   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00472   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00473   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00474 
00475   /* Round 4 */
00476   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00477   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00478   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00479   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00480   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00481   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00482   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00483   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00484   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00485   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00486   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00487   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00488   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00489   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00490   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00491   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00492 
00493   state[0] += a;
00494   state[1] += b;
00495   state[2] += c;
00496   state[3] += d;
00497 
00498   // Zeroize sensitive information.
00499   memset ( (uint1 *) x, 0, sizeof(x));
00500 
00501 }
00502 
00503 
00504 
00505 // Encodes input (UINT4) into output (unsigned char). Assumes len is
00506 // a multiple of 4.
00507 void LLMD5::encode (uint1 *output, const uint4 *input, const uint4 len) {
00508 
00509   unsigned int i, j;
00510 
00511   for (i = 0, j = 0; j < len; i++, j += 4) {
00512     output[j]   = (uint1)  (input[i] & 0xff);
00513     output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
00514     output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
00515     output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
00516   }
00517 }
00518 
00519 
00520 
00521 
00522 // Decodes input (unsigned char) into output (UINT4). Assumes len is
00523 // a multiple of 4.
00524 void LLMD5::decode (uint4 *output, const uint1 *input, const uint4 len){
00525 
00526   unsigned int i, j;
00527 
00528   for (i = 0, j = 0; j < len; i++, j += 4)
00529     output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
00530       (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
00531 }

Generated on Thu Jul 1 06:08:51 2010 for Second Life Viewer by  doxygen 1.4.7