commit bde54f9b76f04b83f70ca14a3bed747bca09d297
parent 1937a9c7ad0c1a2548cdcd647b6b0c08d86c57a1
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Mon, 13 Jul 2026 18:00:09 +0200
Reworked SHA-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:
19 files changed, 1871 insertions(+), 1530 deletions(-)
diff --git a/src/mhd2/Makefile.am b/src/mhd2/Makefile.am
@@ -184,28 +184,32 @@ md5_OPTSOURCES = \
endif
+# Note: the current configure may enable several SHA-256 TLS-lib conditionals
+# at once, while mhd_sha256.h selects the backends in the GnuTLS, 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_SHA256_INTR
sha256_OPTSOURCES = \
- sha256_int.c sha256_int.h \
+ sha256_builtin.c sha256_builtin.h \
mhd_sha256.h
endif
-if MHD_USE_SHA256_GNUTLS
+if MHD_USE_SHA256_MBEDTLS
sha256_OPTSOURCES = \
- sha256_ext.h mhd_sha256.h \
- sha256_ext_gnutls.c
+ sha256_mbedtls.c sha256_mbedtls.h \
+ mhd_sha256.h
endif
if MHD_USE_SHA256_OPENSSL
sha256_OPTSOURCES = \
- sha256_ext.h mhd_sha256.h \
- sha256_ext_openssl.c
+ sha256_openssl.c sha256_openssl.h \
+ mhd_sha256.h
endif
-if MHD_USE_SHA256_MBEDTLS
+if MHD_USE_SHA256_GNUTLS
sha256_OPTSOURCES = \
- sha256_ext.h mhd_sha256.h \
- sha256_ext_mbedtls.c
+ sha256_gnutls.c sha256_gnutls.h \
+ mhd_sha256.h
endif
diff --git a/src/mhd2/auth_digest.c b/src/mhd2/auth_digest.c
@@ -344,7 +344,7 @@ gen_new_nonce (struct MHD_Daemon *restrict d,
if (mhd_SHA512_256_has_err (&(d_ctx.sha512_256_ctx)))
return false;
#elif defined(MHD_SUPPORT_SHA256)
- mhd_SHA256_init_one_time (&(d_ctx.sha256_ctx));
+ mhd_SHA256_init (&(d_ctx.sha256_ctx));
mhd_SHA256_update (&(d_ctx.sha256_ctx),
d->auth_dg.entropy.size,
(const void *)d->auth_dg.entropy.data);
@@ -1607,7 +1607,7 @@ digest_init_one_time (struct DigestAlgorithm *da,
# ifndef NDEBUG
da->algo_selected = true;
# endif
- mhd_SHA256_init_one_time (&(da->ctx.sha256_ctx));
+ mhd_SHA256_init (&(da->ctx.sha256_ctx));
# ifndef NDEBUG
da->ready_for_hashing = true;
# endif
@@ -1785,17 +1785,10 @@ digest_calc_hash (struct DigestAlgorithm *da,
case MHD_DIGEST_BASE_ALGO_SHA256:
#ifdef MHD_SUPPORT_SHA256
-# ifdef mhd_SHA256_HAS_FINISH
mhd_SHA256_finish (&da->ctx.sha256_ctx, digest);
-# ifndef NDEBUG
+# ifndef NDEBUG
da->ready_for_hashing = false;
-# endif /* _DEBUG */
-# else /* ! mhd_SHA256_HAS_FINISH */
- mhd_SHA256_finish_reset (&da->ctx.sha256_ctx, digest);
-# ifndef NDEBUG
- da->ready_for_hashing = true;
-# endif /* _DEBUG */
-# endif /* ! mhd_SHA256_HAS_FINISH */
+# endif /* _DEBUG */
#else /* ! MHD_SUPPORT_SHA256 */
mhd_UNREACHABLE ();
#endif /* ! MHD_SUPPORT_SHA256 */
@@ -1857,11 +1850,7 @@ digest_reset (struct DigestAlgorithm *da)
case MHD_DIGEST_BASE_ALGO_SHA256:
#ifdef MHD_SUPPORT_SHA256
-# ifdef mhd_SHA256_HAS_FINISH
mhd_assert (!da->ready_for_hashing);
-# else /* ! mhd_SHA256_HAS_FINISH */
- mhd_assert (da->ready_for_hashing);
-# endif /* ! mhd_SHA256_HAS_FINISH */
mhd_SHA256_reset (&(da->ctx.sha256_ctx));
# ifndef NDEBUG
da->ready_for_hashing = true;
diff --git a/src/mhd2/mhd_sha256.h b/src/mhd2/mhd_sha256.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_sha256.h
- * @brief Simple wrapper for selection of built-in/external SHA-256
- * implementation
+ * @brief Simple wrapper for selecting the SHA-256 implementation backend
+ *
+ * Usage: declare a context as 'struct mhd_Sha256Ctx', then call
+ * mhd_SHA256_init(), mhd_SHA256_update() (any number of times) and
+ * mhd_SHA256_finish() to get the digest. Reuse the context with
+ * mhd_SHA256_reset() or release it with mhd_SHA256_deinit(). With some
+ * backends an operation can fail; check with mhd_SHA256_has_err().
+ *
* @author Karlson2k (Evgeny Grin)
*/
@@ -51,81 +57,220 @@
#ifndef MHD_SUPPORT_SHA256
# error This file must be used only when SHA-256 is enabled
#endif
-#ifndef MHD_SHA256_EXTR
-# include "sha256_int.h"
-#else /* MHD_SHA256_EXTR */
-# include "sha256_ext.h"
-#endif /* MHD_SHA256_EXTR */
-#ifndef mhd_SHA256_DIGEST_SIZE
+#include "mhd_macro_concat.h"
+
+#if defined(MHD_SHA256_EXTR_GNUTLS)
+# include "sha256_gnutls.h"
+
+/**
+ * The hashing backend identifier for function names
+ */
+# define mhd_SHA256_FUNC_NAME_ID gtls
/**
- * Size of SHA-256 resulting digest in bytes
- * This is the final digest size, not intermediate hash.
+ * The hashing backend identifier for data names
*/
-# define mhd_SHA256_DIGEST_SIZE (32)
-#endif /* ! mhd_SHA256_DIGEST_SIZE */
+# define mhd_SHA256_DATA_NAME_ID Gtls
+/**
+ * The hashing backend identifier for macro names
+ */
+# define mhd_SHA256_MACRO_NAME_ID GTLS
+
+#elif defined(MHD_SHA256_EXTR_OPENSSL)
+# include "sha256_openssl.h"
-#ifndef MHD_SHA256_EXTR
/**
- * Universal ctx type mapped for chosen implementation
+ * The hashing backend identifier for function names
*/
-# define mhd_Sha256Ctx mhd_Sha256CtxInt
-#else /* MHD_SHA256_EXTR */
+# define mhd_SHA256_FUNC_NAME_ID ossl
/**
- * Universal ctx type mapped for chosen implementation
+ * The hashing backend identifier for data names
*/
-# define mhd_Sha256Ctx mhd_Sha256CtxExt
-#endif /* MHD_SHA256_EXTR */
+# define mhd_SHA256_DATA_NAME_ID Ossl
+/**
+ * The hashing backend identifier for macro names
+ */
+# define mhd_SHA256_MACRO_NAME_ID OSSL
-#ifndef mhd_SHA256_HAS_INIT_ONE_TIME
+#elif defined(MHD_SHA256_EXTR_MBEDTLS)
+# include "sha256_mbedtls.h"
+
+/**
+ * The hashing backend identifier for function names
+ */
+# define mhd_SHA256_FUNC_NAME_ID mtls
+/**
+ * The hashing backend identifier for data names
+ */
+# define mhd_SHA256_DATA_NAME_ID Mtls
/**
- * Setup and prepare ctx for hash calculation
+ * The hashing backend identifier for macro names
*/
-# define mhd_SHA256_init_one_time(ctx) mhd_SHA256_init (ctx)
-#endif /* ! mhd_SHA256_HAS_INIT_ONE_TIME */
+# define mhd_SHA256_MACRO_NAME_ID MTLS
+#elif !defined(MHD_SHA256_EXTR)
+# include "sha256_builtin.h"
-#ifndef mhd_SHA256_HAS_FINISH_RESET
/**
- * Re-use the same ctx for the new hashing after digest calculated
+ * The hashing backend identifier for function names
*/
-# define mhd_SHA256_reset(ctx) mhd_SHA256_init (ctx)
+# define mhd_SHA256_FUNC_NAME_ID blti
/**
- * Finalise SHA-512/256 calculation, return digest, reset hash calculation.
+ * The hashing backend identifier for data names
*/
-# define mhd_SHA256_finish_reset(ctx, digest) \
- (mhd_SHA256_finish (ctx,digest), mhd_SHA256_reset (ctx))
+# define mhd_SHA256_DATA_NAME_ID Blti
/**
- * Finalise hash calculation, return digest, de-initialise hash calculation.
+ * The hashing backend identifier for macro names
*/
-# define mhd_SHA256_finish_deinit(ctx, digest) \
- (mhd_SHA256_finish (ctx,digest), mhd_SHA256_deinit (ctx))
-#else /* mhd_SHA256_HAS_FINISH_RESET */
+# define mhd_SHA256_MACRO_NAME_ID BLTI
+#else
+# error No SHA-256 implementation enabled
+#endif
+
+#if mhd_SHA256_DIGEST_SIZE != 32
+# error Wrong value of mhd_SHA256_DIGEST_SIZE
+#endif
+
/**
- * Finalise SHA-256 calculation, return digest
+ * Form the name of the function specific to the selected hashing backend
*/
-# define mhd_SHA256_finish(ctx, digest) mhd_SHA256_finish_reset(ctx, digest)
-# define mhd_SHA256_reset(ctx) ((void) 0)
+#define mhd_SHA256_FUNC(name_suffix) \
+ mhd_MACRO_CONCAT3 (mhd_SHA256_,mhd_SHA256_FUNC_NAME_ID,name_suffix)
+
/**
- * Finalise hash calculation, return digest, de-initialise hash calculation.
+ * Form the name of the macro specific to the selected hashing backend
*/
-# define mhd_SHA256_finish_deinit(ctx, digest) \
- (mhd_SHA256_finish_reset (ctx,digest), mhd_SHA256_deinit (ctx))
-#endif /* mhd_SHA256_HAS_FINISH_RESET */
+#define mhd_SHA256_MACRO(name_suffix) \
+ mhd_MACRO_CONCAT3 (mhd_SHA256_,mhd_SHA256_MACRO_NAME_ID,name_suffix)
-#ifndef mhd_SHA256_HAS_DEINIT
-# define mhd_SHA256_deinit(ctx) ((void) 0)
-#endif /* HAVE_SHA256_DEINIT */
+/**
+ * Struct tag of the calculation context for the selected SHA-256 backend
+ */
+#define mhd_Sha256Ctx mhd_MACRO_CONCAT(mhd_Sha256Ctx,mhd_SHA256_DATA_NAME_ID)
-#ifdef mhd_SHA256_HAS_EXT_ERROR
-# define mhd_SHA256_has_err(ctx) (0 != ((ctx)->ext_error))
-#else /* ! mhd_SHA256_HAS_EXT_ERROR */
-# define mhd_SHA256_has_err(ctx) (((void) (ctx)), ! ! 0)
-#endif /* ! mhd_SHA512_256_HAS_EXT_ERROR */
-/* Sanity checks */
+#if 0 != mhd_SHA256_MACRO (_EXT_ERROR_FLAG)
+/**
+ * Indicates that SHA-256 hashing or initialisation may result in an error
+ */
+# define mhd_SHA256_HAS_EXT_ERROR 1
+/**
+ * 'true' if the hashing backend has reported an error
+ */
+# define mhd_SHA256_has_err(ctx) (!!((ctx)->ext_error))
+/**
+ * Get the error number reported by hashing backend (zero if no error)
+ */
+# define mhd_SHA256_get_err(ctx) ((int)((ctx)->ext_error))
+#else
+# define mhd_SHA256_has_err(ctx) (((void) (ctx)), !!0)
+/**
+ * Get the error number (zero if no error)
+ */
+# define mhd_SHA256_get_err(ctx) ((int)(0))
+#endif
+
+/**
+ * Initialise the context for SHA-256 calculation.
+ *
+ * This function must not be called more than once for @a ctx without an
+ * intervening #mhd_SHA256_deinit().
+ *
+ * Whether or not an error is reported, #mhd_SHA256_deinit() must be
+ * called for @a ctx once this function has returned.
+ *
+ * For backends that track errors (see #mhd_SHA256_has_err()), the error state
+ * is set according to the result: cleared on success, set on failure.
+ *
+ * @param ctx the calculation context
+ */
+#define mhd_SHA256_init(ctx) mhd_SHA256_FUNC(_init) ((ctx))
+
+/**
+ * Add a portion of data to the SHA-256 calculation.
+ *
+ * For backends that track errors (see #mhd_SHA256_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_SHA256_update(ctx, size, data) \
+ mhd_SHA256_FUNC(_update) ((ctx),(size),(data))
+
+/**
+ * Finalise the SHA-256 calculation and return the digest.
+ *
+ * For backends that track errors (see #mhd_SHA256_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_SHA256_DIGEST_SIZE bytes
+ */
+#define mhd_SHA256_finish(ctx, digest) \
+ mhd_SHA256_FUNC(_finish) ((ctx),(digest))
+
+/**
+ * Reset the context for a new SHA-256 calculation.
+ *
+ * This function may be called only after #mhd_SHA256_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_SHA256_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_SHA256_reset(ctx) mhd_SHA256_FUNC(_reset) ((ctx))
+
+/**
+ * Finalise the SHA-256 calculation, return the digest and reset the context.
+ *
+ * For backends that track errors (see #mhd_SHA256_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_SHA256_DIGEST_SIZE bytes
+ */
+#define mhd_SHA256_finish_reset(ctx, digest) \
+ (mhd_SHA256_finish((ctx),(digest)), mhd_SHA256_reset((ctx)))
+
+/**
+ * Deinitialise the SHA-256 calculation context.
+ *
+ * After calling this function, @a ctx can be reinitialised with
+ * #mhd_SHA256_init().
+ *
+ * For backends that track errors (see #mhd_SHA256_has_err()), the recorded
+ * error state is preserved.
+ *
+ * @param ctx the calculation context
+ */
+#define mhd_SHA256_deinit(ctx) mhd_SHA256_FUNC(_deinit) ((ctx))
+
+/**
+ * Finalise the SHA-256 calculation, return the digest and deinitialise
+ * the context.
+ *
+ * For backends that track errors (see #mhd_SHA256_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_SHA256_DIGEST_SIZE bytes
+ */
+#define mhd_SHA256_finish_deinit(ctx, digest) \
+ (mhd_SHA256_finish((ctx),(digest)), mhd_SHA256_deinit((ctx)))
+
+#if 0 == mhd_SHA256_MACRO (_DEINIT_NOOP_FLAG)
+/**
+ * Indicates that #mhd_SHA256_deinit() is a real function that must be called.
+ */
+# define mhd_SHA256_HAS_DEINIT
+#endif
-#if !defined(mhd_SHA256_HAS_FINISH_RESET) && !defined(mhd_SHA256_HAS_FINISH)
-# error Required mhd_SHA256_finish_reset() or mhd_SHA256_finish()
-#endif /* ! mhd_SHA256_HAS_FINISH_RESET && ! mhd_SHA256_HAS_FINISH */
#endif /* MHD_SHA256_H */
diff --git a/src/mhd2/sha256_builtin.c b/src/mhd2/sha256_builtin.c
@@ -0,0 +1,576 @@
+/* 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) 2019-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/sha256_builtin.c
+ * @brief Calculation of SHA-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 "sha256_builtin.h"
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1) void
+mhd_SHA256_blti_init (struct mhd_Sha256CtxBlti *ctx)
+{
+ /* Initial hash values, see FIPS PUB 180-4 paragraph 5.3.3 */
+ /* First thirty-two bits of the fractional parts of the square
+ * roots of the first eight prime numbers: 2, 3, 5, 7, 11, 13,
+ * 17, 19." */
+ ctx->H[0] = UINT32_C (0x6a09e667);
+ ctx->H[1] = UINT32_C (0xbb67ae85);
+ ctx->H[2] = UINT32_C (0x3c6ef372);
+ ctx->H[3] = UINT32_C (0xa54ff53a);
+ ctx->H[4] = UINT32_C (0x510e527f);
+ ctx->H[5] = UINT32_C (0x9b05688c);
+ ctx->H[6] = UINT32_C (0x1f83d9ab);
+ ctx->H[7] = UINT32_C (0x5be0cd19);
+
+ /* Initialise number of bytes. */
+ ctx->count = 0;
+}
+
+
+mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE
+
+static MHD_FN_PAR_NONNULL_ALL_ void
+sha256_transform (uint32_t H[mhd_SHA256_DIGEST_SIZE_WORDS],
+ const void *restrict data)
+{
+ /* Working variables,
+ see FIPS PUB 180-4 paragraph 6.2. */
+ uint32_t a = H[0];
+ uint32_t b = H[1];
+ uint32_t c = H[2];
+ uint32_t d = H[3];
+ uint32_t e = H[4];
+ uint32_t f = H[5];
+ uint32_t g = H[6];
+ uint32_t h = H[7];
+
+ /* Data buffer, used as cyclic buffer.
+ See FIPS PUB 180-4 paragraphs 5.2.1, 6.2. */
+ uint32_t W[16];
+
+#ifndef mhd_GET_32BIT_BE_UNALIGNED
+ if (0 != (((uintptr_t)data) % mhd_UINT32_ALIGN))
+ {
+ /* Copy the unaligned input data to the aligned buffer */
+ memcpy (W, data, mhd_SHA256_BLOCK_SIZE);
+ /* The W[] buffer itself will be used as the source of the data,
+ * but data will be reloaded in correct bytes order during
+ * the next steps */
+ data = (const void *)W;
+ }
+#endif /* mhd_GET_32BIT_BE_UNALIGNED */
+
+ /* 'Ch' and 'Maj' macro functions are defined with
+ widely-used optimization.
+ See FIPS PUB 180-4 formulae 4.2, 4.3. */
+#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.4, 4.5, 4.6, 4.7. */
+#define SIG0(x) (mhd_ROTR32 ((x), 2) ^ mhd_ROTR32 ((x), 13) ^ \
+ mhd_ROTR32 ((x), 22) )
+#define SIG1(x) (mhd_ROTR32 ((x), 6) ^ mhd_ROTR32 ((x), 11) ^ \
+ mhd_ROTR32 ((x), 25) )
+#define sig0(x) (mhd_ROTR32 ((x), 7) ^ mhd_ROTR32 ((x), 18) ^ \
+ ((x) >> 3) )
+#define sig1(x) (mhd_ROTR32 ((x), 17) ^ mhd_ROTR32 ((x),19) ^ \
+ ((x) >> 10) )
+
+ /* One step of SHA-256 computation,
+ see FIPS PUB 180-4 paragraph 6.2.2 step 3.
+ * Note: this macro updates working variables in-place, without rotation.
+ * Note: first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in FIPS PUB 180-4 paragraph 6.2.2 step 3.
+ second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in FIPS PUB 180-4 paragraph 6.2.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 SHA2STEP32(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,
+ See FIPS PUB 180-4 paragraph 6.2.
+ Input data must be read in big-endian bytes order,
+ see FIPS PUB 180-4 paragraph 3.1.2. */
+ /* Use cast to (const void*) to mute compiler alignment warning,
+ * data was already aligned in previous step */
+#define GET_W_FROM_DATA(buf, t) \
+ mhd_GET_32BIT_BE ((const void*) (((const uint8_t*) (buf)) + \
+ (t) * mhd_SHA256_BYTES_IN_WORD))
+
+ /* 'W' generation and assignment for 16 <= t <= 63.
+ See FIPS PUB 180-4 paragraph 6.2.2.
+ As only last 16 'W' are used in calculations, it is possible to
+ use 16 elements array of W as cyclic buffer.
+ * Note: ((t-16)&0xf) have same value as (t&0xf) */
+#define Wgen(w, t) ( (w)[(t - 16) & 0xf] + sig1 ((w)[((t) - 2) & 0xf]) \
+ + (w)[((t) - 7) & 0xf] + sig0 ((w)[((t) - 15) & 0xf]) )
+
+#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 paragraph 4.2.2 for
+ K values. */
+ /* Note: instead of reassigning all working variables on each step,
+ variables are rotated for each step:
+ SHA2STEP32(a, b, c, d, e, f, g, h, K[0], data[0]);
+ SHA2STEP32(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. */
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x428a2f98), W[0]);
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x71374491), W[1]);
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0xb5c0fbcf), W[2]);
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0xe9b5dba5), W[3]);
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x3956c25b), W[4]);
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x59f111f1), W[5]);
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x923f82a4), W[6]);
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xab1c5ed5), W[7]);
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0xd807aa98), W[8]);
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x12835b01), W[9]);
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x243185be), W[10]);
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x550c7dc3), W[11]);
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x72be5d74), W[12]);
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x80deb1fe), W[13]);
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x9bdc06a7), W[14]);
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc19bf174), 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 input data buffer as big-endian value and
+ stored in array of W elements. */
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x428a2f98), W[0] = \
+ GET_W_FROM_DATA (data, 0));
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x71374491), W[1] = \
+ GET_W_FROM_DATA (data, 1));
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0xb5c0fbcf), W[2] = \
+ GET_W_FROM_DATA (data, 2));
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0xe9b5dba5), W[3] = \
+ GET_W_FROM_DATA (data, 3));
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x3956c25b), W[4] = \
+ GET_W_FROM_DATA (data, 4));
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x59f111f1), W[5] = \
+ GET_W_FROM_DATA (data, 5));
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x923f82a4), W[6] = \
+ GET_W_FROM_DATA (data, 6));
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xab1c5ed5), W[7] = \
+ GET_W_FROM_DATA (data, 7));
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0xd807aa98), W[8] = \
+ GET_W_FROM_DATA (data, 8));
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x12835b01), W[9] = \
+ GET_W_FROM_DATA (data, 9));
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x243185be), W[10] = \
+ GET_W_FROM_DATA (data, 10));
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x550c7dc3), W[11] = \
+ GET_W_FROM_DATA (data, 11));
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x72be5d74), W[12] = \
+ GET_W_FROM_DATA (data, 12));
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x80deb1fe), W[13] = \
+ GET_W_FROM_DATA (data, 13));
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x9bdc06a7), W[14] = \
+ GET_W_FROM_DATA (data, 14));
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc19bf174), W[15] = \
+ GET_W_FROM_DATA (data, 15));
+ }
+
+ /* During last 48 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 paragraph 4.2.2 for K values. */
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0xe49b69c1), W[16 & 0xf] = \
+ Wgen (W, 16));
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0xefbe4786), W[17 & 0xf] = \
+ Wgen (W, 17));
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x0fc19dc6), W[18 & 0xf] = \
+ Wgen (W, 18));
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x240ca1cc), W[19 & 0xf] = \
+ Wgen (W, 19));
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x2de92c6f), W[20 & 0xf] = \
+ Wgen (W, 20));
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x4a7484aa), W[21 & 0xf] = \
+ Wgen (W, 21));
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x5cb0a9dc), W[22 & 0xf] = \
+ Wgen (W, 22));
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x76f988da), W[23 & 0xf] = \
+ Wgen (W, 23));
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x983e5152), W[24 & 0xf] = \
+ Wgen (W, 24));
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0xa831c66d), W[25 & 0xf] = \
+ Wgen (W, 25));
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0xb00327c8), W[26 & 0xf] = \
+ Wgen (W, 26));
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0xbf597fc7), W[27 & 0xf] = \
+ Wgen (W, 27));
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0xc6e00bf3), W[28 & 0xf] = \
+ Wgen (W, 28));
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0xd5a79147), W[29 & 0xf] = \
+ Wgen (W, 29));
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x06ca6351), W[30 & 0xf] = \
+ Wgen (W, 30));
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x14292967), W[31 & 0xf] = \
+ Wgen (W, 31));
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x27b70a85), W[32 & 0xf] = \
+ Wgen (W, 32));
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x2e1b2138), W[33 & 0xf] = \
+ Wgen (W, 33));
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x4d2c6dfc), W[34 & 0xf] = \
+ Wgen (W, 34));
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x53380d13), W[35 & 0xf] = \
+ Wgen (W, 35));
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x650a7354), W[36 & 0xf] = \
+ Wgen (W, 36));
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x766a0abb), W[37 & 0xf] = \
+ Wgen (W, 37));
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x81c2c92e), W[38 & 0xf] = \
+ Wgen (W, 38));
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x92722c85), W[39 & 0xf] = \
+ Wgen (W, 39));
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0xa2bfe8a1), W[40 & 0xf] = \
+ Wgen (W, 40));
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0xa81a664b), W[41 & 0xf] = \
+ Wgen (W, 41));
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0xc24b8b70), W[42 & 0xf] = \
+ Wgen (W, 42));
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0xc76c51a3), W[43 & 0xf] = \
+ Wgen (W, 43));
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0xd192e819), W[44 & 0xf] = \
+ Wgen (W, 44));
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0xd6990624), W[45 & 0xf] = \
+ Wgen (W, 45));
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0xf40e3585), W[46 & 0xf] = \
+ Wgen (W, 46));
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x106aa070), W[47 & 0xf] = \
+ Wgen (W, 47));
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x19a4c116), W[48 & 0xf] = \
+ Wgen (W, 48));
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x1e376c08), W[49 & 0xf] = \
+ Wgen (W, 49));
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x2748774c), W[50 & 0xf] = \
+ Wgen (W, 50));
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x34b0bcb5), W[51 & 0xf] = \
+ Wgen (W, 51));
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x391c0cb3), W[52 & 0xf] = \
+ Wgen (W, 52));
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x4ed8aa4a), W[53 & 0xf] = \
+ Wgen (W, 53));
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x5b9cca4f), W[54 & 0xf] = \
+ Wgen (W, 54));
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x682e6ff3), W[55 & 0xf] = \
+ Wgen (W, 55));
+ SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x748f82ee), W[56 & 0xf] = \
+ Wgen (W, 56));
+ SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x78a5636f), W[57 & 0xf] = \
+ Wgen (W, 57));
+ SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x84c87814), W[58 & 0xf] = \
+ Wgen (W, 58));
+ SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x8cc70208), W[59 & 0xf] = \
+ Wgen (W, 59));
+ SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x90befffa), W[60 & 0xf] = \
+ Wgen (W, 60));
+ SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0xa4506ceb), W[61 & 0xf] = \
+ Wgen (W, 61));
+ SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0xbef9a3f7), W[62 & 0xf] = \
+ Wgen (W, 62));
+ SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc67178f2), W[63 & 0xf] = \
+ Wgen (W, 63));
+#else /* ! MHD_FAVOR_SMALL_CODE */
+ if (1)
+ {
+ unsigned int t;
+ /* K constants array.
+ See FIPS PUB 180-4 paragraph 4.2.2 for K values. */
+ static const uint32_t K[80] =
+ { UINT32_C (0x428a2f98), UINT32_C (0x71374491), UINT32_C (0xb5c0fbcf),
+ UINT32_C (0xe9b5dba5), UINT32_C (0x3956c25b), UINT32_C (0x59f111f1),
+ UINT32_C (0x923f82a4), UINT32_C (0xab1c5ed5), UINT32_C (0xd807aa98),
+ UINT32_C (0x12835b01), UINT32_C (0x243185be), UINT32_C (0x550c7dc3),
+ UINT32_C (0x72be5d74), UINT32_C (0x80deb1fe), UINT32_C (0x9bdc06a7),
+ UINT32_C (0xc19bf174), UINT32_C (0xe49b69c1), UINT32_C (0xefbe4786),
+ UINT32_C (0x0fc19dc6), UINT32_C (0x240ca1cc), UINT32_C (0x2de92c6f),
+ UINT32_C (0x4a7484aa), UINT32_C (0x5cb0a9dc), UINT32_C (0x76f988da),
+ UINT32_C (0x983e5152), UINT32_C (0xa831c66d), UINT32_C (0xb00327c8),
+ UINT32_C (0xbf597fc7), UINT32_C (0xc6e00bf3), UINT32_C (0xd5a79147),
+ UINT32_C (0x06ca6351), UINT32_C (0x14292967), UINT32_C (0x27b70a85),
+ UINT32_C (0x2e1b2138), UINT32_C (0x4d2c6dfc), UINT32_C (0x53380d13),
+ UINT32_C (0x650a7354), UINT32_C (0x766a0abb), UINT32_C (0x81c2c92e),
+ UINT32_C (0x92722c85), UINT32_C (0xa2bfe8a1), UINT32_C (0xa81a664b),
+ UINT32_C (0xc24b8b70), UINT32_C (0xc76c51a3), UINT32_C (0xd192e819),
+ UINT32_C (0xd6990624), UINT32_C (0xf40e3585), UINT32_C (0x106aa070),
+ UINT32_C (0x19a4c116), UINT32_C (0x1e376c08), UINT32_C (0x2748774c),
+ UINT32_C (0x34b0bcb5), UINT32_C (0x391c0cb3), UINT32_C (0x4ed8aa4a),
+ UINT32_C (0x5b9cca4f), UINT32_C (0x682e6ff3), UINT32_C (0x748f82ee),
+ UINT32_C (0x78a5636f), UINT32_C (0x84c87814), UINT32_C (0x8cc70208),
+ UINT32_C (0x90befffa), UINT32_C (0xa4506ceb), UINT32_C (0xbef9a3f7),
+ UINT32_C (0xc67178f2) };
+ /* One step of SHA-256 computation with working variables rotation,
+ see FIPS PUB 180-4 paragraph 6.2.2 step 3.
+ * Note: this version of macro reassign all working variable on
+ each step. */
+# define SHA2STEP32RV(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) do { \
+ uint32_t tmp_h_ = (vH); \
+ SHA2STEP32 ((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 input data buffer as big-endian value and
+ stored in array of W elements. */
+ for (t = 0; t < 16; ++t)
+ {
+ SHA2STEP32RV (a, b, c, d, e, f, g, h, K[t], \
+ W[t] = GET_W_FROM_DATA (data, t));
+ }
+
+ /* During last 48 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 < 64; ++t)
+ {
+ SHA2STEP32RV (a, b, c, d, e, f, g, h, K[t], W[t & 15] = Wgen (W, t));
+ }
+ }
+#endif /* ! MHD_FAVOR_SMALL_CODE */
+
+ /* Compute intermediate hash.
+ See FIPS PUB 180-4 paragraph 6.2.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_SHA256_blti_update (struct mhd_Sha256CtxBlti *restrict ctx,
+ size_t size,
+ const void *restrict data)
+{
+ unsigned bytes_have; /**< Number of bytes in buffer */
+ const uint8_t *unpr_d;
+
+ unpr_d = (const uint8_t *)data;
+
+#ifndef MHD_UNIT_TESTING
+ mhd_assert (0 != size);
+#endif
+
+ /* Note: (count & (mhd_SHA256_BLOCK_SIZE-1))
+ equals (count % mhd_SHA256_BLOCK_SIZE) for this block size. */
+ bytes_have = (unsigned)(ctx->count & (mhd_SHA256_BLOCK_SIZE - 1));
+ ctx->count += size;
+
+ if (0 != bytes_have)
+ {
+ unsigned bytes_left = mhd_SHA256_BLOCK_SIZE - bytes_have;
+ if (size >= bytes_left)
+ { /* Combine new data with data in the buffer and
+ process full block. */
+ memcpy (((uint8_t *)ctx->buffer) + bytes_have,
+ unpr_d,
+ bytes_left);
+ unpr_d += bytes_left;
+ size -= bytes_left;
+ sha256_transform (ctx->H, ctx->buffer);
+ bytes_have = 0;
+ }
+ }
+
+ while (mhd_SHA256_BLOCK_SIZE <= size)
+ { /* Process any full blocks of new data directly,
+ without copying to the buffer. */
+ sha256_transform (ctx->H, unpr_d);
+ unpr_d += mhd_SHA256_BLOCK_SIZE;
+ size -= mhd_SHA256_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" padding addition in bytes.
+ * See FIPS PUB 180-4 paragraph 5.1.1.
+ */
+#define SHA256_SIZE_OF_LEN_ADD (64 / 8)
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_OUT_ (2) void
+mhd_SHA256_blti_finish (
+ struct mhd_Sha256CtxBlti *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA256_DIGEST_SIZE)])
+{
+ uint64_t num_bits; /**< Number of processed bits */
+ unsigned bytes_have; /**< Number of bytes in buffer */
+
+ num_bits = ctx->count << 3;
+ /* Note: (count & (mhd_SHA256_BLOCK_SIZE-1))
+ equal (count % mhd_SHA256_BLOCK_SIZE) for this block size. */
+ bytes_have = (unsigned)(ctx->count & (mhd_SHA256_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 paragraph 5.1.1. */
+
+ /* Data is always processed in form of bytes (not by individual bits),
+ therefore position of first padding bit in byte is always
+ predefined (0x80). */
+ /* Buffer always have space at least for one byte (as full buffers are
+ processed immediately). */
+ ((uint8_t *)ctx->buffer)[bytes_have++] = 0x80;
+
+ if (mhd_SHA256_BLOCK_SIZE - bytes_have < SHA256_SIZE_OF_LEN_ADD)
+ { /* No space in current block to put total length of message.
+ Pad current block with zeros and process it. */
+ if (bytes_have < mhd_SHA256_BLOCK_SIZE)
+ memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
+ mhd_SHA256_BLOCK_SIZE - bytes_have);
+ /* Process full block. */
+ sha256_transform (ctx->H, ctx->buffer);
+ /* Start new block. */
+ bytes_have = 0;
+ }
+
+ /* Pad the rest of the buffer with zeros. */
+ memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
+ mhd_SHA256_BLOCK_SIZE - SHA256_SIZE_OF_LEN_ADD - bytes_have);
+ /* Put the number of bits in processed message as big-endian value. */
+ mhd_PUT_64BIT_BE_UNALIGN (ctx->buffer + mhd_SHA256_BLOCK_SIZE_WORDS - 2,
+ num_bits);
+ /* Process full final block. */
+ sha256_transform (ctx->H, ctx->buffer);
+
+ /* Put final hash/digest in BE mode */
+ if (1)
+ {
+ bool use_tmp_buf_to_align_result;
+
+#if defined(mhd_PUT_32BIT_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_UINT32_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. */
+ uint32_t alig_dgst[mhd_SHA256_DIGEST_SIZE_WORDS];
+ mhd_PUT_32BIT_BE (alig_dgst + 0, ctx->H[0]);
+ mhd_PUT_32BIT_BE (alig_dgst + 1, ctx->H[1]);
+ mhd_PUT_32BIT_BE (alig_dgst + 2, ctx->H[2]);
+ mhd_PUT_32BIT_BE (alig_dgst + 3, ctx->H[3]);
+ mhd_PUT_32BIT_BE (alig_dgst + 4, ctx->H[4]);
+ mhd_PUT_32BIT_BE (alig_dgst + 5, ctx->H[5]);
+ mhd_PUT_32BIT_BE (alig_dgst + 6, ctx->H[6]);
+ mhd_PUT_32BIT_BE (alig_dgst + 7, ctx->H[7]);
+ /* Copy result to unaligned destination address */
+ memcpy (digest, alig_dgst, mhd_SHA256_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_32BIT_BE ((void *)(digest + 0 * mhd_SHA256_BYTES_IN_WORD), \
+ ctx->H[0]);
+ mhd_PUT_32BIT_BE ((void *)(digest + 1 * mhd_SHA256_BYTES_IN_WORD), \
+ ctx->H[1]);
+ mhd_PUT_32BIT_BE ((void *)(digest + 2 * mhd_SHA256_BYTES_IN_WORD), \
+ ctx->H[2]);
+ mhd_PUT_32BIT_BE ((void *)(digest + 3 * mhd_SHA256_BYTES_IN_WORD), \
+ ctx->H[3]);
+ mhd_PUT_32BIT_BE ((void *)(digest + 4 * mhd_SHA256_BYTES_IN_WORD), \
+ ctx->H[4]);
+ mhd_PUT_32BIT_BE ((void *)(digest + 5 * mhd_SHA256_BYTES_IN_WORD), \
+ ctx->H[5]);
+ mhd_PUT_32BIT_BE ((void *)(digest + 6 * mhd_SHA256_BYTES_IN_WORD), \
+ ctx->H[6]);
+ mhd_PUT_32BIT_BE ((void *)(digest + 7 * mhd_SHA256_BYTES_IN_WORD), \
+ ctx->H[7]);
+ }
+ }
+
+ /* Erase potentially sensitive data. */
+ memset (ctx, 0, sizeof(struct mhd_Sha256CtxBlti));
+}
+
+
+mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE
diff --git a/src/mhd2/sha256_builtin.h b/src/mhd2/sha256_builtin.h
@@ -0,0 +1,176 @@
+/* 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) 2019-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/sha256_builtin.h
+ * @brief Calculation of SHA-256 digest, built-in implementation
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_SHA256_BUILTIN_H
+#define MHD_SHA256_BUILTIN_H 1
+
+#include "mhd_sys_options.h"
+
+#include "sys_base_types.h"
+
+
+/**
+ * Digest is kept internally as 8 32-bit words.
+ */
+#define mhd_SHA256_DIGEST_SIZE_WORDS 8
+
+/**
+ * Number of bits in single SHA-256 word
+ */
+#define mhd_SHA256_WORD_SIZE_BITS 32
+
+/**
+ * Number of bytes in single SHA-256 word
+ * used to process data
+ */
+#define mhd_SHA256_BYTES_IN_WORD (mhd_SHA256_WORD_SIZE_BITS / 8)
+
+#ifndef mhd_SHA256_DIGEST_SIZE
+/**
+ * Size of SHA-256 digest in bytes
+ */
+# define mhd_SHA256_DIGEST_SIZE \
+ (mhd_SHA256_DIGEST_SIZE_WORDS * mhd_SHA256_BYTES_IN_WORD)
+#endif
+
+/**
+ * Size of single processing block in bits
+ */
+#define mhd_SHA256_BLOCK_SIZE_BITS 512
+
+/**
+ * Size of single processing block in bytes
+ */
+#define mhd_SHA256_BLOCK_SIZE (mhd_SHA256_BLOCK_SIZE_BITS / 8)
+
+/**
+ * Size of single processing block in bytes
+ */
+#define mhd_SHA256_BLOCK_SIZE_WORDS \
+ (mhd_SHA256_BLOCK_SIZE_BITS / mhd_SHA256_WORD_SIZE_BITS)
+
+
+/**
+ * SHA-256 calculation context
+ */
+struct mhd_Sha256CtxBlti
+{
+ uint32_t H[mhd_SHA256_DIGEST_SIZE_WORDS]; /**< Intermediate hash value / digest at end of calculation */
+ uint32_t buffer[mhd_SHA256_BLOCK_SIZE_WORDS]; /**< SHA256 input data buffer */
+ uint64_t count; /**< number of bytes, mod 2^64 */
+};
+
+/**
+ * Indicates whether struct mhd_Sha256CtxBlti has an 'ext_error' member.
+ *
+ * Set to '0' when the structure has no 'ext_error' member.
+ */
+#define mhd_SHA256_BLTI_EXT_ERROR_FLAG 0
+
+/**
+ * Initialise the context for SHA-256 calculation.
+ *
+ * This function must not be called more than once for @a ctx without an
+ * intervening #mhd_SHA256_blti_deinit().
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA256_blti_init (struct mhd_Sha256CtxBlti *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1);
+
+/**
+ * Add a portion of data to the SHA-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_SHA256_blti_update (struct mhd_Sha256CtxBlti *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-256 calculation and return the digest.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #mhd_SHA256_DIGEST_SIZE bytes
+ */
+MHD_INTERNAL void
+mhd_SHA256_blti_finish (
+ struct mhd_Sha256CtxBlti *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA256_DIGEST_SIZE)])
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_OUT_ (2);
+
+/**
+ * Reset the context for a new SHA-256 calculation.
+ *
+ * This function may be called only after #mhd_SHA256_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_SHA256_blti_reset(ctx) mhd_SHA256_blti_init((ctx))
+
+/**
+ * Deinitialise the SHA-256 calculation context.
+ *
+ * After calling this function, @a ctx can be reinitialised with
+ * #mhd_SHA256_blti_init().
+ *
+ * @param ctx the calculation context
+ */
+#define mhd_SHA256_blti_deinit(ctx) ((void) (ctx))
+
+/**
+ * Indicates whether #mhd_SHA256_blti_deinit() is a real function or a no-op.
+ *
+ * Set to '1' as #mhd_SHA256_blti_deinit() is a no-op.
+ */
+#define mhd_SHA256_BLTI_DEINIT_NOOP_FLAG 1
+
+#endif /* MHD_SHA256_BUILTIN_H */
diff --git a/src/mhd2/sha256_ext.h b/src/mhd2/sha256_ext.h
@@ -1,270 +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 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/sha256_ext.h
- * @brief Wrapper declarations for SHA-256 calculation performed by TLS library
- * @author Karlson2k (Evgeny Grin)
- */
-
-#ifndef MHD_SHA256_EXT_H
-# define MHD_SHA256_EXT_H 1
-
-# include "mhd_sys_options.h"
-# include <stdint.h>
-# include "sys_sizet_type.h"
-
-/**
- * Size of SHA-256 resulting digest in bytes
- * This is the final digest size, not intermediate hash.
- */
-# define mhd_SHA256_DIGEST_SIZE (32)
-
-# ifndef MHD_SHA256_Context
-# define MHD_SHA256_Context void
-# endif
-
-/**
- * Indicates that struct mhd_Sha256CtxExt has 'ext_error'
- */
-# define mhd_SHA256_HAS_EXT_ERROR 1
-
-# ifndef MHD_SHA256_Context
-# define MHD_SHA256_Context void
-# endif
-
-/**
- * SHA-256 calculation context
- */
-struct mhd_Sha256CtxExt
-{
- MHD_SHA256_Context *handle; /**< Hash calculation handle */
- int ext_error; /**< Non-zero if external error occurs during init or hashing */
-};
-
-/**
- * Indicates that mhd_SHA256_init_one_time() function is present.
- */
-# define mhd_SHA256_HAS_INIT_ONE_TIME 1
-
-/**
- * Initialise structure for SHA-256 calculation, allocate resources.
- *
- * This function must not be called more than one time for @a ctx.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_init_one_time (struct mhd_Sha256CtxExt *ctx);
-
-
-/**
- * SHA-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_SHA256_update (struct mhd_Sha256CtxExt *ctx,
- size_t size,
- const uint8_t *data);
-
-
-/**
- * Indicates that mhd_SHA256_finish_reset() function is available
- */
-# define mhd_SHA256_HAS_FINISH_RESET 1
-
-/**
- * Finalise SHA-256 calculation, return digest, reset hash calculation.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA256_DIGEST_SIZE bytes
- */
-void
-mhd_SHA256_finish_reset (struct mhd_Sha256CtxExt *ctx,
- uint8_t digest[mhd_SHA256_DIGEST_SIZE]);
-
-/**
- * Indicates that mhd_SHA256_deinit() function is present
- */
-# define mhd_SHA256_HAS_DEINIT 1
-
-/**
- * Free allocated resources.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_deinit (struct mhd_Sha256CtxExt *ctx);
-
-#endif /* MHD_SHA256_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/sha256_ext.h
- * @brief Wrapper declarations for SHA-256 calculation performed by TLS library
- * @author Karlson2k (Evgeny Grin)
- */
-
-#ifndef MHD_SHA256_EXT_H
-# define MHD_SHA256_EXT_H 1
-
-# include "mhd_sys_options.h"
-# include <stdint.h>
-# include "sys_sizet_type.h"
-
-/**
- * Size of SHA-256 resulting digest in bytes
- * This is the final digest size, not intermediate hash.
- */
-# define mhd_SHA256_DIGEST_SIZE (32)
-
-# ifndef MHD_SHA256_Context
-# define MHD_SHA256_Context void
-# endif
-
-/**
- * Indicates that struct mhd_Sha256CtxExt has 'ext_error'
- */
-# define mhd_SHA256_HAS_EXT_ERROR 1
-
-/**
- * SHA-256 calculation context
- */
-struct mhd_Sha256CtxExt
-{
- MHD_SHA256_Context *handle; /**< Hash calculation handle */
- int ext_error; /**< Non-zero if external error occurs during init or hashing */
-};
-
-/**
- * Indicates that mhd_SHA256_init_one_time() function is present.
- */
-# define mhd_SHA256_HAS_INIT_ONE_TIME 1
-
-/**
- * Initialise structure for SHA-256 calculation, allocate resources.
- *
- * This function must not be called more than one time for @a ctx.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_init_one_time (struct mhd_Sha256CtxExt *ctx);
-
-
-/**
- * SHA-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_SHA256_update (struct mhd_Sha256CtxExt *ctx,
- size_t size,
- const uint8_t *data);
-
-
-/**
- * Indicates that mhd_SHA256_finish_reset() function is available
- */
-# define mhd_SHA256_HAS_FINISH_RESET 1
-
-/**
- * Finalise SHA-256 calculation, return digest, reset hash calculation.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA256_DIGEST_SIZE bytes
- */
-void
-mhd_SHA256_finish_reset (struct mhd_Sha256CtxExt *ctx,
- uint8_t digest[mhd_SHA256_DIGEST_SIZE]);
-
-/**
- * Indicates that mhd_SHA256_deinit() function is present
- */
-# define mhd_SHA256_HAS_DEINIT 1
-
-/**
- * Free allocated resources.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_deinit (struct mhd_Sha256CtxExt *ctx);
-
-#endif /* MHD_SHA256_EXT_H */
diff --git a/src/mhd2/sha256_ext_gnutls.c b/src/mhd2/sha256_ext_gnutls.c
@@ -1,131 +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-2023 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/sha256_ext_gnutls.c
- * @brief Wrapper for SHA-256 calculation performed by GnuTLS library
- * @author Karlson2k (Evgeny Grin)
- */
-#include <gnutls/crypto.h>
-#define MHD_SHA256_Context struct hash_hd_st
-#include "sha256_ext.h"
-#include "mhd_assert.h"
-
-
-/**
- * Initialise structure for SHA-256 calculation, allocate resources.
- *
- * This function must not be called more than one time for @a ctx.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_init_one_time (struct mhd_Sha256CtxExt *ctx)
-{
- ctx->handle = NULL;
- ctx->ext_error = gnutls_hash_init (&ctx->handle,
- GNUTLS_DIG_SHA256);
- if ((0 != ctx->ext_error)
- && (NULL != ctx->handle))
- {
- /* GnuTLS may return initialisation error and set the handle at the
- same time. Such handle cannot be used for calculations.
- Note: GnuTLS may also return an error and NOT set the handle. */
- gnutls_free (ctx->handle);
- ctx->handle = NULL;
- }
-
- /* 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 size number of bytes in @a data, must not be 0
- * @param data bytes to add to hash
- */
-void
-mhd_SHA256_update (struct mhd_Sha256CtxExt *ctx,
- size_t size,
- const uint8_t *data)
-{
- mhd_assert (0 != size);
-
- if (0 == ctx->ext_error)
- ctx->ext_error = gnutls_hash (ctx->handle,
- data,
- size);
-}
-
-
-/**
- * Finalise SHA-256 calculation, return digest, reset hash calculation.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA256_DIGEST_SIZE bytes
- */
-void
-mhd_SHA256_finish_reset (struct mhd_Sha256CtxExt *ctx,
- uint8_t digest[mhd_SHA256_DIGEST_SIZE])
-{
- if (0 == ctx->ext_error)
- gnutls_hash_output (ctx->handle,
- digest);
-}
-
-
-/**
- * Free allocated resources.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_deinit (struct mhd_Sha256CtxExt *ctx)
-{
- if (NULL != ctx->handle)
- {
- gnutls_hash_deinit (ctx->handle,
- NULL);
- ctx->handle = NULL;
- }
-}
diff --git a/src/mhd2/sha256_ext_mbedtls.c b/src/mhd2/sha256_ext_mbedtls.c
@@ -1,142 +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/sha256_ext_mbedtls.c
- * @brief Wrapper for SHA-256 calculation performed by TLS library
- * @author Christian Grothoff
- */
-
-#include <mbedtls/sha256.h>
-#define MHD_SHA256_Context mbedtls_sha256_context
-#include "sha256_ext.h"
-#include "mhd_assert.h"
-
-
-/**
- * Initialise structure for SHA-256 calculation, allocate resources.
- *
- * This function must not be called more than one time for @a ctx.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_init_one_time (struct mhd_Sha256CtxExt *ctx)
-{
- ctx->ext_error = 0;
- ctx->handle = (mbedtls_sha256_context *)malloc (
- sizeof (mbedtls_sha256_context));
- if (NULL == ctx->handle)
- {
- ctx->ext_error = 1; /* Allocation failure */
- return;
- }
-
- mbedtls_sha256_init (ctx->handle);
- ctx->ext_error = mbedtls_sha256_starts_ret (ctx->handle,
- 0); /* 0 = SHA-256 */
- if (0 != ctx->ext_error)
- {
- mhd_SHA256_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 size number of bytes in @a data, must not be 0
- * @param data bytes to add to hash
- */
-void
-mhd_SHA256_update (struct mhd_Sha256CtxExt *ctx,
- size_t size,
- const uint8_t *data)
-{
- mhd_assert (0 != size);
-
- if (0 == ctx->ext_error)
- ctx->ext_error = mbedtls_sha256_update_ret (ctx->handle,
- data,
- size);
-}
-
-
-/**
- * Finalise SHA-256 calculation, return digest, reset hash calculation.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA256_DIGEST_SIZE bytes
- */
-void
-mhd_SHA256_finish_reset (struct mhd_Sha256CtxExt *ctx,
- uint8_t digest[mhd_SHA256_DIGEST_SIZE])
-{
- if (0 != ctx->ext_error)
- return;
- ctx->ext_error = mbedtls_sha256_finish_ret (ctx->handle,
- digest);
- if (0 != ctx->ext_error)
- return;
- /* Reset for potential reuse */
- ctx->ext_error = mbedtls_sha256_starts_ret (ctx->handle,
- 0 /* ! is224 */);
-}
-
-
-/**
- * Free allocated resources.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_deinit (struct mhd_Sha256CtxExt *ctx)
-{
- if (NULL != ctx->handle)
- {
- mbedtls_sha256_free (ctx->handle);
- free (ctx->handle);
- ctx->handle = NULL;
- }
-}
diff --git a/src/mhd2/sha256_ext_openssl.c b/src/mhd2/sha256_ext_openssl.c
@@ -1,155 +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/sha256_ext_openssl.c
- * @brief Wrapper for SHA-256 calculation performed by OpenSSL library
- * @author Christian Grothoff
- */
-
-#include <openssl/evp.h>
-#define MHD_SHA256_Context EVP_MD_CTX
-#include "sha256_ext.h"
-#include "mhd_assert.h"
-
-
-/**
- * Initialise structure for SHA-256 calculation, allocate resources.
- *
- * This function must not be called more than one time for @a ctx.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_init_one_time (struct mhd_Sha256CtxExt *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_sha256 (),
- NULL))
- {
- ctx->ext_error = 1; /* Initialization failure */
- mhd_SHA256_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 size number of bytes in @a data, must not be 0
- * @param data bytes to add to hash
- */
-void
-mhd_SHA256_update (struct mhd_Sha256CtxExt *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-256 calculation, return digest, reset hash calculation.
- *
- * @param ctx the calculation context
- * @param[out] digest set to the hash, must be #mhd_SHA256_DIGEST_SIZE bytes
- */
-void
-mhd_SHA256_finish_reset (struct mhd_Sha256CtxExt *ctx,
- uint8_t digest[mhd_SHA256_DIGEST_SIZE])
-{
- unsigned int len;
-
- if (0 != ctx->ext_error)
- return;
- if (1 != EVP_DigestFinal_ex (ctx->handle,
- digest,
- &len))
- {
- ctx->ext_error = 1;
- }
- else
- {
- mhd_assert (mhd_SHA256_DIGEST_SIZE == len);
- /* Reset for potential reuse */
- if (1 != EVP_DigestInit_ex (ctx->handle,
- EVP_sha256 (),
- NULL))
- {
- ctx->ext_error = 1;
- mhd_SHA256_deinit (ctx);
- }
- }
-}
-
-
-/**
- * Free allocated resources.
- *
- * @param ctx the calculation context
- */
-void
-mhd_SHA256_deinit (struct mhd_Sha256CtxExt *ctx)
-{
- if (NULL != ctx->handle)
- {
- EVP_MD_CTX_free (ctx->handle);
- ctx->handle = NULL;
- }
-}
diff --git a/src/mhd2/sha256_gnutls.c b/src/mhd2/sha256_gnutls.c
@@ -0,0 +1,113 @@
+/* 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/sha256_gnutls.c
+ * @brief Wrapper for SHA-256 calculation performed by GnuTLS backend
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "mhd_sys_options.h"
+
+#include <gnutls/crypto.h>
+#include "mhd_assert.h"
+
+#include "sha256_gnutls.h"
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1) void
+mhd_SHA256_gtls_init (struct mhd_Sha256CtxGtls *ctx)
+{
+ ctx->handle = NULL;
+ ctx->ext_error = gnutls_hash_init (&ctx->handle,
+ GNUTLS_DIG_SHA256);
+ if ((0 != ctx->ext_error) && (NULL != ctx->handle))
+ {
+ /* GnuTLS may return an initialisation error and set the handle at the
+ same time. Such a handle cannot be used for calculations.
+ Note: GnuTLS may also return an error and NOT set the handle. */
+ mhd_SHA256_gtls_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));
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_IN_SIZE_ (3, 2) void
+mhd_SHA256_gtls_update (struct mhd_Sha256CtxGtls *restrict ctx,
+ size_t size,
+ const void *restrict data)
+{
+#ifndef MHD_UNIT_TESTING
+ mhd_assert (0 != size);
+#endif
+
+ if (0 == ctx->ext_error)
+ ctx->ext_error = gnutls_hash (ctx->handle,
+ data,
+ size);
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_OUT_ (2) void
+mhd_SHA256_gtls_finish (
+ struct mhd_Sha256CtxGtls *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA256_DIGEST_SIZE)])
+{
+ if (0 == ctx->ext_error)
+ gnutls_hash_output (ctx->handle,
+ digest);
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
+MHD_FN_PAR_INOUT_ (1) void
+mhd_SHA256_gtls_deinit (struct mhd_Sha256CtxGtls *ctx)
+{
+ if (NULL != ctx->handle)
+ {
+ gnutls_hash_deinit (ctx->handle,
+ NULL);
+ ctx->handle = NULL;
+ }
+}
diff --git a/src/mhd2/sha256_gnutls.h b/src/mhd2/sha256_gnutls.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/sha256_gnutls.h
+ * @brief Wrapper declarations for SHA-256 calculation performed by
+ * GnuTLS backend
+ * @author Karlson2k (Evgeny Grin)
+ */
+#ifndef MHD_SHA256_GNUTLS_H
+#define MHD_SHA256_GNUTLS_H 1
+
+#include "mhd_sys_options.h"
+
+#include "sys_base_types.h"
+
+#ifndef mhd_SHA256_DIGEST_SIZE
+/**
+ * Size of SHA-256 resulting digest in bytes
+ * This is the final digest size, not the intermediate hash.
+ */
+# define mhd_SHA256_DIGEST_SIZE (32)
+#endif
+
+/* Forward declaration for GnuTLS struct, to avoid including large header */
+struct hash_hd_st;
+
+/**
+ * SHA-256 calculation context
+ */
+struct mhd_Sha256CtxGtls
+{
+ struct hash_hd_st *handle; /**< Hash calculation handle */
+ int ext_error; /**< Error number reported by the hashing backend (zero if no error) */
+};
+
+/**
+ * Indicates whether struct mhd_Sha256CtxGtls has an 'ext_error' member.
+ *
+ * Set to '1' when the structure has an 'ext_error' member.
+ */
+#define mhd_SHA256_GTLS_EXT_ERROR_FLAG 1
+
+/**
+ * Initialise the context for SHA-256 calculation.
+ *
+ * This function must not be called more than once for @a ctx without an
+ * intervening #mhd_SHA256_gtls_deinit().
+ *
+ * Whether or not an error is reported, #mhd_SHA256_gtls_deinit() must be
+ * called for @a ctx once this function has returned.
+ *
+ * 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_SHA256_gtls_init (struct mhd_Sha256CtxGtls *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1);
+
+/**
+ * Add a portion of data to the SHA-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_SHA256_gtls_update (struct mhd_Sha256CtxGtls *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-256 calculation and return the digest.
+ *
+ * If @a ctx already has a recorded error, this function does nothing.
+ *
+ * The GnuTLS backend resets the underlying hash handle during this operation.
+ * If the context is reused, the caller must still invoke
+ * #mhd_SHA256_gtls_reset() afterwards to follow the common SHA-256 context
+ * lifecycle; that reset operation is a no-op.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #mhd_SHA256_DIGEST_SIZE bytes
+ */
+MHD_INTERNAL void
+mhd_SHA256_gtls_finish (
+ struct mhd_Sha256CtxGtls *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA256_DIGEST_SIZE)])
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_OUT_ (2);
+
+/**
+ * Reset the context for a new SHA-256 calculation.
+ *
+ * This function may be called only after #mhd_SHA256_gtls_finish(). If the
+ * context is subsequently reused for a new calculation, this function must be
+ * called before starting that calculation.
+ *
+ * This operation is a no-op; the recorded error state in @a ctx is preserved.
+ *
+ * @param ctx the calculation context
+ */
+#define mhd_SHA256_gtls_reset(ctx) ((void) (ctx))
+
+/**
+ * Deinitialise the SHA-256 calculation context.
+ *
+ * After calling this function, @a ctx can be reinitialised with
+ * #mhd_SHA256_gtls_init().
+ *
+ * The recorded error state in @a ctx is preserved.
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA256_gtls_deinit (struct mhd_Sha256CtxGtls *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
+
+/**
+ * Indicates whether #mhd_SHA256_gtls_deinit() is a real function or a no-op.
+ *
+ * Set to '0' as #mhd_SHA256_gtls_deinit() is a real function.
+ */
+#define mhd_SHA256_GTLS_DEINIT_NOOP_FLAG 0
+
+#endif /* MHD_SHA256_GNUTLS_H */
diff --git a/src/mhd2/sha256_int.c b/src/mhd2/sha256_int.c
@@ -1,569 +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) 2019-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/sha256.c
- * @brief Calculation of SHA-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 "sha256_int.h"
-
-MHD_INTERNAL void MHD_FN_PAR_NONNULL_ALL_
-mhd_SHA256_init (struct mhd_Sha256CtxInt *ctx)
-{
- /* Initial hash values, see FIPS PUB 180-4 paragraph 5.3.3 */
- /* First thirty-two bits of the fractional parts of the square
- * roots of the first eight prime numbers: 2, 3, 5, 7, 11, 13,
- * 17, 19." */
- ctx->H[0] = UINT32_C (0x6a09e667);
- ctx->H[1] = UINT32_C (0xbb67ae85);
- ctx->H[2] = UINT32_C (0x3c6ef372);
- ctx->H[3] = UINT32_C (0xa54ff53a);
- ctx->H[4] = UINT32_C (0x510e527f);
- ctx->H[5] = UINT32_C (0x9b05688c);
- ctx->H[6] = UINT32_C (0x1f83d9ab);
- ctx->H[7] = UINT32_C (0x5be0cd19);
-
- /* Initialise number of bytes. */
- ctx->count = 0;
-}
-
-
-mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE
-
-static MHD_FN_PAR_NONNULL_ALL_ void
-sha256_transform (uint32_t H[mhd_SHA256_DIGEST_SIZE_WORDS],
- const void *restrict data)
-{
- /* Working variables,
- see FIPS PUB 180-4 paragraph 6.2. */
- uint32_t a = H[0];
- uint32_t b = H[1];
- uint32_t c = H[2];
- uint32_t d = H[3];
- uint32_t e = H[4];
- uint32_t f = H[5];
- uint32_t g = H[6];
- uint32_t h = H[7];
-
- /* Data buffer, used as cyclic buffer.
- See FIPS PUB 180-4 paragraphs 5.2.1, 6.2. */
- uint32_t W[16];
-
-#ifndef mhd_GET_32BIT_BE_UNALIGNED
- if (0 != (((uintptr_t)data) % mhd_UINT32_ALIGN))
- {
- /* Copy the unaligned input data to the aligned buffer */
- memcpy (W, data, mhd_SHA256_BLOCK_SIZE);
- /* The W[] buffer itself will be used as the source of the data,
- * but data will be reloaded in correct bytes order during
- * the next steps */
- data = (const void *)W;
- }
-#endif /* mhd_GET_32BIT_BE_UNALIGNED */
-
- /* 'Ch' and 'Maj' macro functions are defined with
- widely-used optimization.
- See FIPS PUB 180-4 formulae 4.2, 4.3. */
-#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.4, 4.5, 4.6, 4.7. */
-#define SIG0(x) (mhd_ROTR32 ((x), 2) ^ mhd_ROTR32 ((x), 13) ^ \
- mhd_ROTR32 ((x), 22) )
-#define SIG1(x) (mhd_ROTR32 ((x), 6) ^ mhd_ROTR32 ((x), 11) ^ \
- mhd_ROTR32 ((x), 25) )
-#define sig0(x) (mhd_ROTR32 ((x), 7) ^ mhd_ROTR32 ((x), 18) ^ \
- ((x) >> 3) )
-#define sig1(x) (mhd_ROTR32 ((x), 17) ^ mhd_ROTR32 ((x),19) ^ \
- ((x) >> 10) )
-
- /* One step of SHA-256 computation,
- see FIPS PUB 180-4 paragraph 6.2.2 step 3.
- * Note: this macro updates working variables in-place, without rotation.
- * Note: first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in FIPS PUB 180-4 paragraph 6.2.2 step 3.
- second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in FIPS PUB 180-4 paragraph 6.2.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 SHA2STEP32(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,
- See FIPS PUB 180-4 paragraph 6.2.
- Input data must be read in big-endian bytes order,
- see FIPS PUB 180-4 paragraph 3.1.2. */
- /* Use cast to (const void*) to mute compiler alignment warning,
- * data was already aligned in previous step */
-#define GET_W_FROM_DATA(buf, t) \
- mhd_GET_32BIT_BE ((const void*) (((const uint8_t*) (buf)) + \
- (t) * mhd_SHA256_BYTES_IN_WORD))
-
- /* 'W' generation and assignment for 16 <= t <= 63.
- See FIPS PUB 180-4 paragraph 6.2.2.
- As only last 16 'W' are used in calculations, it is possible to
- use 16 elements array of W as cyclic buffer.
- * Note: ((t-16)&0xf) have same value as (t&0xf) */
-#define Wgen(w, t) ( (w)[(t - 16) & 0xf] + sig1 ((w)[((t) - 2) & 0xf]) \
- + (w)[((t) - 7) & 0xf] + sig0 ((w)[((t) - 15) & 0xf]) )
-
-#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 paragraph 4.2.2 for
- K values. */
- /* Note: instead of reassigning all working variables on each step,
- variables are rotated for each step:
- SHA2STEP32(a, b, c, d, e, f, g, h, K[0], data[0]);
- SHA2STEP32(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. */
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x428a2f98), W[0]);
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x71374491), W[1]);
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0xb5c0fbcf), W[2]);
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0xe9b5dba5), W[3]);
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x3956c25b), W[4]);
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x59f111f1), W[5]);
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x923f82a4), W[6]);
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xab1c5ed5), W[7]);
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0xd807aa98), W[8]);
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x12835b01), W[9]);
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x243185be), W[10]);
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x550c7dc3), W[11]);
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x72be5d74), W[12]);
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x80deb1fe), W[13]);
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x9bdc06a7), W[14]);
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc19bf174), 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 input data buffer as big-endian value and
- stored in array of W elements. */
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x428a2f98), W[0] = \
- GET_W_FROM_DATA (data, 0));
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x71374491), W[1] = \
- GET_W_FROM_DATA (data, 1));
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0xb5c0fbcf), W[2] = \
- GET_W_FROM_DATA (data, 2));
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0xe9b5dba5), W[3] = \
- GET_W_FROM_DATA (data, 3));
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x3956c25b), W[4] = \
- GET_W_FROM_DATA (data, 4));
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x59f111f1), W[5] = \
- GET_W_FROM_DATA (data, 5));
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x923f82a4), W[6] = \
- GET_W_FROM_DATA (data, 6));
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xab1c5ed5), W[7] = \
- GET_W_FROM_DATA (data, 7));
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0xd807aa98), W[8] = \
- GET_W_FROM_DATA (data, 8));
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x12835b01), W[9] = \
- GET_W_FROM_DATA (data, 9));
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x243185be), W[10] = \
- GET_W_FROM_DATA (data, 10));
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x550c7dc3), W[11] = \
- GET_W_FROM_DATA (data, 11));
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x72be5d74), W[12] = \
- GET_W_FROM_DATA (data, 12));
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x80deb1fe), W[13] = \
- GET_W_FROM_DATA (data, 13));
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x9bdc06a7), W[14] = \
- GET_W_FROM_DATA (data, 14));
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc19bf174), W[15] = \
- GET_W_FROM_DATA (data, 15));
- }
-
- /* During last 48 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 paragraph 4.2.2 for K values. */
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0xe49b69c1), W[16 & 0xf] = \
- Wgen (W, 16));
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0xefbe4786), W[17 & 0xf] = \
- Wgen (W, 17));
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x0fc19dc6), W[18 & 0xf] = \
- Wgen (W, 18));
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x240ca1cc), W[19 & 0xf] = \
- Wgen (W, 19));
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x2de92c6f), W[20 & 0xf] = \
- Wgen (W, 20));
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x4a7484aa), W[21 & 0xf] = \
- Wgen (W, 21));
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x5cb0a9dc), W[22 & 0xf] = \
- Wgen (W, 22));
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x76f988da), W[23 & 0xf] = \
- Wgen (W, 23));
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x983e5152), W[24 & 0xf] = \
- Wgen (W, 24));
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0xa831c66d), W[25 & 0xf] = \
- Wgen (W, 25));
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0xb00327c8), W[26 & 0xf] = \
- Wgen (W, 26));
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0xbf597fc7), W[27 & 0xf] = \
- Wgen (W, 27));
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0xc6e00bf3), W[28 & 0xf] = \
- Wgen (W, 28));
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0xd5a79147), W[29 & 0xf] = \
- Wgen (W, 29));
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x06ca6351), W[30 & 0xf] = \
- Wgen (W, 30));
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x14292967), W[31 & 0xf] = \
- Wgen (W, 31));
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x27b70a85), W[32 & 0xf] = \
- Wgen (W, 32));
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x2e1b2138), W[33 & 0xf] = \
- Wgen (W, 33));
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x4d2c6dfc), W[34 & 0xf] = \
- Wgen (W, 34));
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x53380d13), W[35 & 0xf] = \
- Wgen (W, 35));
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x650a7354), W[36 & 0xf] = \
- Wgen (W, 36));
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x766a0abb), W[37 & 0xf] = \
- Wgen (W, 37));
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x81c2c92e), W[38 & 0xf] = \
- Wgen (W, 38));
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x92722c85), W[39 & 0xf] = \
- Wgen (W, 39));
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0xa2bfe8a1), W[40 & 0xf] = \
- Wgen (W, 40));
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0xa81a664b), W[41 & 0xf] = \
- Wgen (W, 41));
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0xc24b8b70), W[42 & 0xf] = \
- Wgen (W, 42));
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0xc76c51a3), W[43 & 0xf] = \
- Wgen (W, 43));
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0xd192e819), W[44 & 0xf] = \
- Wgen (W, 44));
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0xd6990624), W[45 & 0xf] = \
- Wgen (W, 45));
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0xf40e3585), W[46 & 0xf] = \
- Wgen (W, 46));
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x106aa070), W[47 & 0xf] = \
- Wgen (W, 47));
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x19a4c116), W[48 & 0xf] = \
- Wgen (W, 48));
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x1e376c08), W[49 & 0xf] = \
- Wgen (W, 49));
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x2748774c), W[50 & 0xf] = \
- Wgen (W, 50));
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x34b0bcb5), W[51 & 0xf] = \
- Wgen (W, 51));
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x391c0cb3), W[52 & 0xf] = \
- Wgen (W, 52));
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0x4ed8aa4a), W[53 & 0xf] = \
- Wgen (W, 53));
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0x5b9cca4f), W[54 & 0xf] = \
- Wgen (W, 54));
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0x682e6ff3), W[55 & 0xf] = \
- Wgen (W, 55));
- SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x748f82ee), W[56 & 0xf] = \
- Wgen (W, 56));
- SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x78a5636f), W[57 & 0xf] = \
- Wgen (W, 57));
- SHA2STEP32 (g, h, a, b, c, d, e, f, UINT32_C (0x84c87814), W[58 & 0xf] = \
- Wgen (W, 58));
- SHA2STEP32 (f, g, h, a, b, c, d, e, UINT32_C (0x8cc70208), W[59 & 0xf] = \
- Wgen (W, 59));
- SHA2STEP32 (e, f, g, h, a, b, c, d, UINT32_C (0x90befffa), W[60 & 0xf] = \
- Wgen (W, 60));
- SHA2STEP32 (d, e, f, g, h, a, b, c, UINT32_C (0xa4506ceb), W[61 & 0xf] = \
- Wgen (W, 61));
- SHA2STEP32 (c, d, e, f, g, h, a, b, UINT32_C (0xbef9a3f7), W[62 & 0xf] = \
- Wgen (W, 62));
- SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc67178f2), W[63 & 0xf] = \
- Wgen (W, 63));
-#else /* ! MHD_FAVOR_SMALL_CODE */
- if (1)
- {
- unsigned int t;
- /* K constants array.
- See FIPS PUB 180-4 paragraph 4.2.2 for K values. */
- static const uint32_t K[80] =
- { UINT32_C (0x428a2f98), UINT32_C (0x71374491), UINT32_C (0xb5c0fbcf),
- UINT32_C (0xe9b5dba5), UINT32_C (0x3956c25b), UINT32_C (0x59f111f1),
- UINT32_C (0x923f82a4), UINT32_C (0xab1c5ed5), UINT32_C (0xd807aa98),
- UINT32_C (0x12835b01), UINT32_C (0x243185be), UINT32_C (0x550c7dc3),
- UINT32_C (0x72be5d74), UINT32_C (0x80deb1fe), UINT32_C (0x9bdc06a7),
- UINT32_C (0xc19bf174), UINT32_C (0xe49b69c1), UINT32_C (0xefbe4786),
- UINT32_C (0x0fc19dc6), UINT32_C (0x240ca1cc), UINT32_C (0x2de92c6f),
- UINT32_C (0x4a7484aa), UINT32_C (0x5cb0a9dc), UINT32_C (0x76f988da),
- UINT32_C (0x983e5152), UINT32_C (0xa831c66d), UINT32_C (0xb00327c8),
- UINT32_C (0xbf597fc7), UINT32_C (0xc6e00bf3), UINT32_C (0xd5a79147),
- UINT32_C (0x06ca6351), UINT32_C (0x14292967), UINT32_C (0x27b70a85),
- UINT32_C (0x2e1b2138), UINT32_C (0x4d2c6dfc), UINT32_C (0x53380d13),
- UINT32_C (0x650a7354), UINT32_C (0x766a0abb), UINT32_C (0x81c2c92e),
- UINT32_C (0x92722c85), UINT32_C (0xa2bfe8a1), UINT32_C (0xa81a664b),
- UINT32_C (0xc24b8b70), UINT32_C (0xc76c51a3), UINT32_C (0xd192e819),
- UINT32_C (0xd6990624), UINT32_C (0xf40e3585), UINT32_C (0x106aa070),
- UINT32_C (0x19a4c116), UINT32_C (0x1e376c08), UINT32_C (0x2748774c),
- UINT32_C (0x34b0bcb5), UINT32_C (0x391c0cb3), UINT32_C (0x4ed8aa4a),
- UINT32_C (0x5b9cca4f), UINT32_C (0x682e6ff3), UINT32_C (0x748f82ee),
- UINT32_C (0x78a5636f), UINT32_C (0x84c87814), UINT32_C (0x8cc70208),
- UINT32_C (0x90befffa), UINT32_C (0xa4506ceb), UINT32_C (0xbef9a3f7),
- UINT32_C (0xc67178f2) };
- /* One step of SHA-256 computation with working variables rotation,
- see FIPS PUB 180-4 paragraph 6.2.2 step 3.
- * Note: this version of macro reassign all working variable on
- each step. */
-# define SHA2STEP32RV(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) do { \
- uint32_t tmp_h_ = (vH); \
- SHA2STEP32 ((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 input data buffer as big-endian value and
- stored in array of W elements. */
- for (t = 0; t < 16; ++t)
- {
- SHA2STEP32RV (a, b, c, d, e, f, g, h, K[t], \
- W[t] = GET_W_FROM_DATA (data, t));
- }
-
- /* During last 48 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 < 64; ++t)
- {
- SHA2STEP32RV (a, b, c, d, e, f, g, h, K[t], W[t & 15] = Wgen (W, t));
- }
- }
-#endif /* ! MHD_FAVOR_SMALL_CODE */
-
- /* Compute intermediate hash.
- See FIPS PUB 180-4 paragraph 6.2.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_SHA256_update (struct mhd_Sha256CtxInt *restrict ctx,
- size_t size,
- const uint8_t *restrict data)
-{
- unsigned bytes_have; /**< Number of bytes in buffer */
-
- mhd_assert (0 != size);
-
- /* Note: (count & (mhd_SHA256_BLOCK_SIZE-1))
- equals (count % mhd_SHA256_BLOCK_SIZE) for this block size. */
- bytes_have = (unsigned)(ctx->count & (mhd_SHA256_BLOCK_SIZE - 1));
- ctx->count += size;
-
- if (0 != bytes_have)
- {
- unsigned bytes_left = mhd_SHA256_BLOCK_SIZE - bytes_have;
- if (size >= bytes_left)
- { /* Combine new data with data in the buffer and
- process full block. */
- memcpy (((uint8_t *)ctx->buffer) + bytes_have,
- data,
- bytes_left);
- data += bytes_left;
- size -= bytes_left;
- sha256_transform (ctx->H, ctx->buffer);
- bytes_have = 0;
- }
- }
-
- while (mhd_SHA256_BLOCK_SIZE <= size)
- { /* Process any full blocks of new data directly,
- without copying to the buffer. */
- sha256_transform (ctx->H, data);
- data += mhd_SHA256_BLOCK_SIZE;
- size -= mhd_SHA256_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" padding addition in bytes.
- * See FIPS PUB 180-4 paragraph 5.1.1.
- */
-#define SHA256_SIZE_OF_LEN_ADD (64 / 8)
-
-MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
-mhd_SHA256_finish (struct mhd_Sha256CtxInt *restrict ctx,
- uint8_t digest[mhd_SHA256_DIGEST_SIZE])
-{
- uint64_t num_bits; /**< Number of processed bits */
- unsigned bytes_have; /**< Number of bytes in buffer */
-
- num_bits = ctx->count << 3;
- /* Note: (count & (mhd_SHA256_BLOCK_SIZE-1))
- equal (count % mhd_SHA256_BLOCK_SIZE) for this block size. */
- bytes_have = (unsigned)(ctx->count & (mhd_SHA256_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 paragraph 5.1.1. */
-
- /* Data is always processed in form of bytes (not by individual bits),
- therefore position of first padding bit in byte is always
- predefined (0x80). */
- /* Buffer always have space at least for one byte (as full buffers are
- processed immediately). */
- ((uint8_t *)ctx->buffer)[bytes_have++] = 0x80;
-
- if (mhd_SHA256_BLOCK_SIZE - bytes_have < SHA256_SIZE_OF_LEN_ADD)
- { /* No space in current block to put total length of message.
- Pad current block with zeros and process it. */
- if (bytes_have < mhd_SHA256_BLOCK_SIZE)
- memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
- mhd_SHA256_BLOCK_SIZE - bytes_have);
- /* Process full block. */
- sha256_transform (ctx->H, ctx->buffer);
- /* Start new block. */
- bytes_have = 0;
- }
-
- /* Pad the rest of the buffer with zeros. */
- memset (((uint8_t *)ctx->buffer) + bytes_have, 0,
- mhd_SHA256_BLOCK_SIZE - SHA256_SIZE_OF_LEN_ADD - bytes_have);
- /* Put the number of bits in processed message as big-endian value. */
- mhd_PUT_64BIT_BE_UNALIGN (ctx->buffer + mhd_SHA256_BLOCK_SIZE_WORDS - 2,
- num_bits);
- /* Process full final block. */
- sha256_transform (ctx->H, ctx->buffer);
-
- /* Put final hash/digest in BE mode */
- if (1)
- {
- bool use_tmp_buf_to_align_result;
-
-#if defined(mhd_PUT_32BIT_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_UINT32_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. */
- uint32_t alig_dgst[mhd_SHA256_DIGEST_SIZE_WORDS];
- mhd_PUT_32BIT_BE (alig_dgst + 0, ctx->H[0]);
- mhd_PUT_32BIT_BE (alig_dgst + 1, ctx->H[1]);
- mhd_PUT_32BIT_BE (alig_dgst + 2, ctx->H[2]);
- mhd_PUT_32BIT_BE (alig_dgst + 3, ctx->H[3]);
- mhd_PUT_32BIT_BE (alig_dgst + 4, ctx->H[4]);
- mhd_PUT_32BIT_BE (alig_dgst + 5, ctx->H[5]);
- mhd_PUT_32BIT_BE (alig_dgst + 6, ctx->H[6]);
- mhd_PUT_32BIT_BE (alig_dgst + 7, ctx->H[7]);
- /* Copy result to unaligned destination address */
- memcpy (digest, alig_dgst, mhd_SHA256_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_32BIT_BE ((void *)(digest + 0 * mhd_SHA256_BYTES_IN_WORD), \
- ctx->H[0]);
- mhd_PUT_32BIT_BE ((void *)(digest + 1 * mhd_SHA256_BYTES_IN_WORD), \
- ctx->H[1]);
- mhd_PUT_32BIT_BE ((void *)(digest + 2 * mhd_SHA256_BYTES_IN_WORD), \
- ctx->H[2]);
- mhd_PUT_32BIT_BE ((void *)(digest + 3 * mhd_SHA256_BYTES_IN_WORD), \
- ctx->H[3]);
- mhd_PUT_32BIT_BE ((void *)(digest + 4 * mhd_SHA256_BYTES_IN_WORD), \
- ctx->H[4]);
- mhd_PUT_32BIT_BE ((void *)(digest + 5 * mhd_SHA256_BYTES_IN_WORD), \
- ctx->H[5]);
- mhd_PUT_32BIT_BE ((void *)(digest + 6 * mhd_SHA256_BYTES_IN_WORD), \
- ctx->H[6]);
- mhd_PUT_32BIT_BE ((void *)(digest + 7 * mhd_SHA256_BYTES_IN_WORD), \
- ctx->H[7]);
- }
- }
-
- /* Erase potentially sensitive data. */
- memset (ctx, 0, sizeof(struct mhd_Sha256CtxInt));
-}
-
-
-mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE
diff --git a/src/mhd2/sha256_int.h b/src/mhd2/sha256_int.h
@@ -1,139 +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) 2019-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/sha256.h
- * @brief Calculation of SHA-256 digest
- * @author Karlson2k (Evgeny Grin)
- */
-
-#ifndef MHD_SHA256_INT_H
-#define MHD_SHA256_INT_H 1
-
-#include "mhd_sys_options.h"
-
-#include "sys_base_types.h"
-
-
-/**
- * Digest is kept internally as 8 32-bit words.
- */
-#define mhd_SHA256_DIGEST_SIZE_WORDS 8
-
-/**
- * Number of bits in single SHA-256 word
- */
-#define mhd_SHA256_WORD_SIZE_BITS 32
-
-/**
- * Number of bytes in single SHA-256 word
- * used to process data
- */
-#define mhd_SHA256_BYTES_IN_WORD (mhd_SHA256_WORD_SIZE_BITS / 8)
-
-/**
- * Size of SHA-256 digest in bytes
- */
-#define mhd_SHA256_DIGEST_SIZE \
- (mhd_SHA256_DIGEST_SIZE_WORDS * mhd_SHA256_BYTES_IN_WORD)
-
-/**
- * Size of single processing block in bits
- */
-#define mhd_SHA256_BLOCK_SIZE_BITS 512
-
-/**
- * Size of single processing block in bytes
- */
-#define mhd_SHA256_BLOCK_SIZE (mhd_SHA256_BLOCK_SIZE_BITS / 8)
-
-/**
- * Size of single processing block in bytes
- */
-#define mhd_SHA256_BLOCK_SIZE_WORDS \
- (mhd_SHA256_BLOCK_SIZE_BITS / mhd_SHA256_WORD_SIZE_BITS)
-
-
-struct mhd_Sha256CtxInt
-{
- uint32_t H[mhd_SHA256_DIGEST_SIZE_WORDS]; /**< Intermediate hash value / digest at end of calculation */
- uint32_t buffer[mhd_SHA256_BLOCK_SIZE_WORDS]; /**< SHA256 input data buffer */
- uint64_t count; /**< number of bytes, mod 2^64 */
-};
-
-/**
- * Initialise structure for SHA-256 calculation.
- *
- * @param ctx must be a `struct mhd_Sha256CtxInt *`
- */
-MHD_INTERNAL void
-mhd_SHA256_init (struct mhd_Sha256CtxInt *ctx)
-MHD_FN_PAR_NONNULL_ALL_;
-
-
-/**
- * Process portion of bytes.
- *
- * @param ctx must be a `struct mhd_Sha256CtxInt *`
- * @param size number of bytes in @a data
- * @param data bytes to add to hash
- */
-MHD_INTERNAL void
-mhd_SHA256_update (struct mhd_Sha256CtxInt *restrict ctx,
- size_t size,
- const uint8_t *restrict data)
-MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (3, 2);
-
-
-/**
- * Finalise SHA256 calculation, return digest.
- *
- * @param ctx must be a `struct mhd_Sha256CtxInt *`
- * @param[out] digest set to the hash, must be #mhd_SHA256_DIGEST_SIZE bytes
- */
-MHD_INTERNAL void
-mhd_SHA256_finish (struct mhd_Sha256CtxInt *restrict ctx,
- uint8_t digest[mhd_SHA256_DIGEST_SIZE])
-MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (2);
-
-/**
- * Indicates that function mhd_SHA256_finish() (without context reset) is available
- */
-#define mhd_SHA256_HAS_FINISH 1
-
-#endif /* MHD_SHA256_INT_H */
diff --git a/src/mhd2/sha256_mbedtls.c b/src/mhd2/sha256_mbedtls.c
@@ -0,0 +1,113 @@
+/* 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/sha256_mbedtls.c
+ * @brief Wrapper for SHA-256 calculation performed by mbedTLS library
+ * @author Karlson2k (Evgeny Grin)
+ * @author Christian Grothoff
+ */
+
+#include "mhd_sys_options.h"
+
+#include "mhd_assert.h"
+
+#include "sha256_mbedtls.h"
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1) void
+mhd_SHA256_mtls_init (struct mhd_Sha256CtxMtls *ctx)
+{
+ mbedtls_sha256_init (&(ctx->mbed_ctx));
+ /* The second argument must be zero to calculate SHA-256 (not SHA-224) */
+ ctx->ext_error = (0 != mbedtls_sha256_starts (&(ctx->mbed_ctx),
+ 0));
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) void
+mhd_SHA256_mtls_reset (struct mhd_Sha256CtxMtls *ctx)
+{
+ if (ctx->ext_error)
+ return;
+
+ /* The second argument must be zero to calculate SHA-256 (not SHA-224) */
+ ctx->ext_error = (0 != mbedtls_sha256_starts (&(ctx->mbed_ctx),
+ 0));
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_IN_SIZE_ (3, 2) void
+mhd_SHA256_mtls_update (struct mhd_Sha256CtxMtls *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_sha256_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_SHA256_mtls_finish (
+ struct mhd_Sha256CtxMtls *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA256_DIGEST_SIZE)])
+{
+ if (ctx->ext_error)
+ return;
+
+ ctx->ext_error = (0 != mbedtls_sha256_finish (&(ctx->mbed_ctx),
+ (unsigned char *)digest));
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) void
+mhd_SHA256_mtls_deinit (struct mhd_Sha256CtxMtls *ctx)
+{
+ mbedtls_sha256_free (&(ctx->mbed_ctx));
+}
diff --git a/src/mhd2/sha256_mbedtls.h b/src/mhd2/sha256_mbedtls.h
@@ -0,0 +1,168 @@
+/* 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/sha256_mbedtls.h
+ * @brief Wrapper declarations for SHA-256 calculation performed by
+ * mbedTLS backend
+ * @author Karlson2k (Evgeny Grin)
+ */
+#ifndef MHD_SHA256_MBEDTLS_H
+#define MHD_SHA256_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/sha256.h>
+
+#ifndef mhd_SHA256_DIGEST_SIZE
+/**
+ * Size of SHA-256 resulting digest in bytes
+ * This is the final digest size, not the intermediate hash.
+ */
+# define mhd_SHA256_DIGEST_SIZE (32)
+#endif
+
+/**
+ * SHA-256 calculation context
+ */
+struct mhd_Sha256CtxMtls
+{
+ struct mbedtls_sha256_context mbed_ctx; /**< Hash calculation handle */
+ bool ext_error; /**< 'true' if the hashing backend has reported an error */
+};
+
+/**
+ * Indicates whether struct mhd_Sha256CtxMtls has an 'ext_error' member.
+ *
+ * Set to '1' when the structure has an 'ext_error' member.
+ */
+#define mhd_SHA256_MTLS_EXT_ERROR_FLAG 1
+
+/**
+ * Initialise the context for SHA-256 calculation.
+ *
+ * This function must not be called more than once for @a ctx without an
+ * intervening #mhd_SHA256_mtls_deinit().
+ *
+ * Whether or not an error is reported, #mhd_SHA256_mtls_deinit() must be
+ * called for @a ctx once this function has returned.
+ *
+ * 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_SHA256_mtls_init (struct mhd_Sha256CtxMtls *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1);
+
+
+/**
+ * Add a portion of data to the SHA-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_SHA256_mtls_update (struct mhd_Sha256CtxMtls *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-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_SHA256_DIGEST_SIZE bytes
+ */
+MHD_INTERNAL void
+mhd_SHA256_mtls_finish (
+ struct mhd_Sha256CtxMtls *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA256_DIGEST_SIZE)])
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_OUT_ (2);
+
+/**
+ * Reset the context for a new SHA-256 calculation.
+ *
+ * This function may be called only after #mhd_SHA256_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_SHA256_mtls_reset (struct mhd_Sha256CtxMtls *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
+
+/**
+ * Deinitialise the SHA-256 calculation context.
+ *
+ * After calling this function, @a ctx can be reinitialised with
+ * #mhd_SHA256_mtls_init().
+ *
+ * The recorded error state in @a ctx is preserved.
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA256_mtls_deinit (struct mhd_Sha256CtxMtls *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
+
+/**
+ * Indicates whether #mhd_SHA256_mtls_deinit() is a real function or a no-op.
+ *
+ * Set to '0' as #mhd_SHA256_mtls_deinit() is a real function.
+ */
+#define mhd_SHA256_MTLS_DEINIT_NOOP_FLAG 0
+
+
+#endif /* MHD_SHA256_MBEDTLS_H */
diff --git a/src/mhd2/sha256_openssl.c b/src/mhd2/sha256_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/sha256_openssl.c
+ * @brief Wrapper for SHA-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 "sha256_openssl.h"
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1) void
+mhd_SHA256_ossl_init (struct mhd_Sha256CtxOssl *ctx)
+{
+ ctx->ossl_ctx = EVP_MD_CTX_new ();
+ ctx->ext_error = (NULL == ctx->ossl_ctx);
+
+ mhd_SHA256_ossl_reset (ctx);
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) void
+mhd_SHA256_ossl_reset (struct mhd_Sha256CtxOssl *ctx)
+{
+ if (ctx->ext_error)
+ return;
+
+ mhd_assert (NULL != ctx->ossl_ctx);
+
+ ctx->ext_error = (0 == EVP_DigestInit_ex (ctx->ossl_ctx,
+ EVP_sha256 (),
+ NULL));
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1)
+MHD_FN_PAR_IN_SIZE_ (3, 2) void
+mhd_SHA256_ossl_update (struct mhd_Sha256CtxOssl *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_SHA256_ossl_finish (
+ struct mhd_Sha256CtxOssl *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA256_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_SHA256_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_SHA256_ossl_deinit (struct mhd_Sha256CtxOssl *ctx)
+{
+ EVP_MD_CTX_free (ctx->ossl_ctx);
+ ctx->ossl_ctx = NULL;
+}
diff --git a/src/mhd2/sha256_openssl.h b/src/mhd2/sha256_openssl.h
@@ -0,0 +1,167 @@
+/* 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/sha256_openssl.h
+ * @brief Wrapper declarations for SHA-256 calculation performed by
+ * OpenSSL backend
+ * @author Karlson2k (Evgeny Grin)
+ */
+#ifndef MHD_SHA256_OPENSSL_H
+#define MHD_SHA256_OPENSSL_H 1
+
+#include "mhd_sys_options.h"
+
+#include "sys_bool_type.h"
+#include "sys_base_types.h"
+
+#ifndef mhd_SHA256_DIGEST_SIZE
+/**
+ * Size of SHA-256 resulting digest in bytes
+ * This is the final digest size, not the intermediate hash.
+ */
+# define mhd_SHA256_DIGEST_SIZE (32)
+#endif
+
+/* Forward declaration for OpenSSL struct, to avoid including large header */
+struct evp_md_ctx_st;
+
+/**
+ * SHA-256 calculation context
+ */
+struct mhd_Sha256CtxOssl
+{
+ 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_Sha256CtxOssl has an 'ext_error' member.
+ *
+ * Set to '1' when the structure has an 'ext_error' member.
+ */
+#define mhd_SHA256_OSSL_EXT_ERROR_FLAG 1
+
+/**
+ * Initialise the context for SHA-256 calculation.
+ *
+ * This function must not be called more than once for @a ctx without an
+ * intervening #mhd_SHA256_ossl_deinit().
+ *
+ * Whether or not an error is reported, #mhd_SHA256_ossl_deinit() must be
+ * called for @a ctx once this function has returned.
+ *
+ * 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_SHA256_ossl_init (struct mhd_Sha256CtxOssl *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (1);
+
+/**
+ * Add a portion of data to the SHA-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_SHA256_ossl_update (struct mhd_Sha256CtxOssl *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-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_SHA256_DIGEST_SIZE bytes
+ */
+MHD_INTERNAL void
+mhd_SHA256_ossl_finish (
+ struct mhd_Sha256CtxOssl *restrict ctx,
+ uint8_t digest[MHD_FN_PAR_FIX_ARR_SIZE_ (mhd_SHA256_DIGEST_SIZE)])
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_OUT_ (2);
+
+/**
+ * Reset the context for a new SHA-256 calculation.
+ *
+ * This function may be called only after #mhd_SHA256_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_SHA256_ossl_reset (struct mhd_Sha256CtxOssl *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
+
+/**
+ * Deinitialise the SHA-256 calculation context.
+ *
+ * After calling this function, @a ctx can be reinitialised with
+ * #mhd_SHA256_ossl_init().
+ *
+ * The recorded error state in @a ctx is preserved.
+ *
+ * @param ctx the calculation context
+ */
+MHD_INTERNAL void
+mhd_SHA256_ossl_deinit (struct mhd_Sha256CtxOssl *ctx)
+MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
+
+/**
+ * Indicates whether #mhd_SHA256_ossl_deinit() is a real function or a no-op.
+ *
+ * Set to '0' as #mhd_SHA256_ossl_deinit() is a real function.
+ */
+#define mhd_SHA256_OSSL_DEINIT_NOOP_FLAG 0
+
+
+#endif /* MHD_SHA256_OPENSSL_H */
diff --git a/src/tests/unit/Makefile.am b/src/tests/unit/Makefile.am
@@ -134,6 +134,22 @@ if MHD_MD5_MBEDTLS
endif
-unit_sha256_SOURCES = unit_sha256.c
+unit_sha256_SOURCES = \
+ unit_sha256.c \
+ $(srcdir)/../../mhd2/mhd_sha256.h \
+ $(srcdir)/../../mhd2/sha256_builtin.c $(srcdir)/../../mhd2/sha256_builtin.h
+
+if MHD_SUPPORT_GNUTLS
+ unit_sha256_SOURCES += \
+ $(srcdir)/../../mhd2/sha256_gnutls.c $(srcdir)/../../mhd2/sha256_gnutls.h
+endif
+if MHD_SUPPORT_OPENSSL
+ unit_sha256_SOURCES += \
+ $(srcdir)/../../mhd2/sha256_openssl.c $(srcdir)/../../mhd2/sha256_openssl.h
+endif
+if MHD_SUPPORT_MBEDTLS
+ unit_sha256_SOURCES += \
+ $(srcdir)/../../mhd2/sha256_mbedtls.c $(srcdir)/../../mhd2/sha256_mbedtls.h
+endif
unit_sha512_256_SOURCES = unit_sha512_256.c
diff --git a/src/tests/unit/unit_sha256.c b/src/tests/unit/unit_sha256.c
@@ -50,20 +50,9 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
-#include <stdbool.h>
#include "mhdt_has_param.h"
-#if defined MHD_SHA256_EXTR_OPENSSL
-# include "../mhd2/sha256_ext_openssl.c"
-#elif defined MHD_SHA256_EXTR_GNUTLS
-# include "../mhd2/sha256_ext_gnutls.c"
-#elif defined MHD_SHA256_EXTR_MBEDTLS
-# include "../mhd2/sha256_ext_mbedtls.c"
-#else
-# include "../mhd2/sha256_int.c"
-#endif
-
#include "../mhd2/mhd_sha256.h"
#define SHA256_DIGEST_STRING_SIZE (mhd_SHA256_DIGEST_SIZE * 2 + 1)
@@ -398,10 +387,10 @@ check_result (const char *test_name,
const uint8_t calculated[mhd_SHA256_DIGEST_SIZE],
const uint8_t expected[mhd_SHA256_DIGEST_SIZE])
{
- bool failed = (0 !=
- memcmp (calculated,
- expected,
- mhd_SHA256_DIGEST_SIZE));
+ int failed = (0 !=
+ memcmp (calculated,
+ expected,
+ mhd_SHA256_DIGEST_SIZE));
check_num++; /* Print 1-based numbers */
if (failed)
@@ -441,7 +430,7 @@ test1_str (void)
unsigned int i;
struct mhd_Sha256Ctx ctx;
- mhd_SHA256_init_one_time (&ctx);
+ mhd_SHA256_init (&ctx);
for (i = 0; i < units1_num; i++)
{
uint8_t digest[mhd_SHA256_DIGEST_SIZE];
@@ -452,13 +441,13 @@ test1_str (void)
(const uint8_t *)data_units1[i].str_l.str);
mhd_SHA256_finish_reset (&ctx,
digest);
-#ifdef MHD_SHA256_HAS_EXT_ERROR
- if (0 != ctx.ext_error)
+ if (mhd_SHA256_has_err (&ctx))
{
- fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ fprintf (stderr,
+ "External hashing error: %d.\n",
+ mhd_SHA256_get_err (&ctx));
exit (99);
}
-#endif /* MHD_SHA256_HAS_EXT_ERROR */
num_failed += check_result (MHD_FUNC_, i, digest,
data_units1[i].digest);
}
@@ -474,7 +463,7 @@ test1_bin (void)
unsigned int i;
struct mhd_Sha256Ctx ctx;
- mhd_SHA256_init_one_time (&ctx);
+ mhd_SHA256_init (&ctx);
for (i = 0; i < units2_num; i++)
{
uint8_t digest[mhd_SHA256_DIGEST_SIZE];
@@ -483,15 +472,13 @@ test1_bin (void)
data_units2[i].bin_l.len,
data_units2[i].bin_l.bin);
mhd_SHA256_finish_reset (&ctx, digest);
-#ifdef MHD_SHA256_HAS_EXT_ERROR
- if (0 != ctx.ext_error)
+ if (mhd_SHA256_has_err (&ctx))
{
fprintf (stderr,
"External hashing error: %d.\n",
- ctx.ext_error);
+ mhd_SHA256_get_err (&ctx));
exit (99);
}
-#endif /* MHD_SHA256_HAS_EXT_ERROR */
num_failed += check_result (MHD_FUNC_, i, digest,
data_units2[i].digest);
}
@@ -508,7 +495,7 @@ test2_str (void)
unsigned int i;
struct mhd_Sha256Ctx ctx;
- mhd_SHA256_init_one_time (&ctx);
+ mhd_SHA256_init (&ctx);
for (i = 0; i < units1_num; i++)
{
uint8_t digest[mhd_SHA256_DIGEST_SIZE];
@@ -523,13 +510,13 @@ test2_str (void)
data_units1[i].str_l.len - part_s,
(const uint8_t *)data_units1[i].str_l.str + part_s);
mhd_SHA256_finish_reset (&ctx, digest);
-#ifdef MHD_SHA256_EXTR
- if (0 != ctx.ext_error)
+ if (mhd_SHA256_has_err (&ctx))
{
- fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ fprintf (stderr,
+ "External hashing error: %d.\n",
+ mhd_SHA256_get_err (&ctx));
exit (99);
}
-#endif
num_failed += check_result (MHD_FUNC_, i, digest,
data_units1[i].digest);
}
@@ -545,7 +532,7 @@ test2_bin (void)
unsigned int i;
struct mhd_Sha256Ctx ctx;
- mhd_SHA256_init_one_time (&ctx);
+ mhd_SHA256_init (&ctx);
for (i = 0; i < units2_num; i++)
{
uint8_t digest[mhd_SHA256_DIGEST_SIZE];
@@ -559,15 +546,13 @@ test2_bin (void)
data_units2[i].bin_l.bin + part_s);
mhd_SHA256_finish_reset (&ctx,
digest);
-#ifdef MHD_SHA256_EXTR
- if (0 != ctx.ext_error)
+ if (mhd_SHA256_has_err (&ctx))
{
fprintf (stderr,
"External hashing error: %d.\n",
- ctx.ext_error);
+ mhd_SHA256_get_err (&ctx));
exit (99);
}
-#endif /* MHD_SHA256_EXTR */
num_failed += check_result (MHD_FUNC_, i, digest,
data_units2[i].digest);
}
@@ -591,7 +576,7 @@ test_unaligned (void)
const struct data_unit2 *const tdata = data_units2 + DATA_POS;
- mhd_SHA256_init_one_time (&ctx);
+ mhd_SHA256_init (&ctx);
buf = (uint8_t *)malloc (tdata->bin_l.len + MAX_OFFSET);
digest_buf = (uint8_t *)malloc (mhd_SHA256_DIGEST_SIZE + MAX_OFFSET);
if ((NULL == buf) || (NULL == digest_buf))
@@ -612,15 +597,13 @@ test_unaligned (void)
unaligned_buf);
mhd_SHA256_finish_reset (&ctx,
unaligned_digest);
-#ifdef MHD_SHA256_EXTR
- if (0 != ctx.ext_error)
+ if (mhd_SHA256_has_err (&ctx))
{
fprintf (stderr,
"External hashing error: %d.\n",
- ctx.ext_error);
+ mhd_SHA256_get_err (&ctx));
exit (99);
}
-#endif /* MHD_SHA256_EXTR */
num_failed += check_result (MHD_FUNC_, MAX_OFFSET - offset,
unaligned_digest, tdata->digest);
}
@@ -674,8 +657,7 @@ main (int argc,
"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d" },
{ "Two bytes 0x00 0x00",
"0000",
- "96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7" },
- { NULL, NULL, NULL }
+ "96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7" }
};
struct mhd_Sha256Ctx ctx;
uint8_t digest[mhd_SHA256_DIGEST_SIZE];
@@ -690,11 +672,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_SHA256_init_one_time (&ctx);
+ mhd_SHA256_init (&ctx);
if (!mhd_SHA256_has_err (&ctx))
{
data_len = hex2bin (t->input,
@@ -716,17 +698,18 @@ 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_SHA256_deinit (&ctx);
- total++;
}
num_failed = total - passed;