[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug in md5.c for glibc 2.2.1 through 2.2.4?
From: |
Eric Sharkey |
Subject: |
bug in md5.c for glibc 2.2.1 through 2.2.4? |
Date: |
Wed, 19 Sep 2001 17:19:52 -0400 |
Hi,
I'm having a problem using the md5sum code in md5.c when processing data
in odd-sized chunks. It appears to be a potentially serious bug in
md5_process_bytes which can cause bytes to be processed out of order.
Imagine passing in a block of 1 byte, followed by the remainder of your
data in another block, which we'll assume is large. The first byte won't be
processed immediately, it will just be dumped into the ctx->buffer.
When the next block is processed, 124 bytes will be moved out of the
input buffer, into the ctx->buffer, 64 bytes will then be processed from
this buffer, leaving 1+124-64=61 bytes in the ctx->buffer.
However, at this point, the input buffer is advanced 124 bytes and processed
in 64 byte chunks, even though there are 61 bytes left in ctx->buffer which
have not yet been processed. These 61 bytes won't get processed until
md5_finish_ctx is called.
What md5_process_bytes needs to do is ensure that ctx->buffer is empty
before proceeding with the remainder of the input.
The version below accomplishes this. I've tested this on both i386/Gnu/Linux
and UltraSparc/Solaris and it works correctly in both cases.
Eric Sharkey
<address@hidden>
<address@hidden>
------- cut here --------------
void
md5_process_bytes (buffer, len, ctx)
const void *buffer;
size_t len;
struct md5_ctx *ctx;
{
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
if (ctx->buflen != 0)
{
size_t left_over = ctx->buflen;
size_t add = 128 - left_over > len ? len : 128 - left_over;
memcpy (&ctx->buffer[left_over], buffer, add);
ctx->buflen += add;
if (ctx->buflen > 64)
{
md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
ctx->buflen &= 63;
/* The regions in the following copy operation cannot overlap. */
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
ctx->buflen);
}
buffer = (const char *) buffer + add;
len -= add;
}
/* Process available complete blocks. */
if (len > 64)
{
/* check to see if we're properly aligned */
if (((unsigned int)buffer)%__alignof__(md5_uint32))
{
while (len > 64)
{
memcpy(ctx->buffer,buffer,64);
md5_process_block (ctx->buffer, 64, ctx);
buffer = (const char *) buffer + 64;
len -= 64;
}
}
else
{
md5_process_block (buffer, len & ~63, ctx);
buffer = (const char *) buffer + (len & ~63);
len &= 63;
}
}
/* Move remaining bytes in internal buffer. */
if (len > 0)
{
size_t left_over = ctx->buflen;
memcpy (&ctx->buffer[left_over], buffer, len);
left_over += len;
if (left_over >= 64)
{
md5_process_block (ctx->buffer, 64, ctx);
left_over -= 64;
memcpy (ctx->buffer, &ctx->buffer[64], left_over);
}
ctx->buflen = left_over;
}
}
- bug in md5.c for glibc 2.2.1 through 2.2.4?,
Eric Sharkey <=