md5.c revision 3995
11844Swollman/* MDDRIVER.C - test driver for MD2, MD4 and MD5
250476Speter */
31844Swollman
41638Srgrimes/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
594940Srurights reserved.
61638Srgrimes
742915SjdpRSA Data Security, Inc. makes no representations concerning either
842915Sjdpthe merchantability of this software or the suitability of this
942915Sjdpsoftware for any particular purpose. It is provided "as is"
1042915Sjdpwithout express or implied warranty of any kind.
11139106Sru
1242915SjdpThese notices must be retained in any copies of any part of this
1342915Sjdpdocumentation and/or software.
1442915Sjdp */
15129024Sdes
16129024Sdes/* The following makes MD default to MD5 if it has not already been
1729141Speter  defined with C compiler flags.
18129024Sdes */
19129024Sdes#ifndef MD
20129024Sdes#define MD 5
21125119Sru#endif
22100332Sru
23100332Sru#include <stdio.h>
2442915Sjdp#include <time.h>
2542915Sjdp#include <string.h>
2629141Speter#include "global.h"
27119607Sru#if MD == 2
28117034Sgordon#include <md2.h>
29119607Sru#endif
30117034Sgordon#if MD == 4
312827Sjkh#include <md4.h>
322827Sjkh#endif
332827Sjkh#if MD == 5
342827Sjkh#include <md5.h>
352827Sjkh#endif
361638Srgrimes
372827Sjkh/* Length of test block, number of test blocks.
381638Srgrimes */
3918529Sbde#define TEST_BLOCK_LEN 1000
4018529Sbde#define TEST_BLOCK_COUNT 1000
411638Srgrimes
4242450Sjdpstatic void MDString PROTO_LIST ((char *));
431638Srgrimesstatic void MDTimeTrial PROTO_LIST ((void));
44117173Srustatic void MDTestSuite PROTO_LIST ((void));
451638Srgrimesstatic void MDFile PROTO_LIST ((char *));
4696512Srustatic void MDFilter PROTO_LIST ((void));
4796512Srustatic void MDPrint PROTO_LIST ((unsigned char [16]));
4896512Sru
4996512Sru#if MD == 2
5096512Sru#define MD_CTX MD2_CTX
5196512Sru#define MDInit MD2Init
5296512Sru#define MDUpdate MD2Update
5396512Sru#define MDFinal MD2Final
54126890Strhodes#endif
55126890Strhodes#if MD == 4
56126890Strhodes#define MD_CTX MD4_CTX
57126890Strhodes#define MDInit MD4Init
58126890Strhodes#define MDUpdate MD4Update
59126890Strhodes#define MDFinal MD4Final
601638Srgrimes#endif
61126890Strhodes#if MD == 5
621638Srgrimes#define MD_CTX MD5_CTX
6342450Sjdp#define MDInit MD5Init
641844Swollman#define MDUpdate MD5Update
651844Swollman#define MDFinal MD5Final
6636673Sdt#endif
67126890Strhodes
681844Swollman/* Main driver.
6942450Sjdp
701844SwollmanArguments (may be any combination):
711844Swollman  -sstring - digests string
721844Swollman  -t       - runs time trial
73127027Strhodes  -x       - runs test script
741844Swollman  filename - digests file
7542450Sjdp  (none)   - digests standard input
761844Swollman */
771844Swollmanint main (argc, argv)
7836054Sbdeint argc;
7936054Sbdechar *argv[];
8036054Sbde{
8142450Sjdp  int i;
8236054Sbde
8336054Sbde  if (argc > 1)
84117173Sru for (i = 1; i < argc; i++)
85117159Sru   if (argv[i][0] == '-' && argv[i][1] == 's')
861638Srgrimes     MDString (argv[i] + 2);
87117173Sru   else if (strcmp (argv[i], "-t") == 0)
88117173Sru     MDTimeTrial ();
89117173Sru   else if (strcmp (argv[i], "-x") == 0)
90117173Sru     MDTestSuite ();
91117173Sru   else
92117173Sru     MDFile (argv[i]);
93117173Sru  else
941844Swollman MDFilter ();
95117122Sru
961844Swollman  return (0);
9742450Sjdp}
98117122Sru
991844Swollman/* Digests a string and prints the result.
10096512Sru */
1011638Srgrimesstatic void MDString (string)
102156772Sdeischenchar *string;
103156772Sdeischen{
104156772Sdeischen  MD_CTX context;
105156772Sdeischen  unsigned char digest[16];
106156772Sdeischen  unsigned int len = strlen (string);
107156772Sdeischen
108156772Sdeischen  MDInit (&context);
109156772Sdeischen  MDUpdate (&context, string, len);
110156772Sdeischen  MDFinal (digest, &context);
111156772Sdeischen
112156772Sdeischen  printf ("MD%d (\"%s\") = ", MD, string);
113156772Sdeischen  MDPrint (digest);
114156772Sdeischen  printf ("\n");
115156772Sdeischen}
116156772Sdeischen
117156772Sdeischen/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
118156772Sdeischen  blocks.
119156772Sdeischen */
120156772Sdeischenstatic void MDTimeTrial ()
121156772Sdeischen{
122156772Sdeischen  MD_CTX context;
123156772Sdeischen  time_t endTime, startTime;
124156772Sdeischen  unsigned char block[TEST_BLOCK_LEN], digest[16];
125156772Sdeischen  unsigned int i;
126156772Sdeischen
127156772Sdeischen  printf
128156772Sdeischen ("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
129156772Sdeischen  TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
130156772Sdeischen
131156772Sdeischen  /* Initialize block */
132156772Sdeischen  for (i = 0; i < TEST_BLOCK_LEN; i++)
133156772Sdeischen block[i] = (unsigned char)(i & 0xff);
134156772Sdeischen
135156772Sdeischen  /* Start timer */
136156772Sdeischen  time (&startTime);
137156772Sdeischen
138156772Sdeischen  /* Digest blocks */
139156772Sdeischen  MDInit (&context);
140156772Sdeischen  for (i = 0; i < TEST_BLOCK_COUNT; i++)
141156772Sdeischen MDUpdate (&context, block, TEST_BLOCK_LEN);
14299362Sru  MDFinal (digest, &context);
14399362Sru
14499362Sru  /* Stop timer */
14599362Sru  time (&endTime);
14696512Sru
14796512Sru  printf (" done\n");
1481638Srgrimes  printf ("Digest = ");
14996512Sru  MDPrint (digest);
15096512Sru  printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
15196512Sru  /*
15296512Sru   * Be careful that endTime-startTime is not zero.
15396512Sru   * (Bug fix from Ric Anderson, ric@Artisoft.COM.)
15499362Sru   */
1551638Srgrimes  printf
15696512Sru ("Speed = %ld bytes/second\n",
15795114Sobrien  (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/((endTime-startTime) != 0 ? (endTime-startTime):1));
158139106Sru}
15996512Sru
16096512Sru/* Digests a reference suite of strings and prints the results.
16195306Sru */
16296512Srustatic void MDTestSuite ()
16396512Sru{
16496512Sru  printf ("MD%d test suite:\n", MD);
16596512Sru
16696512Sru  MDString ("");
16774805Sru  MDString ("a");
1681844Swollman  MDString ("abc");
16999362Sru  MDString ("message digest");
17099362Sru  MDString ("abcdefghijklmnopqrstuvwxyz");
17196512Sru  MDString
17299362Sru ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1731844Swollman  MDString
17496512Sru ("1234567890123456789012345678901234567890\
17596512Sru1234567890123456789012345678901234567890");
1761638Srgrimes}
17742915Sjdp
17842915Sjdp/* Digests a file and prints the result.
17996512Sru */
18042915Sjdpstatic void MDFile (filename)
18196512Sruchar *filename;
18242915Sjdp{
18396343Sobrien  FILE *file;
18496512Sru  MD_CTX context;
18591011Sru  int len;
18628945Speter  unsigned char buffer[1024], digest[16];
1871844Swollman
188148725Sphk  if ((file = fopen (filename, "rb")) == NULL)
18996512Sru printf ("%s can't be opened\n", filename);
19096512Sru
19196512Sru  else {
1922353Sbde MDInit (&context);
19396512Sru while (len = fread (buffer, 1, 1024, file))
19496512Sru   MDUpdate (&context, buffer, len);
19596512Sru MDFinal (digest, &context);
1963859Sbde
1971844Swollman fclose (file);
198139106Sru
19996512Sru printf ("MD%d (%s) = ", MD, filename);
20096512Sru MDPrint (digest);
20196512Sru printf ("\n");
20296512Sru  }
20392491Smarkm}
20496512Sru
20596512Sru/* Digests the standard input and prints the result.
20692491Smarkm */
20792491Smarkmstatic void MDFilter ()
2081638Srgrimes{
209144893Sharti  MD_CTX context;
21096512Sru  int len;
21196512Sru  unsigned char buffer[16], digest[16];
21296512Sru
213139103Sru  MDInit (&context);
21496512Sru  while (len = fread (buffer, 1, 16, stdin))
2151638Srgrimes MDUpdate (&context, buffer, len);
2161638Srgrimes  MDFinal (digest, &context);
21734179Sbde
21824750Sbde  MDPrint (digest);
21942450Sjdp  printf ("\n");
22024750Sbde}
22124750Sbde
222139107Sru/* Prints a message digest in hexadecimal.
22331809Sbde */
22442915Sjdpstatic void MDPrint (digest)
22527910Sasamiunsigned char digest[16];
22628945Speter{
2271638Srgrimes  unsigned int i;
2281638Srgrimes
2291638Srgrimes  for (i = 0; i < 16; i++)
230136019Sru printf ("%02x", digest[i]);
231139111Sru}
2322298Swollman