1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * MD4 hash implementation
3e5b75505Sopenharmony_ci * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci
11e5b75505Sopenharmony_ci#include "common.h"
12e5b75505Sopenharmony_ci#include "crypto.h"
13e5b75505Sopenharmony_ci
14e5b75505Sopenharmony_ci#define	MD4_BLOCK_LENGTH		64
15e5b75505Sopenharmony_ci#define	MD4_DIGEST_LENGTH		16
16e5b75505Sopenharmony_ci
17e5b75505Sopenharmony_citypedef struct MD4Context {
18e5b75505Sopenharmony_ci	u32 state[4];			/* state */
19e5b75505Sopenharmony_ci	u64 count;			/* number of bits, mod 2^64 */
20e5b75505Sopenharmony_ci	u8 buffer[MD4_BLOCK_LENGTH];	/* input buffer */
21e5b75505Sopenharmony_ci} MD4_CTX;
22e5b75505Sopenharmony_ci
23e5b75505Sopenharmony_ci
24e5b75505Sopenharmony_cistatic void MD4Init(MD4_CTX *ctx);
25e5b75505Sopenharmony_cistatic void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len);
26e5b75505Sopenharmony_cistatic void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx);
27e5b75505Sopenharmony_ci
28e5b75505Sopenharmony_ci
29e5b75505Sopenharmony_ciint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
30e5b75505Sopenharmony_ci{
31e5b75505Sopenharmony_ci	MD4_CTX ctx;
32e5b75505Sopenharmony_ci	size_t i;
33e5b75505Sopenharmony_ci
34e5b75505Sopenharmony_ci	if (TEST_FAIL())
35e5b75505Sopenharmony_ci		return -1;
36e5b75505Sopenharmony_ci
37e5b75505Sopenharmony_ci	MD4Init(&ctx);
38e5b75505Sopenharmony_ci	for (i = 0; i < num_elem; i++)
39e5b75505Sopenharmony_ci		MD4Update(&ctx, addr[i], len[i]);
40e5b75505Sopenharmony_ci	MD4Final(mac, &ctx);
41e5b75505Sopenharmony_ci	return 0;
42e5b75505Sopenharmony_ci}
43e5b75505Sopenharmony_ci
44e5b75505Sopenharmony_ci
45e5b75505Sopenharmony_ci/* ===== start - public domain MD4 implementation ===== */
46e5b75505Sopenharmony_ci/*	$OpenBSD: md4.c,v 1.7 2005/08/08 08:05:35 espie Exp $	*/
47e5b75505Sopenharmony_ci
48e5b75505Sopenharmony_ci/*
49e5b75505Sopenharmony_ci * This code implements the MD4 message-digest algorithm.
50e5b75505Sopenharmony_ci * The algorithm is due to Ron Rivest.	This code was
51e5b75505Sopenharmony_ci * written by Colin Plumb in 1993, no copyright is claimed.
52e5b75505Sopenharmony_ci * This code is in the public domain; do with it what you wish.
53e5b75505Sopenharmony_ci * Todd C. Miller modified the MD5 code to do MD4 based on RFC 1186.
54e5b75505Sopenharmony_ci *
55e5b75505Sopenharmony_ci * Equivalent code is available from RSA Data Security, Inc.
56e5b75505Sopenharmony_ci * This code has been tested against that, and is equivalent,
57e5b75505Sopenharmony_ci * except that you don't need to include two pages of legalese
58e5b75505Sopenharmony_ci * with every copy.
59e5b75505Sopenharmony_ci *
60e5b75505Sopenharmony_ci * To compute the message digest of a chunk of bytes, declare an
61e5b75505Sopenharmony_ci * MD4Context structure, pass it to MD4Init, call MD4Update as
62e5b75505Sopenharmony_ci * needed on buffers full of bytes, and then call MD4Final, which
63e5b75505Sopenharmony_ci * will fill a supplied 16-byte array with the digest.
64e5b75505Sopenharmony_ci */
65e5b75505Sopenharmony_ci
66e5b75505Sopenharmony_ci#define	MD4_DIGEST_STRING_LENGTH	(MD4_DIGEST_LENGTH * 2 + 1)
67e5b75505Sopenharmony_ci
68e5b75505Sopenharmony_ci
69e5b75505Sopenharmony_cistatic void
70e5b75505Sopenharmony_ciMD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]);
71e5b75505Sopenharmony_ci
72e5b75505Sopenharmony_ci#define PUT_64BIT_LE(cp, value) do {					\
73e5b75505Sopenharmony_ci	(cp)[7] = (value) >> 56;					\
74e5b75505Sopenharmony_ci	(cp)[6] = (value) >> 48;					\
75e5b75505Sopenharmony_ci	(cp)[5] = (value) >> 40;					\
76e5b75505Sopenharmony_ci	(cp)[4] = (value) >> 32;					\
77e5b75505Sopenharmony_ci	(cp)[3] = (value) >> 24;					\
78e5b75505Sopenharmony_ci	(cp)[2] = (value) >> 16;					\
79e5b75505Sopenharmony_ci	(cp)[1] = (value) >> 8;						\
80e5b75505Sopenharmony_ci	(cp)[0] = (value); } while (0)
81e5b75505Sopenharmony_ci
82e5b75505Sopenharmony_ci#define PUT_32BIT_LE(cp, value) do {					\
83e5b75505Sopenharmony_ci	(cp)[3] = (value) >> 24;					\
84e5b75505Sopenharmony_ci	(cp)[2] = (value) >> 16;					\
85e5b75505Sopenharmony_ci	(cp)[1] = (value) >> 8;						\
86e5b75505Sopenharmony_ci	(cp)[0] = (value); } while (0)
87e5b75505Sopenharmony_ci
88e5b75505Sopenharmony_cistatic const u8 PADDING[MD4_BLOCK_LENGTH] = {
89e5b75505Sopenharmony_ci	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90e5b75505Sopenharmony_ci	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91e5b75505Sopenharmony_ci	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
92e5b75505Sopenharmony_ci};
93e5b75505Sopenharmony_ci
94e5b75505Sopenharmony_ci/*
95e5b75505Sopenharmony_ci * Start MD4 accumulation.
96e5b75505Sopenharmony_ci * Set bit count to 0 and buffer to mysterious initialization constants.
97e5b75505Sopenharmony_ci */
98e5b75505Sopenharmony_cistatic void MD4Init(MD4_CTX *ctx)
99e5b75505Sopenharmony_ci{
100e5b75505Sopenharmony_ci	ctx->count = 0;
101e5b75505Sopenharmony_ci	ctx->state[0] = 0x67452301;
102e5b75505Sopenharmony_ci	ctx->state[1] = 0xefcdab89;
103e5b75505Sopenharmony_ci	ctx->state[2] = 0x98badcfe;
104e5b75505Sopenharmony_ci	ctx->state[3] = 0x10325476;
105e5b75505Sopenharmony_ci}
106e5b75505Sopenharmony_ci
107e5b75505Sopenharmony_ci/*
108e5b75505Sopenharmony_ci * Update context to reflect the concatenation of another buffer full
109e5b75505Sopenharmony_ci * of bytes.
110e5b75505Sopenharmony_ci */
111e5b75505Sopenharmony_cistatic void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len)
112e5b75505Sopenharmony_ci{
113e5b75505Sopenharmony_ci	size_t have, need;
114e5b75505Sopenharmony_ci
115e5b75505Sopenharmony_ci	/* Check how many bytes we already have and how many more we need. */
116e5b75505Sopenharmony_ci	have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
117e5b75505Sopenharmony_ci	need = MD4_BLOCK_LENGTH - have;
118e5b75505Sopenharmony_ci
119e5b75505Sopenharmony_ci	/* Update bitcount */
120e5b75505Sopenharmony_ci	ctx->count += (u64)len << 3;
121e5b75505Sopenharmony_ci
122e5b75505Sopenharmony_ci	if (len >= need) {
123e5b75505Sopenharmony_ci		if (have != 0) {
124e5b75505Sopenharmony_ci			os_memcpy(ctx->buffer + have, input, need);
125e5b75505Sopenharmony_ci			MD4Transform(ctx->state, ctx->buffer);
126e5b75505Sopenharmony_ci			input += need;
127e5b75505Sopenharmony_ci			len -= need;
128e5b75505Sopenharmony_ci			have = 0;
129e5b75505Sopenharmony_ci		}
130e5b75505Sopenharmony_ci
131e5b75505Sopenharmony_ci		/* Process data in MD4_BLOCK_LENGTH-byte chunks. */
132e5b75505Sopenharmony_ci		while (len >= MD4_BLOCK_LENGTH) {
133e5b75505Sopenharmony_ci			MD4Transform(ctx->state, input);
134e5b75505Sopenharmony_ci			input += MD4_BLOCK_LENGTH;
135e5b75505Sopenharmony_ci			len -= MD4_BLOCK_LENGTH;
136e5b75505Sopenharmony_ci		}
137e5b75505Sopenharmony_ci	}
138e5b75505Sopenharmony_ci
139e5b75505Sopenharmony_ci	/* Handle any remaining bytes of data. */
140e5b75505Sopenharmony_ci	if (len != 0)
141e5b75505Sopenharmony_ci		os_memcpy(ctx->buffer + have, input, len);
142e5b75505Sopenharmony_ci}
143e5b75505Sopenharmony_ci
144e5b75505Sopenharmony_ci/*
145e5b75505Sopenharmony_ci * Pad pad to 64-byte boundary with the bit pattern
146e5b75505Sopenharmony_ci * 1 0* (64-bit count of bits processed, MSB-first)
147e5b75505Sopenharmony_ci */
148e5b75505Sopenharmony_cistatic void MD4Pad(MD4_CTX *ctx)
149e5b75505Sopenharmony_ci{
150e5b75505Sopenharmony_ci	u8 count[8];
151e5b75505Sopenharmony_ci	size_t padlen;
152e5b75505Sopenharmony_ci
153e5b75505Sopenharmony_ci	/* Convert count to 8 bytes in little endian order. */
154e5b75505Sopenharmony_ci	PUT_64BIT_LE(count, ctx->count);
155e5b75505Sopenharmony_ci
156e5b75505Sopenharmony_ci	/* Pad out to 56 mod 64. */
157e5b75505Sopenharmony_ci	padlen = MD4_BLOCK_LENGTH -
158e5b75505Sopenharmony_ci	    ((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
159e5b75505Sopenharmony_ci	if (padlen < 1 + 8)
160e5b75505Sopenharmony_ci		padlen += MD4_BLOCK_LENGTH;
161e5b75505Sopenharmony_ci	MD4Update(ctx, PADDING, padlen - 8);		/* padlen - 8 <= 64 */
162e5b75505Sopenharmony_ci	MD4Update(ctx, count, 8);
163e5b75505Sopenharmony_ci}
164e5b75505Sopenharmony_ci
165e5b75505Sopenharmony_ci/*
166e5b75505Sopenharmony_ci * Final wrapup--call MD4Pad, fill in digest and zero out ctx.
167e5b75505Sopenharmony_ci */
168e5b75505Sopenharmony_cistatic void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx)
169e5b75505Sopenharmony_ci{
170e5b75505Sopenharmony_ci	int i;
171e5b75505Sopenharmony_ci
172e5b75505Sopenharmony_ci	MD4Pad(ctx);
173e5b75505Sopenharmony_ci	if (digest != NULL) {
174e5b75505Sopenharmony_ci		for (i = 0; i < 4; i++)
175e5b75505Sopenharmony_ci			PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
176e5b75505Sopenharmony_ci		os_memset(ctx, 0, sizeof(*ctx));
177e5b75505Sopenharmony_ci	}
178e5b75505Sopenharmony_ci}
179e5b75505Sopenharmony_ci
180e5b75505Sopenharmony_ci
181e5b75505Sopenharmony_ci/* The three core functions - F1 is optimized somewhat */
182e5b75505Sopenharmony_ci
183e5b75505Sopenharmony_ci/* #define F1(x, y, z) (x & y | ~x & z) */
184e5b75505Sopenharmony_ci#define F1(x, y, z) (z ^ (x & (y ^ z)))
185e5b75505Sopenharmony_ci#define F2(x, y, z) ((x & y) | (x & z) | (y & z))
186e5b75505Sopenharmony_ci#define F3(x, y, z) (x ^ y ^ z)
187e5b75505Sopenharmony_ci
188e5b75505Sopenharmony_ci/* This is the central step in the MD4 algorithm. */
189e5b75505Sopenharmony_ci#define MD4STEP(f, w, x, y, z, data, s) \
190e5b75505Sopenharmony_ci	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s) )
191e5b75505Sopenharmony_ci
192e5b75505Sopenharmony_ci/*
193e5b75505Sopenharmony_ci * The core of the MD4 algorithm, this alters an existing MD4 hash to
194e5b75505Sopenharmony_ci * reflect the addition of 16 longwords of new data.  MD4Update blocks
195e5b75505Sopenharmony_ci * the data and converts bytes into longwords for this routine.
196e5b75505Sopenharmony_ci */
197e5b75505Sopenharmony_cistatic void
198e5b75505Sopenharmony_ciMD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH])
199e5b75505Sopenharmony_ci{
200e5b75505Sopenharmony_ci	u32 a, b, c, d, in[MD4_BLOCK_LENGTH / 4];
201e5b75505Sopenharmony_ci
202e5b75505Sopenharmony_ci#if BYTE_ORDER == LITTLE_ENDIAN
203e5b75505Sopenharmony_ci	os_memcpy(in, block, sizeof(in));
204e5b75505Sopenharmony_ci#else
205e5b75505Sopenharmony_ci	for (a = 0; a < MD4_BLOCK_LENGTH / 4; a++) {
206e5b75505Sopenharmony_ci		in[a] = (u32)(
207e5b75505Sopenharmony_ci		    (u32)(block[a * 4 + 0]) |
208e5b75505Sopenharmony_ci		    (u32)(block[a * 4 + 1]) <<  8 |
209e5b75505Sopenharmony_ci		    (u32)(block[a * 4 + 2]) << 16 |
210e5b75505Sopenharmony_ci		    (u32)(block[a * 4 + 3]) << 24);
211e5b75505Sopenharmony_ci	}
212e5b75505Sopenharmony_ci#endif
213e5b75505Sopenharmony_ci
214e5b75505Sopenharmony_ci	a = state[0];
215e5b75505Sopenharmony_ci	b = state[1];
216e5b75505Sopenharmony_ci	c = state[2];
217e5b75505Sopenharmony_ci	d = state[3];
218e5b75505Sopenharmony_ci
219e5b75505Sopenharmony_ci	MD4STEP(F1, a, b, c, d, in[ 0],  3);
220e5b75505Sopenharmony_ci	MD4STEP(F1, d, a, b, c, in[ 1],  7);
221e5b75505Sopenharmony_ci	MD4STEP(F1, c, d, a, b, in[ 2], 11);
222e5b75505Sopenharmony_ci	MD4STEP(F1, b, c, d, a, in[ 3], 19);
223e5b75505Sopenharmony_ci	MD4STEP(F1, a, b, c, d, in[ 4],  3);
224e5b75505Sopenharmony_ci	MD4STEP(F1, d, a, b, c, in[ 5],  7);
225e5b75505Sopenharmony_ci	MD4STEP(F1, c, d, a, b, in[ 6], 11);
226e5b75505Sopenharmony_ci	MD4STEP(F1, b, c, d, a, in[ 7], 19);
227e5b75505Sopenharmony_ci	MD4STEP(F1, a, b, c, d, in[ 8],  3);
228e5b75505Sopenharmony_ci	MD4STEP(F1, d, a, b, c, in[ 9],  7);
229e5b75505Sopenharmony_ci	MD4STEP(F1, c, d, a, b, in[10], 11);
230e5b75505Sopenharmony_ci	MD4STEP(F1, b, c, d, a, in[11], 19);
231e5b75505Sopenharmony_ci	MD4STEP(F1, a, b, c, d, in[12],  3);
232e5b75505Sopenharmony_ci	MD4STEP(F1, d, a, b, c, in[13],  7);
233e5b75505Sopenharmony_ci	MD4STEP(F1, c, d, a, b, in[14], 11);
234e5b75505Sopenharmony_ci	MD4STEP(F1, b, c, d, a, in[15], 19);
235e5b75505Sopenharmony_ci
236e5b75505Sopenharmony_ci	MD4STEP(F2, a, b, c, d, in[ 0] + 0x5a827999,  3);
237e5b75505Sopenharmony_ci	MD4STEP(F2, d, a, b, c, in[ 4] + 0x5a827999,  5);
238e5b75505Sopenharmony_ci	MD4STEP(F2, c, d, a, b, in[ 8] + 0x5a827999,  9);
239e5b75505Sopenharmony_ci	MD4STEP(F2, b, c, d, a, in[12] + 0x5a827999, 13);
240e5b75505Sopenharmony_ci	MD4STEP(F2, a, b, c, d, in[ 1] + 0x5a827999,  3);
241e5b75505Sopenharmony_ci	MD4STEP(F2, d, a, b, c, in[ 5] + 0x5a827999,  5);
242e5b75505Sopenharmony_ci	MD4STEP(F2, c, d, a, b, in[ 9] + 0x5a827999,  9);
243e5b75505Sopenharmony_ci	MD4STEP(F2, b, c, d, a, in[13] + 0x5a827999, 13);
244e5b75505Sopenharmony_ci	MD4STEP(F2, a, b, c, d, in[ 2] + 0x5a827999,  3);
245e5b75505Sopenharmony_ci	MD4STEP(F2, d, a, b, c, in[ 6] + 0x5a827999,  5);
246e5b75505Sopenharmony_ci	MD4STEP(F2, c, d, a, b, in[10] + 0x5a827999,  9);
247e5b75505Sopenharmony_ci	MD4STEP(F2, b, c, d, a, in[14] + 0x5a827999, 13);
248e5b75505Sopenharmony_ci	MD4STEP(F2, a, b, c, d, in[ 3] + 0x5a827999,  3);
249e5b75505Sopenharmony_ci	MD4STEP(F2, d, a, b, c, in[ 7] + 0x5a827999,  5);
250e5b75505Sopenharmony_ci	MD4STEP(F2, c, d, a, b, in[11] + 0x5a827999,  9);
251e5b75505Sopenharmony_ci	MD4STEP(F2, b, c, d, a, in[15] + 0x5a827999, 13);
252e5b75505Sopenharmony_ci
253e5b75505Sopenharmony_ci	MD4STEP(F3, a, b, c, d, in[ 0] + 0x6ed9eba1,  3);
254e5b75505Sopenharmony_ci	MD4STEP(F3, d, a, b, c, in[ 8] + 0x6ed9eba1,  9);
255e5b75505Sopenharmony_ci	MD4STEP(F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11);
256e5b75505Sopenharmony_ci	MD4STEP(F3, b, c, d, a, in[12] + 0x6ed9eba1, 15);
257e5b75505Sopenharmony_ci	MD4STEP(F3, a, b, c, d, in[ 2] + 0x6ed9eba1,  3);
258e5b75505Sopenharmony_ci	MD4STEP(F3, d, a, b, c, in[10] + 0x6ed9eba1,  9);
259e5b75505Sopenharmony_ci	MD4STEP(F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11);
260e5b75505Sopenharmony_ci	MD4STEP(F3, b, c, d, a, in[14] + 0x6ed9eba1, 15);
261e5b75505Sopenharmony_ci	MD4STEP(F3, a, b, c, d, in[ 1] + 0x6ed9eba1,  3);
262e5b75505Sopenharmony_ci	MD4STEP(F3, d, a, b, c, in[ 9] + 0x6ed9eba1,  9);
263e5b75505Sopenharmony_ci	MD4STEP(F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11);
264e5b75505Sopenharmony_ci	MD4STEP(F3, b, c, d, a, in[13] + 0x6ed9eba1, 15);
265e5b75505Sopenharmony_ci	MD4STEP(F3, a, b, c, d, in[ 3] + 0x6ed9eba1,  3);
266e5b75505Sopenharmony_ci	MD4STEP(F3, d, a, b, c, in[11] + 0x6ed9eba1,  9);
267e5b75505Sopenharmony_ci	MD4STEP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11);
268e5b75505Sopenharmony_ci	MD4STEP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15);
269e5b75505Sopenharmony_ci
270e5b75505Sopenharmony_ci	state[0] += a;
271e5b75505Sopenharmony_ci	state[1] += b;
272e5b75505Sopenharmony_ci	state[2] += c;
273e5b75505Sopenharmony_ci	state[3] += d;
274e5b75505Sopenharmony_ci}
275e5b75505Sopenharmony_ci/* ===== end - public domain MD4 implementation ===== */
276