md5.c revision 76988
10Sduke/*
22514Ssogoel * Derived from:
32849Ssadayapalam *
40Sduke * MDDRIVER.C - test driver for MD2, MD4 and MD5
50Sduke */
62514Ssogoel
70Sduke/*
80Sduke *  Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
90Sduke *  rights reserved.
100Sduke *
110Sduke *  RSA Data Security, Inc. makes no representations concerning either
120Sduke *  the merchantability of this software or the suitability of this
130Sduke *  software for any particular purpose. It is provided "as is"
140Sduke *  without express or implied warranty of any kind.
150Sduke *
160Sduke *  These notices must be retained in any copies of any part of this
170Sduke *  documentation and/or software.
180Sduke */
190Sduke
200Sduke#ifndef lint
21static const char rcsid[] =
22  "$FreeBSD: head/sbin/md5/md5.c 76988 2001-05-22 10:33:43Z ru $";
23#endif /* not lint */
24
25#include <sys/types.h>
26#include <err.h>
27#include <md5.h>
28#include <stdio.h>
29#include <time.h>
30#include <unistd.h>
31#include <string.h>
32
33/*
34 * Length of test block, number of test blocks.
35 */
36#define TEST_BLOCK_LEN 10000
37#define TEST_BLOCK_COUNT 100000
38
39int qflag;
40int rflag;
41
42static void MDString(const char *);
43static void MDTimeTrial(void);
44static void MDTestSuite(void);
45static void MDFilter(int);
46static void usage(void);
47
48/* Main driver.
49
50Arguments (may be any combination):
51  -sstring - digests string
52  -t       - runs time trial
53  -x       - runs test script
54  filename - digests file
55  (none)   - digests standard input
56 */
57int
58main(int argc, char *argv[])
59{
60	int     ch;
61	char   *p;
62	char	buf[33];
63
64	while ((ch = getopt(argc, argv, "ps:qrtx")) != -1)
65		switch (ch) {
66		case 'p':
67			MDFilter(1);
68			break;
69		case 'q':
70			qflag = 1;
71			break;
72		case 'r':
73			rflag = 1;
74			break;
75		case 's':
76			MDString(optarg);
77			break;
78		case 't':
79			MDTimeTrial();
80			break;
81		case 'x':
82			MDTestSuite();
83			break;
84		default:
85			usage();
86		}
87	argc -= optind;
88	argv += optind;
89
90	if (*argv) {
91		do {
92			p = MD5File(*argv, buf);
93			if (!p)
94				warn("%s", *argv);
95			else
96				if (qflag)
97					printf("%s\n", p);
98				else if (rflag)
99					printf("%s %s\n", p, *argv);
100				else
101					printf("MD5 (%s) = %s\n", *argv, p);
102		} while (*++argv);
103	} else
104		MDFilter(0);
105
106	return (0);
107}
108/*
109 * Digests a string and prints the result.
110 */
111static void
112MDString(const char *string)
113{
114	size_t len = strlen(string);
115	char buf[33];
116
117	if (qflag)
118		printf("%s\n", MD5Data(string, len, buf));
119	else if (rflag)
120		printf("%s \"%s\"\n", MD5Data(string, len, buf), string);
121	else
122		printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf));
123}
124/*
125 * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks.
126 */
127static void
128MDTimeTrial(void)
129{
130	MD5_CTX context;
131	time_t  endTime, startTime;
132	unsigned char block[TEST_BLOCK_LEN];
133	unsigned int i;
134	char   *p, buf[33];
135
136	printf
137	    ("MD5 time trial. Digesting %d %d-byte blocks ...",
138	    TEST_BLOCK_COUNT, TEST_BLOCK_LEN);
139	fflush(stdout);
140
141	/* Initialize block */
142	for (i = 0; i < TEST_BLOCK_LEN; i++)
143		block[i] = (unsigned char) (i & 0xff);
144
145	/* Start timer */
146	time(&startTime);
147
148	/* Digest blocks */
149	MD5Init(&context);
150	for (i = 0; i < TEST_BLOCK_COUNT; i++)
151		MD5Update(&context, block, TEST_BLOCK_LEN);
152	p = MD5End(&context,buf);
153
154	/* Stop timer */
155	time(&endTime);
156
157	printf(" done\n");
158	printf("Digest = %s", p);
159	printf("\nTime = %ld seconds\n", (long) (endTime - startTime));
160	/* Be careful that endTime-startTime is not zero. (Bug fix from Ric
161	 * Anderson, ric@Artisoft.COM.) */
162	printf
163	    ("Speed = %ld bytes/second\n",
164	    (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (endTime - startTime) : 1));
165}
166/*
167 * Digests a reference suite of strings and prints the results.
168 */
169static void
170MDTestSuite(void)
171{
172
173	printf("MD5 test suite:\n");
174
175	MDString("");
176	MDString("a");
177	MDString("abc");
178	MDString("message digest");
179	MDString("abcdefghijklmnopqrstuvwxyz");
180	MDString
181	    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
182	MDString
183	    ("1234567890123456789012345678901234567890\
1841234567890123456789012345678901234567890");
185}
186
187/*
188 * Digests the standard input and prints the result.
189 */
190static void
191MDFilter(int tee)
192{
193	MD5_CTX context;
194	unsigned int len;
195	unsigned char buffer[BUFSIZ];
196	char buf[33];
197
198	MD5Init(&context);
199	while ((len = fread(buffer, 1, BUFSIZ, stdin))) {
200		if (tee && len != fwrite(buffer, 1, len, stdout))
201			err(1, "stdout");
202		MD5Update(&context, buffer, len);
203	}
204	printf("%s\n", MD5End(&context,buf));
205}
206
207static void
208usage(void)
209{
210
211	fprintf(stderr, "usage: md5 [-pqrtx] [-s string] [files ...]\n");
212	exit(1);
213}
214