Back to index

nagios-plugins  1.4.16
md5.c
Go to the documentation of this file.
00001 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
00002  */
00003 
00004 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
00005 rights reserved.
00006 
00007 License to copy and use this software is granted provided that it
00008 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00009 Algorithm" in all material mentioning or referencing this software
00010 or this function.
00011 
00012 License is also granted to make and use derivative works provided
00013 that such works are identified as "derived from the RSA Data
00014 Security, Inc. MD5 Message-Digest Algorithm" in all material
00015 mentioning or referencing the derived work.
00016 
00017 RSA Data Security, Inc. makes no representations concerning either
00018 the merchantability of this software or the suitability of this
00019 software for any particular purpose. It is provided "as is"
00020 without express or implied warranty of any kind.
00021 
00022 These notices must be retained in any copies of any part of this
00023 documentation and/or software.
00024  */
00025 
00026 #include "md5.h"
00027 
00028 /* Constants for MD5Transform routine.
00029  */
00030 #define S11 7
00031 #define S12 12
00032 #define S13 17
00033 #define S14 22
00034 #define S21 5
00035 #define S22 9
00036 #define S23 14
00037 #define S24 20
00038 #define S31 4
00039 #define S32 11
00040 #define S33 16
00041 #define S34 23
00042 #define S41 6
00043 #define S42 10
00044 #define S43 15
00045 #define S44 21
00046 
00047 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
00048 static void Encode PROTO_LIST
00049   ((unsigned char *, UINT4 *, unsigned int));
00050 static void Decode PROTO_LIST
00051   ((UINT4 *, unsigned char *, unsigned int));
00052 static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
00053 static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
00054 
00055 static unsigned char PADDING[64] = {
00056   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00057   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00058   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00059 };
00060 
00061 /* F, G, H and I are basic MD5 functions.
00062  */
00063 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
00064 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
00065 #define H(x, y, z) ((x) ^ (y) ^ (z))
00066 #define I(x, y, z) ((y) ^ ((x) | (~z)))
00067 
00068 /* ROTATE_LEFT rotates x left n bits.
00069  */
00070 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
00071 
00072 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00073 Rotation is separate from addition to prevent recomputation.
00074  */
00075 #define FF(a, b, c, d, x, s, ac) { \
00076  (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
00077  (a) = ROTATE_LEFT ((a), (s)); \
00078  (a) += (b); \
00079   }
00080 #define GG(a, b, c, d, x, s, ac) { \
00081  (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
00082  (a) = ROTATE_LEFT ((a), (s)); \
00083  (a) += (b); \
00084   }
00085 #define HH(a, b, c, d, x, s, ac) { \
00086  (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
00087  (a) = ROTATE_LEFT ((a), (s)); \
00088  (a) += (b); \
00089   }
00090 #define II(a, b, c, d, x, s, ac) { \
00091  (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
00092  (a) = ROTATE_LEFT ((a), (s)); \
00093  (a) += (b); \
00094   }
00095 
00096 void md5_calc(output, input, inlen)
00097 unsigned char *output;
00098 unsigned char *input;                                /* input block */
00099 unsigned int inlen;                     /* length of input block */
00100 {
00101        MD5_CTX       context;
00102 
00103        MD5Init(&context);
00104        MD5Update(&context, input, inlen);
00105        MD5Final(output, &context);
00106 }
00107 
00108 /* MD5 initialization. Begins an MD5 operation, writing a new context.
00109  */
00110 void MD5Init (context)
00111 MD5_CTX *context;                                        /* context */
00112 {
00113   context->count[0] = context->count[1] = 0;
00114   /* Load magic initialization constants.
00115 */
00116   context->state[0] = 0x67452301;
00117   context->state[1] = 0xefcdab89;
00118   context->state[2] = 0x98badcfe;
00119   context->state[3] = 0x10325476;
00120 }
00121 
00122 /* MD5 block update operation. Continues an MD5 message-digest
00123   operation, processing another message block, and updating the
00124   context.
00125  */
00126 void MD5Update (context, input, inputLen)
00127 MD5_CTX *context;                                        /* context */
00128 unsigned char *input;                                /* input block */
00129 unsigned int inputLen;                     /* length of input block */
00130 {
00131   unsigned int i, index, partLen;
00132 
00133   /* Compute number of bytes mod 64 */
00134   index = (unsigned int)((context->count[0] >> 3) & 0x3F);
00135 
00136   /* Update number of bits */
00137   if ((context->count[0] += ((UINT4)inputLen << 3))
00138    < ((UINT4)inputLen << 3))
00139  context->count[1]++;
00140   context->count[1] += ((UINT4)inputLen >> 29);
00141 
00142   partLen = 64 - index;
00143 
00144   /* Transform as many times as possible.
00145 */
00146   if (inputLen >= partLen) {
00147  MD5_memcpy
00148    ((POINTER)&context->buffer[index], (POINTER)input, partLen);
00149  MD5Transform (context->state, context->buffer);
00150 
00151  for (i = partLen; i + 63 < inputLen; i += 64)
00152    MD5Transform (context->state, &input[i]);
00153 
00154  index = 0;
00155   }
00156   else
00157  i = 0;
00158 
00159   /* Buffer remaining input */
00160   MD5_memcpy
00161  ((POINTER)&context->buffer[index], (POINTER)&input[i],
00162   inputLen-i);
00163 }
00164 
00165 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
00166   the message digest and zeroizing the context.
00167  */
00168 void MD5Final (digest, context)
00169 unsigned char digest[16];                         /* message digest */
00170 MD5_CTX *context;                                       /* context */
00171 {
00172   unsigned char bits[8];
00173   unsigned int index, padLen;
00174 
00175   /* Save number of bits */
00176   Encode (bits, context->count, 8);
00177 
00178   /* Pad out to 56 mod 64.
00179 */
00180   index = (unsigned int)((context->count[0] >> 3) & 0x3f);
00181   padLen = (index < 56) ? (56 - index) : (120 - index);
00182   MD5Update (context, PADDING, padLen);
00183 
00184   /* Append length (before padding) */
00185   MD5Update (context, bits, 8);
00186 
00187   /* Store state in digest */
00188   Encode (digest, context->state, 16);
00189 
00190   /* Zeroize sensitive information.
00191 */
00192   MD5_memset ((POINTER)context, 0, sizeof (*context));
00193 }
00194 
00195 /* MD5 basic transformation. Transforms state based on block.
00196  */
00197 static void MD5Transform (state, block)
00198 UINT4 state[4];
00199 unsigned char block[64];
00200 {
00201   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00202 
00203   Decode (x, block, 64);
00204 
00205   /* Round 1 */
00206   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
00207   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
00208   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
00209   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
00210   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
00211   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
00212   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
00213   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
00214   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
00215   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00216   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00217   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00218   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00219   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00220   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00221   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00222 
00223  /* Round 2 */
00224   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00225   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00226   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00227   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00228   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00229   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00230   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00231   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00232   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00233   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00234   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00235   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00236   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00237   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00238   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00239   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00240 
00241   /* Round 3 */
00242   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00243   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00244   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00245   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00246   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00247   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00248   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00249   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00250   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00251   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00252   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00253   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00254   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00255   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00256   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00257   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00258 
00259   /* Round 4 */
00260   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00261   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00262   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00263   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00264   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00265   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00266   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00267   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00268   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00269   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00270   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00271   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00272   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00273   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00274   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00275   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00276 
00277   state[0] += a;
00278   state[1] += b;
00279   state[2] += c;
00280   state[3] += d;
00281 
00282   /* Zeroize sensitive information.
00283 */
00284   MD5_memset ((POINTER)x, 0, sizeof (x));
00285 }
00286 
00287 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
00288   a multiple of 4.
00289  */
00290 static void Encode (output, input, len)
00291 unsigned char *output;
00292 UINT4 *input;
00293 unsigned int len;
00294 {
00295   unsigned int i, j;
00296 
00297   for (i = 0, j = 0; j < len; i++, j += 4) {
00298  output[j] = (unsigned char)(input[i] & 0xff);
00299  output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
00300  output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
00301  output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
00302   }
00303 }
00304 
00305 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
00306   a multiple of 4.
00307  */
00308 static void Decode (output, input, len)
00309 UINT4 *output;
00310 unsigned char *input;
00311 unsigned int len;
00312 {
00313   unsigned int i, j;
00314 
00315   for (i = 0, j = 0; j < len; i++, j += 4)
00316  output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
00317    (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
00318 }
00319 
00320 /* Note: Replace "for loop" with standard memcpy if possible.
00321  */
00322 
00323 static void MD5_memcpy (output, input, len)
00324 POINTER output;
00325 POINTER input;
00326 unsigned int len;
00327 {
00328   unsigned int i;
00329 
00330   for (i = 0; i < len; i++)
00331  output[i] = input[i];
00332 }
00333 
00334 /* Note: Replace "for loop" with standard memset if possible.
00335  */
00336 static void MD5_memset (output, value, len)
00337 POINTER output;
00338 int value;
00339 unsigned int len;
00340 {
00341   unsigned int i;
00342 
00343   for (i = 0; i < len; i++)
00344  ((char *)output)[i] = (char)value;
00345 }