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