1 /* 2 * Derived from: 3 * 4 * MDDRIVER.C - test driver for MD2, MD4 and MD5 5 */ 6 7 /* 8 * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All 9 * rights reserved. 10 * 11 * RSA Data Security, Inc. makes no representations concerning either 12 * the merchantability of this software or the suitability of this 13 * software for any particular purpose. It is provided "as is" 14 * without express or implied warranty of any kind. 15 * 16 * These notices must be retained in any copies of any part of this 17 * documentation and/or software. 18 */ 19 20 #ifndef lint 21 static const char rcsid[] = 22 "$FreeBSD$"; 23 #endif /* not lint */ 24 25 #include <sys/types.h> 26 #include <err.h> 27 #include <md5.h> 28 #include <stdio.h> 29 #include <time.h> 30 #include <unistd.h> 31 #include <string.h> 32 33 /* 34 * Length of test block, number of test blocks. 35 */ 36 #define TEST_BLOCK_LEN 10000 37 #define TEST_BLOCK_COUNT 100000 38 39 int qflag; 40 int rflag; 41 42 static void MDString(const char *); 43 static void MDTimeTrial(void); 44 static void MDTestSuite(void); 45 static void MDFilter(int); 46 static void usage(void); 47 48 /* Main driver. 49 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 58 main(int argc, char *argv[]) 59 { 60 int ch; 61 char *p; 62 char buf[33]; 63 64 while ((ch = getopt(argc, argv, "ps:qrtx")) != -1) 65 switch (ch) { 66 case 'p': 67 MDFilter(1); 68 break; 69 case 'q': 70 qflag = 1; 71 break; 72 case 'r': 73 rflag = 1; 74 break; 75 case 's': 76 MDString(optarg); 77 break; 78 case 't': 79 MDTimeTrial(); 80 break; 81 case 'x': 82 MDTestSuite(); 83 break; 84 default: 85 usage(); 86 } 87 argc -= optind; 88 argv += optind; 89 90 if (*argv) { 91 do { 92 p = MD5File(*argv, buf); 93 if (!p) 94 warn("%s", *argv); 95 else 96 if (qflag) 97 printf("%s\n", p); 98 else if (rflag) 99 printf("%s %s\n", p, *argv); 100 else 101 printf("MD5 (%s) = %s\n", *argv, p); 102 } while (*++argv); 103 } else 104 MDFilter(0); 105 106 return (0); 107 } 108 /* 109 * Digests a string and prints the result. 110 */ 111 static void 112 MDString(const char *string) 113 { 114 size_t len = strlen(string); 115 char buf[33]; 116 117 if (qflag) 118 printf("%s\n", MD5Data(string, len, buf)); 119 else if (rflag) 120 printf("%s \"%s\"\n", MD5Data(string, len, buf), string); 121 else 122 printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf)); 123 } 124 /* 125 * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. 126 */ 127 static void 128 MDTimeTrial(void) 129 { 130 MD5_CTX context; 131 time_t endTime, startTime; 132 unsigned char block[TEST_BLOCK_LEN]; 133 unsigned int i; 134 char *p, buf[33]; 135 136 printf 137 ("MD5 time trial. Digesting %d %d-byte blocks ...", 138 TEST_BLOCK_COUNT, TEST_BLOCK_LEN); 139 fflush(stdout); 140 141 /* Initialize block */ 142 for (i = 0; i < TEST_BLOCK_LEN; i++) 143 block[i] = (unsigned char) (i & 0xff); 144 145 /* Start timer */ 146 time(&startTime); 147 148 /* Digest blocks */ 149 MD5Init(&context); 150 for (i = 0; i < TEST_BLOCK_COUNT; i++) 151 MD5Update(&context, block, TEST_BLOCK_LEN); 152 p = MD5End(&context,buf); 153 154 /* Stop timer */ 155 time(&endTime); 156 157 printf(" done\n"); 158 printf("Digest = %s", p); 159 printf("\nTime = %ld seconds\n", (long) (endTime - startTime)); 160 /* Be careful that endTime-startTime is not zero. (Bug fix from Ric 161 * Anderson, ric@Artisoft.COM.) */ 162 printf 163 ("Speed = %ld bytes/second\n", 164 (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (endTime - startTime) : 1)); 165 } 166 /* 167 * Digests a reference suite of strings and prints the results. 168 */ 169 static void 170 MDTestSuite(void) 171 { 172 173 printf("MD5 test suite:\n"); 174 175 MDString(""); 176 MDString("a"); 177 MDString("abc"); 178 MDString("message digest"); 179 MDString("abcdefghijklmnopqrstuvwxyz"); 180 MDString 181 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); 182 MDString 183 ("1234567890123456789012345678901234567890\ 184 1234567890123456789012345678901234567890"); 185 } 186 187 /* 188 * Digests the standard input and prints the result. 189 */ 190 static void 191 MDFilter(int tee) 192 { 193 MD5_CTX context; 194 unsigned int len; 195 unsigned char buffer[BUFSIZ]; 196 char buf[33]; 197 198 MD5Init(&context); 199 while ((len = fread(buffer, 1, BUFSIZ, stdin))) { 200 if (tee && len != fwrite(buffer, 1, len, stdout)) 201 err(1, "stdout"); 202 MD5Update(&context, buffer, len); 203 } 204 printf("%s\n", MD5End(&context,buf)); 205 } 206 207 static void 208 usage(void) 209 { 210 211 fprintf(stderr, "usage: md5 [-pqrtx] [-s string] [files ...]\n"); 212 exit(1); 213 } 214