2 **********************************************************************
3 ** md5.h -- Header file for implementation of MD5 **
4 ** RSA Data Security, Inc. MD5 Message Digest Algorithm **
5 ** Created: 2/17/90 RLR **
6 ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
7 ** Revised (for MD5): RLR 4/27/91 **
8 ** -- G modified to have y&~z instead of y&z **
9 ** -- FF, GG, HH modified to add in last register done **
10 ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
11 ** -- distinct additive constant for each step **
12 ** -- round 4 added, working mod 7 **
13 **********************************************************************
17 **********************************************************************
18 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
20 ** License to copy and use this software is granted provided that **
21 ** it is identified as the "RSA Data Security, Inc. MD5 Message **
22 ** Digest Algorithm" in all material mentioning or referencing this **
23 ** software or this function. **
25 ** License is also granted to make and use derivative works **
26 ** provided that such works are identified as "derived from the RSA **
27 ** Data Security, Inc. MD5 Message Digest Algorithm" in all **
28 ** material mentioning or referencing the derived work. **
30 ** RSA Data Security, Inc. makes no representations concerning **
31 ** either the merchantability of this software or the suitability **
32 ** of this software for any particular purpose. It is provided "as **
33 ** is" without express or implied warranty of any kind. **
35 ** These notices must be retained in any copies of any part of this **
36 ** documentation and/or software. **
37 **********************************************************************
42 /* typedef a 32 bit type */
43 typedef unsigned long int UINT4
;
45 /* Data structure for MD5 (Message Digest) computation */
47 UINT4 i
[2]; /* number of _bits_ handled mod 2^64 */
48 UINT4 buf
[4]; /* scratch buffer */
49 unsigned char in
[64]; /* input buffer */
50 unsigned char digest
[16]; /* actual digest after MD5Final call */
58 **********************************************************************
60 ******************************* (cut) ********************************
64 **********************************************************************
66 ** RSA Data Security, Inc. MD5 Message Digest Algorithm **
67 ** Created: 2/17/90 RLR **
68 ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
69 **********************************************************************
73 **********************************************************************
74 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
76 ** License to copy and use this software is granted provided that **
77 ** it is identified as the "RSA Data Security, Inc. MD5 Message **
78 ** Digest Algorithm" in all material mentioning or referencing this **
79 ** software or this function. **
81 ** License is also granted to make and use derivative works **
82 ** provided that such works are identified as "derived from the RSA **
83 ** Data Security, Inc. MD5 Message Digest Algorithm" in all **
84 ** material mentioning or referencing the derived work. **
86 ** RSA Data Security, Inc. makes no representations concerning **
87 ** either the merchantability of this software or the suitability **
88 ** of this software for any particular purpose. It is provided "as **
89 ** is" without express or implied warranty of any kind. **
91 ** These notices must be retained in any copies of any part of this **
92 ** documentation and/or software. **
93 **********************************************************************
96 /* -- include the following line if the md5.h header file is separate -- */
97 /* #include "md5.h" */
99 /* forward declaration */
100 static void Transform ();
102 static unsigned char PADDING
[64] = {
103 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
113 /* F, G and H are basic MD5 functions: selection, majority, parity */
114 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
115 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
116 #define H(x, y, z) ((x) ^ (y) ^ (z))
117 #define I(x, y, z) ((y) ^ ((x) | (~z)))
119 /* ROTATE_LEFT rotates x left n bits */
120 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
122 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
123 /* Rotation is separate from addition to prevent recomputation */
124 #define FF(a, b, c, d, x, s, ac) \
125 {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
126 (a) = ROTATE_LEFT ((a), (s)); \
129 #define GG(a, b, c, d, x, s, ac) \
130 {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
131 (a) = ROTATE_LEFT ((a), (s)); \
134 #define HH(a, b, c, d, x, s, ac) \
135 {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
136 (a) = ROTATE_LEFT ((a), (s)); \
139 #define II(a, b, c, d, x, s, ac) \
140 {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
141 (a) = ROTATE_LEFT ((a), (s)); \
145 void MD5Init (mdContext
)
148 mdContext
->i
[0] = mdContext
->i
[1] = (UINT4
)0;
150 /* Load magic initialization constants.
152 mdContext
->buf
[0] = (UINT4
)0x67452301;
153 mdContext
->buf
[1] = (UINT4
)0xefcdab89;
154 mdContext
->buf
[2] = (UINT4
)0x98badcfe;
155 mdContext
->buf
[3] = (UINT4
)0x10325476;
158 void MD5Update (mdContext
, inBuf
, inLen
)
160 unsigned char *inBuf
;
167 /* compute number of bytes mod 64 */
168 mdi
= (int)((mdContext
->i
[0] >> 3) & 0x3F);
170 /* update number of bits */
171 if ((mdContext
->i
[0] + ((UINT4
)inLen
<< 3)) < mdContext
->i
[0])
173 mdContext
->i
[0] += ((UINT4
)inLen
<< 3);
174 mdContext
->i
[1] += ((UINT4
)inLen
>> 29);
177 /* add new character to buffer, increment mdi */
178 mdContext
->in
[mdi
++] = *inBuf
++;
180 /* transform if necessary */
182 for (i
= 0, ii
= 0; i
< 16; i
++, ii
+= 4)
183 in
[i
] = (((UINT4
)mdContext
->in
[ii
+3]) << 24) |
184 (((UINT4
)mdContext
->in
[ii
+2]) << 16) |
185 (((UINT4
)mdContext
->in
[ii
+1]) << 8) |
186 ((UINT4
)mdContext
->in
[ii
]);
187 Transform (mdContext
->buf
, in
);
193 void MD5Final (mdContext
)
201 /* save number of bits */
202 in
[14] = mdContext
->i
[0];
203 in
[15] = mdContext
->i
[1];
205 /* compute number of bytes mod 64 */
206 mdi
= (int)((mdContext
->i
[0] >> 3) & 0x3F);
208 /* pad out to 56 mod 64 */
209 padLen
= (mdi
< 56) ? (56 - mdi
) : (120 - mdi
);
210 MD5Update (mdContext
, PADDING
, padLen
);
212 /* append length in bits and transform */
213 for (i
= 0, ii
= 0; i
< 14; i
++, ii
+= 4)
214 in
[i
] = (((UINT4
)mdContext
->in
[ii
+3]) << 24) |
215 (((UINT4
)mdContext
->in
[ii
+2]) << 16) |
216 (((UINT4
)mdContext
->in
[ii
+1]) << 8) |
217 ((UINT4
)mdContext
->in
[ii
]);
218 Transform (mdContext
->buf
, in
);
220 /* store buffer in digest */
221 for (i
= 0, ii
= 0; i
< 4; i
++, ii
+= 4) {
222 mdContext
->digest
[ii
] = (unsigned char)(mdContext
->buf
[i
] & 0xFF);
223 mdContext
->digest
[ii
+1] =
224 (unsigned char)((mdContext
->buf
[i
] >> 8) & 0xFF);
225 mdContext
->digest
[ii
+2] =
226 (unsigned char)((mdContext
->buf
[i
] >> 16) & 0xFF);
227 mdContext
->digest
[ii
+3] =
228 (unsigned char)((mdContext
->buf
[i
] >> 24) & 0xFF);
232 /* Basic MD5 step. Transform buf based on in.
234 static void Transform (buf
, in
)
238 UINT4 a
= buf
[0], b
= buf
[1], c
= buf
[2], d
= buf
[3];
245 FF ( a
, b
, c
, d
, in
[ 0], S11
, 3614090360); /* 1 */
246 FF ( d
, a
, b
, c
, in
[ 1], S12
, 3905402710); /* 2 */
247 FF ( c
, d
, a
, b
, in
[ 2], S13
, 606105819); /* 3 */
248 FF ( b
, c
, d
, a
, in
[ 3], S14
, 3250441966); /* 4 */
249 FF ( a
, b
, c
, d
, in
[ 4], S11
, 4118548399); /* 5 */
250 FF ( d
, a
, b
, c
, in
[ 5], S12
, 1200080426); /* 6 */
251 FF ( c
, d
, a
, b
, in
[ 6], S13
, 2821735955); /* 7 */
252 FF ( b
, c
, d
, a
, in
[ 7], S14
, 4249261313); /* 8 */
253 FF ( a
, b
, c
, d
, in
[ 8], S11
, 1770035416); /* 9 */
254 FF ( d
, a
, b
, c
, in
[ 9], S12
, 2336552879); /* 10 */
255 FF ( c
, d
, a
, b
, in
[10], S13
, 4294925233); /* 11 */
256 FF ( b
, c
, d
, a
, in
[11], S14
, 2304563134); /* 12 */
257 FF ( a
, b
, c
, d
, in
[12], S11
, 1804603682); /* 13 */
258 FF ( d
, a
, b
, c
, in
[13], S12
, 4254626195); /* 14 */
259 FF ( c
, d
, a
, b
, in
[14], S13
, 2792965006); /* 15 */
260 FF ( b
, c
, d
, a
, in
[15], S14
, 1236535329); /* 16 */
267 GG ( a
, b
, c
, d
, in
[ 1], S21
, 4129170786); /* 17 */
268 GG ( d
, a
, b
, c
, in
[ 6], S22
, 3225465664); /* 18 */
269 GG ( c
, d
, a
, b
, in
[11], S23
, 643717713); /* 19 */
270 GG ( b
, c
, d
, a
, in
[ 0], S24
, 3921069994); /* 20 */
271 GG ( a
, b
, c
, d
, in
[ 5], S21
, 3593408605); /* 21 */
272 GG ( d
, a
, b
, c
, in
[10], S22
, 38016083); /* 22 */
273 GG ( c
, d
, a
, b
, in
[15], S23
, 3634488961); /* 23 */
274 GG ( b
, c
, d
, a
, in
[ 4], S24
, 3889429448); /* 24 */
275 GG ( a
, b
, c
, d
, in
[ 9], S21
, 568446438); /* 25 */
276 GG ( d
, a
, b
, c
, in
[14], S22
, 3275163606); /* 26 */
277 GG ( c
, d
, a
, b
, in
[ 3], S23
, 4107603335); /* 27 */
278 GG ( b
, c
, d
, a
, in
[ 8], S24
, 1163531501); /* 28 */
279 GG ( a
, b
, c
, d
, in
[13], S21
, 2850285829); /* 29 */
280 GG ( d
, a
, b
, c
, in
[ 2], S22
, 4243563512); /* 30 */
281 GG ( c
, d
, a
, b
, in
[ 7], S23
, 1735328473); /* 31 */
282 GG ( b
, c
, d
, a
, in
[12], S24
, 2368359562); /* 32 */
289 HH ( a
, b
, c
, d
, in
[ 5], S31
, 4294588738); /* 33 */
290 HH ( d
, a
, b
, c
, in
[ 8], S32
, 2272392833); /* 34 */
291 HH ( c
, d
, a
, b
, in
[11], S33
, 1839030562); /* 35 */
292 HH ( b
, c
, d
, a
, in
[14], S34
, 4259657740); /* 36 */
293 HH ( a
, b
, c
, d
, in
[ 1], S31
, 2763975236); /* 37 */
294 HH ( d
, a
, b
, c
, in
[ 4], S32
, 1272893353); /* 38 */
295 HH ( c
, d
, a
, b
, in
[ 7], S33
, 4139469664); /* 39 */
296 HH ( b
, c
, d
, a
, in
[10], S34
, 3200236656); /* 40 */
297 HH ( a
, b
, c
, d
, in
[13], S31
, 681279174); /* 41 */
298 HH ( d
, a
, b
, c
, in
[ 0], S32
, 3936430074); /* 42 */
299 HH ( c
, d
, a
, b
, in
[ 3], S33
, 3572445317); /* 43 */
300 HH ( b
, c
, d
, a
, in
[ 6], S34
, 76029189); /* 44 */
301 HH ( a
, b
, c
, d
, in
[ 9], S31
, 3654602809); /* 45 */
302 HH ( d
, a
, b
, c
, in
[12], S32
, 3873151461); /* 46 */
303 HH ( c
, d
, a
, b
, in
[15], S33
, 530742520); /* 47 */
304 HH ( b
, c
, d
, a
, in
[ 2], S34
, 3299628645); /* 48 */
311 II ( a
, b
, c
, d
, in
[ 0], S41
, 4096336452); /* 49 */
312 II ( d
, a
, b
, c
, in
[ 7], S42
, 1126891415); /* 50 */
313 II ( c
, d
, a
, b
, in
[14], S43
, 2878612391); /* 51 */
314 II ( b
, c
, d
, a
, in
[ 5], S44
, 4237533241); /* 52 */
315 II ( a
, b
, c
, d
, in
[12], S41
, 1700485571); /* 53 */
316 II ( d
, a
, b
, c
, in
[ 3], S42
, 2399980690); /* 54 */
317 II ( c
, d
, a
, b
, in
[10], S43
, 4293915773); /* 55 */
318 II ( b
, c
, d
, a
, in
[ 1], S44
, 2240044497); /* 56 */
319 II ( a
, b
, c
, d
, in
[ 8], S41
, 1873313359); /* 57 */
320 II ( d
, a
, b
, c
, in
[15], S42
, 4264355552); /* 58 */
321 II ( c
, d
, a
, b
, in
[ 6], S43
, 2734768916); /* 59 */
322 II ( b
, c
, d
, a
, in
[13], S44
, 1309151649); /* 60 */
323 II ( a
, b
, c
, d
, in
[ 4], S41
, 4149444226); /* 61 */
324 II ( d
, a
, b
, c
, in
[11], S42
, 3174756917); /* 62 */
325 II ( c
, d
, a
, b
, in
[ 2], S43
, 718787259); /* 63 */
326 II ( b
, c
, d
, a
, in
[ 9], S44
, 3951481745); /* 64 */
335 **********************************************************************
337 ******************************* (cut) ********************************
341 **********************************************************************
342 ** md5driver.c -- sample routines to test **
343 ** RSA Data Security, Inc. MD5 message digest algorithm. **
344 ** Created: 2/16/90 RLR **
345 ** Updated: 1/91 SRD **
346 **********************************************************************
350 **********************************************************************
351 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
353 ** RSA Data Security, Inc. makes no representations concerning **
354 ** either the merchantability of this software or the suitability **
355 ** of this software for any particular purpose. It is provided "as **
356 ** is" without express or implied warranty of any kind. **
358 ** These notices must be retained in any copies of any part of this **
359 ** documentation and/or software. **
360 **********************************************************************
364 #include <sys/types.h>
367 /* -- include the following file if the file md5.h is separate -- */
368 /* #include "md5.h" */
370 /* Prints message digest buffer in mdContext as 32 hexadecimal digits.
371 Order is from low-order byte to high-order byte of digest.
372 Each byte is printed with high-order hexadecimal digit first.
374 static void MDPrint (mdContext
)
379 for (i
= 0; i
< 16; i
++)
380 printf ("%02x", mdContext
->digest
[i
]);
383 /* size of test block */
384 #define TEST_BLOCK_SIZE 1000
386 /* number of blocks to process */
387 #define TEST_BLOCKS 10000
389 /* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */
390 static long TEST_BYTES
= (long)TEST_BLOCK_SIZE
* (long)TEST_BLOCKS
;
392 /* A time trial routine, to measure the speed of MD5.
393 Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE
396 static void MDTimeTrial ()
399 time_t endTime
, startTime
;
400 unsigned char data
[TEST_BLOCK_SIZE
];
403 /* initialize test data */
404 for (i
= 0; i
< TEST_BLOCK_SIZE
; i
++)
405 data
[i
] = (unsigned char)(i
& 0xFF);
408 printf ("MD5 time trial. Processing %ld characters...\n", TEST_BYTES
);
411 /* digest data in TEST_BLOCK_SIZE byte blocks */
412 MD5Init (&mdContext
);
413 for (i
= TEST_BLOCKS
; i
> 0; i
--)
414 MD5Update (&mdContext
, data
, TEST_BLOCK_SIZE
);
415 MD5Final (&mdContext
);
417 /* stop timer, get time difference */
419 MDPrint (&mdContext
);
420 printf (" is digest of test input.\n");
422 ("Seconds to process test input: %ld\n", (long)(endTime
-startTime
));
424 ("Characters processed per second: %ld\n",
425 TEST_BYTES
/(endTime
-startTime
));
428 /* Computes the message digest for string inString.
429 Prints out message digest, a space, the string (in quotes) and a
432 static void MDString (inString
)
436 unsigned int len
= strlen (inString
);
438 MD5Init (&mdContext
);
439 MD5Update (&mdContext
, inString
, len
);
440 MD5Final (&mdContext
);
441 MDPrint (&mdContext
);
442 printf (" \"%s\"\n\n", inString
);
445 /* Computes the message digest for a specified file.
446 Prints out message digest, a space, the file name, and a carriage
449 static void MDFile (filename
)
452 FILE *inFile
= fopen (filename
, "rb");
455 unsigned char data
[1024];
457 if (inFile
== NULL
) {
458 printf ("%s can't be opened.\n", filename
);
462 MD5Init (&mdContext
);
463 while ((bytes
= fread (data
, 1, 1024, inFile
)) != 0)
464 MD5Update (&mdContext
, data
, bytes
);
465 MD5Final (&mdContext
);
466 MDPrint (&mdContext
);
467 printf (" %s\n", filename
);
471 /* Writes the message digest of the data from stdin onto stdout,
472 followed by a carriage return.
474 static void MDFilter ()
478 unsigned char data
[16];
480 MD5Init (&mdContext
);
481 while ((bytes
= fread (data
, 1, 16, stdin
)) != 0)
482 MD5Update (&mdContext
, data
, bytes
);
483 MD5Final (&mdContext
);
484 MDPrint (&mdContext
);
488 /* Runs a standard suite of test data.
490 static void MDTestSuite ()
492 printf ("MD5 test suite results:\n\n");
496 MDString ("message digest");
497 MDString ("abcdefghijklmnopqrstuvwxyz");
499 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
501 ("1234567890123456789012345678901234567890\
502 1234567890123456789012345678901234567890");
503 /* Contents of file foo are "abc" */
507 static void MD5 (mdContext
, inString
)
511 unsigned int len
= strlen (inString
);
514 MD5Update (mdContext
, inString
, len
);
515 MD5Final (mdContext
);
518 static void MDPrintDebug (digest
)
519 unsigned char digest
[16];
523 for (i
= 0; i
< 16; i
++)
524 printf ("%02x", digest
[i
]);
527 static void MDHmac (key
, inString
)
529 unsigned char * inString
;
531 mbedtls_md5_context mdContext
;
534 unsigned char ipad
[64];
535 unsigned char opad
[64];
536 unsigned char hash
[16];
538 // Ensure key length is exaclty 16 bytes
539 keylen
= strlen(key
);
541 mbedtls_md5(key
, keylen
, hash
);
542 memcpy(ipad
, hash
, 16);
543 memcpy(opad
, hash
, 16);
547 memcpy(ipad
, key
, keylen
);
548 memcpy(opad
, key
, keylen
);
550 for (pos
= keylen
; pos
< 64; pos
++) {
555 for (pos
= 0; pos
< 64; pos
++) {
560 mbedtls_md5_init(& mdContext
);
561 mbedtls_md5_starts(& mdContext
);
562 mbedtls_md5_update(& mdContext
, ipad
, 64);
563 mbedtls_md5_update(& mdContext
, inString
, strlen(inString
));
564 mbedtls_md5_finish(& mdContext
, hash
);
565 mbedtls_md5_free(& mdContext
);
567 mbedtls_md5_init(& mdContext
);
568 mbedtls_md5_starts(& mdContext
);
569 mbedtls_md5_update(& mdContext
, opad
, 64);
570 mbedtls_md5_update(& mdContext
, hash
, 16);
571 mbedtls_md5_finish(& mdContext
, hash
);
572 mbedtls_md5_free(& mdContext
);
578 static void MDTestHmac ()
580 unsigned char output
[16];
581 mbedtls_md5("Hello", 5, output
);
582 MDPrintDebug(output
);
585 MDHmac ("key", "The quick brown fox jumps over the lazy dog");
588 void main (argc
, argv
)
594 /* For each command line argument in turn:
595 ** filename -- prints message digest and name of file
596 ** -sstring -- prints message digest and contents of string
597 ** -t -- prints time trial statistics for 1M characters
598 ** -x -- execute a standard suite of test data
599 ** (no args) -- writes messages digest of stdin onto stdout
604 for (i
= 1; i
< argc
; i
++)
605 if (argv
[i
][0] == '-' && argv
[i
][1] == 's')
606 MDString (argv
[i
] + 2);
607 else if (strcmp (argv
[i
], "-t") == 0)
609 else if (strcmp (argv
[i
], "-x") == 0)
611 else if (strcmp (argv
[i
], "-h") == 0)
613 else MDFile (argv
[i
]);
617 **********************************************************************
618 ** End of md5driver.c **
619 ******************************* (cut) ********************************