xref: /titanic_50/usr/src/lib/libsum/common/sum-md5.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
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 
55 typedef uint32_t UINT4;
56 
57 typedef 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 
68 static 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 
85 static void
md5_encode(register unsigned char * output,register UINT4 * input,unsigned int len)86 md5_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 
105 static void
md5_decode(register UINT4 * output,register unsigned char * input,unsigned int len)106 md5_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 
118 static int
md5_init(Sum_t * p)119 md5_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 
131 static Sum_t*
md5_open(const Method_t * method,const char * name)132 md5_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 
198 static void
md5_transform(UINT4 state[4],unsigned char block[64])199 md5_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 
287 static int
md5_block(Sum_t * p,const void * s,size_t inputLen)288 md5_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 
323 static int
md5_done(Sum_t * p)324 md5_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 
352 static int
md5_print(Sum_t * p,Sfio_t * sp,register int flags,size_t scale)353 md5_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 
365 static int
md5_data(Sum_t * p,Sumdata_t * data)366 md5_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