xref: /titanic_51/usr/src/lib/libsum/common/sum-md5.c (revision 7c2fbfb345896881c631598ee3852ce9ce33fb07)
1*7c2fbfb3SApril Chin /***********************************************************************
2*7c2fbfb3SApril Chin *                                                                      *
3*7c2fbfb3SApril Chin *               This software is part of the ast package               *
4*7c2fbfb3SApril Chin *          Copyright (c) 1996-2008 AT&T Intellectual Property          *
5*7c2fbfb3SApril Chin *                      and is licensed under the                       *
6*7c2fbfb3SApril Chin *                  Common Public License, Version 1.0                  *
7*7c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8*7c2fbfb3SApril Chin *                                                                      *
9*7c2fbfb3SApril Chin *                A copy of the License is available at                 *
10*7c2fbfb3SApril Chin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*7c2fbfb3SApril Chin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*7c2fbfb3SApril Chin *                                                                      *
13*7c2fbfb3SApril Chin *              Information and Software Systems Research               *
14*7c2fbfb3SApril Chin *                            AT&T Research                             *
15*7c2fbfb3SApril Chin *                           Florham Park NJ                            *
16*7c2fbfb3SApril Chin *                                                                      *
17*7c2fbfb3SApril Chin *                 Glenn Fowler <gsf@research.att.com>                  *
18*7c2fbfb3SApril Chin *                                                                      *
19*7c2fbfb3SApril Chin ***********************************************************************/
20*7c2fbfb3SApril Chin #pragma prototyped
21*7c2fbfb3SApril Chin 
22*7c2fbfb3SApril Chin /*
23*7c2fbfb3SApril Chin  * md5
24*7c2fbfb3SApril Chin  */
25*7c2fbfb3SApril Chin 
26*7c2fbfb3SApril Chin /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
27*7c2fbfb3SApril Chin    rights reserved.
28*7c2fbfb3SApril Chin 
29*7c2fbfb3SApril Chin    License to copy and use this software is granted provided that it
30*7c2fbfb3SApril Chin    is identified as the "RSA Data Security, Inc. MD5 Message-Digest
31*7c2fbfb3SApril Chin    Method" in all material mentioning or referencing this software
32*7c2fbfb3SApril Chin    or this function.
33*7c2fbfb3SApril Chin 
34*7c2fbfb3SApril Chin    License is also granted to make and use derivative works provided
35*7c2fbfb3SApril Chin    that such works are identified as "derived from the RSA Data
36*7c2fbfb3SApril Chin    Security, Inc. MD5 Message-Digest Method" in all material
37*7c2fbfb3SApril Chin    mentioning or referencing the derived work.
38*7c2fbfb3SApril Chin 
39*7c2fbfb3SApril Chin    RSA Data Security, Inc. makes no representations concerning either
40*7c2fbfb3SApril Chin    the merchantability of this software or the suitability of this
41*7c2fbfb3SApril Chin    software for any particular purpose. It is provided "as is"
42*7c2fbfb3SApril Chin    without express or implied warranty of any kind.
43*7c2fbfb3SApril Chin 
44*7c2fbfb3SApril Chin    These notices must be retained in any copies of any part of this
45*7c2fbfb3SApril Chin    documentation and/or software.
46*7c2fbfb3SApril Chin  */
47*7c2fbfb3SApril Chin 
48*7c2fbfb3SApril Chin #define md5_description \
49*7c2fbfb3SApril Chin 	"The RSA Data Security, Inc. MD5 Message-Digest Method, 1991-2, \
50*7c2fbfb3SApril Chin 	used with permission. The block count is not printed."
51*7c2fbfb3SApril Chin #define md5_options	"[+(version)?md5 (RSA Data Security, Inc. MD5 Message-Digest, 1991-2) 1996-02-29]"
52*7c2fbfb3SApril Chin #define md5_match	"md5|MD5"
53*7c2fbfb3SApril Chin #define md5_scale	0
54*7c2fbfb3SApril Chin 
55*7c2fbfb3SApril Chin typedef uint32_t UINT4;
56*7c2fbfb3SApril Chin 
57*7c2fbfb3SApril Chin typedef struct Md5_s
58*7c2fbfb3SApril Chin {
59*7c2fbfb3SApril Chin 	_SUM_PUBLIC_
60*7c2fbfb3SApril Chin 	_SUM_PRIVATE_
61*7c2fbfb3SApril Chin 	UINT4		state[4];	/* state (ABCD)			*/
62*7c2fbfb3SApril Chin 	UINT4		count[2];	/* # bits handled mod 2^64 (lsb)*/
63*7c2fbfb3SApril Chin 	unsigned char	buffer[64];	/* input buffer			*/
64*7c2fbfb3SApril Chin 	unsigned char	digest[16];	/* final digest			*/
65*7c2fbfb3SApril Chin 	unsigned char	digest_sum[16]; /* sum of all digests		*/
66*7c2fbfb3SApril Chin } Md5_t;
67*7c2fbfb3SApril Chin 
68*7c2fbfb3SApril Chin static const unsigned char	md5_pad[] =
69*7c2fbfb3SApril Chin {
70*7c2fbfb3SApril Chin 	0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71*7c2fbfb3SApril Chin 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72*7c2fbfb3SApril Chin 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73*7c2fbfb3SApril Chin 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74*7c2fbfb3SApril Chin 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75*7c2fbfb3SApril Chin 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76*7c2fbfb3SApril Chin 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77*7c2fbfb3SApril Chin 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
78*7c2fbfb3SApril Chin };
79*7c2fbfb3SApril Chin 
80*7c2fbfb3SApril Chin /*
81*7c2fbfb3SApril Chin  * encode input into output
82*7c2fbfb3SApril Chin  * len must be a multiple of 4
83*7c2fbfb3SApril Chin  */
84*7c2fbfb3SApril Chin 
85*7c2fbfb3SApril Chin static void
86*7c2fbfb3SApril Chin md5_encode(register unsigned char* output, register UINT4* input, unsigned int len)
87*7c2fbfb3SApril Chin {
88*7c2fbfb3SApril Chin 	register unsigned int	i;
89*7c2fbfb3SApril Chin 	register unsigned int	j;
90*7c2fbfb3SApril Chin 
91*7c2fbfb3SApril Chin 	for (i = j = 0; j < len; i++, j += 4)
92*7c2fbfb3SApril Chin 	{
93*7c2fbfb3SApril Chin 		output[j] = (unsigned char)(input[i] & 0xff);
94*7c2fbfb3SApril Chin 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
95*7c2fbfb3SApril Chin 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
96*7c2fbfb3SApril Chin 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
97*7c2fbfb3SApril Chin 	}
98*7c2fbfb3SApril Chin }
99*7c2fbfb3SApril Chin 
100*7c2fbfb3SApril Chin /*
101*7c2fbfb3SApril Chin  * decode input into output
102*7c2fbfb3SApril Chin  * len must be a multiple of 4
103*7c2fbfb3SApril Chin  */
104*7c2fbfb3SApril Chin 
105*7c2fbfb3SApril Chin static void
106*7c2fbfb3SApril Chin md5_decode(register UINT4* output, register unsigned char* input, unsigned int len)
107*7c2fbfb3SApril Chin {
108*7c2fbfb3SApril Chin 	unsigned int	i;
109*7c2fbfb3SApril Chin 	unsigned int	j;
110*7c2fbfb3SApril Chin 
111*7c2fbfb3SApril Chin 	for (i = j = 0; j < len; i++, j += 4)
112*7c2fbfb3SApril Chin 		output[i] = ((UINT4)input[j]) |
113*7c2fbfb3SApril Chin 			    (((UINT4)input[j+1]) << 8) |
114*7c2fbfb3SApril Chin 			    (((UINT4)input[j+2]) << 16) |
115*7c2fbfb3SApril Chin 			    (((UINT4)input[j+3]) << 24);
116*7c2fbfb3SApril Chin }
117*7c2fbfb3SApril Chin 
118*7c2fbfb3SApril Chin static int
119*7c2fbfb3SApril Chin md5_init(Sum_t* p)
120*7c2fbfb3SApril Chin {
121*7c2fbfb3SApril Chin 	register Md5_t*	context = (Md5_t*)p;
122*7c2fbfb3SApril Chin 
123*7c2fbfb3SApril Chin 	context->count[0] = context->count[1] = 0;
124*7c2fbfb3SApril Chin 	context->state[0] = 0x67452301;
125*7c2fbfb3SApril Chin 	context->state[1] = 0xefcdab89;
126*7c2fbfb3SApril Chin 	context->state[2] = 0x98badcfe;
127*7c2fbfb3SApril Chin 	context->state[3] = 0x10325476;
128*7c2fbfb3SApril Chin 	return 0;
129*7c2fbfb3SApril Chin }
130*7c2fbfb3SApril Chin 
131*7c2fbfb3SApril Chin static Sum_t*
132*7c2fbfb3SApril Chin md5_open(const Method_t* method, const char* name)
133*7c2fbfb3SApril Chin {
134*7c2fbfb3SApril Chin 	Md5_t*	p;
135*7c2fbfb3SApril Chin 
136*7c2fbfb3SApril Chin 	if (p = newof(0, Md5_t, 1, 0))
137*7c2fbfb3SApril Chin 	{
138*7c2fbfb3SApril Chin 		p->method = (Method_t*)method;
139*7c2fbfb3SApril Chin 		p->name = name;
140*7c2fbfb3SApril Chin 		md5_init((Sum_t*)p);
141*7c2fbfb3SApril Chin 	}
142*7c2fbfb3SApril Chin 	return (Sum_t*)p;
143*7c2fbfb3SApril Chin }
144*7c2fbfb3SApril Chin 
145*7c2fbfb3SApril Chin /*
146*7c2fbfb3SApril Chin  * basic MD5 step -- transforms buf based on in
147*7c2fbfb3SApril Chin  */
148*7c2fbfb3SApril Chin 
149*7c2fbfb3SApril Chin #define S11 7
150*7c2fbfb3SApril Chin #define S12 12
151*7c2fbfb3SApril Chin #define S13 17
152*7c2fbfb3SApril Chin #define S14 22
153*7c2fbfb3SApril Chin #define S21 5
154*7c2fbfb3SApril Chin #define S22 9
155*7c2fbfb3SApril Chin #define S23 14
156*7c2fbfb3SApril Chin #define S24 20
157*7c2fbfb3SApril Chin #define S31 4
158*7c2fbfb3SApril Chin #define S32 11
159*7c2fbfb3SApril Chin #define S33 16
160*7c2fbfb3SApril Chin #define S34 23
161*7c2fbfb3SApril Chin #define S41 6
162*7c2fbfb3SApril Chin #define S42 10
163*7c2fbfb3SApril Chin #define S43 15
164*7c2fbfb3SApril Chin #define S44 21
165*7c2fbfb3SApril Chin 
166*7c2fbfb3SApril Chin /* F, G, H and I are basic MD5 functions */
167*7c2fbfb3SApril Chin #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
168*7c2fbfb3SApril Chin #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
169*7c2fbfb3SApril Chin #define H(x, y, z) ((x) ^ (y) ^ (z))
170*7c2fbfb3SApril Chin #define I(x, y, z) ((y) ^ ((x) | (~z)))
171*7c2fbfb3SApril Chin 
172*7c2fbfb3SApril Chin /* ROTATE_LEFT rotates x left n bits */
173*7c2fbfb3SApril Chin #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
174*7c2fbfb3SApril Chin 
175*7c2fbfb3SApril Chin /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
176*7c2fbfb3SApril Chin /* Rotation is separate from addition to prevent recomputation */
177*7c2fbfb3SApril Chin #define FF(a, b, c, d, x, s, ac) { \
178*7c2fbfb3SApril Chin     (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
179*7c2fbfb3SApril Chin     (a) = ROTATE_LEFT ((a), (s)); \
180*7c2fbfb3SApril Chin     (a) += (b); \
181*7c2fbfb3SApril Chin   }
182*7c2fbfb3SApril Chin #define GG(a, b, c, d, x, s, ac) { \
183*7c2fbfb3SApril Chin     (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
184*7c2fbfb3SApril Chin     (a) = ROTATE_LEFT ((a), (s)); \
185*7c2fbfb3SApril Chin     (a) += (b); \
186*7c2fbfb3SApril Chin   }
187*7c2fbfb3SApril Chin #define HH(a, b, c, d, x, s, ac) { \
188*7c2fbfb3SApril Chin     (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
189*7c2fbfb3SApril Chin     (a) = ROTATE_LEFT ((a), (s)); \
190*7c2fbfb3SApril Chin     (a) += (b); \
191*7c2fbfb3SApril Chin   }
192*7c2fbfb3SApril Chin #define II(a, b, c, d, x, s, ac) { \
193*7c2fbfb3SApril Chin     (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
194*7c2fbfb3SApril Chin     (a) = ROTATE_LEFT ((a), (s)); \
195*7c2fbfb3SApril Chin     (a) += (b); \
196*7c2fbfb3SApril Chin   }
197*7c2fbfb3SApril Chin 
198*7c2fbfb3SApril Chin static void
199*7c2fbfb3SApril Chin md5_transform(UINT4 state[4], unsigned char block[64])
200*7c2fbfb3SApril Chin {
201*7c2fbfb3SApril Chin 	UINT4	a = state[0];
202*7c2fbfb3SApril Chin 	UINT4	b = state[1];
203*7c2fbfb3SApril Chin 	UINT4	c = state[2];
204*7c2fbfb3SApril Chin 	UINT4	d = state[3];
205*7c2fbfb3SApril Chin 	UINT4	x[16];
206*7c2fbfb3SApril Chin 
207*7c2fbfb3SApril Chin 	md5_decode(x, block, 64);
208*7c2fbfb3SApril Chin 
209*7c2fbfb3SApril Chin 	/* round 1 */
210*7c2fbfb3SApril Chin 	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
211*7c2fbfb3SApril Chin 	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
212*7c2fbfb3SApril Chin 	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
213*7c2fbfb3SApril Chin 	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
214*7c2fbfb3SApril Chin 	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
215*7c2fbfb3SApril Chin 	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
216*7c2fbfb3SApril Chin 	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
217*7c2fbfb3SApril Chin 	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
218*7c2fbfb3SApril Chin 	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
219*7c2fbfb3SApril Chin 	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
220*7c2fbfb3SApril Chin 	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
221*7c2fbfb3SApril Chin 	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
222*7c2fbfb3SApril Chin 	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
223*7c2fbfb3SApril Chin 	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
224*7c2fbfb3SApril Chin 	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
225*7c2fbfb3SApril Chin 	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
226*7c2fbfb3SApril Chin 
227*7c2fbfb3SApril Chin 	/* round 2 */
228*7c2fbfb3SApril Chin 	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
229*7c2fbfb3SApril Chin 	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
230*7c2fbfb3SApril Chin 	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
231*7c2fbfb3SApril Chin 	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
232*7c2fbfb3SApril Chin 	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
233*7c2fbfb3SApril Chin 	GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
234*7c2fbfb3SApril Chin 	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
235*7c2fbfb3SApril Chin 	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
236*7c2fbfb3SApril Chin 	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
237*7c2fbfb3SApril Chin 	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
238*7c2fbfb3SApril Chin 	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
239*7c2fbfb3SApril Chin 	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
240*7c2fbfb3SApril Chin 	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
241*7c2fbfb3SApril Chin 	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
242*7c2fbfb3SApril Chin 	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
243*7c2fbfb3SApril Chin 	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
244*7c2fbfb3SApril Chin 
245*7c2fbfb3SApril Chin 	/* round 3 */
246*7c2fbfb3SApril Chin 	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
247*7c2fbfb3SApril Chin 	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
248*7c2fbfb3SApril Chin 	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
249*7c2fbfb3SApril Chin 	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
250*7c2fbfb3SApril Chin 	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
251*7c2fbfb3SApril Chin 	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
252*7c2fbfb3SApril Chin 	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
253*7c2fbfb3SApril Chin 	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
254*7c2fbfb3SApril Chin 	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
255*7c2fbfb3SApril Chin 	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
256*7c2fbfb3SApril Chin 	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
257*7c2fbfb3SApril Chin 	HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
258*7c2fbfb3SApril Chin 	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
259*7c2fbfb3SApril Chin 	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
260*7c2fbfb3SApril Chin 	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
261*7c2fbfb3SApril Chin 	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
262*7c2fbfb3SApril Chin 
263*7c2fbfb3SApril Chin 	/* round 4 */
264*7c2fbfb3SApril Chin 	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
265*7c2fbfb3SApril Chin 	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
266*7c2fbfb3SApril Chin 	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
267*7c2fbfb3SApril Chin 	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
268*7c2fbfb3SApril Chin 	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
269*7c2fbfb3SApril Chin 	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
270*7c2fbfb3SApril Chin 	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
271*7c2fbfb3SApril Chin 	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
272*7c2fbfb3SApril Chin 	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
273*7c2fbfb3SApril Chin 	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
274*7c2fbfb3SApril Chin 	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
275*7c2fbfb3SApril Chin 	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
276*7c2fbfb3SApril Chin 	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
277*7c2fbfb3SApril Chin 	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
278*7c2fbfb3SApril Chin 	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
279*7c2fbfb3SApril Chin 	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
280*7c2fbfb3SApril Chin 
281*7c2fbfb3SApril Chin 	state[0] += a;
282*7c2fbfb3SApril Chin 	state[1] += b;
283*7c2fbfb3SApril Chin 	state[2] += c;
284*7c2fbfb3SApril Chin 	state[3] += d;
285*7c2fbfb3SApril Chin }
286*7c2fbfb3SApril Chin 
287*7c2fbfb3SApril Chin static int
288*7c2fbfb3SApril Chin md5_block(Sum_t* p, const void* s, size_t inputLen)
289*7c2fbfb3SApril Chin {
290*7c2fbfb3SApril Chin 	register Md5_t*	context = (Md5_t*)p;
291*7c2fbfb3SApril Chin 	unsigned char*	input = (unsigned char*)s;
292*7c2fbfb3SApril Chin 	unsigned int	i;
293*7c2fbfb3SApril Chin 	unsigned int	index;
294*7c2fbfb3SApril Chin 	unsigned int	partLen;
295*7c2fbfb3SApril Chin 
296*7c2fbfb3SApril Chin 	/* compute number of bytes mod 64 */
297*7c2fbfb3SApril Chin 	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
298*7c2fbfb3SApril Chin 
299*7c2fbfb3SApril Chin 	/* update number of bits */
300*7c2fbfb3SApril Chin 	if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
301*7c2fbfb3SApril Chin 		context->count[1]++;
302*7c2fbfb3SApril Chin 	context->count[1] += ((UINT4)inputLen >> 29);
303*7c2fbfb3SApril Chin 	partLen = 64 - index;
304*7c2fbfb3SApril Chin 
305*7c2fbfb3SApril Chin 	/* transform as many times as possible */
306*7c2fbfb3SApril Chin 	if (inputLen >= partLen)
307*7c2fbfb3SApril Chin 	{
308*7c2fbfb3SApril Chin 		memcpy(&context->buffer[index], input, partLen);
309*7c2fbfb3SApril Chin 		md5_transform(context->state, context->buffer);
310*7c2fbfb3SApril Chin 		for (i = partLen; i + 63 < inputLen; i += 64)
311*7c2fbfb3SApril Chin 			md5_transform(context->state, &input[i]);
312*7c2fbfb3SApril Chin 		index = 0;
313*7c2fbfb3SApril Chin 	}
314*7c2fbfb3SApril Chin 	else
315*7c2fbfb3SApril Chin 		i = 0;
316*7c2fbfb3SApril Chin 
317*7c2fbfb3SApril Chin 	/* buffer remaining input */
318*7c2fbfb3SApril Chin 	memcpy(&context->buffer[index], &input[i], inputLen - i);
319*7c2fbfb3SApril Chin 
320*7c2fbfb3SApril Chin 	return 0;
321*7c2fbfb3SApril Chin }
322*7c2fbfb3SApril Chin 
323*7c2fbfb3SApril Chin static int
324*7c2fbfb3SApril Chin md5_done(Sum_t* p)
325*7c2fbfb3SApril Chin {
326*7c2fbfb3SApril Chin 	register Md5_t*	context = (Md5_t*)p;
327*7c2fbfb3SApril Chin 	unsigned char	bits[8];
328*7c2fbfb3SApril Chin 	unsigned int	index;
329*7c2fbfb3SApril Chin 	unsigned int	padLen;
330*7c2fbfb3SApril Chin 
331*7c2fbfb3SApril Chin 	/* save number of bits */
332*7c2fbfb3SApril Chin 	md5_encode(bits, context->count, sizeof(bits));
333*7c2fbfb3SApril Chin 
334*7c2fbfb3SApril Chin 	/* pad out to 56 mod 64 */
335*7c2fbfb3SApril Chin 	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
336*7c2fbfb3SApril Chin 	padLen = (index < 56) ? (56 - index) : (120 - index);
337*7c2fbfb3SApril Chin 	md5_block(p, md5_pad, padLen);
338*7c2fbfb3SApril Chin 
339*7c2fbfb3SApril Chin 	/* append length (before padding) */
340*7c2fbfb3SApril Chin 	md5_block(p, bits, sizeof(bits));
341*7c2fbfb3SApril Chin 
342*7c2fbfb3SApril Chin 	/* store state in digest */
343*7c2fbfb3SApril Chin 	md5_encode(context->digest, context->state, sizeof(context->digest));
344*7c2fbfb3SApril Chin 
345*7c2fbfb3SApril Chin 	/* accumulate the digests */
346*7c2fbfb3SApril Chin 	for (index = 0; index < elementsof(context->digest); index++)
347*7c2fbfb3SApril Chin 		context->digest_sum[index] ^= context->digest[index];
348*7c2fbfb3SApril Chin 
349*7c2fbfb3SApril Chin 	return 0;
350*7c2fbfb3SApril Chin }
351*7c2fbfb3SApril Chin 
352*7c2fbfb3SApril Chin static int
353*7c2fbfb3SApril Chin md5_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
354*7c2fbfb3SApril Chin {
355*7c2fbfb3SApril Chin 	register Md5_t*		x = (Md5_t*)p;
356*7c2fbfb3SApril Chin 	register unsigned char*	d;
357*7c2fbfb3SApril Chin 	register int		n;
358*7c2fbfb3SApril Chin 
359*7c2fbfb3SApril Chin 	d = (flags & SUM_TOTAL) ? x->digest_sum : x->digest;
360*7c2fbfb3SApril Chin 	for (n = 0; n < elementsof(x->digest); n++)
361*7c2fbfb3SApril Chin 		sfprintf(sp, "%02x", d[n]);
362*7c2fbfb3SApril Chin 	return 0;
363*7c2fbfb3SApril Chin }
364*7c2fbfb3SApril Chin 
365*7c2fbfb3SApril Chin static int
366*7c2fbfb3SApril Chin md5_data(Sum_t* p, Sumdata_t* data)
367*7c2fbfb3SApril Chin {
368*7c2fbfb3SApril Chin 	register Md5_t*		x = (Md5_t*)p;
369*7c2fbfb3SApril Chin 
370*7c2fbfb3SApril Chin 	data->size = elementsof(x->digest);
371*7c2fbfb3SApril Chin 	data->num = 0;
372*7c2fbfb3SApril Chin 	data->buf = x->digest;
373*7c2fbfb3SApril Chin 	return 0;
374*7c2fbfb3SApril Chin }
375