md5.c revision 3995
1189251Ssam/* MDDRIVER.C - test driver for MD2, MD4 and MD5
2189251Ssam */
3189251Ssam
4189251Ssam/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
5189251Ssamrights reserved.
6189251Ssam
7189251SsamRSA Data Security, Inc. makes no representations concerning either
8189251Ssamthe merchantability of this software or the suitability of this
9189251Ssamsoftware for any particular purpose. It is provided "as is"
10189251Ssamwithout express or implied warranty of any kind.
11189251Ssam
12189251SsamThese notices must be retained in any copies of any part of this
13189251Ssamdocumentation and/or software.
14189251Ssam */
15189251Ssam
16189251Ssam/* The following makes MD default to MD5 if it has not already been
17189251Ssam  defined with C compiler flags.
18189251Ssam */
19189251Ssam#ifndef MD
20189251Ssam#define MD 5
21189251Ssam#endif
22189251Ssam
23189251Ssam#include <stdio.h>
24189251Ssam#include <time.h>
25189251Ssam#include <string.h>
26189251Ssam#include "global.h"
27189251Ssam#if MD == 2
28189251Ssam#include <md2.h>
29189251Ssam#endif
30189251Ssam#if MD == 4
31189251Ssam#include <md4.h>
32189251Ssam#endif
33189251Ssam#if MD == 5
34189251Ssam#include <md5.h>
35189251Ssam#endif
36189251Ssam
37189251Ssam/* Length of test block, number of test blocks.
38189251Ssam */
39189251Ssam#define TEST_BLOCK_LEN 1000
40189251Ssam#define TEST_BLOCK_COUNT 1000
41189251Ssam
42189251Ssamstatic void MDString PROTO_LIST ((char *));
43189251Ssamstatic void MDTimeTrial PROTO_LIST ((void));
44189251Ssamstatic void MDTestSuite PROTO_LIST ((void));
45189251Ssamstatic void MDFile PROTO_LIST ((char *));
46189251Ssamstatic void MDFilter PROTO_LIST ((void));
47189251Ssamstatic void MDPrint PROTO_LIST ((unsigned char [16]));
48189251Ssam
49189251Ssam#if MD == 2
50189251Ssam#define MD_CTX MD2_CTX
51189251Ssam#define MDInit MD2Init
52189251Ssam#define MDUpdate MD2Update
53189251Ssam#define MDFinal MD2Final
54189251Ssam#endif
55189251Ssam#if MD == 4
56189251Ssam#define MD_CTX MD4_CTX
57189251Ssam#define MDInit MD4Init
58189251Ssam#define MDUpdate MD4Update
59189251Ssam#define MDFinal MD4Final
60189251Ssam#endif
61189251Ssam#if MD == 5
62189251Ssam#define MD_CTX MD5_CTX
63189251Ssam#define MDInit MD5Init
64189251Ssam#define MDUpdate MD5Update
65189251Ssam#define MDFinal MD5Final
66189251Ssam#endif
67189251Ssam
68189251Ssam/* Main driver.
69189251Ssam
70189251SsamArguments (may be any combination):
71189251Ssam  -sstring - digests string
72189251Ssam  -t       - runs time trial
73189251Ssam  -x       - runs test script
74189251Ssam  filename - digests file
75189251Ssam  (none)   - digests standard input
76189251Ssam */
77189251Ssamint main (argc, argv)
78189251Ssamint argc;
79189251Ssamchar *argv[];
80189251Ssam{
81189251Ssam  int i;
82189251Ssam
83189251Ssam  if (argc > 1)
84189251Ssam for (i = 1; i < argc; i++)
85189251Ssam   if (argv[i][0] == '-' && argv[i][1] == 's')
86189251Ssam     MDString (argv[i] + 2);
87189251Ssam   else if (strcmp (argv[i], "-t") == 0)
88189251Ssam     MDTimeTrial ();
89189251Ssam   else if (strcmp (argv[i], "-x") == 0)
90189251Ssam     MDTestSuite ();
91189251Ssam   else
92189251Ssam     MDFile (argv[i]);
93189251Ssam  else
94189251Ssam MDFilter ();
95189251Ssam
96189251Ssam  return (0);
97189251Ssam}
98189251Ssam
99189251Ssam/* Digests a string and prints the result.
100189251Ssam */
101189251Ssamstatic void MDString (string)
102189251Ssamchar *string;
103189251Ssam{
104189251Ssam  MD_CTX context;
105189251Ssam  unsigned char digest[16];
106189251Ssam  unsigned int len = strlen (string);
107189251Ssam
108189251Ssam  MDInit (&context);
109189251Ssam  MDUpdate (&context, string, len);
110189251Ssam  MDFinal (digest, &context);
111189251Ssam
112189251Ssam  printf ("MD%d (\"%s\") = ", MD, string);
113189251Ssam  MDPrint (digest);
114189251Ssam  printf ("\n");
115189251Ssam}
116189251Ssam
117189251Ssam/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
118189251Ssam  blocks.
119189251Ssam */
120189251Ssamstatic void MDTimeTrial ()
121189251Ssam{
122189251Ssam  MD_CTX context;
123189251Ssam  time_t endTime, startTime;
124189251Ssam  unsigned char block[TEST_BLOCK_LEN], digest[16];
125189251Ssam  unsigned int i;
126189251Ssam
127189251Ssam  printf
128189251Ssam ("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
129189251Ssam  TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
130189251Ssam
131189251Ssam  /* Initialize block */
132189251Ssam  for (i = 0; i < TEST_BLOCK_LEN; i++)
133189251Ssam block[i] = (unsigned char)(i & 0xff);
134189251Ssam
135189251Ssam  /* Start timer */
136189251Ssam  time (&startTime);
137189251Ssam
138189251Ssam  /* Digest blocks */
139189251Ssam  MDInit (&context);
140189251Ssam  for (i = 0; i < TEST_BLOCK_COUNT; i++)
141189251Ssam MDUpdate (&context, block, TEST_BLOCK_LEN);
142189251Ssam  MDFinal (digest, &context);
143189251Ssam
144189251Ssam  /* Stop timer */
145189251Ssam  time (&endTime);
146189251Ssam
147189251Ssam  printf (" done\n");
148189251Ssam  printf ("Digest = ");
149189251Ssam  MDPrint (digest);
150189251Ssam  printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
151189251Ssam  /*
152189251Ssam   * Be careful that endTime-startTime is not zero.
153189251Ssam   * (Bug fix from Ric Anderson, ric@Artisoft.COM.)
154189251Ssam   */
155189251Ssam  printf
156189251Ssam ("Speed = %ld bytes/second\n",
157189251Ssam  (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/((endTime-startTime) != 0 ? (endTime-startTime):1));
158189251Ssam}
159189251Ssam
160189251Ssam/* Digests a reference suite of strings and prints the results.
161189251Ssam */
162189251Ssamstatic void MDTestSuite ()
163189251Ssam{
164189251Ssam  printf ("MD%d test suite:\n", MD);
165189251Ssam
166189251Ssam  MDString ("");
167189251Ssam  MDString ("a");
168189251Ssam  MDString ("abc");
169189251Ssam  MDString ("message digest");
170189251Ssam  MDString ("abcdefghijklmnopqrstuvwxyz");
171189251Ssam  MDString
172189251Ssam ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
173189251Ssam  MDString
174189251Ssam ("1234567890123456789012345678901234567890\
175189251Ssam1234567890123456789012345678901234567890");
176189251Ssam}
177189251Ssam
178189251Ssam/* Digests a file and prints the result.
179189251Ssam */
180189251Ssamstatic void MDFile (filename)
181189251Ssamchar *filename;
182189251Ssam{
183189251Ssam  FILE *file;
184189251Ssam  MD_CTX context;
185189251Ssam  int len;
186189251Ssam  unsigned char buffer[1024], digest[16];
187189251Ssam
188189251Ssam  if ((file = fopen (filename, "rb")) == NULL)
189189251Ssam printf ("%s can't be opened\n", filename);
190189251Ssam
191189251Ssam  else {
192189251Ssam MDInit (&context);
193189251Ssam while (len = fread (buffer, 1, 1024, file))
194189251Ssam   MDUpdate (&context, buffer, len);
195189251Ssam MDFinal (digest, &context);
196189251Ssam
197189251Ssam fclose (file);
198189251Ssam
199189251Ssam printf ("MD%d (%s) = ", MD, filename);
200189251Ssam MDPrint (digest);
201189251Ssam printf ("\n");
202189251Ssam  }
203189251Ssam}
204189251Ssam
205189251Ssam/* Digests the standard input and prints the result.
206189251Ssam */
207189251Ssamstatic void MDFilter ()
208189251Ssam{
209214734Srpaulo  MD_CTX context;
210214734Srpaulo  int len;
211214734Srpaulo  unsigned char buffer[16], digest[16];
212214734Srpaulo
213214734Srpaulo  MDInit (&context);
214214734Srpaulo  while (len = fread (buffer, 1, 16, stdin))
215189251Ssam MDUpdate (&context, buffer, len);
216189251Ssam  MDFinal (digest, &context);
217189251Ssam
218189251Ssam  MDPrint (digest);
219189251Ssam  printf ("\n");
220189251Ssam}
221189251Ssam
222189251Ssam/* Prints a message digest in hexadecimal.
223189251Ssam */
224189251Ssamstatic void MDPrint (digest)
225189251Ssamunsigned char digest[16];
226189251Ssam{
227189251Ssam  unsigned int i;
228189251Ssam
229189251Ssam  for (i = 0; i < 16; i++)
230189251Ssam printf ("%02x", digest[i]);
231189251Ssam}
232189251Ssam