aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandr Nedvedicky <[email protected]>2026-01-28 08:03:18 +0100
committerNeil Horman <[email protected]>2026-03-12 19:04:07 +0100
commit6d621e6729d41a809d87c221728d11a52d913a13 (patch)
tree7b39de65b339857b92941be2cb947be7b54b2653
parentrand_egd: harden EGD I/O and bounds; defer fdopen until post connect (diff)
downloadopenssl-feature/hqc.tar.gz
openssl-feature/hqc.zip
QUIC LCID hash table collapse on Windows/32-bit due to SipHash digest size misusefeature/hqc
Using sizeof(unsigned long) as SipHash digest size; SipHash supports only 8 or 16 bytes. On platforms where sizeof(unsigned long) == 4, the call fails, and lcid_hash returns the zero-initialized value, degrading the hash table into list. The issue was kindly reported and fix provided by Stanislav Fort at Aisle Research. Reviewed-by: Eugene Syromiatnikov <[email protected]> Reviewed-by: Paul Dale <[email protected]> Reviewed-by: Neil Horman <[email protected]> MergeDate: Thu Mar 12 18:04:10 2026 (Merged from https://github.com/openssl/openssl/pull/29814)
-rw-r--r--ssl/quic/quic_lcidm.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/ssl/quic/quic_lcidm.c b/ssl/quic/quic_lcidm.c
index 660eb802ba3..e23c16ce44b 100644
--- a/ssl/quic/quic_lcidm.c
+++ b/ssl/quic/quic_lcidm.c
@@ -74,15 +74,21 @@ static unsigned long lcid_hash(const QUIC_LCID *lcid_obj)
0,
};
unsigned long hashval = 0;
+ unsigned char digest[SIPHASH_MIN_DIGEST_SIZE];
- if (!SipHash_set_hash_size(&siphash, sizeof(unsigned long)))
+ /* Use a supported SipHash digest size (8 or 16); 8 is sufficient here. */
+ if (!SipHash_set_hash_size(&siphash, SIPHASH_MIN_DIGEST_SIZE))
goto out;
if (!SipHash_Init(&siphash, (uint8_t *)lcid_obj->hash_key, 0, 0))
goto out;
SipHash_Update(&siphash, lcid_obj->cid.id, lcid_obj->cid.id_len);
- if (!SipHash_Final(&siphash, (unsigned char *)&hashval,
- sizeof(unsigned long)))
+ if (!SipHash_Final(&siphash, digest, SIPHASH_MIN_DIGEST_SIZE))
goto out;
+
+ /*
+ * Truncate the 64-bit SipHash digest into an unsigned long.
+ */
+ memcpy(&hashval, digest, sizeof(hashval) < sizeof(digest) ? sizeof(hashval) : sizeof(digest));
out:
return hashval;
}