xref: /netbsd-src/common/lib/libc/md/md4c.c (revision 567219e1d7461bff1b180e494a9674a287b057a7)
1*567219e1Smatt /*	$NetBSD: md4c.c,v 1.5 2012/03/20 16:21:41 matt Exp $	*/
237c9f0a6Schristos 
337c9f0a6Schristos /*
437c9f0a6Schristos  * This file is derived from the RSA Data Security, Inc. MD4 Message-Digest
537c9f0a6Schristos  * Algorithm and has been modified by Jason R. Thorpe <thorpej@NetBSD.org>
637c9f0a6Schristos  * for portability and formatting.
737c9f0a6Schristos  */
837c9f0a6Schristos 
937c9f0a6Schristos /*
1037c9f0a6Schristos  * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
1137c9f0a6Schristos  *
1237c9f0a6Schristos  * License to copy and use this software is granted provided that it
1337c9f0a6Schristos  * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
1437c9f0a6Schristos  * Algorithm" in all material mentioning or referencing this software
1537c9f0a6Schristos  * or this function.
1637c9f0a6Schristos  *
1737c9f0a6Schristos  * License is also granted to make and use derivative works provided
1837c9f0a6Schristos  * that such works are identified as "derived from the RSA Data
1937c9f0a6Schristos  * Security, Inc. MD4 Message-Digest Algorithm" in all material
2037c9f0a6Schristos  * mentioning or referencing the derived work.
2137c9f0a6Schristos  *
2237c9f0a6Schristos  * RSA Data Security, Inc. makes no representations concerning either
2337c9f0a6Schristos  * the merchantability of this software or the suitability of this
2437c9f0a6Schristos  * software for any particular purpose. It is provided "as is"
2537c9f0a6Schristos  * without express or implied warranty of any kind.
2637c9f0a6Schristos  *
2737c9f0a6Schristos  * These notices must be retained in any copies of any part of this
2837c9f0a6Schristos  * documentation and/or software.
2937c9f0a6Schristos  */
3037c9f0a6Schristos 
3137c9f0a6Schristos #if !defined(_KERNEL) && !defined(_STANDALONE)
3237c9f0a6Schristos #include <sys/cdefs.h>
3337c9f0a6Schristos #if defined(LIBC_SCCS) && !defined(lint)
34*567219e1Smatt __RCSID("$NetBSD: md4c.c,v 1.5 2012/03/20 16:21:41 matt Exp $");
3537c9f0a6Schristos #endif /* LIBC_SCCS and not lint */
3637c9f0a6Schristos 
3737c9f0a6Schristos #include "namespace.h"
3837c9f0a6Schristos 
3937c9f0a6Schristos #include <sys/types.h>
4037c9f0a6Schristos 
4137c9f0a6Schristos #include <assert.h>
4237c9f0a6Schristos #include <md4.h>
4337c9f0a6Schristos #include <string.h>
4437c9f0a6Schristos 
4537c9f0a6Schristos #if HAVE_NBTOOL_CONFIG_H
4637c9f0a6Schristos #include "nbtool_config.h"
4737c9f0a6Schristos #endif
4837c9f0a6Schristos 
4937c9f0a6Schristos #else
5037c9f0a6Schristos 
519abe0ed1Smatt #include <sys/param.h>
5237c9f0a6Schristos #include <sys/md4.h>
5337c9f0a6Schristos #include <lib/libkern/libkern.h>
5437c9f0a6Schristos 
5537c9f0a6Schristos #endif /* !_KERNEL && !_STANDALONE */
5637c9f0a6Schristos 
5737c9f0a6Schristos #if !HAVE_MD4_H
5837c9f0a6Schristos 
5937c9f0a6Schristos typedef unsigned char *POINTER;
60267197ecSapb typedef uint16_t UINT2;
61267197ecSapb typedef uint32_t UINT4;
6237c9f0a6Schristos 
6337c9f0a6Schristos /*
6437c9f0a6Schristos  * Constants for MD4Transform routine.
6537c9f0a6Schristos  */
6637c9f0a6Schristos #define S11 3
6737c9f0a6Schristos #define S12 7
6837c9f0a6Schristos #define S13 11
6937c9f0a6Schristos #define S14 19
7037c9f0a6Schristos #define S21 3
7137c9f0a6Schristos #define S22 5
7237c9f0a6Schristos #define S23 9
7337c9f0a6Schristos #define S24 13
7437c9f0a6Schristos #define S31 3
7537c9f0a6Schristos #define S32 9
7637c9f0a6Schristos #define S33 11
7737c9f0a6Schristos #define S34 15
7837c9f0a6Schristos 
79*567219e1Smatt static void MD4Transform(UINT4 [4], const unsigned char [64]);
8037c9f0a6Schristos 
81*567219e1Smatt static void Encode(unsigned char *, UINT4 *, unsigned int);
82*567219e1Smatt static void Decode(UINT4 *, const unsigned char *, unsigned int);
8337c9f0a6Schristos 
8437c9f0a6Schristos static const unsigned char PADDING[64] = {
8537c9f0a6Schristos 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8637c9f0a6Schristos 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8737c9f0a6Schristos 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
8837c9f0a6Schristos };
8937c9f0a6Schristos 
9037c9f0a6Schristos /*
9137c9f0a6Schristos  * F, G and H are basic MD4 functions.
9237c9f0a6Schristos  */
9337c9f0a6Schristos #define F(x, y, z)	(((x) & (y)) | ((~x) & (z)))
9437c9f0a6Schristos #define G(x, y, z)	(((x) & (y)) | ((x) & (z)) | ((y) & (z)))
9537c9f0a6Schristos #define H(x, y, z)	((x) ^ (y) ^ (z))
9637c9f0a6Schristos 
9737c9f0a6Schristos /*
9837c9f0a6Schristos  * ROTATE_LEFT rotates x left n bits.
9937c9f0a6Schristos  */
10037c9f0a6Schristos #define ROTATE_LEFT(x, n)	(((x) << (n)) | ((x) >> (32-(n))))
10137c9f0a6Schristos 
10237c9f0a6Schristos /*
10337c9f0a6Schristos  * FF, GG and HH are transformations for rounds 1, 2 and 3.
10437c9f0a6Schristos  * Rotation is separate from addition to prevent recomputation.
10537c9f0a6Schristos  */
10637c9f0a6Schristos #define FF(a, b, c, d, x, s) { \
10737c9f0a6Schristos 	(a) += F ((b), (c), (d)) + (x); \
10837c9f0a6Schristos 	(a) = ROTATE_LEFT ((a), (s)); \
10937c9f0a6Schristos }
11037c9f0a6Schristos 
11137c9f0a6Schristos #define GG(a, b, c, d, x, s) { \
11237c9f0a6Schristos 	(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
11337c9f0a6Schristos 	(a) = ROTATE_LEFT ((a), (s)); \
11437c9f0a6Schristos }
11537c9f0a6Schristos 
11637c9f0a6Schristos #define HH(a, b, c, d, x, s) { \
11737c9f0a6Schristos 	(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
11837c9f0a6Schristos 	(a) = ROTATE_LEFT ((a), (s)); \
11937c9f0a6Schristos }
12037c9f0a6Schristos 
12137c9f0a6Schristos #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(__weak_alias)
__weak_alias(MD4Init,_MD4Init)12237c9f0a6Schristos __weak_alias(MD4Init,_MD4Init)
12337c9f0a6Schristos __weak_alias(MD4Update,_MD4Update)
12437c9f0a6Schristos __weak_alias(MD4Final,_MD4Final)
12537c9f0a6Schristos __weak_alias(MD4Transform,_MD4Transform)
12637c9f0a6Schristos #endif
12737c9f0a6Schristos 
12837c9f0a6Schristos /*
12937c9f0a6Schristos  * MD4 initialization. Begins an MD4 operation, writing a new context.
13037c9f0a6Schristos  */
13137c9f0a6Schristos void
13296276685Scegger MD4Init(MD4_CTX *context)		/* context */
13337c9f0a6Schristos {
13437c9f0a6Schristos 
13537c9f0a6Schristos 	_DIAGASSERT(context != 0);
13637c9f0a6Schristos 
13737c9f0a6Schristos 	context->count[0] = context->count[1] = 0;
13837c9f0a6Schristos 
13937c9f0a6Schristos 	/* Load magic initialization constants. */
14037c9f0a6Schristos 	context->state[0] = 0x67452301;
14137c9f0a6Schristos 	context->state[1] = 0xefcdab89;
14237c9f0a6Schristos 	context->state[2] = 0x98badcfe;
14337c9f0a6Schristos 	context->state[3] = 0x10325476;
14437c9f0a6Schristos }
14537c9f0a6Schristos 
14637c9f0a6Schristos /*
14737c9f0a6Schristos  * MD4 block update operation.  Continues an MD4 message-digest
14837c9f0a6Schristos  * operation, processing another message block, and updating the
14937c9f0a6Schristos  * context.
15037c9f0a6Schristos  */
15137c9f0a6Schristos void
MD4Update(MD4_CTX * context,const unsigned char * input,unsigned int inputLen)15296276685Scegger MD4Update (MD4_CTX *context,		/* context */
15396276685Scegger 	const unsigned char *input,	/* input block */
15496276685Scegger 	unsigned int inputLen)		/* length of input block */
15537c9f0a6Schristos {
15637c9f0a6Schristos 	unsigned int i, idx, partLen;
15737c9f0a6Schristos 
15837c9f0a6Schristos 	_DIAGASSERT(context != 0);
15937c9f0a6Schristos 	_DIAGASSERT(input != 0);
16037c9f0a6Schristos 
16137c9f0a6Schristos 	/* Compute number of bytes mod 64 */
16237c9f0a6Schristos 	idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
16337c9f0a6Schristos 
16437c9f0a6Schristos 	/* Update number of bits */
16537c9f0a6Schristos 	if ((context->count[0] += ((UINT4)inputLen << 3))
16637c9f0a6Schristos 	    < ((UINT4)inputLen << 3))
16737c9f0a6Schristos 		context->count[1]++;
16837c9f0a6Schristos 	context->count[1] += ((UINT4)inputLen >> 29);
16937c9f0a6Schristos 
17037c9f0a6Schristos 	partLen = 64 - idx;
17137c9f0a6Schristos 
17237c9f0a6Schristos 	/* Transform as many times as possible. */
17337c9f0a6Schristos 	if (inputLen >= partLen) {
17437c9f0a6Schristos 		memcpy(&context->buffer[idx], input, partLen);
17537c9f0a6Schristos 		MD4Transform(context->state, context->buffer);
17637c9f0a6Schristos 
17737c9f0a6Schristos 		for (i = partLen; i + 63 < inputLen; i += 64)
17837c9f0a6Schristos 			MD4Transform(context->state, &input[i]);
17937c9f0a6Schristos 
18037c9f0a6Schristos 		idx = 0;
18137c9f0a6Schristos 	} else
18237c9f0a6Schristos 		i = 0;
18337c9f0a6Schristos 
18437c9f0a6Schristos 	/* Buffer remaining input */
18537c9f0a6Schristos 	memcpy(&context->buffer[idx], &input[i], inputLen - i);
18637c9f0a6Schristos }
18737c9f0a6Schristos 
18837c9f0a6Schristos /*
18937c9f0a6Schristos  * MD4 finalization.  Ends an MD4 message-digest operation, writing the
19037c9f0a6Schristos  * message digest and zeroing the context.
19137c9f0a6Schristos  */
19237c9f0a6Schristos void
MD4Final(unsigned char digest[16],MD4_CTX * context)19396276685Scegger MD4Final (unsigned char digest[16],	/* message digest */
19496276685Scegger 	MD4_CTX *context)		/* context */
19537c9f0a6Schristos {
19637c9f0a6Schristos 	unsigned char bits[8];
19737c9f0a6Schristos 	unsigned int idx, padLen;
19837c9f0a6Schristos 
19937c9f0a6Schristos 	_DIAGASSERT(digest != 0);
20037c9f0a6Schristos 	_DIAGASSERT(context != 0);
20137c9f0a6Schristos 
20237c9f0a6Schristos 	/* Save number of bits */
20337c9f0a6Schristos 	Encode(bits, context->count, 8);
20437c9f0a6Schristos 
20537c9f0a6Schristos 	/* Pad out to 56 mod 64. */
20637c9f0a6Schristos 	idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
20737c9f0a6Schristos 	padLen = (idx < 56) ? (56 - idx) : (120 - idx);
20837c9f0a6Schristos 	MD4Update(context, PADDING, padLen);
20937c9f0a6Schristos 
21037c9f0a6Schristos 	/* Append length (before padding) */
21137c9f0a6Schristos 	MD4Update(context, bits, 8);
21237c9f0a6Schristos 
21337c9f0a6Schristos 	/* Store state in digest */
21437c9f0a6Schristos 	Encode(digest, context->state, 16);
21537c9f0a6Schristos 
21637c9f0a6Schristos 	/* Zeroize sensitive information. */
21737c9f0a6Schristos 	memset(context, 0, sizeof(*context));
21837c9f0a6Schristos }
21937c9f0a6Schristos 
22037c9f0a6Schristos /*
22137c9f0a6Schristos  * MD4 basic transformation.  Transforms state based on block.
22237c9f0a6Schristos  */
22337c9f0a6Schristos static void
MD4Transform(UINT4 state[4],const unsigned char block[64])22496276685Scegger MD4Transform (UINT4 state[4], const unsigned char block[64])
22537c9f0a6Schristos {
22637c9f0a6Schristos 	UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
22737c9f0a6Schristos 
22837c9f0a6Schristos 	Decode(x, block, 64);
22937c9f0a6Schristos 
23037c9f0a6Schristos 	/* Round 1 */
23137c9f0a6Schristos 	FF (a, b, c, d, x[ 0], S11); /* 1 */
23237c9f0a6Schristos 	FF (d, a, b, c, x[ 1], S12); /* 2 */
23337c9f0a6Schristos 	FF (c, d, a, b, x[ 2], S13); /* 3 */
23437c9f0a6Schristos 	FF (b, c, d, a, x[ 3], S14); /* 4 */
23537c9f0a6Schristos 	FF (a, b, c, d, x[ 4], S11); /* 5 */
23637c9f0a6Schristos 	FF (d, a, b, c, x[ 5], S12); /* 6 */
23737c9f0a6Schristos 	FF (c, d, a, b, x[ 6], S13); /* 7 */
23837c9f0a6Schristos 	FF (b, c, d, a, x[ 7], S14); /* 8 */
23937c9f0a6Schristos 	FF (a, b, c, d, x[ 8], S11); /* 9 */
24037c9f0a6Schristos 	FF (d, a, b, c, x[ 9], S12); /* 10 */
24137c9f0a6Schristos 	FF (c, d, a, b, x[10], S13); /* 11 */
24237c9f0a6Schristos 	FF (b, c, d, a, x[11], S14); /* 12 */
24337c9f0a6Schristos 	FF (a, b, c, d, x[12], S11); /* 13 */
24437c9f0a6Schristos 	FF (d, a, b, c, x[13], S12); /* 14 */
24537c9f0a6Schristos 	FF (c, d, a, b, x[14], S13); /* 15 */
24637c9f0a6Schristos 	FF (b, c, d, a, x[15], S14); /* 16 */
24737c9f0a6Schristos 
24837c9f0a6Schristos 	/* Round 2 */
24937c9f0a6Schristos 	GG (a, b, c, d, x[ 0], S21); /* 17 */
25037c9f0a6Schristos 	GG (d, a, b, c, x[ 4], S22); /* 18 */
25137c9f0a6Schristos 	GG (c, d, a, b, x[ 8], S23); /* 19 */
25237c9f0a6Schristos 	GG (b, c, d, a, x[12], S24); /* 20 */
25337c9f0a6Schristos 	GG (a, b, c, d, x[ 1], S21); /* 21 */
25437c9f0a6Schristos 	GG (d, a, b, c, x[ 5], S22); /* 22 */
25537c9f0a6Schristos 	GG (c, d, a, b, x[ 9], S23); /* 23 */
25637c9f0a6Schristos 	GG (b, c, d, a, x[13], S24); /* 24 */
25737c9f0a6Schristos 	GG (a, b, c, d, x[ 2], S21); /* 25 */
25837c9f0a6Schristos 	GG (d, a, b, c, x[ 6], S22); /* 26 */
25937c9f0a6Schristos 	GG (c, d, a, b, x[10], S23); /* 27 */
26037c9f0a6Schristos 	GG (b, c, d, a, x[14], S24); /* 28 */
26137c9f0a6Schristos 	GG (a, b, c, d, x[ 3], S21); /* 29 */
26237c9f0a6Schristos 	GG (d, a, b, c, x[ 7], S22); /* 30 */
26337c9f0a6Schristos 	GG (c, d, a, b, x[11], S23); /* 31 */
26437c9f0a6Schristos 	GG (b, c, d, a, x[15], S24); /* 32 */
26537c9f0a6Schristos 
26637c9f0a6Schristos 	/* Round 3 */
26737c9f0a6Schristos 	HH (a, b, c, d, x[ 0], S31); /* 33 */
26837c9f0a6Schristos 	HH (d, a, b, c, x[ 8], S32); /* 34 */
26937c9f0a6Schristos 	HH (c, d, a, b, x[ 4], S33); /* 35 */
27037c9f0a6Schristos 	HH (b, c, d, a, x[12], S34); /* 36 */
27137c9f0a6Schristos 	HH (a, b, c, d, x[ 2], S31); /* 37 */
27237c9f0a6Schristos 	HH (d, a, b, c, x[10], S32); /* 38 */
27337c9f0a6Schristos 	HH (c, d, a, b, x[ 6], S33); /* 39 */
27437c9f0a6Schristos 	HH (b, c, d, a, x[14], S34); /* 40 */
27537c9f0a6Schristos 	HH (a, b, c, d, x[ 1], S31); /* 41 */
27637c9f0a6Schristos 	HH (d, a, b, c, x[ 9], S32); /* 42 */
27737c9f0a6Schristos 	HH (c, d, a, b, x[ 5], S33); /* 43 */
27837c9f0a6Schristos 	HH (b, c, d, a, x[13], S34); /* 44 */
27937c9f0a6Schristos 	HH (a, b, c, d, x[ 3], S31); /* 45 */
28037c9f0a6Schristos 	HH (d, a, b, c, x[11], S32); /* 46 */
28137c9f0a6Schristos 	HH (c, d, a, b, x[ 7], S33); /* 47 */
28237c9f0a6Schristos 	HH (b, c, d, a, x[15], S34); /* 48 */
28337c9f0a6Schristos 
28437c9f0a6Schristos 	state[0] += a;
28537c9f0a6Schristos 	state[1] += b;
28637c9f0a6Schristos 	state[2] += c;
28737c9f0a6Schristos 	state[3] += d;
28837c9f0a6Schristos 
28937c9f0a6Schristos 	/* Zeroize sensitive information. */
29037c9f0a6Schristos 	memset(x, 0, sizeof (x));
29137c9f0a6Schristos }
29237c9f0a6Schristos 
29337c9f0a6Schristos /*
29437c9f0a6Schristos  * Encodes input (UINT4) into output (unsigned char). Assumes len is
29537c9f0a6Schristos  * a multiple of 4.
29637c9f0a6Schristos  */
29737c9f0a6Schristos static void
Encode(unsigned char * output,UINT4 * input,unsigned int len)29896276685Scegger Encode(unsigned char *output, UINT4 *input, unsigned int len)
29937c9f0a6Schristos {
30037c9f0a6Schristos 	unsigned int i, j;
30137c9f0a6Schristos 
30237c9f0a6Schristos 	for (i = 0, j = 0; j < len; i++, j += 4) {
30337c9f0a6Schristos 		output[j] = (unsigned char)(input[i] & 0xff);
30437c9f0a6Schristos 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
30537c9f0a6Schristos 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
30637c9f0a6Schristos 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
30737c9f0a6Schristos 	}
30837c9f0a6Schristos }
30937c9f0a6Schristos 
31037c9f0a6Schristos /*
31137c9f0a6Schristos  * Decodes input (unsigned char) into output (UINT4). Assumes len is
31237c9f0a6Schristos  * a multiple of 4.
31337c9f0a6Schristos  */
31437c9f0a6Schristos static void
Decode(UINT4 * output,const unsigned char * input,unsigned int len)31596276685Scegger Decode(UINT4 *output, const unsigned char *input, unsigned int len)
31637c9f0a6Schristos {
31737c9f0a6Schristos 	unsigned int i, j;
31837c9f0a6Schristos 
31937c9f0a6Schristos 	for (i = 0, j = 0; j < len; i++, j += 4)
32037c9f0a6Schristos 		output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
32137c9f0a6Schristos 		    (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
32237c9f0a6Schristos }
32337c9f0a6Schristos 
32437c9f0a6Schristos #endif /* HAVE_MD4_H */
325