libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

commit 7ce0a3f8a6eead1f1d835f745d23bc4c2ab21bb7
parent e154ae81202e274d51d869d4d4834c96dd6668d4
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri, 21 Nov 2025 20:12:06 +0100

make sure mhd_rng() only provides strictly good entropy, no weaker fallback; leave fallback to the gen_new_nonce logic

Diffstat:
Msrc/mhd2/auth_digest.c | 166++++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/mhd2/mhd_rng.c | 140++-----------------------------------------------------------------------------
Msrc/mhd2/mhd_rng.h | 10++--------
3 files changed, 84 insertions(+), 232 deletions(-)

diff --git a/src/mhd2/auth_digest.c b/src/mhd2/auth_digest.c @@ -304,11 +304,6 @@ gen_new_nonce (struct MHD_Daemon *restrict d, uint_fast32_t *restrict expir) { uint_fast64_t expiration; -#define OLD 1 -#if OLD - size_t gen_num; - union DigestCtx d_ctx; -#endif mhd_assert (! mhd_D_HAS_MASTER (d)); /* only master daemon should be used */ mhd_assert (d == c->daemon); @@ -317,103 +312,102 @@ gen_new_nonce (struct MHD_Daemon *restrict d, expiration = mhd_monotonic_msec_counter () + d->auth_dg.cfg.nonce_tmout * (uint_fast64_t) 1000; - // TODO: replace with pure random number - -#if ! OLD - if (! mhd_rng (d, - c, - mhd_AUTH_DIGEST_NONCE_BIN_SIZE, + if (! mhd_rng (mhd_AUTH_DIGEST_NONCE_BIN_SIZE, out_buf)) - return false; -#else + { + /* Fallback to generating nonce from application-provided + entropy. Note: this should fail if we do not have + application-provided entropy. */ + size_t gen_num; + union DigestCtx d_ctx; - gen_num = mhd_atomic_counter_get_inc_wrap (&(d->auth_dg.num_gen_nonces)); + gen_num = mhd_atomic_counter_get_inc_wrap (&(d->auth_dg.num_gen_nonces)); #if defined(MHD_SUPPORT_SHA512_256) - mhd_SHA512_256_init_one_time (&(d_ctx.sha512_256_ctx)); - mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), - d->auth_dg.entropy.size, - (const uint8_t*) d->auth_dg.entropy.data); - mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), - sizeof(gen_num), - (const uint8_t*) &gen_num); - if (0 != c->sk.addr.size) + mhd_SHA512_256_init_one_time (&(d_ctx.sha512_256_ctx)); mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), - c->sk.addr.size, - (const uint8_t*) c->sk.addr.data); - mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), - sizeof(expiration), - (const uint8_t*) &expiration); - mhd_SHA512_256_finish_deinit (&(d_ctx.sha512_256_ctx), \ - out_buf); - if (mhd_SHA512_256_has_err (&(d_ctx.sha512_256_ctx))) - return false; + d->auth_dg.entropy.size, + (const uint8_t*) d->auth_dg.entropy.data); + mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), + sizeof(gen_num), + (const uint8_t*) &gen_num); + if (0 != c->sk.addr.size) + mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), + c->sk.addr.size, + (const uint8_t*) c->sk.addr.data); + mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), + sizeof(expiration), + (const uint8_t*) &expiration); + mhd_SHA512_256_finish_deinit (&(d_ctx.sha512_256_ctx), \ + out_buf); + if (mhd_SHA512_256_has_err (&(d_ctx.sha512_256_ctx))) + return false; #elif defined(MHD_SUPPORT_SHA256) - mhd_SHA256_init_one_time (&(d_ctx.sha256_ctx)); - mhd_SHA256_update (&(d_ctx.sha256_ctx), - d->auth_dg.entropy.size, - (const void*) d->auth_dg.entropy.data); - mhd_SHA256_update (&(d_ctx.sha256_ctx), - sizeof(gen_num), - (const void*) &gen_num); - if (0 != c->sk.addr.size) + mhd_SHA256_init_one_time (&(d_ctx.sha256_ctx)); mhd_SHA256_update (&(d_ctx.sha256_ctx), - c->sk.addr.size, - (const void*) c->sk.addr.data); - mhd_SHA256_update (&(d_ctx.sha256_ctx), - sizeof(expiration), - (const void*) &expiration); - mhd_SHA256_finish_deinit (&(d_ctx.sha256_ctx), \ - out_buf); - if (mhd_SHA256_has_err (&(d_ctx.sha256_ctx))) - return false; + d->auth_dg.entropy.size, + (const void*) d->auth_dg.entropy.data); + mhd_SHA256_update (&(d_ctx.sha256_ctx), + sizeof(gen_num), + (const void*) &gen_num); + if (0 != c->sk.addr.size) + mhd_SHA256_update (&(d_ctx.sha256_ctx), + c->sk.addr.size, + (const void*) c->sk.addr.data); + mhd_SHA256_update (&(d_ctx.sha256_ctx), + sizeof(expiration), + (const void*) &expiration); + mhd_SHA256_finish_deinit (&(d_ctx.sha256_ctx), \ + out_buf); + if (mhd_SHA256_has_err (&(d_ctx.sha256_ctx))) + return false; #else /* MHD_SUPPORT_MD5 */ #ifndef MHD_SUPPORT_MD5 #error At least one hashing algorithm must be enabled #endif - mhd_MD5_init_one_time (&(d_ctx.md5_ctx)); - mhd_MD5_update (&(d_ctx.md5_ctx), - d->auth_dg.entropy.size, - (const void*) d->auth_dg.entropy.data); - mhd_MD5_update (&(d_ctx.md5_ctx), - sizeof(gen_num), - (const void*) &gen_num); - if (0 != c->sk.addr.size) + mhd_MD5_init_one_time (&(d_ctx.md5_ctx)); mhd_MD5_update (&(d_ctx.md5_ctx), - c->sk.addr.size, - (const void*) c->sk.addr.data); - mhd_MD5_update (&(d_ctx.md5_ctx), - sizeof(expiration), - (const void*) &expiration); - mhd_MD5_finish_deinit (&(d_ctx.md5_ctx), \ - out_buf); - if (mhd_MD5_has_err (&(d_ctx.md5_ctx))) - return false; + d->auth_dg.entropy.size, + (const void*) d->auth_dg.entropy.data); + mhd_MD5_update (&(d_ctx.md5_ctx), + sizeof(gen_num), + (const void*) &gen_num); + if (0 != c->sk.addr.size) + mhd_MD5_update (&(d_ctx.md5_ctx), + c->sk.addr.size, + (const void*) c->sk.addr.data); + mhd_MD5_update (&(d_ctx.md5_ctx), + sizeof(expiration), + (const void*) &expiration); + mhd_MD5_finish_deinit (&(d_ctx.md5_ctx), \ + out_buf); + if (mhd_MD5_has_err (&(d_ctx.md5_ctx))) + return false; - /* One more hash, for the second part */ - gen_num = mhd_atomic_counter_get_inc_wrap (&(d->auth_dg.num_gen_nonces)); - - mhd_MD5_init_one_time (&(d_ctx.md5_ctx)); - mhd_MD5_update (&(d_ctx.md5_ctx), - d->auth_dg.entropy.size, - (const void*) d->auth_dg.entropy.data); - mhd_MD5_update (&(d_ctx.md5_ctx), - sizeof(gen_num), - (const void*) &gen_num); - if (0 != c->sk.addr.size) + /* One more hash, for the second part */ + gen_num = mhd_atomic_counter_get_inc_wrap (&(d->auth_dg.num_gen_nonces)); + + mhd_MD5_init_one_time (&(d_ctx.md5_ctx)); mhd_MD5_update (&(d_ctx.md5_ctx), - c->sk.addr.size, - (const void*) c->sk.addr.data); - mhd_MD5_update (&(d_ctx.md5_ctx), - sizeof(expiration), - (const void*) &expiration); - mhd_MD5_finish_deinit (&(d_ctx.md5_ctx), \ - out_buf + mhd_MD5_DIGEST_SIZE); - if (mhd_MD5_has_err (&(d_ctx.md5_ctx))) - return false; + d->auth_dg.entropy.size, + (const void*) d->auth_dg.entropy.data); + mhd_MD5_update (&(d_ctx.md5_ctx), + sizeof(gen_num), + (const void*) &gen_num); + if (0 != c->sk.addr.size) + mhd_MD5_update (&(d_ctx.md5_ctx), + c->sk.addr.size, + (const void*) c->sk.addr.data); + mhd_MD5_update (&(d_ctx.md5_ctx), + sizeof(expiration), + (const void*) &expiration); + mhd_MD5_finish_deinit (&(d_ctx.md5_ctx), \ + out_buf + mhd_MD5_DIGEST_SIZE); + if (mhd_MD5_has_err (&(d_ctx.md5_ctx))) + return false; #endif /* MHD_SUPPORT_MD5 */ -#endif /* old code */ + } *expir = (uint_fast32_t) (expiration / 1000u); mhd_PUT_32BIT_LE_UNALIGN (out_buf + mhd_AUTH_DIGEST_NONCE_RAND_BIN_SIZE, \ diff --git a/src/mhd2/mhd_rng.c b/src/mhd2/mhd_rng.c @@ -87,34 +87,14 @@ # include "mhd_md5.h" #endif -#include "mhd_daemon.h" -#include "mhd_connection.h" #include "mhd_mono_clock.h" #include "mhd_atomic_counter.h" #include "mhd_rng.h" -/** - * Digest context data - */ -union DigestCtx -{ -#ifdef MHD_SUPPORT_SHA512_256 - struct mhd_Sha512_256Ctx sha512_256_ctx; -#endif /* MHD_SUPPORT_SHA512_256 */ -#ifdef MHD_SUPPORT_SHA256 - struct mhd_Sha256Ctx sha256_ctx; -#endif /* MHD_SUPPORT_SHA256 */ -#ifdef MHD_SUPPORT_MD5 - struct mhd_Md5Ctx md5_ctx; -#endif /* MHD_SUPPORT_MD5 */ -}; - MHD_INTERNAL bool -mhd_rng (struct MHD_Daemon *restrict d, - struct MHD_Connection *restrict c, - size_t buf_size, +mhd_rng (size_t buf_size, uint8_t buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)]) { #if defined(MHD_SUPPORT_OPENSSL) @@ -237,121 +217,5 @@ mhd_rng (struct MHD_Daemon *restrict d, } } #endif - /* Nothing worked, use hash functions and our entropy pool and - combine it with current time, generation counter and (if - available) client address to make the inputs as unique as - possible. */ - { - size_t off = 0; - - while (off < buf_size) - { - size_t gen_num; - union DigestCtx d_ctx; - uint_fast64_t now; - /* size of the output buffer, same for all of our hash functions */ - uint8_t out_buf[mhd_AUTH_DIGEST_NONCE_BIN_SIZE]; - size_t left; - - gen_num = mhd_atomic_counter_get_inc_wrap (&(d->auth_dg.num_gen_nonces)); - now = mhd_monotonic_msec_counter (); - -#if defined(MHD_SUPPORT_SHA512_256) - mhd_SHA512_256_init_one_time (&(d_ctx.sha512_256_ctx)); - mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), - d->auth_dg.entropy.size, - (const uint8_t*) d->auth_dg.entropy.data); - mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), - sizeof(gen_num), - (const uint8_t*) &gen_num); - if ( (NULL != c) && - (0 != c->sk.addr.size) ) - mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), - c->sk.addr.size, - (const uint8_t*) c->sk.addr.data); - mhd_SHA512_256_update (&(d_ctx.sha512_256_ctx), - sizeof(now), - (const uint8_t*) &now); - mhd_SHA512_256_finish_deinit (&(d_ctx.sha512_256_ctx), \ - out_buf); - if (mhd_SHA512_256_has_err (&(d_ctx.sha512_256_ctx))) - return false; -#elif defined(MHD_SUPPORT_SHA256) - mhd_SHA256_init_one_time (&(d_ctx.sha256_ctx)); - mhd_SHA256_update (&(d_ctx.sha256_ctx), - d->auth_dg.entropy.size, - (const void*) d->auth_dg.entropy.data); - mhd_SHA256_update (&(d_ctx.sha256_ctx), - sizeof(gen_num), - (const void*) &gen_num); - if ( (NULL != c) && - (0 != c->sk.addr.size) ) - mhd_SHA256_update (&(d_ctx.sha256_ctx), - c->sk.addr.size, - (const void*) c->sk.addr.data); - mhd_SHA256_update (&(d_ctx.sha256_ctx), - sizeof(now), - (const void*) &now); - mhd_SHA256_finish_deinit (&(d_ctx.sha256_ctx), \ - out_buf); - if (mhd_SHA256_has_err (&(d_ctx.sha256_ctx))) - return false; -#else /* MHD_SUPPORT_MD5 */ -#ifndef MHD_SUPPORT_MD5 -#error At least one hashing algorithm must be enabled -#endif - mhd_MD5_init_one_time (&(d_ctx.md5_ctx)); - mhd_MD5_update (&(d_ctx.md5_ctx), - d->auth_dg.entropy.size, - (const void*) d->auth_dg.entropy.data); - mhd_MD5_update (&(d_ctx.md5_ctx), - sizeof(gen_num), - (const void*) &gen_num); - if ( (NULL != c) && - (0 != c->sk.addr.size) ) - mhd_MD5_update (&(d_ctx.md5_ctx), - c->sk.addr.size, - (const void*) c->sk.addr.data); - mhd_MD5_update (&(d_ctx.md5_ctx), - sizeof(now), - (const void*) &now); - mhd_MD5_finish_deinit (&(d_ctx.md5_ctx), \ - out_buf); - if (mhd_MD5_has_err (&(d_ctx.md5_ctx))) - return false; - - /* One more hash, for the second part */ - gen_num = mhd_atomic_counter_get_inc_wrap (&(d->auth_dg.num_gen_nonces)); - - mhd_MD5_init_one_time (&(d_ctx.md5_ctx)); - mhd_MD5_update (&(d_ctx.md5_ctx), - d->auth_dg.entropy.size, - (const void*) d->auth_dg.entropy.data); - mhd_MD5_update (&(d_ctx.md5_ctx), - sizeof(gen_num), - (const void*) &gen_num); - if ( (NULL != c) && - (0 != c->sk.addr.size) ) - mhd_MD5_update (&(d_ctx.md5_ctx), - c->sk.addr.size, - (const void*) c->sk.addr.data); - mhd_MD5_update (&(d_ctx.md5_ctx), - sizeof(now), - (const void*) &now); - mhd_MD5_finish_deinit (&(d_ctx.md5_ctx), \ - out_buf + mhd_MD5_DIGEST_SIZE); - if (mhd_MD5_has_err (&(d_ctx.md5_ctx))) - return false; -#endif /* MHD_SUPPORT_MD5 */ - - left = mhd_AUTH_DIGEST_NONCE_BIN_SIZE < (buf_size - off) - ? mhd_AUTH_DIGEST_NONCE_BIN_SIZE - : (buf_size - off); - memcpy (buf + off, - out_buf, - left); - off += left; - } /* end while off < buf_size */ - } /* end hash-based approach scope */ - return true; + return false; } diff --git a/src/mhd2/mhd_rng.h b/src/mhd2/mhd_rng.h @@ -51,23 +51,17 @@ #include "sys_base_types.h" #include "mhd_socket_error.h" -struct MHD_Daemon; /* forward declaration */ -struct MHD_Connection; /* forward declaration */ /** * Initialize @a buf with random data. * - * @param d the daemon to use - * @param c client to create entropy for, can be NULL * @param buf_size the size of the @a buf buffer * @param[out] buf the buffer to fill with the random bytes * @return true on success */ MHD_INTERNAL bool -mhd_rng (struct MHD_Daemon *restrict d, - struct MHD_Connection *restrict c, - size_t buf_size, +mhd_rng (size_t buf_size, uint8_t buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)]) -MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_OUT_SIZE_ (4,3); +MHD_FN_PAR_OUT_SIZE_ (2,1); #endif