secp256k1_chilldkg_pad33 and secp256k1_chilldkg_schnorrsig_sha256_tagged
each guarded a memcpy into a fixed-size stack buffer with VERIFY_CHECK,
which is compiled out in noverify (release) builds. In pad33 the
consequence is worse than the overflowing copy: the following
memset(out33 + len, 0, 33 - len) underflows its length to a huge value
when len exceeds 33.
Neither is reachable today. Every call site passes a string literal of
this module: "BIP DKG/certeq message" (22) and "BIP DKG/recovery
acknowledgment" (31) for pad33, and at most "BIP DKG/pop message" ||
"/challenge" (29 of 64) for the tagged-hash helper. This is the same
shape as the persisted-state guards promoted in ceccb50a, without the
attacker-controlled input path -- so the change is defence in depth, to
keep a future longer tag from smashing the stack in a release build
rather than failing a debug assertion.
Enforce both bounds outside VERIFY_CHECK and keep VERIFY_CHECK(0) inside
the branch as the debug-build diagnostic, matching the existing idiom in
this module (see the point_load fallbacks in the state loaders).
The tagged-hash helper clamps rather than returning early: an early
return would leave the caller's secp256k1_sha256 uninitialized and every
call site writes into it immediately, which is a worse failure than the
one being fixed. A clamped tag changes every hash the module computes,
so the chilldkg vectors would fail loudly rather than silently.
No behaviour change on any reachable input: the full test suite,
including the chilldkg vectors, is unaffected in both verify and
noverify builds.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>