md5.c revision 109870
16562Sphk/* 237421Scharnier * Derived from: 36562Sphk * 46562Sphk * MDDRIVER.C - test driver for MD2, MD4 and MD5 53995Spst */ 63995Spst 76562Sphk/* 86562Sphk * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All 96562Sphk * rights reserved. 106562Sphk * 116562Sphk * RSA Data Security, Inc. makes no representations concerning either 126562Sphk * the merchantability of this software or the suitability of this 136562Sphk * software for any particular purpose. It is provided "as is" 146562Sphk * without express or implied warranty of any kind. 156562Sphk * 166562Sphk * These notices must be retained in any copies of any part of this 176562Sphk * documentation and/or software. 183995Spst */ 193995Spst 2037421Scharnier#ifndef lint 2137421Scharnierstatic const char rcsid[] = 2250476Speter "$FreeBSD: head/sbin/md5/md5.c 109870 2003-01-26 08:23:37Z silby $"; 2337421Scharnier#endif /* not lint */ 2437421Scharnier 2519168Sbde#include <sys/types.h> 2637421Scharnier#include <err.h> 2719168Sbde#include <md5.h> 283995Spst#include <stdio.h> 2978949Sdes#include <stdlib.h> 3078949Sdes#include <string.h> 313995Spst#include <time.h> 3232074Ssteve#include <unistd.h> 3319168Sbde 346562Sphk/* 356562Sphk * Length of test block, number of test blocks. 363995Spst */ 3746226Skris#define TEST_BLOCK_LEN 10000 3846226Skris#define TEST_BLOCK_COUNT 100000 393995Spst 4054109Sobrienint qflag; 4152949Sobrienint rflag; 4288226Sphkint sflag; 4352949Sobrien 4476988Srustatic void MDString(const char *); 4576988Srustatic void MDTimeTrial(void); 4676988Srustatic void MDTestSuite(void); 4776988Srustatic void MDFilter(int); 4876988Srustatic void usage(void); 493995Spst 503995Spst/* Main driver. 513995Spst 523995SpstArguments (may be any combination): 533995Spst -sstring - digests string 543995Spst -t - runs time trial 553995Spst -x - runs test script 563995Spst filename - digests file 573995Spst (none) - digests standard input 583995Spst */ 596562Sphkint 6076988Srumain(int argc, char *argv[]) 613995Spst{ 6232086Ssteve int ch; 636562Sphk char *p; 649489Sphk char buf[33]; 653995Spst 6678756Sru while ((ch = getopt(argc, argv, "pqrs:tx")) != -1) 6776988Sru switch (ch) { 6876988Sru case 'p': 6976988Sru MDFilter(1); 7076988Sru break; 7176988Sru case 'q': 7276988Sru qflag = 1; 7376988Sru break; 7476988Sru case 'r': 7576988Sru rflag = 1; 7676988Sru break; 7776988Sru case 's': 7888226Sphk sflag = 1; 7976988Sru MDString(optarg); 8076988Sru break; 8176988Sru case 't': 8276988Sru MDTimeTrial(); 8376988Sru break; 8476988Sru case 'x': 8576988Sru MDTestSuite(); 8676988Sru break; 8776988Sru default: 8876988Sru usage(); 8932074Ssteve } 9076988Sru argc -= optind; 9176988Sru argv += optind; 9276988Sru 9376988Sru if (*argv) { 9476988Sru do { 9576988Sru p = MD5File(*argv, buf); 9632074Ssteve if (!p) 9776988Sru warn("%s", *argv); 9832074Ssteve else 9954109Sobrien if (qflag) 10054109Sobrien printf("%s\n", p); 10154109Sobrien else if (rflag) 10276988Sru printf("%s %s\n", p, *argv); 10352949Sobrien else 10476988Sru printf("MD5 (%s) = %s\n", *argv, p); 10576988Sru } while (*++argv); 10688226Sphk } else if (!sflag && (optind == 1 || qflag || rflag)) 1076725Sphk MDFilter(0); 1083995Spst 1096562Sphk return (0); 1103995Spst} 1116562Sphk/* 1126562Sphk * Digests a string and prints the result. 1133995Spst */ 1146562Sphkstatic void 11576988SruMDString(const char *string) 1163995Spst{ 11748953Sbillf size_t len = strlen(string); 1189489Sphk char buf[33]; 1193995Spst 12054109Sobrien if (qflag) 12154109Sobrien printf("%s\n", MD5Data(string, len, buf)); 12254109Sobrien else if (rflag) 12353092Sobrien printf("%s \"%s\"\n", MD5Data(string, len, buf), string); 12452949Sobrien else 12552949Sobrien printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf)); 1263995Spst} 1276562Sphk/* 1286562Sphk * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. 1293995Spst */ 1306562Sphkstatic void 13176988SruMDTimeTrial(void) 1323995Spst{ 1336562Sphk MD5_CTX context; 1346562Sphk time_t endTime, startTime; 1356725Sphk unsigned char block[TEST_BLOCK_LEN]; 1366562Sphk unsigned int i; 1379489Sphk char *p, buf[33]; 1383995Spst 1396562Sphk printf 1406562Sphk ("MD5 time trial. Digesting %d %d-byte blocks ...", 14121763Sphk TEST_BLOCK_COUNT, TEST_BLOCK_LEN); 14246226Skris fflush(stdout); 1433995Spst 1446562Sphk /* Initialize block */ 1456562Sphk for (i = 0; i < TEST_BLOCK_LEN; i++) 1466562Sphk block[i] = (unsigned char) (i & 0xff); 1473995Spst 1486562Sphk /* Start timer */ 1496562Sphk time(&startTime); 1503995Spst 1516562Sphk /* Digest blocks */ 1526562Sphk MD5Init(&context); 1536562Sphk for (i = 0; i < TEST_BLOCK_COUNT; i++) 1546562Sphk MD5Update(&context, block, TEST_BLOCK_LEN); 1559489Sphk p = MD5End(&context,buf); 1563995Spst 1576562Sphk /* Stop timer */ 1586562Sphk time(&endTime); 1593995Spst 1606562Sphk printf(" done\n"); 1616562Sphk printf("Digest = %s", p); 1626562Sphk printf("\nTime = %ld seconds\n", (long) (endTime - startTime)); 1636562Sphk /* Be careful that endTime-startTime is not zero. (Bug fix from Ric 1646562Sphk * Anderson, ric@Artisoft.COM.) */ 1656562Sphk printf 1666562Sphk ("Speed = %ld bytes/second\n", 16785611Sdillon (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (long)(endTime - startTime) : 1)); 1683995Spst} 1696562Sphk/* 1706562Sphk * Digests a reference suite of strings and prints the results. 1713995Spst */ 172109870Ssilby 173109870Ssilby#define MD5TESTCOUNT 8 174109870Ssilby 175109870Ssilbychar *MDTestInput[] = { 176109870Ssilby "", 177109870Ssilby "a", 178109870Ssilby "abc", 179109870Ssilby "message digest", 180109870Ssilby "abcdefghijklmnopqrstuvwxyz", 181109870Ssilby "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 182109870Ssilby "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 183109870Ssilby "MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt" 184109870Ssilby}; 185109870Ssilby 186109870Ssilbychar *MDTestOutput[MD5TESTCOUNT] = { 187109870Ssilby "d41d8cd98f00b204e9800998ecf8427e", 188109870Ssilby "0cc175b9c0f1b6a831c399e269772661", 189109870Ssilby "900150983cd24fb0d6963f7d28e17f72", 190109870Ssilby "f96b697d7cb7938d525a2f31aaf161d0", 191109870Ssilby "c3fcd3d76192e4007dfb496cca67e13b", 192109870Ssilby "d174ab98d277d9f5a5611c2c9f419d9f", 193109870Ssilby "57edf4a22be3c955ac49da2e2107b67a", 194109870Ssilby "b50663f41d44d92171cb9976bc118538" 195109870Ssilby}; 196109870Ssilby 1976562Sphkstatic void 19876988SruMDTestSuite(void) 1993995Spst{ 200109870Ssilby int i; 201109870Ssilby char buffer[33]; 20232086Ssteve 2036562Sphk printf("MD5 test suite:\n"); 204109870Ssilby for (i = 0; i < MD5TESTCOUNT; i++) { 205109870Ssilby MD5Data(MDTestInput[i], strlen(MDTestInput[i]), buffer); 206109870Ssilby printf("MD5 (\"%s\") = %s", MDTestInput[i], buffer); 207109870Ssilby if (strcmp(buffer, MDTestOutput[i]) == 0) 208109870Ssilby printf(" - verified correct\n"); 209109870Ssilby else 210109870Ssilby printf(" - INCORRECT RESULT!\n"); 211109870Ssilby } 2123995Spst} 2133995Spst 2146562Sphk/* 2156562Sphk * Digests the standard input and prints the result. 2163995Spst */ 2176562Sphkstatic void 21876988SruMDFilter(int tee) 2193995Spst{ 2206562Sphk MD5_CTX context; 22176988Sru unsigned int len; 22232074Ssteve unsigned char buffer[BUFSIZ]; 2239489Sphk char buf[33]; 2243995Spst 2256562Sphk MD5Init(&context); 22632074Ssteve while ((len = fread(buffer, 1, BUFSIZ, stdin))) { 22776988Sru if (tee && len != fwrite(buffer, 1, len, stdout)) 22837421Scharnier err(1, "stdout"); 2296562Sphk MD5Update(&context, buffer, len); 2306725Sphk } 2319489Sphk printf("%s\n", MD5End(&context,buf)); 2323995Spst} 23332074Ssteve 23432074Sstevestatic void 23576988Sruusage(void) 23632074Ssteve{ 23732086Ssteve 23868503Sobrien fprintf(stderr, "usage: md5 [-pqrtx] [-s string] [files ...]\n"); 23932074Ssteve exit(1); 24032074Ssteve} 241