gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] 07/09: Implemented SHA-512/256 hashing support


From: gnunet
Subject: [libmicrohttpd] 07/09: Implemented SHA-512/256 hashing support
Date: Sun, 11 Sep 2022 19:56:09 +0200

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

commit 6cf8c2f33fd1534687044ec52cb18e86865d7f78
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Fri Sep 9 19:34:20 2022 +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.
---
 configure.ac                     |  30 ++
 src/include/microhttpd.h         |  11 +-
 src/microhttpd/Makefile.am       |  13 +
 src/microhttpd/sha512_256.c      | 591 +++++++++++++++++++++++++++++++++++++++
 src/microhttpd/sha512_256.h      | 138 +++++++++
 src/microhttpd/test_sha512_256.c | 588 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 1370 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 64631425..b8de0798 100644
--- 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
index 95c2bb4f..31d4c648 100644
--- 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',
@@ -4428,6 +4428,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
index fbc545eb..b400d8e6 100644
--- 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
new file mode 100644
index 00000000..54389c6b
--- /dev/null
+++ 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
new file mode 100644
index 00000000..43359dc7
--- /dev/null
+++ 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
new file mode 100644
index 00000000..85c3a0ee
--- /dev/null
+++ 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;
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]