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