gnunet-svn
[Top][All Lists]
Advanced

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

[libmicrohttpd] branch master updated (2699d278 -> 8318f56e)


From: gnunet
Subject: [libmicrohttpd] branch master updated (2699d278 -> 8318f56e)
Date: Sun, 11 Sep 2022 19:56:02 +0200

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

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from 2699d278 .gitignore: added universal patter to ignore test binaries
     new c3680cb7 Digest Auth API: do not store 'userhash' in 'username' members
     new 0531511f Editorial doxy improvements
     new 070947d8 configure: fixed underquoting, typos, wording
     new 3432eaad mhd_bithelpers: Fixed typo in comment
     new 30d2c2ee mhd_bithelpers: added more 64 bit manipulation 
functions/macros
     new 898550e1 microhttpd.h: fixed typo in doxy
     new 6cf8c2f3 Implemented SHA-512/256 hashing support
     new 9fa5a3b9 test_dauth_user{digest,hash}: fixed copy-paste errors
     new 8318f56e digestauth: added support for SHA-512/256, made MD5 and 
SHA-256 optional

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 configure.ac                           | 116 ++++++-
 src/include/microhttpd.h               | 139 +++++---
 src/microhttpd/Makefile.am             |  33 +-
 src/microhttpd/daemon.c                |   8 +-
 src/microhttpd/digestauth.c            | 394 ++++++++++++++++++----
 src/microhttpd/gen_auth.c              |  30 +-
 src/microhttpd/internal.h              |  10 +-
 src/microhttpd/mhd_bithelpers.h        |  58 +++-
 src/microhttpd/sha512_256.c            | 591 +++++++++++++++++++++++++++++++++
 src/microhttpd/sha512_256.h            | 138 ++++++++
 src/microhttpd/test_dauth_userdigest.c | 205 +++++++++++-
 src/microhttpd/test_dauth_userhash.c   | 237 ++++++++++++-
 src/microhttpd/test_sha512_256.c       | 588 ++++++++++++++++++++++++++++++++
 src/testcurl/Makefile.am               |  24 +-
 src/testcurl/test_digestauth2.c        |  62 ++--
 src/testcurl/test_digestauth_emu_ext.c |   8 +
 16 files changed, 2457 insertions(+), 184 deletions(-)
 create mode 100644 src/microhttpd/sha512_256.c
 create mode 100644 src/microhttpd/sha512_256.h
 create mode 100644 src/microhttpd/test_sha512_256.c

diff --git a/configure.ac b/configure.ac
index b12bb253..31ae78ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3033,28 +3033,26 @@ AM_CONDITIONAL([HAVE_GNUTLS_MTHREAD_BROKEN], [[test 
"x${mhd_cv_gnutls_mthread_br
 AM_CONDITIONAL([USE_UPGRADE_TLS_TESTS], [[test 
"x${mhd_cv_gnutls_mthread_broken}" = "xno" || test "x${mhd_cv_gnutls_cli}" = 
"xyes"]])
 
 # optional: HTTP Basic Auth support. Enabled by default
-AC_MSG_CHECKING([[whether to support HTTP basic authentication]])
+AC_MSG_CHECKING([[whether to support HTTP Basic authentication]])
 AC_ARG_ENABLE([bauth],
-               AS_HELP_STRING([--disable-bauth],
-                       [disable HTTP basic Auth support]),
+               [AS_HELP_STRING([--disable-bauth],[disable HTTP Basic 
Authentication support])],
                [enable_bauth=${enableval}],
                [enable_bauth=yes])
 AS_IF([[test "x$enable_bauth" != "xno"]],
   [ enable_bauth=yes
-    AC_DEFINE([BAUTH_SUPPORT],[1],[Define to 1 if libmicrohttpd is compiled 
with basic Auth support.]) ])
+    AC_DEFINE([BAUTH_SUPPORT],[1],[Define to 1 if libmicrohttpd is compiled 
with Basic Auth support.]) ])
 AM_CONDITIONAL([ENABLE_BAUTH], [test "x$enable_bauth" != "xno"])
 AC_MSG_RESULT([[$enable_bauth]])
 
 # optional: HTTP Digest Auth support. Enabled by default
-AC_MSG_CHECKING([[whether to support HTTP digest authentication]])
+AC_MSG_CHECKING([[whether to support HTTP Digest authentication]])
 AC_ARG_ENABLE([dauth],
-               AS_HELP_STRING([--disable-dauth],
-                       [disable HTTP basic and digest Auth support]),
+               [AS_HELP_STRING([--disable-dauth], [disable HTTP Digest 
Authentication support])],
                [enable_dauth=${enableval}],
                [enable_dauth=yes])
 AS_IF([[test "x$enable_dauth" != "xno"]],
   [ enable_dauth=yes
-    AC_DEFINE([DAUTH_SUPPORT],[1],[Define to 1 if libmicrohttpd is compiled 
with digest Auth support.]) ])
+    AC_DEFINE([DAUTH_SUPPORT],[1],[Define to 1 if libmicrohttpd is compiled 
with Digest Auth support.]) ])
 AM_CONDITIONAL([ENABLE_DAUTH], [test "x$enable_dauth" != "xno"])
 AC_MSG_RESULT([[$enable_dauth]])
 
