19b1fd0e5SPoul-Henning Kamp /* 29b1fd0e5SPoul-Henning Kamp * Derived from: 323b5892fSPhilippe Charnier * 49b1fd0e5SPoul-Henning Kamp * MDDRIVER.C - test driver for MD2, MD4 and MD5 5e1645093SPaul Traina */ 6e1645093SPaul Traina 79b1fd0e5SPoul-Henning Kamp /* 89b1fd0e5SPoul-Henning Kamp * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All 99b1fd0e5SPoul-Henning Kamp * rights reserved. 109b1fd0e5SPoul-Henning Kamp * 119b1fd0e5SPoul-Henning Kamp * RSA Data Security, Inc. makes no representations concerning either 129b1fd0e5SPoul-Henning Kamp * the merchantability of this software or the suitability of this 139b1fd0e5SPoul-Henning Kamp * software for any particular purpose. It is provided "as is" 149b1fd0e5SPoul-Henning Kamp * without express or implied warranty of any kind. 159b1fd0e5SPoul-Henning Kamp * 169b1fd0e5SPoul-Henning Kamp * These notices must be retained in any copies of any part of this 179b1fd0e5SPoul-Henning Kamp * documentation and/or software. 18e1645093SPaul Traina */ 19e1645093SPaul Traina 2023b5892fSPhilippe Charnier #ifndef lint 2123b5892fSPhilippe Charnier static const char rcsid[] = 227f3dea24SPeter Wemm "$FreeBSD$"; 2323b5892fSPhilippe Charnier #endif /* not lint */ 24e1645093SPaul Traina 2523b5892fSPhilippe Charnier #include <sys/types.h> 2623b5892fSPhilippe Charnier #include <err.h> 2723b5892fSPhilippe Charnier #include <md5.h> 281ab6205cSBruce Evans #include <stdio.h> 291ab6205cSBruce Evans #include <time.h> 30716847a6SSteve Price #include <unistd.h> 31b76bf6fcSBill Fumerola #include <string.h> 321ab6205cSBruce Evans 331ab6205cSBruce Evans #include "global.h" 341ab6205cSBruce Evans 359b1fd0e5SPoul-Henning Kamp /* 369b1fd0e5SPoul-Henning Kamp * Length of test block, number of test blocks. 37e1645093SPaul Traina */ 3893606d6eSKris Kennaway #define TEST_BLOCK_LEN 10000 3993606d6eSKris Kennaway #define TEST_BLOCK_COUNT 100000 40e1645093SPaul Traina 419e18a3bdSDavid E. O'Brien int rflag; 429e18a3bdSDavid E. O'Brien 43e1645093SPaul Traina static void MDString PROTO_LIST((char *)); 44e1645093SPaul Traina static void MDTimeTrial PROTO_LIST((void)); 45e1645093SPaul Traina static void MDTestSuite PROTO_LIST((void)); 4623b406e1SPoul-Henning Kamp static void MDFilter PROTO_LIST((int)); 47716847a6SSteve Price static void usage PROTO_LIST((void)); 48e1645093SPaul Traina 49e1645093SPaul Traina /* Main driver. 50e1645093SPaul Traina 51e1645093SPaul Traina Arguments (may be any combination): 52e1645093SPaul Traina -sstring - digests string 53e1645093SPaul Traina -t - runs time trial 54e1645093SPaul Traina -x - runs test script 55e1645093SPaul Traina filename - digests file 56e1645093SPaul Traina (none) - digests standard input 57e1645093SPaul Traina */ 589b1fd0e5SPoul-Henning Kamp int 599b1fd0e5SPoul-Henning Kamp main(argc, argv) 60e1645093SPaul Traina int argc; 61e1645093SPaul Traina char *argv[]; 62e1645093SPaul Traina { 639a9791afSSteve Price int ch; 649b1fd0e5SPoul-Henning Kamp char *p; 65116805fdSPoul-Henning Kamp char buf[33]; 66e1645093SPaul Traina 67716847a6SSteve Price if (argc > 1) { 689e18a3bdSDavid E. O'Brien while ((ch = getopt(argc, argv, "ps:rtx")) != -1) { 699a9791afSSteve Price switch (ch) { 70716847a6SSteve Price case 'p': 7123b406e1SPoul-Henning Kamp MDFilter(1); 72716847a6SSteve Price break; 739e18a3bdSDavid E. O'Brien case 'r': 749e18a3bdSDavid E. O'Brien rflag = 1; 759e18a3bdSDavid E. O'Brien break; 76716847a6SSteve Price case 's': 77716847a6SSteve Price MDString(optarg); 78716847a6SSteve Price break; 79716847a6SSteve Price case 't': 80716847a6SSteve Price MDTimeTrial(); 81716847a6SSteve Price break; 82716847a6SSteve Price case 'x': 83e1645093SPaul Traina MDTestSuite(); 84716847a6SSteve Price break; 85716847a6SSteve Price default: 86716847a6SSteve Price usage(); 879b1fd0e5SPoul-Henning Kamp } 88716847a6SSteve Price } 89716847a6SSteve Price while (optind < argc) { 90716847a6SSteve Price p = MD5File(argv[optind], buf); 91716847a6SSteve Price if (!p) 9223b5892fSPhilippe Charnier warn("%s", argv[optind]); 93e1645093SPaul Traina else 949e18a3bdSDavid E. O'Brien if (rflag) 959e18a3bdSDavid E. O'Brien printf("MD5 %s %s\n", p, argv[optind]); 969e18a3bdSDavid E. O'Brien else 979e18a3bdSDavid E. O'Brien printf("MD5 (%s) = %s\n", argv[optind], 989e18a3bdSDavid E. O'Brien p); 99716847a6SSteve Price optind++; 100716847a6SSteve Price } 101716847a6SSteve Price } else 10223b406e1SPoul-Henning Kamp MDFilter(0); 103e1645093SPaul Traina 104e1645093SPaul Traina return (0); 105e1645093SPaul Traina } 1069b1fd0e5SPoul-Henning Kamp /* 1079b1fd0e5SPoul-Henning Kamp * Digests a string and prints the result. 108e1645093SPaul Traina */ 1099b1fd0e5SPoul-Henning Kamp static void 1109b1fd0e5SPoul-Henning Kamp MDString(string) 111e1645093SPaul Traina char *string; 112e1645093SPaul Traina { 113b76bf6fcSBill Fumerola size_t len = strlen(string); 114116805fdSPoul-Henning Kamp char buf[33]; 115e1645093SPaul Traina 1169e18a3bdSDavid E. O'Brien if (rflag) 1179e18a3bdSDavid E. O'Brien printf("MD5 %s (\"%s\")\n", MD5Data(string, len, buf), string); 1189e18a3bdSDavid E. O'Brien else 119116805fdSPoul-Henning Kamp printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf)); 120e1645093SPaul Traina } 1219b1fd0e5SPoul-Henning Kamp /* 1229b1fd0e5SPoul-Henning Kamp * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. 123e1645093SPaul Traina */ 1249b1fd0e5SPoul-Henning Kamp static void 1259b1fd0e5SPoul-Henning Kamp MDTimeTrial() 126e1645093SPaul Traina { 1279b1fd0e5SPoul-Henning Kamp MD5_CTX context; 128e1645093SPaul Traina time_t endTime, startTime; 12923b406e1SPoul-Henning Kamp unsigned char block[TEST_BLOCK_LEN]; 130e1645093SPaul Traina unsigned int i; 131116805fdSPoul-Henning Kamp char *p, buf[33]; 132e1645093SPaul Traina 133e1645093SPaul Traina printf 1349b1fd0e5SPoul-Henning Kamp ("MD5 time trial. Digesting %d %d-byte blocks ...", 1351d0847d3SPoul-Henning Kamp TEST_BLOCK_COUNT, TEST_BLOCK_LEN); 13693606d6eSKris Kennaway fflush(stdout); 137e1645093SPaul Traina 138e1645093SPaul Traina /* Initialize block */ 139e1645093SPaul Traina for (i = 0; i < TEST_BLOCK_LEN; i++) 140e1645093SPaul Traina block[i] = (unsigned char) (i & 0xff); 141e1645093SPaul Traina 142e1645093SPaul Traina /* Start timer */ 143e1645093SPaul Traina time(&startTime); 144e1645093SPaul Traina 145e1645093SPaul Traina /* Digest blocks */ 1469b1fd0e5SPoul-Henning Kamp MD5Init(&context); 147e1645093SPaul Traina for (i = 0; i < TEST_BLOCK_COUNT; i++) 1489b1fd0e5SPoul-Henning Kamp MD5Update(&context, block, TEST_BLOCK_LEN); 149116805fdSPoul-Henning Kamp p = MD5End(&context,buf); 150e1645093SPaul Traina 151e1645093SPaul Traina /* Stop timer */ 152e1645093SPaul Traina time(&endTime); 153e1645093SPaul Traina 154e1645093SPaul Traina printf(" done\n"); 1559b1fd0e5SPoul-Henning Kamp printf("Digest = %s", p); 156e1645093SPaul Traina printf("\nTime = %ld seconds\n", (long) (endTime - startTime)); 1579b1fd0e5SPoul-Henning Kamp /* Be careful that endTime-startTime is not zero. (Bug fix from Ric 1589b1fd0e5SPoul-Henning Kamp * Anderson, ric@Artisoft.COM.) */ 159e1645093SPaul Traina printf 160e1645093SPaul Traina ("Speed = %ld bytes/second\n", 161e1645093SPaul Traina (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (endTime - startTime) : 1)); 162e1645093SPaul Traina } 1639b1fd0e5SPoul-Henning Kamp /* 1649b1fd0e5SPoul-Henning Kamp * Digests a reference suite of strings and prints the results. 165e1645093SPaul Traina */ 1669b1fd0e5SPoul-Henning Kamp static void 1679b1fd0e5SPoul-Henning Kamp MDTestSuite() 168e1645093SPaul Traina { 1699a9791afSSteve Price 1709b1fd0e5SPoul-Henning Kamp printf("MD5 test suite:\n"); 171e1645093SPaul Traina 172e1645093SPaul Traina MDString(""); 173e1645093SPaul Traina MDString("a"); 174e1645093SPaul Traina MDString("abc"); 175e1645093SPaul Traina MDString("message digest"); 176e1645093SPaul Traina MDString("abcdefghijklmnopqrstuvwxyz"); 177e1645093SPaul Traina MDString 178e1645093SPaul Traina ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); 179e1645093SPaul Traina MDString 180e1645093SPaul Traina ("1234567890123456789012345678901234567890\ 181e1645093SPaul Traina 1234567890123456789012345678901234567890"); 182e1645093SPaul Traina } 183e1645093SPaul Traina 1849b1fd0e5SPoul-Henning Kamp /* 1859b1fd0e5SPoul-Henning Kamp * Digests the standard input and prints the result. 186e1645093SPaul Traina */ 1879b1fd0e5SPoul-Henning Kamp static void 1889a9791afSSteve Price MDFilter(pipe) 1899a9791afSSteve Price int pipe; 190e1645093SPaul Traina { 1919b1fd0e5SPoul-Henning Kamp MD5_CTX context; 192e1645093SPaul Traina int len; 193716847a6SSteve Price unsigned char buffer[BUFSIZ]; 194116805fdSPoul-Henning Kamp char buf[33]; 195e1645093SPaul Traina 1969b1fd0e5SPoul-Henning Kamp MD5Init(&context); 197716847a6SSteve Price while ((len = fread(buffer, 1, BUFSIZ, stdin))) { 19823b5892fSPhilippe Charnier if(pipe && (len != fwrite(buffer, 1, len, stdout))) 19923b5892fSPhilippe Charnier err(1, "stdout"); 2009b1fd0e5SPoul-Henning Kamp MD5Update(&context, buffer, len); 20123b406e1SPoul-Henning Kamp } 202116805fdSPoul-Henning Kamp printf("%s\n", MD5End(&context,buf)); 203e1645093SPaul Traina } 204716847a6SSteve Price 205716847a6SSteve Price static void 2069a9791afSSteve Price usage() 207716847a6SSteve Price { 2089a9791afSSteve Price 2099a9791afSSteve Price fprintf(stderr, "usage: md5 [-ptx] [-s string] [files ...]\n"); 210716847a6SSteve Price exit(1); 211716847a6SSteve Price } 212