global.h
1 /* GLOBAL.H - RSAREF types and constants 2 */ 3 4 /* PROTOTYPES should be set to one if and only if the compiler supports 5 function argument prototyping. 6 The following makes PROTOTYPES default to 0 if it has not already 7 been defined with C compiler flags. 8 */ 9 10 #ifndef PROTOTYPES11 #define PROTOTYPES 012 #endif13 14 /* POINTER defines a generic pointer type */15 typedef unsigned char *POINTER;16 17 /* UINT2 defines a two byte word */18 typedef unsigned short int UINT2;19 20 /* UINT4 defines a four byte word */21 typedef unsigned long int UINT4;22 23 /* PROTO_LIST is defined depending on how PROTOTYPES is defined above.24 If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it25 returns an empty list.26 */27 #if PROTOTYPES28 #define PROTO_LIST(list) list29 #else30 #define PROTO_LIST(list) ()31 #endif
md5.h
1 /* MD5.H - header file for MD5C.C 2 */ 3 4 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 5 rights reserved. 6 7 License to copy and use this software is granted provided that it 8 is identified as the "RSA Data Security, Inc. MD5 Message-Digest 9 Algorithm" in all material mentioning or referencing this software10 or this function.11 12 License is also granted to make and use derivative works provided13 that such works are identified as "derived from the RSA Data14 Security, Inc. MD5 Message-Digest Algorithm" in all material15 mentioning or referencing the derived work.16 17 RSA Data Security, Inc. makes no representations concerning either18 the merchantability of this software or the suitability of this19 software for any particular purpose. It is provided "as is"20 without express or implied warranty of any kind.21 These notices must be retained in any copies of any part of this22 documentation and/or software.23 */24 25 #include "global.h"26 27 /* MD5 context. */28 typedef struct {29 UINT4 state[4]; /* state (ABCD) */30 UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */31 unsigned char buffer[64]; /* input buffer */32 } MD5_CTX;33 34 void MD5Init(MD5_CTX *);35 void MD5Update(MD5_CTX *, unsigned char *, unsigned int);36 void MD5Final(unsigned char [16], MD5_CTX *);
md5c.c
1 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm 2 */ 3 4 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 5 rights reserved. 6 7 License to copy and use this software is granted provided that it 8 is identified as the "RSA Data Security, Inc. MD5 Message-Digest 9 Algorithm" in all material mentioning or referencing this software 10 or this function. 11 12 License is also granted to make and use derivative works provided 13 that such works are identified as "derived from the RSA Data 14 Security, Inc. MD5 Message-Digest Algorithm" in all material 15 mentioning or referencing the derived work. 16 17 RSA Data Security, Inc. makes no representations concerning either 18 the merchantability of this software or the suitability of this 19 software for any particular purpose. It is provided "as is" 20 without express or implied warranty of any kind. 21 22 These notices must be retained in any copies of any part of this 23 documentation and/or software. 24 */ 25 26 #include "global.h" 27 #include "md5.h" 28 29 /* Constants for MD5Transform routine. 30 */ 31 #define S11 7 32 #define S12 12 33 #define S13 17 34 #define S14 22 35 #define S21 5 36 #define S22 9 37 #define S23 14 38 #define S24 20 39 #define S31 4 40 #define S32 11 41 #define S33 16 42 #define S34 23 43 #define S41 6 44 #define S42 10 45 #define S43 15 46 #define S44 21 47 48 static void MD5Transform(UINT4 [4], unsigned char [64]); 49 static void Encode(unsigned char *, UINT4 *, unsigned int); 50 static void Decode(UINT4 *, unsigned char *, unsigned int); 51 static void MD5_memcpy(POINTER, POINTER, unsigned int); 52 static void MD5_memset(POINTER, int, unsigned int); 53 54 static unsigned char PADDING[64] = { 55 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 58 }; 59 60 /* F, G, H and I are basic MD5 functions. 61 */ 62 #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 63 #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) 64 #define H(x, y, z) ((x) ^ (y) ^ (z)) 65 #define I(x, y, z) ((y) ^ ((x) | (~z))) 66 67 /* ROTATE_LEFT rotates x left n bits. 68 */ 69 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 70 71 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 72 Rotation is separate from addition to prevent recomputation. 73 */ 74 #define FF(a, b, c, d, x, s, ac) { \ 75 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ 76 (a) = ROTATE_LEFT ((a), (s)); \ 77 (a) += (b); \ 78 } 79 80 #define GG(a, b, c, d, x, s, ac) { \ 81 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ 82 (a) = ROTATE_LEFT ((a), (s)); \ 83 (a) += (b); \ 84 } 85 86 #define HH(a, b, c, d, x, s, ac) { \ 87 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ 88 (a) = ROTATE_LEFT ((a), (s)); \ 89 (a) += (b); \ 90 } 91 92 #define II(a, b, c, d, x, s, ac) { \ 93 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ 94 (a) = ROTATE_LEFT ((a), (s)); \ 95 (a) += (b); \ 96 } 97 98 /* MD5 initialization. Begins an MD5 operation, writing a new context. 99 */100 void MD5Init (MD5_CTX *context)101 {102 context->count[0] = context->count[1] = 0;103 /* Load magic initialization constants.104 */105 context->state[0] = 0x67452301;106 context->state[1] = 0xefcdab89;107 context->state[2] = 0x98badcfe;108 context->state[3] = 0x10325476;109 }110 111 /* MD5 block update operation. Continues an MD5 message-digest112 operation, processing another message block, and updating the113 context.114 */115 void MD5Update (MD5_CTX *context, unsigned char *input, unsigned int inputLen)116 {117 unsigned int i, index, partLen;118 119 /* Compute number of bytes mod 64 */120 index = (unsigned int)((context->count[0] >> 3) & 0x3F);121 122 /* Update number of bits */123 if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))124 {125 context->count[1]++;126 }127 context->count[1] += ((UINT4)inputLen >> 29);128 129 partLen = 64 - index;130 131 /* Transform as many times as possible.132 */133 if (inputLen >= partLen) 134 {135 MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen);136 MD5Transform (context->state, context->buffer);137 138 for (i = partLen; i + 63 < inputLen; i += 64)139 {140 MD5Transform (context->state, &input[i]);141 }142 143 index = 0;144 }145 else146 {147 i = 0;148 }149 150 /* Buffer remaining input */151 MD5_memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);152 }153 154 /* MD5 finalization. Ends an MD5 message-digest operation, writing the155 the message digest and zeroizing the context.156 */157 void MD5Final (unsigned char digest[16], MD5_CTX *context)158 {159 unsigned char bits[8];160 unsigned int index, padLen;161 162 /* Save number of bits */163 Encode (bits, context->count, 8);164 165 /* Pad out to 56 mod 64.166 */167 index = (unsigned int)((context->count[0] >> 3) & 0x3f);168 padLen = (index < 56) ? (56 - index) : (120 - index);169 MD5Update (context, PADDING, padLen);170 171 /* Append length (before padding) */172 MD5Update (context, bits, 8);173 174 /* Store state in digest */175 Encode (digest, context->state, 16);176 177 /* Zeroize sensitive information.178 */179 MD5_memset ((POINTER)context, 0, sizeof (*context));180 }181 182 /* MD5 basic transformation. Transforms state based on block.183 */184 static void MD5Transform (UINT4 state[4], unsigned char block[64])185 {186 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];187 188 Decode (x, block, 64);189 190 /* Round 1 */191 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */192 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */193 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */194 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */195 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */196 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */197 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */198 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */199 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */200 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */201 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */202 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */203 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */204 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */205 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */206 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */207 208 /* Round 2 */209 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */210 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */211 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */212 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */213 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */214 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */215 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */216 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */217 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */218 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */219 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */220 221 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */222 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */223 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */224 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */225 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */226 227 /* Round 3 */228 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */229 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */230 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */231 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */232 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */233 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */234 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */235 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */236 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */237 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */238 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */239 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */240 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */241 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */242 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */243 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */244 245 /* Round 4 */246 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */247 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */248 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */249 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */250 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */251 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */252 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */253 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */254 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */255 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */256 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */257 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */258 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */259 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */260 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */261 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */262 263 state[0] += a;264 state[1] += b;265 state[2] += c;266 state[3] += d;267 268 /* Zeroize sensitive information.269 */270 MD5_memset ((POINTER)x, 0, sizeof (x));271 }272 273 /* Encodes input (UINT4) into output (unsigned char). Assumes len is274 a multiple of 4.275 */276 static void Encode (unsigned char *output, UINT4 *input, unsigned int len)277 {278 unsigned int i, j;279 280 for (i = 0, j = 0; j < len; i++, j += 4) 281 {282 output[j] = (unsigned char)(input[i] & 0xff);283 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);284 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);285 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);286 }287 }288 289 /* Decodes input (unsigned char) into output (UINT4). Assumes len is290 a multiple of 4.291 */292 static void Decode (UINT4 *output, unsigned char *input, unsigned int len)293 {294 unsigned int i, j;295 296 for (i = 0, j = 0; j < len; i++, j += 4)297 {298 output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);299 }300 }301 302 /* Note: Replace "for loop" with standard memcpy if possible.303 */304 static void MD5_memcpy (POINTER output, POINTER input, unsigned int len)305 {306 unsigned int i;307 308 for (i = 0; i < len; i++)309 {310 output[i] = input[i];311 }312 }313 314 /* Note: Replace "for loop" with standard memset if possible.315 */316 static void MD5_memset (POINTER output, int value, unsigned int len)317 {318 unsigned int i;319 320 for (i = 0; i < len; i++)321 {322 ((char *)output)[i] = (char)value;323 }324 325 }
mddriver.c
1 /* MDDRIVER.C - test driver for MD2, MD4 and MD5 2 */ 3 4 /* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All 5 rights reserved. 6 7 RSA Data Security, Inc. makes no representations concerning either 8 the merchantability of this software or the suitability of this 9 software for any particular purpose. It is provided "as is" 10 without express or implied warranty of any kind. 11 12 These notices must be retained in any copies of any part of this 13 documentation and/or software. 14 */ 15 16 /* The following makes MD default to MD5 if it has not already been 17 defined with C compiler flags. 18 */ 19 #ifndef MD 20 #define MD 5 21 #endif 22 23 #include24 #include 25 #include 26 #include 27 #include 28 #include "global.h" 29 #include "md5.h" 30 31 /* Length of test block, number of test blocks. 32 */ 33 #define TEST_BLOCK_LEN 1000 34 #define TEST_BLOCK_COUNT 1000 35 36 static void MDString(char *); 37 static void MDTimeTrial(void); 38 static void MDTestSuite(void); 39 static void MDFile(char *); 40 static void MDFilter(void); 41 static void MDPrint(unsigned char [16]); 42 43 #define MD_CTX MD5_CTX 44 #define MDInit MD5Init 45 #define MDUpdate MD5Update 46 #define MDFinal MD5Final 47 48 49 /* Main driver. 50 Arguments (may be any combination): 51 -sstring - digests string 52 -t - runs time trial 53 -x - runs test script 54 filename - digests file 55 (none) - digests standard input 56 */ 57 int main (int argc, char *argv[]) 58 { 59 int i; 60 61 if (argc > 1) 62 { 63 for (i = 1; i < argc; i++) 64 { 65 if (argv[i][0] == '-' && argv[i][1] == 's') 66 { 67 MDString (argv[i] + 2); 68 } 69 else if (strcmp (argv[i], "-t") == 0) 70 { 71 MDTimeTrial (); 72 } 73 else if (strcmp (argv[i], "-x") == 0) 74 { 75 MDTestSuite (); 76 } 77 else 78 { 79 MDFile (argv[i]); 80 } 81 } 82 } 83 else 84 { 85 MDFilter (); 86 } 87 88 return (0); 89 } 90 91 /* Digests a string and prints the result. 92 */ 93 static void MDString(char *string) 94 { 95 MD_CTX context; 96 unsigned char digest[16]; 97 unsigned int len = strlen (string); 98 99 MDInit (&context);100 MDUpdate (&context, string, len);101 MDFinal (digest, &context);102 103 printf ("MD%d (\"%s\") = ", MD, string);104 MDPrint (digest);105 printf ("\n");106 }107 108 /* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte109 blocks.110 */111 static void MDTimeTrial ()112 {113 MD_CTX context;114 time_t endTime, startTime;115 unsigned char block[TEST_BLOCK_LEN], digest[16];116 unsigned int i;117 printf("MD%d time trial. Digesting %d %d-byte blocks ...", MD, TEST_BLOCK_LEN, TEST_BLOCK_COUNT);118 119 /* Initialize block */120 for (i = 0; i < TEST_BLOCK_LEN; i++)121 {122 block[i] = (unsigned char)(i & 0xff);123 }124 125 /* Start timer */126 time (&startTime);127 128 /* Digest blocks */129 MDInit (&context);130 for (i = 0; i < TEST_BLOCK_COUNT; i++)131 {132 MDUpdate (&context, block, TEST_BLOCK_LEN);133 }134 MDFinal (digest, &context);135 136 Sleep(2000);137 /* Stop timer */138 time (&endTime);139 140 printf (" done\n");141 printf ("Digest = ");142 MDPrint (digest);143 printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));144 printf("Speed = %ld bytes/second\n", (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime));145 }146 147 /* Digests a reference suite of strings and prints the results.148 */149 static void MDTestSuite ()150 {151 printf ("MD%d test suite:\n", MD);152 153 MDString("");154 MDString("a");155 MDString("abc");156 MDString("message digest");157 MDString("abcdefghijklmnopqrstuvwxyz");158 MDString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");159 MDString("12345678901234567890123456789012345678901234567890123456789012345678901234567890");160 }161 162 /* Digests a file and prints the result.163 */164 static void MDFile (char *filename)165 {166 FILE *file;167 MD_CTX context;168 int len;169 unsigned char buffer[1024], digest[16];170 171 if ((file = fopen (filename, "rb")) == NULL)172 {173 printf ("%s can't be opened\n", filename);174 }175 else 176 {177 MDInit (&context);178 179 while (len = fread (buffer, 1, 1024, file))180 {181 MDUpdate (&context, buffer, len);182 }183 184 MDFinal(digest, &context);185 186 fclose (file);187 188 printf ("MD%d (%s) = ", MD, filename);189 MDPrint (digest);190 printf ("\n");191 }192 }193 194 /* Digests the standard input and prints the result.195 */196 static void MDFilter ()197 {198 MD_CTX context;199 int len;200 unsigned char buffer[16], digest[16];201 202 MDInit (&context);203 204 while (len = fread (buffer, 1, 16, stdin))205 {206 MDUpdate (&context, buffer, len);207 }208 209 MDFinal (digest, &context);210 211 MDPrint (digest);212 printf ("\n");213 }214 215 /* Prints a message digest in hexadecimal.216 */217 static void MDPrint (unsigned char digest[16])218 {219 unsigned int i;220 221 for (i = 0; i < 16; i++)222 {223 printf ("%02x", digest[i]);224 }225 226 }