summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorCollin Funk <collin.funk1@gmail.com>2026-02-23 00:20:46 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2026-02-23 00:22:17 -0800
commit29440eedac7968580e35e751c6cdf94af337a95a (patch)
tree511fa2df3d1459c9e3d53d088856194d2123af38 /lib
parentccaa4a07f093428241cbcc81379c3ea3d84b38ee (diff)
Add SHA-3 support to secure-hash
* admin/merge-gnulib (GNULIB_MODULES): Add crypto/sha3-buffer. * lib/sha3.c: New file, imported by running admin/merge-gnulib. * lib/sha3.h: Likewise. * m4/sha3.m4: Likewise. * lib/gnulib.mk.in: Updated by admin/merge-gnulib. * m4/gnulib-comp.m4: Likewise. * src/fns.c: Include sha3.h (Fsecure_hash_algorithms): Add Qsha3_224, Qsha3_256, Qsha3_384, and Qsha3_512. (secure_hash): Likewise. (Fsecure_hash): List the SHA-3 algorithms in the docstring. (syms_of_fns): Define Qsha3_224, Qsha3_256, Qsha3_384, and Qsha3_512. * test/lisp/net/gnutls-tests.el (gnutls-tests-internal-macs-upcased): Filter out the new SHA-3 algorithms since they are currently not implemented in gnutls. * test/src/fns-tests.el (test-secure-hash): Add test cases for the new algorithms. * doc/lispref/text.texi (Checksum/Hash): List the SHA-3 algorithms. Mention that they are considered secure. * etc/NEWS: Mention the new feature.
Diffstat (limited to 'lib')
-rw-r--r--lib/gnulib.mk.in11
-rw-r--r--lib/sha3.c442
-rw-r--r--lib/sha3.h132
3 files changed, 585 insertions, 0 deletions
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index d7203c16fde..053d234a474 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -99,6 +99,7 @@
# crypto/md5-buffer \
# crypto/sha1-buffer \
# crypto/sha256-buffer \
+# crypto/sha3-buffer \
# crypto/sha512-buffer \
# d-type \
# diffseq \
@@ -1853,6 +1854,16 @@ EXTRA_DIST += gl_openssl.h sha256.h
endif
## end gnulib module crypto/sha256-buffer
+## begin gnulib module crypto/sha3-buffer
+ifeq (,$(OMIT_GNULIB_MODULE_crypto/sha3-buffer))
+
+libgnu_a_SOURCES += sha3.c
+
+EXTRA_DIST += sha3.h
+
+endif
+## end gnulib module crypto/sha3-buffer
+
## begin gnulib module crypto/sha512-buffer
ifeq (,$(OMIT_GNULIB_MODULE_crypto/sha512-buffer))
diff --git a/lib/sha3.c b/lib/sha3.c
new file mode 100644
index 00000000000..1bebbc76950
--- /dev/null
+++ b/lib/sha3.c
@@ -0,0 +1,442 @@
+/* sha3.c - Functions to calculate SHA-3 hashes as specified by FIPS-202.
+ Copyright (C) 2025-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/>. */
+
+/* Written by Collin Funk <collin.funk1@gmail.com>, 2025. */
+
+#include <config.h>
+
+/* Specification. */
+#include "sha3.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <byteswap.h>
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n) u64bswap (n)
+#else
+# define SWAP(n) (n)
+#endif
+
+#if ! HAVE_OPENSSL_SHA3
+
+static const u64 rc[] = {
+ u64init (0x00000000, 0x00000001), u64init (0x00000000, 0x00008082),
+ u64init (0x80000000, 0x0000808A), u64init (0x80000000, 0x80008000),
+ u64init (0x00000000, 0x0000808B), u64init (0x00000000, 0x80000001),
+ u64init (0x80000000, 0x80008081), u64init (0x80000000, 0x00008009),
+ u64init (0x00000000, 0x0000008A), u64init (0x00000000, 0x00000088),
+ u64init (0x00000000, 0x80008009), u64init (0x00000000, 0x8000000A),
+ u64init (0x00000000, 0x8000808B), u64init (0x80000000, 0x0000008B),
+ u64init (0x80000000, 0x00008089), u64init (0x80000000, 0x00008003),
+ u64init (0x80000000, 0x00008002), u64init (0x80000000, 0x00000080),
+ u64init (0x00000000, 0x0000800A), u64init (0x80000000, 0x8000000A),
+ u64init (0x80000000, 0x80008081), u64init (0x80000000, 0x00008080),
+ u64init (0x00000000, 0x80000001), u64init (0x80000000, 0x80008008)
+};
+
+#define DEFINE_SHA3_INIT_CTX(SIZE) \
+ bool \
+ sha3_##SIZE##_init_ctx (struct sha3_ctx *ctx) \
+ { \
+ memset (&ctx->state, '\0', sizeof ctx->state); \
+ ctx->buflen = 0; \
+ ctx->digestlen = SHA3_##SIZE##_DIGEST_SIZE; \
+ ctx->blocklen = SHA3_##SIZE##_BLOCK_SIZE; \
+ return true; \
+ }
+
+DEFINE_SHA3_INIT_CTX (224)
+DEFINE_SHA3_INIT_CTX (256)
+DEFINE_SHA3_INIT_CTX (384)
+DEFINE_SHA3_INIT_CTX (512)
+
+void
+sha3_free_ctx (_GL_UNUSED struct sha3_ctx *ctx)
+{
+ /* Do nothing. */
+}
+
+/* Copy the value from V into the memory location pointed to by *CP,
+ If your architecture allows unaligned access, this is equivalent to
+ * (__typeof__ (v) *) cp = v */
+static void
+set_uint64 (char *cp, u64 v)
+{
+ memcpy (cp, &v, sizeof v);
+}
+
+void *
+sha3_read_ctx (struct sha3_ctx const *restrict ctx, void *restrict resbuf)
+{
+ char *r = resbuf;
+ size_t words = ctx->digestlen / sizeof *ctx->state;
+ size_t bytes = ctx->digestlen % sizeof *ctx->state;
+
+ int i;
+ for (i = 0; i < words; ++i, r += sizeof *ctx->state)
+ set_uint64 (r, SWAP (ctx->state[i]));
+ if (bytes)
+ {
+ u64 word = ctx->state[i];
+ do
+ {
+ *r++ = u64getlo (word) & 0xFF;
+ word = u64shr (word, 8);
+ }
+ while (--bytes);
+ }
+ return resbuf;
+}
+
+static void
+sha3_conclude_ctx (struct sha3_ctx *ctx)
+{
+ ctx->buffer[ctx->buflen++] = 0x06;
+ memset (ctx->buffer + ctx->buflen, '\0', ctx->blocklen - ctx->buflen);
+ ctx->buffer[ctx->blocklen - 1] |= 0x80;
+ sha3_process_block (ctx->buffer, ctx->blocklen, ctx);
+}
+
+void *
+sha3_finish_ctx (struct sha3_ctx *restrict ctx, void *restrict resbuf)
+{
+ sha3_conclude_ctx (ctx);
+ return sha3_read_ctx (ctx, resbuf);
+}
+
+#define DEFINE_SHA3_BUFFER(SIZE) \
+ void * \
+ sha3_##SIZE##_buffer (char const *restrict buffer, size_t len, \
+ void *restrict resblock) \
+ { \
+ struct sha3_ctx ctx; \
+ sha3_##SIZE##_init_ctx (&ctx); \
+ sha3_process_bytes (buffer, len, &ctx); \
+ return sha3_finish_ctx (&ctx, resblock); \
+ }
+
+DEFINE_SHA3_BUFFER (224)
+DEFINE_SHA3_BUFFER (256)
+DEFINE_SHA3_BUFFER (384)
+DEFINE_SHA3_BUFFER (512)
+
+bool
+sha3_process_bytes (void const *restrict buffer, size_t len,
+ struct sha3_ctx *restrict ctx)
+{
+ char const *buf = buffer;
+
+ if (0 < ctx->buflen)
+ {
+ size_t left = ctx->blocklen - ctx->buflen;
+ if (len < left)
+ {
+ /* Not enough to fill a full block. */
+ memcpy (ctx->buffer + ctx->buflen, buf, len);
+ ctx->buflen += len;
+ return true;
+ }
+ /* Process the block that already had bytes buffered. */
+ memcpy (ctx->buffer + ctx->buflen, buf, left);
+ buf += left;
+ len -= left;
+ sha3_process_block (ctx->buffer, ctx->blocklen, ctx);
+ }
+
+ /* Process as many complete blocks as possible. */
+ size_t full_len = len - len % ctx->blocklen;
+ sha3_process_block (buf, full_len, ctx);
+ buf += full_len;
+ len -= full_len;
+
+ memcpy (ctx->buffer, buf, len);
+ ctx->buflen = len;
+ return true;
+}
+
+bool
+sha3_process_block (void const *restrict buffer, size_t len,
+ struct sha3_ctx *restrict ctx)
+{
+ u64 *a = ctx->state;
+ const u64 *words = buffer;
+ size_t nwords = len / sizeof *words;
+ const u64 *endp = words + nwords;
+
+ while (words < endp)
+ {
+ for (size_t i = 0; i < ctx->blocklen / sizeof *ctx->state; ++i, ++words)
+ ctx->state[i] = u64xor (ctx->state[i], SWAP (*words));
+ for (int i = 0; i < 24; ++i)
+ {
+ u64 c[5];
+ u64 d[5];
+ u64 t1;
+ u64 t2;
+
+ /* Theta step 1. */
+ c[0] = u64xor (u64xor (u64xor (u64xor (a[0], a[5]), a[10]),
+ a[15]), a[20]);
+ c[1] = u64xor (u64xor (u64xor (u64xor (a[1], a[6]), a[11]),
+ a[16]), a[21]);
+ c[2] = u64xor (u64xor (u64xor (u64xor (a[2], a[7]), a[12]),
+ a[17]), a[22]);
+ c[3] = u64xor (u64xor (u64xor (u64xor (a[3], a[8]), a[13]),
+ a[18]), a[23]);
+ c[4] = u64xor (u64xor (u64xor (u64xor (a[4], a[9]), a[14]),
+ a[19]), a[24]);
+
+ /* Theta step 2. */
+ d[0] = u64xor (c[4], u64rol (c[1], 1));
+ d[1] = u64xor (c[0], u64rol (c[2], 1));
+ d[2] = u64xor (c[1], u64rol (c[3], 1));
+ d[3] = u64xor (c[2], u64rol (c[4], 1));
+ d[4] = u64xor (c[3], u64rol (c[0], 1));
+
+ /* Theta step 3. */
+ a[0] = u64xor (a[0], d[0]);
+ a[5] = u64xor (a[5], d[0]);
+ a[10] = u64xor (a[10], d[0]);
+ a[15] = u64xor (a[15], d[0]);
+ a[20] = u64xor (a[20], d[0]);
+ a[1] = u64xor (a[1], d[1]);
+ a[6] = u64xor (a[6], d[1]);
+ a[11] = u64xor (a[11], d[1]);
+ a[16] = u64xor (a[16], d[1]);
+ a[21] = u64xor (a[21], d[1]);
+ a[2] = u64xor (a[2], d[2]);
+ a[7] = u64xor (a[7], d[2]);
+ a[12] = u64xor (a[12], d[2]);
+ a[17] = u64xor (a[17], d[2]);
+ a[22] = u64xor (a[22], d[2]);
+ a[3] = u64xor (a[3], d[3]);
+ a[8] = u64xor (a[8], d[3]);
+ a[13] = u64xor (a[13], d[3]);
+ a[18] = u64xor (a[18], d[3]);
+ a[23] = u64xor (a[23], d[3]);
+ a[4] = u64xor (a[4], d[4]);
+ a[9] = u64xor (a[9], d[4]);
+ a[14] = u64xor (a[14], d[4]);
+ a[19] = u64xor (a[19], d[4]);
+ a[24] = u64xor (a[24], d[4]);
+
+ /* Rho and Pi. */
+ t1 = a[1];
+ t2 = u64rol (t1, 1);
+ t1 = a[10];
+ a[10] = t2;
+ t2 = u64rol (t1, 3);
+ t1 = a[7];
+ a[7] = t2;
+ t2 = u64rol (t1, 6);
+ t1 = a[11];
+ a[11] = t2;
+ t2 = u64rol (t1, 10);
+ t1 = a[17];
+ a[17] = t2;
+ t2 = u64rol (t1, 15);
+ t1 = a[18];
+ a[18] = t2;
+ t2 = u64rol (t1, 21);
+ t1 = a[3];
+ a[3] = t2;
+ t2 = u64rol (t1, 28);
+ t1 = a[5];
+ a[5] = t2;
+ t2 = u64rol (t1, 36);
+ t1 = a[16];
+ a[16] = t2;
+ t2 = u64rol (t1, 45);
+ t1 = a[8];
+ a[8] = t2;
+ t2 = u64rol (t1, 55);
+ t1 = a[21];
+ a[21] = t2;
+ t2 = u64rol (t1, 2);
+ t1 = a[24];
+ a[24] = t2;
+ t2 = u64rol (t1, 14);
+ t1 = a[4];
+ a[4] = t2;
+ t2 = u64rol (t1, 27);
+ t1 = a[15];
+ a[15] = t2;
+ t2 = u64rol (t1, 41);
+ t1 = a[23];
+ a[23] = t2;
+ t2 = u64rol (t1, 56);
+ t1 = a[19];
+ a[19] = t2;
+ t2 = u64rol (t1, 8);
+ t1 = a[13];
+ a[13] = t2;
+ t2 = u64rol (t1, 25);
+ t1 = a[12];
+ a[12] = t2;
+ t2 = u64rol (t1, 43);
+ t1 = a[2];
+ a[2] = t2;
+ t2 = u64rol (t1, 62);
+ t1 = a[20];
+ a[20] = t2;
+ t2 = u64rol (t1, 18);
+ t1 = a[14];
+ a[14] = t2;
+ t2 = u64rol (t1, 39);
+ t1 = a[22];
+ a[22] = t2;
+ t2 = u64rol (t1, 61);
+ t1 = a[9];
+ a[9] = t2;
+ t2 = u64rol (t1, 20);
+ t1 = a[6];
+ a[6] = t2;
+ t2 = u64rol (t1, 44);
+ t1 = a[1];
+ a[1] = t2;
+
+ /* Chi. */
+ for (int j = 0; j < 25; j += 5)
+ {
+ t1 = a[j];
+ t2 = a[j + 1];
+ a[j] = u64xor (a[j], u64and (u64not (a[j + 1]), a[j + 2]));
+ a[j + 1] = u64xor (a[j + 1], u64and (u64not (a[j + 2]),
+ a[j + 3]));
+ a[j + 2] = u64xor (a[j + 2], u64and (u64not (a[j + 3]),
+ a[j + 4]));
+ a[j + 3] = u64xor (a[j + 3], u64and (u64not (a[j + 4]), t1));
+ a[j + 4] = u64xor (a[j + 4], u64and (u64not (t1), t2));
+ }
+
+ /* Iota. */
+ a[0] = u64xor (a[0], rc[i]);
+ }
+ }
+ return true;
+}
+
+#else /* OpenSSL implementation. */
+
+/* We avoid using all of EVP error strings. Just guess a reasonable errno. */
+#include <errno.h>
+
+#define DEFINE_SHA3_INIT_CTX(SIZE) \
+ bool \
+ sha3_##SIZE##_init_ctx (struct sha3_ctx *ctx) \
+ { \
+ EVP_MD_CTX *evp_ctx = EVP_MD_CTX_new (); \
+ if (evp_ctx && ! EVP_DigestInit_ex (evp_ctx, EVP_sha3_##SIZE (), NULL)) \
+ { \
+ EVP_MD_CTX_free (evp_ctx); \
+ evp_ctx = NULL; \
+ } \
+ ctx->evp_ctx = evp_ctx; \
+ errno = ENOMEM; /* OK to set errno even if successful. */ \
+ return !!evp_ctx; \
+ }
+
+DEFINE_SHA3_INIT_CTX (224)
+DEFINE_SHA3_INIT_CTX (256)
+DEFINE_SHA3_INIT_CTX (384)
+DEFINE_SHA3_INIT_CTX (512)
+
+void
+sha3_free_ctx (struct sha3_ctx *ctx)
+{
+ if (ctx->evp_ctx != NULL)
+ {
+ int saved_errno = errno;
+ EVP_MD_CTX_free (ctx->evp_ctx);
+ ctx->evp_ctx = NULL;
+ errno = saved_errno;
+ }
+}
+
+void *
+sha3_read_ctx (struct sha3_ctx const *restrict ctx, void *restrict resbuf)
+{
+ void *result = NULL;
+ int err = ENOMEM;
+ EVP_MD_CTX *evp_ctx = EVP_MD_CTX_new ();
+ if (evp_ctx)
+ {
+ if (EVP_MD_CTX_copy_ex (evp_ctx, ctx->evp_ctx))
+ {
+ if (EVP_DigestFinal_ex (evp_ctx, resbuf, 0))
+ result = resbuf;
+ err = EINVAL;
+ }
+ EVP_MD_CTX_free (evp_ctx);
+ }
+ errno = err; /* OK to set errno even if successful. */
+ return result;
+}
+
+void *
+sha3_finish_ctx (struct sha3_ctx *restrict ctx, void *restrict resbuf)
+{
+ int result = EVP_DigestFinal_ex (ctx->evp_ctx, resbuf, NULL);
+ if (result == 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ return resbuf;
+}
+
+#define DEFINE_SHA3_BUFFER(SIZE) \
+ void * \
+ sha3_##SIZE##_buffer (char const *restrict buffer, size_t len, \
+ void *restrict resblock) \
+ { \
+ struct sha3_ctx ctx; \
+ void *result = ((sha3_##SIZE##_init_ctx (&ctx) \
+ && sha3_process_bytes (buffer, len, &ctx)) \
+ ? sha3_finish_ctx (&ctx, resblock) \
+ : NULL); \
+ sha3_free_ctx (&ctx); \
+ return result; \
+ }
+
+DEFINE_SHA3_BUFFER (224)
+DEFINE_SHA3_BUFFER (256)
+DEFINE_SHA3_BUFFER (384)
+DEFINE_SHA3_BUFFER (512)
+
+bool
+sha3_process_bytes (void const *restrict buffer, size_t len,
+ struct sha3_ctx *restrict ctx)
+{
+ int result = EVP_DigestUpdate (ctx->evp_ctx, buffer, len);
+ if (result == 0)
+ {
+ errno = EINVAL;
+ return false;
+ }
+ return true;
+}
+
+bool
+sha3_process_block (void const *restrict buffer, size_t len,
+ struct sha3_ctx *restrict ctx)
+{
+ return sha3_process_bytes (buffer, len, ctx);
+}
+
+#endif
diff --git a/lib/sha3.h b/lib/sha3.h
new file mode 100644
index 00000000000..a44922a0843
--- /dev/null
+++ b/lib/sha3.h
@@ -0,0 +1,132 @@
+/* sha3.h - Functions to calculate SHA-3 hashes as specified by FIPS-202.
+ Copyright (C) 2025-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/>. */
+
+/* Written by Collin Funk <collin.funk1@gmail.com>, 2025. */
+
+#ifndef SHA3_H
+# define SHA3_H 1
+
+# include <stddef.h>
+# include <stdio.h>
+# include <stdint.h>
+
+# include "u64.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* OpenSSL does not have the Init, Update, Final API for SHA-3. We must use
+ the EVP API. */
+# if HAVE_OPENSSL_SHA3
+# include <openssl/evp.h>
+# endif
+
+/* Digest sizes in bytes. */
+enum { SHA3_224_DIGEST_SIZE = 224 / 8 };
+enum { SHA3_256_DIGEST_SIZE = 256 / 8 };
+enum { SHA3_384_DIGEST_SIZE = 384 / 8 };
+enum { SHA3_512_DIGEST_SIZE = 512 / 8 };
+
+/* Block sizes in bytes. */
+enum { SHA3_224_BLOCK_SIZE = 1152 / 8 };
+enum { SHA3_256_BLOCK_SIZE = 1088 / 8 };
+enum { SHA3_384_BLOCK_SIZE = 832 / 8 };
+enum { SHA3_512_BLOCK_SIZE = 576 / 8 };
+
+/* Structure to save state of computation between the single steps. */
+struct sha3_ctx
+{
+# if HAVE_OPENSSL_SHA3
+ /* EVP_MD_CTX is an incomplete type. It cannot be placed on the stack. */
+ EVP_MD_CTX *evp_ctx;
+# else
+ u64 state[25];
+ uint8_t buffer[144]; /* Up to BLOCKLEN in use. */
+ size_t buflen; /* ≥ 0, ≤ BLOCKLEN */
+ size_t digestlen; /* One of SHA3_{224,256,384,512}_DIGEST_SIZE. */
+ size_t blocklen; /* One of SHA3_{224,256,384,512}_BLOCK_SIZE. */
+# endif
+};
+
+/* Initialize structure containing state of computation. */
+extern bool sha3_224_init_ctx (struct sha3_ctx *ctx);
+extern bool sha3_256_init_ctx (struct sha3_ctx *ctx);
+extern bool sha3_384_init_ctx (struct sha3_ctx *ctx);
+extern bool sha3_512_init_ctx (struct sha3_ctx *ctx);
+
+/* Free memory allocated by the init_structure. */
+extern void sha3_free_ctx (struct sha3_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+ initialization function update the context for the next LEN bytes
+ starting at BUFFER.
+ It is necessary that LEN is a multiple of the BLOCKLEN member of CTX!!!
+ Return false if an OpenSSL function fails. */
+extern bool sha3_process_block (void const *restrict buffer, size_t len,
+ struct sha3_ctx *restrict ctx);
+
+/* Starting with the result of former calls of this function (or the
+ initialization function update the context for the next LEN bytes
+ starting at BUFFER.
+ It is NOT required that LEN is a multiple of the BLOCKLEN member of CTX.
+ Return false if an OpenSSL function fails. */
+extern bool sha3_process_bytes (void const *restrict buffer, size_t len,
+ struct sha3_ctx *restrict ctx);
+
+/* Process the remaining bytes in the buffer and put result from CTX in RESBUF.
+ The result is always in little endian byte order, so that a byte-wise output
+ yields to the wanted ASCII representation of the message digest.
+ Return NULL if an OpenSSL function fails. */
+extern void *sha3_finish_ctx (struct sha3_ctx *restrict ctx,
+ void *restrict resbuf);
+
+/* Put result from CTX in RESBUF. The result is always in little endian byte
+ order, so that a byte-wise output yields to the wanted ASCII representation
+ of the message digest.
+ Return NULL if an OpenSSL function fails. */
+extern void *sha3_read_ctx (struct sha3_ctx const *restrict ctx,
+ void *restrict resbuf);
+
+/* Compute a SHA-3 message digest for LEN bytes beginning at BUFFER.
+ The result is always in little endian byte order, so that a byte-wise
+ output yields to the wanted ASCII representation of the message
+ digest.
+ Return NULL if an OpenSSL function fails. */
+extern void *sha3_224_buffer (char const *restrict buffer, size_t len,
+ void *restrict resblock);
+extern void *sha3_256_buffer (char const *restrict buffer, size_t len,
+ void *restrict resblock);
+extern void *sha3_384_buffer (char const *restrict buffer, size_t len,
+ void *restrict resblock);
+extern void *sha3_512_buffer (char const *restrict 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 *restrict stream, void *restrict resblock);
+extern int sha3_256_stream (FILE *restrict stream, void *restrict resblock);
+extern int sha3_384_stream (FILE *restrict stream, void *restrict resblock);
+extern int sha3_512_stream (FILE *restrict stream, void *restrict resblock);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif