md5.c revision 54109
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 54109 1999-12-04 01:29:43Z obrien $";
2337421Scharnier#endif /* not lint */
2437421Scharnier
2519168Sbde#include <sys/types.h>
2637421Scharnier#include <err.h>
2719168Sbde#include <md5.h>
283995Spst#include <stdio.h>
293995Spst#include <time.h>
3032074Ssteve#include <unistd.h>
3148953Sbillf#include <string.h>
3219168Sbde
333995Spst#include "global.h"
343995Spst
356562Sphk/*
366562Sphk * Length of test block, number of test blocks.
373995Spst */
3846226Skris#define TEST_BLOCK_LEN 10000
3946226Skris#define TEST_BLOCK_COUNT 100000
403995Spst
4154109Sobrienint qflag;
4252949Sobrienint rflag;
4352949Sobrien
446562Sphkstatic void MDString PROTO_LIST((char *));
456562Sphkstatic void MDTimeTrial PROTO_LIST((void));
466562Sphkstatic void MDTestSuite PROTO_LIST((void));
476725Sphkstatic void MDFilter PROTO_LIST((int));
4832074Sstevestatic void usage PROTO_LIST((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
606562Sphkmain(argc, argv)
616562Sphk	int     argc;
626562Sphk	char   *argv[];
633995Spst{
6432086Ssteve	int     ch;
656562Sphk	char   *p;
669489Sphk	char	buf[33];
673995Spst
6832074Ssteve	if (argc > 1) {
6954109Sobrien		while ((ch = getopt(argc, argv, "ps:qrtx")) != -1) {
7032086Ssteve			switch (ch) {
7132074Ssteve			case 'p':
7232074Ssteve				MDFilter(1);
7332074Ssteve				break;
7454109Sobrien			case 'q':
7554109Sobrien				qflag = 1;
7654109Sobrien				break;
7752949Sobrien			case 'r':
7852949Sobrien				rflag = 1;
7952949Sobrien				break;
8032074Ssteve			case 's':
8132074Ssteve				MDString(optarg);
8232074Ssteve				break;
8332074Ssteve			case 't':
846562Sphk				MDTimeTrial();
8532074Ssteve				break;
8632074Ssteve			case 'x':
876562Sphk				MDTestSuite();
8832074Ssteve				break;
8932074Ssteve			default:
9032074Ssteve				usage();
916562Sphk			}
9232074Ssteve		}
9332074Ssteve		while (optind < argc) {
9432074Ssteve			p = MD5File(argv[optind], buf);
9532074Ssteve			if (!p)
9637421Scharnier				warn("%s", argv[optind]);
9732074Ssteve			else
9854109Sobrien				if (qflag)
9954109Sobrien					printf("%s\n", p);
10054109Sobrien				else if (rflag)
10153060Sobrien					printf("%s %s\n", p, argv[optind]);
10252949Sobrien				else
10352949Sobrien					printf("MD5 (%s) = %s\n", argv[optind],
10452949Sobrien					    p);
10532074Ssteve			optind++;
10632074Ssteve		}
10732074Ssteve	} else
1086725Sphk		MDFilter(0);
1093995Spst
1106562Sphk	return (0);
1113995Spst}
1126562Sphk/*
1136562Sphk * Digests a string and prints the result.
1143995Spst */
1156562Sphkstatic void
1166562SphkMDString(string)
1176562Sphk	char   *string;
1183995Spst{
11948953Sbillf	size_t len = strlen(string);
1209489Sphk	char buf[33];
1213995Spst
12254109Sobrien	if (qflag)
12354109Sobrien		printf("%s\n", MD5Data(string, len, buf));
12454109Sobrien	else if (rflag)
12553092Sobrien		printf("%s \"%s\"\n", MD5Data(string, len, buf), string);
12652949Sobrien	else
12752949Sobrien		printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf));
1283995Spst}
1296562Sphk/*
1306562Sphk * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks.
1313995Spst */
1326562Sphkstatic void
1336562SphkMDTimeTrial()
1343995Spst{
1356562Sphk	MD5_CTX context;
1366562Sphk	time_t  endTime, startTime;
1376725Sphk	unsigned char block[TEST_BLOCK_LEN];
1386562Sphk	unsigned int i;
1399489Sphk	char   *p, buf[33];
1403995Spst
1416562Sphk	printf
1426562Sphk	    ("MD5 time trial. Digesting %d %d-byte blocks ...",
14321763Sphk	    TEST_BLOCK_COUNT, TEST_BLOCK_LEN);
14446226Skris	fflush(stdout);
1453995Spst
1466562Sphk	/* Initialize block */
1476562Sphk	for (i = 0; i < TEST_BLOCK_LEN; i++)
1486562Sphk		block[i] = (unsigned char) (i & 0xff);
1493995Spst
1506562Sphk	/* Start timer */
1516562Sphk	time(&startTime);
1523995Spst
1536562Sphk	/* Digest blocks */
1546562Sphk	MD5Init(&context);
1556562Sphk	for (i = 0; i < TEST_BLOCK_COUNT; i++)
1566562Sphk		MD5Update(&context, block, TEST_BLOCK_LEN);
1579489Sphk	p = MD5End(&context,buf);
1583995Spst
1596562Sphk	/* Stop timer */
1606562Sphk	time(&endTime);
1613995Spst
1626562Sphk	printf(" done\n");
1636562Sphk	printf("Digest = %s", p);
1646562Sphk	printf("\nTime = %ld seconds\n", (long) (endTime - startTime));
1656562Sphk	/* Be careful that endTime-startTime is not zero. (Bug fix from Ric
1666562Sphk	 * Anderson, ric@Artisoft.COM.) */
1676562Sphk	printf
1686562Sphk	    ("Speed = %ld bytes/second\n",
1696562Sphk	    (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (endTime - startTime) : 1));
1703995Spst}
1716562Sphk/*
1726562Sphk * Digests a reference suite of strings and prints the results.
1733995Spst */
1746562Sphkstatic void
1756562SphkMDTestSuite()
1763995Spst{
17732086Ssteve
1786562Sphk	printf("MD5 test suite:\n");
1793995Spst
1806562Sphk	MDString("");
1816562Sphk	MDString("a");
1826562Sphk	MDString("abc");
1836562Sphk	MDString("message digest");
1846562Sphk	MDString("abcdefghijklmnopqrstuvwxyz");
1856562Sphk	MDString
1866562Sphk	    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1876562Sphk	MDString
1886562Sphk	    ("1234567890123456789012345678901234567890\
1893995Spst1234567890123456789012345678901234567890");
1903995Spst}
1913995Spst
1926562Sphk/*
1936562Sphk * Digests the standard input and prints the result.
1943995Spst */
1956562Sphkstatic void
19632086SsteveMDFilter(pipe)
19732086Ssteve	int pipe;
1983995Spst{
1996562Sphk	MD5_CTX context;
2006562Sphk	int     len;
20132074Ssteve	unsigned char buffer[BUFSIZ];
2029489Sphk	char buf[33];
2033995Spst
2046562Sphk	MD5Init(&context);
20532074Ssteve	while ((len = fread(buffer, 1, BUFSIZ, stdin))) {
20637421Scharnier		if(pipe && (len != fwrite(buffer, 1, len, stdout)))
20737421Scharnier			err(1, "stdout");
2086562Sphk		MD5Update(&context, buffer, len);
2096725Sphk	}
2109489Sphk	printf("%s\n", MD5End(&context,buf));
2113995Spst}
21232074Ssteve
21332074Sstevestatic void
21432086Ssteveusage()
21532074Ssteve{
21632086Ssteve
21732086Ssteve	fprintf(stderr, "usage: md5 [-ptx] [-s string] [files ...]\n");
21832074Ssteve	exit(1);
21932074Ssteve}
220