commit c46a9ad4311adf87a14fd7accdcf82350b7945df
parent b5992394edc4af93b24bf12e774b8b1344ef9cab
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Mon, 13 Jul 2026 22:13:10 +0200
Reworked SHA-512/256 backends handling, fixed number of problems
Removed two levels dispatcher/selector, simplified to single level.
Optimised by avoiding unneeded context resets and using proper internal
API functions.
Diffstat:
16 files changed, 1696 insertions(+), 1528 deletions(-)
diff --git a/src/mhd2/Makefile.am b/src/mhd2/Makefile.am
@@ -209,22 +209,26 @@ sha256_OPTSOURCES = \
endif
+# Note: the current configure may enable several SHA-512/256 TLS-lib
+# conditionals at once, while mhd_sha512_256.h selects the backends in the
+# OpenSSL, MbedTLS order of preference. As the last active assignment wins in
+# make, the blocks below are listed in the reversed order of preference.
if MHD_USE_SHA512_256_INTR
sha512_256_OPTSOURCES = \
- sha512_256_int.c sha512_256_int.h \
- mhd_sha256.h
+ sha512_256_builtin.c sha512_256_builtin.h \
+ mhd_sha512_256.h
endif
-if MHD_USE_SHA512_256_OPENSSL
+if MHD_USE_SHA512_256_MBEDTLS
sha512_256_OPTSOURCES = \
- sha512_256_ext.h mhd_sha512_256.h \
- sha512_256_ext_openssl.c
+ sha512_256_mbedtls.c sha512_256_mbedtls.h \
+ mhd_sha512_256.h
endif
-if MHD_USE_SHA512_256_MBEDTLS
+if MHD_USE_SHA512_256_OPENSSL
sha512_256_OPTSOURCES = \
- sha512_256_ext.h mhd_sha512_256.h \
- sha512_256_ext_mbedtls.c
+ sha512_256_openssl.c sha512_256_openssl.h \
+ mhd_sha512_256.h
endif
diff --git a/src/mhd2/auth_digest.c b/src/mhd2/auth_digest.c
@@ -325,7 +325,7 @@ gen_new_nonce (struct MHD_Daemon *restrict d,
gen_num = mhd_atomic_counter_get_inc_wrap (&(d->auth_dg.num_gen_nonces));
#if defined(MHD_SUPPORT_SHA512_256)
- mhd_SHA512_256_init_one_time (&(d_ctx.sha512_256_ctx));
+ mhd_SHA512_256_init (&(d_ctx.sha512_256_ctx));
mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx),
d->auth_dg.entropy.size,
(const uint8_t *)d->auth_dg.entropy.data);
@@ -1621,7 +1621,7 @@ digest_init_one_time (struct DigestAlgorithm *da,
# ifndef NDEBUG
da->algo_selected = true;
# endif
- mhd_SHA512_256_init_one_time (&(da->ctx.sha512_256_ctx));
+ mhd_SHA512_256_init (&(da->ctx.sha512_256_ctx));
# ifndef NDEBUG
da->ready_for_hashing = true;
# endif
@@ -1796,17 +1796,10 @@ digest_calc_hash (struct DigestAlgorithm *da,
case MHD_DIGEST_BASE_ALGO_SHA512_256:
#ifdef MHD_SUPPORT_SHA512_256
-# ifdef mhd_SHA512_256_HAS_FINISH
mhd_SHA512_256_finish (&da->ctx.sha512_256_ctx, digest);
-# ifndef NDEBUG
+# ifndef NDEBUG
da->ready_for_hashing = false;
-# endif /* _DEBUG */
-# else /* ! mhd_SHA512_256_HAS_FINISH */
- mhd_SHA512_256_finish_reset (&da->ctx.sha512_256_ctx, digest);
-# ifndef NDEBUG
- da->ready_for_hashing = true;
-# endif /* _DEBUG */
-# endif /* ! mhd_SHA512_256_HAS_FINISH */
+# endif /* _DEBUG */
#else /* ! MHD_SUPPORT_SHA512_256 */
mhd_UNREACHABLE ();
#endif /* ! MHD_SUPPORT_SHA512_256 */
@@ -1862,11 +1855,7 @@ digest_reset (struct DigestAlgorithm *da)
case MHD_DIGEST_BASE_ALGO_SHA512_256:
#ifdef MHD_SUPPORT_SHA512_256
-# ifdef mhd_SHA512_256_HAS_FINISH
mhd_assert (!da->ready_for_hashing);
-# else /* ! mhd_SHA512_256_HAS_FINISH */
- mhd_assert (da->ready_for_hashing);
-# endif /* ! mhd_SHA512_256_HAS_FINISH */
mhd_SHA512_256_reset (&(da->ctx.sha512_256_ctx));
# ifndef NDEBUG
da->ready_for_hashing = true;
diff --git a/src/mhd2/mhd_sha512_256.h b/src/mhd2/mhd_sha512_256.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
/*
This file is part of GNU libmicrohttpd.
- Copyright (C) 2022-2024 Evgeny Grin (Karlson2k)
+ Copyright (C) 2022-2026 Evgeny Grin (Karlson2k)
GNU libmicrohttpd is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -38,8 +38,14 @@
/**
* @file src/mhd2/mhd_sha512_256.h
- * @brief Simple wrapper for selection of built-in/external SHA-512/256
- * implementation
+ * @brief Simple wrapper for selecting the SHA-512/256 implementation backend
+ *
+ * Usage: declare a context as 'struct mhd_Sha512_256Ctx', then call
+ * mhd_SHA512_256_init(), mhd_SHA512_256_update() (any number of times) and
+ * mhd_SHA512_256_finish() to get the digest. Reuse the context with
+ * mhd_SHA512_256_reset() or release it with mhd_SHA512_256_deinit(). With some
+ * backends an operation can fail; check with mhd_SHA512_256_has_err().
+ *
* @author Karlson2k (Evgeny Grin)
*/
@@ -51,83 +57,209 @@
#ifndef MHD_SUPPORT_SHA512_256
# error This file must be used only when SHA-512/256 is enabled
#endif
-#ifndef MHD_SHA512_256_EXTR
-# include "sha512_256_int.h"
-#else /* MHD_SHA512_256_EXTR */
-# include "sha512_256_ext.h"
-#endif /* MHD_SHA512_256_EXTR */
-#ifndef mhd_SHA512_256_DIGEST_SIZE
+#include "mhd_macro_concat.h"
+
+#if defined(MHD_SHA512_256_EXTR_OPENSSL)
+# include "sha512_256_openssl.h"
+
+/**
+ * The hashing backend identifier for function names
+ */
+# define mhd_SHA512_256_FUNC_NAME_ID ossl
+/**
+ * The hashing backend identifier for data names
+ */
+# define mhd_SHA512_256_DATA_NAME_ID Ossl
+/**
+ * The hashing backend identifier for macro names
+ */
+# define mhd_SHA512_256_MACRO_NAME_ID OSSL
+
+#elif defined(MHD_SHA512_256_EXTR_MBEDTLS)
+# include "sha512_256_mbedtls.h"
+
+/**
+ * The hashing backend identifier for function names
+ */
+# define mhd_SHA512_256_FUNC_NAME_ID mtls
/**
- * Size of SHA-512/256 resulting digest in bytes
- * This is the final digest size, not intermediate hash.
+ * The hashing backend identifier for data names
*/
-# define mhd_SHA512_256_DIGEST_SIZE (32)
-#endif /* ! mhd_SHA512_256_DIGEST_SIZE */
+# define mhd_SHA512_256_DATA_NAME_ID Mtls
+/**
+ * The hashing backend identifier for macro names
+ */
+# define mhd_SHA512_256_MACRO_NAME_ID MTLS
+#elif !defined(MHD_SHA512_256_EXTR)
+# include "sha512_256_builtin.h"
-#ifndef MHD_SHA512_256_EXTR
/**
- * Universal ctx type mapped for chosen implementation
+ * The hashing backend identifier for function names
+ */
+# define mhd_SHA512_256_FUNC_NAME_ID blti
+/**
+ * The hashing backend identifier for data names
*/
-# define mhd_Sha512_256Ctx mhd_Sha512_256CtxInt
-#else /* MHD_SHA512_256_EXTR */
+# define mhd_SHA512_256_DATA_NAME_ID Blti
/**
- * Universal ctx type mapped for chosen implementation
+ * The hashing backend identifier for macro names
*/
-# define mhd_Sha512_256Ctx mhd_Sha512_256CtxExt
-#endif /* MHD_SHA512_256_EXTR */
+# define mhd_SHA512_256_MACRO_NAME_ID BLTI
+#else
+# error No SHA-512/256 implementation enabled
+#endif
+
+#if mhd_SHA512_256_DIGEST_SIZE != 32
+# error Wrong value of mhd_SHA512_256_DIGEST_SIZE
+#endif
-#ifndef mhd_SHA512_256_HAS_INIT_ONE_TIME
/**
- * Setup and prepare ctx for hash calculation
+ * Form the name of the function specific to the selected hashing backend
*/
-# define mhd_SHA512_256_init_one_time(ctx) mhd_SHA512_256_init (ctx)
-#endif /* ! mhd_SHA512_256_HAS_INIT_ONE_TIME */
+#define mhd_SHA512_256_FUNC(name_suffix) \
+ mhd_MACRO_CONCAT3 (mhd_SHA512_256_,mhd_SHA512_256_FUNC_NAME_ID, \
+ name_suffix)
-#ifndef mhd_SHA512_256_HAS_DEINIT
-# define mhd_SHA512_256_deinit(ctx) ((void) 0)
-#endif /* HAVE_SHA512_256_DEINIT */
+/**
+ * Form the name of the macro specific to the selected hashing backend
+ */
+#define mhd_SHA512_256_MACRO(name_suffix) \
+ mhd_MACRO_CONCAT3 (mhd_SHA512_256_,mhd_SHA512_256_MACRO_NAME_ID, \
+ name_suffix)
-#ifndef mhd_SHA512_256_HAS_FINISH_RESET
/**
- * Re-use the same ctx for the new hashing after digest calculated
+ * Struct tag of the calculation context for the selected SHA-512/256 backend
*/
-# define mhd_SHA512_256_reset(ctx) mhd_SHA512_256_init (ctx)
+#define mhd_Sha512_256Ctx \
+ mhd_MACRO_CONCAT (mhd_Sha512_256Ctx,mhd_SHA512_256_DATA_NAME_ID)
+
+
+#if 0 != mhd_SHA512_256_MACRO (_EXT_ERROR_FLAG)
/**
- * Finalise hash calculation, return digest, reset hash calculation.
+ * Indicates that SHA-512/256 hashing or initialisation may result in an error
*/
-# define mhd_SHA512_256_finish_reset(ctx, digest) \
- (mhd_SHA512_256_finish (ctx,digest), mhd_SHA512_256_reset (ctx))
+# define mhd_SHA512_256_HAS_EXT_ERROR 1
/**
- * Finalise hash calculation, return digest, de-initialise hash calculation.
+ * 'true' if the hashing backend has reported an error
*/
-# define mhd_SHA512_256_finish_deinit(ctx, digest) \
- (mhd_SHA512_256_finish (ctx,digest), mhd_SHA512_256_deinit (ctx))
-#else /* mhd_SHA512_256_HAS_FINISH_RESET */
+# define mhd_SHA512_256_has_err(ctx) (!!((ctx)->ext_error))
/**
- * Finalise SHA-512/256 calculation, return digest
+ * Get the error number reported by hashing backend (zero if no error)
*/
-# define mhd_SHA512_256_finish(ctx, digest) \
- mhd_SHA512_256_finish_reset(ctx, digest)
-# define mhd_SHA512_256_reset(ctx) ((void) 0)
+# define mhd_SHA512_256_get_err(ctx) ((int)((ctx)->ext_error))
+#else
+# define mhd_SHA512_256_has_err(ctx) (((void) (ctx)), !!0)
/**
- * Finalise hash calculation, return digest, de-initialise hash calculation.
+ * Get the error number (zero if no error)
*/
-# define mhd_SHA512_256_finish_deinit(ctx, digest) \
- (mhd_SHA512_256_finish_reset (ctx,digest), mhd_SHA512_256_deinit (ctx))
-#endif /* mhd_SHA512_256_HAS_FINISH_RESET */
+# define mhd_SHA512_256_get_err(ctx) ((int)(0))
+#endif
-/* Sanity checks */
+/**
+ * Initialise the context for SHA-512/256 calculation.
+ *
+ * This function must not be called more than once for @a ctx without an
+ * intervening #mhd_SHA512_256_deinit().
+ *
+ * For backends that track errors (see #mhd_SHA512_256_has_err()), the error
+ * state is set according to the result: cleared on success, set on failure.
+ *
+ * @param ctx the calculation context
+ */
+#define mhd_SHA512_256_init(ctx) mhd_SHA512_256_FUNC(_init) ((ctx))
+
+/**
+ * Add a portion of data to the SHA-512/256 calculation.
+ *
+ * For backends that track errors (see #mhd_SHA512_256_has_err()), this does
+ * nothing if @a ctx already has a recorded error, and records an error on
+ * failure.
+ *
+ * @param ctx the calculation context
+ * @param size number of bytes in @a data, must not be 0
+ * @param data bytes to add to hash
+ */
+#define mhd_SHA512_256_update(ctx, size, data) \
+ mhd_SHA512_256_FUNC(_update) ((ctx),(size),(data))
+
+/**
+ * Finalise the SHA-512/256 calculation and return the digest.
+ *
+ * For backends that track errors (see #mhd_SHA512_256_has_err()), this does
+ * nothing if @a ctx already has a recorded error, and may record an error on
+ * failure.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
+ */
+#define mhd_SHA512_256_finish(ctx, digest) \
+ mhd_SHA512_256_FUNC(_finish) ((ctx),(digest))
+
+/**
+ * Reset the context for a new SHA-512/256 calculation.
+ *
+ * This function may be called only after #mhd_SHA512_256_finish(). If the
+ * context is subsequently reused for a new calculation, this function must be
+ * called before starting that calculation.
+ *
+ * For backends that track errors (see #mhd_SHA512_256_has_err()), this does
+ * nothing if @a ctx already has a recorded error, and may record an error on
+ * failure.
+ *
+ * @param ctx the calculation context
+ */
+#define mhd_SHA512_256_reset(ctx) mhd_SHA512_256_FUNC(_reset) ((ctx))
-#if !defined(mhd_SHA512_256_HAS_FINISH_RESET) && \
- !defined(mhd_SHA512_256_HAS_FINISH)
-# error Required mhd_SHA512_256_finish_reset() or mhd_SHA512_256_finish()
-#endif /* ! mhd_SHA512_256_HAS_FINISH_RESET && ! mhd_SHA512_256_HAS_FINISH */
+/**
+ * Finalise the SHA-512/256 calculation, return the digest and reset the
+ * context.
+ *
+ * For backends that track errors (see #mhd_SHA512_256_has_err()): if @a ctx
+ * already has a recorded error, this does nothing and the error is preserved.
+ * Otherwise, an error is recorded in @a ctx if either the finalisation or the
+ * reset fails. A recorded error is never cleared by this macro.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
+ */
+#define mhd_SHA512_256_finish_reset(ctx, digest) \
+ (mhd_SHA512_256_finish((ctx),(digest)), mhd_SHA512_256_reset((ctx)))
+
+/**
+ * Deinitialise the SHA-512/256 calculation context.
+ *
+ * After calling this function, @a ctx can be reinitialised with
+ * #mhd_SHA512_256_init().
+ *
+ * For backends that track errors (see #mhd_SHA512_256_has_err()), the recorded
+ * error state is preserved.
+ *
+ * @param ctx the calculation context
+ */
+#define mhd_SHA512_256_deinit(ctx) mhd_SHA512_256_FUNC(_deinit) ((ctx))
+
+/**
+ * Finalise the SHA-512/256 calculation, return the digest and deinitialise
+ * the context.
+ *
+ * For backends that track errors (see #mhd_SHA512_256_has_err()): if @a ctx
+ * already has a recorded error, the error is preserved. Otherwise, an error is
+ * recorded in @a ctx if the finalisation fails.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
+ */
+#define mhd_SHA512_256_finish_deinit(ctx, digest) \
+ (mhd_SHA512_256_finish((ctx),(digest)), mhd_SHA512_256_deinit((ctx)))
+
+#if 0 == mhd_SHA512_256_MACRO (_DEINIT_NOOP_FLAG)
+/**
+ * Indicates that #mhd_SHA512_256_deinit() is a real function that must be
+ * called.
+ */
+# define mhd_SHA512_256_HAS_DEINIT
+#endif
-#ifdef mhd_SHA512_256_HAS_EXT_ERROR
-# define mhd_SHA512_256_has_err(ctx) (0 != ((ctx)->ext_error))
-#else /* ! mhd_SHA512_256_HAS_EXT_ERROR */
-# define mhd_SHA512_256_has_err(ctx) (((void) (ctx)), ! ! 0)
-#endif /* ! mhd_SHA512_256_HAS_EXT_ERROR */
#endif /* MHD_SHA512_256_H */
diff --git a/src/mhd2/sha512_256_builtin.c b/src/mhd2/sha512_256_builtin.c
@@ -0,0 +1,648 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
+/*
+ This file is part of GNU libmicrohttpd.
+ Copyright (C) 2022-2026 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd 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.
+
+ GNU libmicrohttpd 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.
+
+ Alternatively, you can redistribute GNU libmicrohttpd and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version, together
+ with the eCos exception, as follows:
+
+ As a special exception, if other files instantiate templates or
+ use macros or inline functions from this file, or you compile this
+ file and link it with other works to produce a work based on this
+ file, this file does not by itself cause the resulting work to be
+ covered by the GNU General Public License. However the source code
+ for this file must still be made available in accordance with
+ section (3) of the GNU General Public License v2.
+
+ This exception does not invalidate any other reasons why a work
+ based on this file might be covered by the GNU General Public
+ License.
+
+ You should have received copies of the GNU Lesser General Public
+ License and the GNU General Public License along with this library;
+ if not, see <https://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file src/mhd2/sha512_256_builtin.c
+ * @brief Calculation of SHA-512/256 digest, built-in implementation as defined in FIPS PUB 180-4 (2015)
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "mhd_sys_options.h"
+
+#include "sys_bool_type.h"
+
+#include <string.h>
+#include "mhd_bithelpers.h"
+#include "mhd_align.h"
+#include "mhd_assert.h"
+
+#include "sha512_256_builtin.h"
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1) void
+mhd_SHA512_256_blti_init (struct mhd_Sha512_256CtxBlti *ctx)
+{
+ /* Initial hash values, see FIPS PUB 180-4 clause 5.3.6.2 */
+ /* Values generated by "IV Generation Function" as described in
+ * clause 5.3.6 */
+ ctx->H[0] = UINT64_C (0x22312194FC2BF72C);
+ ctx->H[1] = UINT64_C (0x9F555FA3C84C64C2);
+ ctx->H[2] = UINT64_C (0x2393B86B6F53B151);
+ ctx->H[3] = UINT64_C (0x963877195940EABD);
+ ctx->H[4] = UINT64_C (0x96283EE2A88EFFE3);
+ ctx->H[5] = UINT64_C (0xBE5E1E2553863992);
+ ctx->H[6] = UINT64_C (0x2B0199FC2C85B8AA);
+ ctx->H[7] = UINT64_C (0x0EB72DDC81C52CA2);
+
+ /* Initialise number of bytes and high part of number of bits. */
+ ctx->count = 0;
+ ctx->count_bits_hi = 0;
+}
+
+
+mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE
+
+/**
+ * Base of SHA-512/256 transformation.
+ * Gets full 128 bytes block of data and updates hash values;
+ * @param H hash values
+ * @param data the data buffer with #mhd_SHA512_256_BLOCK_SIZE bytes block
+ */
+static MHD_FN_PAR_NONNULL_ALL_ void
+sha512_256_transform (uint64_t H[mhd_SHA512_256_HASH_SIZE_WORDS],
+ const void *restrict data)
+{
+ /* Working variables,
+ see FIPS PUB 180-4 clause 6.7, 6.4. */
+ uint64_t a = H[0];
+ uint64_t b = H[1];
+ uint64_t c = H[2];
+ uint64_t d = H[3];
+ uint64_t e = H[4];
+ uint64_t f = H[5];
+ uint64_t g = H[6];
+ uint64_t h = H[7];
+
+ /* Data buffer, used as a cyclic buffer.
+ See FIPS PUB 180-4 clause 5.2.2, 6.7, 6.4. */
+ uint64_t W[16];
+
+#ifndef mhd_GET_64BIT_BE_ALLOW_UNALIGNED
+ if (0 != (((uintptr_t)data) % mhd_UINT64_ALIGN))
+ { /* The input data is unaligned */
+ /* Copy the unaligned input data to the aligned buffer */
+ memcpy (W, data, sizeof(W));
+ /* The W[] buffer itself will be used as the source of the data,
+ * but the data will be reloaded in correct bytes order on
+ * the next steps */
+ data = (const void *)W;
+ }
+#endif /* mhd_GET_64BIT_BE_ALLOW_UNALIGNED */
+
+ /* 'Ch' and 'Maj' macro functions are defined with
+ widely-used optimisation.
+ See FIPS PUB 180-4 formulae 4.8, 4.9. */
+#define Ch(x, y, z) ( (z) ^ ((x) & ((y) ^ (z))) )
+#define Maj(x, y, z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
+ /* Unoptimized (original) versions: */
+/* #define Ch(x,y,z) ( ( (x) & (y) ) ^ ( ~(x) & (z) ) ) */
+/* #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */
+
+ /* Four 'Sigma' macro functions.
+ See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
+#define SIG0(x) \
+ (mhd_ROTR64 ((x), 28) ^ mhd_ROTR64 ((x), 34) ^ mhd_ROTR64 ((x), 39) )
+#define SIG1(x) \
+ (mhd_ROTR64 ((x), 14) ^ mhd_ROTR64 ((x), 18) ^ mhd_ROTR64 ((x), 41) )
+#define sig0(x) \
+ (mhd_ROTR64 ((x), 1) ^ mhd_ROTR64 ((x), 8) ^ ((x) >> 7) )
+#define sig1(x) \
+ (mhd_ROTR64 ((x), 19) ^ mhd_ROTR64 ((x), 61) ^ ((x) >> 6) )
+
+ /* One step of SHA-512/256 computation,
+ see FIPS PUB 180-4 clause 6.4.2 step 3.
+ * Note: this macro updates working variables in-place, without rotation.
+ * Note: the first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in
+ FIPS PUB 180-4 clause 6.4.2 step 3.
+ the second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in
+ FIPS PUB 180-4 clause 6.4.2 step 3.
+ * Note: 'wt' must be used exactly one time in this macro as it change other
+ data as well every time when used. */
+#define SHA2STEP64(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) do { \
+ (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \
+ (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0)
+
+ /* Get value of W(t) from input data buffer for 0 <= t <= 15,
+ See FIPS PUB 180-4 clause 6.2.
+ Input data must be read in big-endian bytes order,
+ see FIPS PUB 180-4 clause 3.1.2. */
+#define GET_W_FROM_DATA(buf, t) \
+ mhd_GET_64BIT_BE (((const uint64_t*) (buf)) + (t))
+
+ /* 'W' generation and assignment for 16 <= t <= 79.
+ See FIPS PUB 180-4 clause 6.4.2.
+ As only last 16 'W' are used in calculations, it is possible to
+ use 16 elements array of W as a cyclic buffer.
+ * Note: ((t-16) & 15) have same value as (t & 15) */
+#define Wgen(w, t) ( (w)[(t - 16) & 15] + sig1 ((w)[((t) - 2) & 15]) \
+ + (w)[((t) - 7) & 15] + sig0 ((w)[((t) - 15) & 15]) )
+
+#ifndef MHD_FAVOR_SMALL_CODE
+
+ /* Note: instead of using K constants as array, all K values are specified
+ individually for each step, see FIPS PUB 180-4 clause 4.2.3 for
+ K values. */
+ /* Note: instead of reassigning all working variables on each step,
+ variables are rotated for each step:
+ SHA2STEP64(a, b, c, d, e, f, g, h, K[0], data[0]);
+ SHA2STEP64(h, a, b, c, d, e, f, g, K[1], data[1]);
+ so current 'vD' will be used as 'vE' on next step,
+ current 'vH' will be used as 'vA' on next step. */
+# if mhd_BYTE_ORDER == mhd_BIG_ENDIAN
+ if ((const void *)W == data)
+ {
+ /* The input data is already in the cyclic data buffer W[] in correct bytes
+ order. */
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x428a2f98d728ae22), W[0]);
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x7137449123ef65cd), W[1]);
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xb5c0fbcfec4d3b2f), W[2]);
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xe9b5dba58189dbbc), W[3]);
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x3956c25bf348b538), W[4]);
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x59f111f1b605d019), W[5]);
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x923f82a4af194f9b), W[6]);
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xab1c5ed5da6d8118), W[7]);
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xd807aa98a3030242), W[8]);
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x12835b0145706fbe), W[9]);
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x243185be4ee4b28c), W[10]);
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x550c7dc3d5ffb4e2), W[11]);
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x72be5d74f27b896f), W[12]);
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x80deb1fe3b1696b1), W[13]);
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x9bdc06a725c71235), W[14]);
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xc19bf174cf692694), W[15]);
+ }
+ else /* Combined with the next 'if' */
+# endif /* mhd_BYTE_ORDER == mhd_BIG_ENDIAN */
+ if (1)
+ {
+ /* During first 16 steps, before making any calculations on each step,
+ the W element is read from the input data buffer as big-endian value and
+ stored in the array of W elements. */
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x428a2f98d728ae22), \
+ W[0] = GET_W_FROM_DATA (data, 0));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x7137449123ef65cd), \
+ W[1] = GET_W_FROM_DATA (data, 1));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xb5c0fbcfec4d3b2f), \
+ W[2] = GET_W_FROM_DATA (data, 2));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xe9b5dba58189dbbc), \
+ W[3] = GET_W_FROM_DATA (data, 3));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x3956c25bf348b538), \
+ W[4] = GET_W_FROM_DATA (data, 4));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x59f111f1b605d019), \
+ W[5] = GET_W_FROM_DATA (data, 5));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x923f82a4af194f9b), \
+ W[6] = GET_W_FROM_DATA (data, 6));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xab1c5ed5da6d8118), \
+ W[7] = GET_W_FROM_DATA (data, 7));
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xd807aa98a3030242), \
+ W[8] = GET_W_FROM_DATA (data, 8));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x12835b0145706fbe), \
+ W[9] = GET_W_FROM_DATA (data, 9));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x243185be4ee4b28c), \
+ W[10] = GET_W_FROM_DATA (data, 10));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x550c7dc3d5ffb4e2), \
+ W[11] = GET_W_FROM_DATA (data, 11));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x72be5d74f27b896f), \
+ W[12] = GET_W_FROM_DATA (data, 12));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x80deb1fe3b1696b1), \
+ W[13] = GET_W_FROM_DATA (data, 13));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x9bdc06a725c71235), \
+ W[14] = GET_W_FROM_DATA (data, 14));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xc19bf174cf692694), \
+ W[15] = GET_W_FROM_DATA (data, 15));
+ }
+
+ /* During last 64 steps, before making any calculations on each step,
+ current W element is generated from other W elements of the cyclic buffer
+ and the generated value is stored back in the cyclic buffer. */
+ /* Note: instead of using K constants as array, all K values are specified
+ individually for each step, see FIPS PUB 180-4 clause 4.2.3 for
+ K values. */
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xe49b69c19ef14ad2), \
+ W[16 & 15] = Wgen (W, 16));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xefbe4786384f25e3), \
+ W[17 & 15] = Wgen (W, 17));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x0fc19dc68b8cd5b5), \
+ W[18 & 15] = Wgen (W, 18));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x240ca1cc77ac9c65), \
+ W[19 & 15] = Wgen (W, 19));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x2de92c6f592b0275), \
+ W[20 & 15] = Wgen (W, 20));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x4a7484aa6ea6e483), \
+ W[21 & 15] = Wgen (W, 21));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x5cb0a9dcbd41fbd4), \
+ W[22 & 15] = Wgen (W, 22));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x76f988da831153b5), \
+ W[23 & 15] = Wgen (W, 23));
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x983e5152ee66dfab), \
+ W[24 & 15] = Wgen (W, 24));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xa831c66d2db43210), \
+ W[25 & 15] = Wgen (W, 25));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xb00327c898fb213f), \
+ W[26 & 15] = Wgen (W, 26));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xbf597fc7beef0ee4), \
+ W[27 & 15] = Wgen (W, 27));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0xc6e00bf33da88fc2), \
+ W[28 & 15] = Wgen (W, 28));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0xd5a79147930aa725), \
+ W[29 & 15] = Wgen (W, 29));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x06ca6351e003826f), \
+ W[30 & 15] = Wgen (W, 30));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x142929670a0e6e70), \
+ W[31 & 15] = Wgen (W, 31));
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x27b70a8546d22ffc), \
+ W[32 & 15] = Wgen (W, 32));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x2e1b21385c26c926), \
+ W[33 & 15] = Wgen (W, 33));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x4d2c6dfc5ac42aed), \
+ W[34 & 15] = Wgen (W, 34));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x53380d139d95b3df), \
+ W[35 & 15] = Wgen (W, 35));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x650a73548baf63de), \
+ W[36 & 15] = Wgen (W, 36));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x766a0abb3c77b2a8), \
+ W[37 & 15] = Wgen (W, 37));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x81c2c92e47edaee6), \
+ W[38 & 15] = Wgen (W, 38));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x92722c851482353b), \
+ W[39 & 15] = Wgen (W, 39));
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xa2bfe8a14cf10364), \
+ W[40 & 15] = Wgen (W, 40));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xa81a664bbc423001), \
+ W[41 & 15] = Wgen (W, 41));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xc24b8b70d0f89791), \
+ W[42 & 15] = Wgen (W, 42));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xc76c51a30654be30), \
+ W[43 & 15] = Wgen (W, 43));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0xd192e819d6ef5218), \
+ W[44 & 15] = Wgen (W, 44));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0xd69906245565a910), \
+ W[45 & 15] = Wgen (W, 45));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0xf40e35855771202a), \
+ W[46 & 15] = Wgen (W, 46));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x106aa07032bbd1b8), \
+ W[47 & 15] = Wgen (W, 47));
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x19a4c116b8d2d0c8), \
+ W[48 & 15] = Wgen (W, 48));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x1e376c085141ab53), \
+ W[49 & 15] = Wgen (W, 49));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x2748774cdf8eeb99), \
+ W[50 & 15] = Wgen (W, 50));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x34b0bcb5e19b48a8), \
+ W[51 & 15] = Wgen (W, 51));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x391c0cb3c5c95a63), \
+ W[52 & 15] = Wgen (W, 52));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x4ed8aa4ae3418acb), \
+ W[53 & 15] = Wgen (W, 53));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x5b9cca4f7763e373), \
+ W[54 & 15] = Wgen (W, 54));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x682e6ff3d6b2b8a3), \
+ W[55 & 15] = Wgen (W, 55));
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x748f82ee5defb2fc), \
+ W[56 & 15] = Wgen (W, 56));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x78a5636f43172f60), \
+ W[57 & 15] = Wgen (W, 57));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x84c87814a1f0ab72), \
+ W[58 & 15] = Wgen (W, 58));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x8cc702081a6439ec), \
+ W[59 & 15] = Wgen (W, 59));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x90befffa23631e28), \
+ W[60 & 15] = Wgen (W, 60));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0xa4506cebde82bde9), \
+ W[61 & 15] = Wgen (W, 61));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0xbef9a3f7b2c67915), \
+ W[62 & 15] = Wgen (W, 62));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xc67178f2e372532b), \
+ W[63 & 15] = Wgen (W, 63));
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xca273eceea26619c), \
+ W[64 & 15] = Wgen (W, 64));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xd186b8c721c0c207), \
+ W[65 & 15] = Wgen (W, 65));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xeada7dd6cde0eb1e), \
+ W[66 & 15] = Wgen (W, 66));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xf57d4f7fee6ed178), \
+ W[67 & 15] = Wgen (W, 67));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x06f067aa72176fba), \
+ W[68 & 15] = Wgen (W, 68));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x0a637dc5a2c898a6), \
+ W[69 & 15] = Wgen (W, 69));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x113f9804bef90dae), \
+ W[70 & 15] = Wgen (W, 70));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x1b710b35131c471b), \
+ W[71 & 15] = Wgen (W, 71));
+ SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x28db77f523047d84), \
+ W[72 & 15] = Wgen (W, 72));
+ SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x32caab7b40c72493), \
+ W[73 & 15] = Wgen (W, 73));
+ SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x3c9ebe0a15c9bebc), \
+ W[74 & 15] = Wgen (W, 74));
+ SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x431d67c49c100d4c), \
+ W[75 & 15] = Wgen (W, 75));
+ SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x4cc5d4becb3e42b6), \
+ W[76 & 15] = Wgen (W, 76));
+ SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x597f299cfc657e2a), \
+ W[77 & 15] = Wgen (W, 77));
+ SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x5fcb6fab3ad6faec), \
+ W[78 & 15] = Wgen (W, 78));
+ SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x6c44198c4a475817), \
+ W[79 & 15] = Wgen (W, 79));
+#else /* MHD_FAVOR_SMALL_CODE */
+ if (1)
+ {
+ unsigned int t;
+ /* K constants array.
+ See FIPS PUB 180-4 clause 4.2.3 for K values. */
+ static const uint64_t K[80] =
+ { UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
+ UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
+ UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
+ UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
+ UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
+ UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
+ UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
+ UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
+ UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
+ UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
+ UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
+ UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
+ UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
+ UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
+ UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
+ UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
+ UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
+ UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
+ UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
+ UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
+ UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
+ UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
+ UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
+ UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
+ UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
+ UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
+ UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
+ UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
+ UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
+ UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
+ UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
+ UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
+ UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
+ UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
+ UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
+ UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
+ UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
+ UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
+ UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
+ UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)};
+
+ /* One step of SHA-512/256 computation with working variables rotation,
+ see FIPS PUB 180-4 clause 6.4.2 step 3.
+ * Note: this version of macro reassign all working variable on
+ each step. */
+# define SHA2STEP64RV(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) \
+ do { \
+ uint64_t tmp_h_ = (vH); \
+ SHA2STEP64 ((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt)); \
+ (vH) = (vG); \
+ (vG) = (vF); \
+ (vF) = (vE); \
+ (vE) = (vD); \
+ (vD) = (vC); \
+ (vC) = (vB); \
+ (vB) = (vA); \
+ (vA) = tmp_h_; \
+ } while (0)
+
+ /* During first 16 steps, before making any calculations on each step,
+ the W element is read from the input data buffer as big-endian value and
+ stored in the array of W elements. */
+ for (t = 0; t < 16; ++t)
+ {
+ SHA2STEP64RV (a, b, c, d, e, f, g, h, K[t], \
+ W[t] = GET_W_FROM_DATA (data, t));
+ }
+ /* During last 64 steps, before making any calculations on each step,
+ current W element is generated from other W elements of the cyclic buffer
+ and the generated value is stored back in the cyclic buffer. */
+ for (t = 16; t < 80; ++t)
+ {
+ SHA2STEP64RV (a, b, c, d, e, f, g, h, K[t], \
+ W[t & 15] = Wgen (W, t));
+ }
+ }
+#endif /* MHD_FAVOR_SMALL_CODE */
+
+ /* Compute and store the intermediate hash.
+ See FIPS PUB 180-4 clause 6.4.2 step 4. */
+ H[0] += a;
+ H[1] += b;
+ H[2] += c;
+ H[3] += d;
+ H[4] += e;
+ H[5] += f;
+ H[6] += g;
+ H[7] += h;
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_IN_SIZE_ (3, 2) void
+mhd_SHA512_256_blti_update (struct mhd_Sha512_256CtxBlti *restrict ctx,
+ size_t size,
+ const void *restrict data)
+{
+ unsigned int bytes_have; /**< Number of bytes in the context buffer */
+ uint64_t count_hi; /**< The high part to be moved to another variable */
+ const uint8_t *unpr_d;
+
+ unpr_d = (const uint8_t *)data;
+
+#ifndef MHD_UNIT_TESTING
+ mhd_assert (0 != size);
+#endif
+
+ /* Note: (count & (mhd_SHA512_256_BLOCK_SIZE-1))
+ equals (count % mhd_SHA512_256_BLOCK_SIZE) for this block size. */
+ bytes_have = (unsigned int)(ctx->count & (mhd_SHA512_256_BLOCK_SIZE - 1));
+ ctx->count += size;
+#if SIZEOF_SIZE_T > 7
+ if (size > ctx->count)
+ ctx->count_bits_hi += 1U << 3; /* Value wrap */
+#endif /* SIZEOF_SIZE_T > 7 */
+ count_hi = ctx->count >> 61;
+ if (0 != count_hi)
+ {
+ ctx->count_bits_hi += count_hi;
+ ctx->count &= UINT64_C (0x1FFFFFFFFFFFFFFF);
+ }
+
+ if (0 != bytes_have)
+ {
+ unsigned int bytes_left = mhd_SHA512_256_BLOCK_SIZE - bytes_have;
+ if (size >= bytes_left)
+ { /* Combine new data with data in the buffer and
+ process the full block. */
+ memcpy (((uint8_t *)ctx->buffer) + bytes_have,
+ unpr_d,
+ bytes_left);
+ unpr_d += bytes_left;
+ size -= bytes_left;
+ sha512_256_transform (ctx->H, ctx->buffer);
+ bytes_have = 0;
+ }
+ }
+
+ while (mhd_SHA512_256_BLOCK_SIZE <= size)
+ { /* Process any full blocks of new data directly,
+ without copying to the buffer. */
+ sha512_256_transform (ctx->H, unpr_d);
+ unpr_d += mhd_SHA512_256_BLOCK_SIZE;
+ size -= mhd_SHA512_256_BLOCK_SIZE;
+ }
+
+ if (0 != size)
+ { /* Copy incomplete block of new data (if any)
+ to the buffer. */
+ memcpy (((uint8_t *)ctx->buffer) + bytes_have, unpr_d, size);
+ }
+}
+
+
+/**
+ * Size of "length" insertion in bits.
+ * See FIPS PUB 180-4 clause 5.1.2.
+ */
+#define SHA512_256_SIZE_OF_LEN_ADD_BITS 128
+
+/**
+ * Size of "length" insertion in bytes.
+ */
+#define SHA512_256_SIZE_OF_LEN_ADD (SHA512_256_SIZE_OF_LEN_ADD_BITS / 8)
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_OUT_ (2) void
+mhd_SHA512_256_blti_finish (
+ struct mhd_Sha512_256CtxBlti *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA512_256_DIGEST_SIZE)])
+{
+ uint64_t num_bits; /**< Number of processed bits */
+ unsigned int bytes_have; /**< Number of bytes in the context buffer */
+
+ /* Memorise the number of processed bits.
+ The padding and other data added here during the postprocessing must
+ not change the amount of hashed data. */
+ num_bits = ctx->count << 3;
+
+ /* Note: (count & (mhd_SHA512_256_BLOCK_SIZE-1))
+ equals (count % mhd_SHA512_256_BLOCK_SIZE) for this block size. */
+ bytes_have = (unsigned int)(ctx->count & (mhd_SHA512_256_BLOCK_SIZE - 1));
+
+ /* Input data must be padded with a single bit "1", then with zeros and
+ the finally the length of data in bits must be added as the final bytes
+ of the last block.
+ See FIPS PUB 180-4 clause 5.1.2. */
+
+ /* Data is always processed in form of bytes (not by individual bits),
+ therefore position of the first padding bit in byte is always
+ predefined (0x80). */
+ /* Buffer always have space for one byte at least (as full buffers are
+ processed immediately). */
+ ((uint8_t *)ctx->buffer)[bytes_have++] = 0x80;
+
+ if (mhd_SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD)
+ { /* No space in the current block to put the total length of message.
+ Pad the current block with zeros and process it. */
+ if (bytes_have < mhd_SHA512_256_BLOCK_SIZE)
+ memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
+ mhd_SHA512_256_BLOCK_SIZE - bytes_have);
+ /* Process the full block. */
+ sha512_256_transform (ctx->H, ctx->buffer);
+ /* Start the new block. */
+ bytes_have = 0;
+ }
+
+ /* Pad the rest of the buffer with zeros. */
+ memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
+ mhd_SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have);
+ /* Put high part of number of bits in processed message and then lower
+ part of number of bits as big-endian values.
+ See FIPS PUB 180-4 clause 5.1.2. */
+ /* Note: the target location is predefined and buffer is always aligned */
+ mhd_PUT_64BIT_BE (ctx->buffer + mhd_SHA512_256_BLOCK_SIZE_WORDS - 2,
+ ctx->count_bits_hi);
+ mhd_PUT_64BIT_BE (ctx->buffer + mhd_SHA512_256_BLOCK_SIZE_WORDS - 1,
+ num_bits);
+ /* Process the full final block. */
+ sha512_256_transform (ctx->H, ctx->buffer);
+
+ /* Put in BE mode the leftmost part of the hash as the final digest.
+ See FIPS PUB 180-4 clause 6.7. */
+ if (1)
+ {
+ bool use_tmp_buf_to_align_result;
+
+#if defined(mhd_PUT_64BIT_BE_UNALIGNED)
+ use_tmp_buf_to_align_result = false;
+#elif defined(MHD_FAVOR_SMALL_CODE)
+ use_tmp_buf_to_align_result = true; /* smaller code: eliminated branch below */
+#else
+ use_tmp_buf_to_align_result =
+ (0 != ((uintptr_t)digest) % mhd_UINT64_ALIGN);
+#endif
+ if (use_tmp_buf_to_align_result)
+ {
+ /* If storing of the final result requires aligned address and
+ the destination address is not aligned or compact code is used,
+ store the final digest in aligned temporary buffer first, then
+ copy it to the destination. */
+ uint64_t alig_dgst[mhd_SHA512_256_DIGEST_SIZE_WORDS];
+ mhd_PUT_64BIT_BE (alig_dgst + 0, ctx->H[0]);
+ mhd_PUT_64BIT_BE (alig_dgst + 1, ctx->H[1]);
+ mhd_PUT_64BIT_BE (alig_dgst + 2, ctx->H[2]);
+ mhd_PUT_64BIT_BE (alig_dgst + 3, ctx->H[3]);
+ /* Copy result to the unaligned destination address */
+ memcpy (digest, alig_dgst, mhd_SHA512_256_DIGEST_SIZE);
+ }
+ else
+ {
+ /* Use cast to (void*) here to mute compiler alignment warnings.
+ * Compilers are not smart enough to see that alignment has been checked. */
+ mhd_PUT_64BIT_BE ((void *)(digest + 0 * mhd_SHA512_256_BYTES_IN_WORD), \
+ ctx->H[0]);
+ mhd_PUT_64BIT_BE ((void *)(digest + 1 * mhd_SHA512_256_BYTES_IN_WORD), \
+ ctx->H[1]);
+ mhd_PUT_64BIT_BE ((void *)(digest + 2 * mhd_SHA512_256_BYTES_IN_WORD), \
+ ctx->H[2]);
+ mhd_PUT_64BIT_BE ((void *)(digest + 3 * mhd_SHA512_256_BYTES_IN_WORD), \
+ ctx->H[3]);
+ }
+ }
+
+ /* Erase potentially sensitive data. */
+ memset (ctx, 0, sizeof(struct mhd_Sha512_256CtxBlti));
+}
+
+
+mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE
diff --git a/src/mhd2/sha512_256_builtin.h b/src/mhd2/sha512_256_builtin.h
@@ -0,0 +1,192 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
+/*
+ This file is part of GNU libmicrohttpd.
+ Copyright (C) 2022-2026 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd 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.
+
+ GNU libmicrohttpd 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.
+
+ Alternatively, you can redistribute GNU libmicrohttpd and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version, together
+ with the eCos exception, as follows:
+
+ As a special exception, if other files instantiate templates or
+ use macros or inline functions from this file, or you compile this
+ file and link it with other works to produce a work based on this
+ file, this file does not by itself cause the resulting work to be
+ covered by the GNU General Public License. However the source code
+ for this file must still be made available in accordance with
+ section (3) of the GNU General Public License v2.
+
+ This exception does not invalidate any other reasons why a work
+ based on this file might be covered by the GNU General Public
+ License.
+
+ You should have received copies of the GNU Lesser General Public
+ License and the GNU General Public License along with this library;
+ if not, see <https://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file src/mhd2/sha512_256_builtin.h
+ * @brief Calculation of SHA-512/256 digest, built-in implementation
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_SHA512_256_BUILTIN_H
+#define MHD_SHA512_256_BUILTIN_H 1
+
+#include "mhd_sys_options.h"
+
+#include "sys_base_types.h"
+
+
+/**
+ * Number of bits in single SHA-512/256 word.
+ */
+#define mhd_SHA512_256_WORD_SIZE_BITS 64
+
+/**
+ * Number of bytes in single SHA-512/256 word.
+ */
+#define mhd_SHA512_256_BYTES_IN_WORD (mhd_SHA512_256_WORD_SIZE_BITS / 8)
+
+/**
+ * Hash is kept internally as 8 64-bit words.
+ * This is the intermediate hash size, used while computing the final digest.
+ */
+#define mhd_SHA512_256_HASH_SIZE_WORDS 8
+
+/**
+ * Size of SHA-512/256 resulting digest in words.
+ * This is the final digest size, not the intermediate hash.
+ */
+#define mhd_SHA512_256_DIGEST_SIZE_WORDS (mhd_SHA512_256_HASH_SIZE_WORDS / 2)
+
+#ifndef mhd_SHA512_256_DIGEST_SIZE
+/**
+ * Size of SHA-512/256 resulting digest in bytes.
+ * This is the final digest size, not the intermediate hash.
+ */
+# define mhd_SHA512_256_DIGEST_SIZE \
+ (mhd_SHA512_256_DIGEST_SIZE_WORDS * mhd_SHA512_256_BYTES_IN_WORD)
+#endif
+
+/**
+ * Size of SHA-512/256 single processing block in bits.
+ */
+#define mhd_SHA512_256_BLOCK_SIZE_BITS 1024
+
+/**
+ * Size of SHA-512/256 single processing block in bytes.
+ */
+#define mhd_SHA512_256_BLOCK_SIZE (mhd_SHA512_256_BLOCK_SIZE_BITS / 8)
+
+/**
+ * Size of SHA-512/256 single processing block in words.
+ */
+#define mhd_SHA512_256_BLOCK_SIZE_WORDS \
+ (mhd_SHA512_256_BLOCK_SIZE_BITS / mhd_SHA512_256_WORD_SIZE_BITS)
+
+
+/**
+ * SHA-512/256 calculation context
+ */
+struct mhd_Sha512_256CtxBlti
+{
+ uint64_t H[mhd_SHA512_256_HASH_SIZE_WORDS]; /**< Intermediate hash value */
+ uint64_t buffer[mhd_SHA512_256_BLOCK_SIZE_WORDS]; /**< SHA512_256 input data buffer */
+ /**
+ * The number of bytes, lower part
+ */
+ uint64_t count;
+ /**
+ * The number of bits, high part.
+ * Unlike lower part, this counts the number of bits, not bytes.
+ */
+ uint64_t count_bits_hi;
+};
+
+/**
+ * Indicates whether struct mhd_Sha512_256CtxBlti has an 'ext_error' member.
+ *
+ * Set to '0' when the structure has no 'ext_error' member.
+ */
+#define mhd_SHA512_256_BLTI_EXT_ERROR_FLAG 0
+
+/**
+ * Initialise the context for SHA-512/256 calculation.
+ *
+ * This function must not be called more than once for @a ctx without an
+ * intervening #mhd_SHA512_256_blti_deinit().
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_blti_init (struct mhd_Sha512_256CtxBlti *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1);
+
+/**
+ * Add a portion of data to the SHA-512/256 calculation.
+ *
+ * @param ctx the calculation context
+ * @param size number of bytes in @a data, must not be 0
+ * @param data bytes to add to hash
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_blti_update (struct mhd_Sha512_256CtxBlti *restrict ctx,
+ size_t size,
+ const void *restrict data)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_IN_SIZE_ (3, 2);
+
+/**
+ * Finalise the SHA-512/256 calculation and return the digest.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_blti_finish (
+ struct mhd_Sha512_256CtxBlti *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA512_256_DIGEST_SIZE)])
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_OUT_ (2);
+
+/**
+ * Reset the context for a new SHA-512/256 calculation.
+ *
+ * This function may be called only after #mhd_SHA512_256_blti_finish(). If the
+ * context is subsequently reused for a new calculation, this function must be
+ * called before starting that calculation.
+ *
+ * @param ctx the calculation context
+ */
+#define mhd_SHA512_256_blti_reset(ctx) mhd_SHA512_256_blti_init((ctx))
+
+/**
+ * Deinitialise the SHA-512/256 calculation context.
+ *
+ * After calling this function, @a ctx can be reinitialised with
+ * #mhd_SHA512_256_blti_init().
+ *
+ * @param ctx the calculation context
+ */
+#define mhd_SHA512_256_blti_deinit(ctx) ((void) (ctx))
+
+/**
+ * Indicates whether #mhd_SHA512_256_blti_deinit() is a real function or a
+ * no-op.
+ *
+ * Set to '1' as #mhd_SHA512_256_blti_deinit() is a no-op.
+ */
+#define mhd_SHA512_256_BLTI_DEINIT_NOOP_FLAG 1
+
+#endif /* MHD_SHA512_256_BUILTIN_H */
diff --git a/src/mhd2/sha512_256_ext.h b/src/mhd2/sha512_256_ext.h
@@ -1,266 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
-/*
- This file is part of GNU libmicrohttpd.
- Copyright (C) 2025 Christian Grothoff
-
- GNU libmicrohttpd 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.
-
- GNU libmicrohttpd 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.
-
- Alternatively, you can redistribute GNU libmicrohttpd and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version, together
- with the eCos exception, as follows:
-
- As a special exception, if other files instantiate templates or
- use macros or inline functions from this file, or you compile this
- file and link it with other works to produce a work based on this
- file, this file does not by itself cause the resulting work to be
- covered by the GNU General Public License. However the source code
- for this file must still be made available in accordance with
- section (3) of the GNU General Public License v2.
-
- This exception does not invalidate any other reasons why a work
- based on this file might be covered by the GNU General Public
- License.
-
- You should have received copies of the GNU Lesser General Public
- License and the GNU General Public License along with this library;
- if not, see <https://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file microhttpd/sha512_256_ext.h
- * @brief Wrapper declarations for SHA-512/256 calculation performed by TLS library
- * @author Christian Grothoff
- */
-
-#ifndef MHD_SHA512_256_EXT_H
-# define MHD_SHA512_256_EXT_H 1
-
-# include "mhd_sys_options.h"
-# include <stdint.h>
-# include "sys_sizet_type.h"
-
-/**
- * Size of SHA-512_256 resulting digest in bytes
- * This is the final digest size, not intermediate hash.
- */
-# define mhd_SHA512_256_DIGEST_SIZE (32)
-
-# ifndef MHD_SHA512_256_Context
-# define MHD_SHA512_256_Context void
-# endif
-
-/**
- * Indicates that struct mhd_Sha512_256CtxExt has 'ext_error'
- */
-# define mhd_SHA512_256_HAS_EXT_ERROR 1
-
-/**
- * SHA-512_256 calculation context
- */
-struct mhd_Sha512_256CtxExt
-{
- MHD_SHA512_256_Context *handle; /**< Hash calculation handle */
- int ext_error; /**< Non-zero if external error occurs during init or hashing */
-};
-
-/**
- * Indicates that mhd_SHA512_256_init_one_time() function is present.
- */
-# define mhd_SHA512_256_HAS_INIT_ONE_TIME 1
-
-/**
- * Initialise structure for SHA-512_256 calculation, allocate resources.
- *
- * This function must not be called more than one time for @a ctx.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA512_256_init_one_time (struct mhd_Sha512_256CtxExt *ctx);
-
-
-/**
- * SHA-512_256 process portion of bytes.
- *
- * @param ctx the calculation context
- * @param size number of bytes in @a data, must not be 0
- * @param data bytes to add to hash
- */
-void
-mhd_SHA512_256_update (struct mhd_Sha512_256CtxExt *ctx,
- size_t size,
- const uint8_t *data);
-
-
-/**
- * Indicates that mhd_SHA512_256_finish_reset() function is available
- */
-# define mhd_SHA512_256_HAS_FINISH_RESET 1
-
-/**
- * Finalise SHA-512_256 calculation, return digest, reset hash calculation.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
- */
-void
-mhd_SHA512_256_finish_reset (struct mhd_Sha512_256CtxExt *ctx,
- uint8_t digest[mhd_SHA512_256_DIGEST_SIZE]);
-
-/**
- * Indicates that mhd_SHA512_256_deinit() function is present
- */
-# define mhd_SHA512_256_HAS_DEINIT 1
-
-/**
- * Free allocated resources.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA512_256_deinit (struct mhd_Sha512_256CtxExt *ctx);
-
-#endif /* MHD_SHA512_256_EXT_H */
-/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
-/*
- This file is part of GNU libmicrohttpd.
- Copyright (C) 2022 Evgeny Grin (Karlson2k)
-
- GNU libmicrohttpd 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.
-
- GNU libmicrohttpd 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.
-
- Alternatively, you can redistribute GNU libmicrohttpd and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version, together
- with the eCos exception, as follows:
-
- As a special exception, if other files instantiate templates or
- use macros or inline functions from this file, or you compile this
- file and link it with other works to produce a work based on this
- file, this file does not by itself cause the resulting work to be
- covered by the GNU General Public License. However the source code
- for this file must still be made available in accordance with
- section (3) of the GNU General Public License v2.
-
- This exception does not invalidate any other reasons why a work
- based on this file might be covered by the GNU General Public
- License.
-
- You should have received copies of the GNU Lesser General Public
- License and the GNU General Public License along with this library;
- if not, see <https://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file microhttpd/sha512_256_ext.h
- * @brief Wrapper declarations for SHA-512_256 calculation performed by TLS library
- * @author Karlson2k (Evgeny Grin)
- */
-
-#ifndef MHD_SHA512_256_EXT_H
-# define MHD_SHA512_256_EXT_H 1
-
-# include "mhd_sys_options.h"
-# include <stdint.h>
-# include "sys_sizet_type.h"
-
-/**
- * Size of SHA-512/256 resulting digest in bytes
- * This is the final digest size, not intermediate hash.
- */
-# define mhd_SHA512_256_DIGEST_SIZE (32)
-
-# ifndef MHD_SHA512_256_Context
-# define MHD_SHA512_256_Context void
-# endif
-
-/**
- * Indicates that struct mhd_Sha512_256CtxExt has 'ext_error'
- */
-# define mhd_SHA512_256_HAS_EXT_ERROR 1
-
-/**
- * SHA-512_256 calculation context
- */
-struct mhd_Sha512_256CtxExt
-{
- MHD_SHA512_256_Context *handle; /**< Hash calculation handle */
- int ext_error; /**< Non-zero if external error occurs during init or hashing */
-};
-
-/**
- * Indicates that mhd_SHA512_256_init_one_time() function is present.
- */
-# define mhd_SHA512_256_HAS_INIT_ONE_TIME 1
-
-/**
- * Initialise structure for SHA-512_256 calculation, allocate resources.
- *
- * This function must not be called more than one time for @a ctx.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA512_256_init_one_time (struct mhd_Sha512_256CtxExt *ctx);
-
-
-/**
- * SHA-512_256 process portion of bytes.
- *
- * @param ctx the calculation context
- * @param size number of bytes in @a data, must not be 0
- * @param data bytes to add to hash
- */
-void
-mhd_SHA512_256_update (struct mhd_Sha512_256CtxExt *ctx,
- size_t size,
- const uint8_t *data);
-
-
-/**
- * Indicates that mhd_SHA512_256_finish_reset() function is available
- */
-# define mhd_SHA512_256_HAS_FINISH_RESET 1
-
-/**
- * Finalise SHA-512_256 calculation, return digest, reset hash calculation.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
- */
-void
-mhd_SHA512_256_finish_reset (struct mhd_Sha512_256CtxExt *ctx,
- uint8_t digest[mhd_SHA512_256_DIGEST_SIZE]);
-
-/**
- * Indicates that mhd_SHA512_256_deinit() function is present
- */
-# define mhd_SHA512_256_HAS_DEINIT 1
-
-/**
- * Free allocated resources.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA512_256_deinit (struct mhd_Sha512_256CtxExt *ctx);
-
-#endif /* MHD_SHA512_256_EXT_H */
diff --git a/src/mhd2/sha512_256_ext_mbedtls.c b/src/mhd2/sha512_256_ext_mbedtls.c
@@ -1,203 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
-/*
- This file is part of GNU libmicrohttpd.
- Copyright (C) 2025 Christian Grothoff
-
- GNU libmicrohttpd 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.
-
- GNU libmicrohttpd 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.
-
- Alternatively, you can redistribute GNU libmicrohttpd and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version, together
- with the eCos exception, as follows:
-
- As a special exception, if other files instantiate templates or
- use macros or inline functions from this file, or you compile this
- file and link it with other works to produce a work based on this
- file, this file does not by itself cause the resulting work to be
- covered by the GNU General Public License. However the source code
- for this file must still be made available in accordance with
- section (3) of the GNU General Public License v2.
-
- This exception does not invalidate any other reasons why a work
- based on this file might be covered by the GNU General Public
- License.
-
- You should have received copies of the GNU Lesser General Public
- License and the GNU General Public License along with this library;
- if not, see <https://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file microhttpd/sha512_256_ext_mbedtls.c
- * @brief Wrapper for SHA-512/256 calculation performed by mbedTLS library
- * @author Christian Grothoff
- */
-#include <stdlib.h>
-#include <string.h>
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS 1
-#include <mbedtls/build_info.h>
-#include <mbedtls/sha512.h>
-#define MHD_SHA512_256_Context mbedtls_sha512_context
-#include "sha512_256_ext.h"
-#include "mhd_assert.h"
-
-
-/**
- * Initialize mbedtls context for SHA-512/256.
- * Since SHA-512/256 is not natively supported by
- * mbedTLS, we initialize for SHA-512 and then
- * override the state with the SHA-512/256 IV.
- *
- * @param[in,out] ctx hash context to initialize
- */
-static void
-init512_256 (struct mhd_Sha512_256CtxExt *ctx)
-{
- static const uint64_t iv_sha512_256[8] = {
- 0x22312194FC2BF72CULL, 0x9F555FA3C84C64C2ULL,
- 0x2393B86B6F53B151ULL, 0x963877195940EABDULL,
- 0x96283EE2A88EFFE3ULL, 0xBE5E1E2553863992ULL,
- 0x2B0199FC2C85B8AAULL, 0x0EB72DDC81C52CA2ULL
- };
-
- mbedtls_sha512_init (ctx->handle);
- /* is384=0 for SHA-512 */
-#if MBEDTLS_VERSION_MAJOR >= 4
- ctx->ext_error = mbedtls_sha512_starts_ret (ctx->handle,
- 0);
- if (0 != ctx->ext_error)
- {
- mbedtls_sha512_free (ctx->handle);
- free (ctx->handle);
- ctx->handle = NULL;
- return;
- }
- mhd_assert (sizeof (ctx->handle.state) ==
- sizeof (iv_sha512_256));
- memcpy (ctx->handle.state,
- iv_sha512_256,
- sizeof (iv_sha512_256));
-#else
- mbedtls_sha512_starts (ctx->handle,
- 0);
- mhd_assert (sizeof (ctx->handle->state) ==
- sizeof (iv_sha512_256));
- memcpy (ctx->handle->state,
- iv_sha512_256,
- sizeof (iv_sha512_256));
-#endif
-}
-
-
-/**
- * Initialise structure for SHA-512/256 calculation, allocate resources.
- *
- * This function must not be called more than one time for @a ctx.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA512_256_init_one_time (struct mhd_Sha512_256CtxExt *ctx)
-{
- ctx->ext_error = 0;
- ctx->handle = (mbedtls_sha512_context *)malloc (
- sizeof (mbedtls_sha512_context));
- if (NULL == ctx->handle)
- {
- ctx->ext_error = 1; /* Allocation failure */
- return;
- }
-
- init512_256 (ctx);
-
- /* If handle is NULL, the error must be set */
- mhd_assert ((NULL != ctx->handle) || (0 != ctx->ext_error));
- /* If error is set, the handle must be NULL */
- mhd_assert ((0 == ctx->ext_error) || (NULL == ctx->handle));
-}
-
-
-/**
- * Process portion of bytes.
- *
- * @param ctx the calculation context
- * @param data bytes to add to hash
- * @param length number of bytes in @a data
- */
-void
-mhd_SHA512_256_update (struct mhd_Sha512_256CtxExt *ctx,
- size_t size,
- const uint8_t *data)
-{
- mhd_assert (0 != size);
-#if MBEDTLS_VERSION_MAJOR >= 4
- if (0 == ctx->ext_error)
- ctx->ext_error = mbedtls_sha512_update_ret (ctx->handle,
- data,
- size);
-#else
- mbedtls_sha512_update (ctx->handle,
- data,
- size);
-#endif
-}
-
-
-/**
- * Finalise SHA-512/256 calculation, return digest, reset hash calculation.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
- */
-void
-mhd_SHA512_256_finish_reset (struct mhd_Sha512_256CtxExt *ctx,
- uint8_t digest[mhd_SHA512_256_DIGEST_SIZE])
-{
- uint8_t full_digest[64]; /* SHA-512 produces 64 bytes */
-
- if (0 == ctx->ext_error)
- {
-#if MBEDTLS_VERSION_MAJOR >= 4
- ctx->ext_error = mbedtls_sha512_finish_ret (ctx->handle,
- full_digest);
-#else
- mbedtls_sha512_finish (ctx->handle,
- full_digest);
-#endif
- if (0 == ctx->ext_error)
- {
- /* SHA-512/256 uses first 32 bytes of SHA-512 with different IV */
- memcpy (digest,
- full_digest,
- mhd_SHA512_256_DIGEST_SIZE);
-
- /* Reset for potential reuse */
- init512_256 (ctx);
- }
- }
-}
-
-
-/**
- * Free allocated resources.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA512_256_deinit (struct mhd_Sha512_256CtxExt *ctx)
-{
- if (NULL != ctx->handle)
- {
- mbedtls_sha512_free (ctx->handle);
- free (ctx->handle);
- }
-}
diff --git a/src/mhd2/sha512_256_ext_openssl.c b/src/mhd2/sha512_256_ext_openssl.c
@@ -1,156 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
-/*
- This file is part of GNU libmicrohttpd.
- Copyright (C) 2025 Christian Grothoff
-
- GNU libmicrohttpd 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.
-
- GNU libmicrohttpd 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.
-
- Alternatively, you can redistribute GNU libmicrohttpd and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version, together
- with the eCos exception, as follows:
-
- As a special exception, if other files instantiate templates or
- use macros or inline functions from this file, or you compile this
- file and link it with other works to produce a work based on this
- file, this file does not by itself cause the resulting work to be
- covered by the GNU General Public License. However the source code
- for this file must still be made available in accordance with
- section (3) of the GNU General Public License v2.
-
- This exception does not invalidate any other reasons why a work
- based on this file might be covered by the GNU General Public
- License.
-
- You should have received copies of the GNU Lesser General Public
- License and the GNU General Public License along with this library;
- if not, see <https://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file microhttpd/sha512_256_ext_openssl.c
- * @brief Wrapper for SHA-512/256 calculation performed by OpenSSL library
- * @author Christian Grothoff
- */
-
-#include <openssl/evp.h>
-#define MHD_SHA512_256_Context EVP_MD_CTX
-#include "sha512_256_ext.h"
-#include "mhd_assert.h"
-
-
-/**
- * Initialise structure for SHA-512/256 calculation, allocate resources.
- *
- * This function must not be called more than one time for @a ctx.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA512_256_init_one_time (struct mhd_Sha512_256CtxExt *ctx)
-{
- ctx->ext_error = 0;
- ctx->handle = EVP_MD_CTX_new ();
- if (NULL == ctx->handle)
- {
- ctx->ext_error = 1; /* Allocation failure */
- return;
- }
-
- if (1 != EVP_DigestInit_ex (ctx->handle,
- EVP_sha512_256 (),
- NULL))
- {
- ctx->ext_error = 1; /* Initialization failure */
- mhd_SHA512_256_deinit (ctx);
- }
-
- /* If handle is NULL, the error must be set */
- mhd_assert ((NULL != ctx->handle) || (0 != ctx->ext_error));
- /* If error is set, the handle must be NULL */
- mhd_assert ((0 == ctx->ext_error) || (NULL == ctx->handle));
-}
-
-
-/**
- * Process portion of bytes.
- *
- * @param ctx the calculation context
- * @param data bytes to add to hash
- * @param length number of bytes in @a data
- */
-void
-mhd_SHA512_256_update (struct mhd_Sha512_256CtxExt *ctx,
- size_t size,
- const uint8_t *data)
-{
- mhd_assert (0 != size);
- if (0 == ctx->ext_error)
- {
- if (1 != EVP_DigestUpdate (ctx->handle,
- data,
- size))
- ctx->ext_error = 1;
- }
-}
-
-
-/**
- * Finalise SHA-512/256 calculation, return digest, reset hash calculation.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
- */
-void
-mhd_SHA512_256_finish_reset (struct mhd_Sha512_256CtxExt *ctx,
- uint8_t digest[mhd_SHA512_256_DIGEST_SIZE])
-{
- unsigned int len;
-
- if (0 == ctx->ext_error)
- {
- if (1 != EVP_DigestFinal_ex (ctx->handle,
- digest,
- &len))
- {
- ctx->ext_error = 1;
- }
- else
- {
- mhd_assert (mhd_SHA512_256_DIGEST_SIZE == len);
- /* Reset for potential reuse */
- if (1 != EVP_DigestInit_ex (ctx->handle,
- EVP_sha512_256 (),
- NULL))
- {
- ctx->ext_error = 1;
- mhd_SHA512_256_deinit (ctx);
- }
- }
- }
-}
-
-
-/**
- * Free allocated resources.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA512_256_deinit (struct mhd_Sha512_256CtxExt *ctx)
-{
- if (NULL != ctx->handle)
- {
- EVP_MD_CTX_free (ctx->handle);
- ctx->handle = NULL;
- }
-}
diff --git a/src/mhd2/sha512_256_int.c b/src/mhd2/sha512_256_int.c
@@ -1,641 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
-/*
- This file is part of GNU libmicrohttpd.
- Copyright (C) 2022-2024 Evgeny Grin (Karlson2k)
-
- GNU libmicrohttpd 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.
-
- GNU libmicrohttpd 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.
-
- Alternatively, you can redistribute GNU libmicrohttpd and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version, together
- with the eCos exception, as follows:
-
- As a special exception, if other files instantiate templates or
- use macros or inline functions from this file, or you compile this
- file and link it with other works to produce a work based on this
- file, this file does not by itself cause the resulting work to be
- covered by the GNU General Public License. However the source code
- for this file must still be made available in accordance with
- section (3) of the GNU General Public License v2.
-
- This exception does not invalidate any other reasons why a work
- based on this file might be covered by the GNU General Public
- License.
-
- You should have received copies of the GNU Lesser General Public
- License and the GNU General Public License along with this library;
- if not, see <https://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file src/mhd2/sha512_256.c
- * @brief Calculation of SHA-512/256 digest as defined in FIPS PUB 180-4 (2015)
- * @author Karlson2k (Evgeny Grin)
- */
-
-#include "mhd_sys_options.h"
-
-#include "sys_bool_type.h"
-
-#include <string.h>
-#include "mhd_bithelpers.h"
-#include "mhd_align.h"
-#include "mhd_assert.h"
-
-#include "sha512_256_int.h"
-
-MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
-mhd_SHA512_256_init (struct mhd_Sha512_256CtxInt *ctx)
-{
- /* Initial hash values, see FIPS PUB 180-4 clause 5.3.6.2 */
- /* Values generated by "IV Generation Function" as described in
- * clause 5.3.6 */
- ctx->H[0] = UINT64_C (0x22312194FC2BF72C);
- ctx->H[1] = UINT64_C (0x9F555FA3C84C64C2);
- ctx->H[2] = UINT64_C (0x2393B86B6F53B151);
- ctx->H[3] = UINT64_C (0x963877195940EABD);
- ctx->H[4] = UINT64_C (0x96283EE2A88EFFE3);
- ctx->H[5] = UINT64_C (0xBE5E1E2553863992);
- ctx->H[6] = UINT64_C (0x2B0199FC2C85B8AA);
- ctx->H[7] = UINT64_C (0x0EB72DDC81C52CA2);
-
- /* Initialise number of bytes and high part of number of bits. */
- ctx->count = 0;
- ctx->count_bits_hi = 0;
-}
-
-
-mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE
-
-/**
- * Base of SHA-512/256 transformation.
- * Gets full 128 bytes block of data and updates hash values;
- * @param H hash values
- * @param data the data buffer with #mhd_SHA512_256_BLOCK_SIZE bytes block
- */
-static MHD_FN_PAR_NONNULL_ALL_ void
-sha512_256_transform (uint64_t H[mhd_SHA512_256_HASH_SIZE_WORDS],
- const void *restrict data)
-{
- /* Working variables,
- see FIPS PUB 180-4 clause 6.7, 6.4. */
- uint64_t a = H[0];
- uint64_t b = H[1];
- uint64_t c = H[2];
- uint64_t d = H[3];
- uint64_t e = H[4];
- uint64_t f = H[5];
- uint64_t g = H[6];
- uint64_t h = H[7];
-
- /* Data buffer, used as a cyclic buffer.
- See FIPS PUB 180-4 clause 5.2.2, 6.7, 6.4. */
- uint64_t W[16];
-
-#ifndef mhd_GET_64BIT_BE_ALLOW_UNALIGNED
- if (0 != (((uintptr_t)data) % mhd_UINT64_ALIGN))
- { /* The input data is unaligned */
- /* Copy the unaligned input data to the aligned buffer */
- memcpy (W, data, sizeof(W));
- /* The W[] buffer itself will be used as the source of the data,
- * but the data will be reloaded in correct bytes order on
- * the next steps */
- data = (const void *)W;
- }
-#endif /* mhd_GET_64BIT_BE_ALLOW_UNALIGNED */
-
- /* 'Ch' and 'Maj' macro functions are defined with
- widely-used optimisation.
- See FIPS PUB 180-4 formulae 4.8, 4.9. */
-#define Ch(x, y, z) ( (z) ^ ((x) & ((y) ^ (z))) )
-#define Maj(x, y, z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
- /* Unoptimized (original) versions: */
-/* #define Ch(x,y,z) ( ( (x) & (y) ) ^ ( ~(x) & (z) ) ) */
-/* #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */
-
- /* Four 'Sigma' macro functions.
- See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
-#define SIG0(x) \
- (mhd_ROTR64 ((x), 28) ^ mhd_ROTR64 ((x), 34) ^ mhd_ROTR64 ((x), 39) )
-#define SIG1(x) \
- (mhd_ROTR64 ((x), 14) ^ mhd_ROTR64 ((x), 18) ^ mhd_ROTR64 ((x), 41) )
-#define sig0(x) \
- (mhd_ROTR64 ((x), 1) ^ mhd_ROTR64 ((x), 8) ^ ((x) >> 7) )
-#define sig1(x) \
- (mhd_ROTR64 ((x), 19) ^ mhd_ROTR64 ((x), 61) ^ ((x) >> 6) )
-
- /* One step of SHA-512/256 computation,
- see FIPS PUB 180-4 clause 6.4.2 step 3.
- * Note: this macro updates working variables in-place, without rotation.
- * Note: the first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in
- FIPS PUB 180-4 clause 6.4.2 step 3.
- the second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in
- FIPS PUB 180-4 clause 6.4.2 step 3.
- * Note: 'wt' must be used exactly one time in this macro as it change other
- data as well every time when used. */
-#define SHA2STEP64(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) do { \
- (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \
- (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0)
-
- /* Get value of W(t) from input data buffer for 0 <= t <= 15,
- See FIPS PUB 180-4 clause 6.2.
- Input data must be read in big-endian bytes order,
- see FIPS PUB 180-4 clause 3.1.2. */
-#define GET_W_FROM_DATA(buf, t) \
- mhd_GET_64BIT_BE (((const uint64_t*) (buf)) + (t))
-
- /* 'W' generation and assignment for 16 <= t <= 79.
- See FIPS PUB 180-4 clause 6.4.2.
- As only last 16 'W' are used in calculations, it is possible to
- use 16 elements array of W as a cyclic buffer.
- * Note: ((t-16) & 15) have same value as (t & 15) */
-#define Wgen(w, t) ( (w)[(t - 16) & 15] + sig1 ((w)[((t) - 2) & 15]) \
- + (w)[((t) - 7) & 15] + sig0 ((w)[((t) - 15) & 15]) )
-
-#ifndef MHD_FAVOR_SMALL_CODE
-
- /* Note: instead of using K constants as array, all K values are specified
- individually for each step, see FIPS PUB 180-4 clause 4.2.3 for
- K values. */
- /* Note: instead of reassigning all working variables on each step,
- variables are rotated for each step:
- SHA2STEP64(a, b, c, d, e, f, g, h, K[0], data[0]);
- SHA2STEP64(h, a, b, c, d, e, f, g, K[1], data[1]);
- so current 'vD' will be used as 'vE' on next step,
- current 'vH' will be used as 'vA' on next step. */
-# if mhd_BYTE_ORDER == mhd_BIG_ENDIAN
- if ((const void *)W == data)
- {
- /* The input data is already in the cyclic data buffer W[] in correct bytes
- order. */
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x428a2f98d728ae22), W[0]);
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x7137449123ef65cd), W[1]);
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xb5c0fbcfec4d3b2f), W[2]);
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xe9b5dba58189dbbc), W[3]);
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x3956c25bf348b538), W[4]);
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x59f111f1b605d019), W[5]);
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x923f82a4af194f9b), W[6]);
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xab1c5ed5da6d8118), W[7]);
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xd807aa98a3030242), W[8]);
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x12835b0145706fbe), W[9]);
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x243185be4ee4b28c), W[10]);
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x550c7dc3d5ffb4e2), W[11]);
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x72be5d74f27b896f), W[12]);
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x80deb1fe3b1696b1), W[13]);
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x9bdc06a725c71235), W[14]);
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xc19bf174cf692694), W[15]);
- }
- else /* Combined with the next 'if' */
-# endif /* mhd_BYTE_ORDER == mhd_BIG_ENDIAN */
- if (1)
- {
- /* During first 16 steps, before making any calculations on each step,
- the W element is read from the input data buffer as big-endian value and
- stored in the array of W elements. */
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x428a2f98d728ae22), \
- W[0] = GET_W_FROM_DATA (data, 0));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x7137449123ef65cd), \
- W[1] = GET_W_FROM_DATA (data, 1));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xb5c0fbcfec4d3b2f), \
- W[2] = GET_W_FROM_DATA (data, 2));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xe9b5dba58189dbbc), \
- W[3] = GET_W_FROM_DATA (data, 3));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x3956c25bf348b538), \
- W[4] = GET_W_FROM_DATA (data, 4));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x59f111f1b605d019), \
- W[5] = GET_W_FROM_DATA (data, 5));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x923f82a4af194f9b), \
- W[6] = GET_W_FROM_DATA (data, 6));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xab1c5ed5da6d8118), \
- W[7] = GET_W_FROM_DATA (data, 7));
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xd807aa98a3030242), \
- W[8] = GET_W_FROM_DATA (data, 8));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x12835b0145706fbe), \
- W[9] = GET_W_FROM_DATA (data, 9));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x243185be4ee4b28c), \
- W[10] = GET_W_FROM_DATA (data, 10));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x550c7dc3d5ffb4e2), \
- W[11] = GET_W_FROM_DATA (data, 11));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x72be5d74f27b896f), \
- W[12] = GET_W_FROM_DATA (data, 12));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x80deb1fe3b1696b1), \
- W[13] = GET_W_FROM_DATA (data, 13));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x9bdc06a725c71235), \
- W[14] = GET_W_FROM_DATA (data, 14));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xc19bf174cf692694), \
- W[15] = GET_W_FROM_DATA (data, 15));
- }
-
- /* During last 64 steps, before making any calculations on each step,
- current W element is generated from other W elements of the cyclic buffer
- and the generated value is stored back in the cyclic buffer. */
- /* Note: instead of using K constants as array, all K values are specified
- individually for each step, see FIPS PUB 180-4 clause 4.2.3 for
- K values. */
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xe49b69c19ef14ad2), \
- W[16 & 15] = Wgen (W, 16));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xefbe4786384f25e3), \
- W[17 & 15] = Wgen (W, 17));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x0fc19dc68b8cd5b5), \
- W[18 & 15] = Wgen (W, 18));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x240ca1cc77ac9c65), \
- W[19 & 15] = Wgen (W, 19));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x2de92c6f592b0275), \
- W[20 & 15] = Wgen (W, 20));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x4a7484aa6ea6e483), \
- W[21 & 15] = Wgen (W, 21));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x5cb0a9dcbd41fbd4), \
- W[22 & 15] = Wgen (W, 22));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x76f988da831153b5), \
- W[23 & 15] = Wgen (W, 23));
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x983e5152ee66dfab), \
- W[24 & 15] = Wgen (W, 24));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xa831c66d2db43210), \
- W[25 & 15] = Wgen (W, 25));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xb00327c898fb213f), \
- W[26 & 15] = Wgen (W, 26));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xbf597fc7beef0ee4), \
- W[27 & 15] = Wgen (W, 27));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0xc6e00bf33da88fc2), \
- W[28 & 15] = Wgen (W, 28));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0xd5a79147930aa725), \
- W[29 & 15] = Wgen (W, 29));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x06ca6351e003826f), \
- W[30 & 15] = Wgen (W, 30));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x142929670a0e6e70), \
- W[31 & 15] = Wgen (W, 31));
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x27b70a8546d22ffc), \
- W[32 & 15] = Wgen (W, 32));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x2e1b21385c26c926), \
- W[33 & 15] = Wgen (W, 33));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x4d2c6dfc5ac42aed), \
- W[34 & 15] = Wgen (W, 34));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x53380d139d95b3df), \
- W[35 & 15] = Wgen (W, 35));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x650a73548baf63de), \
- W[36 & 15] = Wgen (W, 36));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x766a0abb3c77b2a8), \
- W[37 & 15] = Wgen (W, 37));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x81c2c92e47edaee6), \
- W[38 & 15] = Wgen (W, 38));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x92722c851482353b), \
- W[39 & 15] = Wgen (W, 39));
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xa2bfe8a14cf10364), \
- W[40 & 15] = Wgen (W, 40));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xa81a664bbc423001), \
- W[41 & 15] = Wgen (W, 41));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xc24b8b70d0f89791), \
- W[42 & 15] = Wgen (W, 42));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xc76c51a30654be30), \
- W[43 & 15] = Wgen (W, 43));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0xd192e819d6ef5218), \
- W[44 & 15] = Wgen (W, 44));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0xd69906245565a910), \
- W[45 & 15] = Wgen (W, 45));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0xf40e35855771202a), \
- W[46 & 15] = Wgen (W, 46));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x106aa07032bbd1b8), \
- W[47 & 15] = Wgen (W, 47));
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x19a4c116b8d2d0c8), \
- W[48 & 15] = Wgen (W, 48));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x1e376c085141ab53), \
- W[49 & 15] = Wgen (W, 49));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x2748774cdf8eeb99), \
- W[50 & 15] = Wgen (W, 50));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x34b0bcb5e19b48a8), \
- W[51 & 15] = Wgen (W, 51));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x391c0cb3c5c95a63), \
- W[52 & 15] = Wgen (W, 52));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x4ed8aa4ae3418acb), \
- W[53 & 15] = Wgen (W, 53));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x5b9cca4f7763e373), \
- W[54 & 15] = Wgen (W, 54));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x682e6ff3d6b2b8a3), \
- W[55 & 15] = Wgen (W, 55));
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x748f82ee5defb2fc), \
- W[56 & 15] = Wgen (W, 56));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x78a5636f43172f60), \
- W[57 & 15] = Wgen (W, 57));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x84c87814a1f0ab72), \
- W[58 & 15] = Wgen (W, 58));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x8cc702081a6439ec), \
- W[59 & 15] = Wgen (W, 59));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x90befffa23631e28), \
- W[60 & 15] = Wgen (W, 60));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0xa4506cebde82bde9), \
- W[61 & 15] = Wgen (W, 61));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0xbef9a3f7b2c67915), \
- W[62 & 15] = Wgen (W, 62));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xc67178f2e372532b), \
- W[63 & 15] = Wgen (W, 63));
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xca273eceea26619c), \
- W[64 & 15] = Wgen (W, 64));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xd186b8c721c0c207), \
- W[65 & 15] = Wgen (W, 65));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xeada7dd6cde0eb1e), \
- W[66 & 15] = Wgen (W, 66));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xf57d4f7fee6ed178), \
- W[67 & 15] = Wgen (W, 67));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x06f067aa72176fba), \
- W[68 & 15] = Wgen (W, 68));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x0a637dc5a2c898a6), \
- W[69 & 15] = Wgen (W, 69));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x113f9804bef90dae), \
- W[70 & 15] = Wgen (W, 70));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x1b710b35131c471b), \
- W[71 & 15] = Wgen (W, 71));
- SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x28db77f523047d84), \
- W[72 & 15] = Wgen (W, 72));
- SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x32caab7b40c72493), \
- W[73 & 15] = Wgen (W, 73));
- SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x3c9ebe0a15c9bebc), \
- W[74 & 15] = Wgen (W, 74));
- SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x431d67c49c100d4c), \
- W[75 & 15] = Wgen (W, 75));
- SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x4cc5d4becb3e42b6), \
- W[76 & 15] = Wgen (W, 76));
- SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x597f299cfc657e2a), \
- W[77 & 15] = Wgen (W, 77));
- SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x5fcb6fab3ad6faec), \
- W[78 & 15] = Wgen (W, 78));
- SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x6c44198c4a475817), \
- W[79 & 15] = Wgen (W, 79));
-#else /* MHD_FAVOR_SMALL_CODE */
- if (1)
- {
- unsigned int t;
- /* K constants array.
- See FIPS PUB 180-4 clause 4.2.3 for K values. */
- static const uint64_t K[80] =
- { UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
- UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
- UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
- UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
- UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
- UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
- UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
- UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
- UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
- UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
- UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
- UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
- UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
- UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
- UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
- UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
- UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
- UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
- UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
- UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
- UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
- UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
- UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
- UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
- UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
- UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
- UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
- UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
- UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
- UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
- UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
- UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
- UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
- UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
- UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
- UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
- UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
- UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
- UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
- UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)};
-
- /* One step of SHA-512/256 computation with working variables rotation,
- see FIPS PUB 180-4 clause 6.4.2 step 3.
- * Note: this version of macro reassign all working variable on
- each step. */
-# define SHA2STEP64RV(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) \
- do { \
- uint64_t tmp_h_ = (vH); \
- SHA2STEP64 ((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt)); \
- (vH) = (vG); \
- (vG) = (vF); \
- (vF) = (vE); \
- (vE) = (vD); \
- (vD) = (vC); \
- (vC) = (vB); \
- (vB) = (vA); \
- (vA) = tmp_h_; \
- } while (0)
-
- /* During first 16 steps, before making any calculations on each step,
- the W element is read from the input data buffer as big-endian value and
- stored in the array of W elements. */
- for (t = 0; t < 16; ++t)
- {
- SHA2STEP64RV (a, b, c, d, e, f, g, h, K[t], \
- W[t] = GET_W_FROM_DATA (data, t));
- }
- /* During last 64 steps, before making any calculations on each step,
- current W element is generated from other W elements of the cyclic buffer
- and the generated value is stored back in the cyclic buffer. */
- for (t = 16; t < 80; ++t)
- {
- SHA2STEP64RV (a, b, c, d, e, f, g, h, K[t], \
- W[t & 15] = Wgen (W, t));
- }
- }
-#endif /* MHD_FAVOR_SMALL_CODE */
-
- /* Compute and store the intermediate hash.
- See FIPS PUB 180-4 clause 6.4.2 step 4. */
- H[0] += a;
- H[1] += b;
- H[2] += c;
- H[3] += d;
- H[4] += e;
- H[5] += f;
- H[6] += g;
- H[7] += h;
-}
-
-
-MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
-MHD_FN_PAR_IN_SIZE_ (3, 2) void
-mhd_SHA512_256_update (struct mhd_Sha512_256CtxInt *restrict ctx,
- size_t size,
- const uint8_t *restrict data)
-{
- unsigned int bytes_have; /**< Number of bytes in the context buffer */
- uint64_t count_hi; /**< The high part to be moved to another variable */
-
- mhd_assert (0 != size);
-
- /* Note: (count & (mhd_SHA512_256_BLOCK_SIZE-1))
- equals (count % mhd_SHA512_256_BLOCK_SIZE) for this block size. */
- bytes_have = (unsigned int)(ctx->count & (mhd_SHA512_256_BLOCK_SIZE - 1));
- ctx->count += size;
-#if SIZEOF_SIZE_T > 7
- if (size > ctx->count)
- ctx->count_bits_hi += 1U << 3; /* Value wrap */
-#endif /* SIZEOF_SIZE_T > 7 */
- count_hi = ctx->count >> 61;
- if (0 != count_hi)
- {
- ctx->count_bits_hi += count_hi;
- ctx->count &= UINT64_C (0x1FFFFFFFFFFFFFFF);
- }
-
- if (0 != bytes_have)
- {
- unsigned int bytes_left = mhd_SHA512_256_BLOCK_SIZE - bytes_have;
- if (size >= bytes_left)
- { /* Combine new data with data in the buffer and
- process the full block. */
- memcpy (((uint8_t *)ctx->buffer) + bytes_have,
- data,
- bytes_left);
- data += bytes_left;
- size -= bytes_left;
- sha512_256_transform (ctx->H, ctx->buffer);
- bytes_have = 0;
- }
- }
-
- while (mhd_SHA512_256_BLOCK_SIZE <= size)
- { /* Process any full blocks of new data directly,
- without copying to the buffer. */
- sha512_256_transform (ctx->H, data);
- data += mhd_SHA512_256_BLOCK_SIZE;
- size -= mhd_SHA512_256_BLOCK_SIZE;
- }
-
- if (0 != size)
- { /* Copy incomplete block of new data (if any)
- to the buffer. */
- memcpy (((uint8_t *)ctx->buffer) + bytes_have, data, size);
- }
-}
-
-
-/**
- * Size of "length" insertion in bits.
- * See FIPS PUB 180-4 clause 5.1.2.
- */
-#define SHA512_256_SIZE_OF_LEN_ADD_BITS 128
-
-/**
- * Size of "length" insertion in bytes.
- */
-#define SHA512_256_SIZE_OF_LEN_ADD (SHA512_256_SIZE_OF_LEN_ADD_BITS / 8)
-
-MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
-mhd_SHA512_256_finish (struct mhd_Sha512_256CtxInt *restrict ctx,
- uint8_t digest[mhd_SHA512_256_DIGEST_SIZE])
-{
- uint64_t num_bits; /**< Number of processed bits */
- unsigned int bytes_have; /**< Number of bytes in the context buffer */
-
- /* Memorise the number of processed bits.
- The padding and other data added here during the postprocessing must
- not change the amount of hashed data. */
- num_bits = ctx->count << 3;
-
- /* Note: (count & (mhd_SHA512_256_BLOCK_SIZE-1))
- equals (count % mhd_SHA512_256_BLOCK_SIZE) for this block size. */
- bytes_have = (unsigned int)(ctx->count & (mhd_SHA512_256_BLOCK_SIZE - 1));
-
- /* Input data must be padded with a single bit "1", then with zeros and
- the finally the length of data in bits must be added as the final bytes
- of the last block.
- See FIPS PUB 180-4 clause 5.1.2. */
-
- /* Data is always processed in form of bytes (not by individual bits),
- therefore position of the first padding bit in byte is always
- predefined (0x80). */
- /* Buffer always have space for one byte at least (as full buffers are
- processed immediately). */
- ((uint8_t *)ctx->buffer)[bytes_have++] = 0x80;
-
- if (mhd_SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD)
- { /* No space in the current block to put the total length of message.
- Pad the current block with zeros and process it. */
- if (bytes_have < mhd_SHA512_256_BLOCK_SIZE)
- memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
- mhd_SHA512_256_BLOCK_SIZE - bytes_have);
- /* Process the full block. */
- sha512_256_transform (ctx->H, ctx->buffer);
- /* Start the new block. */
- bytes_have = 0;
- }
-
- /* Pad the rest of the buffer with zeros. */
- memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
- mhd_SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have);
- /* Put high part of number of bits in processed message and then lower
- part of number of bits as big-endian values.
- See FIPS PUB 180-4 clause 5.1.2. */
- /* Note: the target location is predefined and buffer is always aligned */
- mhd_PUT_64BIT_BE (ctx->buffer + mhd_SHA512_256_BLOCK_SIZE_WORDS - 2,
- ctx->count_bits_hi);
- mhd_PUT_64BIT_BE (ctx->buffer + mhd_SHA512_256_BLOCK_SIZE_WORDS - 1,
- num_bits);
- /* Process the full final block. */
- sha512_256_transform (ctx->H, ctx->buffer);
-
- /* Put in BE mode the leftmost part of the hash as the final digest.
- See FIPS PUB 180-4 clause 6.7. */
- if (1)
- {
- bool use_tmp_buf_to_align_result;
-
-#if defined(mhd_PUT_64BIT_BE_UNALIGNED)
- use_tmp_buf_to_align_result = false;
-#elif defined(MHD_FAVOR_SMALL_CODE)
- use_tmp_buf_to_align_result = true; /* smaller code: eliminated branch below */
-#else
- use_tmp_buf_to_align_result =
- (0 != ((uintptr_t)digest) % mhd_UINT64_ALIGN);
-#endif
- if (use_tmp_buf_to_align_result)
- {
- /* If storing of the final result requires aligned address and
- the destination address is not aligned or compact code is used,
- store the final digest in aligned temporary buffer first, then
- copy it to the destination. */
- uint64_t alig_dgst[mhd_SHA512_256_DIGEST_SIZE_WORDS];
- mhd_PUT_64BIT_BE (alig_dgst + 0, ctx->H[0]);
- mhd_PUT_64BIT_BE (alig_dgst + 1, ctx->H[1]);
- mhd_PUT_64BIT_BE (alig_dgst + 2, ctx->H[2]);
- mhd_PUT_64BIT_BE (alig_dgst + 3, ctx->H[3]);
- /* Copy result to the unaligned destination address */
- memcpy (digest, alig_dgst, mhd_SHA512_256_DIGEST_SIZE);
- }
- else
- {
- /* Use cast to (void*) here to mute compiler alignment warnings.
- * Compilers are not smart enough to see that alignment has been checked. */
- mhd_PUT_64BIT_BE ((void *)(digest + 0 * mhd_SHA512_256_BYTES_IN_WORD), \
- ctx->H[0]);
- mhd_PUT_64BIT_BE ((void *)(digest + 1 * mhd_SHA512_256_BYTES_IN_WORD), \
- ctx->H[1]);
- mhd_PUT_64BIT_BE ((void *)(digest + 2 * mhd_SHA512_256_BYTES_IN_WORD), \
- ctx->H[2]);
- mhd_PUT_64BIT_BE ((void *)(digest + 3 * mhd_SHA512_256_BYTES_IN_WORD), \
- ctx->H[3]);
- }
- }
-
- /* Erase potentially sensitive data. */
- memset (ctx, 0, sizeof(struct mhd_Sha512_256CtxInt));
-}
-
-
-mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE
diff --git a/src/mhd2/sha512_256_int.h b/src/mhd2/sha512_256_int.h
@@ -1,158 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
-/*
- This file is part of GNU libmicrohttpd.
- Copyright (C) 2022-2024 Evgeny Grin (Karlson2k)
-
- GNU libmicrohttpd 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.
-
- GNU libmicrohttpd 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.
-
- Alternatively, you can redistribute GNU libmicrohttpd and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version, together
- with the eCos exception, as follows:
-
- As a special exception, if other files instantiate templates or
- use macros or inline functions from this file, or you compile this
- file and link it with other works to produce a work based on this
- file, this file does not by itself cause the resulting work to be
- covered by the GNU General Public License. However the source code
- for this file must still be made available in accordance with
- section (3) of the GNU General Public License v2.
-
- This exception does not invalidate any other reasons why a work
- based on this file might be covered by the GNU General Public
- License.
-
- You should have received copies of the GNU Lesser General Public
- License and the GNU General Public License along with this library;
- if not, see <https://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file src/mhd2/sha512_256.h
- * @brief Calculation of SHA-512/256 digest
- * @author Karlson2k (Evgeny Grin)
- */
-
-#ifndef MHD_SHA512_256_INT_H
-#define MHD_SHA512_256_INT_H 1
-
-#include "mhd_sys_options.h"
-
-#include "sys_base_types.h"
-
-
-/**
- * Number of bits in single SHA-512/256 word.
- */
-#define mhd_SHA512_256_WORD_SIZE_BITS 64
-
-/**
- * Number of bytes in single SHA-512/256 word.
- */
-#define mhd_SHA512_256_BYTES_IN_WORD (mhd_SHA512_256_WORD_SIZE_BITS / 8)
-
-/**
- * Hash is kept internally as 8 64-bit words.
- * This is intermediate hash size, used during computing the final digest.
- */
-#define mhd_SHA512_256_HASH_SIZE_WORDS 8
-
-/**
- * Size of SHA-512/256 resulting digest in words.
- * This is the final digest size, not intermediate hash.
- */
-#define mhd_SHA512_256_DIGEST_SIZE_WORDS (mhd_SHA512_256_HASH_SIZE_WORDS / 2)
-
-/**
- * Size of SHA-512/256 resulting digest in bytes.
- * This is the final digest size, not intermediate hash.
- */
-#define mhd_SHA512_256_DIGEST_SIZE \
- (mhd_SHA512_256_DIGEST_SIZE_WORDS * mhd_SHA512_256_BYTES_IN_WORD)
-
-/**
- * Size of SHA-512/256 single processing block in bits.
- */
-#define mhd_SHA512_256_BLOCK_SIZE_BITS 1024
-
-/**
- * Size of SHA-512/256 single processing block in bytes.
- */
-#define mhd_SHA512_256_BLOCK_SIZE (mhd_SHA512_256_BLOCK_SIZE_BITS / 8)
-
-/**
- * Size of SHA-512/256 single processing block in words.
- */
-#define mhd_SHA512_256_BLOCK_SIZE_WORDS \
- (mhd_SHA512_256_BLOCK_SIZE_BITS / mhd_SHA512_256_WORD_SIZE_BITS)
-
-
-/**
- * SHA-512/256 calculation context
- */
-struct mhd_Sha512_256CtxInt
-{
- uint64_t H[mhd_SHA512_256_HASH_SIZE_WORDS]; /**< Intermediate hash value */
- uint64_t buffer[mhd_SHA512_256_BLOCK_SIZE_WORDS]; /**< SHA512_256 input data buffer */
- /**
- * The number of bytes, lower part
- */
- uint64_t count;
- /**
- * The number of bits, high part.
- * Unlike lower part, this counts the number of bits, not bytes.
- */
- uint64_t count_bits_hi;
-};
-
-/**
- * Initialise structure for SHA-512/256 calculation.
- *
- * @param ctx the calculation context
- */
-MHD_INTERNAL void
-mhd_SHA512_256_init (struct mhd_Sha512_256CtxInt *ctx)
-MHD_FN_PAR_NONNULL_ALL_;
-
-
-/**
- * Process portion of bytes.
- *
- * @param ctx the calculation context
- * @param size number of bytes in @a data, must not be 0
- * @param data bytes to add to hash
- */
-MHD_INTERNAL void
-mhd_SHA512_256_update (struct mhd_Sha512_256CtxInt *restrict ctx,
- size_t size,
- const uint8_t *restrict data)
-MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (3, 2);
-
-
-/**
- * Finalise SHA-512/256 calculation, return digest.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
- */
-MHD_INTERNAL void
-mhd_SHA512_256_finish (struct mhd_Sha512_256CtxInt *restrict ctx,
- uint8_t digest[mhd_SHA512_256_DIGEST_SIZE])
-MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (2);
-
-/**
- * Indicates that function mhd_SHA512_256_finish() (without context reset) is
- * available
- */
-#define mhd_SHA512_256_HAS_FINISH 1
-
-#endif /* MHD_SHA512_256_H */
diff --git a/src/mhd2/sha512_256_mbedtls.c b/src/mhd2/sha512_256_mbedtls.c
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
+/*
+ This file is part of GNU libmicrohttpd.
+ Copyright (C) 2026 Evgeny Grin (Karlson2k)
+ Copyright (C) 2025 Christian Grothoff
+
+ GNU libmicrohttpd 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.
+
+ GNU libmicrohttpd 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.
+
+ Alternatively, you can redistribute GNU libmicrohttpd and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version, together
+ with the eCos exception, as follows:
+
+ As a special exception, if other files instantiate templates or
+ use macros or inline functions from this file, or you compile this
+ file and link it with other works to produce a work based on this
+ file, this file does not by itself cause the resulting work to be
+ covered by the GNU General Public License. However the source code
+ for this file must still be made available in accordance with
+ section (3) of the GNU General Public License v2.
+
+ This exception does not invalidate any other reasons why a work
+ based on this file might be covered by the GNU General Public
+ License.
+
+ You should have received copies of the GNU Lesser General Public
+ License and the GNU General Public License along with this library;
+ if not, see <https://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file src/mhd2/sha512_256_mbedtls.c
+ * @brief Wrapper for SHA-512/256 calculation performed by mbedTLS library
+ * @author Karlson2k (Evgeny Grin)
+ * @author Christian Grothoff
+ */
+
+#include "mhd_sys_options.h"
+
+/* mbedTLS does not natively support SHA-512/256: the backend initialises
+ SHA-512 and overrides the internal hash state with the SHA-512/256 initial
+ values, which requires access to private context members. The definition
+ must precede the mbedTLS header so that the private members are visible. */
+#ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS
+# define MBEDTLS_ALLOW_PRIVATE_ACCESS 1
+#endif
+
+#include <string.h>
+#include "mhd_assert.h"
+
+#include "sha512_256_mbedtls.h"
+
+
+/**
+ * Start SHA-512 calculation and override the internal state with the
+ * SHA-512/256 initial hash values, see FIPS PUB 180-4 clause 5.3.6.2.
+ *
+ * mbedTLS does not natively support SHA-512/256, so the SHA-512 machinery is
+ * reused with a different initial state.
+ *
+ * @param ctx the calculation context, must be already initialised
+ */
+static MHD_FN_PAR_NONNULL_ALL_ void
+mtls_set_sha512_256_iv (struct mhd_Sha512_256CtxMtls *ctx)
+{
+ static const uint64_t iv_sha512_256[8] = {
+ UINT64_C (0x22312194FC2BF72C), UINT64_C (0x9F555FA3C84C64C2),
+ UINT64_C (0x2393B86B6F53B151), UINT64_C (0x963877195940EABD),
+ UINT64_C (0x96283EE2A88EFFE3), UINT64_C (0xBE5E1E2553863992),
+ UINT64_C (0x2B0199FC2C85B8AA), UINT64_C (0x0EB72DDC81C52CA2)
+ };
+
+ /* The second argument must be zero to start SHA-512 (not SHA-384) */
+ ctx->ext_error = (0 != mbedtls_sha512_starts (&(ctx->mbed_ctx),
+ 0));
+ if (ctx->ext_error)
+ return;
+
+ mhd_assert (sizeof(ctx->mbed_ctx.state) == sizeof(iv_sha512_256));
+ memcpy (ctx->mbed_ctx.state,
+ iv_sha512_256,
+ sizeof(iv_sha512_256));
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1) void
+mhd_SHA512_256_mtls_init (struct mhd_Sha512_256CtxMtls *ctx)
+{
+ mbedtls_sha512_init (&(ctx->mbed_ctx));
+ mtls_set_sha512_256_iv (ctx);
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) void
+mhd_SHA512_256_mtls_reset (struct mhd_Sha512_256CtxMtls *ctx)
+{
+ if (ctx->ext_error)
+ return;
+
+ mtls_set_sha512_256_iv (ctx);
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_IN_SIZE_ (3, 2) void
+mhd_SHA512_256_mtls_update (struct mhd_Sha512_256CtxMtls *restrict ctx,
+ size_t size,
+ const void *restrict data)
+{
+#ifndef MHD_UNIT_TESTING
+ mhd_assert (0 != size);
+#endif
+
+ if (ctx->ext_error)
+ return;
+
+ ctx->ext_error = (0 != mbedtls_sha512_update (&(ctx->mbed_ctx),
+ (const unsigned char *)data,
+ size));
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_OUT_ (2) void
+mhd_SHA512_256_mtls_finish (
+ struct mhd_Sha512_256CtxMtls *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA512_256_DIGEST_SIZE)])
+{
+ uint8_t full_digest[64]; /* SHA-512 produces 64 bytes */
+
+ if (ctx->ext_error)
+ return;
+
+ ctx->ext_error = (0 != mbedtls_sha512_finish (&(ctx->mbed_ctx),
+ (unsigned char *)full_digest));
+ if (ctx->ext_error)
+ return;
+
+ /* SHA-512/256 is the leftmost 256 bits of SHA-512 computed with the
+ SHA-512/256 initial values. */
+ memcpy (digest,
+ full_digest,
+ mhd_SHA512_256_DIGEST_SIZE);
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) void
+mhd_SHA512_256_mtls_deinit (struct mhd_Sha512_256CtxMtls *ctx)
+{
+ mbedtls_sha512_free (&(ctx->mbed_ctx));
+}
diff --git a/src/mhd2/sha512_256_mbedtls.h b/src/mhd2/sha512_256_mbedtls.h
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
+/*
+ This file is part of GNU libmicrohttpd.
+ Copyright (C) 2022-2026 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd 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.
+
+ GNU libmicrohttpd 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.
+
+ Alternatively, you can redistribute GNU libmicrohttpd and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version, together
+ with the eCos exception, as follows:
+
+ As a special exception, if other files instantiate templates or
+ use macros or inline functions from this file, or you compile this
+ file and link it with other works to produce a work based on this
+ file, this file does not by itself cause the resulting work to be
+ covered by the GNU General Public License. However the source code
+ for this file must still be made available in accordance with
+ section (3) of the GNU General Public License v2.
+
+ This exception does not invalidate any other reasons why a work
+ based on this file might be covered by the GNU General Public
+ License.
+
+ You should have received copies of the GNU Lesser General Public
+ License and the GNU General Public License along with this library;
+ if not, see <https://www.gnu.org/licenses/>.
+*/
+/**
+ * @file src/mhd2/sha512_256_mbedtls.h
+ * @brief Wrapper declarations for SHA-512/256 calculation performed by
+ * mbedTLS backend
+ * @author Karlson2k (Evgeny Grin)
+ */
+#ifndef MHD_SHA512_256_MBEDTLS_H
+#define MHD_SHA512_256_MBEDTLS_H 1
+
+#include "mhd_sys_options.h"
+
+#include "sys_bool_type.h"
+#include "sys_base_types.h"
+/* MbedTLS header is small in size and scope, it is directly included here */
+#include <mbedtls/sha512.h>
+
+#ifndef mhd_SHA512_256_DIGEST_SIZE
+/**
+ * Size of SHA-512/256 resulting digest in bytes
+ * This is the final digest size, not the intermediate hash.
+ */
+# define mhd_SHA512_256_DIGEST_SIZE (32)
+#endif
+
+/**
+ * SHA-512/256 calculation context
+ */
+struct mhd_Sha512_256CtxMtls
+{
+ struct mbedtls_sha512_context mbed_ctx; /**< Hash calculation handle */
+ bool ext_error; /**< 'true' if the hashing backend has reported an error */
+};
+
+/**
+ * Indicates whether struct mhd_Sha512_256CtxMtls has an 'ext_error' member.
+ *
+ * Set to '1' when the structure has an 'ext_error' member.
+ */
+#define mhd_SHA512_256_MTLS_EXT_ERROR_FLAG 1
+
+/**
+ * Initialise the context for SHA-512/256 calculation.
+ *
+ * This function must not be called more than once for @a ctx without an
+ * intervening #mhd_SHA512_256_mtls_deinit().
+ *
+ * The error state in @a ctx is set according to the result: cleared on
+ * success, set on failure.
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_mtls_init (struct mhd_Sha512_256CtxMtls *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1);
+
+
+/**
+ * Add a portion of data to the SHA-512/256 calculation.
+ *
+ * If @a ctx already has a recorded error, this function does nothing.
+ * Otherwise, if the operation fails, the error is recorded in @a ctx.
+ *
+ * @param ctx the calculation context
+ * @param size number of bytes in @a data, must not be 0
+ * @param data bytes to add to hash
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_mtls_update (struct mhd_Sha512_256CtxMtls *restrict ctx,
+ size_t size,
+ const void *restrict data)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_IN_SIZE_ (3, 2);
+
+/**
+ * Finalise the SHA-512/256 calculation and return the digest.
+ *
+ * If @a ctx already has a recorded error, this function does nothing.
+ * Otherwise, if the operation fails, the error is recorded in @a ctx.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_mtls_finish (
+ struct mhd_Sha512_256CtxMtls *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA512_256_DIGEST_SIZE)])
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_OUT_ (2);
+
+/**
+ * Reset the context for a new SHA-512/256 calculation.
+ *
+ * This function may be called only after #mhd_SHA512_256_mtls_finish(). If the
+ * context is subsequently reused for a new calculation, this function must be
+ * called before starting that calculation.
+ *
+ * If @a ctx already has a recorded error, this function does nothing and the
+ * error is preserved. Otherwise, if the operation fails, the error is recorded
+ * in @a ctx.
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_mtls_reset (struct mhd_Sha512_256CtxMtls *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
+
+/**
+ * Deinitialise the SHA-512/256 calculation context.
+ *
+ * After calling this function, @a ctx can be reinitialised with
+ * #mhd_SHA512_256_mtls_init().
+ *
+ * The recorded error state in @a ctx is preserved.
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_mtls_deinit (struct mhd_Sha512_256CtxMtls *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
+
+/**
+ * Indicates whether #mhd_SHA512_256_mtls_deinit() is a real function or a
+ * no-op.
+ *
+ * Set to '0' as #mhd_SHA512_256_mtls_deinit() is a real function.
+ */
+#define mhd_SHA512_256_MTLS_DEINIT_NOOP_FLAG 0
+
+
+#endif /* MHD_SHA512_256_MBEDTLS_H */
diff --git a/src/mhd2/sha512_256_openssl.c b/src/mhd2/sha512_256_openssl.c
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
+/*
+ This file is part of GNU libmicrohttpd.
+ Copyright (C) 2026 Evgeny Grin (Karlson2k)
+ Copyright (C) 2025 Christian Grothoff
+
+ GNU libmicrohttpd 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.
+
+ GNU libmicrohttpd 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.
+
+ Alternatively, you can redistribute GNU libmicrohttpd and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version, together
+ with the eCos exception, as follows:
+
+ As a special exception, if other files instantiate templates or
+ use macros or inline functions from this file, or you compile this
+ file and link it with other works to produce a work based on this
+ file, this file does not by itself cause the resulting work to be
+ covered by the GNU General Public License. However the source code
+ for this file must still be made available in accordance with
+ section (3) of the GNU General Public License v2.
+
+ This exception does not invalidate any other reasons why a work
+ based on this file might be covered by the GNU General Public
+ License.
+
+ You should have received copies of the GNU Lesser General Public
+ License and the GNU General Public License along with this library;
+ if not, see <https://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file src/mhd2/sha512_256_openssl.c
+ * @brief Wrapper for SHA-512/256 calculation performed by OpenSSL backend
+ * @author Karlson2k (Evgeny Grin)
+ * @author Christian Grothoff
+ */
+
+#include "mhd_sys_options.h"
+
+#include "mhd_assert.h"
+
+#include <openssl/evp.h>
+
+#include "sha512_256_openssl.h"
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1) void
+mhd_SHA512_256_ossl_init (struct mhd_Sha512_256CtxOssl *ctx)
+{
+ ctx->ossl_ctx = EVP_MD_CTX_new ();
+ ctx->ext_error = (NULL == ctx->ossl_ctx);
+
+ mhd_SHA512_256_ossl_reset (ctx);
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) void
+mhd_SHA512_256_ossl_reset (struct mhd_Sha512_256CtxOssl *ctx)
+{
+ if (ctx->ext_error)
+ return;
+
+ mhd_assert (NULL != ctx->ossl_ctx);
+
+ ctx->ext_error = (0 == EVP_DigestInit_ex (ctx->ossl_ctx,
+ EVP_sha512_256 (),
+ NULL));
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_IN_SIZE_ (3, 2) void
+mhd_SHA512_256_ossl_update (struct mhd_Sha512_256CtxOssl *restrict ctx,
+ size_t size,
+ const void *restrict data)
+{
+#ifndef MHD_UNIT_TESTING
+ mhd_assert (0 != size);
+#endif
+
+ if (ctx->ext_error)
+ return;
+
+ mhd_assert (NULL != ctx->ossl_ctx);
+
+ ctx->ext_error = (0 == EVP_DigestUpdate (ctx->ossl_ctx,
+ data,
+ size));
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_OUT_ (2) void
+mhd_SHA512_256_ossl_finish (
+ struct mhd_Sha512_256CtxOssl *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA512_256_DIGEST_SIZE)])
+{
+ if (!ctx->ext_error)
+ {
+#ifndef NDEBUG
+ unsigned int len;
+
+ mhd_assert (NULL != ctx->ossl_ctx);
+
+ ctx->ext_error = (0 == EVP_DigestFinal_ex (ctx->ossl_ctx,
+ digest,
+ &len));
+ mhd_assert ((ctx->ext_error) || (mhd_SHA512_256_DIGEST_SIZE == len));
+#else
+ ctx->ext_error = (0 == EVP_DigestFinal_ex (ctx->ossl_ctx,
+ digest,
+ NULL));
+#endif
+ }
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) void
+mhd_SHA512_256_ossl_deinit (struct mhd_Sha512_256CtxOssl *ctx)
+{
+ EVP_MD_CTX_free (ctx->ossl_ctx);
+ ctx->ossl_ctx = NULL;
+}
diff --git a/src/mhd2/sha512_256_openssl.h b/src/mhd2/sha512_256_openssl.h
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
+/*
+ This file is part of GNU libmicrohttpd.
+ Copyright (C) 2022-2026 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd 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.
+
+ GNU libmicrohttpd 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.
+
+ Alternatively, you can redistribute GNU libmicrohttpd and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version, together
+ with the eCos exception, as follows:
+
+ As a special exception, if other files instantiate templates or
+ use macros or inline functions from this file, or you compile this
+ file and link it with other works to produce a work based on this
+ file, this file does not by itself cause the resulting work to be
+ covered by the GNU General Public License. However the source code
+ for this file must still be made available in accordance with
+ section (3) of the GNU General Public License v2.
+
+ This exception does not invalidate any other reasons why a work
+ based on this file might be covered by the GNU General Public
+ License.
+
+ You should have received copies of the GNU Lesser General Public
+ License and the GNU General Public License along with this library;
+ if not, see <https://www.gnu.org/licenses/>.
+*/
+/**
+ * @file src/mhd2/sha512_256_openssl.h
+ * @brief Wrapper declarations for SHA-512/256 calculation performed by
+ * OpenSSL backend
+ * @author Karlson2k (Evgeny Grin)
+ */
+#ifndef MHD_SHA512_256_OPENSSL_H
+#define MHD_SHA512_256_OPENSSL_H 1
+
+#include "mhd_sys_options.h"
+
+#include "sys_bool_type.h"
+#include "sys_base_types.h"
+
+#ifndef mhd_SHA512_256_DIGEST_SIZE
+/**
+ * Size of SHA-512/256 resulting digest in bytes
+ * This is the final digest size, not the intermediate hash.
+ */
+# define mhd_SHA512_256_DIGEST_SIZE (32)
+#endif
+
+/* Forward declaration for OpenSSL struct, to avoid including large header */
+struct evp_md_ctx_st;
+
+/**
+ * SHA-512/256 calculation context
+ */
+struct mhd_Sha512_256CtxOssl
+{
+ struct evp_md_ctx_st *ossl_ctx; /**< Hash calculation handle */
+ bool ext_error; /**< 'true' if the hashing backend has reported an error */
+};
+
+/**
+ * Indicates whether struct mhd_Sha512_256CtxOssl has an 'ext_error' member.
+ *
+ * Set to '1' when the structure has an 'ext_error' member.
+ */
+#define mhd_SHA512_256_OSSL_EXT_ERROR_FLAG 1
+
+/**
+ * Initialise the context for SHA-512/256 calculation.
+ *
+ * This function must not be called more than once for @a ctx without an
+ * intervening #mhd_SHA512_256_ossl_deinit().
+ *
+ * The error state in @a ctx is set according to the result: cleared on
+ * success, set on failure.
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_ossl_init (struct mhd_Sha512_256CtxOssl *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1);
+
+/**
+ * Add a portion of data to the SHA-512/256 calculation.
+ *
+ * If @a ctx already has a recorded error, this function does nothing.
+ * Otherwise, if the operation fails, the error is recorded in @a ctx.
+ *
+ * @param ctx the calculation context
+ * @param size number of bytes in @a data, must not be 0
+ * @param data bytes to add to hash
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_ossl_update (struct mhd_Sha512_256CtxOssl *restrict ctx,
+ size_t size,
+ const void *restrict data)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_IN_SIZE_ (3, 2);
+
+/**
+ * Finalise the SHA-512/256 calculation and return the digest.
+ *
+ * If @a ctx already has a recorded error, this function does nothing.
+ * Otherwise, if the operation fails, the error is recorded in @a ctx.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #mhd_SHA512_256_DIGEST_SIZE bytes
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_ossl_finish (
+ struct mhd_Sha512_256CtxOssl *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA512_256_DIGEST_SIZE)])
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_OUT_ (2);
+
+/**
+ * Reset the context for a new SHA-512/256 calculation.
+ *
+ * This function may be called only after #mhd_SHA512_256_ossl_finish(). If the
+ * context is subsequently reused for a new calculation, this function must be
+ * called before starting that calculation.
+ *
+ * If @a ctx already has a recorded error, this function does nothing and the
+ * error is preserved. Otherwise, if the operation fails, the error is recorded
+ * in @a ctx.
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_ossl_reset (struct mhd_Sha512_256CtxOssl *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
+
+/**
+ * Deinitialise the SHA-512/256 calculation context.
+ *
+ * After calling this function, @a ctx can be reinitialised with
+ * #mhd_SHA512_256_ossl_init().
+ *
+ * The recorded error state in @a ctx is preserved.
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA512_256_ossl_deinit (struct mhd_Sha512_256CtxOssl *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
+
+/**
+ * Indicates whether #mhd_SHA512_256_ossl_deinit() is a real function or a
+ * no-op.
+ *
+ * Set to '0' as #mhd_SHA512_256_ossl_deinit() is a real function.
+ */
+#define mhd_SHA512_256_OSSL_DEINIT_NOOP_FLAG 0
+
+
+#endif /* MHD_SHA512_256_OPENSSL_H */
diff --git a/src/tests/unit/Makefile.am b/src/tests/unit/Makefile.am
@@ -155,4 +155,19 @@ if MHD_SHA256_MBEDTLS
$(srcdir)/../../mhd2/sha256_mbedtls.c $(srcdir)/../../mhd2/sha256_mbedtls.h
endif
-unit_sha512_256_SOURCES = unit_sha512_256.c
+unit_sha512_256_SOURCES = \
+ unit_sha512_256.c \
+ $(srcdir)/../../mhd2/mhd_sha512_256.h \
+ $(srcdir)/../../mhd2/sha512_256_builtin.c \
+ $(srcdir)/../../mhd2/sha512_256_builtin.h
+
+if MHD_SUPPORT_OPENSSL
+ unit_sha512_256_SOURCES += \
+ $(srcdir)/../../mhd2/sha512_256_openssl.c \
+ $(srcdir)/../../mhd2/sha512_256_openssl.h
+endif
+if MHD_SUPPORT_MBEDTLS
+ unit_sha512_256_SOURCES += \
+ $(srcdir)/../../mhd2/sha512_256_mbedtls.c \
+ $(srcdir)/../../mhd2/sha512_256_mbedtls.h
+endif
diff --git a/src/tests/unit/unit_sha512_256.c b/src/tests/unit/unit_sha512_256.c
@@ -51,21 +51,12 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
-#include <stdbool.h>
#include "mhdt_has_param.h"
-#if defined MHD_SHA512_256_EXTR_OPENSSL
-# include "../mhd2/sha512_256_ext_openssl.c"
-#elif defined MHD_SHA512_256_EXTR_MBEDTLS
-# include "../mhd2/sha512_256_ext_mbedtls.c"
-#else
-# include "../mhd2/sha512_256_int.c"
-#endif
-
#include "../mhd2/mhd_sha512_256.h"
-#define SHA512_256_DIGEST_STRING_SIZE (mhd_SHA256_DIGEST_SIZE * 2 + 1)
+#define SHA512_256_DIGEST_STRING_SIZE (mhd_SHA512_256_DIGEST_SIZE * 2 + 1)
/**
* Verbose output?
@@ -506,9 +497,9 @@ check_result (const char *test_name,
const uint8_t calculated[mhd_SHA512_256_DIGEST_SIZE],
const uint8_t expected[mhd_SHA512_256_DIGEST_SIZE])
{
- bool failed = (0 != memcmp (calculated,
- expected,
- mhd_SHA512_256_DIGEST_SIZE));
+ int failed = (0 != memcmp (calculated,
+ expected,
+ mhd_SHA512_256_DIGEST_SIZE));
check_num++; /* Print 1-based numbers */
if (failed)
@@ -552,7 +543,7 @@ test1_str (void)
{
uint8_t digest[mhd_SHA512_256_DIGEST_SIZE];
- mhd_SHA512_256_init_one_time (&ctx);
+ mhd_SHA512_256_init (&ctx);
if (0 != data_units1[i].str_l.len)
mhd_SHA512_256_update (&ctx,
data_units1[i].str_l.len,
@@ -580,7 +571,7 @@ test1_bin (void)
{
uint8_t digest[mhd_SHA512_256_DIGEST_SIZE];
- mhd_SHA512_256_init_one_time (&ctx);
+ mhd_SHA512_256_init (&ctx);
mhd_SHA512_256_update (&ctx,
data_units2[i].bin_l.len,
data_units2[i].bin_l.bin);
@@ -609,7 +600,7 @@ test2_str (void)
uint8_t digest[mhd_SHA512_256_DIGEST_SIZE];
size_t part_s = data_units1[i].str_l.len / 4;
- mhd_SHA512_256_init_one_time (&ctx);
+ mhd_SHA512_256_init (&ctx);
if (0 != part_s)
mhd_SHA512_256_update (&ctx,
part_s,
@@ -643,7 +634,7 @@ test2_bin (void)
uint8_t digest[mhd_SHA512_256_DIGEST_SIZE];
size_t part_s = data_units2[i].bin_l.len * 2 / 3;
- mhd_SHA512_256_init_one_time (&ctx);
+ mhd_SHA512_256_init (&ctx);
mhd_SHA512_256_update (&ctx,
part_s,
data_units2[i].bin_l.bin);
@@ -694,7 +685,7 @@ test_unaligned (void)
memset (unaligned_digest,
0,
mhd_SHA512_256_DIGEST_SIZE);
- mhd_SHA512_256_init_one_time (&ctx);
+ mhd_SHA512_256_init (&ctx);
mhd_SHA512_256_update (&ctx,
tdata->bin_l.len,
unaligned_buf);
@@ -751,8 +742,7 @@ main (int argc,
"The quick brown fox jumps over the lazy dog",
"54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67",
"dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d"
- },
- { NULL, NULL, NULL }
+ }
};
struct mhd_Sha512_256Ctx ctx;
uint8_t digest[mhd_SHA512_256_DIGEST_SIZE];
@@ -767,11 +757,11 @@ main (int argc,
verbose = 1;
- while (NULL != tests[total].name)
+ for (total = 0; total < sizeof(tests) / sizeof(tests[0]); ++total)
{
const struct Test *t = &tests[total];
- mhd_SHA512_256_init_one_time (&ctx);
+ mhd_SHA512_256_init (&ctx);
if (!mhd_SHA512_256_has_err (&ctx))
{
data_len = hex2bin (t->input,
@@ -793,17 +783,17 @@ main (int argc,
}
else
{
- printf ("FAIL: %s - error in finish\n",
+ printf ("FAIL: %s - digest function failed due to backend error\n",
t->name);
+ exit (99);
}
}
else
{
printf ("FAIL: %s - error in init\n",
t->name);
+ exit (99);
}
- mhd_SHA512_256_deinit (&ctx);
- total++;
}
num_failed = total - passed;