xref: /netbsd-src/external/bsd/wpa/dist/src/crypto/md4-internal.c (revision 3d6c0713cbbf51a549dcd172f2c1ea93f7781249)
18dbcf02cSchristos /*
28dbcf02cSchristos  * MD4 hash implementation
38dbcf02cSchristos  * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos  *
5e604d861Schristos  * This software may be distributed under the terms of the BSD license.
6e604d861Schristos  * See README for more details.
78dbcf02cSchristos  */
88dbcf02cSchristos 
98dbcf02cSchristos #include "includes.h"
108dbcf02cSchristos 
118dbcf02cSchristos #include "common.h"
128dbcf02cSchristos #include "crypto.h"
138dbcf02cSchristos 
148dbcf02cSchristos #define	MD4_BLOCK_LENGTH		64
158dbcf02cSchristos #define	MD4_DIGEST_LENGTH		16
168dbcf02cSchristos 
178dbcf02cSchristos typedef struct MD4Context {
188dbcf02cSchristos 	u32 state[4];			/* state */
198dbcf02cSchristos 	u64 count;			/* number of bits, mod 2^64 */
208dbcf02cSchristos 	u8 buffer[MD4_BLOCK_LENGTH];	/* input buffer */
218dbcf02cSchristos } MD4_CTX;
228dbcf02cSchristos 
238dbcf02cSchristos 
248dbcf02cSchristos static void MD4Init(MD4_CTX *ctx);
258dbcf02cSchristos static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len);
268dbcf02cSchristos static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx);
278dbcf02cSchristos 
288dbcf02cSchristos 
md4_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)298dbcf02cSchristos int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
308dbcf02cSchristos {
318dbcf02cSchristos 	MD4_CTX ctx;
328dbcf02cSchristos 	size_t i;
338dbcf02cSchristos 
3436ebd06eSchristos 	if (TEST_FAIL())
3536ebd06eSchristos 		return -1;
3636ebd06eSchristos 
378dbcf02cSchristos 	MD4Init(&ctx);
388dbcf02cSchristos 	for (i = 0; i < num_elem; i++)
398dbcf02cSchristos 		MD4Update(&ctx, addr[i], len[i]);
408dbcf02cSchristos 	MD4Final(mac, &ctx);
418dbcf02cSchristos 	return 0;
428dbcf02cSchristos }
438dbcf02cSchristos 
448dbcf02cSchristos 
458dbcf02cSchristos /* ===== start - public domain MD4 implementation ===== */
468dbcf02cSchristos /*	$OpenBSD: md4.c,v 1.7 2005/08/08 08:05:35 espie Exp $	*/
478dbcf02cSchristos 
488dbcf02cSchristos /*
498dbcf02cSchristos  * This code implements the MD4 message-digest algorithm.
508dbcf02cSchristos  * The algorithm is due to Ron Rivest.	This code was
518dbcf02cSchristos  * written by Colin Plumb in 1993, no copyright is claimed.
528dbcf02cSchristos  * This code is in the public domain; do with it what you wish.
538dbcf02cSchristos  * Todd C. Miller modified the MD5 code to do MD4 based on RFC 1186.
548dbcf02cSchristos  *
558dbcf02cSchristos  * Equivalent code is available from RSA Data Security, Inc.
568dbcf02cSchristos  * This code has been tested against that, and is equivalent,
578dbcf02cSchristos  * except that you don't need to include two pages of legalese
588dbcf02cSchristos  * with every copy.
598dbcf02cSchristos  *
608dbcf02cSchristos  * To compute the message digest of a chunk of bytes, declare an
618dbcf02cSchristos  * MD4Context structure, pass it to MD4Init, call MD4Update as
628dbcf02cSchristos  * needed on buffers full of bytes, and then call MD4Final, which
638dbcf02cSchristos  * will fill a supplied 16-byte array with the digest.
648dbcf02cSchristos  */
658dbcf02cSchristos 
668dbcf02cSchristos #define	MD4_DIGEST_STRING_LENGTH	(MD4_DIGEST_LENGTH * 2 + 1)
678dbcf02cSchristos 
688dbcf02cSchristos 
698dbcf02cSchristos static void
708dbcf02cSchristos MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]);
718dbcf02cSchristos 
728dbcf02cSchristos #define PUT_64BIT_LE(cp, value) do {					\
738dbcf02cSchristos 	(cp)[7] = (value) >> 56;					\
748dbcf02cSchristos 	(cp)[6] = (value) >> 48;					\
758dbcf02cSchristos 	(cp)[5] = (value) >> 40;					\
768dbcf02cSchristos 	(cp)[4] = (value) >> 32;					\
778dbcf02cSchristos 	(cp)[3] = (value) >> 24;					\
788dbcf02cSchristos 	(cp)[2] = (value) >> 16;					\
798dbcf02cSchristos 	(cp)[1] = (value) >> 8;						\
808dbcf02cSchristos 	(cp)[0] = (value); } while (0)
818dbcf02cSchristos 
828dbcf02cSchristos #define PUT_32BIT_LE(cp, value) do {					\
838dbcf02cSchristos 	(cp)[3] = (value) >> 24;					\
848dbcf02cSchristos 	(cp)[2] = (value) >> 16;					\
858dbcf02cSchristos 	(cp)[1] = (value) >> 8;						\
868dbcf02cSchristos 	(cp)[0] = (value); } while (0)
878dbcf02cSchristos 
88*3d6c0713Schristos static const u8 PADDING[MD4_BLOCK_LENGTH] = {
898dbcf02cSchristos 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
908dbcf02cSchristos 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
918dbcf02cSchristos 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
928dbcf02cSchristos };
938dbcf02cSchristos 
948dbcf02cSchristos /*
958dbcf02cSchristos  * Start MD4 accumulation.
968dbcf02cSchristos  * Set bit count to 0 and buffer to mysterious initialization constants.
978dbcf02cSchristos  */
MD4Init(MD4_CTX * ctx)988dbcf02cSchristos static void MD4Init(MD4_CTX *ctx)
998dbcf02cSchristos {
1008dbcf02cSchristos 	ctx->count = 0;
1018dbcf02cSchristos 	ctx->state[0] = 0x67452301;
1028dbcf02cSchristos 	ctx->state[1] = 0xefcdab89;
1038dbcf02cSchristos 	ctx->state[2] = 0x98badcfe;
1048dbcf02cSchristos 	ctx->state[3] = 0x10325476;
1058dbcf02cSchristos }
1068dbcf02cSchristos 
1078dbcf02cSchristos /*
1088dbcf02cSchristos  * Update context to reflect the concatenation of another buffer full
1098dbcf02cSchristos  * of bytes.
1108dbcf02cSchristos  */
MD4Update(MD4_CTX * ctx,const unsigned char * input,size_t len)1118dbcf02cSchristos static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len)
1128dbcf02cSchristos {
1138dbcf02cSchristos 	size_t have, need;
1148dbcf02cSchristos 
1158dbcf02cSchristos 	/* Check how many bytes we already have and how many more we need. */
1168dbcf02cSchristos 	have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
1178dbcf02cSchristos 	need = MD4_BLOCK_LENGTH - have;
1188dbcf02cSchristos 
1198dbcf02cSchristos 	/* Update bitcount */
1208dbcf02cSchristos 	ctx->count += (u64)len << 3;
1218dbcf02cSchristos 
1228dbcf02cSchristos 	if (len >= need) {
1238dbcf02cSchristos 		if (have != 0) {
1248dbcf02cSchristos 			os_memcpy(ctx->buffer + have, input, need);
1258dbcf02cSchristos 			MD4Transform(ctx->state, ctx->buffer);
1268dbcf02cSchristos 			input += need;
1278dbcf02cSchristos 			len -= need;
1288dbcf02cSchristos 			have = 0;
1298dbcf02cSchristos 		}
1308dbcf02cSchristos 
1318dbcf02cSchristos 		/* Process data in MD4_BLOCK_LENGTH-byte chunks. */
1328dbcf02cSchristos 		while (len >= MD4_BLOCK_LENGTH) {
1338dbcf02cSchristos 			MD4Transform(ctx->state, input);
1348dbcf02cSchristos 			input += MD4_BLOCK_LENGTH;
1358dbcf02cSchristos 			len -= MD4_BLOCK_LENGTH;
1368dbcf02cSchristos 		}
1378dbcf02cSchristos 	}
1388dbcf02cSchristos 
1398dbcf02cSchristos 	/* Handle any remaining bytes of data. */
1408dbcf02cSchristos 	if (len != 0)
1418dbcf02cSchristos 		os_memcpy(ctx->buffer + have, input, len);
1428dbcf02cSchristos }
1438dbcf02cSchristos 
1448dbcf02cSchristos /*
1458dbcf02cSchristos  * Pad pad to 64-byte boundary with the bit pattern
1468dbcf02cSchristos  * 1 0* (64-bit count of bits processed, MSB-first)
1478dbcf02cSchristos  */
MD4Pad(MD4_CTX * ctx)1488dbcf02cSchristos static void MD4Pad(MD4_CTX *ctx)
1498dbcf02cSchristos {
1508dbcf02cSchristos 	u8 count[8];
1518dbcf02cSchristos 	size_t padlen;
1528dbcf02cSchristos 
1538dbcf02cSchristos 	/* Convert count to 8 bytes in little endian order. */
1548dbcf02cSchristos 	PUT_64BIT_LE(count, ctx->count);
1558dbcf02cSchristos 
1568dbcf02cSchristos 	/* Pad out to 56 mod 64. */
1578dbcf02cSchristos 	padlen = MD4_BLOCK_LENGTH -
1588dbcf02cSchristos 	    ((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
1598dbcf02cSchristos 	if (padlen < 1 + 8)
1608dbcf02cSchristos 		padlen += MD4_BLOCK_LENGTH;
1618dbcf02cSchristos 	MD4Update(ctx, PADDING, padlen - 8);		/* padlen - 8 <= 64 */
1628dbcf02cSchristos 	MD4Update(ctx, count, 8);
1638dbcf02cSchristos }
1648dbcf02cSchristos 
1658dbcf02cSchristos /*
1668dbcf02cSchristos  * Final wrapup--call MD4Pad, fill in digest and zero out ctx.
1678dbcf02cSchristos  */
MD4Final(unsigned char digest[MD4_DIGEST_LENGTH],MD4_CTX * ctx)1688dbcf02cSchristos static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx)
1698dbcf02cSchristos {
1708dbcf02cSchristos 	int i;
1718dbcf02cSchristos 
1728dbcf02cSchristos 	MD4Pad(ctx);
1738dbcf02cSchristos 	if (digest != NULL) {
1748dbcf02cSchristos 		for (i = 0; i < 4; i++)
1758dbcf02cSchristos 			PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
1768dbcf02cSchristos 		os_memset(ctx, 0, sizeof(*ctx));
1778dbcf02cSchristos 	}
1788dbcf02cSchristos }
1798dbcf02cSchristos 
1808dbcf02cSchristos 
1818dbcf02cSchristos /* The three core functions - F1 is optimized somewhat */
1828dbcf02cSchristos 
1838dbcf02cSchristos /* #define F1(x, y, z) (x & y | ~x & z) */
1848dbcf02cSchristos #define F1(x, y, z) (z ^ (x & (y ^ z)))
1858dbcf02cSchristos #define F2(x, y, z) ((x & y) | (x & z) | (y & z))
1868dbcf02cSchristos #define F3(x, y, z) (x ^ y ^ z)
1878dbcf02cSchristos 
1888dbcf02cSchristos /* This is the central step in the MD4 algorithm. */
1898dbcf02cSchristos #define MD4STEP(f, w, x, y, z, data, s) \
1908dbcf02cSchristos 	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s) )
1918dbcf02cSchristos 
1928dbcf02cSchristos /*
1938dbcf02cSchristos  * The core of the MD4 algorithm, this alters an existing MD4 hash to
1948dbcf02cSchristos  * reflect the addition of 16 longwords of new data.  MD4Update blocks
1958dbcf02cSchristos  * the data and converts bytes into longwords for this routine.
1968dbcf02cSchristos  */
1978dbcf02cSchristos static void
MD4Transform(u32 state[4],const u8 block[MD4_BLOCK_LENGTH])1988dbcf02cSchristos MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH])
1998dbcf02cSchristos {
2008dbcf02cSchristos 	u32 a, b, c, d, in[MD4_BLOCK_LENGTH / 4];
2018dbcf02cSchristos 
2028dbcf02cSchristos #if BYTE_ORDER == LITTLE_ENDIAN
2038dbcf02cSchristos 	os_memcpy(in, block, sizeof(in));
2048dbcf02cSchristos #else
2058dbcf02cSchristos 	for (a = 0; a < MD4_BLOCK_LENGTH / 4; a++) {
2068dbcf02cSchristos 		in[a] = (u32)(
2078dbcf02cSchristos 		    (u32)(block[a * 4 + 0]) |
2088dbcf02cSchristos 		    (u32)(block[a * 4 + 1]) <<  8 |
2098dbcf02cSchristos 		    (u32)(block[a * 4 + 2]) << 16 |
2108dbcf02cSchristos 		    (u32)(block[a * 4 + 3]) << 24);
2118dbcf02cSchristos 	}
2128dbcf02cSchristos #endif
2138dbcf02cSchristos 
2148dbcf02cSchristos 	a = state[0];
2158dbcf02cSchristos 	b = state[1];
2168dbcf02cSchristos 	c = state[2];
2178dbcf02cSchristos 	d = state[3];
2188dbcf02cSchristos 
2198dbcf02cSchristos 	MD4STEP(F1, a, b, c, d, in[ 0],  3);
2208dbcf02cSchristos 	MD4STEP(F1, d, a, b, c, in[ 1],  7);
2218dbcf02cSchristos 	MD4STEP(F1, c, d, a, b, in[ 2], 11);
2228dbcf02cSchristos 	MD4STEP(F1, b, c, d, a, in[ 3], 19);
2238dbcf02cSchristos 	MD4STEP(F1, a, b, c, d, in[ 4],  3);
2248dbcf02cSchristos 	MD4STEP(F1, d, a, b, c, in[ 5],  7);
2258dbcf02cSchristos 	MD4STEP(F1, c, d, a, b, in[ 6], 11);
2268dbcf02cSchristos 	MD4STEP(F1, b, c, d, a, in[ 7], 19);
2278dbcf02cSchristos 	MD4STEP(F1, a, b, c, d, in[ 8],  3);
2288dbcf02cSchristos 	MD4STEP(F1, d, a, b, c, in[ 9],  7);
2298dbcf02cSchristos 	MD4STEP(F1, c, d, a, b, in[10], 11);
2308dbcf02cSchristos 	MD4STEP(F1, b, c, d, a, in[11], 19);
2318dbcf02cSchristos 	MD4STEP(F1, a, b, c, d, in[12],  3);
2328dbcf02cSchristos 	MD4STEP(F1, d, a, b, c, in[13],  7);
2338dbcf02cSchristos 	MD4STEP(F1, c, d, a, b, in[14], 11);
2348dbcf02cSchristos 	MD4STEP(F1, b, c, d, a, in[15], 19);
2358dbcf02cSchristos 
2368dbcf02cSchristos 	MD4STEP(F2, a, b, c, d, in[ 0] + 0x5a827999,  3);
2378dbcf02cSchristos 	MD4STEP(F2, d, a, b, c, in[ 4] + 0x5a827999,  5);
2388dbcf02cSchristos 	MD4STEP(F2, c, d, a, b, in[ 8] + 0x5a827999,  9);
2398dbcf02cSchristos 	MD4STEP(F2, b, c, d, a, in[12] + 0x5a827999, 13);
2408dbcf02cSchristos 	MD4STEP(F2, a, b, c, d, in[ 1] + 0x5a827999,  3);
2418dbcf02cSchristos 	MD4STEP(F2, d, a, b, c, in[ 5] + 0x5a827999,  5);
2428dbcf02cSchristos 	MD4STEP(F2, c, d, a, b, in[ 9] + 0x5a827999,  9);
2438dbcf02cSchristos 	MD4STEP(F2, b, c, d, a, in[13] + 0x5a827999, 13);
2448dbcf02cSchristos 	MD4STEP(F2, a, b, c, d, in[ 2] + 0x5a827999,  3);
2458dbcf02cSchristos 	MD4STEP(F2, d, a, b, c, in[ 6] + 0x5a827999,  5);
2468dbcf02cSchristos 	MD4STEP(F2, c, d, a, b, in[10] + 0x5a827999,  9);
2478dbcf02cSchristos 	MD4STEP(F2, b, c, d, a, in[14] + 0x5a827999, 13);
2488dbcf02cSchristos 	MD4STEP(F2, a, b, c, d, in[ 3] + 0x5a827999,  3);
2498dbcf02cSchristos 	MD4STEP(F2, d, a, b, c, in[ 7] + 0x5a827999,  5);
2508dbcf02cSchristos 	MD4STEP(F2, c, d, a, b, in[11] + 0x5a827999,  9);
2518dbcf02cSchristos 	MD4STEP(F2, b, c, d, a, in[15] + 0x5a827999, 13);
2528dbcf02cSchristos 
2538dbcf02cSchristos 	MD4STEP(F3, a, b, c, d, in[ 0] + 0x6ed9eba1,  3);
2548dbcf02cSchristos 	MD4STEP(F3, d, a, b, c, in[ 8] + 0x6ed9eba1,  9);
2558dbcf02cSchristos 	MD4STEP(F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11);
2568dbcf02cSchristos 	MD4STEP(F3, b, c, d, a, in[12] + 0x6ed9eba1, 15);
2578dbcf02cSchristos 	MD4STEP(F3, a, b, c, d, in[ 2] + 0x6ed9eba1,  3);
2588dbcf02cSchristos 	MD4STEP(F3, d, a, b, c, in[10] + 0x6ed9eba1,  9);
2598dbcf02cSchristos 	MD4STEP(F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11);
2608dbcf02cSchristos 	MD4STEP(F3, b, c, d, a, in[14] + 0x6ed9eba1, 15);
2618dbcf02cSchristos 	MD4STEP(F3, a, b, c, d, in[ 1] + 0x6ed9eba1,  3);
2628dbcf02cSchristos 	MD4STEP(F3, d, a, b, c, in[ 9] + 0x6ed9eba1,  9);
2638dbcf02cSchristos 	MD4STEP(F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11);
2648dbcf02cSchristos 	MD4STEP(F3, b, c, d, a, in[13] + 0x6ed9eba1, 15);
2658dbcf02cSchristos 	MD4STEP(F3, a, b, c, d, in[ 3] + 0x6ed9eba1,  3);
2668dbcf02cSchristos 	MD4STEP(F3, d, a, b, c, in[11] + 0x6ed9eba1,  9);
2678dbcf02cSchristos 	MD4STEP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11);
2688dbcf02cSchristos 	MD4STEP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15);
2698dbcf02cSchristos 
2708dbcf02cSchristos 	state[0] += a;
2718dbcf02cSchristos 	state[1] += b;
2728dbcf02cSchristos 	state[2] += c;
2738dbcf02cSchristos 	state[3] += d;
2748dbcf02cSchristos }
2758dbcf02cSchristos /* ===== end - public domain MD4 implementation ===== */
276