@@ -3063,8 +3061,7 @@ AM_CONDITIONAL([HAVE_ANYAUTH],[test "x$enable_bauth" != 
"xno" || test "x$enable_
 # optional: HTTP "Upgrade" support. Enabled by default
 AC_MSG_CHECKING([[whether to support HTTP "Upgrade"]])
 AC_ARG_ENABLE([[httpupgrade]],
-    AS_HELP_STRING([[--disable-httpupgrade]],
-      [disable HTTP "Upgrade" support]),
+    [AS_HELP_STRING([[--disable-httpupgrade]], [disable HTTP "Upgrade" 
support])],
     
[AS_VAR_IF([[enable_httpupgrade]],[["no"]],[],[[enable_httpupgrade='yes']])],
     [[enable_httpupgrade='yes']])
 AS_VAR_IF([[enable_httpupgrade]],[["yes"]],
@@ -3076,8 +3073,7 @@ AC_MSG_RESULT([[$enable_httpupgrade]])
 # optional: HTTP cookie parsing support. Enabled by default
 AC_MSG_CHECKING([[whether to support HTTP cookie parsing]])
 AC_ARG_ENABLE([[cookie]],
-    AS_HELP_STRING([[--disable-cookie]],
-      [disable HTTP cookie parsing support]),
+    [AS_HELP_STRING([[--disable-cookie]], [disable HTTP cookie parsing 
support])],
     [AS_VAR_IF([[enable_cookie]],[["no"]],[],[[enable_cookie='yes']])],
     [[enable_cookie='yes']])
 AS_VAR_IF([[enable_cookie]],[["yes"]],
@@ -3086,6 +3082,96 @@ AS_VAR_IF([[enable_cookie]],[["yes"]],
 AM_CONDITIONAL([ENABLE_COOKIE], [[test "x$enable_cookie" = "xyes"]])
 AC_MSG_RESULT([[$enable_cookie]])
 
+# optional: MD5 support for Digest Auth. Enabled by default.
+AC_ARG_ENABLE([[md5]],
+  [AS_HELP_STRING([[--disable-md5]],[disable MD5 hashing support for Digest 
Authentication])
+  ],
+  [
+    AS_VAR_IF([[enable_md5]],[["yes"]],
+      [
+        AS_VAR_IF([enable_dauth],["yes"],[],
+          [
+            AC_MSG_WARN([The parameter --enable-md5 is ignored as Digest 
Authentication is disabled])
+            enable_md5='no'
+          ]
+        )
+      ],[[enable_md5='no']]
+    )
+  ], [[enable_md5="${enable_dauth}"]]
+)
+AC_MSG_CHECKING([[whether to support MD5]])
+AS_VAR_IF([[enable_md5]],[["yes"]],
+  [
+   AC_DEFINE([[MHD_MD5_SUPPORT]],[[1]],
+     [Define to 1 if libmicrohttpd is compiled with MD5 hashing support.])
+  ]
+)
+AM_CONDITIONAL([ENABLE_MD5], [[test "x${enable_md5}" = "xyes"]])
+AC_MSG_RESULT([[${enable_md5}]])
+
+# optional: SHA-256 support for Digest Auth. Enabled by default.
+AC_ARG_ENABLE([[sha256]],
+  [AS_HELP_STRING([[--disable-sha256]],[disable SHA-256 hashing support for 
Digest Authentication])
+  ],
+  [
+    AS_VAR_IF([[enable_sha256]],[["yes"]],
+      [
+        AS_VAR_IF([enable_dauth],["yes"],[],
+          [
+            AC_MSG_WARN([The parameter --enable-sha256 is ignored as Digest 
Authentication is disabled])
+            enable_sha256='no'
+          ]
+        )
+      ],[[enable_sha256='no']]
+    )
+  ], [[enable_sha256="${enable_dauth}"]]
+)
+AC_MSG_CHECKING([[whether to support SHA-256]])
+AS_VAR_IF([[enable_sha256]],[["yes"]],
+  [
+   AC_DEFINE([[MHD_SHA256_SUPPORT]],[[1]],
+     [Define to 1 if libmicrohttpd is compiled with SHA-256 hashing support.])
+  ]
+)
+AM_CONDITIONAL([ENABLE_SHA256], [[test "x${enable_sha256}" = "xyes"]])
+AC_MSG_RESULT([[${enable_sha256}]])
+
+# 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 hashing 
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([[MHD_SHA512_256_SUPPORT]],[[1]],
+     [Define to 1 if libmicrohttpd is compiled with SHA-512/256 hashing 
support.])
+  ]
+)
+AM_CONDITIONAL([ENABLE_SHA512_256], [[test "x${enable_sha512_256}" = "xyes"]])
+AC_MSG_RESULT([[${enable_sha512_256}]])
+
+AS_IF([test "x$enable_dauth" != "xno"],
+  [
+    AS_IF([test "x${enable_md5}" != "xyes" &&  test "x${enable_sha256}" != 
"xyes" && test "x${enable_sha512_256}" != "xyes"],
+      [AC_MSG_ERROR([At least one hashing algorithm must be enabled if Digest 
Auth is enabled])]
+    )
+  ]
+)
+
+
 AC_CACHE_CHECK([[for calloc()]], [[mhd_cv_have_func_calloc]],
   [
    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@@ -3966,6 +4052,9 @@ AC_MSG_NOTICE([GNU libmicrohttpd ${PACKAGE_VERSION} 
Configuration Summary:
   Messages:          ${enable_messages}
   Basic auth.:       ${enable_bauth}
   Digest auth.:      ${enable_dauth}
+  MD5:               ${enable_md5}
+  SHA-256:           ${enable_sha256}
+  SHA-512/256:       ${enable_sha512_256}
   HTTP "Upgrade":    ${enable_httpupgrade}
   Cookie parsing:    ${enable_cookie}
   Postproc:          ${enable_postprocessor}
@@ -3986,6 +4075,9 @@ AS_IF([test "x$enable_https" = "xyes"],
 
 AS_IF([test "x$enable_bauth" != "xyes" || \
    test "x$enable_dauth" != "xyes" || \
+   test "x${enable_md5}" != "xyes" || \
+   test "x${enable_sha256}" != "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 7b72dfa6..e5f0abac 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 0x00097536
+#define MHD_VERSION 0x00097539
 
 /* If generic headers don't work on your platform, include headers
    which define 'va_list', 'size_t', 'ssize_t', 'intptr_t', 'off_t',
@@ -4421,7 +4421,6 @@ MHD_destroy_post_processor (struct MHD_PostProcessor *pp);
  */
 #define MHD_MD5_DIGEST_SIZE 16
 
-
 /**
  * Length of the binary output of the SHA-256 hash function.
  * @sa #MHD_digest_get_hash_size()
@@ -4429,6 +4428,16 @@ 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.
+ * @warning While this value is the same as the #MHD_SHA256_DIGEST_SIZE,
+ *          the calculated digests for SHA-256 and SHA-512/256 are different.
+ * @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.
@@ -4457,22 +4466,21 @@ enum MHD_DigestBaseAlgo
 
   /**
    * SHA-512/256 hash algorithm.
-   * Not supported for calculations, only supported for parsing of
-   * client's authorisation headers.
+   * As specified by FIPS PUB 180-4
    */
   MHD_DIGEST_BASE_ALGO_SHA512_256 = (1 << 2)
 } _MHD_FIXED_FLAGS_ENUM;
 
 /**
- * The flag indicating digest calculation types,
- * like 'MD5' or 'SHA-256'.
+ * The flag indicating non-session algorithm types,
+ * like 'MD5', 'SHA-256' or 'SHA-512-256'.
  * @note Available since #MHD_VERSION 0x00097519
  */
 #define MHD_DIGEST_AUTH_ALGO3_NON_SESSION    (1 << 6)
 
 /**
  * The flag indicating session algorithm types,
- * like 'MD5-sess' or 'SHA-256-sess'.
+ * like 'MD5-sess', 'SHA-256-sess' or 'SHA-512-256-sess'.
  * @note Available since #MHD_VERSION 0x00097519
  */
 #define MHD_DIGEST_AUTH_ALGO3_SESSION        (1 << 7)
@@ -4520,7 +4528,6 @@ enum MHD_DigestAuthAlgo3
 
   /**
    * The 'SHA-512-256' (SHA-512/256) algorithm.
-   * Not supported by MHD for authentication.
    */
   MHD_DIGEST_AUTH_ALGO3_SHA512_256 =
     MHD_DIGEST_BASE_ALGO_SHA512_256 | MHD_DIGEST_AUTH_ALGO3_NON_SESSION,
@@ -4541,8 +4548,8 @@ enum MHD_DigestAuthAlgo3
  * and other parameters which size depends on used hash algorithm.
  * @param algo3 the algorithm to check
  * @return the size of the digest (either #MHD_MD5_DIGEST_SIZE or
- *         #MHD_SHA256_DIGEST_SIZE) or zero if the input value is not
- *         recognised/valid
+ *         #MHD_SHA256_DIGEST_SIZE/MHD_SHA512_256_DIGEST_SIZE)
+ *         or zero if the input value is not supported or not valid
  * @sa #MHD_digest_auth_calc_userdigest()
  * @sa #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_calc_userhash_hex()
  * @note Available since #MHD_VERSION 0x00097526
@@ -4593,8 +4600,6 @@ enum MHD_DigestAuthMultiAlgo3
 
   /**
    * The 'SHA-512-256' (SHA-512/256) algorithm.
-   * Not supported by MHD for authentication.
-   * Reserved value.
    */
   MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256 = MHD_DIGEST_AUTH_ALGO3_SHA512_256,
 
@@ -4637,6 +4642,15 @@ enum MHD_DigestAuthMultiAlgo3
     MHD_DIGEST_AUTH_MULT_ALGO3_SHA256
     | MHD_DIGEST_AUTH_MULT_ALGO3_SHA256_SESSION,
 
+  /**
+   * The 'SHA-512/256' algorithm, session or non-session.
+   * Not supported by MHD.
+   * Reserved value.
+   */
+  MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_ANY =
+    MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256
+    | MHD_DIGEST_AUTH_MULT_ALGO3_SHA512_256_SESSION,
+
   /**
    * Any algorithm, MHD will choose.
    */
@@ -4738,7 +4752,16 @@ MHD_digest_auth_calc_userhash_hex (enum 
MHD_DigestAuthAlgo3 algo3,
 /**
  * The type of username used by client in Digest Authorization header
  *
- * @note Available since #MHD_VERSION 0x00097519
+ * Values are sorted so simplified checks could be used.
+ * For example:
+ * * (value <= MHD_DIGEST_AUTH_UNAME_TYPE_INVALID) is true if no valid username
+ *   is provided by the client
+ * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH) is true if username is
+ *   provided in any form
+ * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD) is true if username is
+ *   provided in clear text (not userhash matching is needed)
+ *
+ * @note Available since #MHD_VERSION 0x00097537
  */
 enum MHD_DigestAuthUsernameType
 {
@@ -4751,7 +4774,7 @@ enum MHD_DigestAuthUsernameType
   /**
    * The 'username' parameter is used to specify the username.
    */
-  MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD = 1,
+  MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD = (1 << 2),
 
   /**
    * The username is specified by 'username*' parameter with
@@ -4759,14 +4782,14 @@ enum MHD_DigestAuthUsernameType
    * The only difference between standard and extended types is
    * the way how username value is encoded in the header.
    */
-  MHD_DIGEST_AUTH_UNAME_TYPE_EXTENDED = 2,
+  MHD_DIGEST_AUTH_UNAME_TYPE_EXTENDED = (1 << 3),
 
   /**
    * The username provided in form of 'userhash' as
    * specified by RFC 7616 #section-3.4.4.
    * @sa #MHD_digest_auth_calc_userhash_hex(), #MHD_digest_auth_calc_userhash()
    */
-  MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH = 3,
+  MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH = (1 << 1),
 
   /**
    * The invalid combination of username parameters are used by client.
@@ -4776,7 +4799,7 @@ enum MHD_DigestAuthUsernameType
    * * 'username*' used with invalid extended notation
    * * 'username' is not hexadecimal digits, while 'userhash' set to 'true'
    */
-  MHD_DIGEST_AUTH_UNAME_TYPE_INVALID = 15
+  MHD_DIGEST_AUTH_UNAME_TYPE_INVALID = (1 << 0)
 } _MHD_FIXED_ENUM;
 
 /**
@@ -4883,7 +4906,7 @@ enum MHD_DigestAuthMultiQOP
  *
  * Application may modify buffers as needed until #MHD_free() is called for
  * pointer to this structure
- * @note Available since #MHD_VERSION 0x00097533
+ * @note Available since #MHD_VERSION 0x00097537
  */
 struct MHD_DigestAuthInfo
 {
@@ -4902,14 +4925,12 @@ struct MHD_DigestAuthInfo
 
   /**
    * The username string.
-   * Valid only if username is standard, extended, or userhash.
-   * For userhash this is unqoted string without decoding of the
-   * hexadecimal digits (as provided by the client).
+   * Used only if username type is standard or extended, always NULL otherwise.
    * If extended notation is used, this string is pct-decoded string
    * with charset and language tag removed (i.e. it is original username
    * extracted from the extended notation).
-   * This can be NULL is username is missing or invalid.
-   * @sa #MHD_digest_auth_calc_userhash_hex()
+   * When userhash is used by the client, this member is NULL and
+   * @a userhash_hex is set.
    */
   char *username;
 
@@ -4919,12 +4940,28 @@ struct MHD_DigestAuthInfo
    */
   size_t username_len;
 
+  /**
+   * The userhash string.
+   * Valid only if username type is userhash.
+   * This is unqoted string without decoding of the hexadecimal
+   * digits (as provided by the client).
+   * @sa #MHD_digest_auth_calc_userhash_hex()
+   */
+  char *userhash_hex;
+
+  /**
+   * The length of the @a userhash_hex in characters.
+   * The valid size should be #MHD_digest_get_hash_size(algo3) * 2 characters.
+   * When the @a userhash_hex is NULL, this member is always zero.
+   */
+  size_t userhash_hex_len;
+
   /**
    * The userhash decoded to binary form.
    * Used only if username type is userhash, always NULL otherwise.
-   * When not NULL, this points to binary sequence @a username_len /2 bytes
+   * When not NULL, this points to binary sequence @a userhash_hex_len /2 bytes
    * long.
-   * The valid size should be #MHD_digest_get_hash_size(algo) bytes.
+   * The valid size should be #MHD_digest_get_hash_size(algo3) bytes.
    * @warning This is binary data, no zero termination.
    * @warning To avoid buffer overruns, always check the size of the data 
before
    *          use, because @a userhash_bin can point even to zero-sized
@@ -4976,7 +5013,7 @@ struct MHD_DigestAuthInfo
    * The nc parameter value.
    * Can be used by application to limit the number of nonce re-uses. If @a nc
    * is higher than application wants to allow, then auth required response 
with
-   * 'stale=true' could be used to force client to get the fresh 'nonce'.
+   * 'stale=true' could be used to force client to retry with the fresh 
'nonce'.
    * If not specified by client or does not have hexadecimal digits only, the
    * value is #MHD_DIGEST_AUTH_INVALID_NC_VALUE.
    */
@@ -5007,7 +5044,7 @@ MHD_digest_auth_get_request_info3 (struct MHD_Connection 
*connection);
  *
  * Application may modify buffers as needed until #MHD_free() is called for
  * pointer to this structure
- * @note Available since #MHD_VERSION 0x00097534
+ * @note Available since #MHD_VERSION 0x00097537
  */
 struct MHD_DigestAuthUsernameInfo
 {
@@ -5028,12 +5065,12 @@ struct MHD_DigestAuthUsernameInfo
 
   /**
    * The username string.
-   * For userhash this is unqoted string without decoding of the
-   * hexadecimal digits (as provided by client).
+   * Used only if username type is standard or extended, always NULL otherwise.
    * If extended notation is used, this string is pct-decoded string
    * with charset and language tag removed (i.e. it is original username
    * extracted from the extended notation).
-   * @sa #MHD_digest_auth_calc_userhash_hex()
+   * When userhash is used by the client, this member is NULL and
+   * @a userhash_hex is set.
    */
   char *username;
 
@@ -5043,12 +5080,28 @@ struct MHD_DigestAuthUsernameInfo
    */
   size_t username_len;
 
+  /**
+   * The userhash string.
+   * Valid only if username type is userhash.
+   * This is unqoted string without decoding of the hexadecimal
+   * digits (as provided by the client).
+   * @sa #MHD_digest_auth_calc_userhash_hex()
+   */
+  char *userhash_hex;
+
+  /**
+   * The length of the @a userhash_hex in characters.
+   * The valid size should be #MHD_digest_get_hash_size(algo3) * 2 characters.
+   * When the @a userhash_hex is NULL, this member is always zero.
+   */
+  size_t userhash_hex_len;
+
   /**
    * The userhash decoded to binary form.
    * Used only if username type is userhash, always NULL otherwise.
-   * When not NULL, this points to binary sequence @a username_len /2 bytes
+   * When not NULL, this points to binary sequence @a userhash_hex_len /2 bytes
    * long.
-   * The valid size should be #MHD_digest_get_hash_size(algo) bytes.
+   * The valid size should be #MHD_digest_get_hash_size(algo3) bytes.
    * @warning This is binary data, no zero termination.
    * @warning To avoid buffer overruns, always check the size of the data 
before
    *          use, because @a userhash_bin can point even to zero-sized
@@ -5270,7 +5323,8 @@ MHD_digest_auth_calc_userdigest (enum MHD_DigestAuthAlgo3 
algo3,
  *                   see #MHD_digest_auth_calc_userdigest()
  * @param userdigest_size the size of the @a userdigest in bytes, must match 
the
  *                        hashing algorithm (see #MHD_MD5_DIGEST_SIZE,
- *                        #MHD_SHA256_DIGEST_SIZE, #MHD_digest_get_hash_size())
+ *                        #MHD_SHA256_DIGEST_SIZE, #MHD_SHA512_256_DIGEST_SIZE,
+ *                        #MHD_digest_get_hash_size())
  * @param nonce_timeout the period of seconds since nonce generation, when
  *                      the nonce is recognised as valid and not stale.
  * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc
@@ -5280,9 +5334,9 @@ MHD_digest_auth_calc_userdigest (enum MHD_DigestAuthAlgo3 
algo3,
  * @param mqop the QOP to use
  * @param malgo3 digest algorithms allowed to use, fail if algorithm used
  *               by the client is not allowed by this parameter;
- *               both MD5-based and SHA-256-based algorithms cannot be used at
- *               the same time for this function as @a userdigest_size must
- *               match specified algorithm
+ *               more than one base algorithms (MD5, SHA-256, SHA-512/256)
+ *               cannot be used at the same time for this function
+ *               as @a userdigest must match specified algorithm
  * @return #MHD_DAUTH_OK if authenticated,
  *         the error code otherwise
  * @sa #MHD_digest_auth_calc_userdigest()
@@ -5390,10 +5444,11 @@ MHD_queue_auth_required_response3 (struct 
MHD_Connection *connection,
  *
  * @param connection The MHD connection structure
  * @return NULL if no username could be found, username provided as
- *         "userhash" or memory allocation error occurred;
+ *         "userhash", extended notation broken or memory allocation error
+ *         occurs;
  *         a pointer to the username if found, free using #MHD_free().
  * @warning Returned value must be freed by #MHD_free().
- * @deprecated use MHD_digest_auth_get_username3()
+ * @sa #MHD_digest_auth_get_username3()
  * @ingroup authentication
  */
 _MHD_EXTERN char *
@@ -6037,7 +6092,8 @@ enum MHD_FEATURE
   /**
    * Get whether the MD5-based hashing algorithms are supported for Digest
    * Authorization.
-   * Currently it is always supported if Digest Auth module is built.
+   * Currently it is always supported if Digest Auth module is built
+   * unless manually disabled in a custom build.
    * @note Available since #MHD_VERSION 0x00097527
    */
   MHD_FEATURE_DIGEST_AUTH_MD5 = 26,
@@ -6046,7 +6102,7 @@ enum MHD_FEATURE
    * Get whether the SHA-256-based hashing algorithms are supported for Digest
    * Authorization.
    * It it always supported since #MHD_VERSION 0x00096200 if Digest Auth
-   * module is built.
+   * module is built unless manually disabled in a custom build.
    * @note Available since #MHD_VERSION 0x00097527
    */
   MHD_FEATURE_DIGEST_AUTH_SHA256 = 27,
@@ -6054,7 +6110,8 @@ enum MHD_FEATURE
   /**
    * Get whether the SHA-512/256-based hashing algorithms are supported
    * for Digest Authorization.
-   * Currently it is always not supported.
+   * It it always supported since #MHD_VERSION 0x00097539 if Digest Auth
+   * module is built unless manually disabled in a custom build.
    * @note Available since #MHD_VERSION 0x00097536
    */
   MHD_FEATURE_DIGEST_AUTH_SHA512_256 = 28,
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index fbc545eb..10a32f59 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -168,10 +168,20 @@ endif
 if ENABLE_DAUTH
 libmicrohttpd_la_SOURCES += \
   digestauth.c digestauth.h \
-  mhd_bithelpers.h mhd_byteorder.h mhd_align.h \
-  md5.c md5.h \
+  mhd_bithelpers.h mhd_byteorder.h mhd_align.h
+if ENABLE_MD5
+libmicrohttpd_la_SOURCES += \
+  md5.c md5.h
+endif
+if ENABLE_SHA256
+libmicrohttpd_la_SOURCES += \
   sha256.c sha256.h
 endif
+if ENABLE_SHA512_256
+libmicrohttpd_la_SOURCES += \
+  sha512_256.c sha512_256.h
+endif
+endif
 
 if ENABLE_BAUTH
 libmicrohttpd_la_SOURCES += \
@@ -193,9 +203,7 @@ check_PROGRAMS = \
   test_str_pct \
   test_str_bin_hex \
   test_http_reasons \
-  test_md5 \
   test_sha1 \
-  test_sha256 \
   test_start_stop \
   test_daemon \
   test_response_entries \
@@ -215,6 +223,19 @@ check_PROGRAMS = \
   test_options \
   test_set_panic
 
+if ENABLE_MD5
+check_PROGRAMS += \
+  test_md5
+endif
+if ENABLE_SHA256
+check_PROGRAMS += \
+  test_sha256
+endif
+if ENABLE_SHA512_256
+check_PROGRAMS += \
+  test_sha512_256
+endif
+
 if HAVE_POSIX_THREADS
 if ENABLE_UPGRADE
 if USE_POSIX_THREADS
@@ -448,6 +469,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/daemon.c b/src/microhttpd/daemon.c
index fc7d4da3..fc293a1f 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -8430,20 +8430,20 @@ MHD_is_feature_supported (enum MHD_FEATURE feature)
     return MHD_NO;
 #endif
   case MHD_FEATURE_DIGEST_AUTH_MD5:
-#ifdef DAUTH_SUPPORT
+#if defined(DAUTH_SUPPORT) && defined(MHD_MD5_SUPPORT)
     return MHD_YES;
 #else
     return MHD_NO;
 #endif
   case MHD_FEATURE_DIGEST_AUTH_SHA256:
-#ifdef DAUTH_SUPPORT
+#if defined(DAUTH_SUPPORT) && defined(MHD_SHA256_SUPPORT)
     return MHD_YES;
 #else
     return MHD_NO;
 #endif
   case MHD_FEATURE_DIGEST_AUTH_SHA512_256:
-#ifdef DAUTH_SUPPORT
-    return MHD_NO;
+#if defined(DAUTH_SUPPORT) && defined(MHD_SHA512_256_SUPPORT)
+    return MHD_YES;
 #else
     return MHD_NO;
 #endif
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index fac3e280..1155e6ff 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -33,8 +33,15 @@
 #include "mhd_limits.h"
 #include "internal.h"
 #include "response.h"
-#include "md5.h"
-#include "sha256.h"
+#ifdef MHD_MD5_SUPPORT
+#  include "md5.h"
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
+#  include "sha256.h"
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+#  include "sha512_256.h"
+#endif /* MHD_SHA512_256_SUPPORT */
 #include "mhd_locks.h"
 #include "mhd_mono_clock.h"
 #include "mhd_str.h"
@@ -86,12 +93,38 @@
   ((digest_size) * 2 + TIMESTAMP_CHARS_LEN)
 
 
+#ifdef MHD_SHA512_256_SUPPORT
+/**
+ * Maximum size of any digest hash supported by MHD.
+ * (SHA-512/256 > MD5).
+ */
+#define MAX_DIGEST SHA512_256_DIGEST_SIZE
+
+/**
+ * The common size of SHA-256 digest and SHA-512/256 digest
+ */
+#define SHA256_SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_SIZE
+#elif defined(MHD_SHA256_SUPPORT)
 /**
  * Maximum size of any digest hash supported by MHD.
  * (SHA-256 > MD5).
  */
 #define MAX_DIGEST SHA256_DIGEST_SIZE
 
+/**
+ * The common size of SHA-256 digest and SHA-512/256 digest
+ */
+#define SHA256_SHA512_256_DIGEST_SIZE SHA256_DIGEST_SIZE
+#elif defined(MHD_MD5_SUPPORT)
+/**
+ * Maximum size of any digest hash supported by MHD.
+ */
+#define MAX_DIGEST MD5_DIGEST_SIZE
+#else  /* ! MHD_MD5_SUPPORT */
+#error At least one hashing algorithm must be enabled
+#endif /* ! MHD_MD5_SUPPORT */
+
+
 /**
  * Macro to avoid using VLAs if the compiler does not support them.
  */
@@ -193,26 +226,54 @@ get_base_digest_algo (enum MHD_DigestAuthAlgo3 algo3)
  * Internal inline version.
  * @param algo3 the algorithm to check
  * @return the size of the digest or zero if the input value is not
- *         recognised/valid
+ *         supported/valid
  */
 _MHD_static_inline size_t
 digest_get_hash_size (enum MHD_DigestAuthAlgo3 algo3)
 {
+#ifdef MHD_MD5_SUPPORT
   mhd_assert (MHD_MD5_DIGEST_SIZE == MD5_DIGEST_SIZE);
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
   mhd_assert (MHD_SHA256_DIGEST_SIZE == SHA256_DIGEST_SIZE);
-  /* Both MD5 and SHA-256 must not be specified at the same time */
-  mhd_assert ( (0 == (((unsigned int) algo3)   \
-                      & ((unsigned int) MHD_DIGEST_BASE_ALGO_MD5))) || \
-               (0 == (((unsigned int) algo3)   \
-                      & ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA256))) );
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+  mhd_assert (MHD_SHA512_256_DIGEST_SIZE == SHA512_256_DIGEST_SIZE);
+#ifdef MHD_SHA256_SUPPORT
+  mhd_assert (SHA256_DIGEST_SIZE == SHA512_256_DIGEST_SIZE);
+#endif /* MHD_SHA256_SUPPORT */
+#endif /* MHD_SHA512_256_SUPPORT */
+  /* Only one algorithm must be specified */
+  mhd_assert (1 == \
+              (((0 != (algo3 & MHD_DIGEST_BASE_ALGO_MD5)) ? 1 : 0)   \
+               + ((0 != (algo3 & MHD_DIGEST_BASE_ALGO_SHA256)) ? 1 : 0)   \
+               + ((0 != (algo3 & MHD_DIGEST_BASE_ALGO_SHA512_256)) ? 1 : 0)));
+#ifdef MHD_MD5_SUPPORT
   if (0 != (((unsigned int) algo3)
             & ((unsigned int) MHD_DIGEST_BASE_ALGO_MD5)))
     return MHD_MD5_DIGEST_SIZE;
-  else if (0 != (((unsigned int) algo3)
-                 & ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA256)))
+  else
+#endif /* MHD_MD5_SUPPORT */
+#if defined(MHD_SHA256_SUPPORT) && defined(MHD_SHA512_256_SUPPORT)
+  if (0 != (((unsigned int) algo3)
+            & ( ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA256)
+                | ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA512_256))))
+    return MHD_SHA256_DIGEST_SIZE; /* The same as SHA512_256_DIGEST_SIZE */
+  else
+#elif defined(MHD_SHA256_SUPPORT)
+  if (0 != (((unsigned int) algo3)
+            & ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA256)))
     return MHD_SHA256_DIGEST_SIZE;
+  else
+#elif defined(MHD_SHA512_256_SUPPORT)
+  if (0 != (((unsigned int) algo3)
+            & ((unsigned int) MHD_DIGEST_BASE_ALGO_SHA512_256)))
+    return MHD_SHA512_256_DIGEST_SIZE;
+  else
+#endif /* MHD_SHA512_256_SUPPORT */
+    (void) 0; /* Unsupported algorithm */
 
-  return 0; /* Wrong input */
+  return 0; /* Wrong input or unsupported algorithm */
 }
 
 
@@ -223,8 +284,8 @@ digest_get_hash_size (enum MHD_DigestAuthAlgo3 algo3)
  * and other parameters which size depends on used hash algorithm.
  * @param algo3 the algorithm to check
  * @return the size of the digest (either #MHD_MD5_DIGEST_SIZE or
- *         #MHD_SHA256_DIGEST_SIZE) or zero if the input value is not
- *         recognised/valid
+ *         #MHD_SHA256_DIGEST_SIZE/MHD_SHA512_256_DIGEST_SIZE)
+ *         or zero if the input value is not supported or not valid
  * @sa #MHD_digest_auth_calc_userdigest()
  * @sa #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_calc_userhash_hex()
  * @note Available since #MHD_VERSION 0x00097526
@@ -242,8 +303,15 @@ MHD_digest_get_hash_size (enum MHD_DigestAuthAlgo3 algo3)
  */
 union DigestCtx
 {
+#ifdef MHD_MD5_SUPPORT
   struct MD5Context md5_ctx;
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
   struct Sha256Ctx sha256_ctx;
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+  struct Sha512_256Ctx sha512_256_ctx;
+#endif /* MHD_SHA512_256_SUPPORT */
 };
 
 /**
@@ -282,10 +350,18 @@ _MHD_static_inline unsigned int
 digest_get_size (struct DigestAlgorithm *da)
 {
   mhd_assert (da->setup);
+#ifdef MHD_MD5_SUPPORT
   if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
     return MD5_DIGEST_SIZE;
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
   if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
     return SHA256_DIGEST_SIZE;
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+  if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
+    return SHA512_256_DIGEST_SIZE;
+#endif /* MHD_SHA512_256_SUPPORT */
   mhd_assert (0); /* May not happen */
   return 0;
 }
@@ -307,8 +383,17 @@ digest_setup (struct DigestAlgorithm *da,
   da->inited = false;
   da->digest_calculated = false;
 #endif /* _DEBUG */
-  if ((MHD_DIGEST_BASE_ALGO_MD5 == algo) ||
-      (MHD_DIGEST_BASE_ALGO_SHA256 == algo))
+  if (false
+#ifdef MHD_MD5_SUPPORT
+      || (MHD_DIGEST_BASE_ALGO_MD5 == algo)
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
+      || (MHD_DIGEST_BASE_ALGO_SHA256 == algo)
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+      || (MHD_DIGEST_BASE_ALGO_SHA512_256 == algo)
+#endif /* MHD_SHA512_256_SUPPORT */
+      )
   {
     da->algo = algo;
 #ifdef _DEBUG
@@ -316,8 +401,7 @@ digest_setup (struct DigestAlgorithm *da,
 #endif /* _DEBUG */
     return true;
   }
-  mhd_assert (0); /* Bad parameter */
-  return false;
+  return false; /* Bad or unsupported algorithm */
 }
 
 
@@ -332,6 +416,7 @@ digest_init (struct DigestAlgorithm *da)
 #ifdef _DEBUG
   da->digest_calculated = false;
 #endif
+#ifdef MHD_MD5_SUPPORT
   if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
   {
     MHD_MD5Init (&da->ctx.md5_ctx);
@@ -339,7 +424,10 @@ digest_init (struct DigestAlgorithm *da)
     da->inited = true;
 #endif
   }
-  else if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
+  else
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
+  if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
   {
     MHD_SHA256_init (&da->ctx.sha256_ctx);
 #ifdef _DEBUG
@@ -347,6 +435,17 @@ digest_init (struct DigestAlgorithm *da)
 #endif
   }
   else
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+  if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
+  {
+    MHD_SHA512_256_init (&da->ctx.sha512_256_ctx);
+#ifdef _DEBUG
+    da->inited = true;
+#endif
+  }
+  else
+#endif /* MHD_SHA512_256_SUPPORT */
   {
 #ifdef _DEBUG
     da->inited = false;
@@ -369,12 +468,23 @@ digest_update (struct DigestAlgorithm *da,
 {
   mhd_assert (da->inited);
   mhd_assert (! da->digest_calculated);
+#ifdef MHD_MD5_SUPPORT
   if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
     MHD_MD5Update (&da->ctx.md5_ctx, (const uint8_t *) data, length);
-  else if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
+  else
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
+  if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
     MHD_SHA256_update (&da->ctx.sha256_ctx, (const uint8_t *) data, length);
   else
-    mhd_assert (0); /* May not happen */
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+  if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
+    MHD_SHA512_256_update (&da->ctx.sha512_256_ctx,
+                           (const uint8_t *) data, length);
+  else
+#endif /* MHD_SHA512_256_SUPPORT */
+  mhd_assert (0);   /* May not happen */
 }
 
 
@@ -416,12 +526,22 @@ digest_calc_hash (struct DigestAlgorithm *da, uint8_t 
*digest)
 {
   mhd_assert (da->inited);
   mhd_assert (! da->digest_calculated);
+#ifdef MHD_MD5_SUPPORT
   if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
     MHD_MD5Final (&da->ctx.md5_ctx, digest);
-  else if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
+  else
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
+  if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
     MHD_SHA256_finish (&da->ctx.sha256_ctx, digest);
   else
-    mhd_assert (0); /* May not happen */
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+  if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
+    MHD_SHA512_256_finish (&da->ctx.sha512_256_ctx, digest);
+  else
+#endif /* MHD_SHA512_256_SUPPORT */
+  mhd_assert (0);   /* May not happen */
 #ifdef _DEBUG
   da->digest_calculated = true;
 #endif
@@ -444,8 +564,14 @@ get_nonce_timestamp (const char *const nonce,
   if (0 == noncelen)
     noncelen = strlen (nonce);
 
-  if ( (NONCE_STD_LEN (SHA256_DIGEST_SIZE) != noncelen) &&
-       (NONCE_STD_LEN (MD5_DIGEST_SIZE) != noncelen) )
+  if (true
+#ifdef MHD_MD5_SUPPORT
+      && (NONCE_STD_LEN (MD5_DIGEST_SIZE) != noncelen)
+#endif /* MHD_MD5_SUPPORT */
+#if defined(MHD_SHA256_SUPPORT) || defined(MHD_SHA512_256_SUPPORT)
+      && (NONCE_STD_LEN (SHA256_SHA512_256_DIGEST_SIZE) != noncelen)
+#endif /* MHD_SHA256_SUPPORT */
+      )
     return false;
 
   if (TIMESTAMP_CHARS_LEN !=
@@ -801,37 +927,47 @@ get_rq_uname (const struct MHD_RqDAuth *params,
   mhd_assert (MHD_DIGEST_AUTH_UNAME_TYPE_INVALID != uname_type);
   mhd_assert (MHD_DIGEST_AUTH_UNAME_TYPE_MISSING != uname_type);
 
-  if ( (MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD == uname_type) ||
-       (MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH == uname_type) )
+  uname_info->username = NULL;
+  uname_info->username_len = 0;
+  uname_info->userhash_hex = NULL;
+  uname_info->userhash_hex_len = 0;
+  uname_info->userhash_bin = NULL;
+
+  if (MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD == uname_type)
   {
     uname_info->username = (char *) (buf + buf_used);
     uname_info->username_len =
       get_rq_param_unquoted_copy_z (&params->username,
                                     uname_info->username);
     buf_used += uname_info->username_len + 1;
-    if (MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH == uname_type)
+    uname_info->uname_type = MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD;
+  }
+  else if (MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH == uname_type)
+  {
+    size_t res;
+
+    uname_info->userhash_hex = (char *) (buf + buf_used);
+    uname_info->userhash_hex_len =
+      get_rq_param_unquoted_copy_z (&params->username,
+                                    uname_info->userhash_hex);
+    buf_used += uname_info->userhash_hex_len + 1;
+    uname_info->userhash_bin = (uint8_t *) (buf + buf_used);
+    res = MHD_hex_to_bin (uname_info->userhash_hex,
+                          uname_info->userhash_hex_len,
+                          uname_info->userhash_bin);
+    if (res != uname_info->username_len / 2)
     {
-      size_t res;
-      uint8_t *const bin_data = (uint8_t *) (buf + buf_used);
-      res = MHD_hex_to_bin (uname_info->username,
-                            uname_info->username_len,
-                            bin_data);
-      if (res != uname_info->username_len / 2)
-      {
-        uname_info->userhash_bin = NULL;
-        uname_info->uname_type = MHD_DIGEST_AUTH_UNAME_TYPE_INVALID;
-      }
-      else
-      {
-        /* Avoid pointers outside allocated region when the size is zero */
-        uname_info->userhash_bin = (0 != res) ?
-                                   bin_data : (uint8_t *) uname_info->username;
-        uname_info->uname_type = MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH;
-        buf_used += res;
-      }
+      uname_info->userhash_bin = NULL;
+      uname_info->uname_type = MHD_DIGEST_AUTH_UNAME_TYPE_INVALID;
     }
     else
-      uname_info->uname_type = MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD;
+    {
+      /* Avoid pointers outside allocated region when the size is zero */
+      if (0 == res)
+        uname_info->userhash_bin = (uint8_t *) uname_info->username;
+      uname_info->uname_type = MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH;
+      buf_used += res;
+    }
   }
   else if (MHD_DIGEST_AUTH_UNAME_TYPE_EXTENDED == uname_type)
   {
@@ -1077,15 +1213,16 @@ MHD_digest_auth_get_username3 (struct MHD_Connection 
*connection)
 /**
  * Get the username from the authorization header sent by the client
  *
- * This function support username in standard and extended notations.
+ * This function supports username in standard and extended notations.
  * "userhash" is not supported by this function.
  *
  * @param connection The MHD connection structure
  * @return NULL if no username could be found, username provided as
- *         "userhash" or memory allocation error occurs;
+ *         "userhash", extended notation broken or memory allocation error
+ *         occurs;
  *         a pointer to the username if found, free using #MHD_free().
  * @warning Returned value must be freed by #MHD_free().
- * @deprecated use MHD_digest_auth_get_username3()
+ * @sa #MHD_digest_auth_get_username3()
  * @ingroup authentication
  */
 _MHD_EXTERN char *
@@ -2202,19 +2339,43 @@ digest_auth_check_all_inner (struct MHD_Connection 
*connection,
 #endif /* HAVE_MESSAGES */
     return MHD_DAUTH_WRONG_ALGO;
   }
+#ifndef MHD_MD5_SUPPORT
+  if (0 != (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_MD5))
+  {
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (connection->daemon,
+              _ ("The MD5 algorithm is not supported by this MHD build.\n"));
+#endif /* HAVE_MESSAGES */
+    return MHD_DAUTH_WRONG_ALGO;
+  }
+#endif /* ! MHD_MD5_SUPPORT */
+#ifndef MHD_SHA256_SUPPORT
+  if (0 != (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_SHA256))
+  {
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (connection->daemon,
+              _ ("The SHA-256 algorithm is not supported by "
+                 "this MHD build.\n"));
+#endif /* HAVE_MESSAGES */
+    return MHD_DAUTH_WRONG_ALGO;
+  }
+#endif /* ! MHD_SHA256_SUPPORT */
+#ifndef MHD_SHA512_256_SUPPORT
   if (0 != (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_SHA512_256))
   {
 #ifdef HAVE_MESSAGES
     MHD_DLOG (connection->daemon,
-              _ ("The SHA-512/256 algorithm is not supported.\n"));
+              _ ("The SHA-512/256 algorithm is not supported by "
+                 "this MHD build.\n"));
 #endif /* HAVE_MESSAGES */
     return MHD_DAUTH_WRONG_ALGO;
   }
+#endif /* ! MHD_SHA512_256_SUPPORT */
   if (! digest_setup (&da, get_base_digest_algo (c_algo)))
     MHD_PANIC (_ ("Wrong 'malgo3' value, API violation"));
   /* Check 'mqop' value */
   c_qop = params->qop;
-  /* Check whether client's algorithm is allowed by function parameter */
+  /* Check whether client's QOP is allowed by function parameter */
   if (((unsigned int) c_qop) !=
       (((unsigned int) c_qop) & ((unsigned int) mqop)))
     return MHD_DAUTH_WRONG_QOP;
@@ -2230,8 +2391,8 @@ digest_auth_check_all_inner (struct MHD_Connection 
*connection,
   if ((MHD_DIGEST_AUTH_QOP_NONE == c_qop) &&
       (0 == (((unsigned int) c_algo) & MHD_DIGEST_BASE_ALGO_MD5)))
     MHD_DLOG (connection->daemon,
-              _ ("RFC2069 with SHA-256 algorithm is non-standard " \
-                 "extension.\n"));
+              _ ("RFC2069 with SHA-256 or SHA-512/256 algorithm is " \
+                 "non-standard extension.\n"));
 #endif /* HAVE_MESSAGES */
 
   digest_size = digest_get_size (&da);
@@ -2765,7 +2926,8 @@ MHD_digest_auth_check3 (struct MHD_Connection *connection,
  *                   see #MHD_digest_auth_calc_userdigest()
  * @param userdigest_size the size of the @a userdigest in bytes, must match 
the
  *                        hashing algorithm (see #MHD_MD5_DIGEST_SIZE,
- *                        #MHD_SHA256_DIGEST_SIZE, #MHD_digest_get_hash_size())
+ *                        #MHD_SHA256_DIGEST_SIZE, #MHD_SHA512_256_DIGEST_SIZE,
+ *                        #MHD_digest_get_hash_size())
  * @param nonce_timeout the period of seconds since nonce generation, when
  *                      the nonce is recognised as valid and not stale.
  * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc
@@ -2775,9 +2937,9 @@ MHD_digest_auth_check3 (struct MHD_Connection *connection,
  * @param mqop the QOP to use
  * @param malgo3 digest algorithms allowed to use, fail if algorithm used
  *               by the client is not allowed by this parameter;
- *               both MD5-based and SHA-256-based algorithms cannot be used at
- *               the same time for this function as @a userdigest_size must
- *               match specified algorithm
+ *               more than one base algorithms (MD5, SHA-256, SHA-512/256)
+ *               cannot be used at the same time for this function
+ *               as @a userdigest must match specified algorithm
  * @return #MHD_DAUTH_OK if authenticated,
  *         the error code otherwise
  * @sa #MHD_digest_auth_calc_userdigest()
@@ -2795,13 +2957,46 @@ MHD_digest_auth_check_digest3 (struct MHD_Connection 
*connection,
                                enum MHD_DigestAuthMultiQOP mqop,
                                enum MHD_DigestAuthMultiAlgo3 malgo3)
 {
-  if (((unsigned int) (MHD_DIGEST_BASE_ALGO_MD5
-                       | MHD_DIGEST_BASE_ALGO_SHA256)) ==
-      (((unsigned int) malgo3) & (MHD_DIGEST_BASE_ALGO_MD5
-                                  | MHD_DIGEST_BASE_ALGO_SHA256)))
-    MHD_PANIC (_ ("Wrong 'malgo3' value, both MD5 and SHA-256 specified, "
+  if (1 != (((0 != (malgo3 & MHD_DIGEST_BASE_ALGO_MD5)) ? 1 : 0)
+            + ((0 != (malgo3 & MHD_DIGEST_BASE_ALGO_SHA256)) ? 1 : 0)
+            + ((0 != (malgo3 & MHD_DIGEST_BASE_ALGO_SHA512_256)) ? 1 : 0)))
+    MHD_PANIC (_ ("Wrong 'malgo3' value, only one base hashing algorithm " \
+                  "(MD5, SHA-256 or SHA-512/256) must be specified, " \
                   "API violation"));
 
+#ifndef MHD_MD5_SUPPORT
+  if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_MD5))
+  {
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (connection->daemon,
+              _ ("The MD5 algorithm is not supported by this MHD build.\n"));
+#endif /* HAVE_MESSAGES */
+    return MHD_DAUTH_WRONG_ALGO;
+  }
+#endif /* ! MHD_MD5_SUPPORT */
+#ifndef MHD_SHA256_SUPPORT
+  if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA256))
+  {
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (connection->daemon,
+              _ ("The SHA-256 algorithm is not supported by "
+                 "this MHD build.\n"));
+#endif /* HAVE_MESSAGES */
+    return MHD_DAUTH_WRONG_ALGO;
+  }
+#endif /* ! MHD_SHA256_SUPPORT */
+#ifndef MHD_SHA512_256_SUPPORT
+  if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA512_256))
+  {
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (connection->daemon,
+              _ ("The SHA-512/256 algorithm is not supported by "
+                 "this MHD build.\n"));
+#endif /* HAVE_MESSAGES */
+    return MHD_DAUTH_WRONG_ALGO;
+  }
+#endif /* ! MHD_SHA512_256_SUPPORT */
+
   if (digest_get_hash_size ((enum MHD_DigestAuthAlgo3) malgo3) !=
       userdigest_size)
     MHD_PANIC (_ ("Wrong 'userdigest_size' value, does not match 'malgo3', "
@@ -3061,12 +3256,45 @@ MHD_queue_auth_required_response3 (struct 
MHD_Connection *connection,
 #endif /* HAVE_MESSAGES */
     return MHD_NO;
   }
+#ifndef MHD_SHA512_256_SUPPORT
+  if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA512_256))
+  {
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (connection->daemon,
+              _ ("The SHA-512/256 algorithm is not enabled.\n"));
+#endif /* HAVE_MESSAGES */
+    return MHD_NO;
+  }
+#endif /* ! MHD_SHA512_256_SUPPORT */
+#ifdef MHD_MD5_SUPPORT
   if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_MD5))
     s_algo = MHD_DIGEST_AUTH_ALGO3_MD5;
-  else if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA256))
+  else
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
+  if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA256))
     s_algo = MHD_DIGEST_AUTH_ALGO3_SHA256;
   else
-    MHD_PANIC (_ ("Wrong 'malgo3' value, API violation"));
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+  if (0 != (((unsigned int) malgo3) & MHD_DIGEST_BASE_ALGO_SHA512_256))
+    s_algo = MHD_DIGEST_AUTH_ALGO3_SHA512_256;
+  else
+#endif /* MHD_SHA512_256_SUPPORT */
+  {
+    if (0 == (((unsigned int) malgo3)
+              & (MHD_DIGEST_BASE_ALGO_MD5 | MHD_DIGEST_BASE_ALGO_SHA512_256
+                 | MHD_DIGEST_BASE_ALGO_SHA512_256)))
+      MHD_PANIC (_ ("Wrong 'malgo3' value, API violation"));
+    else
+    {
+#ifdef HAVE_MESSAGES
+      MHD_DLOG (connection->daemon,
+                _ ("No requested algorithm is supported by this MHD 
build.\n"));
+#endif /* HAVE_MESSAGES */
+    }
+    return MHD_NO;
+  }
 
   if (((unsigned int) mqop) !=
       (((unsigned int) mqop) & MHD_DIGEST_AUTH_MULT_QOP_ANY_NON_INT))
@@ -3084,8 +3312,8 @@ MHD_queue_auth_required_response3 (struct MHD_Connection 
*connection,
                    "are not compatible with RFC2069 and ignored.\n"));
     if (0 == (((unsigned int) s_algo) & MHD_DIGEST_BASE_ALGO_MD5))
       MHD_DLOG (connection->daemon,
-                _ ("RFC2069 with SHA-256 algorithm is non-standard " \
-                   "extension.\n"));
+                _ ("RFC2069 with SHA-256 or SHA-512/256 algorithm is " \
+                   "non-standard extension.\n"));
 #endif
     userhash_support = 0;
     prefer_utf8 = 0;
@@ -3130,12 +3358,22 @@ MHD_queue_auth_required_response3 (struct 
MHD_Connection *connection,
       (0 == (((unsigned int) s_algo) & MHD_DIGEST_BASE_ALGO_MD5)))
   {
     buf_size += MHD_STATICSTR_LEN_ (prefix_algo) + 2; /* 2 for ', ' */
+#ifdef MHD_MD5_SUPPORT
     if (MHD_DIGEST_AUTH_ALGO3_MD5 == s_algo)
       buf_size += MHD_STATICSTR_LEN_ (_MHD_MD5_TOKEN);
-    else if (MHD_DIGEST_AUTH_ALGO3_SHA256 == s_algo)
+    else
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
+    if (MHD_DIGEST_AUTH_ALGO3_SHA256 == s_algo)
       buf_size += MHD_STATICSTR_LEN_ (_MHD_SHA256_TOKEN);
     else
-      mhd_assert (0);
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+    if (MHD_DIGEST_AUTH_ALGO3_SHA512_256 == s_algo)
+      buf_size += MHD_STATICSTR_LEN_ (_MHD_SHA512_256_TOKEN);
+    else
+#endif /* MHD_SHA512_256_SUPPORT */
+    mhd_assert (0);
   }
   /* 'nonce="xxxx", ' */
   buf_size += MHD_STATICSTR_LEN_ (prefix_nonce) + 3; /* 3 for '", ' */
@@ -3232,18 +3470,34 @@ MHD_queue_auth_required_response3 (struct 
MHD_Connection *connection,
     memcpy (buf + p, prefix_algo,
             MHD_STATICSTR_LEN_ (prefix_algo));
     p += MHD_STATICSTR_LEN_ (prefix_algo);
+#ifdef MHD_MD5_SUPPORT
     if (MHD_DIGEST_AUTH_ALGO3_MD5 == s_algo)
     {
       memcpy (buf + p, _MHD_MD5_TOKEN,
               MHD_STATICSTR_LEN_ (_MHD_MD5_TOKEN));
       p += MHD_STATICSTR_LEN_ (_MHD_MD5_TOKEN);
     }
-    else if (MHD_DIGEST_AUTH_ALGO3_SHA256 == s_algo)
+    else
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
+    if (MHD_DIGEST_AUTH_ALGO3_SHA256 == s_algo)
     {
       memcpy (buf + p, _MHD_SHA256_TOKEN,
               MHD_STATICSTR_LEN_ (_MHD_SHA256_TOKEN));
       p += MHD_STATICSTR_LEN_ (_MHD_SHA256_TOKEN);
     }
+    else
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+    if (MHD_DIGEST_AUTH_ALGO3_SHA512_256 == s_algo)
+    {
+      memcpy (buf + p, _MHD_SHA512_256_TOKEN,
+              MHD_STATICSTR_LEN_ (_MHD_SHA512_256_TOKEN));
+      p += MHD_STATICSTR_LEN_ (_MHD_SHA512_256_TOKEN);
+    }
+    else
+#endif /* MHD_SHA512_256_SUPPORT */
+    mhd_assert (0);
     buf[p++] = ',';
     buf[p++] = ' ';
   }
@@ -3371,7 +3625,7 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection 
*connection,
     algo3 = MHD_DIGEST_AUTH_MULT_ALGO3_MD5;
   else if (MHD_DIGEST_ALG_SHA256 == algo)
     algo3 = MHD_DIGEST_AUTH_MULT_ALGO3_SHA256;
-  else if ((MHD_DIGEST_ALG_MD5 == algo) || (MHD_DIGEST_ALG_AUTO == algo))
+  else if (MHD_DIGEST_ALG_AUTO == algo)
     algo3 = MHD_DIGEST_AUTH_MULT_ALGO3_ANY_NON_SESSION;
   else
     MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
diff --git a/src/microhttpd/gen_auth.c b/src/microhttpd/gen_auth.c
index c86d35ba..c10e4bee 100644
--- a/src/microhttpd/gen_auth.c
+++ b/src/microhttpd/gen_auth.c
@@ -300,23 +300,23 @@ get_rq_dauth_algo (const struct MHD_RqDAuthParam *const 
algo_param)
     if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \
                                                algo_param->value.len, \
                                                _MHD_MD5_TOKEN _MHD_SESS_TOKEN))
-      return MHD_DIGEST_AUTH_ALGO3_MD5_SESSION;
+      return MHD_DIGEST_AUTH_ALGO3_SHA512_256;
     if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \
                                                algo_param->value.len, \
-                                               _MHD_SHA256_TOKEN \
+                                               _MHD_SHA512_256_TOKEN \
                                                _MHD_SESS_TOKEN))
-      return MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION;
 
-    /* Algorithms below are not supported by MHD for authentication */
+      /* Algorithms below are not supported by MHD for authentication */
 
+      return MHD_DIGEST_AUTH_ALGO3_MD5_SESSION;
     if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \
                                                algo_param->value.len, \
-                                               _MHD_SHA512_256_TOKEN))
-      return MHD_DIGEST_AUTH_ALGO3_SHA512_256;
+                                               _MHD_SHA256_TOKEN \
+                                               _MHD_SESS_TOKEN))
+      return MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION;
     if (MHD_str_equal_caseless_quoted_s_bin_n (algo_param->value.str, \
                                                algo_param->value.len, \
-                                               _MHD_SHA512_256_TOKEN \
-                                               _MHD_SESS_TOKEN))
+                                               _MHD_SHA512_256_TOKEN))
       return MHD_DIGEST_AUTH_ALGO3_SHA512_256_SESSION;
 
     /* No known algorithm has been detected */
