From: Collin Funk Date: Sun, 31 Aug 2025 21:21:02 +0000 (-0700) Subject: crypto/sha3: New module. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3a3a63530b1b6931be7dba66371aed3ffd9cb1db;p=thirdparty%2Fgnulib.git crypto/sha3: New module. * modules/crypto/sha3: New file. * lib/sha3-stream.c: New file, based on sha512-stream.c. * lib/sha3.h (sha3_224_stream, sha3_256_stream, sha3_384_stream) (sha3_512_stream): New declarations. --- diff --git a/ChangeLog b/ChangeLog index 924d67e135..d202892dd1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2025-08-31 Collin Funk + crypto/sha3: New module. + * modules/crypto/sha3: New file. + * lib/sha3-stream.c: New file, based on sha512-stream.c. + * lib/sha3.h (sha3_224_stream, sha3_256_stream, sha3_384_stream) + (sha3_512_stream): New declarations. + crypto/sha3-buffer: Add tests. * modules/crypto/sha3-buffer-tests: New file. * tests/test-sha3-224-buffer.c: Likewise. diff --git a/lib/sha3-stream.c b/lib/sha3-stream.c new file mode 100644 index 0000000000..708dafa7dc --- /dev/null +++ b/lib/sha3-stream.c @@ -0,0 +1,145 @@ +/* sha3-stream.c - Functions to compute the SHA-3 message digest of files as + specified by FIPS-202. + + Copyright (C) 2025 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 . */ + +#include + +/* Specification. */ +#include "sha3.h" + +#include + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +#include "af_alg.h" + +#define BLOCKSIZE 31824 +#if (BLOCKSIZE % 144 != 0 && BLOCKSIZE % 136 != 0 && BLOCKSIZE % 104 != 0 \ + && BLOCKSIZE % 72 != 0) +# error "invalid BLOCKSIZE" +#endif + +/* Compute message digest for bytes read from STREAM using algorithm ALG. + Write the message digest into RESBLOCK, which contains HASHLEN bytes. + The initial operation is INIT_CTX. Return zero if and only if + successful. */ +static int +sha3_xxx_stream (FILE *stream, char const *alg, void *resblock, + ssize_t hashlen, void (*init_ctx) (struct sha3_ctx *)) +{ + switch (afalg_stream (stream, alg, resblock, hashlen)) + { + case 0: return 0; + case -EIO: return 1; + } + + char *buffer = malloc (BLOCKSIZE + 72); + if (!buffer) + return 1; + + struct sha3_ctx ctx; + init_ctx (&ctx); + size_t sum; + + /* Iterate over full file contents. */ + 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. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + while (1) + { + /* Either process a partial fread() from this loop, + or the fread() in afalg_stream may have gotten EOF. + We need to avoid a subsequent fread() as EOF may + not be sticky. For details of such systems, see: + https://sourceware.org/PR1190 */ + if (feof (stream)) + goto process_partial_block; + + 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; + } + } + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % ctx.blocklen == 0 + */ + sha3_process_block (buffer, BLOCKSIZE, &ctx); + } + + process_partial_block:; + + /* Process any remaining bytes. */ + if (sum > 0) + sha3_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + sha3_finish_ctx (&ctx, resblock); + free (buffer); + return 0; +} + +int +sha3_224_stream (FILE *stream, void *resblock) +{ + return sha3_xxx_stream (stream, "sha3-224", resblock, SHA3_224_DIGEST_SIZE, + sha3_224_init_ctx); +} + +int +sha3_256_stream (FILE *stream, void *resblock) +{ + return sha3_xxx_stream (stream, "sha3-256", resblock, SHA3_256_DIGEST_SIZE, + sha3_256_init_ctx); +} + +int +sha3_384_stream (FILE *stream, void *resblock) +{ + return sha3_xxx_stream (stream, "sha3-384", resblock, SHA3_384_DIGEST_SIZE, + sha3_384_init_ctx); +} + +int +sha3_512_stream (FILE *stream, void *resblock) +{ + return sha3_xxx_stream (stream, "sha3-512", resblock, SHA3_512_DIGEST_SIZE, + sha3_512_init_ctx); +} diff --git a/lib/sha3.h b/lib/sha3.h index c299c6fab7..8e0a7a7fdf 100644 --- a/lib/sha3.h +++ b/lib/sha3.h @@ -94,6 +94,16 @@ extern void *sha3_384_buffer (const char *buffer, size_t len, extern void *sha3_512_buffer (const char *buffer, size_t len, void *restrict resblock); +/* Compute SHA-3 message digest for bytes read from STREAM. STREAM is an open + file stream. Regular files are handled more efficiently. The contents of + STREAM from its current position to its end will be read. The case that the + last operation on STREAM was an 'ungetc' is not supported. The resulting + message digest number will be written into RESBLOCK. */ +extern int sha3_224_stream (FILE *stream, void *resblock); +extern int sha3_256_stream (FILE *stream, void *resblock); +extern int sha3_384_stream (FILE *stream, void *resblock); +extern int sha3_512_stream (FILE *stream, void *resblock); + # ifdef __cplusplus } # endif diff --git a/modules/crypto/sha3 b/modules/crypto/sha3 new file mode 100644 index 0000000000..f2b878794a --- /dev/null +++ b/modules/crypto/sha3 @@ -0,0 +1,23 @@ +Description: +Compute SHA-3 checksums. + +Files: +lib/sha3-stream.c + +Depends-on: +crypto/af_alg +crypto/sha3-buffer + +configure.ac: + +Makefile.am: +lib_SOURCES += sha3-stream.c + +Include: +"sha3.h" + +License: +LGPLv2+ + +Maintainer: +all