From fc1ae6582fa5e199cc9c50dc2297297c1893955c Mon Sep 17 00:00:00 2001 From: "J.W. Schultz" Date: Thu, 10 Apr 2003 01:50:12 +0000 Subject: [PATCH] - for protocol version >= 27, mdfour_tail() is called when the block size (including checksum_seed) is a multiple of 64. Previously it was not called, giving the wrong MD4 checksum. - for protocol version >= 27, a 64 bit bit counter is used in mdfour.c as required by the RFC. Previously only a 32 bit bit counter was used, causing incorrect MD4 file checksums for file sizes >= 512MB - 4. -- Craig Barratt --- checksum.c | 16 +++++++++++++++- lib/mdfour.c | 51 +++++++++++++++++++++++++++++++++++++++------------ lib/mdfour.h | 5 +++-- 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/checksum.c b/checksum.c index 8e584fab..f9f46d72 100644 --- a/checksum.c +++ b/checksum.c @@ -74,7 +74,13 @@ void get_checksum2(char *buf,int len,char *sum) for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) { mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK); } - if (len - i > 0) { + /* + * Prior to version 27 an incorrect MD4 checksum was computed + * by failing to call mdfour_tail() for block sizes that + * are multiples of 64. This is fixed by calling mdfour_update() + * even when there are no more bytes. + */ + if (len - i > 0 || remote_version >= 27) { mdfour_update(&m, (uchar *)(buf1+i), (len-i)); } @@ -105,8 +111,16 @@ void file_checksum(char *fname,char *sum,OFF_T size) mdfour_update(&m, (uchar *)tmpchunk, CSUM_CHUNK); } + /* + * Prior to version 27 an incorrect MD4 checksum was computed + * by failing to call mdfour_tail() for block sizes that + * are multiples of 64. This is fixed by calling mdfour_update() + * even when there are no more bytes. + */ if (len - i > 0) { memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i); + } + if (len - i > 0 || remote_version >= 27) { mdfour_update(&m, (uchar *)tmpchunk, (len-i)); } diff --git a/lib/mdfour.c b/lib/mdfour.c index c7bc7abf..d8e86322 100644 --- a/lib/mdfour.c +++ b/lib/mdfour.c @@ -109,29 +109,53 @@ void mdfour_begin(struct mdfour *md) md->C = 0x98badcfe; md->D = 0x10325476; md->totalN = 0; + md->totalN2 = 0; } -static void mdfour_tail(unsigned char *in, int n) +static void mdfour_tail(unsigned char *in, uint32 n) { unsigned char buf[128]; uint32 M[16]; - uint32 b; - - m->totalN += n; - - b = m->totalN * 8; + extern int remote_version; + + /* + * Count total number of bits, modulo 2^64 + */ + m->totalN += n << 3; + if (m->totalN < (n << 3)) { + m->totalN2++; + } + m->totalN2 += n >> 29; memset(buf, 0, 128); if (n) memcpy(buf, in, n); buf[n] = 0x80; if (n <= 55) { - copy4(buf+56, b); + copy4(buf+56, m->totalN); + /* + * Prior to protocol version 27 only the number of bits + * modulo 2^32 was included. MD4 requires the number + * of bits modulo 2^64, which was fixed starting with + * protocol version 27. + */ + if (remote_version >= 27) { + copy4(buf+60, m->totalN2); + } copy64(M, buf); mdfour64(M); } else { - copy4(buf+120, b); + copy4(buf+120, m->totalN); + /* + * Prior to protocol version 27 only the number of bits + * modulo 2^32 was included. MD4 requires the number + * of bits modulo 2^64, which was fixed starting with + * protocol version 27. + */ + if (remote_version >= 27) { + copy4(buf+124, m->totalN2); + } copy64(M, buf); mdfour64(M); copy64(M, buf+64); @@ -139,20 +163,23 @@ static void mdfour_tail(unsigned char *in, int n) } } -void mdfour_update(struct mdfour *md, unsigned char *in, int n) +void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n) { uint32 M[16]; - if (n == 0) mdfour_tail(in, n); - m = md; + if (n == 0) mdfour_tail(in, n); + while (n >= 64) { copy64(M, in); mdfour64(M); in += 64; n -= 64; - m->totalN += 64; + m->totalN += 64 << 3; + if (m->totalN < 64 << 3) { + m->totalN2++; + } } if (n) mdfour_tail(in, n); diff --git a/lib/mdfour.h b/lib/mdfour.h index 2dd5527f..b0f3176f 100644 --- a/lib/mdfour.h +++ b/lib/mdfour.h @@ -21,11 +21,12 @@ struct mdfour { uint32 A, B, C, D; - uint32 totalN; + uint32 totalN; /* bit count, lower 32 bits */ + uint32 totalN2; /* bit count, upper 32 bits */ }; void mdfour_begin(struct mdfour *md); -void mdfour_update(struct mdfour *md, unsigned char *in, int n); +void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n); void mdfour_result(struct mdfour *md, unsigned char *out); void mdfour(unsigned char *out, unsigned char *in, int n); -- 2.34.1