@@ -331,6 +331,13 @@ get_rq_dauth_algo (const struct MHD_RqDAuthParam *const 
algo_param)
                                        algo_param->value.str, \
                                        algo_param->value.len))
     return MHD_DIGEST_AUTH_ALGO3_SHA256;
+  if (MHD_str_equal_caseless_s_bin_n_ (_MHD_SHA512_256_TOKEN, \
+                                       algo_param->value.str, \
+                                       algo_param->value.len))
+    return MHD_DIGEST_AUTH_ALGO3_SHA512_256;
+
+  /* Algorithms below are not supported by MHD for authentication */
+
   if (MHD_str_equal_caseless_s_bin_n_ (_MHD_MD5_TOKEN _MHD_SESS_TOKEN, \
                                        algo_param->value.str, \
                                        algo_param->value.len))
@@ -339,13 +346,6 @@ get_rq_dauth_algo (const struct MHD_RqDAuthParam *const 
algo_param)
                                        algo_param->value.str, \
                                        algo_param->value.len))
     return MHD_DIGEST_AUTH_ALGO3_SHA256_SESSION;
-
-  /* Algorithms below are not supported by MHD for authentication */
-
-  if (MHD_str_equal_caseless_s_bin_n_ (_MHD_SHA512_256_TOKEN, \
-                                       algo_param->value.str, \
-                                       algo_param->value.len))
-    return MHD_DIGEST_AUTH_ALGO3_SHA512_256;
   if (MHD_str_equal_caseless_s_bin_n_ (_MHD_SHA512_256_TOKEN _MHD_SESS_TOKEN, \
                                        algo_param->value.str, \
                                        algo_param->value.len))
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 3fa773a7..adb69b32 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -250,11 +250,15 @@ enum MHD_ConnectionEventLoopInfo
 /**
  * The maximum size of MHD-generated nonce when printed with hexadecimal chars.
  *
- * This is equal to "(32 bytes for SHA-256 nonce plus 6 bytes for timestamp)
- * multiplied by two hex chars per byte".
+ * This is equal to "(32 bytes for SHA-256 (or SHA-512/256) nonce plus 6 bytes
+ * for timestamp) multiplied by two hex chars per byte".
  * Please keep it in sync with digestauth.c
  */
