Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

md5.c

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

Generated on Thu Sep 9 04:15:44 2010 for SIPExpressRouter by  doxygen 1.3.9.1