blocxx
|
00001 /******************************************************************************* 00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved. 00003 * Copyright (C) 2006, Novell, Inc. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of 00014 * Vintela, Inc., 00015 * nor Novell, Inc., 00016 * nor the names of its contributors or employees may be used to 00017 * endorse or promote products derived from this software without 00018 * specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00030 * POSSIBILITY OF SUCH DAMAGE. 00031 *******************************************************************************/ 00032 00033 00039 #include "blocxx/BLOCXX_config.h" 00040 #include "blocxx/MD5.hpp" 00041 #include "blocxx/String.hpp" 00042 #include "blocxx/ExceptionIds.hpp" 00043 00044 #include <string.h> // for memset 00045 00046 #ifdef BLOCXX_WIN32 00047 #pragma warning (push) 00048 #pragma warning (disable: 4355) 00049 #endif 00050 00051 namespace BLOCXX_NAMESPACE 00052 { 00053 00054 const int MD5HASHHEXLEN = 32; 00055 00056 BLOCXX_DEFINE_EXCEPTION_WITH_ID(MD5); 00058 MD5OStreamBase::MD5OStreamBase(MD5* md5): _buf(md5) {} 00060 MD5StreamBuffer::MD5StreamBuffer(MD5* md5): _md5(md5) {} 00062 int 00063 MD5StreamBuffer::overflow(int c) 00064 { 00065 unsigned char lc = c; 00066 MD5::MD5Update(&(_md5->m_ctx), &lc, 1); 00067 return c; 00068 } 00070 std::streamsize 00071 MD5StreamBuffer::xsputn(const char* s, std::streamsize num) 00072 { 00073 MD5::MD5Update(&(_md5->m_ctx), 00074 reinterpret_cast<const unsigned char*>(s), num); 00075 return num; 00076 } 00078 MD5::MD5() 00079 : MD5OStreamBase(this), std::ostream(&_buf), m_ctx(), m_finished(false) 00080 { 00081 MD5Init(&m_ctx); 00082 } 00084 void 00085 MD5::init(const String& input) 00086 { 00087 m_finished = false; 00088 MD5Init(&m_ctx); 00089 update(input); 00090 } 00092 MD5::MD5(const String& input) 00093 : MD5OStreamBase(this), std::ostream(&_buf), m_ctx(), m_finished(false) 00094 { 00095 MD5Init(&m_ctx); 00096 update(input); 00097 } 00099 void 00100 MD5::update(const String& input) 00101 { 00102 if (m_finished) 00103 { 00104 BLOCXX_THROW(MD5Exception, "Cannot update after a call to toString()"); 00105 } 00106 MD5Update(&m_ctx, reinterpret_cast<const unsigned char*>(input.c_str()), 00107 input.length()); 00108 } 00110 String 00111 MD5::toString() 00112 { 00113 return convertBinToHex(getDigest()); 00114 } 00116 unsigned char* 00117 MD5::getDigest() 00118 { 00119 if (!m_finished) 00120 { 00121 MD5Final(m_digest, &m_ctx); 00122 m_finished = true; 00123 } 00124 return m_digest; 00125 } 00127 String 00128 MD5::convertBinToHex( const unsigned char* sBin) 00129 { 00130 unsigned short i; 00131 unsigned char j; 00132 char Hex[ MD5HASHHEXLEN + 1 ]; 00133 for ( i = 0; i < MD5HASHLEN; i++ ) 00134 { 00135 j = (sBin[i] >> 4) & 0xf; 00136 if ( j <= 9 ) 00137 { 00138 Hex[i*2] = (j + '0'); 00139 } 00140 else 00141 { 00142 Hex[i*2] = (j + 'a' - 10); 00143 } 00144 j = sBin[i] & 0xf; 00145 if ( j <= 9 ) 00146 { 00147 Hex[i*2+1] = (j + '0'); 00148 } 00149 else 00150 { 00151 Hex[i*2+1] = (j + 'a' - 10); 00152 } 00153 }; 00154 Hex[MD5HASHHEXLEN] = '\0'; 00155 return String(Hex); 00156 }; 00157 //A.3 md5c.c 00158 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm 00159 */ 00160 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 00161 rights reserved. 00162 License to copy and use this software is granted provided that it 00163 is identified as the "RSA Data Security, Inc. MD5 Message-Digest 00164 Algorithm" in all material mentioning or referencing this software 00165 or this function. 00166 License is also granted to make and use derivative works provided 00167 that such works are identified as "derived from the RSA Data 00168 Security, Inc. MD5 Message-Digest Algorithm" in all material 00169 mentioning or referencing the derived work. 00170 RSA Data Security, Inc. makes no representations concerning either 00171 the merchantability of this software or the suitability of this 00172 software for any particular purpose. It is provided "as is" 00173 without express or implied warranty of any kind. 00174 These notices must be retained in any copies of any part of this 00175 documentation and/or software. 00176 */ 00177 /* POINTER defines a generic pointer type */ 00178 typedef unsigned char *POINTER; 00179 /* Constants for MD5Transform routine. 00180 */ 00181 #define S11 7 00182 #define S12 12 00183 #define S13 17 00184 #define S14 22 00185 #define S21 5 00186 #define S22 9 00187 #define S23 14 00188 #define S24 20 00189 #define S31 4 00190 #define S32 11 00191 #define S33 16 00192 #define S34 23 00193 #define S41 6 00194 #define S42 10 00195 #define S43 15 00196 #define S44 21 00197 static void MD5Transform(UInt32*, const unsigned char*); 00198 static void Encode(unsigned char *, UInt32 *, UInt32); 00199 static void Decode(UInt32 *, const unsigned char *, UInt32); 00200 //static void MD5_memcpy(POINTER, POINTER, UInt32); 00201 //static void MD5_memset(POINTER, Int32, UInt32); 00202 static unsigned char PADDING[64] = { 00203 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00204 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00205 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00206 }; 00207 /* F, G, H and I are basic MD5 functions. 00208 */ 00209 #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 00210 #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) 00211 #define H(x, y, z) ((x) ^ (y) ^ (z)) 00212 #define I(x, y, z) ((y) ^ ((x) | (~z))) 00213 /* ROTATE_LEFT rotates x left n bits. 00214 */ 00215 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 00216 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 00217 Rotation is separate from addition to prevent recomputation. 00218 */ 00219 #define FF(a, b, c, d, x, s, ac) { \ 00220 (a) += F ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \ 00221 (a) = ROTATE_LEFT ((a), (s)); \ 00222 (a) += (b); \ 00223 } 00224 #define GG(a, b, c, d, x, s, ac) { \ 00225 (a) += G ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \ 00226 (a) = ROTATE_LEFT ((a), (s)); \ 00227 (a) += (b); \ 00228 } 00229 #define HH(a, b, c, d, x, s, ac) { \ 00230 (a) += H ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \ 00231 (a) = ROTATE_LEFT ((a), (s)); \ 00232 (a) += (b); \ 00233 } 00234 #define II(a, b, c, d, x, s, ac) { \ 00235 (a) += I ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \ 00236 (a) = ROTATE_LEFT ((a), (s)); \ 00237 (a) += (b); \ 00238 } 00239 /* MD5 initialization. Begins an MD5 operation, writing a new context. 00240 */ // STATIC 00241 void 00242 MD5::MD5Init(MD5_CTX* context) 00243 { 00244 context->count[0] = context->count[1] = 0; 00245 /* Load magic initialization constants. 00246 */ 00247 context->state[0] = 0x67452301; 00248 context->state[1] = 0xefcdab89; 00249 context->state[2] = 0x98badcfe; 00250 context->state[3] = 0x10325476; 00251 } 00252 /* MD5 block update operation. Continues an MD5 message-digest 00253 operation, processing another message block, and updating the 00254 context. 00255 */ // STATIC 00256 void 00257 MD5::MD5Update(MD5_CTX* context, const unsigned char* input, 00258 UInt32 inputLen) 00259 { 00260 UInt32 i, index, partLen; 00261 /* Compute number of bytes mod 64 */ 00262 index = ((context->count[0] >> 3) & 0x3F); 00263 /* Update number of bits */ 00264 if ((context->count[0] += (inputLen << 3)) < (inputLen << 3)) 00265 { 00266 context->count[1]++; 00267 } 00268 context->count[1] += (inputLen >> 29); 00269 partLen = 64 - index; 00270 /* Transform as many times as possible. 00271 */ 00272 if (inputLen >= partLen) 00273 { 00274 memcpy(static_cast<POINTER>(&context->buffer[index]), 00275 static_cast<const unsigned char*>(input), partLen); 00276 MD5Transform (context->state, context->buffer); 00277 for (i = partLen; i + 63 < inputLen; i += 64) 00278 MD5Transform (context->state, &input[i]); 00279 index = 0; 00280 } 00281 else 00282 i = 0; 00283 /* Buffer remaining input */ 00284 memcpy 00285 (static_cast<POINTER>(&context->buffer[index]), 00286 static_cast<const unsigned char*>(&input[i]), 00287 inputLen-i); 00288 } 00289 /* MD5 finalization. Ends an MD5 message-digest operation, writing the 00290 the message digest and zeroizing the context. 00291 */ // STATIC 00292 void 00293 MD5::MD5Final (unsigned char* digest, MD5_CTX* context) 00294 { 00295 unsigned char bits[8]; 00296 UInt32 index, padLen; 00297 /* Save number of bits */ 00298 Encode (bits, context->count, 8); 00299 /* Pad out to 56 mod 64. 00300 */ 00301 index = ((context->count[0] >> 3) & 0x3f); 00302 padLen = (index < 56) ? (56 - index) : (120 - index); 00303 MD5Update (context, PADDING, padLen); 00304 /* Append length (before padding) */ 00305 MD5Update (context, bits, 8); 00306 /* Store state in digest */ 00307 Encode (digest, context->state, 16); 00308 /* Zeroize sensitive information. 00309 */ 00310 memset (reinterpret_cast<POINTER>(context), 0, sizeof (*context)); 00311 } 00312 /* MD5 basic transformation. Transforms state based on block. 00313 */ 00314 static void MD5Transform (UInt32* state, const unsigned char* block) 00315 { 00316 UInt32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 00317 Decode (x, block, 64); 00318 /* Round 1 */ 00319 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ 00320 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ 00321 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ 00322 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ 00323 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ 00324 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ 00325 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ 00326 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ 00327 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ 00328 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ 00329 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 00330 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 00331 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 00332 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 00333 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 00334 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 00335 /* Round 2 */ 00336 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ 00337 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ 00338 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 00339 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ 00340 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ 00341 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ 00342 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 00343 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ 00344 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ 00345 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 00346 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ 00347 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ 00348 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 00349 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ 00350 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ 00351 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 00352 /* Round 3 */ 00353 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ 00354 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ 00355 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 00356 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 00357 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ 00358 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ 00359 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ 00360 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 00361 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 00362 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ 00363 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ 00364 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ 00365 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ 00366 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 00367 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 00368 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ 00369 /* Round 4 */ 00370 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ 00371 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ 00372 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 00373 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ 00374 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 00375 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ 00376 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 00377 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ 00378 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ 00379 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 00380 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ 00381 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 00382 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ 00383 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 00384 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ 00385 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ 00386 state[0] += a; 00387 state[1] += b; 00388 state[2] += c; 00389 state[3] += d; 00390 /* Zeroize sensitive information. */ 00391 memset (reinterpret_cast<POINTER>(x), 0, sizeof (x)); 00392 } 00393 /* Encodes input (UInt32) into output (unsigned char). Assumes len is 00394 a multiple of 4. 00395 */ 00396 static void Encode (unsigned char* output, UInt32* input, UInt32 len) 00397 { 00398 UInt32 i, j; 00399 for (i = 0, j = 0; j < len; i++, j += 4) 00400 { 00401 output[j] = (input[i] & 0xff); 00402 output[j+1] = ((input[i] >> 8) & 0xff); 00403 output[j+2] = ((input[i] >> 16) & 0xff); 00404 output[j+3] = ((input[i] >> 24) & 0xff); 00405 } 00406 } 00407 /* Decodes input (unsigned char) into output (UInt32). Assumes len is 00408 a multiple of 4. 00409 */ 00410 static void Decode (UInt32* output, const unsigned char* input, UInt32 len) 00411 { 00412 UInt32 i, j; 00413 for (i = 0, j = 0; j < len; i++, j += 4) 00414 output[i] = (static_cast<UInt32>(input[j])) | ((static_cast<UInt32>(input[j+1])) << 8) | 00415 ((static_cast<UInt32>(input[j+2])) << 16) | ((static_cast<UInt32>(input[j+3])) << 24); 00416 } 00417 /* Note: Replace "for loop" with standard memcpy if possible. 00418 */ 00419 //static void MD5_memcpy (POINTER output, POINTER input, UInt32 len) 00420 //{ 00421 //UInt32 i; 00422 //for (i = 0; i < len; i++) 00423 // output[i] = input[i]; 00424 //} 00425 /* Note: Replace "for loop" with standard memset if possible. */ 00426 //static void MD5_memset (POINTER output, Int32 value, UInt32 len) 00427 //{ 00428 //UInt32 i; 00429 //for (i = 0; i < len; i++) 00430 // ((char *)output)[i] = (char)value; 00431 //} 00432 00433 } // end namespace BLOCXX_NAMESPACE 00434 00435 00436 #ifdef BLOCXX_WIN32 00437 #pragma warning (pop) 00438 #endif 00439