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 <stdlib.h> 30 #include <string.h> 31 #include <time.h> 32 #include <unistd.h> 33 34 /* 35 * Length of test block, number of test blocks. 36 */ 37 #define TEST_BLOCK_LEN 10000 38 #define TEST_BLOCK_COUNT 100000 39 40 int qflag; 41 int rflag; 42 43 static void MDString(const char *); 44 static void MDTimeTrial(void); 45 static void MDTestSuite(void); 46 static void MDFilter(int); 47 static void usage(void); 48 49 /* Main driver. 50 51 Arguments (may be any combination): 52 -sstring - digests string 53 -t - runs time trial 54 -x - runs test script 55 filename - digests file 56 (none) - digests standard input 57 */ 58 int 59 main(int argc, char *argv[]) 60 { 61 int ch; 62 char *p; 63 char buf[33]; 64 65 while ((ch = getopt(argc, argv, "pqrs:tx")) != -1) 66 switch (ch) { 67 case 'p': 68 MDFilter(1); 69 break; 70 case 'q': 71 qflag = 1; 72 break; 73 case 'r': 74 rflag = 1; 75 break; 76 case 's': 77 MDString(optarg); 78 break; 79 case 't': 80 MDTimeTrial(); 81 break; 82 case 'x': 83 MDTestSuite(); 84 break; 85 default: 86 usage(); 87 } 88 argc -= optind; 89 argv += optind; 90 91 if (*argv) { 92 do { 93 p = MD5File(*argv, buf); 94 if (!p) 95 warn("%s", *argv); 96 else 97 if (qflag) 98 printf("%s\n", p); 99 else if (rflag) 100 printf("%s %s\n", p, *argv); 101 else 102 printf("MD5 (%s) = %s\n", *argv, p); 103 } while (*++argv); 104 } else if (optind == 1 || qflag || rflag) 105 MDFilter(0); 106 107 return (0); 108 } 109 /* 110 * Digests a string and prints the result. 111 */ 112 static void 113 MDString(const char *string) 114 { 115 size_t len = strlen(string); 116 char buf[33]; 117 118 if (qflag) 119 printf("%s\n", MD5Data(string, len, buf)); 120 else if (rflag) 121 printf("%s \"%s\"\n", MD5Data(string, len, buf), string); 122 else 123 printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf)); 124 } 125 /* 126 * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. 127 */ 128 static void 129 MDTimeTrial(void) 130 { 131 MD5_CTX context; 132 time_t endTime, startTime; 133 unsigned char block[TEST_BLOCK_LEN]; 134 unsigned int i; 135 char *p, buf[33]; 136 137 printf 138 ("MD5 time trial. Digesting %d %d-byte blocks ...", 139 TEST_BLOCK_COUNT, TEST_BLOCK_LEN); 140 fflush(stdout); 141 142 /* Initialize block */ 143 for (i = 0; i < TEST_BLOCK_LEN; i++) 144 block[i] = (unsigned char) (i & 0xff); 145 146 /* Start timer */ 147 time(&startTime); 148 149 /* Digest blocks */ 150 MD5Init(&context); 151 for (i = 0; i < TEST_BLOCK_COUNT; i++) 152 MD5Update(&context, block, TEST_BLOCK_LEN); 153 p = MD5End(&context,buf); 154 155 /* Stop timer */ 156 time(&endTime); 157 158 printf(" done\n"); 159 printf("Digest = %s", p); 160 printf("\nTime = %ld seconds\n", (long) (endTime - startTime)); 161 /* Be careful that endTime-startTime is not zero. (Bug fix from Ric 162 * Anderson, ric@Artisoft.COM.) */ 163 printf 164 ("Speed = %ld bytes/second\n", 165 (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (endTime - startTime) : 1)); 166 } 167 /* 168 * Digests a reference suite of strings and prints the results. 169 */ 170 static void 171 MDTestSuite(void) 172 { 173 174 printf("MD5 test suite:\n"); 175 176 MDString(""); 177 MDString("a"); 178 MDString("abc"); 179 MDString("message digest"); 180 MDString("abcdefghijklmnopqrstuvwxyz"); 181 MDString 182 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); 183 MDString 184 ("1234567890123456789012345678901234567890\ 185 1234567890123456789012345678901234567890"); 186 } 187 188 /* 189 * Digests the standard input and prints the result. 190 */ 191 static void 192 MDFilter(int tee) 193 { 194 MD5_CTX context; 195 unsigned int len; 196 unsigned char buffer[BUFSIZ]; 197 char buf[33]; 198 199 MD5Init(&context); 200 while ((len = fread(buffer, 1, BUFSIZ, stdin))) { 201 if (tee && len != fwrite(buffer, 1, len, stdout)) 202 err(1, "stdout"); 203 MD5Update(&context, buffer, len); 204 } 205 printf("%s\n", MD5End(&context,buf)); 206 } 207 208 static void 209 usage(void) 210 { 211 212 fprintf(stderr, "usage: md5 [-pqrtx] [-s string] [files ...]\n"); 213 exit(1); 214 } 215