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