17c2fbfb3SApril Chin /***********************************************************************
27c2fbfb3SApril Chin * *
37c2fbfb3SApril Chin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1996-2010 AT&T Intellectual Property *
57c2fbfb3SApril Chin * and is licensed under the *
67c2fbfb3SApril Chin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
87c2fbfb3SApril Chin * *
97c2fbfb3SApril Chin * A copy of the License is available at *
107c2fbfb3SApril Chin * http://www.opensource.org/licenses/cpl1.0.txt *
117c2fbfb3SApril Chin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
127c2fbfb3SApril Chin * *
137c2fbfb3SApril Chin * Information and Software Systems Research *
147c2fbfb3SApril Chin * AT&T Research *
157c2fbfb3SApril Chin * Florham Park NJ *
167c2fbfb3SApril Chin * *
177c2fbfb3SApril Chin * Glenn Fowler <gsf@research.att.com> *
187c2fbfb3SApril Chin * *
197c2fbfb3SApril Chin ***********************************************************************/
207c2fbfb3SApril Chin #pragma prototyped
217c2fbfb3SApril Chin
227c2fbfb3SApril Chin /*
237c2fbfb3SApril Chin * md5
247c2fbfb3SApril Chin */
257c2fbfb3SApril Chin
267c2fbfb3SApril Chin /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
277c2fbfb3SApril Chin rights reserved.
287c2fbfb3SApril Chin
297c2fbfb3SApril Chin License to copy and use this software is granted provided that it
307c2fbfb3SApril Chin is identified as the "RSA Data Security, Inc. MD5 Message-Digest
317c2fbfb3SApril Chin Method" in all material mentioning or referencing this software
327c2fbfb3SApril Chin or this function.
337c2fbfb3SApril Chin
347c2fbfb3SApril Chin License is also granted to make and use derivative works provided
357c2fbfb3SApril Chin that such works are identified as "derived from the RSA Data
367c2fbfb3SApril Chin Security, Inc. MD5 Message-Digest Method" in all material
377c2fbfb3SApril Chin mentioning or referencing the derived work.
387c2fbfb3SApril Chin
397c2fbfb3SApril Chin RSA Data Security, Inc. makes no representations concerning either
407c2fbfb3SApril Chin the merchantability of this software or the suitability of this
417c2fbfb3SApril Chin software for any particular purpose. It is provided "as is"
427c2fbfb3SApril Chin without express or implied warranty of any kind.
437c2fbfb3SApril Chin
447c2fbfb3SApril Chin These notices must be retained in any copies of any part of this
457c2fbfb3SApril Chin documentation and/or software.
467c2fbfb3SApril Chin */
477c2fbfb3SApril Chin
487c2fbfb3SApril Chin #define md5_description \
497c2fbfb3SApril Chin "The RSA Data Security, Inc. MD5 Message-Digest Method, 1991-2, \
507c2fbfb3SApril Chin used with permission. The block count is not printed."
517c2fbfb3SApril Chin #define md5_options "[+(version)?md5 (RSA Data Security, Inc. MD5 Message-Digest, 1991-2) 1996-02-29]"
527c2fbfb3SApril Chin #define md5_match "md5|MD5"
537c2fbfb3SApril Chin #define md5_scale 0
547c2fbfb3SApril Chin
557c2fbfb3SApril Chin typedef uint32_t UINT4;
567c2fbfb3SApril Chin
577c2fbfb3SApril Chin typedef struct Md5_s
587c2fbfb3SApril Chin {
597c2fbfb3SApril Chin _SUM_PUBLIC_
607c2fbfb3SApril Chin _SUM_PRIVATE_
617c2fbfb3SApril Chin UINT4 state[4]; /* state (ABCD) */
627c2fbfb3SApril Chin UINT4 count[2]; /* # bits handled mod 2^64 (lsb)*/
637c2fbfb3SApril Chin unsigned char buffer[64]; /* input buffer */
647c2fbfb3SApril Chin unsigned char digest[16]; /* final digest */
657c2fbfb3SApril Chin unsigned char digest_sum[16]; /* sum of all digests */
667c2fbfb3SApril Chin } Md5_t;
677c2fbfb3SApril Chin
687c2fbfb3SApril Chin static const unsigned char md5_pad[] =
697c2fbfb3SApril Chin {
707c2fbfb3SApril Chin 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717c2fbfb3SApril Chin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727c2fbfb3SApril Chin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737c2fbfb3SApril Chin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747c2fbfb3SApril Chin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757c2fbfb3SApril Chin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767c2fbfb3SApril Chin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777c2fbfb3SApril Chin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
787c2fbfb3SApril Chin };
797c2fbfb3SApril Chin
807c2fbfb3SApril Chin /*
817c2fbfb3SApril Chin * encode input into output
827c2fbfb3SApril Chin * len must be a multiple of 4
837c2fbfb3SApril Chin */
847c2fbfb3SApril Chin
857c2fbfb3SApril Chin static void
md5_encode(register unsigned char * output,register UINT4 * input,unsigned int len)867c2fbfb3SApril Chin md5_encode(register unsigned char* output, register UINT4* input, unsigned int len)
877c2fbfb3SApril Chin {
887c2fbfb3SApril Chin register unsigned int i;
897c2fbfb3SApril Chin register unsigned int j;
907c2fbfb3SApril Chin
917c2fbfb3SApril Chin for (i = j = 0; j < len; i++, j += 4)
927c2fbfb3SApril Chin {
937c2fbfb3SApril Chin output[j] = (unsigned char)(input[i] & 0xff);
947c2fbfb3SApril Chin output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
957c2fbfb3SApril Chin output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
967c2fbfb3SApril Chin output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
977c2fbfb3SApril Chin }
987c2fbfb3SApril Chin }
997c2fbfb3SApril Chin
1007c2fbfb3SApril Chin /*
1017c2fbfb3SApril Chin * decode input into output
1027c2fbfb3SApril Chin * len must be a multiple of 4
1037c2fbfb3SApril Chin */
1047c2fbfb3SApril Chin
1057c2fbfb3SApril Chin static void
md5_decode(register UINT4 * output,register unsigned char * input,unsigned int len)1067c2fbfb3SApril Chin md5_decode(register UINT4* output, register unsigned char* input, unsigned int len)
1077c2fbfb3SApril Chin {
1087c2fbfb3SApril Chin unsigned int i;
1097c2fbfb3SApril Chin unsigned int j;
1107c2fbfb3SApril Chin
1117c2fbfb3SApril Chin for (i = j = 0; j < len; i++, j += 4)
1127c2fbfb3SApril Chin output[i] = ((UINT4)input[j]) |
1137c2fbfb3SApril Chin (((UINT4)input[j+1]) << 8) |
1147c2fbfb3SApril Chin (((UINT4)input[j+2]) << 16) |
1157c2fbfb3SApril Chin (((UINT4)input[j+3]) << 24);
1167c2fbfb3SApril Chin }
1177c2fbfb3SApril Chin
1187c2fbfb3SApril Chin static int
md5_init(Sum_t * p)1197c2fbfb3SApril Chin md5_init(Sum_t* p)
1207c2fbfb3SApril Chin {
1217c2fbfb3SApril Chin register Md5_t* context = (Md5_t*)p;
1227c2fbfb3SApril Chin
1237c2fbfb3SApril Chin context->count[0] = context->count[1] = 0;
1247c2fbfb3SApril Chin context->state[0] = 0x67452301;
1257c2fbfb3SApril Chin context->state[1] = 0xefcdab89;
1267c2fbfb3SApril Chin context->state[2] = 0x98badcfe;
1277c2fbfb3SApril Chin context->state[3] = 0x10325476;
1287c2fbfb3SApril Chin return 0;
1297c2fbfb3SApril Chin }
1307c2fbfb3SApril Chin
1317c2fbfb3SApril Chin static Sum_t*
md5_open(const Method_t * method,const char * name)1327c2fbfb3SApril Chin md5_open(const Method_t* method, const char* name)
1337c2fbfb3SApril Chin {
1347c2fbfb3SApril Chin Md5_t* p;
1357c2fbfb3SApril Chin
1367c2fbfb3SApril Chin if (p = newof(0, Md5_t, 1, 0))
1377c2fbfb3SApril Chin {
1387c2fbfb3SApril Chin p->method = (Method_t*)method;
1397c2fbfb3SApril Chin p->name = name;
1407c2fbfb3SApril Chin md5_init((Sum_t*)p);
1417c2fbfb3SApril Chin }
1427c2fbfb3SApril Chin return (Sum_t*)p;
1437c2fbfb3SApril Chin }
1447c2fbfb3SApril Chin
1457c2fbfb3SApril Chin /*
1467c2fbfb3SApril Chin * basic MD5 step -- transforms buf based on in
1477c2fbfb3SApril Chin */
1487c2fbfb3SApril Chin
1497c2fbfb3SApril Chin #define S11 7
1507c2fbfb3SApril Chin #define S12 12
1517c2fbfb3SApril Chin #define S13 17
1527c2fbfb3SApril Chin #define S14 22
1537c2fbfb3SApril Chin #define S21 5
1547c2fbfb3SApril Chin #define S22 9
1557c2fbfb3SApril Chin #define S23 14
1567c2fbfb3SApril Chin #define S24 20
1577c2fbfb3SApril Chin #define S31 4
1587c2fbfb3SApril Chin #define S32 11
1597c2fbfb3SApril Chin #define S33 16
1607c2fbfb3SApril Chin #define S34 23
1617c2fbfb3SApril Chin #define S41 6
1627c2fbfb3SApril Chin #define S42 10
1637c2fbfb3SApril Chin #define S43 15
1647c2fbfb3SApril Chin #define S44 21
1657c2fbfb3SApril Chin
1667c2fbfb3SApril Chin /* F, G, H and I are basic MD5 functions */
1677c2fbfb3SApril Chin #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
1687c2fbfb3SApril Chin #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
1697c2fbfb3SApril Chin #define H(x, y, z) ((x) ^ (y) ^ (z))
1707c2fbfb3SApril Chin #define I(x, y, z) ((y) ^ ((x) | (~z)))
1717c2fbfb3SApril Chin
1727c2fbfb3SApril Chin /* ROTATE_LEFT rotates x left n bits */
1737c2fbfb3SApril Chin #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
1747c2fbfb3SApril Chin
1757c2fbfb3SApril Chin /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
1767c2fbfb3SApril Chin /* Rotation is separate from addition to prevent recomputation */
1777c2fbfb3SApril Chin #define FF(a, b, c, d, x, s, ac) { \
1787c2fbfb3SApril Chin (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
1797c2fbfb3SApril Chin (a) = ROTATE_LEFT ((a), (s)); \
1807c2fbfb3SApril Chin (a) += (b); \
1817c2fbfb3SApril Chin }
1827c2fbfb3SApril Chin #define GG(a, b, c, d, x, s, ac) { \
1837c2fbfb3SApril Chin (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
1847c2fbfb3SApril Chin (a) = ROTATE_LEFT ((a), (s)); \
1857c2fbfb3SApril Chin (a) += (b); \
1867c2fbfb3SApril Chin }
1877c2fbfb3SApril Chin #define HH(a, b, c, d, x, s, ac) { \
1887c2fbfb3SApril Chin (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
1897c2fbfb3SApril Chin (a) = ROTATE_LEFT ((a), (s)); \
1907c2fbfb3SApril Chin (a) += (b); \
1917c2fbfb3SApril Chin }
1927c2fbfb3SApril Chin #define II(a, b, c, d, x, s, ac) { \
1937c2fbfb3SApril Chin (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
1947c2fbfb3SApril Chin (a) = ROTATE_LEFT ((a), (s)); \
1957c2fbfb3SApril Chin (a) += (b); \
1967c2fbfb3SApril Chin }
1977c2fbfb3SApril Chin
1987c2fbfb3SApril Chin static void
md5_transform(UINT4 state[4],unsigned char block[64])1997c2fbfb3SApril Chin md5_transform(UINT4 state[4], unsigned char block[64])
2007c2fbfb3SApril Chin {
2017c2fbfb3SApril Chin UINT4 a = state[0];
2027c2fbfb3SApril Chin UINT4 b = state[1];
2037c2fbfb3SApril Chin UINT4 c = state[2];
2047c2fbfb3SApril Chin UINT4 d = state[3];
2057c2fbfb3SApril Chin UINT4 x[16];
2067c2fbfb3SApril Chin
2077c2fbfb3SApril Chin md5_decode(x, block, 64);
2087c2fbfb3SApril Chin
2097c2fbfb3SApril Chin /* round 1 */
2107c2fbfb3SApril Chin FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
2117c2fbfb3SApril Chin FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
2127c2fbfb3SApril Chin FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
2137c2fbfb3SApril Chin FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
2147c2fbfb3SApril Chin FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
2157c2fbfb3SApril Chin FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
2167c2fbfb3SApril Chin FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
2177c2fbfb3SApril Chin FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
2187c2fbfb3SApril Chin FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
2197c2fbfb3SApril Chin FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
2207c2fbfb3SApril Chin FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
2217c2fbfb3SApril Chin FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
2227c2fbfb3SApril Chin FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
2237c2fbfb3SApril Chin FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
2247c2fbfb3SApril Chin FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
2257c2fbfb3SApril Chin FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
2267c2fbfb3SApril Chin
2277c2fbfb3SApril Chin /* round 2 */
2287c2fbfb3SApril Chin GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
2297c2fbfb3SApril Chin GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
2307c2fbfb3SApril Chin GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
2317c2fbfb3SApril Chin GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
2327c2fbfb3SApril Chin GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
2337c2fbfb3SApril Chin GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
2347c2fbfb3SApril Chin GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
2357c2fbfb3SApril Chin GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
2367c2fbfb3SApril Chin GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
2377c2fbfb3SApril Chin GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
2387c2fbfb3SApril Chin GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
2397c2fbfb3SApril Chin GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
2407c2fbfb3SApril Chin GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
2417c2fbfb3SApril Chin GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
2427c2fbfb3SApril Chin GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
2437c2fbfb3SApril Chin GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
2447c2fbfb3SApril Chin
2457c2fbfb3SApril Chin /* round 3 */
2467c2fbfb3SApril Chin HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
2477c2fbfb3SApril Chin HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
2487c2fbfb3SApril Chin HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
2497c2fbfb3SApril Chin HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
2507c2fbfb3SApril Chin HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
2517c2fbfb3SApril Chin HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
2527c2fbfb3SApril Chin HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
2537c2fbfb3SApril Chin HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
2547c2fbfb3SApril Chin HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
2557c2fbfb3SApril Chin HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
2567c2fbfb3SApril Chin HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
2577c2fbfb3SApril Chin HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
2587c2fbfb3SApril Chin HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
2597c2fbfb3SApril Chin HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
2607c2fbfb3SApril Chin HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
2617c2fbfb3SApril Chin HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
2627c2fbfb3SApril Chin
2637c2fbfb3SApril Chin /* round 4 */
2647c2fbfb3SApril Chin II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
2657c2fbfb3SApril Chin II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
2667c2fbfb3SApril Chin II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
2677c2fbfb3SApril Chin II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
2687c2fbfb3SApril Chin II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
2697c2fbfb3SApril Chin II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
2707c2fbfb3SApril Chin II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
2717c2fbfb3SApril Chin II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
2727c2fbfb3SApril Chin II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
2737c2fbfb3SApril Chin II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
2747c2fbfb3SApril Chin II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
2757c2fbfb3SApril Chin II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
2767c2fbfb3SApril Chin II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
2777c2fbfb3SApril Chin II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
2787c2fbfb3SApril Chin II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
2797c2fbfb3SApril Chin II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
2807c2fbfb3SApril Chin
2817c2fbfb3SApril Chin state[0] += a;
2827c2fbfb3SApril Chin state[1] += b;
2837c2fbfb3SApril Chin state[2] += c;
2847c2fbfb3SApril Chin state[3] += d;
2857c2fbfb3SApril Chin }
2867c2fbfb3SApril Chin
2877c2fbfb3SApril Chin static int
md5_block(Sum_t * p,const void * s,size_t inputLen)2887c2fbfb3SApril Chin md5_block(Sum_t* p, const void* s, size_t inputLen)
2897c2fbfb3SApril Chin {
2907c2fbfb3SApril Chin register Md5_t* context = (Md5_t*)p;
2917c2fbfb3SApril Chin unsigned char* input = (unsigned char*)s;
2927c2fbfb3SApril Chin unsigned int i;
2937c2fbfb3SApril Chin unsigned int index;
2947c2fbfb3SApril Chin unsigned int partLen;
2957c2fbfb3SApril Chin
2967c2fbfb3SApril Chin /* compute number of bytes mod 64 */
2977c2fbfb3SApril Chin index = (unsigned int)((context->count[0] >> 3) & 0x3f);
2987c2fbfb3SApril Chin
2997c2fbfb3SApril Chin /* update number of bits */
3007c2fbfb3SApril Chin if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
3017c2fbfb3SApril Chin context->count[1]++;
3027c2fbfb3SApril Chin context->count[1] += ((UINT4)inputLen >> 29);
3037c2fbfb3SApril Chin partLen = 64 - index;
3047c2fbfb3SApril Chin
3057c2fbfb3SApril Chin /* transform as many times as possible */
3067c2fbfb3SApril Chin if (inputLen >= partLen)
3077c2fbfb3SApril Chin {
3087c2fbfb3SApril Chin memcpy(&context->buffer[index], input, partLen);
3097c2fbfb3SApril Chin md5_transform(context->state, context->buffer);
3107c2fbfb3SApril Chin for (i = partLen; i + 63 < inputLen; i += 64)
3117c2fbfb3SApril Chin md5_transform(context->state, &input[i]);
3127c2fbfb3SApril Chin index = 0;
3137c2fbfb3SApril Chin }
3147c2fbfb3SApril Chin else
3157c2fbfb3SApril Chin i = 0;
3167c2fbfb3SApril Chin
3177c2fbfb3SApril Chin /* buffer remaining input */
3187c2fbfb3SApril Chin memcpy(&context->buffer[index], &input[i], inputLen - i);
3197c2fbfb3SApril Chin
3207c2fbfb3SApril Chin return 0;
3217c2fbfb3SApril Chin }
3227c2fbfb3SApril Chin
3237c2fbfb3SApril Chin static int
md5_done(Sum_t * p)3247c2fbfb3SApril Chin md5_done(Sum_t* p)
3257c2fbfb3SApril Chin {
3267c2fbfb3SApril Chin register Md5_t* context = (Md5_t*)p;
3277c2fbfb3SApril Chin unsigned char bits[8];
3287c2fbfb3SApril Chin unsigned int index;
3297c2fbfb3SApril Chin unsigned int padLen;
3307c2fbfb3SApril Chin
3317c2fbfb3SApril Chin /* save number of bits */
3327c2fbfb3SApril Chin md5_encode(bits, context->count, sizeof(bits));
3337c2fbfb3SApril Chin
3347c2fbfb3SApril Chin /* pad out to 56 mod 64 */
3357c2fbfb3SApril Chin index = (unsigned int)((context->count[0] >> 3) & 0x3f);
3367c2fbfb3SApril Chin padLen = (index < 56) ? (56 - index) : (120 - index);
3377c2fbfb3SApril Chin md5_block(p, md5_pad, padLen);
3387c2fbfb3SApril Chin
3397c2fbfb3SApril Chin /* append length (before padding) */
3407c2fbfb3SApril Chin md5_block(p, bits, sizeof(bits));
3417c2fbfb3SApril Chin
3427c2fbfb3SApril Chin /* store state in digest */
3437c2fbfb3SApril Chin md5_encode(context->digest, context->state, sizeof(context->digest));
3447c2fbfb3SApril Chin
3457c2fbfb3SApril Chin /* accumulate the digests */
3467c2fbfb3SApril Chin for (index = 0; index < elementsof(context->digest); index++)
3477c2fbfb3SApril Chin context->digest_sum[index] ^= context->digest[index];
3487c2fbfb3SApril Chin
3497c2fbfb3SApril Chin return 0;
3507c2fbfb3SApril Chin }
3517c2fbfb3SApril Chin
3527c2fbfb3SApril Chin static int
md5_print(Sum_t * p,Sfio_t * sp,register int flags,size_t scale)3537c2fbfb3SApril Chin md5_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
3547c2fbfb3SApril Chin {
3557c2fbfb3SApril Chin register Md5_t* x = (Md5_t*)p;
3567c2fbfb3SApril Chin register unsigned char* d;
3577c2fbfb3SApril Chin register int n;
3587c2fbfb3SApril Chin
3597c2fbfb3SApril Chin d = (flags & SUM_TOTAL) ? x->digest_sum : x->digest;
3607c2fbfb3SApril Chin for (n = 0; n < elementsof(x->digest); n++)
3617c2fbfb3SApril Chin sfprintf(sp, "%02x", d[n]);
3627c2fbfb3SApril Chin return 0;
3637c2fbfb3SApril Chin }
3647c2fbfb3SApril Chin
3657c2fbfb3SApril Chin static int
md5_data(Sum_t * p,Sumdata_t * data)3667c2fbfb3SApril Chin md5_data(Sum_t* p, Sumdata_t* data)
3677c2fbfb3SApril Chin {
3687c2fbfb3SApril Chin register Md5_t* x = (Md5_t*)p;
3697c2fbfb3SApril Chin
3707c2fbfb3SApril Chin data->size = elementsof(x->digest);
3717c2fbfb3SApril Chin data->num = 0;
3727c2fbfb3SApril Chin data->buf = x->digest;
3737c2fbfb3SApril Chin return 0;
3747c2fbfb3SApril Chin }
375