md5.c revision 3996
1/* MDDRIVER.C - test driver for MD2, MD4 and MD5
2 */
3
4/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
5rights reserved.
6
7RSA Data Security, Inc. makes no representations concerning either
8the merchantability of this software or the suitability of this
9software for any particular purpose. It is provided "as is"
10without express or implied warranty of any kind.
11
12These notices must be retained in any copies of any part of this
13documentation and/or software.
14 */
15
16/* The following makes MD default to MD5 if it has not already been
17  defined with C compiler flags.
18 */
19#ifndef MD
20#define MD 5
21#endif
22
23#include <stdio.h>
24#include <time.h>
25#include <string.h>
26#include "global.h"
27#if MD == 2
28#include <md2.h>
29#endif
30#if MD == 4
31#include <md4.h>
32#endif
33#if MD == 5
34#include <md5.h>
35#endif
36
37/* Length of test block, number of test blocks.
38 */
39#define TEST_BLOCK_LEN 1000
40#define TEST_BLOCK_COUNT 1000
41
42static void MDString PROTO_LIST ((char *));
43static void MDTimeTrial PROTO_LIST ((void));
44static void MDTestSuite PROTO_LIST ((void));
45static void MDFile PROTO_LIST ((char *));
46static void MDFilter PROTO_LIST ((void));
47static void MDPrint PROTO_LIST ((unsigned char [16]));
48
49#if MD == 2
50#define MD_CTX MD2_CTX
51#define MDInit MD2Init
52#define MDUpdate MD2Update
53#define MDFinal MD2Final
54#endif
55#if MD == 4
56#define MD_CTX MD4_CTX
57#define MDInit MD4Init
58#define MDUpdate MD4Update
59#define MDFinal MD4Final
60#endif
61#if MD == 5
62#define MD_CTX MD5_CTX
63#define MDInit MD5Init
64#define MDUpdate MD5Update
65#define MDFinal MD5Final
66#endif
67
68/* Main driver.
69
70Arguments (may be any combination):
71  -sstring - digests string
72  -t       - runs time trial
73  -x       - runs test script
74  filename - digests file
75  (none)   - digests standard input
76 */
77int main (argc, argv)
78int argc;
79char *argv[];
80{
81  int i;
82
83  if (argc > 1)
84 for (i = 1; i < argc; i++)
85   if (argv[i][0] == '-' && argv[i][1] == 's')
86     MDString (argv[i] + 2);
87   else if (strcmp (argv[i], "-t") == 0)
88     MDTimeTrial ();
89   else if (strcmp (argv[i], "-x") == 0)
90     MDTestSuite ();
91   else
92     MDFile (argv[i]);
93  else
94 MDFilter ();
95
96  return (0);
97}
98
99/* Digests a string and prints the result.
100 */
101static void MDString (string)
102char *string;
103{
104  MD_CTX context;
105  unsigned char digest[16];
106  unsigned int len = strlen (string);
107
108  MDInit (&context);
109  MDUpdate (&context, string, len);
110  MDFinal (digest, &context);
111
112  printf ("MD%d (\"%s\") = ", MD, string);
113  MDPrint (digest);
114  printf ("\n");
115}
116
117/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
118  blocks.
119 */
120static void MDTimeTrial ()
121{
122  MD_CTX context;
123  time_t endTime, startTime;
124  unsigned char block[TEST_BLOCK_LEN], digest[16];
125  unsigned int i;
126
127  printf
128 ("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
129  TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
130
131  /* Initialize block */
132  for (i = 0; i < TEST_BLOCK_LEN; i++)
133 block[i] = (unsigned char)(i & 0xff);
134
135  /* Start timer */
136  time (&startTime);
137
138  /* Digest blocks */
139  MDInit (&context);
140  for (i = 0; i < TEST_BLOCK_COUNT; i++)
141 MDUpdate (&context, block, TEST_BLOCK_LEN);
142  MDFinal (digest, &context);
143
144  /* Stop timer */
145  time (&endTime);
146
147  printf (" done\n");
148  printf ("Digest = ");
149  MDPrint (digest);
150  printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
151  /*
152   * Be careful that endTime-startTime is not zero.
153   * (Bug fix from Ric Anderson, ric@Artisoft.COM.)
154   */
155  printf
156 ("Speed = %ld bytes/second\n",
157  (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/((endTime-startTime) != 0 ? (endTime-startTime):1));
158}
159
160/* Digests a reference suite of strings and prints the results.
161 */
162static void MDTestSuite ()
163{
164  printf ("MD%d test suite:\n", MD);
165
166  MDString ("");
167  MDString ("a");
168  MDString ("abc");
169  MDString ("message digest");
170  MDString ("abcdefghijklmnopqrstuvwxyz");
171  MDString
172 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
173  MDString
174 ("1234567890123456789012345678901234567890\
1751234567890123456789012345678901234567890");
176}
177
178/* Digests a file and prints the result.
179 */
180static void MDFile (filename)
181char *filename;
182{
183  FILE *file;
184  MD_CTX context;
185  int len;
186  unsigned char buffer[1024], digest[16];
187
188  if ((file = fopen (filename, "rb")) == NULL)
189 printf ("%s can't be opened\n", filename);
190
191  else {
192 MDInit (&context);
193 while (len = fread (buffer, 1, 1024, file))
194   MDUpdate (&context, buffer, len);
195 MDFinal (digest, &context);
196
197 fclose (file);
198
199 printf ("MD%d (%s) = ", MD, filename);
200 MDPrint (digest);
201 printf ("\n");
202  }
203}
204
205/* Digests the standard input and prints the result.
206 */
207static void MDFilter ()
208{
209  MD_CTX context;
210  int len;
211  unsigned char buffer[16], digest[16];
212
213  MDInit (&context);
214  while (len = fread (buffer, 1, 16, stdin))
215 MDUpdate (&context, buffer, len);
216  MDFinal (digest, &context);
217
218  MDPrint (digest);
219  printf ("\n");
220}
221
222/* Prints a message digest in hexadecimal.
223 */
224static void MDPrint (digest)
225unsigned char digest[16];
226{
227  unsigned int i;
228
229  for (i = 0; i < 16; i++)
230 printf ("%02x", digest[i]);
231}
232