libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

commit c46a9ad4311adf87a14fd7accdcf82350b7945df
parent b5992394edc4af93b24bf12e774b8b1344ef9cab
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date:   Mon, 13 Jul 2026 22:13:10 +0200

Reworked SHA-512/256 backends handling, fixed number of problems

Removed two levels dispatcher/selector, simplified to single level.
Optimised by avoiding unneeded context resets and using proper internal
API functions.

Diffstat:
Msrc/mhd2/Makefile.am | 20++++++++++++--------
Msrc/mhd2/auth_digest.c | 19++++---------------
Msrc/mhd2/mhd_sha512_256.h | 242+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Asrc/mhd2/sha512_256_builtin.c | 648+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/mhd2/sha512_256_builtin.h | 192+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/mhd2/sha512_256_ext.h | 266-------------------------------------------------------------------------------
Dsrc/mhd2/sha512_256_ext_mbedtls.c | 203-------------------------------------------------------------------------------
Dsrc/mhd2/sha512_256_ext_openssl.c | 156-------------------------------------------------------------------------------
Dsrc/mhd2/sha512_256_int.c | 641-------------------------------------------------------------------------------
Dsrc/mhd2/sha512_256_int.h | 158-------------------------------------------------------------------------------
Asrc/mhd2/sha512_256_mbedtls.c | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/mhd2/sha512_256_mbedtls.h | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/mhd2/sha512_256_openssl.c | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/mhd2/sha512_256_openssl.h | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/tests/unit/Makefile.am | 17++++++++++++++++-
Msrc/tests/unit/unit_sha512_256.c | 40+++++++++++++++-------------------------
16 files changed, 1696 insertions(+), 1528 deletions(-)

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