+#if defined(MHD_SHA256_SUPPORT) || defined(MHD_SHA512_256_SUPPORT)
 #define MAX_DIGEST_NONCE_LENGTH ((32 + 6) * 2)
+#else  /* !MHD_SHA256_SUPPORT && !MHD_SHA512_256_SUPPORT */
+#define MAX_DIGEST_NONCE_LENGTH ((16 + 6) * 2)
+#endif /* !MHD_SHA256_SUPPORT && !MHD_SHA512_256_SUPPORT */
 
 /**
  * A structure representing the internal holder of the
@@ -280,7 +284,7 @@ struct MHD_NonceNc
   uint64_t nmask;
 
   /**
-   * Nonce value:
+   * Nonce value
    */
   char nonce[MAX_DIGEST_NONCE_LENGTH + 1];
 
diff --git a/src/microhttpd/mhd_bithelpers.h b/src/microhttpd/mhd_bithelpers.h
index 5cfcc846..94f4e1ab 100644
--- a/src/microhttpd/mhd_bithelpers.h
+++ b/src/microhttpd/mhd_bithelpers.h
@@ -140,7 +140,7 @@ _MHD_PUT_64BIT_LE_SAFE (void *dst, uint64_t value)
   if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN))
     _MHD_PUT_64BIT_LE_SLOW (dst, value);
   else
