md5.c revision 53060
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 53060 1999-11-09 17:28:47Z 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
4152949Sobrienint rflag;
4252949Sobrien
436562Sphkstatic void MDString PROTO_LIST((char *));
446562Sphkstatic void MDTimeTrial PROTO_LIST((void));
456562Sphkstatic void MDTestSuite PROTO_LIST((void));
466725Sphkstatic void MDFilter PROTO_LIST((int));
4732074Sstevestatic void usage PROTO_LIST((void));
483995Spst
493995Spst/* Main driver.
503995Spst
513995SpstArguments (may be any combination):
523995Spst  -sstring - digests string
533995Spst  -t       - runs time trial
543995Spst  -x       - runs test script
553995Spst  filename - digests file
563995Spst  (none)   - digests standard input
573995Spst */
586562Sphkint
596562Sphkmain(argc, argv)
606562Sphk	int     argc;
616562Sphk	char   *argv[];
623995Spst{
6332086Ssteve	int     ch;
646562Sphk	char   *p;
659489Sphk	char	buf[33];
663995Spst
6732074Ssteve	if (argc > 1) {
6852949Sobrien		while ((ch = getopt(argc, argv, "ps:rtx")) != -1) {
6932086Ssteve			switch (ch) {
7032074Ssteve			case 'p':
7132074Ssteve				MDFilter(1);
7232074Ssteve				break;
7352949Sobrien			case 'r':
7452949Sobrien				rflag = 1;
7552949Sobrien				break;
7632074Ssteve			case 's':
7732074Ssteve				MDString(optarg);
7832074Ssteve				break;
7932074Ssteve			case 't':
806562Sphk				MDTimeTrial();
8132074Ssteve				break;
8232074Ssteve			case 'x':
836562Sphk				MDTestSuite();
8432074Ssteve				break;
8532074Ssteve			default:
8632074Ssteve				usage();
876562Sphk			}
8832074Ssteve		}
8932074Ssteve		while (optind < argc) {
9032074Ssteve			p = MD5File(argv[optind], buf);
9132074Ssteve			if (!p)
9237421Scharnier				warn("%s", argv[optind]);
9332074Ssteve			else
9452949Sobrien				if (rflag)
9553060Sobrien					printf("%s %s\n", p, argv[optind]);
9652949Sobrien				else
9752949Sobrien					printf("MD5 (%s) = %s\n", argv[optind],
9852949Sobrien					    p);
9932074Ssteve			optind++;
10032074Ssteve		}
10132074Ssteve	} else
1026725Sphk		MDFilter(0);
1033995Spst
1046562Sphk	return (0);
1053995Spst}
1066562Sphk/*
1076562Sphk * Digests a string and prints the result.
1083995Spst */
1096562Sphkstatic void
1106562SphkMDString(string)
1116562Sphk	char   *string;
1123995Spst{
11348953Sbillf	size_t len = strlen(string);
1149489Sphk	char buf[33];
1153995Spst
11652949Sobrien	if (rflag)
11753060Sobrien		printf("%s (\"%s\")\n", MD5Data(string, len, buf), string);
11852949Sobrien	else
11952949Sobrien		printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf));
1203995Spst}
1216562Sphk/*
1226562Sphk * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks.
1233995Spst */
1246562Sphkstatic void
1256562SphkMDTimeTrial()
1263995Spst{
1276562Sphk	MD5_CTX context;
1286562Sphk	time_t  endTime, startTime;
1296725Sphk	unsigned char block[TEST_BLOCK_LEN];
1306562Sphk	unsigned int i;
1319489Sphk	char   *p, buf[33];
1323995Spst
1336562Sphk	printf
1346562Sphk	    ("MD5 time trial. Digesting %d %d-byte blocks ...",
13521763Sphk	    TEST_BLOCK_COUNT, TEST_BLOCK_LEN);
13646226Skris	fflush(stdout);
1373995Spst
1386562Sphk	/* Initialize block */
1396562Sphk	for (i = 0; i < TEST_BLOCK_LEN; i++)
1406562Sphk		block[i] = (unsigned char) (i & 0xff);
1413995Spst
1426562Sphk	/* Start timer */
1436562Sphk	time(&startTime);
1443995Spst
1456562Sphk	/* Digest blocks */
1466562Sphk	MD5Init(&context);
1476562Sphk	for (i = 0; i < TEST_BLOCK_COUNT; i++)
1486562Sphk		MD5Update(&context, block, TEST_BLOCK_LEN);
1499489Sphk	p = MD5End(&context,buf);
1503995Spst
1516562Sphk	/* Stop timer */
1526562Sphk	time(&endTime);
1533995Spst
1546562Sphk	printf(" done\n");
1556562Sphk	printf("Digest = %s", p);
1566562Sphk	printf("\nTime = %ld seconds\n", (long) (endTime - startTime));
1576562Sphk	/* Be careful that endTime-startTime is not zero. (Bug fix from Ric
1586562Sphk	 * Anderson, ric@Artisoft.COM.) */
1596562Sphk	printf
1606562Sphk	    ("Speed = %ld bytes/second\n",
1616562Sphk	    (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (endTime - startTime) : 1));
1623995Spst}
1636562Sphk/*
1646562Sphk * Digests a reference suite of strings and prints the results.
1653995Spst */
1666562Sphkstatic void
1676562SphkMDTestSuite()
1683995Spst{
16932086Ssteve
1706562Sphk	printf("MD5 test suite:\n");
1713995Spst
1726562Sphk	MDString("");
1736562Sphk	MDString("a");
1746562Sphk	MDString("abc");
1756562Sphk	MDString("message digest");
1766562Sphk	MDString("abcdefghijklmnopqrstuvwxyz");
1776562Sphk	MDString
1786562Sphk	    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1796562Sphk	MDString
1806562Sphk	    ("1234567890123456789012345678901234567890\
1813995Spst1234567890123456789012345678901234567890");
1823995Spst}
1833995Spst
1846562Sphk/*
1856562Sphk * Digests the standard input and prints the result.
1863995Spst */
1876562Sphkstatic void
18832086SsteveMDFilter(pipe)
18932086Ssteve	int pipe;
1903995Spst{
1916562Sphk	MD5_CTX context;
1926562Sphk	int     len;
19332074Ssteve	unsigned char buffer[BUFSIZ];
1949489Sphk	char buf[33];
1953995Spst
1966562Sphk	MD5Init(&context);
19732074Ssteve	while ((len = fread(buffer, 1, BUFSIZ, stdin))) {
19837421Scharnier		if(pipe && (len != fwrite(buffer, 1, len, stdout)))
19937421Scharnier			err(1, "stdout");
2006562Sphk		MD5Update(&context, buffer, len);
2016725Sphk	}
2029489Sphk	printf("%s\n", MD5End(&context,buf));
2033995Spst}
20432074Ssteve
20532074Sstevestatic void
20632086Ssteveusage()
20732074Ssteve{
20832086Ssteve
20932086Ssteve	fprintf(stderr, "usage: md5 [-ptx] [-s string] [files ...]\n");
21032074Ssteve	exit(1);
21132074Ssteve}
212