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