-#endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */
+#endif /* ! _MHD_PUT_64BIT_LE_UNALIGNED */
   _MHD_PUT_64BIT_LE (dst, value);
 }
 
@@ -230,6 +230,31 @@ _MHD_PUT_64BIT_BE_SAFE (void *dst, uint64_t value)
 }
 
 
+/* _MHD_GET_64BIT_BE (addr)
+ * load 64-bit value located at addr in big endian mode.
+ */
+#if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
+#define _MHD_GET_64BIT_BE(addr)             \
+  (*(const uint64_t*) (addr))
+#elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
+#define _MHD_GET_64BIT_BE(addr)             \
+  _MHD_BYTES_SWAP64 (*(const uint64_t*) (addr))
+#else  /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
+/* Endianness was not detected or non-standard like PDP-endian */
+#define _MHD_GET_64BIT_BE(addr)                           \
+  (   (((uint64_t) (((const uint8_t*) addr)[0])) << 56)   \
+    | (((uint64_t) (((const uint8_t*) addr)[1])) << 48)   \
+    | (((uint64_t) (((const uint8_t*) addr)[2])) << 40)   \
+    | (((uint64_t) (((const uint8_t*) addr)[3])) << 32)   \
+    | (((uint64_t) (((const uint8_t*) addr)[4])) << 24)   \
+    | (((uint64_t) (((const uint8_t*) addr)[5])) << 16)   \
+    | (((uint64_t) (((const uint8_t*) addr)[6])) << 8)    \
+    | ((uint64_t)  (((const uint8_t*) addr)[7])) )
+/* Indicate that _MHD_GET_64BIT_BE does not need aligned pointer */
+#define _MHD_GET_64BIT_BE_ALLOW_UNALIGNED 1
+#endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
+
+
 /* _MHD_PUT_32BIT_BE (addr, value32)
  * put native-endian 32-bit value32 to addr
  * in big-endian mode.
@@ -333,6 +358,37 @@ _MHD_ROTL32 (uint32_t value32, int bits)
 
 #endif /* ! __builtin_rotateleft32 */
 
