md5.c revision 109870
11541Srgrimes/* 21541Srgrimes * Derived from: 31541Srgrimes * 41541Srgrimes * MDDRIVER.C - test driver for MD2, MD4 and MD5 51541Srgrimes */ 61541Srgrimes 71541Srgrimes/* 81541Srgrimes * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All 91541Srgrimes * rights reserved. 101541Srgrimes * 111541Srgrimes * RSA Data Security, Inc. makes no representations concerning either 121541Srgrimes * the merchantability of this software or the suitability of this 131541Srgrimes * software for any particular purpose. It is provided "as is" 141541Srgrimes * without express or implied warranty of any kind. 151541Srgrimes * 161541Srgrimes * These notices must be retained in any copies of any part of this 171541Srgrimes * documentation and/or software. 181541Srgrimes */ 191541Srgrimes 201541Srgrimes#ifndef lint 211541Srgrimesstatic const char rcsid[] = 221541Srgrimes "$FreeBSD: head/sbin/md5/md5.c 109870 2003-01-26 08:23:37Z silby $"; 231541Srgrimes#endif /* not lint */ 241541Srgrimes 251541Srgrimes#include <sys/types.h> 261541Srgrimes#include <err.h> 271541Srgrimes#include <md5.h> 281541Srgrimes#include <stdio.h> 291541Srgrimes#include <stdlib.h> 301541Srgrimes#include <string.h> 311541Srgrimes#include <time.h> 321541Srgrimes#include <unistd.h> 331541Srgrimes 3441087Struckman/* 351541Srgrimes * Length of test block, number of test blocks. 361541Srgrimes */ 371541Srgrimes#define TEST_BLOCK_LEN 10000 381541Srgrimes#define TEST_BLOCK_COUNT 100000 391541Srgrimes 401541Srgrimesint qflag; 4132726Seivindint rflag; 4232726Seivindint sflag; 431541Srgrimes 441541Srgrimesstatic void MDString(const char *); 4512577Sbdestatic void MDTimeTrial(void); 461541Srgrimesstatic void MDTestSuite(void); 471541Srgrimesstatic void MDFilter(int); 4824206Sbdestatic void usage(void); 4924206Sbde 501541Srgrimes/* Main driver. 513308Sphk 5212517SjulianArguments (may be any combination): 5329357Speter -sstring - digests string 5441086Struckman -t - runs time trial 5512517Sjulian -x - runs test script 5612517Sjulian filename - digests file 5712517Sjulian (none) - digests standard input 5812517Sjulian */ 591541Srgrimesint 601541Srgrimesmain(int argc, char *argv[]) 611541Srgrimes{ 621541Srgrimes int ch; 631541Srgrimes char *p; 6412675Sjulian char buf[33]; 6512675Sjulian 6612675Sjulian while ((ch = getopt(argc, argv, "pqrs:tx")) != -1) 6712675Sjulian switch (ch) { 6829357Speter case 'p': 6912675Sjulian MDFilter(1); 7012675Sjulian break; 7112678Sphk case 'q': 7212675Sjulian qflag = 1; 7312675Sjulian break; 7429357Speter case 'r': 7512675Sjulian rflag = 1; 7612819Sphk break; 771541Srgrimes case 's': 781541Srgrimes sflag = 1; 7941087Struckman MDString(optarg); 801541Srgrimes break; 811541Srgrimes case 't': 821541Srgrimes MDTimeTrial(); 831541Srgrimes break; 841541Srgrimes case 'x': 8512675Sjulian MDTestSuite(); 861541Srgrimes break; 871541Srgrimes default: 881541Srgrimes usage(); 891541Srgrimes } 901541Srgrimes argc -= optind; 911541Srgrimes argv += optind; 921541Srgrimes 931541Srgrimes if (*argv) { 9441086Struckman do { 951541Srgrimes p = MD5File(*argv, buf); 961541Srgrimes if (!p) 971541Srgrimes warn("%s", *argv); 981541Srgrimes else 9912675Sjulian if (qflag) 1001541Srgrimes printf("%s\n", p); 1011541Srgrimes else if (rflag) 1021541Srgrimes printf("%s %s\n", p, *argv); 1031541Srgrimes else 1041541Srgrimes printf("MD5 (%s) = %s\n", *argv, p); 1051541Srgrimes } while (*++argv); 1061541Srgrimes } else if (!sflag && (optind == 1 || qflag || rflag)) 1071541Srgrimes MDFilter(0); 10841086Struckman 1091541Srgrimes return (0); 1101541Srgrimes} 1111541Srgrimes/* 1121541Srgrimes * Digests a string and prints the result. 11312675Sjulian */ 1141541Srgrimesstatic void 1151541SrgrimesMDString(const char *string) 1161541Srgrimes{ 1171541Srgrimes size_t len = strlen(string); 1181541Srgrimes char buf[33]; 1191541Srgrimes 1201541Srgrimes if (qflag) 1211541Srgrimes printf("%s\n", MD5Data(string, len, buf)); 1221541Srgrimes else if (rflag) 1231541Srgrimes printf("%s \"%s\"\n", MD5Data(string, len, buf), string); 1241541Srgrimes else 1251541Srgrimes printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf)); 1261541Srgrimes} 1271541Srgrimes/* 1281541Srgrimes * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. 1291541Srgrimes */ 1301541Srgrimesstatic void 1313098SphkMDTimeTrial(void) 1323098Sphk{ 1331541Srgrimes MD5_CTX context; 1341541Srgrimes time_t endTime, startTime; 1351541Srgrimes unsigned char block[TEST_BLOCK_LEN]; 1361541Srgrimes unsigned int i; 1371541Srgrimes char *p, buf[33]; 1381541Srgrimes 1391541Srgrimes printf 1401541Srgrimes ("MD5 time trial. Digesting %d %d-byte blocks ...", 1411541Srgrimes TEST_BLOCK_COUNT, TEST_BLOCK_LEN); 1421541Srgrimes fflush(stdout); 14336179Sphk 1441541Srgrimes /* Initialize block */ 1451541Srgrimes for (i = 0; i < TEST_BLOCK_LEN; i++) 1461541Srgrimes block[i] = (unsigned char) (i & 0xff); 14736179Sphk 14836179Sphk /* Start timer */ 1491541Srgrimes time(&startTime); 1501541Srgrimes 1511541Srgrimes /* Digest blocks */ 15236179Sphk MD5Init(&context); 1531541Srgrimes for (i = 0; i < TEST_BLOCK_COUNT; i++) 1541541Srgrimes MD5Update(&context, block, TEST_BLOCK_LEN); 1551541Srgrimes p = MD5End(&context,buf); 1561541Srgrimes 1571541Srgrimes /* Stop timer */ 1581541Srgrimes time(&endTime); 15912675Sjulian 16029357Speter printf(" done\n"); 1611541Srgrimes printf("Digest = %s", p); 16229357Speter printf("\nTime = %ld seconds\n", (long) (endTime - startTime)); 1631541Srgrimes /* Be careful that endTime-startTime is not zero. (Bug fix from Ric 1641541Srgrimes * Anderson, ric@Artisoft.COM.) */ 16529357Speter printf 16629357Speter ("Speed = %ld bytes/second\n", 1671541Srgrimes (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (long)(endTime - startTime) : 1)); 16829357Speter} 1691541Srgrimes/* 17029357Speter * Digests a reference suite of strings and prints the results. 17129357Speter */ 17229357Speter 17329357Speter#define MD5TESTCOUNT 8 17429357Speter 17529357Speterchar *MDTestInput[] = { 1761541Srgrimes "", 17729357Speter "a", 1781541Srgrimes "abc", 1791541Srgrimes "message digest", 1801549Srgrimes "abcdefghijklmnopqrstuvwxyz", 1811541Srgrimes "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1821541Srgrimes "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 1831541Srgrimes "MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt" 1841541Srgrimes}; 1851541Srgrimes 1861541Srgrimeschar *MDTestOutput[MD5TESTCOUNT] = { 1871541Srgrimes "d41d8cd98f00b204e9800998ecf8427e", 18841086Struckman "0cc175b9c0f1b6a831c399e269772661", 18941086Struckman "900150983cd24fb0d6963f7d28e17f72", 1901541Srgrimes "f96b697d7cb7938d525a2f31aaf161d0", 1911541Srgrimes "c3fcd3d76192e4007dfb496cca67e13b", 1921541Srgrimes "d174ab98d277d9f5a5611c2c9f419d9f", 1931541Srgrimes "57edf4a22be3c955ac49da2e2107b67a", 1941541Srgrimes "b50663f41d44d92171cb9976bc118538" 1951541Srgrimes}; 1961541Srgrimes 19712675Sjulianstatic void 1981541SrgrimesMDTestSuite(void) 1991541Srgrimes{ 20036735Sdfr int i; 2011541Srgrimes char buffer[33]; 2021541Srgrimes 2031541Srgrimes printf("MD5 test suite:\n"); 2041541Srgrimes for (i = 0; i < MD5TESTCOUNT; i++) { 2051541Srgrimes MD5Data(MDTestInput[i], strlen(MDTestInput[i]), buffer); 2061541Srgrimes printf("MD5 (\"%s\") = %s", MDTestInput[i], buffer); 2071541Srgrimes if (strcmp(buffer, MDTestOutput[i]) == 0) 2081541Srgrimes printf(" - verified correct\n"); 2091541Srgrimes else 2101541Srgrimes printf(" - INCORRECT RESULT!\n"); 2111541Srgrimes } 2121541Srgrimes} 2131541Srgrimes 2141541Srgrimes/* 2151541Srgrimes * Digests the standard input and prints the result. 21636179Sphk */ 2171541Srgrimesstatic void 2181541SrgrimesMDFilter(int tee) 2191541Srgrimes{ 2201541Srgrimes MD5_CTX context; 2211541Srgrimes unsigned int len; 2221541Srgrimes unsigned char buffer[BUFSIZ]; 2231541Srgrimes char buf[33]; 2241541Srgrimes 2251541Srgrimes MD5Init(&context); 2261541Srgrimes while ((len = fread(buffer, 1, BUFSIZ, stdin))) { 2271541Srgrimes if (tee && len != fwrite(buffer, 1, len, stdout)) 2281541Srgrimes err(1, "stdout"); 2291541Srgrimes MD5Update(&context, buffer, len); 23041086Struckman } 23141086Struckman printf("%s\n", MD5End(&context,buf)); 23241086Struckman} 23341086Struckman 23441086Struckmanstatic void 2351541Srgrimesusage(void) 2361541Srgrimes{ 23741086Struckman 23841086Struckman fprintf(stderr, "usage: md5 [-pqrtx] [-s string] [files ...]\n"); 23941086Struckman exit(1); 24041086Struckman} 24141086Struckman