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