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