Implemented support for hash calculation by GnuTLS lib functions

This commit is contained in:
Evgeny Grin (Karlson2k)
2022-09-25 18:40:50 +03:00
parent 281b22da0e
commit 172b0eeb45
25 changed files with 1682 additions and 270 deletions
+229 -31
View File
@@ -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}"]]
)
AC_MSG_CHECKING([[whether to support MD5]])
AS_VAR_IF([[enable_md5]],[["yes"]],
AS_CASE([${enable_md5}],[yes|tlslib],
[
AC_DEFINE([[MHD_MD5_SUPPORT]],[[1]],
[Define to 1 if libmicrohttpd is compiled with MD5 hashing support.])
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"
]
)
]
)
AM_CONDITIONAL([ENABLE_MD5], [[test "x${enable_md5}" = "xyes"]])
AC_MSG_RESULT([[${enable_md5}]])
AC_MSG_CHECKING([[whether to support MD5]])
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.])
]
)
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}"]]
)
AC_MSG_CHECKING([[whether to support SHA-256]])
AS_VAR_IF([[enable_sha256]],[["yes"]],
AS_CASE([${enable_sha256}],[yes|tlslib],
[
AC_DEFINE([[MHD_SHA256_SUPPORT]],[[1]],
[Define to 1 if libmicrohttpd is compiled with SHA-256 hashing support.])
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"
]
)
]
)
AM_CONDITIONAL([ENABLE_SHA256], [[test "x${enable_sha256}" = "xyes"]])
AC_MSG_RESULT([[${enable_sha256}]])
AC_MSG_CHECKING([[whether to support SHA-256]])
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.])
]
)
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" || \
+31 -8
View File
@@ -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
};
+44 -2
View File
@@ -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 \
+6
View File
@@ -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;
+510 -155
View File
@@ -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.
* Indicates presence of digest_deinit() function
*/
#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->uninitialised = false;
da->algo_selected = false;
da->ready_for_hashing = false;
da->hashing = false;
#endif /* _DEBUG */
da->algo = MHD_DIGEST_BASE_ALGO_INVALID;
}
/**
* 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_deinit (struct DigestAlgorithm *da)
{
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_setup (struct DigestAlgorithm *da,
enum MHD_DigestBaseAlgo algo)
digest_init_one_time (struct DigestAlgorithm *da,
enum MHD_DigestBaseAlgo algo)
{
#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 */
)
if (MHD_DIGEST_BASE_ALGO_MD5 == algo)
{
da->algo = algo;
da->algo = MHD_DIGEST_BASE_ALGO_MD5;
#ifdef _DEBUG
da->setup = true;
#endif /* _DEBUG */
da->algo_selected = true;
#endif
MHD_MD5_init_one_time (&da->ctx.md5_ctx);
#ifdef _DEBUG
da->ready_for_hashing = true;
#endif
return true;
}
return false; /* Bad or unsupported algorithm */
}
/**
* Initialise/reset the digest calculation structure.
* @param da the structure to initialise/reset
*/
_MHD_static_inline void
digest_init (struct DigestAlgorithm *da)
{
mhd_assert (da->setup);
mhd_assert (! da->hashing);
mhd_assert (! da->inited);
#ifdef MHD_MD5_SUPPORT
if (MHD_DIGEST_BASE_ALGO_MD5 == da->algo)
{
MHD_MD5_init (&da->ctx.md5_ctx);
#ifdef _DEBUG
da->inited = true;
#endif
}
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)
{
da->algo = MHD_DIGEST_BASE_ALGO_SHA512_256;
#ifdef _DEBUG
da->algo_selected = true;
#endif
MHD_SHA512_256_init (&da->ctx.sha512_256_ctx);
#ifdef _DEBUG
da->inited = true;
da->ready_for_hashing = true;
#endif
return true;
}
else
#endif /* MHD_SHA512_256_SUPPORT */
{
#ifdef _DEBUG
da->inited = false;
#endif
mhd_assert (0); /* Bad algorithm */
}
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
#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 (&params->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 (&params->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 (&params->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 (&params->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 (&params->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
*
+5
View File
@@ -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 */
+95
View File
@@ -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);
}
+115
View File
@@ -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 */
+98
View File
@@ -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 */
+100
View File
@@ -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 */
+5
View File
@@ -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 */
+95
View File
@@ -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);
}
+115
View File
@@ -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 */
+14
View File
@@ -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 ();
+14
View File
@@ -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 ();
+76 -19
View File
@@ -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 ();
+71 -19
View File
@@ -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 ();
+9 -10
View File
@@ -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 ();
+13 -1
View File
@@ -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") ||
+8 -10
View File
@@ -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 ();
+9 -10
View File
@@ -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 ();
@@ -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>
+6
View File
@@ -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
+2
View File
@@ -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" />
+6
View File
@@ -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>