md5.c revision 50476
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 50476 1999-08-28 00:22:10Z peter $";
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
41static void MDString PROTO_LIST((char *));
42static void MDTimeTrial PROTO_LIST((void));
43static void MDTestSuite PROTO_LIST((void));
44static void MDFilter PROTO_LIST((int));
45static void usage PROTO_LIST((void));
46
47/* Main driver.
48
49Arguments (may be any combination):
50  -sstring - digests string
51  -t       - runs time trial
52  -x       - runs test script
53  filename - digests file
54  (none)   - digests standard input
55 */
56int
57main(argc, argv)
58	int     argc;
59	char   *argv[];
60{
61	int     ch;
62	char   *p;
63	char	buf[33];
64
65	if (argc > 1) {
66		while ((ch = getopt(argc, argv, "ps:tx")) != -1) {
67			switch (ch) {
68			case 'p':
69				MDFilter(1);
70				break;
71			case 's':
72				MDString(optarg);
73				break;
74			case 't':
75				MDTimeTrial();
76				break;
77			case 'x':
78				MDTestSuite();
79				break;
80			default:
81				usage();
82			}
83		}
84		while (optind < argc) {
85			p = MD5File(argv[optind], buf);
86			if (!p)
87				warn("%s", argv[optind]);
88			else
89				printf("MD5 (%s) = %s\n", argv[optind], p);
90			optind++;
91		}
92	} else
93		MDFilter(0);
94
95	return (0);
96}
97/*
98 * Digests a string and prints the result.
99 */
100static void
101MDString(string)
102	char   *string;
103{
104	size_t len = strlen(string);
105	char buf[33];
106
107	printf("MD5 (\"%s\") = %s\n", string, MD5Data(string, len, buf));
108}
109/*
110 * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks.
111 */
112static void
113MDTimeTrial()
114{
115	MD5_CTX context;
116	time_t  endTime, startTime;
117	unsigned char block[TEST_BLOCK_LEN];
118	unsigned int i;
119	char   *p, buf[33];
120
121	printf
122	    ("MD5 time trial. Digesting %d %d-byte blocks ...",
123	    TEST_BLOCK_COUNT, TEST_BLOCK_LEN);
124	fflush(stdout);
125
126	/* Initialize block */
127	for (i = 0; i < TEST_BLOCK_LEN; i++)
128		block[i] = (unsigned char) (i & 0xff);
129
130	/* Start timer */
131	time(&startTime);
132
133	/* Digest blocks */
134	MD5Init(&context);
135	for (i = 0; i < TEST_BLOCK_COUNT; i++)
136		MD5Update(&context, block, TEST_BLOCK_LEN);
137	p = MD5End(&context,buf);
138
139	/* Stop timer */
140	time(&endTime);
141
142	printf(" done\n");
143	printf("Digest = %s", p);
144	printf("\nTime = %ld seconds\n", (long) (endTime - startTime));
145	/* Be careful that endTime-startTime is not zero. (Bug fix from Ric
146	 * Anderson, ric@Artisoft.COM.) */
147	printf
148	    ("Speed = %ld bytes/second\n",
149	    (long) TEST_BLOCK_LEN * (long) TEST_BLOCK_COUNT / ((endTime - startTime) != 0 ? (endTime - startTime) : 1));
150}
151/*
152 * Digests a reference suite of strings and prints the results.
153 */
154static void
155MDTestSuite()
156{
157
158	printf("MD5 test suite:\n");
159
160	MDString("");
161	MDString("a");
162	MDString("abc");
163	MDString("message digest");
164	MDString("abcdefghijklmnopqrstuvwxyz");
165	MDString
166	    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
167	MDString
168	    ("1234567890123456789012345678901234567890\
1691234567890123456789012345678901234567890");
170}
171
172/*
173 * Digests the standard input and prints the result.
174 */
175static void
176MDFilter(pipe)
177	int pipe;
178{
179	MD5_CTX context;
180	int     len;
181	unsigned char buffer[BUFSIZ];
182	char buf[33];
183
184	MD5Init(&context);
185	while ((len = fread(buffer, 1, BUFSIZ, stdin))) {
186		if(pipe && (len != fwrite(buffer, 1, len, stdout)))
187			err(1, "stdout");
188		MD5Update(&context, buffer, len);
189	}
190	printf("%s\n", MD5End(&context,buf));
191}
192
193static void
194usage()
195{
196
197	fprintf(stderr, "usage: md5 [-ptx] [-s string] [files ...]\n");
198	exit(1);
199}
200