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