xref: /freebsd/sbin/md5/md5.c (revision 417ed37975261df51f61d13e179ad04d8f4839c7)
1 /* MDDRIVER.C - test driver for MD2, MD4 and MD5
2  */
3 
4 /* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
5 rights reserved.
6 
7 RSA Data Security, Inc. makes no representations concerning either
8 the merchantability of this software or the suitability of this
9 software for any particular purpose. It is provided "as is"
10 without express or implied warranty of any kind.
11 
12 These notices must be retained in any copies of any part of this
13 documentation 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 
42 static void MDString PROTO_LIST ((char *));
43 static void MDTimeTrial PROTO_LIST ((void));
44 static void MDTestSuite PROTO_LIST ((void));
45 static void MDFile PROTO_LIST ((char *));
46 static void MDFilter PROTO_LIST ((void));
47 static 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 
70 Arguments (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  */
77 int main (argc, argv)
78 int argc;
79 char *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  */
101 static void MDString (string)
102 char *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  */
120 static 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  */
162 static 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\
175 1234567890123456789012345678901234567890");
176 }
177 
178 /* Digests a file and prints the result.
179  */
180 static void MDFile (filename)
181 char *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  */
207 static 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  */
224 static void MDPrint (digest)
225 unsigned char digest[16];
226 {
227   unsigned int i;
228 
229   for (i = 0; i < 16; i++)
230  printf ("%02x", digest[i]);
231 }
232