md5.c revision 3995
13995Spst/* MDDRIVER.C - test driver for MD2, MD4 and MD5
23995Spst */
33995Spst
43995Spst/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
53995Spstrights reserved.
63995Spst
73995SpstRSA Data Security, Inc. makes no representations concerning either
83995Spstthe merchantability of this software or the suitability of this
93995Spstsoftware for any particular purpose. It is provided "as is"
103995Spstwithout express or implied warranty of any kind.
113995Spst
123995SpstThese notices must be retained in any copies of any part of this
133995Spstdocumentation and/or software.
143995Spst */
153995Spst
163995Spst/* The following makes MD default to MD5 if it has not already been
173995Spst  defined with C compiler flags.
183995Spst */
193995Spst#ifndef MD
203995Spst#define MD 5
213995Spst#endif
223995Spst
233995Spst#include <stdio.h>
243995Spst#include <time.h>
253995Spst#include <string.h>
263995Spst#include "global.h"
273995Spst#if MD == 2
283995Spst#include <md2.h>
293995Spst#endif
303995Spst#if MD == 4
313995Spst#include <md4.h>
323995Spst#endif
333995Spst#if MD == 5
343995Spst#include <md5.h>
353995Spst#endif
363995Spst
373995Spst/* Length of test block, number of test blocks.
383995Spst */
393995Spst#define TEST_BLOCK_LEN 1000
403995Spst#define TEST_BLOCK_COUNT 1000
413995Spst
423995Spststatic void MDString PROTO_LIST ((char *));
433995Spststatic void MDTimeTrial PROTO_LIST ((void));
443995Spststatic void MDTestSuite PROTO_LIST ((void));
453995Spststatic void MDFile PROTO_LIST ((char *));
463995Spststatic void MDFilter PROTO_LIST ((void));
473995Spststatic void MDPrint PROTO_LIST ((unsigned char [16]));
483995Spst
493995Spst#if MD == 2
503995Spst#define MD_CTX MD2_CTX
513995Spst#define MDInit MD2Init
523995Spst#define MDUpdate MD2Update
533995Spst#define MDFinal MD2Final
543995Spst#endif
553995Spst#if MD == 4
563995Spst#define MD_CTX MD4_CTX
573995Spst#define MDInit MD4Init
583995Spst#define MDUpdate MD4Update
593995Spst#define MDFinal MD4Final
603995Spst#endif
613995Spst#if MD == 5
623995Spst#define MD_CTX MD5_CTX
633995Spst#define MDInit MD5Init
643995Spst#define MDUpdate MD5Update
653995Spst#define MDFinal MD5Final
663995Spst#endif
673995Spst
683995Spst/* Main driver.
693995Spst
703995SpstArguments (may be any combination):
713995Spst  -sstring - digests string
723995Spst  -t       - runs time trial
733995Spst  -x       - runs test script
743995Spst  filename - digests file
753995Spst  (none)   - digests standard input
763995Spst */
773995Spstint main (argc, argv)
783995Spstint argc;
793995Spstchar *argv[];
803995Spst{
813995Spst  int i;
823995Spst
833995Spst  if (argc > 1)
843995Spst for (i = 1; i < argc; i++)
853995Spst   if (argv[i][0] == '-' && argv[i][1] == 's')
863995Spst     MDString (argv[i] + 2);
873995Spst   else if (strcmp (argv[i], "-t") == 0)
883995Spst     MDTimeTrial ();
893995Spst   else if (strcmp (argv[i], "-x") == 0)
903995Spst     MDTestSuite ();
913995Spst   else
923995Spst     MDFile (argv[i]);
933995Spst  else
943995Spst MDFilter ();
953995Spst
963995Spst  return (0);
973995Spst}
983995Spst
993995Spst/* Digests a string and prints the result.
1003995Spst */
1013995Spststatic void MDString (string)
1023995Spstchar *string;
1033995Spst{
1043995Spst  MD_CTX context;
1053995Spst  unsigned char digest[16];
1063995Spst  unsigned int len = strlen (string);
1073995Spst
1083995Spst  MDInit (&context);
1093995Spst  MDUpdate (&context, string, len);
1103995Spst  MDFinal (digest, &context);
1113995Spst
1123995Spst  printf ("MD%d (\"%s\") = ", MD, string);
1133995Spst  MDPrint (digest);
1143995Spst  printf ("\n");
1153995Spst}
1163995Spst
1173995Spst/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
1183995Spst  blocks.
1193995Spst */
1203995Spststatic void MDTimeTrial ()
1213995Spst{
1223995Spst  MD_CTX context;
1233995Spst  time_t endTime, startTime;
1243995Spst  unsigned char block[TEST_BLOCK_LEN], digest[16];
1253995Spst  unsigned int i;
1263995Spst
1273995Spst  printf
1283995Spst ("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
1293995Spst  TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
1303995Spst
1313995Spst  /* Initialize block */
1323995Spst  for (i = 0; i < TEST_BLOCK_LEN; i++)
1333995Spst block[i] = (unsigned char)(i & 0xff);
1343995Spst
1353995Spst  /* Start timer */
1363995Spst  time (&startTime);
1373995Spst
1383995Spst  /* Digest blocks */
1393995Spst  MDInit (&context);
1403995Spst  for (i = 0; i < TEST_BLOCK_COUNT; i++)
1413995Spst MDUpdate (&context, block, TEST_BLOCK_LEN);
1423995Spst  MDFinal (digest, &context);
1433995Spst
1443995Spst  /* Stop timer */
1453995Spst  time (&endTime);
1463995Spst
1473995Spst  printf (" done\n");
1483995Spst  printf ("Digest = ");
1493995Spst  MDPrint (digest);
1503995Spst  printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
1513995Spst  /*
1523995Spst   * Be careful that endTime-startTime is not zero.
1533995Spst   * (Bug fix from Ric Anderson, ric@Artisoft.COM.)
1543995Spst   */
1553995Spst  printf
1563995Spst ("Speed = %ld bytes/second\n",
1573995Spst  (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/((endTime-startTime) != 0 ? (endTime-startTime):1));
1583995Spst}
1593995Spst
1603995Spst/* Digests a reference suite of strings and prints the results.
1613995Spst */
1623995Spststatic void MDTestSuite ()
1633995Spst{
1643995Spst  printf ("MD%d test suite:\n", MD);
1653995Spst
1663995Spst  MDString ("");
1673995Spst  MDString ("a");
1683995Spst  MDString ("abc");
1693995Spst  MDString ("message digest");
1703995Spst  MDString ("abcdefghijklmnopqrstuvwxyz");
1713995Spst  MDString
1723995Spst ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1733995Spst  MDString
1743995Spst ("1234567890123456789012345678901234567890\
1753995Spst1234567890123456789012345678901234567890");
1763995Spst}
1773995Spst
1783995Spst/* Digests a file and prints the result.
1793995Spst */
1803995Spststatic void MDFile (filename)
1813995Spstchar *filename;
1823995Spst{
1833995Spst  FILE *file;
1843995Spst  MD_CTX context;
1853995Spst  int len;
1863995Spst  unsigned char buffer[1024], digest[16];
1873995Spst
1883995Spst  if ((file = fopen (filename, "rb")) == NULL)
1893995Spst printf ("%s can't be opened\n", filename);
1903995Spst
1913995Spst  else {
1923995Spst MDInit (&context);
1933995Spst while (len = fread (buffer, 1, 1024, file))
1943995Spst   MDUpdate (&context, buffer, len);
1953995Spst MDFinal (digest, &context);
1963995Spst
1973995Spst fclose (file);
1983995Spst
1993995Spst printf ("MD%d (%s) = ", MD, filename);
2003995Spst MDPrint (digest);
2013995Spst printf ("\n");
2023995Spst  }
2033995Spst}
2043995Spst
2053995Spst/* Digests the standard input and prints the result.
2063995Spst */
2073995Spststatic void MDFilter ()
2083995Spst{
2093995Spst  MD_CTX context;
2103995Spst  int len;
2113995Spst  unsigned char buffer[16], digest[16];
2123995Spst
2133995Spst  MDInit (&context);
2143995Spst  while (len = fread (buffer, 1, 16, stdin))
2153995Spst MDUpdate (&context, buffer, len);
2163995Spst  MDFinal (digest, &context);
2173995Spst
2183995Spst  MDPrint (digest);
2193995Spst  printf ("\n");
2203995Spst}
2213995Spst
2223995Spst/* Prints a message digest in hexadecimal.
2233995Spst */
2243995Spststatic void MDPrint (digest)
2253995Spstunsigned char digest[16];
2263995Spst{
2273995Spst  unsigned int i;
2283995Spst
2293995Spst  for (i = 0; i < 16; i++)
2303995Spst printf ("%02x", digest[i]);
2313995Spst}
232