xref: /netbsd-src/common/lib/libc/md/md5c.c (revision 404fbe5fb94ca1e054339640cabb2801ce52dd30)
1 /*	$NetBSD: md5c.c,v 1.3 2008/02/16 17:37:13 apb 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.3 2008/02/16 17:37:13 apb 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 __P((UINT4 [4], const unsigned char [64]));
88 
89 static void Encode __P((unsigned char *, UINT4 *, unsigned int));
90 static void Decode __P((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
97 Encode (output, input, len)
98 	unsigned char *output;
99 	UINT4 *input;
100 	unsigned int len;
101 {
102 	unsigned int i, j;
103 
104 	for (i = 0, j = 0; j < len; i++, j += 4) {
105 		output[j] = (unsigned char)(input[i] & 0xff);
106 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
107 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
108 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
109 	}
110 }
111 
112 /*
113  * Decodes input (unsigned char) into output (UINT4).  Assumes len is
114  * a multiple of 4.
115  */
116 static void
117 Decode (output, input, len)
118 	UINT4 *output;
119 	const unsigned char *input;
120 	unsigned int len;
121 {
122 	unsigned int i, j;
123 
124 	for (i = 0, j = 0; j < len; i++, j += 4)
125 		output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
126 		    (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
127 }
128 
129 static const unsigned char PADDING[64] = {
130 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
133 };
134 
135 /*
136  * F, G, H and I are basic MD5 functions.
137  */
138 #define F(x, y, z)	(((x) & (y)) | ((~x) & (z)))
139 #define G(x, y, z)	(((x) & (z)) | ((y) & (~z)))
140 #define H(x, y, z)	((x) ^ (y) ^ (z))
141 #define I(x, y, z)	((y) ^ ((x) | (~z)))
142 
143 /*
144  * ROTATE_LEFT rotates x left n bits.
145  */
146 #define ROTATE_LEFT(x, n)	(((x) << (n)) | ((x) >> (32-(n))))
147 
148 /*
149  * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
150  * Rotation is separate from addition to prevent recomputation.
151  */
152 #define FF(a, b, c, d, x, s, ac) { \
153 	(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
154 	(a) = ROTATE_LEFT ((a), (s)); \
155 	(a) += (b); \
156 }
157 
158 #define GG(a, b, c, d, x, s, ac) { \
159 	(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
160 	(a) = ROTATE_LEFT ((a), (s)); \
161 	(a) += (b); \
162 }
163 
164 #define HH(a, b, c, d, x, s, ac) { \
165 	(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
166 	(a) = ROTATE_LEFT ((a), (s)); \
167 	(a) += (b); \
168 }
169 
170 #define II(a, b, c, d, x, s, ac) { \
171 	(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
172 	(a) = ROTATE_LEFT ((a), (s)); \
173 	(a) += (b); \
174 }
175 
176 /*
177  * MD5 initialization. Begins an MD5 operation, writing a new context.
178  */
179 void
180 MD5Init(context)
181 	MD5_CTX *context;		/* context */
182 {
183 
184 	_DIAGASSERT(context != 0);
185 
186 	context->count[0] = context->count[1] = 0;
187 
188 	/* Load magic initialization constants. */
189 	context->state[0] = 0x67452301;
190 	context->state[1] = 0xefcdab89;
191 	context->state[2] = 0x98badcfe;
192 	context->state[3] = 0x10325476;
193 }
194 
195 /*
196  * MD5 block update operation.  Continues an MD5 message-digest
197  * operation, processing another message block, and updating the
198  * context.
199  */
200 void
201 MD5Update(context, input, inputLen)
202 	MD5_CTX *context;		/* context */
203 	const unsigned char *input;	/* input block */
204 	unsigned int inputLen;		/* length of input block */
205 {
206 	unsigned int i, idx, partLen;
207 
208 	_DIAGASSERT(context != 0);
209 	_DIAGASSERT(input != 0);
210 
211 	/* Compute number of bytes mod 64 */
212 	idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
213 
214 	/* Update number of bits */
215 	if ((context->count[0] += ((UINT4)inputLen << 3))
216 	    < ((UINT4)inputLen << 3))
217 		context->count[1]++;
218 	context->count[1] += ((UINT4)inputLen >> 29);
219 
220 	partLen = 64 - idx;
221 
222 	/* Transform as many times as possible. */
223 	if (inputLen >= partLen) {
224 		memcpy((POINTER)&context->buffer[idx], input, partLen);
225 		MD5Transform(context->state, context->buffer);
226 
227 		for (i = partLen; i + 63 < inputLen; i += 64)
228 			MD5Transform(context->state, &input[i]);
229 
230 		idx = 0;
231 	} else
232 		i = 0;
233 
234 	/* Buffer remaining input */
235 	memcpy(&context->buffer[idx], &input[i], inputLen - i);
236 }
237 
238 /*
239  * MD5 finalization.  Ends an MD5 message-digest operation, writing the
240  * message digest and zeroing the context.
241  */
242 void
243 MD5Final(digest, context)
244 	unsigned char digest[16];	/* message digest */
245 	MD5_CTX *context;		/* context */
246 {
247 	unsigned char bits[8];
248 	unsigned int idx, padLen;
249 
250 	_DIAGASSERT(digest != 0);
251 	_DIAGASSERT(context != 0);
252 
253 	/* Save number of bits */
254 	Encode(bits, context->count, 8);
255 
256 	/* Pad out to 56 mod 64. */
257 	idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
258 	padLen = (idx < 56) ? (56 - idx) : (120 - idx);
259 	MD5Update (context, PADDING, padLen);
260 
261 	/* Append length (before padding) */
262 	MD5Update(context, bits, 8);
263 
264 	/* Store state in digest */
265 	Encode(digest, context->state, 16);
266 
267 	/* Zeroize sensitive information. */
268 	ZEROIZE((POINTER)(void *)context, sizeof(*context));
269 }
270 
271 /*
272  * MD5 basic transformation. Transforms state based on block.
273  */
274 static void
275 MD5Transform(state, block)
276 	UINT4 state[4];
277 	const unsigned char block[64];
278 {
279 	UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
280 
281 	Decode(x, block, 64);
282 
283 	/* Round 1 */
284 	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
285 	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
286 	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
287 	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
288 	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
289 	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
290 	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
291 	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
292 	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
293 	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
294 	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
295 	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
296 	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
297 	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
298 	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
299 	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
300 
301 	/* Round 2 */
302 	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
303 	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
304 	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
305 	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
306 	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
307 	GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
308 	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
309 	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
310 	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
311 	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
312 	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
313 	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
314 	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
315 	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
316 	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
317 	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
318 
319 	/* Round 3 */
320 	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
321 	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
322 	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
323 	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
324 	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
325 	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
326 	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
327 	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
328 	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
329 	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
330 	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
331 	HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
332 	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
333 	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
334 	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
335 	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
336 
337 	/* Round 4 */
338 	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
339 	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
340 	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
341 	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
342 	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
343 	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
344 	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
345 	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
346 	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
347 	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
348 	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
349 	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
350 	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
351 	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
352 	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
353 	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
354 
355 	state[0] += a;
356 	state[1] += b;
357 	state[2] += c;
358 	state[3] += d;
359 
360 	/* Zeroize sensitive information. */
361 	ZEROIZE((POINTER)(void *)x, sizeof (x));
362 }
363 
364 #endif /* HAVE_MD5_H */
365