bug-glibc
[Top][All Lists]
Advanced

[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;
    }
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]