X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fmd5.c;h=d742c54f66514c4b16ec1d54862eeed9053ac693;hb=862d856cf0083d07c86d56dce8f9be7b207a8dd4;hp=5f8bb83273967a02f959004b7cebec004a23d20a;hpb=032abe8887ed7a081d374fca8ec0095be3baaeb7;p=gnulib.git diff --git a/lib/md5.c b/lib/md5.c index 5f8bb8327..d742c54f6 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -1,11 +1,13 @@ /* md5.c - Functions to compute MD5 message digest of files or memory blocks according to the definition of MD5 in RFC 1321 from April 1992. - Copyright (C) 1995 Software Foundation, Inc. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -13,10 +15,10 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Written by Ulrich Drepper . */ +/* Written by Ulrich Drepper , 1995. */ #ifdef HAVE_CONFIG_H # include @@ -24,8 +26,24 @@ #include +#if STDC_HEADERS || defined _LIBC +# include +# include +#else +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + #include "md5.h" +#ifdef _LIBC +# include +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +#endif + #ifdef WORDS_BIGENDIAN # define SWAP(n) \ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) @@ -49,10 +67,16 @@ md5_init_ctx (ctx) ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; } -/* Put result from CTX in first 16 bytes following RESBUF. The result must - be in little endian byte order. */ +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ void * md5_read_ctx (ctx, resbuf) const struct md5_ctx *ctx; @@ -66,6 +90,39 @@ md5_read_ctx (ctx, resbuf) return resbuf; } +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_finish_ctx (ctx, resbuf) + struct md5_ctx *ctx; + void *resbuf; +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return md5_read_ctx (ctx, resbuf); +} + /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ @@ -77,16 +134,12 @@ md5_stream (stream, resblock) /* Important: BLOCKSIZE must be a multiple of 64. */ #define BLOCKSIZE 4096 struct md5_ctx ctx; - md5_uint32 len[2]; char buffer[BLOCKSIZE + 72]; - size_t pad, sum; + size_t sum; /* Initialize the computation context. */ md5_init_ctx (&ctx); - len[0] = 0; - len[1] = 0; - /* Iterate over full file contents. */ while (1) { @@ -99,7 +152,7 @@ md5_stream (stream, resblock) /* Read block. Take care for partial reads. */ do { - n = fread (buffer, 1, BLOCKSIZE - sum, stream); + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); sum += n; } @@ -107,13 +160,6 @@ md5_stream (stream, resblock) if (n == 0 && ferror (stream)) return 1; - /* RFC 1321 specifies the possible length of the file up to 2^64 bits. - Here we only compute the number of bytes. Do a double word - increment. */ - len[0] += sum; - if (len[0] < sum) - ++len[1]; - /* If end of file is reached, end the loop. */ if (n == 0) break; @@ -124,27 +170,12 @@ md5_stream (stream, resblock) md5_process_block (buffer, BLOCKSIZE, &ctx); } - /* We can copy 64 byte because the buffer is always big enough. FILLBUF - contains the needed bits. */ - memcpy (&buffer[sum], fillbuf, 64); - - /* Compute amount of padding bytes needed. Alignment is done to - (N + PAD) % 64 == 56 - There is always at least one byte padded. I.e. even the alignment - is correctly aligned 64 padding bytes are added. */ - pad = sum & 63; - pad = pad >= 56 ? 64 + 56 - pad : 56 - pad; - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - *(md5_uint32 *) &buffer[sum + pad] = SWAP (len[0] << 3); - *(md5_uint32 *) &buffer[sum + pad + 4] = SWAP ((len[1] << 3) - | (len[0] >> 29)); - - /* Process last bytes. */ - md5_process_block (buffer, sum + pad + 8, &ctx); + /* Add the last bytes if necessary. */ + if (sum > 0) + md5_process_bytes (buffer, sum, &ctx); /* Construct result in desired memory. */ - md5_read_ctx (&ctx, resblock); + md5_finish_ctx (&ctx, resblock); return 0; } @@ -159,37 +190,61 @@ md5_buffer (buffer, len, resblock) void *resblock; { struct md5_ctx ctx; - char restbuf[64 + 72]; - size_t blocks = len & ~63; - size_t pad, rest; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Process whole buffer but last len % 64 bytes. */ - md5_process_block (buffer, blocks, &ctx); + md5_process_bytes (buffer, len, &ctx); - /* REST bytes are not processed yet. */ - rest = len - blocks; - /* Copy to own buffer. */ - memcpy (restbuf, &buffer[blocks], rest); - /* Append needed fill bytes at end of buffer. We can copy 64 byte - because the buffer is always big enough. */ - memcpy (&restbuf[rest], fillbuf, 64); + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} - /* PAD bytes are used for padding to correct alignment. Note that - always at least one byte is padded. */ - pad = rest >= 56 ? 64 + 56 - rest : 56 - rest; - /* Put length of buffer in *bits* in last eight bytes. */ - *(md5_uint32 *) &restbuf[rest + pad] = SWAP (len << 3); - *(md5_uint32 *) &restbuf[rest + pad + 4] = SWAP (len >> 29); +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; - /* Process last bytes. */ - md5_process_block (restbuf, rest + pad + 8, &ctx); + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; - /* Put result in desired memory area. */ - return md5_read_ctx (&ctx, resblock); + if (left_over + add > 64) + { + md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx); + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + (left_over + add) & 63); + ctx->buflen = (left_over + add) & 63; + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len > 64) + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + memcpy (ctx->buffer, buffer, len); + ctx->buflen = len; + } } @@ -220,6 +275,13 @@ md5_process_block (buffer, len, ctx) md5_uint32 C = ctx->C; md5_uint32 D = ctx->D; + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + /* Process all bytes in the buffer with 64 bytes in each round of the loop. */ while (words < endp)