+
+/**
+ * Rotate right 64-bit value by number of bits.
+ * bits parameter must be more than zero and must be less than 64.
+ */
+#if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
+  defined(__OPTIMIZE__)))
+/* Clang/C2 do not inline this function if optimisations are turned off. */
+#ifndef __clang__
+#pragma intrinsic(_rotr64)
+#endif /* ! __clang__ */
+#define _MHD_ROTR64(value64, bits) \
+  ((uint64_t) _rotr64 ((uint64_t) (value64),(bits)))
+#elif __has_builtin (__builtin_rotateright64)
+#define _MHD_ROTR64(value64, bits) \
+  ((uint64_t) __builtin_rotateright64 ((value64), (bits)))
+#else  /* ! __builtin_rotateright64 */
+_MHD_static_inline uint64_t
+_MHD_ROTR64 (uint64_t value64, int bits)
+{
+  bits %= 64;
+  if (0 == bits)
+    return value64;
+  /* Defined in form which modern compiler could optimise. */
+  return (value64 >> bits) | (value64 << (64 - bits));
+}
+
+
+#endif /* ! __builtin_rotateright64 */
+
+
 #ifdef _MHD_has_builtin_dummy
 /* Remove macro function replacement to avoid misdetection in files which
  * include this header */
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_dauth_userdigest.c 
b/src/microhttpd/test_dauth_userdigest.c
index 3af45156..6b15a282 100644
--- a/src/microhttpd/test_dauth_userdigest.c
+++ b/src/microhttpd/test_dauth_userdigest.c
@@ -123,6 +123,54 @@ static const struct data_sha256 sha256_tests[] = {
     0xcb, 0x14, 0x9c, 0x54, 0xf3, 0x7c, 0xff, 0x37}}
 };
 
