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
56typedef unsigned char *POINTER;
57typedef uint16_t UINT2;
58typedef 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
87static void MD5Transform(UINT4 [4], const unsigned char [64]);
88
89static void Encode(unsigned char *, UINT4 *, unsigned int);
90static 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 */
96static void
97Encode (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 */
115static void
116Decode (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
127static 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 */
177void
178MD5Init(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 */
197void
198MD5Update(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 */
238void
239MD5Final(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 */
269static void
270MD5Transform(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