I'm confused by one line of code in an implementation of MD5,
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
MD5_u32plus saved_lo;
unsigned long used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo size) & 0x1fffffff) < saved_lo)
ctx->hi ;
ctx->hi = size >> 29;
used = saved_lo & 0x3f;
if (used)
{
available = 64 - used;
if (size < available)
{
memcpy(&ctx->buffer[used], data, size);
return;
}
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char *)data available;
size -= available;
body(ctx, ctx->buffer, 64);
}
if (size >= 64)
{
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
memcpy(ctx->buffer, data, size);
}
The question line is if ((ctx->lo = (saved_lo size) & 0x1fffffff) < saved_lo)
, it seems the 'size' counts bytes, but the 'ctx->lo' and 'saved_lo' count bits. Why add them together? There are also some similar codes in Github, and also some projects use these code. So anyone can give some explanation?
CodePudding user response:
The remarks about "bit counters" are likely misleading - ctx->hi
and ctx->lo
count bytes, just like size
does.
You correctly notice that you're just adding size
(bytes) to ctx->lo
(and then checking for overflow/propagating overflow into ctx->hi
). The overflow check is pretty simple - lo
is used as a 29-bit integer, and if the result after adding/masking is less than the original value, then overflow occurred.
The checks around used
are also evidence for ctx->lo
and ctx->hi
being byte counters -- body
processes data 64 bytes at a time, and the lo
counter is ANDed with 0x3F
(i.e. 63).