+struct data_sha512_256
+{
+  unsigned int line_num;
+  const char *const username;
+  const char *const realm;
+  const char *const password;
+  const uint8_t hash[MHD_SHA512_256_DIGEST_SIZE];
+};
+
+static const struct data_sha512_256 sha512_256_tests[] = {
+  {__LINE__,
+   "u", "r", "p",
+   {0xd5, 0xe8, 0xe7, 0x3b, 0xa3, 0x47, 0xb9, 0xad, 0xf0, 0xe4, 0x7a, 0x9a,
+    0xce, 0x43, 0xb7, 0x08, 0x2a, 0xbc, 0x8d, 0x27, 0x27, 0x2e, 0x38, 0x7d,
+    0x1d, 0x9c, 0xe2, 0x44, 0x25, 0x68, 0x74, 0x04}},
+  {__LINE__,
+   "testuser", "testrealm", "testpass",
+   {0x41, 0x7d, 0xf9, 0x60, 0x7c, 0xc9, 0x60, 0x28, 0x44, 0x74, 0x75, 0xf7,
+    0x7b, 0x78, 0xe7, 0x60, 0xec, 0x9a, 0xe1, 0x62, 0xd4, 0x95, 0x82, 0x61,
+    0x68, 0xa7, 0x94, 0xe8, 0x3b, 0xdf, 0x8d, 0x59}},
+  {__LINE__,  /* Values from testcurl/test_digestauth2.c */
+   "test_user", "TestRealm", "test pass",
+   {0xe7, 0xa1, 0x9e, 0x27, 0xf6, 0x73, 0x88, 0xb2, 0xde, 0xa4, 0xe2, 0x66,
+    0xc5, 0x16, 0x37, 0x17, 0x4d, 0x29, 0xcc, 0xa3, 0xc1, 0xf5, 0xb2, 0x49,
+    0x20, 0xc1, 0x05, 0xc9, 0x20, 0x13, 0x3c, 0x3d}},
+  {__LINE__,
+   "Mufasa", "myhost@testrealm.com", "CircleOfLife",
+   {0x44, 0xbc, 0xd2, 0xb1, 0x1f, 0x6f, 0x7d, 0xd3, 0xae, 0xa6, 0x66, 0x8a,
+    0x24, 0x84, 0x4b, 0x87, 0x7d, 0xe1, 0x80, 0x24, 0x9a, 0x26, 0x6b, 0xe6,
+    0xdb, 0x7f, 0xe3, 0xc8, 0x7a, 0xf9, 0x75, 0x64}},
+  {__LINE__,
+   "Mufasa", "myhost@example.com", "Circle Of Life",
+   {0xd5, 0xf6, 0x25, 0x7c, 0x64, 0xe4, 0x01, 0xd2, 0x87, 0xd5, 0xaa, 0x19,
+    0xae, 0xf0, 0xa2, 0xa2, 0xce, 0x4e, 0x5d, 0xfc, 0x77, 0x70, 0x0b, 0x72,
+    0x90, 0x43, 0x96, 0xd2, 0x95, 0x6e, 0x83, 0x0a}},
+  {__LINE__,
+   "Mufasa", "http-auth@example.org", "Circle of Life",
+   {0xfb, 0x17, 0x4f, 0x5c, 0x3c, 0x78, 0x02, 0x72, 0x15, 0x17, 0xca, 0xe1,
+    0x3b, 0x98, 0xe2, 0xb8, 0xda, 0xe2, 0xe0, 0x11, 0x8c, 0xb7, 0x05, 0xd9,
+    0x4e, 0xe2, 0x99, 0x46, 0x31, 0x92, 0x04, 0xce}},
+  {__LINE__,
+   "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */,
+   "api@example.org", "Secret, or not?",
+   {0x2d, 0x3d, 0x9f, 0x12, 0xc9, 0xf3, 0xd3, 0x00, 0x11, 0x25, 0x9d, 0xc5,
+    0xfe, 0xce, 0xe0, 0x05, 0xae, 0x24, 0xde, 0x40, 0xe3, 0xe1, 0xf6, 0x18,
+    0x06, 0xd0, 0x3e, 0x65, 0xf1, 0xe6, 0x02, 0x4f}}
+};
+
 
 /*
  *  Helper functions
@@ -356,7 +404,7 @@ test_sha256_failure (void)
              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
              func_name, (unsigned) __LINE__);
   }
-  if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
+  if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
   {
     if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
                                                  "u", "r",
@@ -390,7 +438,157 @@ test_sha256_failure (void)
              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
              func_name, (unsigned) __LINE__);
   }
-  if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
+  if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
+  {
+    if (MHD_NO !=
+        MHD_digest_auth_calc_userhash_hex (algo3,
+                                           "u", "r",
+                                           hash_hex, sizeof(hash_hex)))
+    {
+      failed++;
+      fprintf (stderr,
+               "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+               func_name, (unsigned) __LINE__);
+    }
+  }
+
+  if (! failed && verbose)
+  {
+    printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
+            (unsigned) __LINE__);
+  }
+  return failed ? 1 : 0;
+}
+
+
+static unsigned int
+check_sha512_256 (const struct data_sha512_256 *const data)
+{
+  static const enum MHD_DigestAuthAlgo3 algo3 =
+    MHD_DIGEST_AUTH_ALGO3_SHA512_256;
+  uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
+  char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
+  char expected_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
+  const char *func_name;
+  unsigned int failed = 0;
+
+  func_name = "MHD_digest_auth_calc_userdigest";
+  if (MHD_YES != MHD_digest_auth_calc_userdigest (algo3,
+                                                  data->username,
+                                                  data->realm,
+                                                  data->password,
+                                                  hash_bin, sizeof(hash_bin)))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_YES.\n",
+             func_name);
+  }
+  else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
+  {
+    failed++;
+    bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
+    bin2hex (data->hash, sizeof(data->hash), expected_hex);
+    fprintf (stderr,
+             "FAILED: %s() produced wrong hash. "
+             "Calculated digest %s, expected digest %s.\n",
+             func_name,
+             hash_hex, expected_hex);
+  }
+
+  if (failed)
+  {
+    fprintf (stderr,
+             "The check failed for data located at line: %u.\n",
+             data->line_num);
+    fflush (stderr);
+  }
+  else if (verbose)
+  {
+    printf ("PASSED: check for data at line: %u.\n",
+            data->line_num);
+  }
+  return failed ? 1 : 0;
+}
+
+
+static unsigned int
+test_sha512_256 (void)
+{
+  unsigned int num_failed = 0;
+  size_t i;
+
+  for (i = 0; i < sizeof(sha512_256_tests) / sizeof(sha512_256_tests[0]); i++)
+    num_failed += check_sha512_256 (sha512_256_tests + i);
+  return num_failed;
+}
+
+
+static unsigned int
+test_sha512_256_failure (void)
+{
+  static const enum MHD_DigestAuthAlgo3 algo3 =
+    MHD_DIGEST_AUTH_ALGO3_SHA512_256;
+  static const enum MHD_FEATURE feature = MHD_FEATURE_DIGEST_AUTH_SHA512_256;
+  uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
+  char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
+  const char *func_name;
+  unsigned int failed = 0;
+
+  func_name = "MHD_digest_auth_calc_userhash";
+  if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
+                                               "u", "r",
+                                               hash_bin, sizeof(hash_bin) - 1))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+             func_name, (unsigned) __LINE__);
+  }
+  if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
+                                               "u", "r",
+                                               hash_bin, 0))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+             func_name, (unsigned) __LINE__);
+  }
+  if (MHD_NO == MHD_is_feature_supported (feature))
+  {
+    if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
+                                                 "u", "r",
+                                                 hash_bin, sizeof(hash_bin)))
+    {
+      failed++;
+      fprintf (stderr,
+               "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+               func_name, (unsigned) __LINE__);
+    }
+  }
+
+  func_name = "MHD_digest_auth_calc_userhash_hex";
+  if (MHD_NO !=
+      MHD_digest_auth_calc_userhash_hex (algo3,
+                                         "u", "r",
+                                         hash_hex, sizeof(hash_hex) - 1))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+             func_name, (unsigned) __LINE__);
+  }
+  if (MHD_NO !=
+      MHD_digest_auth_calc_userhash_hex (algo3,
+                                         "u", "r",
+                                         hash_hex, 0))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+             func_name, (unsigned) __LINE__);
+  }
+  if (MHD_NO == MHD_is_feature_supported (feature))
   {
     if (MHD_NO !=
         MHD_digest_auth_calc_userhash_hex (algo3,
@@ -427,6 +625,9 @@ main (int argc, char *argv[])
   if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
     num_failed += test_sha256 ();
   num_failed += test_sha256_failure ();
+  if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA512_256))
+    num_failed += test_sha512_256 ();
+  num_failed += test_sha512_256_failure ();
 
   return num_failed ? 1 : 0;
 }
diff --git a/src/microhttpd/test_dauth_userhash.c 
b/src/microhttpd/test_dauth_userhash.c
index 6e525773..633ab4b9 100644
--- a/src/microhttpd/test_dauth_userhash.c
+++ b/src/microhttpd/test_dauth_userhash.c
@@ -119,6 +119,53 @@ static const struct data_sha256 sha256_tests[] = {
     0xe9, 0x19, 0x1d, 0x8e, 0x94, 0x6f, 0xc4, 0xe7}}
 };
 
+struct data_sha512_256
+{
+  unsigned int line_num;
+  const char *const username;
+  const char *const realm;
+  const uint8_t hash[MHD_SHA512_256_DIGEST_SIZE];
+};
+
+
+static const struct data_sha512_256 sha512_256_tests[] = {
+  {__LINE__,
+   "u", "r",
+   {0xc7, 0x38, 0xf2, 0xad, 0x40, 0x1b, 0xc8, 0x7a, 0x71, 0xfe, 0x78, 0x09,
+    0x60, 0x15, 0xc9, 0x7b, 0x9a, 0x26, 0xd5, 0x5f, 0x15, 0xe9, 0xf5, 0x0a,
+    0xc3, 0xa6, 0xde, 0x73, 0xdd, 0xcd, 0x3d, 0x08}},
+  {__LINE__,
+   "testuser", "testrealm",
+   {0x4f, 0x69, 0x1e, 0xe9, 0x50, 0x8a, 0xe4, 0x55, 0x21, 0x32, 0x9e, 0xcf,
+    0xd4, 0x91, 0xf7, 0xe2, 0x77, 0x4b, 0x6f, 0xb8, 0x60, 0x2c, 0x14, 0x86,
+    0xad, 0x94, 0x9d, 0x1c, 0x23, 0xd8, 0xa1, 0xf5}},
+  {__LINE__,
+   "test_user", "TestRealm", /* Values from testcurl/test_digestauth2.c */
+   {0x62, 0xe1, 0xac, 0x9f, 0x6c, 0xb1, 0xeb, 0x26, 0xaa, 0x75, 0xeb, 0x5d,
+    0x46, 0xef, 0xcd, 0xc8, 0x9c, 0xcb, 0xa7, 0x81, 0xf0, 0xf9, 0xf7, 0x2f,
+    0x6a, 0xfd, 0xb9, 0x42, 0x65, 0xd9, 0xa7, 0x9a}},
+  {__LINE__,
+   "Mufasa", "myhost@testrealm.com",
+   {0xbd, 0x3e, 0xbc, 0x30, 0x10, 0x0b, 0x7c, 0xf1, 0x61, 0x45, 0x6c, 0xfe,
+    0x64, 0x1c, 0x4c, 0xd2, 0x82, 0xe0, 0x62, 0x6e, 0x2c, 0x5e, 0x09, 0xc2,
+    0x4c, 0x90, 0xb1, 0x60, 0x8a, 0xec, 0x28, 0x64}},
+  {__LINE__,
+   "Mufasa", "myhost@example.com",
+   {0xea, 0x4b, 0x59, 0x37, 0xde, 0x2c, 0x4e, 0x9f, 0x16, 0xf9, 0x9c, 0x31,
+    0x01, 0xb6, 0xdd, 0xf8, 0x8c, 0x85, 0xd7, 0xe8, 0xf1, 0x75, 0x90, 0xd0,
+    0x63, 0x2a, 0x75, 0x75, 0xe4, 0x80, 0x13, 0x69}},
+  {__LINE__,
+   "Mufasa", "http-auth@example.org",
+   {0xe2, 0xdf, 0xab, 0xd1, 0xa9, 0x6d, 0xdf, 0x86, 0x77, 0x10, 0xb6, 0x53,
+    0xb6, 0xe6, 0x85, 0x7d, 0x1f, 0x14, 0x70, 0x86, 0xde, 0x7d, 0x7e, 0xf7,
+    0x9d, 0xcd, 0x24, 0x98, 0x59, 0x87, 0x25, 0x70}},
+  {__LINE__,
+   "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */, "api@example.org",
+   {0x79, 0x32, 0x63, 0xca, 0xab, 0xb7, 0x07, 0xa5, 0x62, 0x11, 0x94, 0x0d,
+    0x90, 0x41, 0x1e, 0xa4, 0xa5, 0x75, 0xad, 0xec, 0xcb, 0x7e, 0x36, 0x0a,
+    0xeb, 0x62, 0x4e, 0xd0, 0x6e, 0xce, 0x9b, 0x0b}}
+};
+
 
 /*
  *  Helper functions
@@ -453,7 +500,7 @@ test_sha256_failure (void)
              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
              func_name, (unsigned) __LINE__);
   }
-  if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
+  if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
   {
     if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
                                                  "u", "r",
@@ -487,7 +534,190 @@ test_sha256_failure (void)
              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
              func_name, (unsigned) __LINE__);
   }
-  if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
+  if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
+  {
+    if (MHD_NO !=
+        MHD_digest_auth_calc_userhash_hex (algo3,
+                                           "u", "r",
+                                           hash_hex, sizeof(hash_hex)))
+    {
+      failed++;
+      fprintf (stderr,
+               "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+               func_name, (unsigned) __LINE__);
+    }
+  }
+
+  if (! failed && verbose)
+  {
+    printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
+            (unsigned) __LINE__);
+  }
+  return failed ? 1 : 0;
+}
+
+
+static unsigned int
+check_sha512_256 (const struct data_sha512_256 *const data)
+{
+  static const enum MHD_DigestAuthAlgo3 algo3 =
+    MHD_DIGEST_AUTH_ALGO3_SHA512_256;
+  uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
+  char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
+  char expected_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
+  const char *func_name;
+  unsigned int failed = 0;
+
+  func_name = "MHD_digest_auth_calc_userhash";
+  if (MHD_YES != MHD_digest_auth_calc_userhash (algo3,
+                                                data->username, data->realm,
+                                                hash_bin, sizeof(hash_bin)))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_YES.\n",
+             func_name);
+  }
+  else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
+  {
+    failed++;
+    bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
+    bin2hex (data->hash, sizeof(data->hash), expected_hex);
+    fprintf (stderr,
+             "FAILED: %s() produced wrong hash. "
+             "Calculated digest %s, expected digest %s.\n",
+             func_name,
+             hash_hex, expected_hex);
+  }
+
+  func_name = "MHD_digest_auth_calc_userhash_hex";
+  if (MHD_YES !=
+      MHD_digest_auth_calc_userhash_hex (algo3,
+                                         data->username, data->realm,
+                                         hash_hex, sizeof(hash_hex)))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_YES.\n",
+             func_name);
+  }
+  else if (sizeof(hash_hex) - 1 != strlen (hash_hex))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s produced hash with wrong length. "
+             "Calculated length %u, expected digest %u.\n",
+             func_name,
+             (unsigned) strlen (hash_hex),
+             (unsigned) (sizeof(hash_hex) - 1));
+  }
+  else
+  {
+    bin2hex (data->hash, sizeof(data->hash), expected_hex);
+    if (0 != memcmp (hash_hex, expected_hex, sizeof(hash_hex)))
+    {
+      failed++;
+      fprintf (stderr,
+               "FAILED: %s() produced wrong hash. "
+               "Calculated digest %s, expected digest %s.\n",
+               func_name,
+               hash_hex, expected_hex);
+    }
+  }
+
+  if (failed)
+  {
+    fprintf (stderr,
+             "The check failed for data located at line: %u.\n",
+             data->line_num);
+    fflush (stderr);
+  }
+  else if (verbose)
+  {
+    printf ("PASSED: check for data at line: %u.\n",
+            data->line_num);
+  }
+  return failed ? 1 : 0;
+}
+
+
+static unsigned int
+test_sha512_256 (void)
+{
+  unsigned int num_failed = 0;
+  size_t i;
+
+  for (i = 0; i < sizeof(sha512_256_tests) / sizeof(sha512_256_tests[0]); i++)
+    num_failed += check_sha512_256 (sha512_256_tests + i);
+  return num_failed;
+}
+
+
+static unsigned int
+test_sha512_256_failure (void)
+{
+  static const enum MHD_DigestAuthAlgo3 algo3 =
+    MHD_DIGEST_AUTH_ALGO3_SHA512_256;
+  static const enum MHD_FEATURE feature = MHD_FEATURE_DIGEST_AUTH_SHA512_256;
+  uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
+  char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
+  const char *func_name;
+  unsigned int failed = 0;
+
+  func_name = "MHD_digest_auth_calc_userhash";
+  if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
+                                               "u", "r",
+                                               hash_bin, sizeof(hash_bin) - 1))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+             func_name, (unsigned) __LINE__);
+  }
+  if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
+                                               "u", "r",
+                                               hash_bin, 0))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+             func_name, (unsigned) __LINE__);
+  }
+  if (MHD_NO == MHD_is_feature_supported (feature))
+  {
+    if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
+                                                 "u", "r",
+                                                 hash_bin, sizeof(hash_bin)))
+    {
+      failed++;
+      fprintf (stderr,
+               "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+               func_name, (unsigned) __LINE__);
+    }
+  }
+
+  func_name = "MHD_digest_auth_calc_userhash_hex";
+  if (MHD_NO !=
+      MHD_digest_auth_calc_userhash_hex (algo3,
+                                         "u", "r",
+                                         hash_hex, sizeof(hash_hex) - 1))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+             func_name, (unsigned) __LINE__);
+  }
+  if (MHD_NO !=
+      MHD_digest_auth_calc_userhash_hex (algo3,
+                                         "u", "r",
+                                         hash_hex, 0))
+  {
+    failed++;
+    fprintf (stderr,
+             "FAILED: %s() has not returned MHD_NO at line: %u.\n",
+             func_name, (unsigned) __LINE__);
+  }
+  if (MHD_NO == MHD_is_feature_supported (feature))
   {
     if (MHD_NO !=
         MHD_digest_auth_calc_userhash_hex (algo3,
@@ -524,6 +754,9 @@ main (int argc, char *argv[])
   if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
     num_failed += test_sha256 ();
   num_failed += test_sha256_failure ();
+  if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA512_256))
+    num_failed += test_sha512_256 ();
+  num_failed += test_sha512_256_failure ();
 
   return num_failed ? 1 : 0;
 }
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;
+}
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am
index 0e23f251..a4bc94ef 100644
--- a/src/testcurl/Makefile.am
+++ b/src/testcurl/Makefile.am
@@ -161,12 +161,18 @@ endif
 
 
 if ENABLE_DAUTH
+if ENABLE_MD5
 THREAD_ONLY_TESTS += \
   test_digestauth \
-  test_digestauth_sha256 \
   test_digestauth_with_arguments \
   test_digestauth_concurrent
+endif
+if ENABLE_SHA256
+THREAD_ONLY_TESTS += \
+  test_digestauth_sha256
+endif
 
+if ENABLE_MD5
 check_PROGRAMS += \
   test_digestauth_emu_ext \
   test_digestauth_emu_ext_oldapi \
@@ -176,21 +182,25 @@ check_PROGRAMS += \
   test_digestauth2_oldapi1 \
   test_digestauth2_oldapi2 \
   test_digestauth2_userhash \
-  test_digestauth2_sha256 \
-  test_digestauth2_sha256_userhash \
-  test_digestauth2_oldapi2_sha256 \
   test_digestauth2_userdigest \
   test_digestauth2_oldapi1_userdigest \
   test_digestauth2_oldapi2_userdigest \
   test_digestauth2_userhash_userdigest \
-  test_digestauth2_sha256_userdigest \
-  test_digestauth2_oldapi2_sha256_userdigest \
-  test_digestauth2_sha256_userhash_userdigest \
   test_digestauth2_bind_all \
   test_digestauth2_bind_uri \
   test_digestauth2_oldapi1_bind_all \
   test_digestauth2_oldapi1_bind_uri
 endif
+if ENABLE_SHA256
+check_PROGRAMS += \
+  test_digestauth2_sha256 \
+  test_digestauth2_sha256_userhash \
+  test_digestauth2_oldapi2_sha256 \
+  test_digestauth2_sha256_userdigest \
+  test_digestauth2_oldapi2_sha256_userdigest \
+  test_digestauth2_sha256_userhash_userdigest
+endif
+endif
 
 if HEAVY_TESTS
 if HAVE_FORK_WAITPID
diff --git a/src/testcurl/test_digestauth2.c b/src/testcurl/test_digestauth2.c
index f92d6d14..81a93b5e 100644
--- a/src/testcurl/test_digestauth2.c
+++ b/src/testcurl/test_digestauth2.c
@@ -476,8 +476,6 @@ ahc_echo (void *cls,
       enum MHD_DigestAuthResult check_res;
       enum MHD_DigestAuthResult expect_res;
 
-      if (NULL == dinfo->username)
-        mhdErrorExitDesc ("'username' is NULL");
       if (curl_uses_usehash)
       {
         if (MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH != dinfo->uname_type)
@@ -488,29 +486,33 @@ ahc_echo (void *cls,
                    (int) dinfo->uname_type);
           mhdErrorExitDesc ("Wrong 'uname_type'");
         }
-        else if (dinfo->username_len != userhash_hex_len)
+        else if (dinfo->userhash_hex_len != userhash_hex_len)
         {
-          fprintf (stderr, "'username_len' does not match.\n"
+          fprintf (stderr, "'userhash_hex_len' does not match.\n"
                    "Expected: %u\tRecieved: %u. ",
                    (unsigned) userhash_hex_len,
-                   (unsigned) dinfo->username_len);
-          mhdErrorExitDesc ("Wrong 'username_len'");
+                   (unsigned) dinfo->userhash_hex_len);
+          mhdErrorExitDesc ("Wrong 'userhash_hex_len'");
         }
-        else if (0 != memcmp (dinfo->username, userhash_hex,
-                              dinfo->username_len))
+        else if (0 != memcmp (dinfo->userhash_hex, userhash_hex,
+                              dinfo->userhash_hex_len))
         {
-          fprintf (stderr, "'username' does not match.\n"
+          fprintf (stderr, "'userhash_hex' does not match.\n"
                    "Expected: '%s'\tRecieved: '%.*s'. ",
                    userhash_hex,
-                   (int) dinfo->username_len,
-                   dinfo->username);
-          mhdErrorExitDesc ("Wrong 'username'");
+                   (int) dinfo->userhash_hex_len,
+                   dinfo->userhash_hex);
+          mhdErrorExitDesc ("Wrong 'userhash_hex'");
         }
         else if (NULL == dinfo->userhash_bin)
           mhdErrorExitDesc ("'userhash_bin' is NULL");
         else if (0 != memcmp (dinfo->userhash_bin, userhash_bin,
                               dinfo->username_len / 2))
           mhdErrorExitDesc ("Wrong 'userhash_bin'");
+        else if (NULL != dinfo->username)
+          mhdErrorExitDesc ("'username' is NOT NULL");
+        else if (0 != dinfo->username_len)
+          mhdErrorExitDesc ("'username_len' is NOT zero");
       }
       else
       {
@@ -522,6 +524,8 @@ ahc_echo (void *cls,
                    (int) dinfo->uname_type);
           mhdErrorExitDesc ("Wrong 'uname_type'");
         }
+        else if (NULL == dinfo->username)
+          mhdErrorExitDesc ("'username' is NULL");
         else if (dinfo->username_len != strlen (username_ptr))
         {
           fprintf (stderr, "'username_len' does not match.\n"
@@ -540,6 +544,10 @@ ahc_echo (void *cls,
                    dinfo->username);
           mhdErrorExitDesc ("Wrong 'username'");
         }
+        else if (NULL != dinfo->userhash_hex)
+          mhdErrorExitDesc ("'userhash_hex' is NOT NULL");
+        else if (0 != dinfo->userhash_hex_len)
+          mhdErrorExitDesc ("'userhash_hex_len' is NOT zero");
         else if (NULL != dinfo->userhash_bin)
           mhdErrorExitDesc ("'userhash_bin' is NOT NULL");
       }
@@ -620,8 +628,6 @@ ahc_echo (void *cls,
       uname = MHD_digest_auth_get_username3 (connection);
       if (NULL == uname)
         mhdErrorExitDesc ("MHD_digest_auth_get_username3() returned NULL");
-      else if (NULL == uname->username)
-        mhdErrorExitDesc ("'username' is NULL");
       if (curl_uses_usehash)
       {
         if (MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH != uname->uname_type)
@@ -632,29 +638,33 @@ ahc_echo (void *cls,
                    (int) uname->uname_type);
           mhdErrorExitDesc ("Wrong 'uname_type'");
         }
-        else if (uname->username_len != userhash_hex_len)
+        else if (uname->userhash_hex_len != userhash_hex_len)
         {
-          fprintf (stderr, "'username_len' does not match.\n"
+          fprintf (stderr, "'userhash_hex_len' does not match.\n"
                    "Expected: %u\tRecieved: %u. ",
                    (unsigned) userhash_hex_len,
-                   (unsigned) uname->username_len);
-          mhdErrorExitDesc ("Wrong 'username_len'");
+                   (unsigned) uname->userhash_hex_len);
+          mhdErrorExitDesc ("Wrong 'userhash_hex_len'");
         }
-        else if (0 != memcmp (uname->username, userhash_hex,
-                              uname->username_len))
+        else if (0 != memcmp (uname->userhash_hex, userhash_hex,
+                              uname->userhash_hex_len))
         {
           fprintf (stderr, "'username' does not match.\n"
                    "Expected: '%s'\tRecieved: '%.*s'. ",
                    userhash_hex,
-                   (int) uname->username_len,
-                   uname->username);
-          mhdErrorExitDesc ("Wrong 'username'");
+                   (int) uname->userhash_hex_len,
+                   uname->userhash_hex);
+          mhdErrorExitDesc ("Wrong 'userhash_hex'");
         }
         else if (NULL == uname->userhash_bin)
           mhdErrorExitDesc ("'userhash_bin' is NULL");
         else if (0 != memcmp (uname->userhash_bin, userhash_bin,
                               uname->username_len / 2))
           mhdErrorExitDesc ("Wrong 'userhash_bin'");
+        else if (NULL != uname->username)
+          mhdErrorExitDesc ("'username' is NOT NULL");
+        else if (0 != uname->username_len)
+          mhdErrorExitDesc ("'username_len' is NOT zero");
       }
       else
       {
@@ -666,6 +676,8 @@ ahc_echo (void *cls,
                    (int) uname->uname_type);
           mhdErrorExitDesc ("Wrong 'uname_type'");
         }
+        else if (NULL == uname->username)
+          mhdErrorExitDesc ("'username' is NULL");
         else if (uname->username_len != strlen (username_ptr))
         {
           fprintf (stderr, "'username_len' does not match.\n"
@@ -684,6 +696,10 @@ ahc_echo (void *cls,
                    uname->username);
           mhdErrorExitDesc ("Wrong 'username'");
         }
+        else if (NULL != uname->userhash_hex)
+          mhdErrorExitDesc ("'userhash_hex' is NOT NULL");
+        else if (0 != uname->userhash_hex_len)
+          mhdErrorExitDesc ("'userhash_hex_len' is NOT zero");
         else if (NULL != uname->userhash_bin)
           mhdErrorExitDesc ("'userhash_bin' is NOT NULL");
       }
diff --git a/src/testcurl/test_digestauth_emu_ext.c 
b/src/testcurl/test_digestauth_emu_ext.c
index fc4f4aaa..b3925d13 100644
--- a/src/testcurl/test_digestauth_emu_ext.c
+++ b/src/testcurl/test_digestauth_emu_ext.c
@@ -381,6 +381,10 @@ ahc_echo (void *cls,
                creds->username);
       mhdErrorExitDesc ("Wrong 'username'");
     }
+    else if (NULL != creds->userhash_hex)
+      mhdErrorExitDesc ("'userhash_hex' is NOT NULL");
+    else if (0 != creds->userhash_hex_len)
+      mhdErrorExitDesc ("'userhash_hex' is NOT zero");
     else if (NULL != creds->userhash_bin)
       mhdErrorExitDesc ("'userhash_bin' is NOT NULL");
     MHD_free (creds);
@@ -415,6 +419,10 @@ ahc_echo (void *cls,
                dinfo->username);
       mhdErrorExitDesc ("Wrong 'username'");
     }
+    else if (NULL != dinfo->userhash_hex)
+      mhdErrorExitDesc ("'userhash_hex' is NOT NULL");
+    else if (0 != dinfo->userhash_hex_len)
+      mhdErrorExitDesc ("'userhash_hex' is NOT zero");
     else if (NULL != dinfo->userhash_bin)
       mhdErrorExitDesc ("'userhash_bin' is NOT NULL");
     else if (MHD_DIGEST_AUTH_ALGO3_MD5 != dinfo->algo3)

-- 
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]