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