From 18f22665503cb4161d8c98fbd59dff25dec56347 Mon Sep 17 00:00:00 2001 From: millert <> Date: Thu, 29 Apr 2004 18:45:39 +0000 Subject: [PATCH] Sync with md5.c rev. 1.4 --- src/lib/libc/hash/md4.c | 211 ++++++++++++++++------------------------ 1 file changed, 83 insertions(+), 128 deletions(-) diff --git a/src/lib/libc/hash/md4.c b/src/lib/libc/hash/md4.c index 330343c6..c795722d 100644 --- a/src/lib/libc/hash/md4.c +++ b/src/lib/libc/hash/md4.c @@ -1,4 +1,4 @@ -/* $OpenBSD: md4.c,v 1.2 2004/04/28 20:24:59 millert Exp $ */ +/* $OpenBSD: md4.c,v 1.3 2004/04/29 18:45:39 millert Exp $ */ /* * This code implements the MD4 message-digest algorithm. @@ -19,65 +19,34 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$OpenBSD: md4.c,v 1.2 2004/04/28 20:24:59 millert Exp $"; +static const char rcsid[] = "$OpenBSD: md4.c,v 1.3 2004/04/29 18:45:39 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include #include -#if BYTE_ORDER == LITTLE_ENDIAN - -#define htole32_4(buf) /* Nothing */ -#define htole32_14(buf) /* Nothing */ -#define htole32_16(buf) /* Nothing */ - -#else - -#define htole32_4(buf) do { \ - (buf)[ 0] = htole32((buf)[ 0]); \ - (buf)[ 1] = htole32((buf)[ 1]); \ - (buf)[ 2] = htole32((buf)[ 2]); \ - (buf)[ 3] = htole32((buf)[ 3]); \ -} while (0) - -#define htole32_14(buf) do { \ - (buf)[ 0] = htole32((buf)[ 0]); \ - (buf)[ 1] = htole32((buf)[ 1]); \ - (buf)[ 2] = htole32((buf)[ 2]); \ - (buf)[ 3] = htole32((buf)[ 3]); \ - (buf)[ 4] = htole32((buf)[ 4]); \ - (buf)[ 5] = htole32((buf)[ 5]); \ - (buf)[ 6] = htole32((buf)[ 6]); \ - (buf)[ 7] = htole32((buf)[ 7]); \ - (buf)[ 8] = htole32((buf)[ 8]); \ - (buf)[ 9] = htole32((buf)[ 9]); \ - (buf)[10] = htole32((buf)[10]); \ - (buf)[11] = htole32((buf)[11]); \ - (buf)[12] = htole32((buf)[12]); \ - (buf)[13] = htole32((buf)[13]); \ -} while (0) - -#define htole32_16(buf) do { \ - (buf)[ 0] = htole32((buf)[ 0]); \ - (buf)[ 1] = htole32((buf)[ 1]); \ - (buf)[ 2] = htole32((buf)[ 2]); \ - (buf)[ 3] = htole32((buf)[ 3]); \ - (buf)[ 4] = htole32((buf)[ 4]); \ - (buf)[ 5] = htole32((buf)[ 5]); \ - (buf)[ 6] = htole32((buf)[ 6]); \ - (buf)[ 7] = htole32((buf)[ 7]); \ - (buf)[ 8] = htole32((buf)[ 8]); \ - (buf)[ 9] = htole32((buf)[ 9]); \ - (buf)[10] = htole32((buf)[10]); \ - (buf)[11] = htole32((buf)[11]); \ - (buf)[12] = htole32((buf)[12]); \ - (buf)[13] = htole32((buf)[13]); \ - (buf)[14] = htole32((buf)[14]); \ - (buf)[15] = htole32((buf)[15]); \ -} while (0) - -#endif +#define PUT_64BIT_LE(cp, value) do { \ + (cp)[7] = (value) >> 56; \ + (cp)[6] = (value) >> 48; \ + (cp)[5] = (value) >> 40; \ + (cp)[4] = (value) >> 32; \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +#define PUT_32BIT_LE(cp, value) do { \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +static u_char PADDING[MD4_BLOCK_LENGTH] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; /* * Start MD4 accumulation. @@ -98,43 +67,37 @@ MD4Init(MD4_CTX *ctx) * of bytes. */ void -MD4Update(MD4_CTX *ctx, const unsigned char *buf, size_t len) +MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len) { - u_int32_t count; + u_int32_t have, need; - /* Bytes already stored in ctx->buffer */ - count = (u_int32_t)((ctx->count >> 3) & 0x3f); + /* Check how many bytes we already have and how many more we need. */ + have = (u_int32_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); + need = MD4_BLOCK_LENGTH - have; /* Update bitcount */ ctx->count += (u_int64_t)len << 3; - /* Handle any leading odd-sized chunks */ - if (count) { - unsigned char *p = (unsigned char *)ctx->buffer + count; - - count = MD4_BLOCK_LENGTH - count; - if (len < count) { - memcpy(p, buf, len); - return; + if (len >= need) { + if (have != 0) { + memcpy(ctx->buffer + have, input, need); + MD4Transform(ctx->state, ctx->buffer); + input += need; + len -= need; + have = 0; } - memcpy(p, buf, count); - htole32_16((u_int32_t *)ctx->buffer); - MD4Transform(ctx->state, ctx->buffer); - buf += count; - len -= count; - } - /* Process data in MD4_BLOCK_LENGTH-byte chunks */ - while (len >= MD4_BLOCK_LENGTH) { - memcpy(ctx->buffer, buf, MD4_BLOCK_LENGTH); - htole32_16((u_int32_t *)ctx->buffer); - MD4Transform(ctx->state, ctx->buffer); - buf += MD4_BLOCK_LENGTH; - len -= MD4_BLOCK_LENGTH; + /* Process data in MD4_BLOCK_LENGTH-byte chunks. */ + while (len >= MD4_BLOCK_LENGTH) { + MD4Transform(ctx->state, input); + input += MD4_BLOCK_LENGTH; + len -= MD4_BLOCK_LENGTH; + } } /* Handle any remaining bytes of data. */ - memcpy(ctx->buffer, buf, len); + if (len != 0) + memcpy(ctx->buffer + have, input, len); } /* @@ -144,44 +107,25 @@ MD4Update(MD4_CTX *ctx, const unsigned char *buf, size_t len) void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx) { - u_int32_t count; - unsigned char *p; - - /* number of bytes mod 64 */ - count = (u_int32_t)(ctx->count >> 3) & 0x3f; - - /* - * Set the first char of padding to 0x80. - * This is safe since there is always at least one byte free. - */ - p = ctx->buffer + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - htole32_16((u_int32_t *)ctx->buffer); - MD4Transform(ctx->state, ctx->buffer); - - /* Now fill the next block with 56 bytes */ - memset(ctx->buffer, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); + u_int8_t count[8]; + u_int32_t padlen; + int i; + + /* Convert count to 8 bytes in little endian order. */ + PUT_64BIT_LE(count, ctx->count); + + /* Pad out to 56 mod 64. */ + padlen = MD4_BLOCK_LENGTH - + ((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); + if (padlen < 1 + 8) + padlen += MD4_BLOCK_LENGTH; + MD4Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ + MD4Update(ctx, count, 8); + + if (digest != NULL) { + for (i = 0; i < 4; i++) + PUT_32BIT_LE(digest + i * 4, ctx->state[i]); } - htole32_14((u_int32_t *)ctx->buffer); - - /* Append bit count and transform */ - ((u_int32_t *)ctx->buffer)[14] = ctx->count & 0xffffffff; - ((u_int32_t *)ctx->buffer)[15] = (u_int32_t)(ctx->count >> 32); - - MD4Transform(ctx->state, ctx->buffer); - htole32_4(ctx->state); - memcpy(digest, ctx->state, MD4_DIGEST_LENGTH); memset(ctx, 0, sizeof(*ctx)); /* in case it's sensitive */ } @@ -203,15 +147,26 @@ MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx) * the data and converts bytes into longwords for this routine. */ void -MD4Transform(u_int32_t buf[4], const unsigned char inc[MD4_BLOCK_LENGTH]) +MD4Transform(u_int32_t state[4], const u_int8_t block[MD4_BLOCK_LENGTH]) { - u_int32_t a, b, c, d; - const u_int32_t *in = (const u_int32_t *)inc; + u_int32_t a, b, c, d, in[MD4_BLOCK_LENGTH / 4]; + +#if BYTE_ORDER == LITTLE_ENDIAN + memcpy(in, block, sizeof(in)); +#else + for (a = 0; a < MD4_BLOCK_LENGTH / 4; a++) { + in[a] = (u_int32_t)( + (u_int32_t)(block[a * 4 + 0]) | + (u_int32_t)(block[a * 4 + 1]) << 8 | + (u_int32_t)(block[a * 4 + 2]) << 16 | + (u_int32_t)(block[a * 4 + 3]) << 24); + } +#endif - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; MD4STEP(F1, a, b, c, d, in[ 0], 3); MD4STEP(F1, d, a, b, c, in[ 1], 7); @@ -264,8 +219,8 @@ MD4Transform(u_int32_t buf[4], const unsigned char inc[MD4_BLOCK_LENGTH]) MD4STEP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15); - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; }