[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 21/22: Implemented support for hash calculation by GnuTL
From: |
gnunet |
Subject: |
[libmicrohttpd] 21/22: Implemented support for hash calculation by GnuTLS lib functions |
Date: |
Sun, 25 Sep 2022 17:43:56 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit 172b0eeb45e771ca0df56697bcfb581cc8a96a88
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Sat Sep 24 20:13:16 2022 +0300
Implemented support for hash calculation by GnuTLS lib functions
---
configure.ac | 256 ++++++++--
src/include/microhttpd.h | 39 +-
src/microhttpd/Makefile.am | 46 +-
src/microhttpd/daemon.c | 6 +
src/microhttpd/digestauth.c | 659 ++++++++++++++++++++------
src/microhttpd/md5.h | 5 +
src/microhttpd/md5_ext.c | 95 ++++
src/microhttpd/md5_ext.h | 115 +++++
src/microhttpd/mhd_md5_wrap.h | 98 ++++
src/microhttpd/mhd_sha256_wrap.h | 100 ++++
src/microhttpd/sha256.h | 5 +
src/microhttpd/sha256_ext.c | 95 ++++
src/microhttpd/sha256_ext.h | 115 +++++
src/microhttpd/test_dauth_userdigest.c | 14 +
src/microhttpd/test_dauth_userhash.c | 14 +
src/microhttpd/test_md5.c | 95 +++-
src/microhttpd/test_sha256.c | 90 +++-
src/testcurl/test_digestauth.c | 19 +-
src/testcurl/test_digestauth2.c | 14 +-
src/testcurl/test_digestauth_concurrent.c | 18 +-
src/testcurl/test_digestauth_sha256.c | 19 +-
src/testcurl/test_digestauth_with_arguments.c | 11 +-
w32/common/MHD_config.h | 6 +
w32/common/libmicrohttpd-files.vcxproj | 2 +
w32/common/libmicrohttpd-filters.vcxproj | 6 +
25 files changed, 1677 insertions(+), 265 deletions(-)
diff --git a/configure.ac b/configure.ac
index 31ae78ec..1b6310da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3048,8 +3048,8 @@ AC_MSG_RESULT([[$enable_bauth]])
AC_MSG_CHECKING([[whether to support HTTP Digest authentication]])
AC_ARG_ENABLE([dauth],
[AS_HELP_STRING([--disable-dauth], [disable HTTP Digest
Authentication support])],
- [enable_dauth=${enableval}],
- [enable_dauth=yes])
+ [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.]) ])
@@ -3084,57 +3084,249 @@ 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_HELP_STRING([[--enable-md5=TYPE]],[enable TYPE of MD5 hashing code (yes,
no, builtin, tlslib) [yes if dauth enabled]])
],
[
- AS_VAR_IF([[enable_md5]],[["yes"]],
+ AS_VAR_IF([enable_md5],["internal"],[enable_md5='builtin'])
+ AS_VAR_IF([enable_md5],["built-in"],[enable_md5='builtin'])
+ AS_VAR_IF([enable_dauth],["yes"],[],
[
- AS_VAR_IF([enable_dauth],["yes"],[],
+ AS_VAR_IF([enable_md5],["no"],[],
[
- AC_MSG_WARN([The parameter --enable-md5 is ignored as Digest
Authentication is disabled])
+ AC_MSG_WARN([The parameter --enable-md5=${enable_md5} is ignored
as Digest Authentication is disabled])
enable_md5='no'
]
)
- ],[[enable_md5='no']]
+ ]
)
], [[enable_md5="${enable_dauth}"]]
)
+AS_CASE([${enable_md5}],[yes|tlslib],
+ [
+ AS_IF([test "x${enable_compact_code}" != "xno" || test "x$enable_md5" =
"xtlslib"],
+ [
+ AS_IF([test "x$enable_https" = "xyes"],
+ [
+ AC_CACHE_CHECK([whether GnuTLS supports MD5
hashing],[mhd_cv_gnutls_md5],
+ [
+ CFLAGS="${CFLAGS_ac} ${GNUTLS_CFLAGS} ${user_CFLAGS}"
+ CPPFLAGS="${CPPFLAGS_ac} ${MHD_TLS_LIB_CPPFLAGS}
${user_CPPFLAGS}"
+ CFLAGS="${CFLAGS_ac} ${MHD_TLS_LIB_CFLAGS} ${user_CFLAGS}"
+ LDFLAGS="${LDFLAGS_ac} ${MHD_TLS_LIB_LDFLAGS} ${user_LDFLAGS}"
+ save_LIBS="$LIBS"
+ LIBS="${MHD_TLS_LIBDEPS} ${LIBS}"
+ AC_LINK_IFELSE(
+ [
+ AC_LANG_PROGRAM(
+ [[
+#include <gnutls/crypto.h>
+ ]],
+ [[
+ gnutls_hash_hd_t hash_handle;
+ unsigned char digest[16];
+ int exit_code;
+
+ if (0 == gnutls_hash_init(&hash_handle, GNUTLS_DIG_MD5))
+ {
+ if (0 == gnutls_hash(hash_handle, "", 1))
+ {
+ gnutls_hash_output(hash_handle, digest);
+ if (0x93 == digest[0])
+ exit_code = 0;
+ else
+ exit_code = 7;
+ }
+ else
+ exit_code = 5;
+ gnutls_hash_deinit(hash_handle, (void *)0);
+ }
+ else
+ exit_code = 2;
+ if (exit_code)
+ return exit_code;
+ ]]
+ )
+ ],
+ [mhd_cv_gnutls_md5='yes'],[mhd_cv_gnutls_md5='no']
+ )
+ LIBS="${save_LIBS}"
+ CFLAGS="${CFLAGS_ac} ${user_CFLAGS}"
+ CPPFLAGS="${CPPFLAGS_ac} ${user_CPPFLAGS}"
+ CFLAGS="${CFLAGS_ac} ${user_CFLAGS}"
+ LDFLAGS="${LDFLAGS_ac} ${user_LDFLAGS}"
+ ]
+ )
+ AS_VAR_IF([mhd_cv_gnutls_md5],["no"],
+ [
+ AS_VAR_IF([enable_md5],["tlslib"],
+ [AC_MSG_FAILURE([TLS library MD5 implementation is not
available])]
+ )
+ enable_md5="builtin"
+ ],
+ [enable_md5="tlslib"]
+ )
+ ],
+ [
+ AS_VAR_IF([enable_md5],["tlslib"],
+ [AC_MSG_ERROR([HTTPS is not enabled, TLS library MD5
implementation cannot be used])]
+ )
+ enable_md5="builtin"
+ ]
+ )
+ ],
+ [
+ enable_md5="builtin"
+ ]
+ )
+ ]
+)
AC_MSG_CHECKING([[whether to support MD5]])
-AS_VAR_IF([[enable_md5]],[["yes"]],
+AS_UNSET([enable_md5_MSG])
+AS_CASE([${enable_md5}],
+ [builtin],[enable_md5_MSG='yes, built-in'],
+ [tlslib],[enable_md5_MSG='yes, external (TLS library)'],
+ [no],[enable_md5_MSG='no'],
+ [yes],[AC_MSG_ERROR([configure internal error: unexpected variable value])],
+ [AC_MSG_ERROR([Unrecognized parameter --enable-md5=${enable_md5}])]
+)
+AS_IF([test "x${enable_md5}" = "xbuiltin" || test "x${enable_md5}" = "xtlslib"
],
[
- AC_DEFINE([[MHD_MD5_SUPPORT]],[[1]],
- [Define to 1 if libmicrohttpd is compiled with MD5 hashing support.])
+ 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}]])
+AS_IF([test "x${enable_md5}" = "xtlslib" ],
+ [
+ AC_DEFINE([[MHD_MD5_TLSLIB]],[[1]],
+ [Define to 1 if libmicrohttpd is compiled with MD5 hashing by TLS
library.])
+ ]
+)
+AM_CONDITIONAL([ENABLE_MD5], [[test "x${enable_md5}" = "xbuiltin" || test
"x${enable_md5}" = "xtlslib" ]])
+AM_CONDITIONAL([ENABLE_MD5_EXT], [[test "x${enable_md5}" = "xtlslib" ]])
+AC_MSG_RESULT([[${enable_md5_MSG}]])
# 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_HELP_STRING([[--enable-sha256=TYPE]],[enable TYPE of SHA-256 hashing
code (yes, no, builtin, tlslib) [yes if dauth enabled]])
],
[
- AS_VAR_IF([[enable_sha256]],[["yes"]],
+ AS_VAR_IF([enable_sha256],["internal"],[enable_sha256='builtin'])
+ AS_VAR_IF([enable_sha256],["built-in"],[enable_sha256='builtin'])
+ AS_VAR_IF([enable_dauth],["yes"],[],
[
- AS_VAR_IF([enable_dauth],["yes"],[],
+ AS_VAR_IF([enable_sha256],["no"],[],
[
- AC_MSG_WARN([The parameter --enable-sha256 is ignored as Digest
Authentication is disabled])
+ AC_MSG_WARN([The parameter --enable-sha256=${enable_sha256} is
ignored as Digest Authentication is disabled])
enable_sha256='no'
]
)
- ],[[enable_sha256='no']]
+ ]
)
], [[enable_sha256="${enable_dauth}"]]
)
+AS_CASE([${enable_sha256}],[yes|tlslib],
+ [
+ AS_IF([test "x${enable_compact_code}" != "xno" || test "x$enable_sha256" =
"xtlslib"],
+ [
+ AS_IF([test "x$enable_https" = "xyes"],
+ [
+ AC_CACHE_CHECK([whether GnuTLS supports sha256
hashing],[mhd_cv_gnutls_sha256],
+ [
+ CFLAGS="${CFLAGS_ac} ${GNUTLS_CFLAGS} ${user_CFLAGS}"
+ CPPFLAGS="${CPPFLAGS_ac} ${MHD_TLS_LIB_CPPFLAGS}
${user_CPPFLAGS}"
+ CFLAGS="${CFLAGS_ac} ${MHD_TLS_LIB_CFLAGS} ${user_CFLAGS}"
+ LDFLAGS="${LDFLAGS_ac} ${MHD_TLS_LIB_LDFLAGS} ${user_LDFLAGS}"
+ save_LIBS="$LIBS"
+ LIBS="${MHD_TLS_LIBDEPS} ${LIBS}"
+ AC_LINK_IFELSE(
+ [
+ AC_LANG_PROGRAM(
+ [[
+#include <gnutls/crypto.h>
+ ]],
+ [[
+ gnutls_hash_hd_t hash_handle;
+ unsigned char digest[32];
+ int exit_code;
+
+ if (0 == gnutls_hash_init(&hash_handle, GNUTLS_DIG_SHA256))
+ {
+ if (0 == gnutls_hash(hash_handle, "", 1))
+ {
+ gnutls_hash_output(hash_handle, digest);
+ if (0x6e == digest[0])
+ exit_code = 0;
+ else
+ exit_code = 7;
+ }
+ else
+ exit_code = 5;
+ gnutls_hash_deinit(hash_handle, (void *)0);
+ }
+ else
+ exit_code = 2;
+ if (exit_code)
+ return exit_code;
+ ]]
+ )
+ ],
+ [mhd_cv_gnutls_sha256='yes'],[mhd_cv_gnutls_sha256='no']
+ )
+ LIBS="${save_LIBS}"
+ CFLAGS="${CFLAGS_ac} ${user_CFLAGS}"
+ CPPFLAGS="${CPPFLAGS_ac} ${user_CPPFLAGS}"
+ CFLAGS="${CFLAGS_ac} ${user_CFLAGS}"
+ LDFLAGS="${LDFLAGS_ac} ${user_LDFLAGS}"
+ ]
+ )
+ AS_VAR_IF([mhd_cv_gnutls_sha256],["no"],
+ [
+ AS_VAR_IF([enable_sha256],["tlslib"],
+ [AC_MSG_FAILURE([TLS library SHA-256 implementation is not
available])]
+ )
+ enable_sha256="builtin"
+ ],
+ [enable_sha256="tlslib"]
+ )
+ ],
+ [
+ AS_VAR_IF([enable_sha256],["tlslib"],
+ [AC_MSG_ERROR([HTTPS is not enabled, TLS library SHA-256
implementation cannot be used])]
+ )
+ enable_sha256="builtin"
+ ]
+ )
+ ],
+ [
+ enable_sha256="builtin"
+ ]
+ )
+ ]
+)
AC_MSG_CHECKING([[whether to support SHA-256]])
-AS_VAR_IF([[enable_sha256]],[["yes"]],
+AS_UNSET([enable_sha256_MSG])
+AS_CASE([${enable_sha256}],
+ [builtin],[enable_sha256_MSG='yes, built-in'],
+ [tlslib],[enable_sha256_MSG='yes, external (TLS library)'],
+ [no],[enable_sha256_MSG='no'],
+ [yes],[AC_MSG_ERROR([configure internal error: unexpected variable value])],
+ [AC_MSG_ERROR([Unrecognized parameter --enable-sha256=${enable_sha256}])]
+)
+AS_IF([test "x${enable_sha256}" = "xbuiltin" || test "x${enable_sha256}" =
"xtlslib" ],
[
- AC_DEFINE([[MHD_SHA256_SUPPORT]],[[1]],
- [Define to 1 if libmicrohttpd is compiled with SHA-256 hashing support.])
+ 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}]])
+AS_IF([test "x${enable_sha256}" = "xtlslib" ],
+ [
+ AC_DEFINE([[MHD_SHA256_TLSLIB]],[[1]],
+ [Define to 1 if libmicrohttpd is compiled with SHA-256 hashing by TLS
library.])
+ ]
+)
+AM_CONDITIONAL([ENABLE_SHA256], [[test "x${enable_sha256}" = "xbuiltin" ||
test "x${enable_sha256}" = "xtlslib" ]])
+AM_CONDITIONAL([ENABLE_SHA256_EXT], [[test "x${enable_sha256}" = "xtlslib" ]])
+AC_MSG_RESULT([[${enable_sha256_MSG}]])
# optional: SHA-512/256 support for Digest Auth. Enabled by default.
AC_ARG_ENABLE([[sha512-256]],
@@ -3154,6 +3346,12 @@ AC_ARG_ENABLE([[sha512-256]],
], [[enable_sha512_256="${enable_dauth}"]]
)
AC_MSG_CHECKING([[whether to support SHA-512/256]])
+AS_UNSET([enable_sha512_256_MSG])
+AS_CASE([${enable_sha512_256}],
+ [yes],[enable_sha512_256_MSG='yes, built-in'],
+ [no],[enable_sha512_256_MSG='no'],
+ [AC_MSG_ERROR([Unrecognized parameter
--enable-sha512-256=${enable_sha512_256}])]
+)
AS_VAR_IF([[enable_sha512_256]],[["yes"]],
[
AC_DEFINE([[MHD_SHA512_256_SUPPORT]],[[1]],
@@ -3161,11 +3359,11 @@ AS_VAR_IF([[enable_sha512_256]],[["yes"]],
]
)
AM_CONDITIONAL([ENABLE_SHA512_256], [[test "x${enable_sha512_256}" = "xyes"]])
-AC_MSG_RESULT([[${enable_sha512_256}]])
+AC_MSG_RESULT([[${enable_sha512_256_MSG}]])
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"],
+ AS_IF([test "x${enable_md5}" = "xno" && test "x${enable_sha256}" = "xno"
&& test "x${enable_sha512_256}" != "xyes"],
[AC_MSG_ERROR([At least one hashing algorithm must be enabled if Digest
Auth is enabled])]
)
]
@@ -4052,9 +4250,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}
+ MD5: ${enable_md5_MSG}
+ SHA-256: ${enable_sha256_MSG}
+ SHA-512/256: ${enable_sha512_256_MSG}
HTTP "Upgrade": ${enable_httpupgrade}
Cookie parsing: ${enable_cookie}
Postproc: ${enable_postprocessor}
@@ -4075,8 +4273,8 @@ 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_md5}" = "xno" || \
+ test "x${enable_sha256}" = "xno" || \
test "x${enable_sha512_256}" != "xyes" || \
test "x$enable_httpupgrade" != "xyes" || \
test "x$enable_cookie" != "xyes" || \
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index e5f0abac..5e744b69 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 0x00097539
+#define MHD_VERSION 0x00097540
/* If generic headers don't work on your platform, include headers
which define 'va_list', 'size_t', 'ssize_t', 'intptr_t', 'off_t',
@@ -4691,8 +4691,10 @@ enum MHD_DigestAuthMultiAlgo3
* upon return
* @param bin_buf_size the size of the @a userhash_bin buffer, must be
* at least #MHD_digest_get_hash_size(algo3) bytes long
- * @return MHD_YES on success, MHD_NO if @a bin_buf_size is too small or
- * if @a algo3 algorithm is not supported.
+ * @return MHD_YES on success,
+ * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is
+ * not supported (or external error has occurred,
+ * see #MHD_FEATURE_EXTERN_HASH)
* @note Available since #MHD_VERSION 0x00097535
* @ingroup authentication
*/
@@ -4736,8 +4738,10 @@ MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3
algo3,
* userhash string
* @param bin_buf_size the size of the @a userhash_bin buffer, must be
* at least #MHD_digest_get_hash_size(algo3)*2+1 chars long
- * @return MHD_YES on success, MHD_NO if @a bin_buf_size is too small or
- * if @a algo3 algorithm is not supported.
+ * @return MHD_YES on success,
+ * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is
+ * not supported (or external error has occurred,
+ * see #MHD_FEATURE_EXTERN_HASH).
* @note Available since #MHD_VERSION 0x00097535
* @ingroup authentication
*/
@@ -5287,8 +5291,10 @@ MHD_digest_auth_check3 (struct MHD_Connection
*connection,
* userdigest upon return
* @param userdigest_bin the size of the @a userdigest_bin buffer, must be
* at least #MHD_digest_get_hash_size(algo3) bytes long
- * @return MHD_YES on success, MHD_NO if @a userdigest_bin is too small or
- * if @a algo3 algorithm is not supported.
+ * @return MHD_YES on success,
+ * MHD_NO if @a userdigest_bin is too small or if @a algo3 algorithm is
+ * not supported (or external error has occurred,
+ * see #MHD_FEATURE_EXTERN_HASH).
* @sa #MHD_digest_auth_check_digest3()
* @note Available since #MHD_VERSION 0x00097535
* @ingroup authentication
@@ -5651,6 +5657,9 @@ MHD_queue_auth_fail_response (struct MHD_Connection
*connection,
int signal_stale);
+/* ********************* Basic Authentication functions *************** */
+
+
/**
* Information decoded from Basic Authentication client's header.
*
@@ -6138,7 +6147,21 @@ enum MHD_FEATURE
* module is built.
* @note Available since #MHD_VERSION 0x00097536
*/
- MHD_FEATURE_DIGEST_AUTH_USERHASH = 31
+ MHD_FEATURE_DIGEST_AUTH_USERHASH = 31,
+
+ /**
+ * Get whether any of hashing algorithms is implemented by external
+ * function (like TLS library) and may fail due to external conditions,
+ * like "out-of-memory".
+ *
+ * If result is #MHD_YES then functions which use hash calculations
+ * like #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_check3() and
others
+ * potentially may fail even with valid input because of out-of-memory error
+ * or crypto accelerator device failure, however in practice such fails are
+ * unlikely.
+ * @note Available since #MHD_VERSION 0x00097540
+ */
+ MHD_FEATURE_EXTERN_HASH = 32
};
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index 10a32f59..c4c15608 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -170,12 +170,26 @@ libmicrohttpd_la_SOURCES += \
digestauth.c digestauth.h \
mhd_bithelpers.h mhd_byteorder.h mhd_align.h
if ENABLE_MD5
+libmicrohttpd_la_SOURCES += \
+ mhd_md5_wrap.h
+if ! ENABLE_MD5_EXT
libmicrohttpd_la_SOURCES += \
md5.c md5.h
+else
+libmicrohttpd_la_SOURCES += \
+ md5_ext.c md5_ext.h
+endif
endif
if ENABLE_SHA256
+libmicrohttpd_la_SOURCES += \
+ mhd_sha256_wrap.h
+if ! ENABLE_SHA256_EXT
libmicrohttpd_la_SOURCES += \
sha256.c sha256.h
+else
+libmicrohttpd_la_SOURCES += \
+ sha256_ext.c sha256_ext.h
+endif
endif
if ENABLE_SHA512_256
libmicrohttpd_la_SOURCES += \
@@ -462,12 +476,40 @@ test_http_reasons_SOURCES = \
reason_phrase.c mhd_str.c mhd_str.h
test_md5_SOURCES = \
- test_md5.c test_helpers.h \
+ test_md5.c test_helpers.h mhd_md5_wrap.h ../include/mhd_options.h
+if ! ENABLE_MD5_EXT
+test_md5_SOURCES += \
md5.c md5.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h
+test_md5_CPPFLAGS = $(AM_CPPFLAGS)
+test_md5_CFLAGS = $(AM_CFLAGS)
+test_md5_LDFLAGS = $(AM_LDFLAGS)
+test_md5_LDADD = $(LDADD)
+else
+test_md5_SOURCES += \
+ md5_ext.c md5_ext.h
+test_md5_CPPFLAGS = $(AM_CPPFLAGS) $(MHD_TLS_LIB_CPPFLAGS)
+test_md5_CFLAGS = $(AM_CFLAGS) $(MHD_TLS_LIB_CFLAGS)
+test_md5_LDFLAGS = $(AM_LDFLAGS) $(MHD_TLS_LIB_LDFLAGS)
+test_md5_LDADD = $(MHD_TLS_LIBDEPS) $(LDADD)
+endif
test_sha256_SOURCES = \
- test_sha256.c test_helpers.h \
+ test_sha256.c test_helpers.h mhd_sha256_wrap.h ../include/mhd_options.h
+if ! ENABLE_SHA256_EXT
+test_sha256_SOURCES += \
sha256.c sha256.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h
+test_sha256_CPPFLAGS = $(AM_CPPFLAGS)
+test_sha256_CFLAGS = $(AM_CFLAGS)
+test_sha256_LDFLAGS = $(AM_LDFLAGS)
+test_sha256_LDADD = $(LDADD)
+else
+test_sha256_SOURCES += \
+ sha256_ext.c sha256_ext.h
+test_sha256_CPPFLAGS = $(AM_CPPFLAGS) $(MHD_TLS_LIB_CPPFLAGS)
+test_sha256_CFLAGS = $(AM_CFLAGS) $(MHD_TLS_LIB_CFLAGS)
+test_sha256_LDFLAGS = $(AM_LDFLAGS) $(MHD_TLS_LIB_LDFLAGS)
+test_sha256_LDADD = $(MHD_TLS_LIBDEPS) $(LDADD)
+endif
test_sha512_256_SOURCES = \
test_sha512_256.c test_helpers.h \
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index bb9daa52..29ce1ccc 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -8465,6 +8465,12 @@ MHD_is_feature_supported (enum MHD_FEATURE feature)
#else
return MHD_NO;
#endif
+ case MHD_FEATURE_EXTERN_HASH:
+#if defined(MHD_MD5_TLSLIB) || defined(MHD_SHA256_TLSLIB)
+ return MHD_YES;
+#else
+ return MHD_NO;
+#endif
default:
break;
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index 88668d1d..926ac5f4 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -34,10 +34,10 @@
#include "internal.h"
#include "response.h"
#ifdef MHD_MD5_SUPPORT
-# include "md5.h"
+# include "mhd_md5_wrap.h"
#endif /* MHD_MD5_SUPPORT */
#ifdef MHD_SHA256_SUPPORT
-# include "sha256.h"
+# include "mhd_sha256_wrap.h"
#endif /* MHD_SHA256_SUPPORT */
#ifdef MHD_SHA512_256_SUPPORT
# include "sha512_256.h"
@@ -304,10 +304,10 @@ MHD_digest_get_hash_size (enum MHD_DigestAuthAlgo3 algo3)
union DigestCtx
{
#ifdef MHD_MD5_SUPPORT
- struct Md5Ctx md5_ctx;
+ struct Md5CtxWr md5_ctx;
#endif /* MHD_MD5_SUPPORT */
#ifdef MHD_SHA256_SUPPORT
- struct Sha256Ctx sha256_ctx;
+ struct Sha256CtxWr sha256_ctx;
#endif /* MHD_SHA256_SUPPORT */
#ifdef MHD_SHA512_256_SUPPORT
struct Sha512_256Ctx sha512_256_ctx;
@@ -334,9 +334,10 @@ struct DigestAlgorithm
* Buffer for hex-print of the final digest.
*/
#if _DEBUG
- bool setup; /**< The structure was set-up */
- bool inited; /**< The calculation was initialised */
- bool hashing; /**< Some data has been hashed, but digest is not yet
finalised */
+ bool uninitialised; /**< The structure has been not set-up */
+ bool algo_selected; /**< The algorithm has been selected */
+ bool ready_for_hashing; /**< The structure is ready to hash data */
+ bool hashing; /**< Some data has been hashed, but the digest has not
finalised yet */
#endif /* _DEBUG */
};
@@ -349,7 +350,8 @@ struct DigestAlgorithm
_MHD_static_inline unsigned int
digest_get_size (struct DigestAlgorithm *da)
{
- mhd_assert (da->setup);
+ mhd_assert (! da->uninitialised);
+ mhd_assert (da->algo_selected);
#ifdef MHD_MD5_SUPPORT
if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
return MD5_DIGEST_SIZE;
@@ -367,90 +369,136 @@ digest_get_size (struct DigestAlgorithm *da)
}
+#if defined(MHD_MD5_HAS_DEINIT) || defined(MHD_SHA256_HAS_DEINIT)
/**
- * Set-up the digest calculation structure.
- * @param da the structure to set-up
- * @param algo the algorithm to use for digest calculation
- * @return boolean 'true' if successfully set-up,
- * false otherwise.
+ * Indicates presence of digest_deinit() function
*/
-_MHD_static_inline bool
-digest_setup (struct DigestAlgorithm *da,
- enum MHD_DigestBaseAlgo algo)
+#define MHD_DIGEST_HAS_DEINIT 1
+#endif /* MHD_MD5_HAS_DEINIT || MHD_SHA256_HAS_DEINIT */
+
+#ifdef MHD_DIGEST_HAS_DEINIT
+/**
+ * Zero-initialise digest calculation structure.
+ *
+ * This initialisation is enough to safely call #digest_deinit() only.
+ * To make any real digest calculation, #digest_setup_and_init() must be
called.
+ * @param da the digest calculation
+ */
+_MHD_static_inline void
+digest_setup_zero (struct DigestAlgorithm *da)
{
#ifdef _DEBUG
- da->setup = false;
- da->inited = false;
+ da->uninitialised = false;
+ da->algo_selected = false;
+ da->ready_for_hashing = false;
da->hashing = false;
#endif /* _DEBUG */
- 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
- da->setup = true;
-#endif /* _DEBUG */
- return true;
- }
- return false; /* Bad or unsupported algorithm */
+ da->algo = MHD_DIGEST_BASE_ALGO_INVALID;
}
/**
- * Initialise/reset the digest calculation structure.
- * @param da the structure to initialise/reset
+ * De-initialise digest calculation structure.
+ *
+ * This function must be called if #digest_setup_and_init() was called for
+ * @a da.
+ * This function must not be called if @a da was not initialised by
+ * #digest_setup_and_init() or by #digest_setup_zero().
+ * @param da the digest calculation
*/
_MHD_static_inline void
-digest_init (struct DigestAlgorithm *da)
+digest_deinit (struct DigestAlgorithm *da)
{
- mhd_assert (da->setup);
- mhd_assert (! da->hashing);
- mhd_assert (! da->inited);
-#ifdef MHD_MD5_SUPPORT
+ mhd_assert (! da->uninitialised);
+#ifdef MHD_MD5_HAS_DEINIT
if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
+ MHD_MD5_deinit (&da->ctx.md5_ctx);
+ else
+#endif /* MHD_MD5_HAS_DEINIT */
+#ifdef MHD_SHA256_HAS_DEINIT
+ if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
+ MHD_SHA256_deinit (&da->ctx.sha256_ctx);
+ else
+#endif /* MHD_SHA256_HAS_DEINIT */
+ (void) 0;
+ digest_setup_zero (da);
+}
+
+
+#else /* ! MHD_DIGEST_HAS_DEINIT */
+#define digest_setup_zero(da) (void)0
+#define digest_deinit(da) (void)0
+#endif /* ! MHD_DIGEST_HAS_DEINIT */
+
+
+/**
+ * Set-up the digest calculation structure and initialise with initial values.
+ *
+ * If @a da was successfully initialised, #digest_deinit() must be called
+ * after finishing using of the @a da.
+ *
+ * This function must not be called more than once for any @a da.
+ *
+ * @param da the structure to set-up
+ * @param algo the algorithm to use for digest calculation
+ * @return boolean 'true' if successfully set-up,
+ * false otherwise.
+ */
+_MHD_static_inline bool
+digest_init_one_time (struct DigestAlgorithm *da,
+ enum MHD_DigestBaseAlgo algo)
+{
+#ifdef _DEBUG
+ da->uninitialised = false;
+ da->algo_selected = false;
+ da->ready_for_hashing = false;
+ da->hashing = false;
+#endif /* _DEBUG */
+#ifdef MHD_MD5_SUPPORT
+ if (MHD_DIGEST_BASE_ALGO_MD5 == algo)
{
- MHD_MD5_init (&da->ctx.md5_ctx);
+ da->algo = MHD_DIGEST_BASE_ALGO_MD5;
#ifdef _DEBUG
- da->inited = true;
+ da->algo_selected = true;
#endif
+ MHD_MD5_init_one_time (&da->ctx.md5_ctx);
+#ifdef _DEBUG
+ da->ready_for_hashing = true;
+#endif
+ return true;
}
- else
#endif /* MHD_MD5_SUPPORT */
#ifdef MHD_SHA256_SUPPORT
- if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
+ if (MHD_DIGEST_BASE_ALGO_SHA256 == algo)
{
- MHD_SHA256_init (&da->ctx.sha256_ctx);
+ da->algo = MHD_DIGEST_BASE_ALGO_SHA256;
#ifdef _DEBUG
- da->inited = true;
+ da->algo_selected = true;
#endif
+ MHD_SHA256_init_one_time (&da->ctx.sha256_ctx);
+#ifdef _DEBUG
+ da->ready_for_hashing = true;
+#endif
+ return true;
}
- else
#endif /* MHD_SHA256_SUPPORT */
#ifdef MHD_SHA512_256_SUPPORT
- if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
+ if (MHD_DIGEST_BASE_ALGO_SHA512_256 == algo)
{
- MHD_SHA512_256_init (&da->ctx.sha512_256_ctx);
+ da->algo = MHD_DIGEST_BASE_ALGO_SHA512_256;
#ifdef _DEBUG
- da->inited = true;
+ da->algo_selected = true;
#endif
- }
- else
-#endif /* MHD_SHA512_256_SUPPORT */
- {
+ MHD_SHA512_256_init (&da->ctx.sha512_256_ctx);
#ifdef _DEBUG
- da->inited = false;
+ da->ready_for_hashing = true;
#endif
- mhd_assert (0); /* Bad algorithm */
+ return true;
}
+#endif /* MHD_SHA512_256_SUPPORT */
+
+ da->algo = MHD_DIGEST_BASE_ALGO_INVALID;
+ return false; /* Unsupported or bad algorithm */
}
@@ -465,7 +513,9 @@ digest_update (struct DigestAlgorithm *da,
const void *data,
size_t length)
{
- mhd_assert (da->inited);
+ mhd_assert (! da->uninitialised);
+ mhd_assert (da->algo_selected);
+ mhd_assert (da->ready_for_hashing);
#ifdef MHD_MD5_SUPPORT
if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
MHD_MD5_update (&da->ctx.md5_ctx, (const uint8_t *) data, length);
@@ -525,30 +575,160 @@ digest_update_with_colon (struct DigestAlgorithm *da)
_MHD_static_inline void
digest_calc_hash (struct DigestAlgorithm *da, uint8_t *digest)
{
- mhd_assert (da->inited);
+ mhd_assert (! da->uninitialised);
+ mhd_assert (da->algo_selected);
+ mhd_assert (da->ready_for_hashing);
#ifdef MHD_MD5_SUPPORT
if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
+ {
+#ifdef MHD_MD5_HAS_FINISH
MHD_MD5_finish (&da->ctx.md5_ctx, digest);
+#ifdef _DEBUG
+ da->ready_for_hashing = false;
+#endif /* _DEBUG */
+#else /* ! MHD_MD5_HAS_FINISH */
+ MHD_MD5_finish_reset (&da->ctx.md5_ctx, digest);
+#ifdef _DEBUG
+ da->ready_for_hashing = true;
+#endif /* _DEBUG */
+#endif /* ! MHD_MD5_HAS_FINISH */
+ }
else
#endif /* MHD_MD5_SUPPORT */
#ifdef MHD_SHA256_SUPPORT
if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
+ {
+#ifdef MHD_SHA256_HAS_FINISH
MHD_SHA256_finish (&da->ctx.sha256_ctx, digest);
+#ifdef _DEBUG
+ da->ready_for_hashing = false;
+#endif /* _DEBUG */
+#else /* ! MHD_SHA256_HAS_FINISH */
+ MHD_SHA256_finish_reset (&da->ctx.sha256_ctx, digest);
+#ifdef _DEBUG
+ da->ready_for_hashing = true;
+#endif /* _DEBUG */
+#endif /* ! MHD_SHA256_HAS_FINISH */
+ }
else
#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);
+#ifdef _DEBUG
+ da->ready_for_hashing = false;
+#endif /* _DEBUG */
+ }
else
#endif /* MHD_SHA512_256_SUPPORT */
- mhd_assert (0); /* May not happen */
+ mhd_assert (0); /* Should not happen */
#ifdef _DEBUG
da->hashing = false;
- da->inited = false;
+#endif /* _DEBUG */
+}
+
+
+/**
+ * Reset the digest calculation structure.
+ *
+ * @param da the structure to reset
+ */
+_MHD_static_inline void
+digest_reset (struct DigestAlgorithm *da)
+{
+ mhd_assert (! da->uninitialised);
+ mhd_assert (da->algo_selected);
+ mhd_assert (! da->hashing);
+#ifdef MHD_MD5_SUPPORT
+ if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
+ {
+#ifdef MHD_MD5_HAS_FINISH
+ mhd_assert (! da->ready_for_hashing);
+#else /* ! MHD_MD5_HAS_FINISH */
+ mhd_assert (da->ready_for_hashing);
+#endif /* ! MHD_MD5_HAS_FINISH */
+ MHD_MD5_reset (&da->ctx.md5_ctx);
+#ifdef _DEBUG
+ da->ready_for_hashing = true;
+#endif /* _DEBUG */
+ }
+ else
+#endif /* MHD_MD5_SUPPORT */
+#ifdef MHD_SHA256_SUPPORT
+ if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
+ {
+#ifdef MHD_SHA256_HAS_FINISH
+ mhd_assert (! da->ready_for_hashing);
+#else /* ! MHD_SHA256_HAS_FINISH */
+ mhd_assert (da->ready_for_hashing);
+#endif /* ! MHD_SHA256_HAS_FINISH */
+ MHD_SHA256_reset (&da->ctx.sha256_ctx);
+#ifdef _DEBUG
+ da->ready_for_hashing = true;
+#endif /* _DEBUG */
+ }
+ else
+#endif /* MHD_SHA256_SUPPORT */
+#ifdef MHD_SHA512_256_SUPPORT
+ if (MHD_DIGEST_BASE_ALGO_SHA512_256 == da->algo)
+ {
+ mhd_assert (! da->ready_for_hashing);
+ MHD_SHA512_256_init (&da->ctx.sha512_256_ctx);
+#ifdef _DEBUG
+ da->ready_for_hashing = true;
+#endif
+ }
+ else
+#endif /* MHD_SHA512_256_SUPPORT */
+ {
+#ifdef _DEBUG
+ da->ready_for_hashing = false;
#endif
+ mhd_assert (0); /* May not happen, bad algorithm */
+ }
}
+#if defined(MHD_MD5_HAS_EXT_ERROR) || defined(MHD_SHA256_HAS_EXT_ERROR)
+/**
+ * Indicates that digest algorithm has external error status
+ */
+#define MHD_DIGEST_HAS_EXT_ERROR 1
+#endif /* MHD_MD5_HAS_EXT_ERROR || MHD_SHA256_HAS_EXT_ERROR */
+
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+/**
+ * Get external error code.
+ *
+ * When external digest calculation used, an error may occur during
+ * initialisation or hashing data. This function checks whether external
+ * error has been reported for digest calculation.
+ * @param da the digest calculation
+ * @return true if external error occurs
+ */
+_MHD_static_inline bool
+digest_ext_error (struct DigestAlgorithm *da)
+{
+ mhd_assert (! da->uninitialised);
+ mhd_assert (da->algo_selected);
+#ifdef MHD_MD5_HAS_EXT_ERROR
+ if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
+ return 0 != da->ctx.md5_ctx.ext_error;
+#endif /* MHD_MD5_HAS_EXT_ERROR */
+#ifdef MHD_SHA256_HAS_EXT_ERROR
+ if (MHD_DIGEST_BASE_ALGO_SHA256 == da->algo)
+ return 0 != da->ctx.sha256_ctx.ext_error;
+#endif /* MHD_MD5_HAS_EXT_ERROR */
+ return false;
+}
+
+
+#else /* ! MHD_DIGEST_HAS_EXT_ERROR */
+#define digest_ext_error(da) (false)
+#endif /* ! MHD_DIGEST_HAS_EXT_ERROR */
+
+
/**
* Extract timestamp from the given nonce.
* @param nonce the nonce to check
@@ -1314,7 +1494,7 @@ calculate_nonce (uint64_t nonce_time,
struct DigestAlgorithm *da,
char *nonce)
{
- digest_init (da);
+ mhd_assert (! da->hashing);
if (1)
{
/* Add the timestamp to the hash calculation */
@@ -1522,6 +1702,7 @@ calculate_add_nonce (struct MHD_Connection *const
connection,
const size_t nonce_size = NONCE_STD_LEN (digest_get_size (da));
bool ret;
+ mhd_assert (! da->hashing);
mhd_assert (MAX_DIGEST_NONCE_LENGTH >= nonce_size);
mhd_assert (0 != nonce_size);
@@ -1541,6 +1722,11 @@ calculate_add_nonce (struct MHD_Connection *const
connection,
da,
nonce);
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ if (digest_ext_error (da))
+ return false;
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
+
if (0 == daemon->nonce_nc_size)
return false;
@@ -1589,6 +1775,7 @@ calculate_add_nonce_with_retry (struct MHD_Connection
*const connection,
{
const uint64_t timestamp1 = MHD_monotonic_msec_counter ();
const size_t realm_len = strlen (realm);
+ mhd_assert (! da->hashing);
#ifdef HAVE_MESSAGES
if (0 == MHD_get_master (connection->daemon)->digest_auth_rand_size)
@@ -1612,6 +1799,10 @@ calculate_add_nonce_with_retry (struct MHD_Connection
*const connection,
const size_t digest_size = digest_get_size (da);
char nonce2[NONCE_STD_LEN (MAX_DIGEST) + 1];
uint64_t timestamp2;
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ if (digest_ext_error (da))
+ return false; /* No need to re-try */
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
if (0 == MHD_get_master (connection->daemon)->nonce_nc_size)
return false; /* No need to re-try */
@@ -1652,6 +1843,7 @@ calculate_add_nonce_with_retry (struct MHD_Connection
*const connection,
if (timestamp1 == timestamp2)
timestamp2 -= 2; /* Fallback value */
}
+ digest_reset (da);
if (! calculate_add_nonce (connection, timestamp2, realm, realm_len, da,
nonce2))
{
@@ -1690,7 +1882,7 @@ calc_userdigest (struct DigestAlgorithm *da,
const char *password,
uint8_t *ha1_bin)
{
- digest_init (da);
+ mhd_assert (! da->hashing);
digest_update (da, username, username_len);
digest_update_with_colon (da);
digest_update (da, realm, realm_len);
@@ -1725,8 +1917,10 @@ calc_userdigest (struct DigestAlgorithm *da,
* userdigest upon return
* @param userdigest_bin the size of the @a userdigest_bin buffer, must be
* at least #MHD_digest_get_hash_size(algo3) bytes long
- * @return MHD_YES on success, MHD_NO if @a userdigest_bin is too small or
- * if @a algo3 algorithm is not supported.
+ * @return MHD_YES on success,
+ * MHD_NO if @a userdigest_bin is too small or if @a algo3 algorithm is
+ * not supported (or external error has occurred,
+ * see #MHD_FEATURE_EXTERN_HASH).
* @sa #MHD_digest_auth_check_digest3()
* @note Available since #MHD_VERSION 0x00097535
* @ingroup authentication
@@ -1740,18 +1934,31 @@ MHD_digest_auth_calc_userdigest (enum
MHD_DigestAuthAlgo3 algo3,
size_t bin_buf_size)
{
struct DigestAlgorithm da;
- if (! digest_setup (&da, get_base_digest_algo (algo3)))
+ enum MHD_Result ret;
+ if (! digest_init_one_time (&da, get_base_digest_algo (algo3)))
return MHD_NO;
+
if (digest_get_size (&da) > bin_buf_size)
- return MHD_NO;
- calc_userdigest (&da,
- username,
- strlen (username),
- realm,
- strlen (realm),
- password,
- userdigest_bin);
- return MHD_YES;
+ ret = MHD_NO;
+ else
+ {
+ calc_userdigest (&da,
+ username,
+ strlen (username),
+ realm,
+ strlen (realm),
+ password,
+ userdigest_bin);
+ ret = MHD_YES;
+
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ if (digest_ext_error (&da))
+ ret = MHD_NO;
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
+ }
+ digest_deinit (&da);
+
+ return ret;
}
@@ -1775,7 +1982,7 @@ calc_userhash (struct DigestAlgorithm *da,
uint8_t *digest_bin)
{
mhd_assert (NULL != username);
- digest_init (da);
+ mhd_assert (! da->hashing);
digest_update (da, username, username_len);
digest_update_with_colon (da);
digest_update (da, realm, realm_len);
@@ -1815,8 +2022,10 @@ calc_userhash (struct DigestAlgorithm *da,
* upon return
* @param bin_buf_size the size of the @a userhash_bin buffer, must be
* at least #MHD_digest_get_hash_size(algo3) bytes long
- * @return MHD_YES on success, MHD_NO if @a bin_buf_size is too small or
- * if @a algo3 algorithm is not supported.
+ * @return MHD_YES on success,
+ * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is
+ * not supported (or external error has occurred,
+ * see #MHD_FEATURE_EXTERN_HASH)
* @note Available since #MHD_VERSION 0x00097535
* @ingroup authentication
*/
@@ -1828,17 +2037,30 @@ MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3
algo3,
size_t bin_buf_size)
{
struct DigestAlgorithm da;
- if (! digest_setup (&da, get_base_digest_algo (algo3)))
+ enum MHD_Result ret;
+
+ if (! digest_init_one_time (&da, get_base_digest_algo (algo3)))
return MHD_NO;
if (digest_get_size (&da) > bin_buf_size)
- return MHD_NO;
- calc_userhash (&da,
- username,
- strlen (username),
- realm,
- strlen (realm),
- userhash_bin);
- return MHD_YES;
+ ret = MHD_NO;
+ else
+ {
+ calc_userhash (&da,
+ username,
+ strlen (username),
+ realm,
+ strlen (realm),
+ userhash_bin);
+ ret = MHD_YES;
+
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ if (digest_ext_error (&da))
+ ret = MHD_NO;
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
+ }
+ digest_deinit (&da);
+
+ return ret;
}
@@ -1874,8 +2096,10 @@ MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo3
algo3,
* userhash string
* @param bin_buf_size the size of the @a userhash_bin buffer, must be
* at least #MHD_digest_get_hash_size(algo3)*2+1 chars long
- * @return MHD_YES on success, MHD_NO if @a bin_buf_size is too small or
- * if @a algo3 algorithm is not supported.
+ * @return MHD_YES on success,
+ * MHD_NO if @a bin_buf_size is too small or if @a algo3 algorithm is
+ * not supported (or external error has occurred,
+ * see #MHD_FEATURE_EXTERN_HASH).
* @note Available since #MHD_VERSION 0x00097535
* @ingroup authentication
*/
@@ -2302,12 +2526,12 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
uint32_t max_nc,
enum MHD_DigestAuthMultiQOP mqop,
enum MHD_DigestAuthMultiAlgo3 malgo3,
- char **pbuf)
+ char **pbuf,
+ struct DigestAlgorithm *da)
{
struct MHD_Daemon *daemon = MHD_get_master (connection->daemon);
enum MHD_DigestAuthAlgo3 c_algo; /**< Client's algorithm */
enum MHD_DigestAuthQOP c_qop; /**< Client's QOP */
- struct DigestAlgorithm da;
unsigned int digest_size;
uint8_t hash1_bin[MAX_DIGEST];
uint8_t hash2_bin[MAX_DIGEST];
@@ -2383,7 +2607,7 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
return MHD_DAUTH_WRONG_ALGO;
}
#endif /* ! MHD_SHA512_256_SUPPORT */
- if (! digest_setup (&da, get_base_digest_algo (c_algo)))
+ if (! digest_init_one_time (da, get_base_digest_algo (c_algo)))
MHD_PANIC (_ ("Wrong 'malgo3' value, API violation"));
/* Check 'mqop' value */
c_qop = params->qop;
@@ -2407,7 +2631,7 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
"non-standard extension.\n"));
#endif /* HAVE_MESSAGES */
- digest_size = digest_get_size (&da);
+ digest_size = digest_get_size (da);
/* ** A quick check for presence of all required parameters ** */
@@ -2525,11 +2749,18 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
else
{ /* Userhash */
mhd_assert (NULL != params->username.value.str);
- calc_userhash (&da, username, username_len, realm, realm_len, hash1_bin);
+ calc_userhash (da, username, username_len, realm, realm_len, hash1_bin);
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ if (digest_ext_error (da))
+ return MHD_DAUTH_ERROR;
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
mhd_assert (sizeof (tmp1) >= (2 * digest_size));
MHD_bin_to_hex (hash1_bin, digest_size, tmp1);
if (! is_param_equal_caseless (¶ms->username, tmp1, 2 * digest_size))
return MHD_DAUTH_WRONG_USERNAME;
+ /* To simplify the logic, the digest is reset here instead of resetting
+ before the next hash calculation. */
+ digest_reset (da);
}
/* 'username' valid */
@@ -2643,9 +2874,9 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
/* ** Build H(A2) and check URI match in the header and in the request ** */
/* Get 'uri' */
- digest_init (&da);
- digest_update_str (&da, connection->rq.method);
- digest_update_with_colon (&da);
+ mhd_assert (! da->hashing);
+ digest_update_str (da, connection->rq.method);
+ digest_update_with_colon (da);
#if 0
/* TODO: add support for "auth-int" */
digest_update_str (da, hentity);
@@ -2656,33 +2887,45 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
if (_MHD_UNQ_OK != unq_res)
return MHD_DAUTH_ERROR;
- digest_update (&da, unq_copy.str, unq_copy.len);
+ digest_update (da, unq_copy.str, unq_copy.len);
/* The next check will modify copied URI string */
if (! check_uri_match (connection, unq_copy.str, unq_copy.len))
return MHD_DAUTH_WRONG_URI;
- digest_calc_hash (&da, hash2_bin);
+ digest_calc_hash (da, hash2_bin);
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ /* Skip digest calculation external error check, the next one checks both */
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
/* Got H(A2) */
/* ** Build H(A1) ** */
if (NULL == userdigest)
- calc_userdigest (&da,
+ {
+ mhd_assert (! da->hashing);
+ digest_reset (da);
+ calc_userdigest (da,
username, username_len,
realm, realm_len,
password,
hash1_bin);
+ }
/* TODO: support '-sess' versions */
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ if (digest_ext_error (da))
+ return MHD_DAUTH_ERROR;
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
/* Got H(A1) */
/* ** Check 'response' ** */
- digest_init (&da);
+ mhd_assert (! da->hashing);
+ digest_reset (da);
/* Update digest with H(A1) */
mhd_assert (sizeof (tmp1) >= (digest_size * 2));
if (NULL == userdigest)
MHD_bin_to_hex (hash1_bin, digest_size, tmp1);
else
MHD_bin_to_hex (userdigest, digest_size, tmp1);
- digest_update (&da, (const uint8_t *) tmp1, digest_size * 2);
+ digest_update (da, (const uint8_t *) tmp1, digest_size * 2);
/* H(A1) is not needed anymore, reuse the buffer.
* Use hash1_bin for the client's 'response' decoded to binary form. */
@@ -2694,15 +2937,15 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
return MHD_DAUTH_RESPONSE_WRONG;
/* Update digest with ':' */
- digest_update_with_colon (&da);
+ digest_update_with_colon (da);
/* Update digest with 'nonce' text value */
unq_res = get_unquoted_param (¶ms->nonce, tmp1, ptmp2, &tmp2_size,
&unquoted);
if (_MHD_UNQ_OK != unq_res)
return MHD_DAUTH_ERROR;
- digest_update (&da, (const uint8_t *) unquoted.str, unquoted.len);
+ digest_update (da, (const uint8_t *) unquoted.str, unquoted.len);
/* Update digest with ':' */
- digest_update_with_colon (&da);
+ digest_update_with_colon (da);
if (MHD_DIGEST_AUTH_QOP_NONE != c_qop)
{
/* Update digest with 'nc' text value */
@@ -2710,33 +2953,37 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
&unquoted);
if (_MHD_UNQ_OK != unq_res)
return MHD_DAUTH_ERROR;
- digest_update (&da, (const uint8_t *) unquoted.str, unquoted.len);
+ digest_update (da, (const uint8_t *) unquoted.str, unquoted.len);
/* Update digest with ':' */
- digest_update_with_colon (&da);
+ digest_update_with_colon (da);
/* Update digest with 'cnonce' value */
unq_res = get_unquoted_param (¶ms->cnonce, tmp1, ptmp2, &tmp2_size,
&unquoted);
if (_MHD_UNQ_OK != unq_res)
return MHD_DAUTH_ERROR;
- digest_update (&da, (const uint8_t *) unquoted.str, unquoted.len);
+ digest_update (da, (const uint8_t *) unquoted.str, unquoted.len);
/* Update digest with ':' */
- digest_update_with_colon (&da);
+ digest_update_with_colon (da);
/* Update digest with 'qop' value */
unq_res = get_unquoted_param (¶ms->qop_raw, tmp1, ptmp2, &tmp2_size,
&unquoted);
if (_MHD_UNQ_OK != unq_res)
return MHD_DAUTH_ERROR;
- digest_update (&da, (const uint8_t *) unquoted.str, unquoted.len);
+ digest_update (da, (const uint8_t *) unquoted.str, unquoted.len);
/* Update digest with ':' */
- digest_update_with_colon (&da);
+ digest_update_with_colon (da);
}
/* Update digest with H(A2) */
MHD_bin_to_hex (hash2_bin, digest_size, tmp1);
- digest_update (&da, (const uint8_t *) tmp1, digest_size * 2);
+ digest_update (da, (const uint8_t *) tmp1, digest_size * 2);
/* H(A2) is not needed anymore, reuse the buffer.
* Use hash2_bin for the calculated response in binary form */
- digest_calc_hash (&da, hash2_bin);
+ digest_calc_hash (da, hash2_bin);
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ if (digest_ext_error (da))
+ return MHD_DAUTH_ERROR;
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
if (0 != memcmp (hash1_bin, hash2_bin, digest_size))
return MHD_DAUTH_RESPONSE_WRONG;
@@ -2746,6 +2993,8 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
mhd_assert (sizeof(tmp1) >= (NONCE_STD_LEN (digest_size) + 1));
/* It was already checked that 'nonce' (including timestamp) was generated
by MHD. */
+ mhd_assert (! da->hashing);
+ digest_reset (da);
calculate_nonce (nonce_time,
connection->rq.http_mthd,
connection->rq.method,
@@ -2759,9 +3008,13 @@ digest_auth_check_all_inner (struct MHD_Connection
*connection,
realm,
realm_len,
daemon->dauth_bind_type,
- &da,
+ da,
tmp1);
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ if (digest_ext_error (da))
+ return MHD_DAUTH_ERROR;
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
if (! is_param_equal (¶ms->nonce, tmp1,
NONCE_STD_LEN (digest_size)))
@@ -2816,13 +3069,16 @@ digest_auth_check_all (struct MHD_Connection
*connection,
{
enum MHD_DigestAuthResult res;
char *buf;
+ struct DigestAlgorithm da;
buf = NULL;
+ digest_setup_zero (&da);
res = digest_auth_check_all_inner (connection, realm, username, password,
userdigest,
nonce_timeout,
max_nc, mqop, malgo3,
- &buf);
+ &buf, &da);
+ digest_deinit (&da);
if (NULL != buf)
free (buf);
@@ -3173,20 +3429,8 @@ MHD_digest_auth_check_digest (struct MHD_Connection
*connection,
/**
- * Queues a response to request authentication from the client
- *
- * This function modifies provided @a response. The @a response must not be
- * reused and should be destroyed (by #MHD_destroy_response()) after call of
- * this function.
- *
- * If @a mqop allows both RFC 2069 (MHD_DIGEST_AUTH_QOP_NONE) and QOP with
- * value, then response is formed like if MHD_DIGEST_AUTH_QOP_NONE bit was
- * not set, because such response should be backward-compatible with RFC 2069.
- *
- * If @a mqop allows only MHD_DIGEST_AUTH_MULT_QOP_NONE, then the response is
- * formed in strict accordance with RFC 2069 (no 'qop', no 'userhash', no
- * 'charset'). For better compatibility with clients, it is recommended (but
- * not required) to set @a domain to NULL in this mode.
+ * Internal version of #MHD_queue_auth_required_response3() to simplify
+ * cleanups.
*
* @param connection the MHD connection structure
* @param realm the realm presented to the client
@@ -3226,21 +3470,26 @@ MHD_digest_auth_check_digest (struct MHD_Connection
*connection,
* @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
* added, indicating for the client that UTF-8 encoding
* is preferred
+ * @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
+ * added, indicating for the client that UTF-8 encoding
+ * is preferred
* @return #MHD_YES on success, #MHD_NO otherwise
* @note Available since #MHD_VERSION 0x00097526
* @ingroup authentication
*/
-_MHD_EXTERN enum MHD_Result
-MHD_queue_auth_required_response3 (struct MHD_Connection *connection,
- const char *realm,
- const char *opaque,
- const char *domain,
- struct MHD_Response *response,
- int signal_stale,
- enum MHD_DigestAuthMultiQOP mqop,
- enum MHD_DigestAuthMultiAlgo3 malgo3,
- int userhash_support,
- int prefer_utf8)
+static enum MHD_Result
+queue_auth_required_response3_inner (struct MHD_Connection *connection,
+ const char *realm,
+ const char *opaque,
+ const char *domain,
+ struct MHD_Response *response,
+ int signal_stale,
+ enum MHD_DigestAuthMultiQOP mqop,
+ enum MHD_DigestAuthMultiAlgo3 malgo3,
+ int userhash_support,
+ int prefer_utf8,
+ char **buf_ptr,
+ struct DigestAlgorithm *da)
{
static const char prefix_realm[] = "realm=\"";
static const char prefix_qop[] = "qop=\"";
@@ -3258,7 +3507,6 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
size_t buf_size;
char *buf;
size_t p; /* The position in the buffer */
- struct DigestAlgorithm da;
if (0 != (((unsigned int) malgo3) & MHD_DIGEST_AUTH_ALGO3_SESSION))
{
@@ -3302,7 +3550,7 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
(((unsigned int) mqop) & MHD_DIGEST_AUTH_MULT_QOP_ANY_NON_INT))
MHD_PANIC (_ ("Wrong 'mqop' value, API violation"));
- if (! digest_setup (&da, get_base_digest_algo (s_algo)))
+ if (! digest_init_one_time (da, get_base_digest_algo (s_algo)))
MHD_PANIC (_ ("Wrong 'algo' value, API violation"));
if (MHD_DIGEST_AUTH_MULT_QOP_NONE == mqop)
@@ -3348,6 +3596,7 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
if ((NULL != memchr (realm, '\r', realm_len)) ||
(NULL != memchr (realm, '\n', realm_len)))
return MHD_NO;
+
buf_size += realm_len * 2; /* Quoting may double the size */
/* 'qop="xxxx", ' */
if (MHD_DIGEST_AUTH_MULT_QOP_NONE != mqop)
@@ -3379,7 +3628,7 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
}
/* 'nonce="xxxx", ' */
buf_size += MHD_STATICSTR_LEN_ (prefix_nonce) + 3; /* 3 for '", ' */
- buf_size += NONCE_STD_LEN (digest_get_size (&da)); /* Escaping not needed */
+ buf_size += NONCE_STD_LEN (digest_get_size (da)); /* Escaping not needed */
/* 'opaque="xxxx", ' */
if (NULL != opaque)
{
@@ -3388,6 +3637,7 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
if ((NULL != memchr (opaque, '\r', opaque_len)) ||
(NULL != memchr (opaque, '\n', opaque_len)))
return MHD_NO;
+
buf_size += opaque_len * 2; /* Quoting may double the size */
}
else
@@ -3400,6 +3650,7 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
if ((NULL != memchr (domain, '\r', domain_len)) ||
(NULL != memchr (domain, '\n', domain_len)))
return MHD_NO;
+
buf_size += domain_len * 2; /* Quoting may double the size */
}
else
@@ -3421,6 +3672,7 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
buf = malloc (buf_size);
if (NULL == buf)
return MHD_NO;
+ *buf_ptr = buf;
/* Build the challenge string */
p = 0;
@@ -3444,7 +3696,6 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
MHD_DLOG (connection->daemon,
_ ("The 'realm' is too large after 'quoting'.\n"));
#endif /* HAVE_MESSAGES */
- free (buf);
return MHD_NO;
}
p += quoted_size;
@@ -3507,9 +3758,20 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
memcpy (buf + p, prefix_nonce,
MHD_STATICSTR_LEN_ (prefix_nonce));
p += MHD_STATICSTR_LEN_ (prefix_nonce);
- mhd_assert ((buf_size - p) >= (NONCE_STD_LEN (digest_get_size (&da))));
- if (! calculate_add_nonce_with_retry (connection, realm, &da, buf + p))
+ mhd_assert ((buf_size - p) >= (NONCE_STD_LEN (digest_get_size (da))));
+ if (! calculate_add_nonce_with_retry (connection, realm, da, buf + p))
{
+#ifdef MHD_DIGEST_HAS_EXT_ERROR
+ if (digest_ext_error (da))
+ {
+#ifdef HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ _ ("TLS library reported hash calculation error, nonce could "
+ "not be generated.\n"));
+#endif /* HAVE_MESSAGES */
+ return MHD_NO;
+ }
+#endif /* MHD_DIGEST_HAS_EXT_ERROR */
#ifdef HAVE_MESSAGES
MHD_DLOG (connection->daemon,
_ ("Could not register nonce. Client's requests with this "
@@ -3518,7 +3780,7 @@ MHD_queue_auth_required_response3 (struct MHD_Connection
*connection,
#endif /* HAVE_MESSAGES */
(void) 0; /* Mute compiler warning for builds without messages */
}
- p += NONCE_STD_LEN (digest_get_size (&da));
+ p += NONCE_STD_LEN (digest_get_size (da));
buf[p++] = '\"';
buf[p++] = ',';
buf[p++] = ' ';
@@ -3588,15 +3850,108 @@ MHD_queue_auth_required_response3 (struct
MHD_Connection *connection,
MHD_DLOG (connection->daemon,
_ ("Failed to add Digest auth header.\n"));
#endif /* HAVE_MESSAGES */
- free (buf);
return MHD_NO;
}
- free (buf);
return MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
}
+/**
+ * Queues a response to request authentication from the client
+ *
+ * This function modifies provided @a response. The @a response must not be
+ * reused and should be destroyed (by #MHD_destroy_response()) after call of
+ * this function.
+ *
+ * If @a mqop allows both RFC 2069 (MHD_DIGEST_AUTH_QOP_NONE) and QOP with
+ * value, then response is formed like if MHD_DIGEST_AUTH_QOP_NONE bit was
+ * not set, because such response should be backward-compatible with RFC 2069.
+ *
+ * If @a mqop allows only MHD_DIGEST_AUTH_MULT_QOP_NONE, then the response is
+ * formed in strict accordance with RFC 2069 (no 'qop', no 'userhash', no
+ * 'charset'). For better compatibility with clients, it is recommended (but
+ * not required) to set @a domain to NULL in this mode.
+ *
+ * @param connection the MHD connection structure
+ * @param realm the realm presented to the client
+ * @param opaque the string for opaque value, can be NULL, but NULL is
+ * not recommended for better compatibility with clients;
+ * the recommended format is hex or Base64 encoded string
+ * @param domain the optional space-separated list of URIs for which the
+ * same authorisation could be used, URIs can be in form
+ * "path-absolute" (the path for the same host with initial
slash)
+ * or in form "absolute-URI" (the full path with protocol), in
+ * any case client may assume that URI is in the same "protection
+ * space" if it starts with any of values specified here;
+ * could be NULL (clients typically assume that the same
+ * credentials could be used for any URI on the same host)
+ * @param response the reply to send; should contain the "access denied"
+ * body; note that this function sets the "WWW Authenticate"
+ * header and that the caller should not do this;
+ * the NULL is tolerated
+ * @param signal_stale set to #MHD_YES if the nonce is stale to add
'stale=true'
+ * to the authentication header, this instructs the client
+ * to retry immediately with the new nonce and the same
+ * credentials, without asking user for the new password
+ * @param mqop the QOP to use
+ * @param malgo3 digest algorithm to use, MHD selects; if several algorithms
+ * are allowed then MD5 is preferred (currently, may be changed
+ * in next versions)
+ * @param userhash_support if set to non-zero value (#MHD_YES) then support of
+ * userhash is indicated, the client may provide
+ * hash("username:realm") instead of username in
+ * clear text;
+ * note that clients are allowed to provide the
username
+ * in cleartext even if this parameter set to non-zero;
+ * when userhash is used, application must be ready to
+ * identify users by provided userhash value instead of
+ * username; see #MHD_digest_auth_calc_userhash() and
+ * #MHD_digest_auth_calc_userhash_hex()
+ * @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
+ * added, indicating for the client that UTF-8 encoding
+ * is preferred
+ * @return #MHD_YES on success, #MHD_NO otherwise
+ * @note Available since #MHD_VERSION 0x00097526
+ * @ingroup authentication
+ */
+_MHD_EXTERN enum MHD_Result
+MHD_queue_auth_required_response3 (struct MHD_Connection *connection,
+ const char *realm,
+ const char *opaque,
+ const char *domain,
+ struct MHD_Response *response,
+ int signal_stale,
+ enum MHD_DigestAuthMultiQOP mqop,
+ enum MHD_DigestAuthMultiAlgo3 malgo3,
+ int userhash_support,
+ int prefer_utf8)
+{
+ struct DigestAlgorithm da;
+ char *buf_ptr;
+ enum MHD_Result ret;
+
+ buf_ptr = NULL;
+ digest_setup_zero (&da);
+ ret = queue_auth_required_response3_inner (connection,
+ realm,
+ opaque,
+ domain,
+ response,
+ signal_stale,
+ mqop,
+ malgo3,
+ userhash_support,
+ prefer_utf8,
+ &buf_ptr,
+ &da);
+ digest_deinit (&da);
+ if (NULL != buf_ptr)
+ free (buf_ptr);
+ return ret;
+}
+
+
/**
* Queues a response to request authentication from the client
*
diff --git a/src/microhttpd/md5.h b/src/microhttpd/md5.h
index 7d522254..71cb29f3 100644
--- a/src/microhttpd/md5.h
+++ b/src/microhttpd/md5.h
@@ -123,4 +123,9 @@ void
MHD_MD5_finish (struct Md5Ctx *ctx,
uint8_t digest[MD5_DIGEST_SIZE]);
+/**
+ * Indicates that function MHD_MD5_finish() (without context reset) is
available
+ */
+#define MHD_MD5_HAS_FINISH 1
+
#endif /* MHD_MD5_H */
diff --git a/src/microhttpd/md5_ext.c b/src/microhttpd/md5_ext.c
new file mode 100644
index 00000000..5466f704
--- /dev/null
+++ b/src/microhttpd/md5_ext.c
@@ -0,0 +1,95 @@
+/*
+ This file is part of GNU libmicrohttpd
+ Copyright (C) 2022 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ 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 GNU libmicrohttpd.
+ If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file microhttpd/md5_ext.h
+ * @brief Wrapper for MD5 calculation performed by TLS library
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include <gnutls/crypto.h>
+#include "md5_ext.h"
+#include "mhd_assert.h"
+
+
+/**
+ * Initialise structure for MD5 calculation, allocate resources.
+ *
+ * This function must not be called more than one time for @a ctx.
+ *
+ * @param ctx the calculation context
+ */
+void
+MHD_MD5_init_one_time (struct Md5CtxExt *ctx)
+{
+ ctx->handle = NULL;
+ ctx->ext_error = gnutls_hash_init (&ctx->handle, GNUTLS_DIG_MD5);
+ if ((0 != ctx->ext_error) && (NULL != ctx->handle))
+ {
+ gnutls_free (ctx->handle);
+ ctx->handle = NULL;
+ }
+ else
+ mhd_assert (NULL != ctx->handle);
+}
+
+
+/**
+ * Process portion of bytes.
+ *
+ * @param ctx the calculation context
+ * @param data bytes to add to hash
+ * @param length number of bytes in @a data
+ */
+void
+MHD_MD5_update (struct Md5CtxExt *ctx,
+ const uint8_t *data,
+ size_t length)
+{
+ if (0 == ctx->ext_error)
+ ctx->ext_error = gnutls_hash (ctx->handle, data, length);
+}
+
+
+/**
+ * Finalise MD5 calculation, return digest, reset hash calculation.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #MD5_DIGEST_SIZE bytes
+ */
+void
+MHD_MD5_finish_reset (struct Md5CtxExt *ctx,
+ uint8_t digest[MD5_DIGEST_SIZE])
+{
+ if (0 == ctx->ext_error)
+ gnutls_hash_output (ctx->handle, digest);
+}
+
+
+/**
+ * Free allocated resources.
+ *
+ * @param ctx the calculation context
+ */
+void
+MHD_MD5_deinit (struct Md5CtxExt *ctx)
+{
+ if (NULL != ctx->handle)
+ gnutls_hash_deinit (ctx->handle, NULL);
+}
diff --git a/src/microhttpd/md5_ext.h b/src/microhttpd/md5_ext.h
new file mode 100644
index 00000000..b7437c03
--- /dev/null
+++ b/src/microhttpd/md5_ext.h
@@ -0,0 +1,115 @@
+/*
+ This file is part of GNU libmicrohttpd
+ Copyright (C) 2022 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ 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 GNU libmicrohttpd.
+ If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file microhttpd/md5_ext.h
+ * @brief Wrapper declarations for MD5 calculation performed by TLS library
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_MD5_EXT_H
+#define MHD_MD5_EXT_H 1
+
+#include "mhd_options.h"
+#include <stdint.h>
+#ifdef HAVE_STDDEF_H
+#include <stddef.h> /* for size_t */
+#endif /* HAVE_STDDEF_H */
+
+/**
+ * Size of MD5 resulting digest in bytes
+ * This is the final digest size, not intermediate hash.
+ */
+#define MD5_DIGEST_SIZE (16)
+
+/* Actual declaration is in GnuTLS lib header */
+struct hash_hd_st;
+
+/**
+ * Indicates that struct Md5CtxExt has 'ext_error'
+ */
+#define MHD_MD5_HAS_EXT_ERROR 1
+
+/**
+ * MD5 calculation context
+ */
+struct Md5CtxExt
+{
+ struct hash_hd_st *handle; /**< Hash calculation handle */
+ int ext_error; /**< Non-zero if external error occurs during init or hashing
*/
+};
+
+/**
+ * Indicates that MHD_MD5_init_one_time() function is present.
+ */
+#define MHD_MD5_HAS_INIT_ONE_TIME 1
+
+/**
+ * Initialise structure for MD5 calculation, allocate resources.
+ *
+ * This function must not be called more than one time for @a ctx.
+ *
+ * @param ctx the calculation context
+ */
+void
+MHD_MD5_init_one_time (struct Md5CtxExt *ctx);
+
+
+/**
+ * MD5 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_MD5_update (struct Md5CtxExt *ctx,
+ const uint8_t *data,
+ size_t length);
+
+
+/**
+ * Indicates that MHD_MD5_finish_reset() function is available
+ */
+#define MHD_MD5_HAS_FINISH_RESET 1
+
+/**
+ * Finalise MD5 calculation, return digest, reset hash calculation.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #MD5_DIGEST_SIZE bytes
+ */
+void
+MHD_MD5_finish_reset (struct Md5CtxExt *ctx,
+ uint8_t digest[MD5_DIGEST_SIZE]);
+
+/**
+ * Indicates that MHD_MD5_deinit() function is present
+ */
+#define MHD_MD5_HAS_DEINIT 1
+
+/**
+ * Free allocated resources.
+ *
+ * @param ctx the calculation context
+ */
+void
+MHD_MD5_deinit (struct Md5CtxExt *ctx);
+
+#endif /* MHD_MD5_EXT_H */
diff --git a/src/microhttpd/mhd_md5_wrap.h b/src/microhttpd/mhd_md5_wrap.h
new file mode 100644
index 00000000..98a5d958
--- /dev/null
+++ b/src/microhttpd/mhd_md5_wrap.h
@@ -0,0 +1,98 @@
+/*
+ This file is part of GNU libmicrohttpd
+ Copyright (C) 2022 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ 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 GNU libmicrohttpd.
+ If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file microhttpd/mhd_md5_wrap.h
+ * @brief Simple wrapper for selection of built-in/external MD5 implementation
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_MD5_WRAP_H
+#define MHD_MD5_WRAP_H 1
+
+#include "mhd_options.h"
+#ifndef MHD_MD5_SUPPORT
+#error This file must be used only when MD5 is enabled
+#endif
+#ifndef MHD_MD5_TLSLIB
+#include "md5.h"
+#else /* MHD_MD5_TLSLIB */
+#include "md5_ext.h"
+#endif /* MHD_MD5_TLSLIB */
+
+#ifndef MD5_DIGEST_SIZE
+/**
+ * Size of MD5 resulting digest in bytes
+ * This is the final digest size, not intermediate hash.
+ */
+#define MD5_DIGEST_SIZE (16)
+#endif /* ! MD5_DIGEST_SIZE */
+
+#ifndef MD5_DIGEST_STRING_SIZE
+/**
+ * Size of MD5 digest string in chars including termination NUL.
+ */
+#define MD5_DIGEST_STRING_SIZE ((MD5_DIGEST_SIZE) * 2 + 1)
+#endif /* ! MD5_DIGEST_STRING_SIZE */
+
+#ifndef MHD_MD5_TLSLIB
+/**
+ * Universal ctx type mapped for chosen implementation
+ */
+#define Md5CtxWr Md5Ctx
+#else /* MHD_MD5_TLSLIB */
+/**
+ * Universal ctx type mapped for chosen implementation
+ */
+#define Md5CtxWr Md5CtxExt
+#endif /* MHD_MD5_TLSLIB */
+
+#ifndef MHD_MD5_HAS_INIT_ONE_TIME
+/**
+ * Setup and prepare ctx for hash calculation
+ */
+#define MHD_MD5_init_one_time(ctx) MHD_MD5_init(ctx)
+#endif /* ! MHD_MD5_HAS_INIT_ONE_TIME */
+
+#ifndef MHD_MD5_HAS_FINISH_RESET
+/**
+ * Re-use the same ctx for the new hashing after digest calculated
+ */
+#define MHD_MD5_reset(ctx) MHD_MD5_init(ctx)
+/**
+ * Finalise MD5 calculation, return digest, reset hash calculation.
+ */
+#define MHD_MD5_finish_reset(ctx,digest) MHD_MD5_finish(ctx,digest), \
+ MHD_MD5_reset(ctx)
+
+#else /* MHD_MD5_HAS_FINISH_RESET */
+#define MHD_MD5_reset(ctx) (void)0
+#endif /* MHD_MD5_HAS_FINISH_RESET */
+
+#ifndef MHD_MD5_HAS_DEINIT
+#define MHD_MD5_deinit(ignore) (void)0
+#endif /* HAVE_MD5_DEINIT */
+
+/* Sanity checks */
+
+#if ! defined(MHD_MD5_HAS_FINISH_RESET) && ! defined(MHD_MD5_HAS_FINISH)
+#error Required at least one of MHD_MD5_finish_reset(), MHD_MD5_finish_reset()
+#endif /* ! MHD_MD5_HAS_FINISH_RESET && ! MHD_MD5_HAS_FINISH */
+
+#endif /* MHD_MD5_WRAP_H */
diff --git a/src/microhttpd/mhd_sha256_wrap.h b/src/microhttpd/mhd_sha256_wrap.h
new file mode 100644
index 00000000..5879c2ca
--- /dev/null
+++ b/src/microhttpd/mhd_sha256_wrap.h
@@ -0,0 +1,100 @@
+/*
+ This file is part of GNU libmicrohttpd
+ Copyright (C) 2022 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ 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 GNU libmicrohttpd.
+ If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file microhttpd/mhd_sha256_wrap.h
+ * @brief Simple wrapper for selection of built-in/external SHA-256
+ * implementation
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_SHA256_WRAP_H
+#define MHD_SHA256_WRAP_H 1
+
+#include "mhd_options.h"
+#include "mhd_options.h"
+#ifndef MHD_SHA256_SUPPORT
+#error This file must be used only when SHA-256 is enabled
+#endif
+#ifndef MHD_SHA256_TLSLIB
+#include "sha256.h"
+#else /* MHD_SHA256_TLSLIB */
+#include "sha256_ext.h"
+#endif /* MHD_SHA256_TLSLIB */
+
+#ifndef SHA256_DIGEST_SIZE
+/**
+ * Size of SHA-256 resulting digest in bytes
+ * This is the final digest size, not intermediate hash.
+ */
+#define SHA256_DIGEST_SIZE (32)
+#endif /* ! SHA256_DIGEST_SIZE */
+
+#ifndef SHA256_DIGEST_STRING_SIZE
+/**
+ * Size of MD5 digest string in chars including termination NUL.
+ */
+#define SHA256_DIGEST_STRING_SIZE ((SHA256_DIGEST_SIZE) * 2 + 1)
+#endif /* ! SHA256_DIGEST_STRING_SIZE */
+
+#ifndef MHD_SHA256_TLSLIB
+/**
+ * Universal ctx type mapped for chosen implementation
+ */
+#define Sha256CtxWr Sha256Ctx
+#else /* MHD_SHA256_TLSLIB */
+/**
+ * Universal ctx type mapped for chosen implementation
+ */
+#define Sha256CtxWr Sha256CtxExt
+#endif /* MHD_SHA256_TLSLIB */
+
+#ifndef MHD_SHA256_HAS_INIT_ONE_TIME
+/**
+ * Setup and prepare ctx for hash calculation
+ */
+#define MHD_SHA256_init_one_time(ctx) MHD_SHA256_init(ctx)
+#endif /* ! MHD_SHA256_HAS_INIT_ONE_TIME */
+
+#ifndef MHD_SHA256_HAS_FINISH_RESET
+/**
+ * Re-use the same ctx for the new hashing after digest calculated
+ */
+#define MHD_SHA256_reset(ctx) MHD_SHA256_init(ctx)
+/**
+ * Finalise MD5 calculation, return digest, reset hash calculation.
+ */
+#define MHD_SHA256_finish_reset(ctx,digest) MHD_SHA256_finish(ctx,digest), \
+ MHD_SHA256_reset(ctx)
+
+#else /* MHD_SHA256_HAS_FINISH_RESET */
+#define MHD_SHA256_reset(ctx) (void)0
+#endif /* MHD_SHA256_HAS_FINISH_RESET */
+
+#ifndef MHD_SHA256_HAS_DEINIT
+#define MHD_SHA256_deinit(ignore) (void)0
+#endif /* HAVE_SHA256_DEINIT */
+
+/* Sanity checks */
+
+#if ! defined(MHD_SHA256_HAS_FINISH_RESET) && ! defined(MHD_SHA256_HAS_FINISH)
+#error Required MHD_SHA256_finish_reset() or MHD_SHA256_finish_reset()
+#endif /* ! MHD_SHA256_HAS_FINISH_RESET && ! MHD_SHA256_HAS_FINISH */
+
+#endif /* MHD_SHA256_WRAP_H */
diff --git a/src/microhttpd/sha256.h b/src/microhttpd/sha256.h
index c3d32e9c..9069a59a 100644
--- a/src/microhttpd/sha256.h
+++ b/src/microhttpd/sha256.h
@@ -114,4 +114,9 @@ void
MHD_SHA256_finish (struct Sha256Ctx *ctx,
uint8_t digest[SHA256_DIGEST_SIZE]);
+/**
+ * Indicates that function MHD_SHA256_finish() (without context reset) is
available
+ */
+#define MHD_SHA256_HAS_FINISH 1
+
#endif /* MHD_SHA256_H */
diff --git a/src/microhttpd/sha256_ext.c b/src/microhttpd/sha256_ext.c
new file mode 100644
index 00000000..d1c2a6ed
--- /dev/null
+++ b/src/microhttpd/sha256_ext.c
@@ -0,0 +1,95 @@
+/*
+ This file is part of GNU libmicrohttpd
+ Copyright (C) 2022 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ 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 GNU libmicrohttpd.
+ If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file microhttpd/sha256_ext.h
+ * @brief Wrapper for SHA-256 calculation performed by TLS library
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include <gnutls/crypto.h>
+#include "sha256_ext.h"
+#include "mhd_assert.h"
+
+
+/**
+ * Initialise structure for SHA-256 calculation, allocate resources.
+ *
+ * This function must not be called more than one time for @a ctx.
+ *
+ * @param ctx the calculation context
+ */
+void
+MHD_SHA256_init_one_time (struct Sha256CtxExt *ctx)
+{
+ ctx->handle = NULL;
+ ctx->ext_error = gnutls_hash_init (&ctx->handle, GNUTLS_DIG_SHA256);
+ if ((0 != ctx->ext_error) && (NULL != ctx->handle))
+ {
+ gnutls_free (ctx->handle);
+ ctx->handle = NULL;
+ }
+ else
+ mhd_assert (NULL != ctx->handle);
+}
+
+
+/**
+ * Process portion of bytes.
+ *
+ * @param ctx the calculation context
+ * @param data bytes to add to hash
+ * @param length number of bytes in @a data
+ */
+void
+MHD_SHA256_update (struct Sha256CtxExt *ctx,
+ const uint8_t *data,
+ size_t length)
+{
+ if (0 == ctx->ext_error)
+ ctx->ext_error = gnutls_hash (ctx->handle, data, length);
+}
+
+
+/**
+ * Finalise SHA-256 calculation, return digest, reset hash calculation.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #SHA256_DIGEST_SIZE bytes
+ */
+void
+MHD_SHA256_finish_reset (struct Sha256CtxExt *ctx,
+ uint8_t digest[SHA256_DIGEST_SIZE])
+{
+ if (0 == ctx->ext_error)
+ gnutls_hash_output (ctx->handle, digest);
+}
+
+
+/**
+ * Free allocated resources.
+ *
+ * @param ctx the calculation context
+ */
+void
+MHD_SHA256_deinit (struct Sha256CtxExt *ctx)
+{
+ if (NULL != ctx->handle)
+ gnutls_hash_deinit (ctx->handle, NULL);
+}
diff --git a/src/microhttpd/sha256_ext.h b/src/microhttpd/sha256_ext.h
new file mode 100644
index 00000000..7d2ee6a5
--- /dev/null
+++ b/src/microhttpd/sha256_ext.h
@@ -0,0 +1,115 @@
+/*
+ This file is part of GNU libmicrohttpd
+ Copyright (C) 2022 Evgeny Grin (Karlson2k)
+
+ GNU libmicrohttpd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ 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 GNU libmicrohttpd.
+ If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file microhttpd/sha256_ext.h
+ * @brief Wrapper declarations for SHA-256 calculation performed by TLS
library
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_SHA256_EXT_H
+#define MHD_SHA256_EXT_H 1
+
+#include "mhd_options.h"
+#include <stdint.h>
+#ifdef HAVE_STDDEF_H
+#include <stddef.h> /* for size_t */
+#endif /* HAVE_STDDEF_H */
+
+/**
+ * Size of SHA-256 resulting digest in bytes
+ * This is the final digest size, not intermediate hash.
+ */
+#define SHA256_DIGEST_SIZE (32)
+
+/* Actual declaration is in GnuTLS lib header */
+struct hash_hd_st;
+
+/**
+ * Indicates that struct Sha256CtxExt has 'ext_error'
+ */
+#define MHD_SHA256_HAS_EXT_ERROR 1
+
+/**
+ * SHA-256 calculation context
+ */
+struct Sha256CtxExt
+{
+ struct hash_hd_st *handle; /**< Hash calculation handle */
+ int ext_error; /**< Non-zero if external error occurs during init or hashing
*/
+};
+
+/**
+ * Indicates that MHD_SHA256_init_one_time() function is present.
+ */
+#define MHD_SHA256_HAS_INIT_ONE_TIME 1
+
+/**
+ * Initialise structure for SHA-256 calculation, allocate resources.
+ *
+ * This function must not be called more than one time for @a ctx.
+ *
+ * @param ctx the calculation context
+ */
+void
+MHD_SHA256_init_one_time (struct Sha256CtxExt *ctx);
+
+
+/**
+ * SHA-256 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_SHA256_update (struct Sha256CtxExt *ctx,
+ const uint8_t *data,
+ size_t length);
+
+
+/**
+ * Indicates that MHD_SHA256_finish_reset() function is available
+ */
+#define MHD_SHA256_HAS_FINISH_RESET 1
+
+/**
+ * Finalise SHA-256 calculation, return digest, reset hash calculation.
+ *
+ * @param ctx the calculation context
+ * @param[out] digest set to the hash, must be #SHA256_DIGEST_SIZE bytes
+ */
+void
+MHD_SHA256_finish_reset (struct Sha256CtxExt *ctx,
+ uint8_t digest[SHA256_DIGEST_SIZE]);
+
+/**
+ * Indicates that MHD_SHA256_deinit() function is present
+ */
+#define MHD_SHA256_HAS_DEINIT 1
+
+/**
+ * Free allocated resources.
+ *
+ * @param ctx the calculation context
+ */
+void
+MHD_SHA256_deinit (struct Sha256CtxExt *ctx);
+
+#endif /* MHD_SHA256_EXT_H */
diff --git a/src/microhttpd/test_dauth_userdigest.c
b/src/microhttpd/test_dauth_userdigest.c
index 6b15a282..f467be6d 100644
--- a/src/microhttpd/test_dauth_userdigest.c
+++ b/src/microhttpd/test_dauth_userdigest.c
@@ -23,12 +23,19 @@
* @author Karlson2k (Evgeny Grin)
*/
+#include "mhd_options.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "microhttpd.h"
#include "test_helpers.h"
+#if defined(MHD_HTTPS_REQUIRE_GCRYPT) && \
+ (defined(MHD_SHA256_TLSLIB) || defined(MHD_MD5_TLSLIB))
+#define NEED_GCRYP_INIT 1
+#include <gcrypt.h>
+#endif /* MHD_HTTPS_REQUIRE_GCRYPT && (MHD_SHA256_TLSLIB || MHD_MD5_TLSLIB) */
+
static int verbose = 1; /* verbose level (0-1)*/
/* Declarations and data */
@@ -619,6 +626,13 @@ main (int argc, char *argv[])
if (has_param (argc, argv, "-s") || has_param (argc, argv, "--silent"))
verbose = 0;
+#ifdef NEED_GCRYP_INIT
+ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+#ifdef GCRYCTL_INITIALIZATION_FINISHED
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+#endif /* GCRYCTL_INITIALIZATION_FINISHED */
+#endif /* NEED_GCRYP_INIT */
+
if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
num_failed += test_md5 ();
num_failed += test_md5_failure ();
diff --git a/src/microhttpd/test_dauth_userhash.c
b/src/microhttpd/test_dauth_userhash.c
index 633ab4b9..c145beb0 100644
--- a/src/microhttpd/test_dauth_userhash.c
+++ b/src/microhttpd/test_dauth_userhash.c
@@ -26,9 +26,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "mhd_options.h"
#include "microhttpd.h"
#include "test_helpers.h"
+#if defined(MHD_HTTPS_REQUIRE_GCRYPT) && \
+ (defined(MHD_SHA256_TLSLIB) || defined(MHD_MD5_TLSLIB))
+#define NEED_GCRYP_INIT 1
+#include <gcrypt.h>
+#endif /* MHD_HTTPS_REQUIRE_GCRYPT && (MHD_SHA256_TLSLIB || MHD_MD5_TLSLIB) */
+
static int verbose = 1; /* verbose level (0-1)*/
/* Declarations and data */
@@ -748,6 +755,13 @@ main (int argc, char *argv[])
if (has_param (argc, argv, "-s") || has_param (argc, argv, "--silent"))
verbose = 0;
+#ifdef NEED_GCRYP_INIT
+ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+#ifdef GCRYCTL_INITIALIZATION_FINISHED
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+#endif /* GCRYCTL_INITIALIZATION_FINISHED */
+#endif /* NEED_GCRYP_INIT */
+
if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
num_failed += test_md5 ();
num_failed += test_md5_failure ();
diff --git a/src/microhttpd/test_md5.c b/src/microhttpd/test_md5.c
index 13f9d46e..e6addab3 100644
--- a/src/microhttpd/test_md5.c
+++ b/src/microhttpd/test_md5.c
@@ -24,11 +24,16 @@
*/
#include "mhd_options.h"
-#include "md5.h"
+#include "mhd_md5_wrap.h"
#include "test_helpers.h"
#include <stdio.h>
#include <stdlib.h>
+#if defined(MHD_MD5_TLSLIB) && defined(MHD_HTTPS_REQUIRE_GCRYPT)
+#define NEED_GCRYP_INIT 1
+#include <gcrypt.h>
+#endif /* MHD_MD5_TLSLIB && MHD_HTTPS_REQUIRE_GCRYPT */
+
static int verbose = 0; /* verbose level (0-1)*/
@@ -293,9 +298,9 @@ check_result (const char *test_name,
{
char calc_str[MD5_DIGEST_STRING_SIZE];
bin2hex (calculated, MD5_DIGEST_SIZE, calc_str);
- printf (
- "PASSED: %s check %u: calculated digest %s match expected digest.\n",
- test_name, check_num, 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;
@@ -312,19 +317,28 @@ test1_str (void)
{
unsigned int i;
int num_failed = 0;
- struct Md5Ctx ctx;
+ struct Md5CtxWr ctx;
+
+ MHD_MD5_init_one_time (&ctx);
for (i = 0; i < units1_num; i++)
{
uint8_t digest[MD5_DIGEST_SIZE];
- MHD_MD5_init (&ctx);
MHD_MD5_update (&ctx, (const uint8_t *) data_units1[i].str_l.str,
data_units1[i].str_l.len);
- MHD_MD5_finish (&ctx, digest);
+ MHD_MD5_finish_reset (&ctx, digest);
+#ifdef MHD_MD5_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif
num_failed += check_result (__FUNCTION__, i, digest,
data_units1[i].digest);
}
+ MHD_MD5_deinit (&ctx);
return num_failed;
}
@@ -334,18 +348,27 @@ test1_bin (void)
{
unsigned int i;
int num_failed = 0;
- struct Md5Ctx ctx;
+ struct Md5CtxWr ctx;
+
+ MHD_MD5_init_one_time (&ctx);
for (i = 0; i < units2_num; i++)
{
uint8_t digest[MD5_DIGEST_SIZE];
- MHD_MD5_init (&ctx);
MHD_MD5_update (&ctx, data_units2[i].bin_l.bin, data_units2[i].bin_l.len);
- MHD_MD5_finish (&ctx, digest);
+ MHD_MD5_finish_reset (&ctx, digest);
+#ifdef MHD_MD5_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif
num_failed += check_result (__FUNCTION__, i, digest,
data_units2[i].digest);
}
+ MHD_MD5_deinit (&ctx);
return num_failed;
}
@@ -356,24 +379,33 @@ test2_str (void)
{
unsigned int i;
int num_failed = 0;
- struct Md5Ctx ctx;
+ struct Md5CtxWr ctx;
+
+ MHD_MD5_init_one_time (&ctx);
for (i = 0; i < units1_num; i++)
{
uint8_t digest[MD5_DIGEST_SIZE];
size_t part_s = data_units1[i].str_l.len / 4;
- MHD_MD5_init (&ctx);
MHD_MD5_update (&ctx, (const uint8_t *) "", 0);
MHD_MD5_update (&ctx, (const uint8_t *) data_units1[i].str_l.str, part_s);
MHD_MD5_update (&ctx, (const uint8_t *) "", 0);
MHD_MD5_update (&ctx, (const uint8_t *) data_units1[i].str_l.str + part_s,
data_units1[i].str_l.len - part_s);
MHD_MD5_update (&ctx, (const uint8_t *) "", 0);
- MHD_MD5_finish (&ctx, digest);
+ MHD_MD5_finish_reset (&ctx, digest);
+#ifdef MHD_MD5_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif
num_failed += check_result (__FUNCTION__, i, digest,
data_units1[i].digest);
}
+ MHD_MD5_deinit (&ctx);
return num_failed;
}
@@ -383,22 +415,31 @@ test2_bin (void)
{
unsigned int i;
int num_failed = 0;
- struct Md5Ctx ctx;
+ struct Md5CtxWr ctx;
+
+ MHD_MD5_init_one_time (&ctx);
for (i = 0; i < units2_num; i++)
{
uint8_t digest[MD5_DIGEST_SIZE];
size_t part_s = data_units2[i].bin_l.len * 2 / 3;
- MHD_MD5_init (&ctx);
MHD_MD5_update (&ctx, data_units2[i].bin_l.bin, part_s);
MHD_MD5_update (&ctx, (const uint8_t *) "", 0);
MHD_MD5_update (&ctx, data_units2[i].bin_l.bin + part_s,
data_units2[i].bin_l.len - part_s);
- MHD_MD5_finish (&ctx, digest);
+ MHD_MD5_finish_reset (&ctx, digest);
+#ifdef MHD_MD5_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif
num_failed += check_result (__FUNCTION__, i, digest,
data_units2[i].digest);
}
+ MHD_MD5_deinit (&ctx);
return num_failed;
}
@@ -414,7 +455,7 @@ test_unaligned (void)
unsigned int offset;
uint8_t *buf;
uint8_t *digest_buf;
- struct Md5Ctx ctx;
+ struct Md5CtxWr ctx;
const struct data_unit2 *const tdata = data_units2 + DATA_POS;
@@ -423,6 +464,8 @@ test_unaligned (void)
if ((NULL == buf) || (NULL == digest_buf))
exit (99);
+ MHD_MD5_init_one_time (&ctx);
+
for (offset = MAX_OFFSET; offset >= 1; --offset)
{
uint8_t *unaligned_digest;
@@ -433,12 +476,19 @@ test_unaligned (void)
unaligned_digest = digest_buf + MAX_OFFSET - offset;
memset (unaligned_digest, 0, MD5_DIGEST_SIZE);
- MHD_MD5_init (&ctx);
MHD_MD5_update (&ctx, unaligned_buf, tdata->bin_l.len);
- MHD_MD5_finish (&ctx, unaligned_digest);
+ MHD_MD5_finish_reset (&ctx, unaligned_digest);
+#ifdef MHD_MD5_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif
num_failed += check_result (__FUNCTION__, MAX_OFFSET - offset,
unaligned_digest, tdata->digest);
}
+ MHD_MD5_deinit (&ctx);
free (digest_buf);
free (buf);
return num_failed;
@@ -453,6 +503,13 @@ main (int argc, char *argv[])
if (has_param (argc, argv, "-v") || has_param (argc, argv, "--verbose"))
verbose = 1;
+#ifdef NEED_GCRYP_INIT
+ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+#ifdef GCRYCTL_INITIALIZATION_FINISHED
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+#endif /* GCRYCTL_INITIALIZATION_FINISHED */
+#endif /* NEED_GCRYP_INIT */
+
num_failed += test1_str ();
num_failed += test1_bin ();
diff --git a/src/microhttpd/test_sha256.c b/src/microhttpd/test_sha256.c
index f287afd6..5f6559e2 100644
--- a/src/microhttpd/test_sha256.c
+++ b/src/microhttpd/test_sha256.c
@@ -24,11 +24,16 @@
*/
#include "mhd_options.h"
-#include "sha256.h"
+#include "mhd_sha256_wrap.h"
#include "test_helpers.h"
#include <stdio.h>
#include <stdlib.h>
+#if defined(MHD_SHA256_TLSLIB) && defined(MHD_HTTPS_REQUIRE_GCRYPT)
+#define NEED_GCRYP_INIT 1
+#include <gcrypt.h>
+#endif /* MHD_SHA256_TLSLIB && MHD_HTTPS_REQUIRE_GCRYPT */
+
static int verbose = 0; /* verbose level (0-1)*/
@@ -320,9 +325,9 @@ check_result (const char *test_name,
{
char calc_str[SHA256_DIGEST_STRING_SIZE];
bin2hex (calculated, SHA256_DIGEST_SIZE, calc_str);
- printf (
- "PASSED: %s check %u: calculated digest %s matches expected digest.\n",
- test_name, check_num, 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;
@@ -339,19 +344,27 @@ test1_str (void)
{
int num_failed = 0;
unsigned int i;
- struct Sha256Ctx ctx;
+ struct Sha256CtxWr ctx;
+ MHD_SHA256_init_one_time (&ctx);
for (i = 0; i < units1_num; i++)
{
uint8_t digest[SHA256_DIGEST_SIZE];
- MHD_SHA256_init (&ctx);
MHD_SHA256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str,
data_units1[i].str_l.len);
- MHD_SHA256_finish (&ctx, digest);
+ MHD_SHA256_finish_reset (&ctx, digest);
+#ifdef MHD_SHA256_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif /* MHD_SHA256_HAS_EXT_ERROR */
num_failed += check_result (__FUNCTION__, i, digest,
data_units1[i].digest);
}
+ MHD_SHA256_deinit (&ctx);
return num_failed;
}
@@ -361,19 +374,27 @@ test1_bin (void)
{
int num_failed = 0;
unsigned int i;
- struct Sha256Ctx ctx;
+ struct Sha256CtxWr ctx;
+ MHD_SHA256_init_one_time (&ctx);
for (i = 0; i < units2_num; i++)
{
uint8_t digest[SHA256_DIGEST_SIZE];
- MHD_SHA256_init (&ctx);
MHD_SHA256_update (&ctx, data_units2[i].bin_l.bin,
data_units2[i].bin_l.len);
- MHD_SHA256_finish (&ctx, digest);
+ MHD_SHA256_finish_reset (&ctx, digest);
+#ifdef MHD_SHA256_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif /* MHD_SHA256_HAS_EXT_ERROR */
num_failed += check_result (__FUNCTION__, i, digest,
data_units2[i].digest);
}
+ MHD_SHA256_deinit (&ctx);
return num_failed;
}
@@ -384,14 +405,14 @@ test2_str (void)
{
int num_failed = 0;
unsigned int i;
- struct Sha256Ctx ctx;
+ struct Sha256CtxWr ctx;
+ MHD_SHA256_init_one_time (&ctx);
for (i = 0; i < units1_num; i++)
{
uint8_t digest[SHA256_DIGEST_SIZE];
size_t part_s = data_units1[i].str_l.len / 4;
- MHD_SHA256_init (&ctx);
MHD_SHA256_update (&ctx, (const uint8_t *) "", 0);
MHD_SHA256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str,
part_s);
@@ -400,10 +421,18 @@ test2_str (void)
+ part_s,
data_units1[i].str_l.len - part_s);
MHD_SHA256_update (&ctx, (const uint8_t *) "", 0);
- MHD_SHA256_finish (&ctx, digest);
+ MHD_SHA256_finish_reset (&ctx, digest);
+#ifdef MHD_SHA256_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif /* MHD_SHA256_HAS_EXT_ERROR */
num_failed += check_result (__FUNCTION__, i, digest,
data_units1[i].digest);
}
+ MHD_SHA256_deinit (&ctx);
return num_failed;
}
@@ -413,22 +442,30 @@ test2_bin (void)
{
int num_failed = 0;
unsigned int i;
- struct Sha256Ctx ctx;
+ struct Sha256CtxWr ctx;
+ MHD_SHA256_init_one_time (&ctx);
for (i = 0; i < units2_num; i++)
{
uint8_t digest[SHA256_DIGEST_SIZE];
size_t part_s = data_units2[i].bin_l.len * 2 / 3;
- MHD_SHA256_init (&ctx);
MHD_SHA256_update (&ctx, data_units2[i].bin_l.bin, part_s);
MHD_SHA256_update (&ctx, (const uint8_t *) "", 0);
MHD_SHA256_update (&ctx, data_units2[i].bin_l.bin + part_s,
data_units2[i].bin_l.len - part_s);
- MHD_SHA256_finish (&ctx, digest);
+ MHD_SHA256_finish_reset (&ctx, digest);
+#ifdef MHD_SHA256_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif /* MHD_SHA256_HAS_EXT_ERROR */
num_failed += check_result (__FUNCTION__, i, digest,
data_units2[i].digest);
}
+ MHD_SHA256_deinit (&ctx);
return num_failed;
}
@@ -444,10 +481,11 @@ test_unaligned (void)
unsigned int offset;
uint8_t *buf;
uint8_t *digest_buf;
- struct Sha256Ctx ctx;
+ struct Sha256CtxWr ctx;
const struct data_unit2 *const tdata = data_units2 + DATA_POS;
+ MHD_SHA256_init_one_time (&ctx);
buf = malloc (tdata->bin_l.len + MAX_OFFSET);
digest_buf = malloc (SHA256_DIGEST_SIZE + MAX_OFFSET);
if ((NULL == buf) || (NULL == digest_buf))
@@ -463,14 +501,21 @@ test_unaligned (void)
unaligned_digest = digest_buf + MAX_OFFSET - offset;
memset (unaligned_digest, 0, SHA256_DIGEST_SIZE);
- MHD_SHA256_init (&ctx);
MHD_SHA256_update (&ctx, unaligned_buf, tdata->bin_l.len);
- MHD_SHA256_finish (&ctx, unaligned_digest);
+ MHD_SHA256_finish_reset (&ctx, unaligned_digest);
+#ifdef MHD_SHA256_HAS_EXT_ERROR
+ if (0 != ctx.ext_error)
+ {
+ fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
+ exit (99);
+ }
+#endif /* MHD_SHA256_HAS_EXT_ERROR */
num_failed += check_result (__FUNCTION__, MAX_OFFSET - offset,
unaligned_digest, tdata->digest);
}
free (digest_buf);
free (buf);
+ MHD_SHA256_deinit (&ctx);
return num_failed;
}
@@ -483,6 +528,13 @@ main (int argc, char *argv[])
if (has_param (argc, argv, "-v") || has_param (argc, argv, "--verbose"))
verbose = 1;
+#ifdef NEED_GCRYP_INIT
+ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+#ifdef GCRYCTL_INITIALIZATION_FINISHED
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+#endif /* GCRYCTL_INITIALIZATION_FINISHED */
+#endif /* NEED_GCRYP_INIT */
+
num_failed += test1_str ();
num_failed += test1_bin ();
diff --git a/src/testcurl/test_digestauth.c b/src/testcurl/test_digestauth.c
index 387d8abf..adc5f330 100644
--- a/src/testcurl/test_digestauth.c
+++ b/src/testcurl/test_digestauth.c
@@ -26,18 +26,19 @@
* @author Karlson2k (Evgeny Grin)
*/
-#include "MHD_config.h"
+#include "mhd_options.h"
#include "platform.h"
#include <curl/curl.h>
#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#ifdef MHD_HTTPS_REQUIRE_GCRYPT
-#ifdef HAVE_GCRYPT_H
+
+#if defined(MHD_HTTPS_REQUIRE_GCRYPT) && \
+ (defined(MHD_SHA256_TLSLIB) || defined(MHD_MD5_TLSLIB))
+#define NEED_GCRYP_INIT 1
#include <gcrypt.h>
-#endif
-#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
+#endif /* MHD_HTTPS_REQUIRE_GCRYPT && (MHD_SHA256_TLSLIB || MHD_MD5_TLSLIB) */
#ifndef WINDOWS
#include <sys/socket.h>
@@ -491,14 +492,12 @@ main (int argc, char *const *argv)
unsigned int errorCount = 0;
(void) argc; (void) argv; /* Unused. Silent compiler warning. */
-#ifdef MHD_HTTPS_REQUIRE_GCRYPT
-#ifdef HAVE_GCRYPT_H
+#ifdef NEED_GCRYP_INIT
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
#ifdef GCRYCTL_INITIALIZATION_FINISHED
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
-#endif
-#endif
-#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
+#endif /* GCRYCTL_INITIALIZATION_FINISHED */
+#endif /* NEED_GCRYP_INIT */
if (0 != curl_global_init (CURL_GLOBAL_WIN32))
return 2;
errorCount += testDigestAuth ();
diff --git a/src/testcurl/test_digestauth2.c b/src/testcurl/test_digestauth2.c
index 81a93b5e..ab8d2b07 100644
--- a/src/testcurl/test_digestauth2.c
+++ b/src/testcurl/test_digestauth2.c
@@ -25,7 +25,7 @@
* @author Karlson2k (Evgeny Grin)
*/
-#include "MHD_config.h"
+#include "mhd_options.h"
#include "platform.h"
#include <curl/curl.h>
#include <microhttpd.h>
@@ -33,6 +33,12 @@
#include <string.h>
#include <time.h>
+#if defined(MHD_HTTPS_REQUIRE_GCRYPT) && \
+ (defined(MHD_SHA256_TLSLIB) || defined(MHD_MD5_TLSLIB))
+#define NEED_GCRYP_INIT 1
+#include <gcrypt.h>
+#endif /* MHD_HTTPS_REQUIRE_GCRYPT && (MHD_SHA256_TLSLIB || MHD_MD5_TLSLIB) */
+
#ifndef _WIN32
#include <sys/socket.h>
#include <unistd.h>
@@ -1464,6 +1470,12 @@ main (int argc, char *const *argv)
int curl_sspi;
(void) argc; (void) argv; /* Unused. Silent compiler warning. */
+#ifdef NEED_GCRYP_INIT
+ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+#ifdef GCRYCTL_INITIALIZATION_FINISHED
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+#endif /* GCRYCTL_INITIALIZATION_FINISHED */
+#endif /* NEED_GCRYP_INIT */
/* Test type and test parameters */
verbose = ! (has_param (argc, argv, "-q") ||
has_param (argc, argv, "--quiet") ||
diff --git a/src/testcurl/test_digestauth_concurrent.c
b/src/testcurl/test_digestauth_concurrent.c
index d2bcfd47..792d15de 100644
--- a/src/testcurl/test_digestauth_concurrent.c
+++ b/src/testcurl/test_digestauth_concurrent.c
@@ -26,18 +26,18 @@
* @author Karlson2k (Evgeny Grin)
*/
-#include "MHD_config.h"
+#include "mhd_options.h"
#include "platform.h"
#include <curl/curl.h>
#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#ifdef MHD_HTTPS_REQUIRE_GCRYPT
-#ifdef HAVE_GCRYPT_H
+#if defined(MHD_HTTPS_REQUIRE_GCRYPT) && \
+ (defined(MHD_SHA256_TLSLIB) || defined(MHD_MD5_TLSLIB))
+#define NEED_GCRYP_INIT 1
#include <gcrypt.h>
-#endif
-#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
+#endif /* MHD_HTTPS_REQUIRE_GCRYPT && (MHD_SHA256_TLSLIB || MHD_MD5_TLSLIB) */
#ifndef WINDOWS
#include <sys/socket.h>
@@ -669,14 +669,12 @@ main (int argc, char *const *argv)
has_param (argc, argv, "-s") ||
has_param (argc, argv, "--silent"));
- #ifdef MHD_HTTPS_REQUIRE_GCRYPT
-#ifdef HAVE_GCRYPT_H
+#ifdef NEED_GCRYP_INIT
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
#ifdef GCRYCTL_INITIALIZATION_FINISHED
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
-#endif
-#endif
-#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
+#endif /* GCRYCTL_INITIALIZATION_FINISHED */
+#endif /* NEED_GCRYP_INIT */
if (0 != curl_global_init (CURL_GLOBAL_WIN32))
return 2;
errorCount += testDigestAuth ();
diff --git a/src/testcurl/test_digestauth_sha256.c
b/src/testcurl/test_digestauth_sha256.c
index 0781c44c..cf6ab8ff 100644
--- a/src/testcurl/test_digestauth_sha256.c
+++ b/src/testcurl/test_digestauth_sha256.c
@@ -27,18 +27,19 @@
* @author Karlson2k (Evgeny Grin)
*/
-#include "MHD_config.h"
+#include "mhd_options.h"
#include "platform.h"
#include <curl/curl.h>
#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#ifdef MHD_HTTPS_REQUIRE_GCRYPT
-#ifdef HAVE_GCRYPT_H
+
+#if defined(MHD_HTTPS_REQUIRE_GCRYPT) && \
+ (defined(MHD_SHA256_TLSLIB) || defined(MHD_MD5_TLSLIB))
+#define NEED_GCRYP_INIT 1
#include <gcrypt.h>
-#endif
-#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
+#endif /* MHD_HTTPS_REQUIRE_GCRYPT && (MHD_SHA256_TLSLIB || MHD_MD5_TLSLIB) */
#ifndef WINDOWS
#include <sys/socket.h>
@@ -320,14 +321,12 @@ main (int argc, char *const *argv)
/* curl added SHA256 support in 7.57 = 7.0x39 */
if (d->version_num < 0x073900)
return 77; /* skip test, curl is too old */
-#ifdef MHD_HTTPS_REQUIRE_GCRYPT
-#ifdef HAVE_GCRYPT_H
+#ifdef NEED_GCRYP_INIT
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
#ifdef GCRYCTL_INITIALIZATION_FINISHED
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
-#endif
-#endif
-#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
+#endif /* GCRYCTL_INITIALIZATION_FINISHED */
+#endif /* NEED_GCRYP_INIT */
if (0 != curl_global_init (CURL_GLOBAL_WIN32))
return 2;
errorCount += testDigestAuth ();
diff --git a/src/testcurl/test_digestauth_with_arguments.c
b/src/testcurl/test_digestauth_with_arguments.c
index 09d70674..903d90a2 100644
--- a/src/testcurl/test_digestauth_with_arguments.c
+++ b/src/testcurl/test_digestauth_with_arguments.c
@@ -25,18 +25,19 @@
* @author Amr Ali
* @author Karlson2k (Evgeny Grin)
*/
-#include "MHD_config.h"
+#include "mhd_options.h"
#include "platform.h"
#include <curl/curl.h>
#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#ifdef MHD_HTTPS_REQUIRE_GCRYPT
-#ifdef HAVE_GCRYPT_H
+
+#if defined(MHD_HTTPS_REQUIRE_GCRYPT) && \
+ (defined(MHD_SHA256_TLSLIB) || defined(MHD_MD5_TLSLIB))
+#define NEED_GCRYP_INIT 1
#include <gcrypt.h>
-#endif
-#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
+#endif /* MHD_HTTPS_REQUIRE_GCRYPT && (MHD_SHA256_TLSLIB || MHD_MD5_TLSLIB) */
#ifndef WINDOWS
#include <sys/socket.h>
diff --git a/w32/common/MHD_config.h b/w32/common/MHD_config.h
index 7a658d7b..d3ac3f7e 100644
--- a/w32/common/MHD_config.h
+++ b/w32/common/MHD_config.h
@@ -74,6 +74,12 @@
/* Enable digest Auth support */
#define DAUTH_SUPPORT 1
+/* Enable MD5 hashing support. */
+#define MHD_MD5_SUPPORT 1
+
+/* Enable SHA-256 hashing support. */
+#define MHD_SHA256_SUPPORT 1
+
/* Enable postprocessor.c */
#define HAVE_POSTPROCESSOR 1
diff --git a/w32/common/libmicrohttpd-files.vcxproj
b/w32/common/libmicrohttpd-files.vcxproj
index 1818f0df..c78a2c7c 100644
--- a/w32/common/libmicrohttpd-files.vcxproj
+++ b/w32/common/libmicrohttpd-files.vcxproj
@@ -38,7 +38,9 @@
<ClInclude Include="$(MhdSrc)microhttpd\digestauth.h" />
<ClInclude Include="$(MhdSrc)microhttpd\gen_auth.h" />
<ClInclude Include="$(MhdSrc)microhttpd\internal.h" />
+ <ClInclude Include="$(MhdSrc)microhttpd\mhd_md5_wrap.h" />
<ClInclude Include="$(MhdSrc)microhttpd\md5.h" />
+ <ClInclude Include="$(MhdSrc)microhttpd\mhd_sha256_wrap.h" />
<ClInclude Include="$(MhdSrc)microhttpd\sha256.h" />
<ClInclude Include="$(MhdSrc)microhttpd\memorypool.h" />
<ClInclude Include="$(MhdSrc)microhttpd\mhd_assert.h" />
diff --git a/w32/common/libmicrohttpd-filters.vcxproj
b/w32/common/libmicrohttpd-filters.vcxproj
index 76c0c56e..346fc9d7 100644
--- a/w32/common/libmicrohttpd-filters.vcxproj
+++ b/w32/common/libmicrohttpd-filters.vcxproj
@@ -58,9 +58,15 @@
<ClInclude Include="$(MhdSrc)microhttpd\internal.h">
<Filter>Internal Headers</Filter>
</ClInclude>
+ <ClInclude Include="$(MhdSrc)microhttpd\mhd_md5_wrap.h">
+ <Filter>Internal Headers</Filter>
+ </ClInclude>
<ClInclude Include="$(MhdSrc)microhttpd\md5.h">
<Filter>Internal Headers</Filter>
</ClInclude>
+ <ClInclude Include="$(MhdSrc)microhttpd\mhd_sha256_wrap.h">
+ <Filter>Internal Headers</Filter>
+ </ClInclude>
<ClInclude Include="$(MhdSrc)microhttpd\sha256.h">
<Filter>Internal Headers</Filter>
</ClInclude>
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libmicrohttpd] 09/22: md5: improved performance of the first round on LE arches, (continued)
- [libmicrohttpd] 09/22: md5: improved performance of the first round on LE arches, gnunet, 2022/09/25
- [libmicrohttpd] 17/22: digestauth: removed redundant check and report, gnunet, 2022/09/25
- [libmicrohttpd] 12/22: test_sha{256,512_256}: minor fixes, gnunet, 2022/09/25
- [libmicrohttpd] 08/22: md5: replaced public domain MD5 implementation with our own implementation, gnunet, 2022/09/25
- [libmicrohttpd] 20/22: digestauth: refactored hashing asserts, gnunet, 2022/09/25
- [libmicrohttpd] 15/22: sha{256, 512_256}: improved performance of the first steps on BE arches, gnunet, 2022/09/25
- [libmicrohttpd] 22/22: w32: sync projects with autotools, gnunet, 2022/09/25
- [libmicrohttpd] 11/22: test_{md5,sha256,sha512_256}: added more checks, gnunet, 2022/09/25
- [libmicrohttpd] 16/22: test_{md5,sha{256,512_256}}: re-use of the context structure, gnunet, 2022/09/25
- [libmicrohttpd] 19/22: digestauth: used weak pseudo-random generators to avoid nonces clashes, gnunet, 2022/09/25
- [libmicrohttpd] 21/22: Implemented support for hash calculation by GnuTLS lib functions,
gnunet <=
- [libmicrohttpd] 13/22: test_md5: added more test sequences, gnunet, 2022/09/25
- [libmicrohttpd] 18/22: digestauth: changed "slot used" detection logic, gnunet, 2022/09/25