Download
plus
/MD5
/mddriver.c
(View History)
mrw Initial commit. | Latest amendment: 1 on 2024-10-15 |
1 | |
2 | /* MDDRIVER.C - test driver for MD2, MD4 and MD5 |
3 | */ |
4 | |
5 | /* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All |
6 | rights reserved. |
7 | |
8 | RSA Data Security, Inc. makes no representations concerning either |
9 | the merchantability of this software or the suitability of this |
10 | software for any particular purpose. It is provided "as is" |
11 | without express or implied warranty of any kind. |
12 | |
13 | These notices must be retained in any copies of any part of this |
14 | documentation and/or software. |
15 | |
16 | Additional main() function ©2024 mrw <plus@m0001a.org> |
17 | */ |
18 | |
19 | /* The following makes MD default to MD5 if it has not already been |
20 | defined with C compiler flags. |
21 | */ |
22 | #ifndef MD |
23 | #define MD 5 |
24 | #endif |
25 | |
26 | #include <stdio.h> |
27 | #include <time.h> |
28 | #include <string.h> |
29 | #include "global.h" |
30 | #if MD == 2 |
31 | #include "md2.h" |
32 | #endif |
33 | #if MD == 4 |
34 | #include "md4.h" |
35 | #endif |
36 | #if MD == 5 |
37 | #include "md5.h" |
38 | #endif |
39 | |
40 | /* for ccommand - mrw */ |
41 | #include <console.h> |
42 | |
43 | /* Length of test block, number of test blocks. |
44 | */ |
45 | #define TEST_BLOCK_LEN 1000 |
46 | #define TEST_BLOCK_COUNT 1000 |
47 | |
48 | static void MDString PROTO_LIST ((char *, unsigned char [16])); |
49 | static void MDTimeTrial PROTO_LIST ((void)); |
50 | static void MDTestSuite PROTO_LIST ((void)); |
51 | static void MDFile PROTO_LIST ((char *)); |
52 | static void MDFilter PROTO_LIST ((void)); |
53 | static void MDPrint PROTO_LIST ((unsigned char [16])); |
54 | |
55 | #if MD == 2 |
56 | #define MD_CTX MD2_CTX |
57 | #define MDInit MD2Init |
58 | #define MDUpdate MD2Update |
59 | #define MDFinal MD2Final |
60 | #endif |
61 | #if MD == 4 |
62 | #define MD_CTX MD4_CTX |
63 | #define MDInit MD4Init |
64 | #define MDUpdate MD4Update |
65 | #define MDFinal MD4Final |
66 | #endif |
67 | #if MD == 5 |
68 | #define MD_CTX MD5_CTX |
69 | #define MDInit MD5Init |
70 | #define MDUpdate MD5Update |
71 | #define MDFinal MD5Final |
72 | #endif |
73 | |
74 | |
75 | /* Main driver. |
76 | |
77 | Arguments (may be any combination): |
78 | -sstring - digests string |
79 | -t - runs time trial |
80 | -x - runs test script |
81 | filename - digests file |
82 | (none) - digests standard input |
83 | */ |
84 | int main (argc, argv) |
85 | int argc; |
86 | char *argv[]; |
87 | { |
88 | int i; |
89 | |
90 | argc = ccommand(&argv); |
91 | |
92 | if (argc > 1) |
93 | for (i = 1; i < argc; i++) |
94 | if (argv[i][0] == '-' && argv[i][1] == 's') |
95 | MDString (argv[i] + 2, NULL); |
96 | else if (strcmp (argv[i], "-t") == 0) |
97 | MDTimeTrial (); |
98 | else if (strcmp (argv[i], "-x") == 0) |
99 | MDTestSuite (); |
100 | else |
101 | MDFile (argv[i]); |
102 | else |
103 | MDFilter (); |
104 | |
105 | return (0); |
106 | } |
107 | /* Added so MDTestSuite can check output - mrw |
108 | */ |
109 | static int MDEqual(unsigned char a[16], unsigned char b[16]) |
110 | { |
111 | int i; |
112 | for (i = 0; i < sizeof(a); i++) { |
113 | if (a[i] != b[i]) |
114 | return 0; |
115 | } |
116 | |
117 | return 1; |
118 | } |
119 | |
120 | /* Digests a string and prints the result. |
121 | * |
122 | * Extended to check expected digest. |
123 | */ |
124 | static void MDString (string, expected) |
125 | char *string; |
126 | unsigned char expected[16]; |
127 | { |
128 | MD_CTX context; |
129 | unsigned char digest[16]; |
130 | unsigned int len = strlen (string); |
131 | |
132 | MDInit (&context); |
133 | MDUpdate (&context, (unsigned char *)string, len); |
134 | MDFinal (digest, &context); |
135 | |
136 | printf ("MD%d (\"%s\") = ", MD, string); |
137 | MDPrint (digest); |
138 | |
139 | if (expected && !MDEqual(digest, expected)) { |
140 | printf(" ** FAIL **"); |
141 | } |
142 | |
143 | printf ("\n"); |
144 | } |
145 | |
146 | /* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte |
147 | blocks. |
148 | */ |
149 | static void MDTimeTrial () |
150 | { |
151 | MD_CTX context; |
152 | time_t endTime, startTime; |
153 | unsigned char block[TEST_BLOCK_LEN], digest[16]; |
154 | unsigned int i; |
155 | |
156 | printf |
157 | ("MD%d time trial. Digesting %d %d-byte blocks ...", MD, |
158 | TEST_BLOCK_LEN, TEST_BLOCK_COUNT); |
159 | |
160 | /* Initialize block */ |
161 | for (i = 0; i < TEST_BLOCK_LEN; i++) |
162 | block[i] = (unsigned char)(i & 0xff); |
163 | |
164 | /* Start timer */ |
165 | time (&startTime); |
166 | |
167 | /* Digest blocks */ |
168 | MDInit (&context); |
169 | for (i = 0; i < TEST_BLOCK_COUNT; i++) |
170 | MDUpdate (&context, block, TEST_BLOCK_LEN); |
171 | MDFinal (digest, &context); |
172 | |
173 | /* Stop timer */ |
174 | time (&endTime); |
175 | |
176 | printf (" done\n"); |
177 | printf ("Digest = "); |
178 | MDPrint (digest); |
179 | printf ("\nTime = %ld seconds\n", (long)(endTime-startTime)); |
180 | printf |
181 | ("Speed = %ld bytes/second\n", |
182 | (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime)); |
183 | } |
184 | |
185 | /* Digests a reference suite of strings and prints the results. |
186 | */ |
187 | static void MDTestSuite () |
188 | { |
189 | unsigned char digests[7][16] = { |
190 | { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, |
191 | { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, |
192 | { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, |
193 | { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, |
194 | { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, |
195 | { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, |
196 | { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }, |
197 | }; |
198 | |
199 | printf ("MD%d test suite:\n", MD); |
200 | |
201 | |
202 | MDString ("", digests[0]); |
203 | MDString ("a", digests[1]); |
204 | MDString ("abc", digests[2]); |
205 | MDString ("message digest", digests[3]); |
206 | MDString ("abcdefghijklmnopqrstuvwxyz", digests[4]); |
207 | MDString |
208 | ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", |
209 | digests[5]); |
210 | MDString |
211 | ("1234567890123456789012345678901234567890\ |
212 | 1234567890123456789012345678901234567890", |
213 | digests[6]); |
214 | } |
215 | |
216 | /* Digests a file and prints the result. |
217 | */ |
218 | static void MDFile (filename) |
219 | char *filename; |
220 | { |
221 | FILE *file; |
222 | MD_CTX context; |
223 | int len; |
224 | unsigned char buffer[1024], digest[16]; |
225 | |
226 | if ((file = fopen (filename, "rb")) == NULL) |
227 | printf ("%s can't be opened\n", filename); |
228 | |
229 | else { |
230 | MDInit (&context); |
231 | while (len = fread (buffer, 1, 1024, file)) |
232 | MDUpdate (&context, buffer, len); |
233 | MDFinal (digest, &context); |
234 | |
235 | fclose (file); |
236 | |
237 | printf ("MD%d (%s) = ", MD, filename); |
238 | MDPrint (digest); |
239 | printf ("\n"); |
240 | } |
241 | } |
242 | |
243 | /* Digests the standard input and prints the result. |
244 | */ |
245 | static void MDFilter () |
246 | { |
247 | MD_CTX context; |
248 | int len; |
249 | unsigned char buffer[16], digest[16]; |
250 | |
251 | MDInit (&context); |
252 | while (len = fread (buffer, 1, 16, stdin)) |
253 | MDUpdate (&context, buffer, len); |
254 | MDFinal (digest, &context); |
255 | |
256 | MDPrint (digest); |
257 | printf ("\n"); |
258 | } |
259 | |
260 | /* Prints a message digest in hexadecimal. |
261 | */ |
262 | static void MDPrint (digest) |
263 | unsigned char digest[16]; |
264 | { |
265 | unsigned int i; |
266 | |
267 | for (i = 0; i < 16; i++) |
268 | printf ("%02x", digest[i]); |
269 | } |