Collin Funk <[email protected]> writes: > Anyways, will push this patch later to give some time for review. I'll > have to write the the crypto/sha3-stream module but that is fairly > simple.
Here is a patch implementing the crypto/sha3-stream module. The second is needed to allow lib/u64.h to be included twice as is done in coreutils src/cksum.c (once in sha512.h and once in sha3.h). Tested using a local patch to cksum compared to openssl on a various files. Collin
>From c00faa784608f77cdd46ea08fa180eab017a4405 Mon Sep 17 00:00:00 2001 Message-ID: <c00faa784608f77cdd46ea08fa180eab017a4405.1756619842.git.collin.fu...@gmail.com> From: Collin Funk <[email protected]> Date: Sat, 30 Aug 2025 21:52:15 -0700 Subject: [PATCH 1/2] 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. --- ChangeLog | 6 ++ lib/sha3-stream.c | 145 ++++++++++++++++++++++++++++++++++++++++++++ lib/sha3.h | 10 +++ modules/crypto/sha3 | 23 +++++++ 4 files changed, 184 insertions(+) create mode 100644 lib/sha3-stream.c create mode 100644 modules/crypto/sha3 diff --git a/ChangeLog b/ChangeLog index 0eef5a44fc..4507c51298 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2025-08-30 Collin Funk <[email protected]> + 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..c569c36b68 --- /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 <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "sha3.h" + +#include <stdlib.h> + +#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 and finishing operations are INIT_CTX and FINISH_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 % 128 == 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..23bb8f8f7e 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 SHA5-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 -- 2.51.0
>From a99da69b2c6b618cd9a873605cab459cffae8ae7 Mon Sep 17 00:00:00 2001 Message-ID: <a99da69b2c6b618cd9a873605cab459cffae8ae7.1756619842.git.collin.fu...@gmail.com> In-Reply-To: <c00faa784608f77cdd46ea08fa180eab017a4405.1756619842.git.collin.fu...@gmail.com> References: <c00faa784608f77cdd46ea08fa180eab017a4405.1756619842.git.collin.fu...@gmail.com> From: Collin Funk <[email protected]> Date: Sat, 30 Aug 2025 22:53:13 -0700 Subject: [PATCH 2/2] u64: Allow the header to be included twice. * lib/u64.h: Add include gaurd. --- ChangeLog | 3 +++ lib/u64.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4507c51298..441aa663c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2025-08-30 Collin Funk <[email protected]> + u64: Allow the header to be included twice. + * lib/u64.h: Add include gaurd. + crypto/sha3: New module. * modules/crypto/sha3: New file. * lib/sha3-stream.c: New file, based on sha512-stream.c. diff --git a/lib/u64.h b/lib/u64.h index 35dbb944ec..d6bbee0f85 100644 --- a/lib/u64.h +++ b/lib/u64.h @@ -17,6 +17,9 @@ /* Written by Paul Eggert. */ +#ifndef U64_H +#define U64_H 1 + /* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE. */ #if !_GL_CONFIG_H_INCLUDED #error "Please include config.h first." @@ -228,3 +231,5 @@ u64rol (u64 x, int n) #endif _GL_INLINE_HEADER_END + +#endif -- 2.51.0
