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 #include <stdio.h> 24 #include <time.h> 25 #include <string.h> 26 #include "global.h" 27 #if MD == 2 28 #include <md2.h> 29 #endif 30 #if MD == 4 31 #include <md4.h> 32 #endif 33 #if MD == 5 34 #include <md5.h> 35 #endif 36 37 /* Length of test block, number of test blocks. 38 */ 39 #define TEST_BLOCK_LEN 1000 40 #define TEST_BLOCK_COUNT 1000 41 42 static void MDString PROTO_LIST ((char *)); 43 static void MDTimeTrial PROTO_LIST ((void)); 44 static void MDTestSuite PROTO_LIST ((void)); 45 static void MDFile PROTO_LIST ((char *)); 46 static void MDFilter PROTO_LIST ((void)); 47 static void MDPrint PROTO_LIST ((unsigned char [16])); 48 49 #if MD == 2 50 #define MD_CTX MD2_CTX 51 #define MDInit MD2Init 52 #define MDUpdate MD2Update 53 #define MDFinal MD2Final 54 #endif 55 #if MD == 4 56 #define MD_CTX MD4_CTX 57 #define MDInit MD4Init 58 #define MDUpdate MD4Update 59 #define MDFinal MD4Final 60 #endif 61 #if MD == 5 62 #define MD_CTX MD5_CTX 63 #define MDInit MD5Init 64 #define MDUpdate MD5Update 65 #define MDFinal MD5Final 66 #endif 67 68 /* Main driver. 69 70 Arguments (may be any combination): 71 -sstring - digests string 72 -t - runs time trial 73 -x - runs test script 74 filename - digests file 75 (none) - digests standard input 76 */ 77 int main (argc, argv) 78 int argc; 79 char *argv[]; 80 { 81 int i; 82 83 if (argc > 1) 84 for (i = 1; i < argc; i++) 85 if (argv[i][0] == '-' && argv[i][1] == 's') 86 MDString (argv[i] + 2); 87 else if (strcmp (argv[i], "-t") == 0) 88 MDTimeTrial (); 89 else if (strcmp (argv[i], "-x") == 0) 90 MDTestSuite (); 91 else 92 MDFile (argv[i]); 93 else 94 MDFilter (); 95 96 return (0); 97 } 98 99 /* Digests a string and prints the result. 100 */ 101 static void MDString (string) 102 char *string; 103 { 104 MD_CTX context; 105 unsigned char digest[16]; 106 unsigned int len = strlen (string); 107 108 MDInit (&context); 109 MDUpdate (&context, string, len); 110 MDFinal (digest, &context); 111 112 printf ("MD%d (\"%s\") = ", MD, string); 113 MDPrint (digest); 114 printf ("\n"); 115 } 116 117 /* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte 118 blocks. 119 */ 120 static void MDTimeTrial () 121 { 122 MD_CTX context; 123 time_t endTime, startTime; 124 unsigned char block[TEST_BLOCK_LEN], digest[16]; 125 unsigned int i; 126 127 printf 128 ("MD%d time trial. Digesting %d %d-byte blocks ...", MD, 129 TEST_BLOCK_LEN, TEST_BLOCK_COUNT); 130 131 /* Initialize block */ 132 for (i = 0; i < TEST_BLOCK_LEN; i++) 133 block[i] = (unsigned char)(i & 0xff); 134 135 /* Start timer */ 136 time (&startTime); 137 138 /* Digest blocks */ 139 MDInit (&context); 140 for (i = 0; i < TEST_BLOCK_COUNT; i++) 141 MDUpdate (&context, block, TEST_BLOCK_LEN); 142 MDFinal (digest, &context); 143 144 /* Stop timer */ 145 time (&endTime); 146 147 printf (" done\n"); 148 printf ("Digest = "); 149 MDPrint (digest); 150 printf ("\nTime = %ld seconds\n", (long)(endTime-startTime)); 151 /* 152 * Be careful that endTime-startTime is not zero. 153 * (Bug fix from Ric Anderson, ric@Artisoft.COM.) 154 */ 155 printf 156 ("Speed = %ld bytes/second\n", 157 (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/((endTime-startTime) != 0 ? (endTime-startTime):1)); 158 } 159 160 /* Digests a reference suite of strings and prints the results. 161 */ 162 static void MDTestSuite () 163 { 164 printf ("MD%d test suite:\n", MD); 165 166 MDString (""); 167 MDString ("a"); 168 MDString ("abc"); 169 MDString ("message digest"); 170 MDString ("abcdefghijklmnopqrstuvwxyz"); 171 MDString 172 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); 173 MDString 174 ("1234567890123456789012345678901234567890\ 175 1234567890123456789012345678901234567890"); 176 } 177 178 /* Digests a file and prints the result. 179 */ 180 static void MDFile (filename) 181 char *filename; 182 { 183 FILE *file; 184 MD_CTX context; 185 int len; 186 unsigned char buffer[1024], digest[16]; 187 188 if ((file = fopen (filename, "rb")) == NULL) 189 printf ("%s can't be opened\n", filename); 190 191 else { 192 MDInit (&context); 193 while (len = fread (buffer, 1, 1024, file)) 194 MDUpdate (&context, buffer, len); 195 MDFinal (digest, &context); 196 197 fclose (file); 198 199 printf ("MD%d (%s) = ", MD, filename); 200 MDPrint (digest); 201 printf ("\n"); 202 } 203 } 204 205 /* Digests the standard input and prints the result. 206 */ 207 static void MDFilter () 208 { 209 MD_CTX context; 210 int len; 211 unsigned char buffer[16], digest[16]; 212 213 MDInit (&context); 214 while (len = fread (buffer, 1, 16, stdin)) 215 MDUpdate (&context, buffer, len); 216 MDFinal (digest, &context); 217 218 MDPrint (digest); 219 printf ("\n"); 220 } 221 222 /* Prints a message digest in hexadecimal. 223 */ 224 static void MDPrint (digest) 225 unsigned char digest[16]; 226 { 227 unsigned int i; 228 229 for (i = 0; i < 16; i++) 230 printf ("%02x", digest[i]); 231 } 232