xref: /netbsd/common/lib/libc/md/md5c.c (revision 043d89a7)
1 /*	$NetBSD: md5c.c,v 1.5 2012/03/20 16:21:41 matt Exp $	*/
2 
3 /*
4  * This file is derived from the RSA Data Security, Inc. MD5 Message-Digest
5  * Algorithm and has been modified by Jason R. Thorpe <thorpej@NetBSD.org>
6  * for portability and formatting.
7  */
8 
9 /*
10  * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
11  * rights reserved.
12  *
13  * License to copy and use this software is granted provided that it
14  * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
15  * Algorithm" in all material mentioning or referencing this software
16  * or this function.
17  *
18  * License is also granted to make and use derivative works provided
19  * that such works are identified as "derived from the RSA Data
20  * Security, Inc. MD5 Message-Digest Algorithm" in all material
21  * mentioning or referencing the derived work.
22  *
23  * RSA Data Security, Inc. makes no representations concerning either
24  * the merchantability of this software or the suitability of this
25  * software for any particular purpose. It is provided "as is"
26  * without express or implied warranty of any kind.
27  *
28  * These notices must be retained in any copies of any part of this
29  * documentation and/or software.
30  */
31 
32 #if defined(_KERNEL) || defined(_STANDALONE)
33 #include <sys/param.h>
34 #include <sys/md5.h>
35 #include <lib/libkern/libkern.h>
36 #else
37 #include <sys/cdefs.h>
38 #if defined(LIBC_SCCS) && !defined(lint)
39 __RCSID("$NetBSD: md5c.c,v 1.5 2012/03/20 16:21:41 matt Exp $");
40 #endif /* LIBC_SCCS and not lint */
41 #include "namespace.h"
42 #include <sys/types.h>
43 #include <assert.h>
44 #include <string.h>
45 #include <md5.h>
46 #endif /* _KERNEL || _STANDALONE */
47 
48 #if HAVE_NBTOOL_CONFIG_H
49 #include "nbtool_config.h"
50 #endif
51 
52 #if !HAVE_MD5_H
53 
54 #define	ZEROIZE(d, l)		memset((d), 0, (l))
55 
56 typedef unsigned char *POINTER;
57 typedef uint16_t UINT2;
58 typedef uint32_t UINT4;
59 
60 /*
61  * Constants for MD5Transform routine.
62  */
63 #define S11 7
64 #define S12 12
65 #define S13 17
66 #define S14 22
67 #define S21 5
68 #define S22 9
69 #define S23 14
70 #define S24 20
71 #define S31 4
72 #define S32 11
73 #define S33 16
74 #define S34 23
75 #define S41 6
76 #define S42 10
77 #define S43 15
78 #define S44 21
79 
80 #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(__weak_alias)
81 __weak_alias(MD5Init,_MD5Init)
82 __weak_alias(MD5Update,_MD5Update)
83 __weak_alias(MD5Final,_MD5Final)
84 __weak_alias(MD5Transform,_MD5Transform)
85 #endif
86 
87 static void MD5Transform(UINT4 [4], const unsigned char [64]);
88 
89 static void Encode(unsigned char *, UINT4 *, unsigned int);
90 static void Decode(UINT4 *, const unsigned char *, unsigned int);
91 
92 /*
93  * Encodes input (UINT4) into output (unsigned char).  Assumes len is
94  * a multiple of 4.
95  */
96 static void
Encode(unsigned char * output,UINT4 * input,unsigned int len)97 Encode (unsigned char *output,
98 	UINT4 *input,
99 	unsigned int len)
100 {
101 	unsigned int i, j;
102 
103 	for (i = 0, j = 0; j < len; i++, j += 4) {
104 		output[j] = (unsigned char)(input[i] & 0xff);
105 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
106 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
107 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
108 	}
109 }
110 
111 /*
112  * Decodes input (unsigned char) into output (UINT4).  Assumes len is
113  * a multiple of 4.
114  */
115 static void
Decode(UINT4 * output,const unsigned char * input,unsigned int len)116 Decode (UINT4 *output,
117 	const unsigned char *input,
118 	unsigned int len)
119 {
120 	unsigned int i, j;
121 
122 	for (i = 0, j = 0; j < len; i++, j += 4)
123 		output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
124 		    (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
125 }
126 
127 static const unsigned char PADDING[64] = {
128 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
129 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
131 };
132 
133 /*
134  * F, G, H and I are basic MD5 functions.
135  */
136 #define F(x, y, z)	(((x) & (y)) | ((~x) & (z)))
137 #define G(x, y, z)	(((x) & (z)) | ((y) & (~z)))
138 #define H(x, y, z)	((x) ^ (y) ^ (z))
139 #define I(x, y, z)	((y) ^ ((x) | (~z)))
140 
141 /*
142  * ROTATE_LEFT rotates x left n bits.
143  */
144 #define ROTATE_LEFT(x, n)	(((x) << (n)) | ((x) >> (32-(n))))
145 
146 /*
147  * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
148  * Rotation is separate from addition to prevent recomputation.
149  */
150 #define FF(a, b, c, d, x, s, ac) { \
151 	(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
152 	(a) = ROTATE_LEFT ((a), (s)); \
153 	(a) += (b); \
154 }
155 
156 #define GG(a, b, c, d, x, s, ac) { \
157 	(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
158 	(a) = ROTATE_LEFT ((a), (s)); \
159 	(a) += (b); \
160 }
161 
162 #define HH(a, b, c, d, x, s, ac) { \
163 	(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
164 	(a) = ROTATE_LEFT ((a), (s)); \
165 	(a) += (b); \
166 }
167 
168 #define II(a, b, c, d, x, s, ac) { \
169 	(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
170 	(a) = ROTATE_LEFT ((a), (s)); \
171 	(a) += (b); \
172 }
173 
174 /*
175  * MD5 initialization. Begins an MD5 operation, writing a new context.
176  */
177 void
MD5Init(MD5_CTX * context)178 MD5Init(MD5_CTX *context)
179 {
180 
181 	_DIAGASSERT(context != 0);
182 
183 	context->count[0] = context->count[1] = 0;
184 
185 	/* Load magic initialization constants. */
186 	context->state[0] = 0x67452301;
187 	context->state[1] = 0xefcdab89;
188 	context->state[2] = 0x98badcfe;
189 	context->state[3] = 0x10325476;
190 }
191 
192 /*
193  * MD5 block update operation.  Continues an MD5 message-digest
194  * operation, processing another message block, and updating the
195  * context.
196  */
197 void
MD5Update(MD5_CTX * context,const unsigned char * input,unsigned int inputLen)198 MD5Update(MD5_CTX *context,
199 	const unsigned char *input,	/* input block */
200 	unsigned int inputLen)		/* length of input block */
201 {
202 	unsigned int i, idx, partLen;
203 
204 	_DIAGASSERT(context != 0);
205 	_DIAGASSERT(input != 0);
206 
207 	/* Compute number of bytes mod 64 */
208 	idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
209 
210 	/* Update number of bits */
211 	if ((context->count[0] += ((UINT4)inputLen << 3))
212 	    < ((UINT4)inputLen << 3))
213 		context->count[1]++;
214 	context->count[1] += ((UINT4)inputLen >> 29);
215 
216 	partLen = 64 - idx;
217 
218 	/* Transform as many times as possible. */
219 	if (inputLen >= partLen) {
220 		memcpy((POINTER)&context->buffer[idx], input, partLen);
221 		MD5Transform(context->state, context->buffer);
222 
223 		for (i = partLen; i + 63 < inputLen; i += 64)
224 			MD5Transform(context->state, &input[i]);
225 
226 		idx = 0;
227 	} else
228 		i = 0;
229 
230 	/* Buffer remaining input */
231 	memcpy(&context->buffer[idx], &input[i], inputLen - i);
232 }
233 
234 /*
235  * MD5 finalization.  Ends an MD5 message-digest operation, writing the
236  * message digest and zeroing the context.
237  */
238 void
MD5Final(unsigned char digest[16],MD5_CTX * context)239 MD5Final(unsigned char digest[16],	/* message digest */
240 	MD5_CTX *context)		/* context */
241 {
242 	unsigned char bits[8];
243 	unsigned int idx, padLen;
244 
245 	_DIAGASSERT(digest != 0);
246 	_DIAGASSERT(context != 0);
247 
248 	/* Save number of bits */
249 	Encode(bits, context->count, 8);
250 
251 	/* Pad out to 56 mod 64. */
252 	idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
253 	padLen = (idx < 56) ? (56 - idx) : (120 - idx);
254 	MD5Update (context, PADDING, padLen);
255 
256 	/* Append length (before padding) */
257 	MD5Update(context, bits, 8);
258 
259 	/* Store state in digest */
260 	Encode(digest, context->state, 16);
261 
262 	/* Zeroize sensitive information. */
263 	ZEROIZE((POINTER)(void *)context, sizeof(*context));
264 }
265 
266 /*
267  * MD5 basic transformation. Transforms state based on block.
268  */
269 static void
MD5Transform(UINT4 state[4],const unsigned char block[64])270 MD5Transform(UINT4 state[4], const unsigned char block[64])
271 {
272 	UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
273 
274 	Decode(x, block, 64);
275 
276 	/* Round 1 */
277 	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
278 	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
279 	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
280 	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
281 	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
282 	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
283 	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
284 	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
285 	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
286 	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
287 	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
288 	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
289 	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
290 	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
291 	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
292 	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
293 
294 	/* Round 2 */
295 	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
296 	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
297 	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
298 	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
299 	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
300 	GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
301 	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
302 	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
303 	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
304 	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
305 	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
306 	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
307 	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
308 	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
309 	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
310 	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
311 
312 	/* Round 3 */
313 	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
314 	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
315 	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
316 	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
317 	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
318 	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
319 	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
320 	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
321 	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
322 	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
323 	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
324 	HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
325 	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
326 	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
327 	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
328 	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
329 
330 	/* Round 4 */
331 	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
332 	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
333 	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
334 	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
335 	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
336 	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
337 	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
338 	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
339 	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
340 	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
341 	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
342 	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
343 	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
344 	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
345 	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
346 	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
347 
348 	state[0] += a;
349 	state[1] += b;
350 	state[2] += c;
351 	state[3] += d;
352 
353 	/* Zeroize sensitive information. */
354 	ZEROIZE((POINTER)(void *)x, sizeof (x));
355 }
356 
357 #endif /* HAVE_MD5_H */
358