+/*\r
+ **********************************************************************\r
+ ** md5.h -- Header file for implementation of MD5 **\r
+ ** RSA Data Security, Inc. MD5 Message Digest Algorithm **\r
+ ** Created: 2/17/90 RLR **\r
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **\r
+ ** Revised (for MD5): RLR 4/27/91 **\r
+ ** -- G modified to have y&~z instead of y&z **\r
+ ** -- FF, GG, HH modified to add in last register done **\r
+ ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **\r
+ ** -- distinct additive constant for each step **\r
+ ** -- round 4 added, working mod 7 **\r
+ **********************************************************************\r
+ */\r
+\r
+/*\r
+ **********************************************************************\r
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **\r
+ ** **\r
+ ** License to copy and use this software is granted provided that **\r
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message **\r
+ ** Digest Algorithm" in all material mentioning or referencing this **\r
+ ** software or this function. **\r
+ ** **\r
+ ** License is also granted to make and use derivative works **\r
+ ** provided that such works are identified as "derived from the RSA **\r
+ ** Data Security, Inc. MD5 Message Digest Algorithm" in all **\r
+ ** material mentioning or referencing the derived work. **\r
+ ** **\r
+ ** RSA Data Security, Inc. makes no representations concerning **\r
+ ** either the merchantability of this software or the suitability **\r
+ ** of this software for any particular purpose. It is provided "as **\r
+ ** is" without express or implied warranty of any kind. **\r
+ ** **\r
+ ** These notices must be retained in any copies of any part of this **\r
+ ** documentation and/or software. **\r
+ **********************************************************************\r
+ */\r
+\r
+#include "md5.h"\r
+\r
+/* typedef a 32 bit type */\r
+typedef unsigned long int UINT4;\r
+\r
+/* Data structure for MD5 (Message Digest) computation */\r
+typedef struct {\r
+ UINT4 i[2]; /* number of _bits_ handled mod 2^64 */\r
+ UINT4 buf[4]; /* scratch buffer */\r
+ unsigned char in[64]; /* input buffer */\r
+ unsigned char digest[16]; /* actual digest after MD5Final call */\r
+} MD5_CTX;\r
+\r
+void MD5Init ();\r
+void MD5Update ();\r
+void MD5Final ();\r
+\r
+/*\r
+ **********************************************************************\r
+ ** End of md5.h **\r
+ ******************************* (cut) ********************************\r
+ */\r
+\r
+/*\r
+ **********************************************************************\r
+ ** md5.c **\r
+ ** RSA Data Security, Inc. MD5 Message Digest Algorithm **\r
+ ** Created: 2/17/90 RLR **\r
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **\r
+ **********************************************************************\r
+ */\r
+\r
+/*\r
+ **********************************************************************\r
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **\r
+ ** **\r
+ ** License to copy and use this software is granted provided that **\r
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message **\r
+ ** Digest Algorithm" in all material mentioning or referencing this **\r
+ ** software or this function. **\r
+ ** **\r
+ ** License is also granted to make and use derivative works **\r
+ ** provided that such works are identified as "derived from the RSA **\r
+ ** Data Security, Inc. MD5 Message Digest Algorithm" in all **\r
+ ** material mentioning or referencing the derived work. **\r
+ ** **\r
+ ** RSA Data Security, Inc. makes no representations concerning **\r
+ ** either the merchantability of this software or the suitability **\r
+ ** of this software for any particular purpose. It is provided "as **\r
+ ** is" without express or implied warranty of any kind. **\r
+ ** **\r
+ ** These notices must be retained in any copies of any part of this **\r
+ ** documentation and/or software. **\r
+ **********************************************************************\r
+ */\r
+\r
+/* -- include the following line if the md5.h header file is separate -- */\r
+/* #include "md5.h" */\r
+\r
+/* forward declaration */\r
+static void Transform ();\r
+\r
+static unsigned char PADDING[64] = {\r
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
+};\r
+\r
+/* F, G and H are basic MD5 functions: selection, majority, parity */\r
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))\r
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))\r
+#define H(x, y, z) ((x) ^ (y) ^ (z))\r
+#define I(x, y, z) ((y) ^ ((x) | (~z))) \r
+\r
+/* ROTATE_LEFT rotates x left n bits */\r
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))\r
+\r
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */\r
+/* Rotation is separate from addition to prevent recomputation */\r
+#define FF(a, b, c, d, x, s, ac) \\r
+ {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \\r
+ (a) = ROTATE_LEFT ((a), (s)); \\r
+ (a) += (b); \\r
+ }\r
+#define GG(a, b, c, d, x, s, ac) \\r
+ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \\r
+ (a) = ROTATE_LEFT ((a), (s)); \\r
+ (a) += (b); \\r
+ }\r
+#define HH(a, b, c, d, x, s, ac) \\r
+ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \\r
+ (a) = ROTATE_LEFT ((a), (s)); \\r
+ (a) += (b); \\r
+ }\r
+#define II(a, b, c, d, x, s, ac) \\r
+ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \\r
+ (a) = ROTATE_LEFT ((a), (s)); \\r
+ (a) += (b); \\r
+ }\r
+\r
+void MD5Init (mdContext)\r
+MD5_CTX *mdContext;\r
+{\r
+ mdContext->i[0] = mdContext->i[1] = (UINT4)0;\r
+\r
+ /* Load magic initialization constants.\r
+ */\r
+ mdContext->buf[0] = (UINT4)0x67452301;\r
+ mdContext->buf[1] = (UINT4)0xefcdab89;\r
+ mdContext->buf[2] = (UINT4)0x98badcfe;\r
+ mdContext->buf[3] = (UINT4)0x10325476;\r
+}\r
+\r
+void MD5Update (mdContext, inBuf, inLen)\r
+MD5_CTX *mdContext;\r
+unsigned char *inBuf;\r
+unsigned int inLen;\r
+{\r
+ UINT4 in[16];\r
+ int mdi;\r
+ unsigned int i, ii;\r
+\r
+ /* compute number of bytes mod 64 */\r
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);\r
+\r
+ /* update number of bits */\r
+ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])\r
+ mdContext->i[1]++;\r
+ mdContext->i[0] += ((UINT4)inLen << 3);\r
+ mdContext->i[1] += ((UINT4)inLen >> 29);\r
+\r
+ while (inLen--) {\r
+ /* add new character to buffer, increment mdi */\r
+ mdContext->in[mdi++] = *inBuf++;\r
+\r
+ /* transform if necessary */\r
+ if (mdi == 0x40) {\r
+ for (i = 0, ii = 0; i < 16; i++, ii += 4)\r
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |\r
+ (((UINT4)mdContext->in[ii+2]) << 16) |\r
+ (((UINT4)mdContext->in[ii+1]) << 8) |\r
+ ((UINT4)mdContext->in[ii]);\r
+ Transform (mdContext->buf, in);\r
+ mdi = 0;\r
+ }\r
+ }\r
+}\r
+\r
+void MD5Final (mdContext)\r
+MD5_CTX *mdContext;\r
+{\r
+ UINT4 in[16];\r
+ int mdi;\r
+ unsigned int i, ii;\r
+ unsigned int padLen;\r
+\r
+ /* save number of bits */\r
+ in[14] = mdContext->i[0];\r
+ in[15] = mdContext->i[1];\r
+\r
+ /* compute number of bytes mod 64 */\r
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);\r
+\r
+ /* pad out to 56 mod 64 */\r
+ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);\r
+ MD5Update (mdContext, PADDING, padLen);\r
+\r
+ /* append length in bits and transform */\r
+ for (i = 0, ii = 0; i < 14; i++, ii += 4)\r
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |\r
+ (((UINT4)mdContext->in[ii+2]) << 16) |\r
+ (((UINT4)mdContext->in[ii+1]) << 8) |\r
+ ((UINT4)mdContext->in[ii]);\r
+ Transform (mdContext->buf, in);\r
+\r
+ /* store buffer in digest */\r
+ for (i = 0, ii = 0; i < 4; i++, ii += 4) {\r
+ mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);\r
+ mdContext->digest[ii+1] =\r
+ (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);\r
+ mdContext->digest[ii+2] =\r
+ (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);\r
+ mdContext->digest[ii+3] =\r
+ (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);\r
+ }\r
+}\r
+\r
+/* Basic MD5 step. Transform buf based on in.\r
+ */\r
+static void Transform (buf, in)\r
+UINT4 *buf;\r
+UINT4 *in;\r
+{\r
+ UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];\r
+\r
+ /* Round 1 */\r
+#define S11 7\r
+#define S12 12\r
+#define S13 17\r
+#define S14 22\r
+ FF ( a, b, c, d, in[ 0], S11, 3614090360); /* 1 */\r
+ FF ( d, a, b, c, in[ 1], S12, 3905402710); /* 2 */\r
+ FF ( c, d, a, b, in[ 2], S13, 606105819); /* 3 */\r
+ FF ( b, c, d, a, in[ 3], S14, 3250441966); /* 4 */\r
+ FF ( a, b, c, d, in[ 4], S11, 4118548399); /* 5 */\r
+ FF ( d, a, b, c, in[ 5], S12, 1200080426); /* 6 */\r
+ FF ( c, d, a, b, in[ 6], S13, 2821735955); /* 7 */\r
+ FF ( b, c, d, a, in[ 7], S14, 4249261313); /* 8 */\r
+ FF ( a, b, c, d, in[ 8], S11, 1770035416); /* 9 */\r
+ FF ( d, a, b, c, in[ 9], S12, 2336552879); /* 10 */\r
+ FF ( c, d, a, b, in[10], S13, 4294925233); /* 11 */\r
+ FF ( b, c, d, a, in[11], S14, 2304563134); /* 12 */\r
+ FF ( a, b, c, d, in[12], S11, 1804603682); /* 13 */\r
+ FF ( d, a, b, c, in[13], S12, 4254626195); /* 14 */\r
+ FF ( c, d, a, b, in[14], S13, 2792965006); /* 15 */\r
+ FF ( b, c, d, a, in[15], S14, 1236535329); /* 16 */\r
+\r
+ /* Round 2 */\r
+#define S21 5\r
+#define S22 9\r
+#define S23 14\r
+#define S24 20\r
+ GG ( a, b, c, d, in[ 1], S21, 4129170786); /* 17 */\r
+ GG ( d, a, b, c, in[ 6], S22, 3225465664); /* 18 */\r
+ GG ( c, d, a, b, in[11], S23, 643717713); /* 19 */\r
+ GG ( b, c, d, a, in[ 0], S24, 3921069994); /* 20 */\r
+ GG ( a, b, c, d, in[ 5], S21, 3593408605); /* 21 */\r
+ GG ( d, a, b, c, in[10], S22, 38016083); /* 22 */\r
+ GG ( c, d, a, b, in[15], S23, 3634488961); /* 23 */\r
+ GG ( b, c, d, a, in[ 4], S24, 3889429448); /* 24 */\r
+ GG ( a, b, c, d, in[ 9], S21, 568446438); /* 25 */\r
+ GG ( d, a, b, c, in[14], S22, 3275163606); /* 26 */\r
+ GG ( c, d, a, b, in[ 3], S23, 4107603335); /* 27 */\r
+ GG ( b, c, d, a, in[ 8], S24, 1163531501); /* 28 */\r
+ GG ( a, b, c, d, in[13], S21, 2850285829); /* 29 */\r
+ GG ( d, a, b, c, in[ 2], S22, 4243563512); /* 30 */\r
+ GG ( c, d, a, b, in[ 7], S23, 1735328473); /* 31 */\r
+ GG ( b, c, d, a, in[12], S24, 2368359562); /* 32 */\r
+\r
+ /* Round 3 */\r
+#define S31 4\r
+#define S32 11\r
+#define S33 16\r
+#define S34 23\r
+ HH ( a, b, c, d, in[ 5], S31, 4294588738); /* 33 */\r
+ HH ( d, a, b, c, in[ 8], S32, 2272392833); /* 34 */\r
+ HH ( c, d, a, b, in[11], S33, 1839030562); /* 35 */\r
+ HH ( b, c, d, a, in[14], S34, 4259657740); /* 36 */\r
+ HH ( a, b, c, d, in[ 1], S31, 2763975236); /* 37 */\r
+ HH ( d, a, b, c, in[ 4], S32, 1272893353); /* 38 */\r
+ HH ( c, d, a, b, in[ 7], S33, 4139469664); /* 39 */\r
+ HH ( b, c, d, a, in[10], S34, 3200236656); /* 40 */\r
+ HH ( a, b, c, d, in[13], S31, 681279174); /* 41 */\r
+ HH ( d, a, b, c, in[ 0], S32, 3936430074); /* 42 */\r
+ HH ( c, d, a, b, in[ 3], S33, 3572445317); /* 43 */\r
+ HH ( b, c, d, a, in[ 6], S34, 76029189); /* 44 */\r
+ HH ( a, b, c, d, in[ 9], S31, 3654602809); /* 45 */\r
+ HH ( d, a, b, c, in[12], S32, 3873151461); /* 46 */\r
+ HH ( c, d, a, b, in[15], S33, 530742520); /* 47 */\r
+ HH ( b, c, d, a, in[ 2], S34, 3299628645); /* 48 */\r
+\r
+ /* Round 4 */\r
+#define S41 6\r
+#define S42 10\r
+#define S43 15\r
+#define S44 21\r
+ II ( a, b, c, d, in[ 0], S41, 4096336452); /* 49 */\r
+ II ( d, a, b, c, in[ 7], S42, 1126891415); /* 50 */\r
+ II ( c, d, a, b, in[14], S43, 2878612391); /* 51 */\r
+ II ( b, c, d, a, in[ 5], S44, 4237533241); /* 52 */\r
+ II ( a, b, c, d, in[12], S41, 1700485571); /* 53 */\r
+ II ( d, a, b, c, in[ 3], S42, 2399980690); /* 54 */\r
+ II ( c, d, a, b, in[10], S43, 4293915773); /* 55 */\r
+ II ( b, c, d, a, in[ 1], S44, 2240044497); /* 56 */\r
+ II ( a, b, c, d, in[ 8], S41, 1873313359); /* 57 */\r
+ II ( d, a, b, c, in[15], S42, 4264355552); /* 58 */\r
+ II ( c, d, a, b, in[ 6], S43, 2734768916); /* 59 */\r
+ II ( b, c, d, a, in[13], S44, 1309151649); /* 60 */\r
+ II ( a, b, c, d, in[ 4], S41, 4149444226); /* 61 */\r
+ II ( d, a, b, c, in[11], S42, 3174756917); /* 62 */\r
+ II ( c, d, a, b, in[ 2], S43, 718787259); /* 63 */\r
+ II ( b, c, d, a, in[ 9], S44, 3951481745); /* 64 */\r
+\r
+ buf[0] += a;\r
+ buf[1] += b;\r
+ buf[2] += c;\r
+ buf[3] += d;\r
+}\r
+\r
+/*\r
+ **********************************************************************\r
+ ** End of md5.c **\r
+ ******************************* (cut) ********************************\r
+ */\r
+\r
+/*\r
+ **********************************************************************\r
+ ** md5driver.c -- sample routines to test **\r
+ ** RSA Data Security, Inc. MD5 message digest algorithm. **\r
+ ** Created: 2/16/90 RLR **\r
+ ** Updated: 1/91 SRD **\r
+ **********************************************************************\r
+ */\r
+\r
+/*\r
+ **********************************************************************\r
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **\r
+ ** **\r
+ ** RSA Data Security, Inc. makes no representations concerning **\r
+ ** either the merchantability of this software or the suitability **\r
+ ** of this software for any particular purpose. It is provided "as **\r
+ ** is" without express or implied warranty of any kind. **\r
+ ** **\r
+ ** These notices must be retained in any copies of any part of this **\r
+ ** documentation and/or software. **\r
+ **********************************************************************\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <sys/types.h>\r
+#include <time.h>\r
+#include <string.h>\r
+/* -- include the following file if the file md5.h is separate -- */\r
+/* #include "md5.h" */\r
+\r
+/* Prints message digest buffer in mdContext as 32 hexadecimal digits.\r
+ Order is from low-order byte to high-order byte of digest.\r
+ Each byte is printed with high-order hexadecimal digit first.\r
+ */\r
+static void MDPrint (mdContext)\r
+MD5_CTX *mdContext;\r
+{\r
+ int i;\r
+\r
+ for (i = 0; i < 16; i++)\r
+ printf ("%02x", mdContext->digest[i]);\r
+}\r
+\r
+/* size of test block */\r
+#define TEST_BLOCK_SIZE 1000\r
+\r
+/* number of blocks to process */\r
+#define TEST_BLOCKS 10000\r
+\r
+/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */\r
+static long TEST_BYTES = (long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS;\r
+\r
+/* A time trial routine, to measure the speed of MD5.\r
+ Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE\r
+ characters.\r
+ */\r
+static void MDTimeTrial ()\r
+{\r
+ MD5_CTX mdContext;\r
+ time_t endTime, startTime;\r
+ unsigned char data[TEST_BLOCK_SIZE];\r
+ unsigned int i;\r
+\r
+ /* initialize test data */\r
+ for (i = 0; i < TEST_BLOCK_SIZE; i++)\r
+ data[i] = (unsigned char)(i & 0xFF);\r
+\r
+ /* start timer */\r
+ printf ("MD5 time trial. Processing %ld characters...\n", TEST_BYTES);\r
+ time (&startTime);\r
+\r
+ /* digest data in TEST_BLOCK_SIZE byte blocks */\r
+ MD5Init (&mdContext);\r
+ for (i = TEST_BLOCKS; i > 0; i--)\r
+ MD5Update (&mdContext, data, TEST_BLOCK_SIZE);\r
+ MD5Final (&mdContext);\r
+\r
+ /* stop timer, get time difference */\r
+ time (&endTime);\r
+ MDPrint (&mdContext);\r
+ printf (" is digest of test input.\n");\r
+ printf\r
+ ("Seconds to process test input: %ld\n", (long)(endTime-startTime));\r
+ printf\r
+ ("Characters processed per second: %ld\n",\r
+ TEST_BYTES/(endTime-startTime));\r
+}\r
+\r
+/* Computes the message digest for string inString.\r
+ Prints out message digest, a space, the string (in quotes) and a\r
+ carriage return.\r
+ */\r
+static void MDString (inString)\r
+char *inString;\r
+{\r
+ MD5_CTX mdContext;\r
+ unsigned int len = strlen (inString);\r
+\r
+ MD5Init (&mdContext);\r
+ MD5Update (&mdContext, inString, len);\r
+ MD5Final (&mdContext);\r
+ MDPrint (&mdContext);\r
+ printf (" \"%s\"\n\n", inString);\r
+}\r
+\r
+/* Computes the message digest for a specified file.\r
+ Prints out message digest, a space, the file name, and a carriage\r
+ return.\r
+ */\r
+static void MDFile (filename)\r
+char *filename;\r
+{\r
+ FILE *inFile = fopen (filename, "rb");\r
+ MD5_CTX mdContext;\r
+ int bytes;\r
+ unsigned char data[1024];\r
+\r
+ if (inFile == NULL) {\r
+ printf ("%s can't be opened.\n", filename);\r
+ return;\r
+ }\r
+\r
+ MD5Init (&mdContext);\r
+ while ((bytes = fread (data, 1, 1024, inFile)) != 0)\r
+ MD5Update (&mdContext, data, bytes);\r
+ MD5Final (&mdContext);\r
+ MDPrint (&mdContext);\r
+ printf (" %s\n", filename);\r
+ fclose (inFile);\r
+}\r
+\r
+/* Writes the message digest of the data from stdin onto stdout,\r
+ followed by a carriage return.\r
+ */\r
+static void MDFilter ()\r
+{\r
+ MD5_CTX mdContext;\r
+ int bytes;\r
+ unsigned char data[16];\r
+\r
+ MD5Init (&mdContext);\r
+ while ((bytes = fread (data, 1, 16, stdin)) != 0)\r
+ MD5Update (&mdContext, data, bytes);\r
+ MD5Final (&mdContext);\r
+ MDPrint (&mdContext);\r
+ printf ("\n");\r
+}\r
+\r
+/* Runs a standard suite of test data.\r
+ */\r
+static void MDTestSuite ()\r
+{\r
+ printf ("MD5 test suite results:\n\n");\r
+ MDString ("");\r
+ MDString ("a");\r
+ MDString ("abc");\r
+ MDString ("message digest");\r
+ MDString ("abcdefghijklmnopqrstuvwxyz");\r
+ MDString\r
+ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");\r
+ MDString\r
+ ("1234567890123456789012345678901234567890\\r
+1234567890123456789012345678901234567890");\r
+ /* Contents of file foo are "abc" */\r
+ MDFile ("foo");\r
+}\r
+\r
+static void MD5 (mdContext, inString)\r
+MD5_CTX * mdContext;\r
+char * inString;\r
+{\r
+ unsigned int len = strlen (inString);\r
+\r
+ MD5Init (mdContext);\r
+ MD5Update (mdContext, inString, len);\r
+ MD5Final (mdContext);\r
+}\r
+\r
+static void MDPrintDebug (digest)\r
+unsigned char digest[16];\r
+{\r
+ int i;\r
+\r
+ for (i = 0; i < 16; i++)\r
+ printf ("%02x", digest[i]);\r
+}\r
+\r
+static void MDHmac (key, inString)\r
+unsigned char * key;\r
+unsigned char * inString;\r
+{\r
+ mbedtls_md5_context mdContext;\r
+ unsigned int keylen;\r
+ int pos;\r
+ unsigned char ipad[64];\r
+ unsigned char opad[64];\r
+ unsigned char hash[16];\r
+\r
+ // Ensure key length is exaclty 16 bytes\r
+ keylen = strlen(key);\r
+ if (keylen > 64) {\r
+ mbedtls_md5(key, keylen, hash);\r
+ memcpy(ipad, hash, 16);\r
+ memcpy(opad, hash, 16);\r
+ keylen = 16;\r
+ }\r
+ else {\r
+ memcpy(ipad, key, keylen);\r
+ memcpy(opad, key, keylen);\r
+ }\r
+ for (pos = keylen; pos < 64; pos++) {\r
+ ipad[pos] = '\0';\r
+ opad[pos] = '\0';\r
+ }\r
+\r
+ for (pos = 0; pos < 64; pos++) {\r
+ ipad[pos] ^= 0x36;\r
+ opad[pos] ^= 0x5C;\r
+ }\r
+\r
+ mbedtls_md5_init(& mdContext);\r
+ mbedtls_md5_starts(& mdContext);\r
+ mbedtls_md5_update(& mdContext, ipad, 64);\r
+ mbedtls_md5_update(& mdContext, inString, strlen(inString));\r
+ mbedtls_md5_finish(& mdContext, hash);\r
+ mbedtls_md5_free(& mdContext);\r
+\r
+ mbedtls_md5_init(& mdContext);\r
+ mbedtls_md5_starts(& mdContext);\r
+ mbedtls_md5_update(& mdContext, opad, 64);\r
+ mbedtls_md5_update(& mdContext, hash, 16);\r
+ mbedtls_md5_finish(& mdContext, hash);\r
+ mbedtls_md5_free(& mdContext);\r
+\r
+ MDPrintDebug (hash);\r
+ printf ("\n");\r
+}\r
+\r
+static void MDTestHmac ()\r
+{\r
+ unsigned char output[16];\r
+ mbedtls_md5("Hello", 5, output);\r
+ MDPrintDebug(output);\r
+ printf ("\n");\r
+ \r
+ MDHmac ("key", "The quick brown fox jumps over the lazy dog");\r
+}\r
+\r
+void main (argc, argv)\r
+int argc;\r
+char *argv[];\r
+{\r
+ int i;\r
+\r
+ /* For each command line argument in turn:\r
+ ** filename -- prints message digest and name of file\r
+ ** -sstring -- prints message digest and contents of string\r
+ ** -t -- prints time trial statistics for 1M characters\r
+ ** -x -- execute a standard suite of test data\r
+ ** (no args) -- writes messages digest of stdin onto stdout\r
+ */\r
+ if (argc == 1)\r
+ MDFilter ();\r
+ else\r
+ for (i = 1; i < argc; i++)\r
+ if (argv[i][0] == '-' && argv[i][1] == 's')\r
+ MDString (argv[i] + 2);\r
+ else if (strcmp (argv[i], "-t") == 0)\r
+ MDTimeTrial ();\r
+ else if (strcmp (argv[i], "-x") == 0)\r
+ MDTestSuite ();\r
+ else if (strcmp (argv[i], "-h") == 0)\r
+ MDTestHmac ();\r
+ else MDFile (argv[i]);\r
+}\r
+\r
+/*\r
+ **********************************************************************\r
+ ** End of md5driver.c **\r
+ ******************************* (cut) ********************************\r
+ */\r