1 /*_############################################################################
 
   6   _##  -----------------------------------------------
 
   7   _##  Copyright (c) 2001-2010 Jochen Katz, Frank Fock
 
   9   _##  This software is based on SNMP++2.6 from Hewlett Packard:
 
  11   _##    Copyright (c) 1996
 
  12   _##    Hewlett-Packard Company
 
  14   _##  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
 
  15   _##  Permission to use, copy, modify, distribute and/or sell this software 
 
  16   _##  and/or its documentation is hereby granted without fee. User agrees 
 
  17   _##  to display the above copyright notice and this license notice in all 
 
  18   _##  copies of the software and any documentation of the software. User 
 
  19   _##  agrees to assume all liability for the use of the software; 
 
  20   _##  Hewlett-Packard and Jochen Katz make no representations about the 
 
  21   _##  suitability of this software for any purpose. It is provided 
 
  22   _##  "AS-IS" without warranty of any kind, either express or implied. User 
 
  23   _##  hereby grants a royalty-free license to any and all derivatives based
 
  24   _##  upon this software code base. 
 
  26   _##  Stuttgart, Germany, Thu Sep  2 00:07:47 CEST 2010 
 
  28   _##########################################################################*/
 
  29 char md5c_cpp_version[]="#(@) SNMP++ $Id: md5c.cpp 43 2004-03-03 23:11:21Z katz $";
 
  30 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */
 
  32 /* Copyright (C) 1991, RSA Data Security, Inc. All rights reserved.
 
  34    License to copy and use this software is granted provided that it
 
  35    is identified as the "RSA Data Security, Inc. MD5 Message-Digest
 
  36    Algorithm" in all material mentioning or referencing this software
 
  39    License is also granted to make and use derivative works provided
 
  40    that such works are identified as "derived from the RSA Data
 
  41    Security, Inc. MD5 Message-Digest Algorithm" in all material
 
  42    mentioning or referencing the derived work.
 
  44    RSA Data Security, Inc. makes no representations concerning either
 
  45    the merchantability of this software or the suitability of this
 
  46    software for any particular purpose. It is provided "as is"
 
  47    without express or implied warranty of any kind.
 
  49    These notices must be retained in any copies of any part of this
 
  50    documentation and/or software.
 
  53 #include "snmp_pp/md5.h"
 
  55 #if !defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
 
  63 #ifdef SNMP_PP_NAMESPACE
 
  67 /* Constants for MD5Transform routine.
 
  86 static void MD5Transform PROTO_LIST ((UINT4 [4], const unsigned char [64]));
 
  87 static void Encode PROTO_LIST ((unsigned char *, UINT4 *, unsigned int));
 
  88 static void Decode PROTO_LIST ((UINT4 *, const unsigned char *, unsigned int));
 
  89 static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
 
  90 static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
 
  92 static unsigned char PADDING[64] = {
 
  93   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
  94   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
  95   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 
  98 /* F, G, H and I are basic MD5 functions.
 
 100 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
 
 101 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
 
 102 #define H(x, y, z) ((x) ^ (y) ^ (z))
 
 103 #define I(x, y, z) ((y) ^ ((x) | (~z)))
 
 105 /* ROTATE_LEFT rotates x left n bits.
 
 107 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
 
 109 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
 
 110    Rotation is separate from addition to prevent recomputation.
 
 112 #define FF(a, b, c, d, x, s, ac) { \
 
 113     (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
 
 114     (a) = ROTATE_LEFT ((a), (s)); \
 
 117 #define GG(a, b, c, d, x, s, ac) { \
 
 118     (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
 
 119     (a) = ROTATE_LEFT ((a), (s)); \
 
 122 #define HH(a, b, c, d, x, s, ac) { \
 
 123     (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
 
 124     (a) = ROTATE_LEFT ((a), (s)); \
 
 127 #define II(a, b, c, d, x, s, ac) { \
 
 128     (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
 
 129     (a) = ROTATE_LEFT ((a), (s)); \
 
 133 /* MD5 initialization. Begins an MD5 operation, writing a new context.
 
 135 void MD5Init (MD5_CTX *context)
 
 137   context->count[0] = context->count[1] = 0;
 
 139   /* Load magic initialization constants.
 
 141   context->state[0] = 0x67452301;
 
 142   context->state[1] = 0xefcdab89;
 
 143   context->state[2] = 0x98badcfe;
 
 144   context->state[3] = 0x10325476;
 
 147 /* MD5 block update operation. Continues an MD5 message-digest operation,
 
 148      processing another message block, and updating the context.
 
 150 void MD5Update (MD5_CTX *context,                /* context */
 
 151                 const unsigned char *input,      /* input block */
 
 152                 const unsigned int inputLen)     /* length of input block */
 
 154   unsigned int i, index, partLen;
 
 156   /* Compute number of bytes mod 64 */
 
 157   index = (unsigned int)((context->count[0] >> 3) & 0x3F);
 
 159   /* Update number of bits */
 
 160   if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
 
 162   context->count[1] += ((UINT4)inputLen >> 29);
 
 164   partLen = 64 - index;
 
 166   /* Transform as many times as possible.
 
 168   if (inputLen >= partLen) {
 
 169     MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen);
 
 170     MD5Transform (context->state, context->buffer);
 
 172     for (i = partLen; i + 63 < inputLen; i += 64)
 
 173       MD5Transform (context->state, &input[i]);
 
 180   /* Buffer remaining input */
 
 182     ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
 
 185 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
 
 186      the message digest and zeroizing the context.
 
 189 unsigned char digest[16],                                 /* message digest */
 
 190 MD5_CTX *context)                                                /* context */
 
 192   unsigned char bits[8];
 
 193   unsigned int index, padLen;
 
 195   /* Save number of bits */
 
 196   Encode (bits, context->count, 8);
 
 198   /* Pad out to 56 mod 64.
 
 200   index = (unsigned int)((context->count[0] >> 3) & 0x3f);
 
 201   padLen = (index < 56) ? (56 - index) : (120 - index);
 
 202   MD5Update (context, PADDING, padLen);
 
 204   /* Append length (before padding) */
 
 205   MD5Update (context, bits, 8);
 
 207   /* Store state in digest */
 
 208   Encode (digest, context->state, 16);
 
 210   /* Zeroize sensitive information.
 
 212   MD5_memset ((POINTER)context, 0, sizeof (*context));
 
 215 /* MD5 basic transformation. Transforms state based on block.
 
 217 static void MD5Transform (
 
 219 const unsigned char block[64])
 
 221   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
 
 223   Decode (x, block, 64);
 
 226   FF ( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
 
 227   FF ( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
 
 228   FF ( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
 
 229   FF ( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
 
 230   FF ( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
 
 231   FF ( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
 
 232   FF ( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
 
 233   FF ( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
 
 234   FF ( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
 
 235   FF ( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
 
 236   FF ( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
 
 237   FF ( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
 
 238   FF ( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
 
 239   FF ( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
 
 240   FF ( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
 
 241   FF ( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
 
 244   GG ( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
 
 245   GG ( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
 
 246   GG ( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
 
 247   GG ( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
 
 248   GG ( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
 
 249   GG ( d, a, b, c, x[10], S22,  0x2441453); /* 22 */
 
 250   GG ( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
 
 251   GG ( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
 
 252   GG ( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
 
 253   GG ( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
 
 254   GG ( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
 
 255   GG ( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
 
 256   GG ( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
 
 257   GG ( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
 
 258   GG ( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
 
 259   GG ( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
 
 262   HH ( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
 
 263   HH ( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
 
 264   HH ( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
 
 265   HH ( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
 
 266   HH ( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
 
 267   HH ( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
 
 268   HH ( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
 
 269   HH ( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
 
 270   HH ( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
 
 271   HH ( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
 
 272   HH ( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
 
 273   HH ( b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
 
 274   HH ( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
 
 275   HH ( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
 
 276   HH ( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
 
 277   HH ( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
 
 280   II ( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
 
 281   II ( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
 
 282   II ( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
 
 283   II ( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
 
 284   II ( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
 
 285   II ( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
 
 286   II ( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
 
 287   II ( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
 
 288   II ( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
 
 289   II ( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
 
 290   II ( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
 
 291   II ( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
 
 292   II ( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
 
 293   II ( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
 
 294   II ( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
 
 295   II ( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
 
 302   /* Zeroize sensitive information.
 
 304   MD5_memset ((POINTER)x, 0, sizeof (x));
 
 307 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
 
 311                     unsigned char *output,
 
 317   for (i = 0, j = 0; j < len; i++, j += 4) {
 
 318     output[j] = (unsigned char)(input[i] & 0xff);
 
 319     output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
 
 320     output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
 
 321     output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
 
 325 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
 
 330                     const unsigned char *input,
 
 335   for (i = 0, j = 0; j < len; i++, j += 4)
 
 336     output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
 
 337       (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
 
 340 static void MD5_memcpy (
 
 345   memcpy(output, input, len);
 
 348 static void MD5_memset (
 
 353   memset(output, value, len);
 
 356 #ifdef SNMP_PP_NAMESPACE
 
 357 }; // end of namespace Snmp_pp
 
 364 #endif // !defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)