| /* Functions to compute MD4 message digest of files or memory blocks. | |
| according to the definition of MD4 in RFC 1320 from April 1992. | |
| Copyright (C) 1995-1997, 1999-2003, 2005-2006, 2008-2026 Free Software | |
| Foundation, Inc. | |
| This file is free software: you can redistribute it and/or modify | |
| it under the terms of the GNU Lesser General Public License as | |
| published by the Free Software Foundation; either version 2.1 of the | |
| License, or (at your option) any later version. | |
| This file is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU Lesser General Public License for more details. | |
| You should have received a copy of the GNU Lesser General Public License | |
| along with this program. If not, see <https://www.gnu.org/licenses/>. */ | |
| /* Adapted by Simon Josefsson from gnulib md5.? and Libgcrypt | |
| cipher/md4.c . */ | |
| #include <config.h> | |
| /* Specification. */ | |
| #include "md4.h" | |
| #include <stdlib.h> | |
| #if USE_UNLOCKED_IO | |
| # include "unlocked-io.h" | |
| #endif | |
| #define BLOCKSIZE 32768 | |
| #if BLOCKSIZE % 64 != 0 | |
| # error "invalid BLOCKSIZE" | |
| #endif | |
| /* Compute MD4 message digest for bytes read from STREAM. The | |
| resulting message digest number will be written into the 16 bytes | |
| beginning at RESBLOCK. */ | |
| int | |
| md4_stream (FILE *restrict stream, void *restrict resblock) | |
| { | |
| char *buffer = malloc (BLOCKSIZE); | |
| if (!buffer) | |
| return 1; | |
| /* Initialize the computation context. */ | |
| struct md4_ctx ctx; | |
| md4_init_ctx (&ctx); | |
| /* Iterate over full file contents. */ | |
| size_t sum; | |
| while (1) | |
| { | |
| /* We read the file in blocks of BLOCKSIZE bytes. One call of the | |
| computation function processes the whole buffer so that with the | |
| next round of the loop another block can be read. */ | |
| sum = 0; | |
| /* Read block. Take care for partial reads. */ | |
| while (1) | |
| { | |
| size_t n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); | |
| sum += n; | |
| if (sum == BLOCKSIZE) | |
| break; | |
| if (n == 0) | |
| { | |
| /* Check for the error flag IFF N == 0, so that we don't | |
| exit the loop after a partial read due to e.g., EAGAIN | |
| or EWOULDBLOCK. */ | |
| if (ferror (stream)) | |
| { | |
| free (buffer); | |
| return 1; | |
| } | |
| goto process_partial_block; | |
| } | |
| /* We've read at least one byte, so ignore errors. But always | |
| check for EOF, since feof may be true even though N > 0. | |
| Otherwise, we could end up calling fread after EOF. */ | |
| if (feof (stream)) | |
| goto process_partial_block; | |
| } | |
| /* Process buffer with BLOCKSIZE bytes. Note that | |
| BLOCKSIZE % 64 == 0 | |
| */ | |
| md4_process_block (buffer, BLOCKSIZE, &ctx); | |
| } | |
| process_partial_block:; | |
| /* Process any remaining bytes. */ | |
| if (sum > 0) | |
| md4_process_bytes (buffer, sum, &ctx); | |
| /* Construct result in desired memory. */ | |
| md4_finish_ctx (&ctx, resblock); | |
| free (buffer); | |
| return 0; | |
| } |