xref: /onnv-gate/usr/src/common/crypto/md4/md4.c (revision 7434:7702b99082d7)
11694Sdarrenm /*
27421SDaniel.Anderson@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
31694Sdarrenm  * Use is subject to license terms.
41694Sdarrenm  */
51694Sdarrenm 
61694Sdarrenm /*
71694Sdarrenm  * MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm
81694Sdarrenm  */
91694Sdarrenm 
101694Sdarrenm /*
111694Sdarrenm  * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
121694Sdarrenm  *
131694Sdarrenm  * License to copy and use this software is granted provided that it
141694Sdarrenm  * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
151694Sdarrenm  * Algorithm" in all material mentioning or referencing this software
161694Sdarrenm  * or this function.
171694Sdarrenm  *
181694Sdarrenm  * License is also granted to make and use derivative works provided
191694Sdarrenm  * that such works are identified as "derived from the RSA Data
201694Sdarrenm  * Security, Inc. MD4 Message-Digest Algorithm" in all material
211694Sdarrenm  * mentioning or referencing the derived work.
221694Sdarrenm  *
231694Sdarrenm  * RSA Data Security, Inc. makes no representations concerning either
241694Sdarrenm  * the merchantability of this software or the suitability of this
251694Sdarrenm  * software for any particular purpose. It is provided "as is"
261694Sdarrenm  * without express or implied warranty of any kind.
271694Sdarrenm  *
281694Sdarrenm  * These notices must be retained in any copies of any part of this
291694Sdarrenm  * documentation and/or software.
301694Sdarrenm  */
311694Sdarrenm 
324002Sdarrenm #include <sys/types.h>
334002Sdarrenm #ifdef _KERNEL
344002Sdarrenm #include <sys/sunddi.h>
354002Sdarrenm #else
364002Sdarrenm #include <strings.h>
374002Sdarrenm #endif /* _KERNEL */
381694Sdarrenm 
397421SDaniel.Anderson@Sun.COM #if defined(__i386) || defined(__amd64)
407421SDaniel.Anderson@Sun.COM #define	UNALIGNED_POINTERS_PERMITTED
417421SDaniel.Anderson@Sun.COM #endif
427421SDaniel.Anderson@Sun.COM 
434002Sdarrenm #include <sys/md4.h>
441694Sdarrenm 
451694Sdarrenm /*
461694Sdarrenm  * Constants for MD4Transform routine.
471694Sdarrenm  */
481694Sdarrenm #define	S11 3
491694Sdarrenm #define	S12 7
501694Sdarrenm #define	S13 11
511694Sdarrenm #define	S14 19
521694Sdarrenm #define	S21 3
531694Sdarrenm #define	S22 5
541694Sdarrenm #define	S23 9
551694Sdarrenm #define	S24 13
561694Sdarrenm #define	S31 3
571694Sdarrenm #define	S32 9
581694Sdarrenm #define	S33 11
591694Sdarrenm #define	S34 15
601694Sdarrenm 
614002Sdarrenm static void MD4Transform(uint32_t [4], unsigned char [64]);
624002Sdarrenm static void Encode(unsigned char *, uint32_t *, unsigned int);
634002Sdarrenm static void Decode(uint32_t *, unsigned char *, unsigned int);
641694Sdarrenm 
651694Sdarrenm static unsigned char PADDING[64] = {
661694Sdarrenm 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
671694Sdarrenm 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
681694Sdarrenm 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
691694Sdarrenm };
701694Sdarrenm 
711694Sdarrenm /*
721694Sdarrenm  * F, G and H are basic MD4 functions.
731694Sdarrenm  */
741694Sdarrenm #define	F(x, y, z) (((x) & (y)) | ((~x) & (z)))
751694Sdarrenm #define	G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
761694Sdarrenm #define	H(x, y, z) ((x) ^ (y) ^ (z))
771694Sdarrenm 
781694Sdarrenm /*
791694Sdarrenm  * ROTATE_LEFT rotates x left n bits.
801694Sdarrenm  */
811694Sdarrenm #define	ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
821694Sdarrenm 
831694Sdarrenm /* FF, GG and HH are transformations for rounds 1, 2 and 3 */
841694Sdarrenm /* Rotation is separate from addition to prevent recomputation */
851694Sdarrenm 
861694Sdarrenm #define	FF(a, b, c, d, x, s) { \
871694Sdarrenm 		(a) += F((b), (c), (d)) + (x); \
881694Sdarrenm 		(a) = ROTATE_LEFT((a), (s)); \
891694Sdarrenm 	}
901694Sdarrenm #define	GG(a, b, c, d, x, s) { \
914002Sdarrenm 		(a) += G((b), (c), (d)) + (x) + (uint32_t)0x5a827999; \
921694Sdarrenm 		(a) = ROTATE_LEFT((a), (s)); \
931694Sdarrenm 	}
941694Sdarrenm #define	HH(a, b, c, d, x, s) { \
954002Sdarrenm 		(a) += H((b), (c), (d)) + (x) + (uint32_t)0x6ed9eba1; \
961694Sdarrenm 		(a) = ROTATE_LEFT((a), (s)); \
971694Sdarrenm 	}
981694Sdarrenm 
991694Sdarrenm /*
1001694Sdarrenm  * MD4 initialization. Begins an MD4 operation, writing a new context.
1011694Sdarrenm  */
1021694Sdarrenm void
MD4Init(MD4_CTX * context)1034002Sdarrenm MD4Init(MD4_CTX *context)
1041694Sdarrenm {
1051694Sdarrenm 	context->count[0] = context->count[1] = 0;
1061694Sdarrenm 
1071694Sdarrenm 	/*
1081694Sdarrenm 	 * Load magic initialization constants.
1091694Sdarrenm 	 */
1101694Sdarrenm 	context->state[0] = 0x67452301UL;
1111694Sdarrenm 	context->state[1] = 0xefcdab89UL;
1121694Sdarrenm 	context->state[2] = 0x98badcfeUL;
1131694Sdarrenm 	context->state[3] = 0x10325476UL;
1141694Sdarrenm }
1151694Sdarrenm 
1161694Sdarrenm 
1171694Sdarrenm /*
1181694Sdarrenm  * MD4 block update operation. Continues an MD4 message-digest
1191694Sdarrenm  * operation, processing another message block, and updating the
1201694Sdarrenm  * context.
1211694Sdarrenm  */
1221694Sdarrenm void
MD4Update(MD4_CTX * context,const void * _RESTRICT_KYWD inptr,size_t inputLen)1231694Sdarrenm MD4Update(MD4_CTX *context, const void *_RESTRICT_KYWD inptr, size_t inputLen)
1241694Sdarrenm {
1251694Sdarrenm 	unsigned int i, index, partLen;
1261694Sdarrenm 	uchar_t *input = (uchar_t *)inptr;
1271694Sdarrenm 
1281694Sdarrenm 	/* Compute number of bytes mod 64 */
1291694Sdarrenm 	index = (unsigned int)((context->count[0] >> 3) & 0x3F);
1301694Sdarrenm 	/* Update number of bits */
1314002Sdarrenm 	if ((context->count[0] += ((uint32_t)inputLen << 3))
1324002Sdarrenm 	    < ((uint32_t)inputLen << 3))
1331694Sdarrenm 		context->count[1]++;
1344002Sdarrenm 	context->count[1] += ((uint32_t)inputLen >> 29);
1351694Sdarrenm 
1361694Sdarrenm 	partLen = 64 - index;
1371694Sdarrenm 
1381694Sdarrenm 	/*
1391694Sdarrenm 	 * Transform as many times as possible.
1401694Sdarrenm 	 */
1411694Sdarrenm 	if (inputLen >= partLen) {
1421694Sdarrenm 		bcopy(input, &context->buffer[index], partLen);
1431694Sdarrenm 		MD4Transform(context->state, (uchar_t *)context->buffer);
1441694Sdarrenm 
1451694Sdarrenm 		for (i = partLen; i + 63 < inputLen; i += 64) {
1461694Sdarrenm 			MD4Transform(context->state, (uchar_t *)&input[i]);
1471694Sdarrenm 		}
1481694Sdarrenm 
1491694Sdarrenm 		index = 0;
1501694Sdarrenm 	} else {
1511694Sdarrenm 		i = 0;
1521694Sdarrenm 	}
1531694Sdarrenm 
1541694Sdarrenm 	/* Buffer remaining input */
1551694Sdarrenm 	bcopy(&input[i], &context->buffer[index], inputLen - i);
1561694Sdarrenm }
1571694Sdarrenm 
1581694Sdarrenm /*
1591694Sdarrenm  * MD4 finalization. Ends an MD4 message-digest operation, writing the
1601694Sdarrenm  *	the message digest and zeroizing the context.
1611694Sdarrenm  */
1621694Sdarrenm void
MD4Final(void * digest,MD4_CTX * context)1631694Sdarrenm MD4Final(void *digest, MD4_CTX *context)
1641694Sdarrenm {
1651694Sdarrenm 	unsigned char bits[8];
1661694Sdarrenm 	unsigned int index, padLen;
1671694Sdarrenm 
1681694Sdarrenm 	/* Save number of bits */
1691694Sdarrenm 	Encode(bits, context->count, 8);
1701694Sdarrenm 
1711694Sdarrenm 	/*
1721694Sdarrenm 	 * Pad out to 56 mod 64.
1731694Sdarrenm 	 */
1741694Sdarrenm 	index = (unsigned int)((context->count[0] >> 3) & 0x3f);
1751694Sdarrenm 	padLen = (index < 56) ? (56 - index) : (120 - index);
1761694Sdarrenm 	MD4Update(context, PADDING, padLen);
1771694Sdarrenm 
1781694Sdarrenm 	/* Append length (before padding) */
1791694Sdarrenm 	MD4Update(context, bits, 8);
1801694Sdarrenm 	/* Store state in digest */
1811694Sdarrenm 	Encode(digest, context->state, 16);
1821694Sdarrenm 
1831694Sdarrenm 	/* zeroize sensitive information */
1841694Sdarrenm 	bzero(context, sizeof (*context));
1851694Sdarrenm }
1861694Sdarrenm 
1871694Sdarrenm /*
1881694Sdarrenm  * MD4 basic transformation. Transforms state based on block.
1891694Sdarrenm  */
1901694Sdarrenm static void
MD4Transform(uint32_t state[4],unsigned char block[64])1914002Sdarrenm MD4Transform(uint32_t state[4], unsigned char block[64])
1921694Sdarrenm {
1934002Sdarrenm 	uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
1941694Sdarrenm 
1951694Sdarrenm 
1961694Sdarrenm 	Decode(x, block, 64);
1971694Sdarrenm 
1981694Sdarrenm 	/* Round 1 */
1991694Sdarrenm 	FF(a, b, c, d, x[ 0], S11); /* 1 */
2001694Sdarrenm 	FF(d, a, b, c, x[ 1], S12); /* 2 */
2011694Sdarrenm 	FF(c, d, a, b, x[ 2], S13); /* 3 */
2021694Sdarrenm 	FF(b, c, d, a, x[ 3], S14); /* 4 */
2031694Sdarrenm 	FF(a, b, c, d, x[ 4], S11); /* 5 */
2041694Sdarrenm 	FF(d, a, b, c, x[ 5], S12); /* 6 */
2051694Sdarrenm 	FF(c, d, a, b, x[ 6], S13); /* 7 */
2061694Sdarrenm 	FF(b, c, d, a, x[ 7], S14); /* 8 */
2071694Sdarrenm 	FF(a, b, c, d, x[ 8], S11); /* 9 */
2081694Sdarrenm 	FF(d, a, b, c, x[ 9], S12); /* 10 */
2091694Sdarrenm 	FF(c, d, a, b, x[10], S13); /* 11 */
2101694Sdarrenm 	FF(b, c, d, a, x[11], S14); /* 12 */
2111694Sdarrenm 	FF(a, b, c, d, x[12], S11); /* 13 */
2121694Sdarrenm 	FF(d, a, b, c, x[13], S12); /* 14 */
2131694Sdarrenm 	FF(c, d, a, b, x[14], S13); /* 15 */
2141694Sdarrenm 	FF(b, c, d, a, x[15], S14); /* 16 */
2151694Sdarrenm 
2161694Sdarrenm 	/* Round 2 */
2171694Sdarrenm 	GG(a, b, c, d, x[ 0], S21); /* 17 */
2181694Sdarrenm 	GG(d, a, b, c, x[ 4], S22); /* 18 */
2191694Sdarrenm 	GG(c, d, a, b, x[ 8], S23); /* 19 */
2201694Sdarrenm 	GG(b, c, d, a, x[12], S24); /* 20 */
2211694Sdarrenm 	GG(a, b, c, d, x[ 1], S21); /* 21 */
2221694Sdarrenm 	GG(d, a, b, c, x[ 5], S22); /* 22 */
2231694Sdarrenm 	GG(c, d, a, b, x[ 9], S23); /* 23 */
2241694Sdarrenm 	GG(b, c, d, a, x[13], S24); /* 24 */
2251694Sdarrenm 	GG(a, b, c, d, x[ 2], S21); /* 25 */
2261694Sdarrenm 	GG(d, a, b, c, x[ 6], S22); /* 26 */
2271694Sdarrenm 	GG(c, d, a, b, x[10], S23); /* 27 */
2281694Sdarrenm 	GG(b, c, d, a, x[14], S24); /* 28 */
2291694Sdarrenm 	GG(a, b, c, d, x[ 3], S21); /* 29 */
2301694Sdarrenm 	GG(d, a, b, c, x[ 7], S22); /* 30 */
2311694Sdarrenm 	GG(c, d, a, b, x[11], S23); /* 31 */
2321694Sdarrenm 	GG(b, c, d, a, x[15], S24); /* 32 */
2331694Sdarrenm 
2341694Sdarrenm 
2351694Sdarrenm 	/* Round 3 */
2361694Sdarrenm 	HH(a, b, c, d, x[ 0], S31); /* 33 */
2371694Sdarrenm 	HH(d, a, b, c, x[ 8], S32); /* 34 */
2381694Sdarrenm 	HH(c, d, a, b, x[ 4], S33); /* 35 */
2391694Sdarrenm 	HH(b, c, d, a, x[12], S34); /* 36 */
2401694Sdarrenm 	HH(a, b, c, d, x[ 2], S31); /* 37 */
2411694Sdarrenm 	HH(d, a, b, c, x[10], S32); /* 38 */
2421694Sdarrenm 	HH(c, d, a, b, x[ 6], S33); /* 39 */
2431694Sdarrenm 	HH(b, c, d, a, x[14], S34); /* 40 */
2441694Sdarrenm 	HH(a, b, c, d, x[ 1], S31); /* 41 */
2451694Sdarrenm 	HH(d, a, b, c, x[ 9], S32); /* 42 */
2461694Sdarrenm 	HH(c, d, a, b, x[ 5], S33); /* 43 */
2471694Sdarrenm 	HH(b, c, d, a, x[13], S34); /* 44 */
2481694Sdarrenm 	HH(a, b, c, d, x[ 3], S31); /* 45 */
2491694Sdarrenm 	HH(d, a, b, c, x[11], S32); /* 46 */
2501694Sdarrenm 	HH(c, d, a, b, x[ 7], S33); /* 47 */
2511694Sdarrenm 	HH(b, c, d, a, x[15], S34); /* 48 */
2521694Sdarrenm 
2531694Sdarrenm 	state[0] += a;
2541694Sdarrenm 	state[1] += b;
2551694Sdarrenm 	state[2] += c;
2561694Sdarrenm 	state[3] += d;
2571694Sdarrenm 
2581694Sdarrenm 	/* zeroize sensitive information */
2591694Sdarrenm 	bzero(x, sizeof (*x));
2601694Sdarrenm }
2611694Sdarrenm 
2621694Sdarrenm /*
2634002Sdarrenm  * Encodes input (uint32_t) into output (unsigned char). Assumes len is
2641694Sdarrenm  * a multiple of 4.
2651694Sdarrenm  */
2661694Sdarrenm static void
Encode(unsigned char * output,uint32_t * input,unsigned int len)2677421SDaniel.Anderson@Sun.COM Encode(unsigned char *output, uint32_t *input, unsigned int len)
2681694Sdarrenm {
2691694Sdarrenm 	unsigned int i, j;
2701694Sdarrenm 
2711694Sdarrenm 	for (i = 0, j = 0; j < len; i++, j += 4) {
2727421SDaniel.Anderson@Sun.COM #if defined(_LITTLE_ENDIAN) && defined(UNALIGNED_POINTERS_PERMITTED)
273*7434SDaniel.Anderson@Sun.COM 		*(uint32_t *)(void *)&output[j] = input[i];
2747421SDaniel.Anderson@Sun.COM #else
2757421SDaniel.Anderson@Sun.COM 		/* endian-independent code */
2761694Sdarrenm 		output[j] = (unsigned char)(input[i] & 0xff);
2771694Sdarrenm 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
2781694Sdarrenm 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
2791694Sdarrenm 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
2807421SDaniel.Anderson@Sun.COM #endif	/* _LITTLE_ENDIAN && UNALIGNED_POINTERS_PERMITTED */
2811694Sdarrenm 	}
2821694Sdarrenm }
2831694Sdarrenm 
2841694Sdarrenm /*
2854002Sdarrenm  * Decodes input (unsigned char) into output (uint32_t). Assumes len is
2861694Sdarrenm  * a multiple of 4.
2871694Sdarrenm  */
2881694Sdarrenm static void
Decode(uint32_t * output,unsigned char * input,unsigned int len)2897421SDaniel.Anderson@Sun.COM Decode(uint32_t *output, unsigned char *input, unsigned int len)
2901694Sdarrenm {
2911694Sdarrenm 	unsigned int i, j;
2921694Sdarrenm 
2937421SDaniel.Anderson@Sun.COM 	for (i = 0, j = 0; j < len; i++, j += 4) {
2947421SDaniel.Anderson@Sun.COM #if defined(_LITTLE_ENDIAN) && defined(UNALIGNED_POINTERS_PERMITTED)
295*7434SDaniel.Anderson@Sun.COM 		output[i] = *(uint32_t *)(void *)&input[j];
2967421SDaniel.Anderson@Sun.COM #else
2977421SDaniel.Anderson@Sun.COM 		/* endian-independent code */
2984002Sdarrenm 		output[i] = ((uint32_t)input[j]) |
2997421SDaniel.Anderson@Sun.COM 		    (((uint32_t)input[j+1]) << 8) |
3007421SDaniel.Anderson@Sun.COM 		    (((uint32_t)input[j+2]) << 16) |
3017421SDaniel.Anderson@Sun.COM 		    (((uint32_t)input[j+3]) << 24);
3027421SDaniel.Anderson@Sun.COM #endif	/* _LITTLE_ENDIAN && UNALIGNED_POINTERS_PERMITTED */
3037421SDaniel.Anderson@Sun.COM 	}
3047421SDaniel.Anderson@Sun.COM 
3051694Sdarrenm }
306