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