| 1 |  | 
    
      | 2 | /* MDDRIVER.C - test driver for MD2, MD4 and MD5 | 
    
      | 3 | */ | 
    
      | 4 |  | 
    
      | 5 | /* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All | 
    
      | 6 | rights reserved. | 
    
      | 7 |  | 
    
      | 8 | RSA Data Security, Inc. makes no representations concerning either | 
    
      | 9 | the merchantability of this software or the suitability of this | 
    
      | 10 | software for any particular purpose. It is provided "as is" | 
    
      | 11 | without express or implied warranty of any kind. | 
    
      | 12 |  | 
    
      | 13 | These notices must be retained in any copies of any part of this | 
    
      | 14 | documentation and/or software. | 
    
      | 15 |  | 
    
      | 16 | Additional main() function ©2024 mrw <plus@m0001a.org> | 
    
      | 17 | */ | 
    
      | 18 |  | 
    
      | 19 | /* The following makes MD default to MD5 if it has not already been | 
    
      | 20 | defined with C compiler flags. | 
    
      | 21 | */ | 
    
      | 22 | #ifndef MD | 
    
      | 23 | #define MD 5 | 
    
      | 24 | #endif | 
    
      | 25 |  | 
    
      | 26 | #include <stdio.h> | 
    
      | 27 | #include <time.h> | 
    
      | 28 | #include <string.h> | 
    
      | 29 | #include "global.h" | 
    
      | 30 | #if MD == 2 | 
    
      | 31 | #include "md2.h" | 
    
      | 32 | #endif | 
    
      | 33 | #if MD == 4 | 
    
      | 34 | #include "md4.h" | 
    
      | 35 | #endif | 
    
      | 36 | #if MD == 5 | 
    
      | 37 | #include "md5.h" | 
    
      | 38 | #endif | 
    
      | 39 |  | 
    
      | 40 | /* for ccommand - mrw */ | 
    
      | 41 | #include <console.h> | 
    
      | 42 |  | 
    
      | 43 | /* Length of test block, number of test blocks. | 
    
      | 44 | */ | 
    
      | 45 | #define TEST_BLOCK_LEN 1000 | 
    
      | 46 | #define TEST_BLOCK_COUNT 1000 | 
    
      | 47 |  | 
    
      | 48 | static void MDString PROTO_LIST ((char *, unsigned char [16])); | 
    
      | 49 | static void MDTimeTrial PROTO_LIST ((void)); | 
    
      | 50 | static void MDTestSuite PROTO_LIST ((void)); | 
    
      | 51 | static void MDFile PROTO_LIST ((char *)); | 
    
      | 52 | static void MDFilter PROTO_LIST ((void)); | 
    
      | 53 | static void MDPrint PROTO_LIST ((unsigned char [16])); | 
    
      | 54 |  | 
    
      | 55 | #if MD == 2 | 
    
      | 56 | #define MD_CTX MD2_CTX | 
    
      | 57 | #define MDInit MD2Init | 
    
      | 58 | #define MDUpdate MD2Update | 
    
      | 59 | #define MDFinal MD2Final | 
    
      | 60 | #endif | 
    
      | 61 | #if MD == 4 | 
    
      | 62 | #define MD_CTX MD4_CTX | 
    
      | 63 | #define MDInit MD4Init | 
    
      | 64 | #define MDUpdate MD4Update | 
    
      | 65 | #define MDFinal MD4Final | 
    
      | 66 | #endif | 
    
      | 67 | #if MD == 5 | 
    
      | 68 | #define MD_CTX MD5_CTX | 
    
      | 69 | #define MDInit MD5Init | 
    
      | 70 | #define MDUpdate MD5Update | 
    
      | 71 | #define MDFinal MD5Final | 
    
      | 72 | #endif | 
    
      | 73 |  | 
    
      | 74 |  | 
    
      | 75 | /* Main driver. | 
    
      | 76 |  | 
    
      | 77 | Arguments (may be any combination): | 
    
      | 78 | -sstring - digests string | 
    
      | 79 | -t		- runs time trial | 
    
      | 80 | -x		- runs test script | 
    
      | 81 | filename - digests file | 
    
      | 82 | (none)	- digests standard input | 
    
      | 83 | */ | 
    
      | 84 | int main (argc, argv) | 
    
      | 85 | int argc; | 
    
      | 86 | char *argv[]; | 
    
      | 87 | { | 
    
      | 88 | int i; | 
    
      | 89 |  | 
    
      | 90 | argc = ccommand(&argv); | 
    
      | 91 |  | 
    
      | 92 | if (argc > 1) | 
    
      | 93 | for (i = 1; i < argc; i++) | 
    
      | 94 | if (argv[i][0] == '-' && argv[i][1] == 's') | 
    
      | 95 | MDString (argv[i] + 2, NULL); | 
    
      | 96 | else if (strcmp (argv[i], "-t") == 0) | 
    
      | 97 | MDTimeTrial (); | 
    
      | 98 | else if (strcmp (argv[i], "-x") == 0) | 
    
      | 99 | MDTestSuite (); | 
    
      | 100 | else | 
    
      | 101 | MDFile (argv[i]); | 
    
      | 102 | else | 
    
      | 103 | MDFilter (); | 
    
      | 104 |  | 
    
      | 105 | return (0); | 
    
      | 106 | } | 
    
      | 107 | /* Added so MDTestSuite can check output - mrw | 
    
      | 108 | */ | 
    
      | 109 | static int MDEqual(unsigned char a[16], unsigned char b[16]) | 
    
      | 110 | { | 
    
      | 111 | int i; | 
    
      | 112 | for (i = 0; i < sizeof(a); i++) { | 
    
      | 113 | if (a[i] != b[i]) | 
    
      | 114 | return 0; | 
    
      | 115 | } | 
    
      | 116 |  | 
    
      | 117 | return 1; | 
    
      | 118 | } | 
    
      | 119 |  | 
    
      | 120 | /* Digests a string and prints the result. | 
    
      | 121 | * | 
    
      | 122 | * Extended to check expected digest. | 
    
      | 123 | */ | 
    
      | 124 | static void MDString (string, expected) | 
    
      | 125 | char *string; | 
    
      | 126 | unsigned char expected[16]; | 
    
      | 127 | { | 
    
      | 128 | MD_CTX context; | 
    
      | 129 | unsigned char digest[16]; | 
    
      | 130 | unsigned int len = strlen (string); | 
    
      | 131 |  | 
    
      | 132 | MDInit (&context); | 
    
      | 133 | MDUpdate (&context, (unsigned char *)string, len); | 
    
      | 134 | MDFinal (digest, &context); | 
    
      | 135 |  | 
    
      | 136 | printf ("MD%d (\"%s\") = ", MD, string); | 
    
      | 137 | MDPrint (digest); | 
    
      | 138 |  | 
    
      | 139 | if (expected && !MDEqual(digest, expected)) { | 
    
      | 140 | printf(" ** FAIL **"); | 
    
      | 141 | } | 
    
      | 142 |  | 
    
      | 143 | printf ("\n"); | 
    
      | 144 | } | 
    
      | 145 |  | 
    
      | 146 | /* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte | 
    
      | 147 | blocks. | 
    
      | 148 | */ | 
    
      | 149 | static void MDTimeTrial () | 
    
      | 150 | { | 
    
      | 151 | MD_CTX context; | 
    
      | 152 | time_t endTime, startTime; | 
    
      | 153 | unsigned char block[TEST_BLOCK_LEN], digest[16]; | 
    
      | 154 | unsigned int i; | 
    
      | 155 |  | 
    
      | 156 | printf | 
    
      | 157 | ("MD%d time trial. Digesting %d %d-byte blocks ...", MD, | 
    
      | 158 | TEST_BLOCK_LEN, TEST_BLOCK_COUNT); | 
    
      | 159 |  | 
    
      | 160 | /* Initialize block */ | 
    
      | 161 | for (i = 0; i < TEST_BLOCK_LEN; i++) | 
    
      | 162 | block[i] = (unsigned char)(i & 0xff); | 
    
      | 163 |  | 
    
      | 164 | /* Start timer */ | 
    
      | 165 | time (&startTime); | 
    
      | 166 |  | 
    
      | 167 | /* Digest blocks */ | 
    
      | 168 | MDInit (&context); | 
    
      | 169 | for (i = 0; i < TEST_BLOCK_COUNT; i++) | 
    
      | 170 | MDUpdate (&context, block, TEST_BLOCK_LEN); | 
    
      | 171 | MDFinal (digest, &context); | 
    
      | 172 |  | 
    
      | 173 | /* Stop timer */ | 
    
      | 174 | time (&endTime); | 
    
      | 175 |  | 
    
      | 176 | printf (" done\n"); | 
    
      | 177 | printf ("Digest = "); | 
    
      | 178 | MDPrint (digest); | 
    
      | 179 | printf ("\nTime = %ld seconds\n", (long)(endTime-startTime)); | 
    
      | 180 | printf | 
    
      | 181 | ("Speed = %ld bytes/second\n", | 
    
      | 182 | (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime)); | 
    
      | 183 | } | 
    
      | 184 |  | 
    
      | 185 | /* Digests a reference suite of strings and prints the results. | 
    
      | 186 | */ | 
    
      | 187 | static void MDTestSuite () | 
    
      | 188 | { | 
    
      | 189 | unsigned char digests[7][16] = { | 
    
      | 190 | { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, | 
    
      | 191 | { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, | 
    
      | 192 | { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, | 
    
      | 193 | { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, | 
    
      | 194 | { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, | 
    
      | 195 | { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, | 
    
      | 196 | { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }, | 
    
      | 197 | }; | 
    
      | 198 |  | 
    
      | 199 | printf ("MD%d test suite:\n", MD); | 
    
      | 200 |  | 
    
      | 201 |  | 
    
      | 202 | MDString ("", digests[0]); | 
    
      | 203 | MDString ("a", digests[1]); | 
    
      | 204 | MDString ("abc", digests[2]); | 
    
      | 205 | MDString ("message digest", digests[3]); | 
    
      | 206 | MDString ("abcdefghijklmnopqrstuvwxyz", digests[4]); | 
    
      | 207 | MDString | 
    
      | 208 | ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", | 
    
      | 209 | digests[5]); | 
    
      | 210 | MDString | 
    
      | 211 | ("1234567890123456789012345678901234567890\ | 
    
      | 212 | 1234567890123456789012345678901234567890", | 
    
      | 213 | digests[6]); | 
    
      | 214 | } | 
    
      | 215 |  | 
    
      | 216 | /* Digests a file and prints the result. | 
    
      | 217 | */ | 
    
      | 218 | static void MDFile (filename) | 
    
      | 219 | char *filename; | 
    
      | 220 | { | 
    
      | 221 | FILE *file; | 
    
      | 222 | MD_CTX context; | 
    
      | 223 | int len; | 
    
      | 224 | unsigned char buffer[1024], digest[16]; | 
    
      | 225 |  | 
    
      | 226 | if ((file = fopen (filename, "rb")) == NULL) | 
    
      | 227 | printf ("%s can't be opened\n", filename); | 
    
      | 228 |  | 
    
      | 229 | else { | 
    
      | 230 | MDInit (&context); | 
    
      | 231 | while (len = fread (buffer, 1, 1024, file)) | 
    
      | 232 | MDUpdate (&context, buffer, len); | 
    
      | 233 | MDFinal (digest, &context); | 
    
      | 234 |  | 
    
      | 235 | fclose (file); | 
    
      | 236 |  | 
    
      | 237 | printf ("MD%d (%s) = ", MD, filename); | 
    
      | 238 | MDPrint (digest); | 
    
      | 239 | printf ("\n"); | 
    
      | 240 | } | 
    
      | 241 | } | 
    
      | 242 |  | 
    
      | 243 | /* Digests the standard input and prints the result. | 
    
      | 244 | */ | 
    
      | 245 | static void MDFilter () | 
    
      | 246 | { | 
    
      | 247 | MD_CTX context; | 
    
      | 248 | int len; | 
    
      | 249 | unsigned char buffer[16], digest[16]; | 
    
      | 250 |  | 
    
      | 251 | MDInit (&context); | 
    
      | 252 | while (len = fread (buffer, 1, 16, stdin)) | 
    
      | 253 | MDUpdate (&context, buffer, len); | 
    
      | 254 | MDFinal (digest, &context); | 
    
      | 255 |  | 
    
      | 256 | MDPrint (digest); | 
    
      | 257 | printf ("\n"); | 
    
      | 258 | } | 
    
      | 259 |  | 
    
      | 260 | /* Prints a message digest in hexadecimal. | 
    
      | 261 | */ | 
    
      | 262 | static void MDPrint (digest) | 
    
      | 263 | unsigned char digest[16]; | 
    
      | 264 | { | 
    
      | 265 | unsigned int i; | 
    
      | 266 |  | 
    
      | 267 | for (i = 0; i < 16; i++) | 
    
      | 268 | printf ("%02x", digest[i]); | 
    
      | 269 | } |