libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 6cf8c2f33fd1534687044ec52cb18e86865d7f78
parent 898550e1aeb894d3f285a21f91d652a7db1feb11
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Fri,  9 Sep 2022 19:34:20 +0300

Implemented SHA-512/256 hashing support

The full implementation, with support hashing of more than 2 EiB
(exbibytes), as described by specification.
Includes additional code path for more compact code.

Diffstat:
Mconfigure.ac | 30++++++++++++++++++++++++++++++
Msrc/include/microhttpd.h | 11++++++++++-
Msrc/microhttpd/Makefile.am | 13+++++++++++++
Asrc/microhttpd/sha512_256.c | 591+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/microhttpd/sha512_256.h | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/microhttpd/test_sha512_256.c | 588+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 1370 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac @@ -3082,6 +3082,34 @@ AS_VAR_IF([[enable_cookie]],[["yes"]], AM_CONDITIONAL([ENABLE_COOKIE], [[test "x$enable_cookie" = "xyes"]]) AC_MSG_RESULT([[$enable_cookie]]) +# optional: SHA-512/256 support for Digest Auth. Enabled by default. +AC_ARG_ENABLE([[sha512-256]], + [AS_HELP_STRING([[--disable-sha512-256]],[disable SHA-512/256 support for Digest Authentication]) + ], + [ + AS_VAR_IF([[enable_sha512_256]],[["yes"]], + [ + AS_VAR_IF([enable_dauth],["yes"],[], + [ + AC_MSG_WARN([The parameter --enable-sha512-256 is ignored as Digest Authentication is disabled]) + enable_sha512_256='no' + ] + ) + ],[[enable_sha512_256='no']] + ) + ], [[enable_sha512_256="${enable_dauth}"]] +) +AC_MSG_CHECKING([[whether to support SHA-512/256]]) +AS_VAR_IF([[enable_sha512_256]],[["yes"]], + [ + AC_DEFINE([[SHA512_256_SUPPORT]],[[1]], + [Define to 1 if libmicrohttpd is compiled with SHA-512/256 support.]) + ] +) +AM_CONDITIONAL([ENABLE_SHA512_256], [[test "x${enable_sha512_256}" = "xyes"]]) +AC_MSG_RESULT([[${enable_sha512_256}]]) + + AC_CACHE_CHECK([[for calloc()]], [[mhd_cv_have_func_calloc]], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @@ -3962,6 +3990,7 @@ AC_MSG_NOTICE([GNU libmicrohttpd ${PACKAGE_VERSION} Configuration Summary: Messages: ${enable_messages} Basic auth.: ${enable_bauth} Digest auth.: ${enable_dauth} + SHA-512/256: ${enable_sha512_256} HTTP "Upgrade": ${enable_httpupgrade} Cookie parsing: ${enable_cookie} Postproc: ${enable_postprocessor} @@ -3982,6 +4011,7 @@ AS_IF([test "x$enable_https" = "xyes"], AS_IF([test "x$enable_bauth" != "xyes" || \ test "x$enable_dauth" != "xyes" || \ + test "x${enable_sha512_256}" != "xyes" || \ test "x$enable_httpupgrade" != "xyes" || \ test "x$enable_cookie" != "xyes" || \ test "x$enable_postprocessor" != "xyes"], diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -96,7 +96,7 @@ extern "C" * they are parsed as decimal numbers. * Example: 0x01093001 = 1.9.30-1. */ -#define MHD_VERSION 0x00097537 +#define MHD_VERSION 0x00097538 /* If generic headers don't work on your platform, include headers which define 'va_list', 'size_t', 'ssize_t', 'intptr_t', 'off_t', @@ -4429,6 +4429,15 @@ MHD_destroy_post_processor (struct MHD_PostProcessor *pp); #define MHD_SHA256_DIGEST_SIZE 32 /** + * Length of the binary output of the SHA-512/256 hash function. + * The value is the same as the #MHD_SHA256_DIGEST_SIZE. + * @sa #MHD_digest_get_hash_size() + * @note Available since #MHD_VERSION 0x00097538 + * @ingroup authentication + */ +#define MHD_SHA512_256_DIGEST_SIZE 32 + +/** * Base type of hash calculation. * Used as part of #MHD_DigestAuthAlgo3 values. * diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am @@ -171,6 +171,10 @@ libmicrohttpd_la_SOURCES += \ mhd_bithelpers.h mhd_byteorder.h mhd_align.h \ md5.c md5.h \ sha256.c sha256.h +if ENABLE_SHA512_256 +libmicrohttpd_la_SOURCES += \ + sha512_256.c sha512_256.h +endif endif if ENABLE_BAUTH @@ -215,6 +219,11 @@ check_PROGRAMS = \ test_options \ test_set_panic +if ENABLE_SHA512_256 +check_PROGRAMS += \ + test_sha512_256 +endif + if HAVE_POSIX_THREADS if ENABLE_UPGRADE if USE_POSIX_THREADS @@ -448,6 +457,10 @@ test_sha256_SOURCES = \ test_sha256.c test_helpers.h \ sha256.c sha256.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h +test_sha512_256_SOURCES = \ + test_sha512_256.c test_helpers.h \ + sha512_256.c sha512_256.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h + test_sha1_SOURCES = \ test_sha1.c test_helpers.h \ sha1.c sha1.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h diff --git a/src/microhttpd/sha512_256.c b/src/microhttpd/sha512_256.c @@ -0,0 +1,591 @@ +/* + This file is part of GNU libmicrohttpd + Copyright (C) 2022 Karlson2k (Evgeny Grin) + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @file microhttpd/sha512_256.c + * @brief Calculation of SHA-512/256 digest as defined in FIPS PUB 180-4 (2015) + * @author Karlson2k (Evgeny Grin) + */ + +#include "sha512_256.h" + +#include <string.h> +#ifdef HAVE_MEMORY_H +#include <memory.h> +#endif /* HAVE_MEMORY_H */ +#include "mhd_bithelpers.h" +#include "mhd_assert.h" + +/** + * Initialise structure for SHA-512/256 calculation. + * + * @param ctx the calculation context + */ +void +MHD_SHA512_256_init (struct Sha512_256Ctx *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; +} + + +/** + * Base of SHA-512/256 transformation. + * Gets full 64 bytes block of data and updates hash values; + * @param H hash values + * @param data the data buffer with SHA512_256_BLOCK_SIZE bytes block + */ +static void +sha512_256_transform (uint64_t H[SHA512_256_HASH_SIZE_WORDS], + const void *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 = (uint8_t *) 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: 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. + * 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 + /* 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. */ + /* 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. */ + 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; +} + + +/** + * 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 Sha512_256Ctx *ctx, + const uint8_t *data, + size_t length) +{ + 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 ((data != NULL) || (length == 0)); + + if (0 == length) + return; /* Do nothing */ + + /* Note: (count & (SHA512_256_BLOCK_SIZE-1)) + equals (count % SHA512_256_BLOCK_SIZE) for this block size. */ + bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1)); + ctx->count += length; + 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 = SHA512_256_BLOCK_SIZE - bytes_have; + if (length >= 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; + length -= bytes_left; + sha512_256_transform (ctx->H, ctx->buffer); + bytes_have = 0; + } + } + + while (SHA512_256_BLOCK_SIZE <= length) + { /* Process any full blocks of new data directly, + without copying to the buffer. */ + sha512_256_transform (ctx->H, data); + data += SHA512_256_BLOCK_SIZE; + length -= SHA512_256_BLOCK_SIZE; + } + + if (0 != length) + { /* Copy incomplete block of new data (if any) + to the buffer. */ + memcpy (((uint8_t *) ctx->buffer) + bytes_have, data, length); + } +} + + +/** + * 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) + +/** + * Finalise SHA-512/256 calculation, return digest. + * + * @param ctx the calculation context + * @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes + */ +void +MHD_SHA512_256_finish (struct Sha512_256Ctx *ctx, + uint8_t digest[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 & (SHA512_256_BLOCK_SIZE-1)) + equals (count % SHA512_256_BLOCK_SIZE) for this block size. */ + bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1)); + + /* Input data must be padded with bit "1" and then 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 (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 < SHA512_256_BLOCK_SIZE) + memset (((uint8_t *) ctx->buffer) + bytes_have, 0, + 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, + 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 + SHA512_256_BLOCK_SIZE_WORDS - 2, + ctx->count_bits_hi); + _MHD_PUT_64BIT_BE (ctx->buffer + 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. */ +#ifndef _MHD_PUT_64BIT_BE_UNALIGNED + if (0 != ((uintptr_t) digest) % _MHD_UINT64_ALIGN) + { /* The destination is unaligned */ + uint64_t alig_dgst[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, SHA512_256_DIGEST_SIZE); + } + else /* Combined with the next 'if' */ +#endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */ + if (1) + { + /* 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 * SHA512_256_BYTES_IN_WORD), \ + ctx->H[0]); + _MHD_PUT_64BIT_BE ((void *) (digest + 1 * SHA512_256_BYTES_IN_WORD), \ + ctx->H[1]); + _MHD_PUT_64BIT_BE ((void *) (digest + 2 * SHA512_256_BYTES_IN_WORD), \ + ctx->H[2]); + _MHD_PUT_64BIT_BE ((void *) (digest + 3 * SHA512_256_BYTES_IN_WORD), \ + ctx->H[3]); + } + + /* Erase potentially sensitive data. */ + memset (ctx, 0, sizeof(struct Sha512_256Ctx)); +} diff --git a/src/microhttpd/sha512_256.h b/src/microhttpd/sha512_256.h @@ -0,0 +1,138 @@ +/* + This file is part of GNU libmicrohttpd + Copyright (C) 2022 Karlson2k (Evgeny Grin) + + 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. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @file microhttpd/sha512_256.h + * @brief Calculation of SHA-512/256 digest + * @author Karlson2k (Evgeny Grin) + */ + +#ifndef MHD_SHA512_256_H +#define MHD_SHA512_256_H 1 + +#include "mhd_options.h" +#include <stdint.h> +#ifdef HAVE_STDDEF_H +#include <stddef.h> /* for size_t */ +#endif /* HAVE_STDDEF_H */ + + +/** + * Number of bits in single SHA-512/256 word. + */ +#define SHA512_256_WORD_SIZE_BITS 64 + +/** + * Number of bytes in single SHA-512/256 word. + */ +#define SHA512_256_BYTES_IN_WORD (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 SHA512_256_HASH_SIZE_WORDS 8 + +/** + * Size of SHA-512/256 resulting digest in bytes. + * This is the final digest size, not intermediate hash. + */ +#define SHA512_256_DIGEST_SIZE_WORDS (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 SHA512_256_DIGEST_SIZE \ + (SHA512_256_DIGEST_SIZE_WORDS * SHA512_256_BYTES_IN_WORD) + +/** + * Size of SHA-512/256 digest string in chars including termination NUL. + */ +#define SHA512_256_DIGEST_STRING_SIZE ((SHA512_256_DIGEST_SIZE) * 2 + 1) + +/** + * Size of single processing block in bits. + * This is the final digest size, not intermediate hash. + */ +#define SHA512_256_BLOCK_SIZE_BITS 1024 + +/** + * Size of single processing block in bytes. + */ +#define SHA512_256_BLOCK_SIZE (SHA512_256_BLOCK_SIZE_BITS / 8) + +/** + * Size of single processing block in words. + */ +#define SHA512_256_BLOCK_SIZE_WORDS \ + (SHA512_256_BLOCK_SIZE_BITS / SHA512_256_WORD_SIZE_BITS) + + +/** + * SHA-512/256 calculation context + */ +struct Sha512_256Ctx +{ + uint64_t H[SHA512_256_HASH_SIZE_WORDS]; /**< Intermediate hash value */ + uint64_t buffer[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 + */ +void +MHD_SHA512_256_init (struct Sha512_256Ctx *ctx); + + +/** + * 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 Sha512_256Ctx *ctx, + const uint8_t *data, + size_t length); + + +/** + * Finalise SHA-512/256 calculation, return digest. + * + * @param ctx the calculation context + * @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes + */ +void +MHD_SHA512_256_finish (struct Sha512_256Ctx *ctx, + uint8_t digest[SHA512_256_DIGEST_SIZE]); + +#endif /* MHD_SHA512_256_H */ diff --git a/src/microhttpd/test_sha512_256.c b/src/microhttpd/test_sha512_256.c @@ -0,0 +1,588 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2019-2022 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_sha512_256.h + * @brief Unit tests for SHA-512/256 functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_options.h" +#include "sha512_256.h" +#include "test_helpers.h" +#include <stdio.h> +#include <stdlib.h> + +static int verbose = 0; /* verbose level (0-1)*/ + + +struct str_with_len +{ + const char *const str; + const size_t len; +}; + +#define D_STR_W_LEN(s) {(s), (sizeof((s)) / sizeof(char)) - 1} + +struct data_unit1 +{ + const struct str_with_len str_l; + const uint8_t digest[SHA512_256_DIGEST_SIZE]; +}; + +static const struct data_unit1 data_units1[] = { + {D_STR_W_LEN ("abc"), + {0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, 0x9B, 0x2E, 0x29, 0xB7, + 0x6B, 0x4C, 0x7D, 0xAB, 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, + 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23}}, + {D_STR_W_LEN ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" \ + "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), + {0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, 0x40, 0xDA, 0x39, 0x88, + 0x12, 0x1D, 0x31, 0xBE, 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, + 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A}}, + {D_STR_W_LEN (""), /* The empty zero-size input */ + {0xc6, 0x72, 0xb8, 0xd1, 0xef, 0x56, 0xed, 0x28, 0xab, 0x87, 0xc3, 0x62, + 0x2c, 0x51, 0x14, 0x06, 0x9b, 0xdd, 0x3a, 0xd7, 0xb8, 0xf9, 0x73, 0x74, + 0x98, 0xd0, 0xc0, 0x1e, 0xce, 0xf0, 0x96, 0x7a}}, + {D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`."), + {0xc8, 0x7c, 0x5a, 0x55, 0x27, 0x77, 0x1b, 0xe7, 0x69, 0x3c, 0x50, 0x79, + 0x32, 0xad, 0x7c, 0x79, 0xe9, 0x60, 0xa0, 0x18, 0xb7, 0x78, 0x2b, 0x6f, + 0xa9, 0x7b, 0xa3, 0xa0, 0xb5, 0x18, 0x17, 0xa5}}, + {D_STR_W_LEN ("Simple string."), + {0xde, 0xcb, 0x3c, 0x81, 0x65, 0x4b, 0xa0, 0xf5, 0xf0, 0x45, 0x6b, 0x7e, + 0x61, 0xf5, 0x0d, 0xf5, 0x38, 0xa4, 0xfc, 0xb1, 0x8a, 0x95, 0xff, 0x59, + 0xbc, 0x04, 0x82, 0xcf, 0x23, 0xb2, 0x32, 0x56}}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz"), + {0xfc, 0x31, 0x89, 0x44, 0x3f, 0x9c, 0x26, 0x8f, 0x62, 0x6a, 0xea, 0x08, + 0xa7, 0x56, 0xab, 0xe7, 0xb7, 0x26, 0xb0, 0x5f, 0x70, 0x1c, 0xb0, 0x82, + 0x22, 0x31, 0x2c, 0xcf, 0xd6, 0x71, 0x0a, 0x26, }}, + {D_STR_W_LEN ("zyxwvutsrqponMLKJIHGFEDCBA"), + {0xd2, 0x6d, 0x24, 0x81, 0xa4, 0xf9, 0x0a, 0x72, 0xd2, 0x7f, 0xc1, 0xac, + 0xac, 0xe1, 0xc0, 0x6b, 0x39, 0x94, 0xac, 0x73, 0x50, 0x2e, 0x27, 0x97, + 0xa3, 0x65, 0x37, 0x4e, 0xbb, 0x5c, 0x27, 0xe9}}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA" \ + "abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA"), + {0xad, 0xe9, 0x5d, 0x55, 0x3b, 0x9e, 0x45, 0x69, 0xdb, 0x53, 0xa4, 0x04, + 0x92, 0xe7, 0x87, 0x94, 0xff, 0xc9, 0x98, 0x5f, 0x93, 0x03, 0x86, 0x45, + 0xe1, 0x97, 0x17, 0x72, 0x7c, 0xbc, 0x31, 0x15}}, +}; + +static const size_t units1_num = sizeof(data_units1) / sizeof(data_units1[0]); + +struct bin_with_len +{ + const uint8_t bin[512]; + const size_t len; +}; + +struct data_unit2 +{ + const struct bin_with_len bin_l; + const uint8_t digest[SHA512_256_DIGEST_SIZE]; +}; + +/* Size must be less than 512 bytes! */ +static const struct data_unit2 data_units2[] = { + { { {97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122}, 26}, /* a..z ASCII sequence */ + {0xfc, 0x31, 0x89, 0x44, 0x3f, 0x9c, 0x26, 0x8f, 0x62, 0x6a, 0xea, 0x08, + 0xa7, 0x56, 0xab, 0xe7, 0xb7, 0x26, 0xb0, 0x5f, 0x70, 0x1c, 0xb0, 0x82, + 0x22, 0x31, 0x2c, 0xcf, 0xd6, 0x71, 0x0a, 0x26}}, + { { {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65}, + 72 }, /* 'A' x 72 times */ + {0x36, 0x5d, 0x41, 0x0e, 0x55, 0xd1, 0xfd, 0xe6, 0xc3, 0xb8, 0x68, 0xcc, + 0xed, 0xeb, 0xcd, 0x0d, 0x2e, 0x34, 0xb2, 0x5c, 0xdf, 0xe7, 0x79, 0xe2, + 0xe9, 0x65, 0x07, 0x33, 0x78, 0x0d, 0x01, 0x89}}, + { { {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73}, 55}, /* 19..73 sequence */ + {0xb9, 0xe5, 0x74, 0x11, 0xbf, 0xa2, 0x0e, 0x98, 0xbe, 0x08, 0x69, 0x2e, + 0x17, 0x9e, 0xc3, 0xfe, 0x61, 0xe3, 0x7a, 0x80, 0x2e, 0x25, 0x8c, 0xf3, + 0x76, 0xda, 0x9f, 0x5f, 0xcd, 0x87, 0x48, 0x0d}}, + { { {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69}, 63}, /* 7..69 sequence */ + {0x80, 0x15, 0x83, 0xed, 0x7d, 0xef, 0x9f, 0xdf, 0xfb, 0x83, 0x1f, 0xc5, + 0x8b, 0x50, 0x37, 0x81, 0x00, 0xc3, 0x4f, 0xfd, 0xfe, 0xc2, 0x9b, 0xaf, + 0xfe, 0x15, 0x66, 0xe5, 0x08, 0x42, 0x5e, 0xae}}, + { { {38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92}, 55}, /* 38..92 sequence */ + {0x76, 0x2f, 0x27, 0x4d, 0xfa, 0xd5, 0xa9, 0x21, 0x4e, 0xe9, 0x56, 0x22, + 0x54, 0x38, 0x71, 0x3e, 0xef, 0x14, 0xa9, 0x22, 0x37, 0xf3, 0xb0, 0x50, + 0x3d, 0x95, 0x40, 0xb7, 0x08, 0x64, 0xa9, 0xfd}}, + { { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72}, 72}, /* 1..72 sequence */ + {0x3f, 0x5c, 0xd3, 0xec, 0x40, 0xc4, 0xb9, 0x78, 0x35, 0x57, 0xc6, 0x4f, + 0x3e, 0x46, 0x82, 0xdc, 0xd4, 0x46, 0x11, 0xd0, 0xb3, 0x0a, 0xbb, 0x89, + 0xf1, 0x1d, 0x34, 0xb5, 0xf9, 0xd5, 0x10, 0x35}}, + { { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, + 249, 250, 251, 252, 253, 254, 255}, 256}, /* 0..255 sequence */ + {0x08, 0x37, 0xa1, 0x1d, 0x99, 0x4d, 0x5a, 0xa8, 0x60, 0xd0, 0x69, 0x17, + 0xa8, 0xa0, 0xf6, 0x3e, 0x31, 0x11, 0xb9, 0x56, 0x33, 0xde, 0xeb, 0x15, + 0xee, 0xd9, 0x94, 0x93, 0x76, 0xf3, 0x7d, 0x36, }}, + { { {199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, + 185, 184, 183, 182, 181, 180, + 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, + 165, 164, 163, 162, 161, 160, + 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, + 145, 144, 143, 142, 141, 140, + 139}, 61}, /* 199..139 sequence */ + {0xcf, 0x21, 0x4b, 0xb2, 0xdd, 0x40, 0x98, 0xdf, 0x3a, 0xb7, 0x21, 0xb4, + 0x69, 0x0e, 0x19, 0x36, 0x24, 0xa9, 0xbe, 0x30, 0xf7, 0xd0, 0x75, 0xb0, + 0x39, 0x94, 0x82, 0xda, 0x55, 0x97, 0xe4, 0x79}}, + { { {255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, + 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, + 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, + 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, + 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, + 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, + 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, + 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, + 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, + 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, + 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, + 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, + 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, + 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 255}, /* 255..1 sequence */ + {0x22, 0x31, 0xf2, 0xa1, 0xb4, 0x89, 0xb2, 0x44, 0xf7, 0x66, 0xa0, 0xb8, + 0x31, 0xed, 0xb7, 0x73, 0x8a, 0x34, 0xdc, 0x11, 0xc8, 0x2c, 0xf2, 0xb5, + 0x88, 0x60, 0x39, 0x6b, 0x5c, 0x06, 0x70, 0x37}}, + { { {41, 35, 190, 132, 225, 108, 214, 174, 82, 144, 73, 241, 241, 187, 233, + 235, 179, 166, 219, 60, 135, 12, 62, 153, 36, 94, 13, 28, 6, 183, 71, + 222, 179, 18, 77, 200, 67, 187, 139, 166, 31, 3, 90, 125, 9, 56, 37, + 31, 93, 212, 203, 252, 150, 245, 69, 59, 19, 13, 137, 10, 28, 219, 174, + 50, 32, 154, 80, 238, 64, 120, 54, 253, 18, 73, 50, 246, 158, 125, 73, + 220, 173, 79, 20, 242, 68, 64, 102, 208, 107, 196, 48, 183, 50, 59, + 161, 34, 246, 34, 145, 157, 225, 139, 31, 218, 176, 202, 153, 2, 185, + 114, 157, 73, 44, 128, 126, 197, 153, 213, 233, 128, 178, 234, 201, + 204, 83, 191, 103, 214, 191, 20, 214, 126, 45, 220, 142, 102, 131, 239, + 87, 73, 97, 255, 105, 143, 97, 205, 209, 30, 157, 156, 22, 114, 114, + 230, 29, 240, 132, 79, 74, 119, 2, 215, 232, 57, 44, 83, 203, 201, 18, + 30, 51, 116, 158, 12, 244, 213, 212, 159, 212, 164, 89, 126, 53, 207, + 50, 34, 244, 204, 207, 211, 144, 45, 72, 211, 143, 117, 230, 217, 29, + 42, 229, 192, 247, 43, 120, 129, 135, 68, 14, 95, 80, 0, 212, 97, 141, + 190, 123, 5, 21, 7, 59, 51, 130, 31, 24, 112, 146, 218, 100, 84, 206, + 177, 133, 62, 105, 21, 248, 70, 106, 4, 150, 115, 14, 217, 22, 47, 103, + 104, 212, 247, 74, 74, 208, 87, 104}, 255}, /* pseudo-random data */ + {0xb8, 0xdb, 0x2c, 0x2e, 0xf3, 0x12, 0x77, 0x14, 0xf9, 0x34, 0x2d, 0xfa, + 0xda, 0x42, 0xbe, 0xfe, 0x67, 0x3a, 0x8a, 0xf6, 0x71, 0x36, 0x00, 0xff, + 0x77, 0xa5, 0x83, 0x14, 0x55, 0x2a, 0x05, 0xaf}}, + { { {66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66}, 110}, /* 'B' x 110 times */ + {0xc8, 0x9e, 0x0d, 0x8f, 0x7b, 0x35, 0xfd, 0x3e, 0xdc, 0x90, 0x87, 0x64, + 0x45, 0x94, 0x94, 0x21, 0xb3, 0x8e, 0xb5, 0xc7, 0x54, 0xc8, 0xee, 0xde, + 0xfc, 0x77, 0xd6, 0xe3, 0x9f, 0x81, 0x8e, 0x78}}, + { { {67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67}, 111}, /* 'C' x 111 times */ + {0x86, 0xca, 0x6d, 0x2a, 0x72, 0xe2, 0x8c, 0x17, 0x89, 0x86, 0x89, 0x1b, + 0x36, 0xf9, 0x6d, 0xda, 0x8c, 0xd6, 0x30, 0xb2, 0xd3, 0x60, 0x39, 0xfb, + 0xc9, 0x04, 0xc5, 0x11, 0xcd, 0x2d, 0xe3, 0x62}}, + { { {68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68}, 112}, /* 'D' x 112 times */ + {0xdf, 0x9d, 0x4a, 0xcf, 0x81, 0x0d, 0x3a, 0xd4, 0x8e, 0xa4, 0x65, 0x9e, + 0x1e, 0x15, 0xe4, 0x15, 0x1b, 0x37, 0xb6, 0xeb, 0x17, 0xab, 0xf6, 0xb1, + 0xbc, 0x30, 0x46, 0x34, 0x24, 0x56, 0x1c, 0x06}}, + { { {69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69}, 113}, /* 'E' x 113 times */ + {0xa5, 0xf1, 0x47, 0x74, 0xf8, 0x2b, 0xed, 0x23, 0xe4, 0x10, 0x59, 0x8f, + 0x7e, 0xb1, 0x30, 0xe5, 0x7e, 0xd1, 0x4b, 0xbc, 0x72, 0x58, 0x58, 0x81, + 0xbb, 0xa0, 0xa5, 0xb6, 0x15, 0x39, 0x49, 0xa1}}, + { { {70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70}, 114}, /* 'F' x 114 times */ + {0xe6, 0xa3, 0xc9, 0x63, 0xd5, 0x28, 0x6e, 0x2d, 0xfb, 0x71, 0xdf, 0xd4, + 0xff, 0xc2, 0xd4, 0x2b, 0x5d, 0x9b, 0x76, 0x28, 0xd2, 0xcb, 0x15, 0xc8, + 0x81, 0x57, 0x14, 0x09, 0xc3, 0x8e, 0x92, 0xce}}, + { { {76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76}, 127}, /* 'L' x 127 times */ + {0x5d, 0x18, 0xff, 0xd7, 0xbe, 0x23, 0xb2, 0xb2, 0xbd, 0xe3, 0x13, 0x12, + 0x1c, 0x16, 0x89, 0x14, 0x4a, 0x42, 0xb4, 0x3f, 0xab, 0xc8, 0x41, 0x14, + 0x62, 0x00, 0xb5, 0x53, 0xa7, 0xd6, 0xd5, 0x35}}, + { { {77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77}, 128}, /* 'M' x 128 times */ + {0x6e, 0xf0, 0xda, 0x81, 0x3d, 0x50, 0x1d, 0x31, 0xf1, 0x4a, 0xf8, 0xd9, + 0x7d, 0xd2, 0x13, 0xdd, 0xa4, 0x46, 0x15, 0x0b, 0xb8, 0x5a, 0x8a, 0xc6, + 0x1e, 0x3a, 0x1f, 0x21, 0x35, 0xa2, 0xbb, 0x4f}}, + { { {78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78}, 129}, /* 'N' x 129 times */ + {0xee, 0xce, 0xd5, 0x34, 0xab, 0x14, 0x13, 0x9e, 0x8f, 0x5c, 0xb4, 0xef, + 0xac, 0xaf, 0xc5, 0xeb, 0x1d, 0x2f, 0xe3, 0xc5, 0xca, 0x09, 0x29, 0x96, + 0xfa, 0x84, 0xff, 0x12, 0x26, 0x6a, 0x50, 0x49}}, + { { {97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97}, 238}, /* 'a' x 238 times */ + {0xb4, 0x24, 0xe5, 0x7b, 0xa7, 0x37, 0xe3, 0xc4, 0xac, 0x35, 0x21, 0x17, + 0x98, 0xec, 0xb9, 0xae, 0x45, 0x13, 0x24, 0xa4, 0x2c, 0x76, 0xae, 0x7d, + 0x17, 0x75, 0x27, 0x8a, 0xaa, 0x4a, 0x48, 0x60}}, + { { {98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98}, 239}, /* 'b' x 239 times */ + {0xcd, 0x93, 0xb8, 0xab, 0x6a, 0x74, 0xbd, 0x34, 0x8c, 0x43, 0x76, 0x0c, + 0x2a, 0xd0, 0x6e, 0xd8, 0x76, 0xcf, 0xdf, 0x2a, 0x21, 0x04, 0xfb, 0xf6, + 0x16, 0x53, 0x68, 0xf6, 0x10, 0xc3, 0xa1, 0xac}}, + { { {99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99}, 240}, /* 'c' x 240 times */ + {0x5f, 0x60, 0xea, 0x44, 0xb6, 0xc6, 0x9e, 0xfe, 0xfc, 0x0e, 0x6a, 0x0a, + 0x99, 0x40, 0x1b, 0x61, 0x43, 0x58, 0xba, 0x4a, 0x0a, 0xee, 0x6b, 0x52, + 0x10, 0xdb, 0x32, 0xd9, 0x7f, 0x12, 0xba, 0x70}}, + { { {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48}, 241}, /* '0' x 241 times */ + {0x3c, 0xcb, 0xcf, 0x50, 0x79, 0xd5, 0xb6, 0xf5, 0xbf, 0x25, 0x07, 0xfb, + 0x4d, 0x1f, 0xa3, 0x77, 0xc3, 0x6f, 0xe8, 0xe3, 0xc4, 0x4b, 0xf8, 0xcd, + 0x90, 0x93, 0xf1, 0x3e, 0x08, 0x09, 0xa7, 0x69}} +}; + +static const size_t units2_num = sizeof(data_units2) / sizeof(data_units2[0]); + + +/* + * Helper functions + */ + +/** + * Print bin as hex + * + * @param bin binary data + * @param len number of bytes in bin + * @param hex pointer to len*2+1 bytes buffer + */ +static void +bin2hex (const uint8_t *bin, + size_t len, + char *hex) +{ + while (len-- > 0) + { + unsigned int b1, b2; + b1 = (*bin >> 4) & 0xf; + *hex++ = (char) ((b1 > 9) ? (b1 + 'A' - 10) : (b1 + '0')); + b2 = *bin++ & 0xf; + *hex++ = (char) ((b2 > 9) ? (b2 + 'A' - 10) : (b2 + '0')); + } + *hex = 0; +} + + +static int +check_result (const char *test_name, + unsigned int check_num, + const uint8_t calculated[SHA512_256_DIGEST_SIZE], + const uint8_t expected[SHA512_256_DIGEST_SIZE]) +{ + int failed = memcmp (calculated, expected, SHA512_256_DIGEST_SIZE); + check_num++; /* Print 1-based numbers */ + if (failed) + { + char calc_str[SHA512_256_DIGEST_SIZE * 2 + 1]; + char expc_str[SHA512_256_DIGEST_SIZE * 2 + 1]; + bin2hex (calculated, SHA512_256_DIGEST_SIZE, calc_str); + bin2hex (expected, SHA512_256_DIGEST_SIZE, expc_str); + fprintf (stderr, + "FAILED: %s check %u: calculated digest %s, expected digest %s.\n", + test_name, check_num, calc_str, expc_str); + fflush (stderr); + } + else if (verbose) + { + char calc_str[SHA512_256_DIGEST_SIZE * 2 + 1]; + bin2hex (calculated, SHA512_256_DIGEST_SIZE, calc_str); + printf ( + "PASSED: %s check %u: calculated digest %s matches expected digest.\n", + test_name, check_num, calc_str); + fflush (stdout); + } + return failed ? 1 : 0; +} + + +/* + * Tests + */ + +/* Calculated SHA-512/256 as one pass for whole data */ +static int +test1_str (void) +{ + int num_failed = 0; + unsigned int i; + + for (i = 0; i < units1_num; i++) + { + struct Sha512_256Ctx ctx; + uint8_t digest[SHA512_256_DIGEST_SIZE]; + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str, + data_units1[i].str_l.len); + MHD_SHA512_256_finish (&ctx, digest); + num_failed += check_result (__FUNCTION__, i, digest, + data_units1[i].digest); + } + return num_failed; +} + + +static int +test1_bin (void) +{ + int num_failed = 0; + unsigned int i; + + for (i = 0; i < units2_num; i++) + { + struct Sha512_256Ctx ctx; + uint8_t digest[SHA512_256_DIGEST_SIZE]; + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, data_units2[i].bin_l.bin, + data_units2[i].bin_l.len); + MHD_SHA512_256_finish (&ctx, digest); + num_failed += check_result (__FUNCTION__, i, digest, + data_units2[i].digest); + } + return num_failed; +} + + +/* Calculated SHA-512/256 as two iterations for whole data */ +static int +test2_str (void) +{ + int num_failed = 0; + unsigned int i; + + for (i = 0; i < units1_num; i++) + { + struct Sha512_256Ctx ctx; + uint8_t digest[SHA512_256_DIGEST_SIZE]; + size_t part_s = data_units1[i].str_l.len / 4; + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str, + part_s); + MHD_SHA512_256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str + + part_s, + data_units1[i].str_l.len - part_s); + MHD_SHA512_256_finish (&ctx, digest); + num_failed += check_result (__FUNCTION__, i, digest, + data_units1[i].digest); + } + return num_failed; +} + + +static int +test2_bin (void) +{ + int num_failed = 0; + unsigned int i; + + for (i = 0; i < units2_num; i++) + { + struct Sha512_256Ctx ctx; + uint8_t digest[SHA512_256_DIGEST_SIZE]; + size_t part_s = data_units2[i].bin_l.len * 2 / 3; + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, data_units2[i].bin_l.bin, part_s); + MHD_SHA512_256_update (&ctx, data_units2[i].bin_l.bin + part_s, + data_units2[i].bin_l.len - part_s); + MHD_SHA512_256_finish (&ctx, digest); + num_failed += check_result (__FUNCTION__, i, digest, + data_units2[i].digest); + } + return num_failed; +} + + +/* Use data set number 7 as it has the longest sequence */ +#define DATA_POS 6 +#define MAX_OFFSET 63 + +static int +test_unaligned (void) +{ + int num_failed = 0; + unsigned int offset; + uint8_t *buf; + uint8_t *digest_buf; + + const struct data_unit2 *const tdata = data_units2 + DATA_POS; + + buf = malloc (tdata->bin_l.len + MAX_OFFSET); + digest_buf = malloc (SHA512_256_DIGEST_SIZE + MAX_OFFSET); + if ((NULL == buf) || (NULL == digest_buf)) + exit (99); + + for (offset = MAX_OFFSET; offset >= 1; --offset) + { + struct Sha512_256Ctx ctx; + uint8_t *unaligned_digest; + uint8_t *unaligned_buf; + + unaligned_buf = buf + offset; + memcpy (unaligned_buf, tdata->bin_l.bin, tdata->bin_l.len); + unaligned_digest = digest_buf + MAX_OFFSET - offset; + memset (unaligned_digest, 0, SHA512_256_DIGEST_SIZE); + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, unaligned_buf, tdata->bin_l.len); + MHD_SHA512_256_finish (&ctx, unaligned_digest); + num_failed += check_result (__FUNCTION__, MAX_OFFSET - offset, + unaligned_digest, tdata->digest); + } + free (digest_buf); + free (buf); + return num_failed; +} + + +int +main (int argc, char *argv[]) +{ + int num_failed = 0; + (void) has_in_name; /* Mute compiler warning. */ + if (has_param (argc, argv, "-v") || has_param (argc, argv, "--verbose")) + verbose = 1; + + num_failed += test1_str (); + num_failed += test1_bin (); + + num_failed += test2_str (); + num_failed += test2_bin (); + + num_failed += test_unaligned (); + + return num_failed ? 1 : 0; +}