VER-004: Undocumented NTT primitives representation invariants may cause incorrect computations - #5
Draft
gnosed wants to merge 3 commits into
Draft
VER-004: Undocumented NTT primitives representation invariants may cause incorrect computations#5gnosed wants to merge 3 commits into
gnosed wants to merge 3 commits into
Conversation
Severity Warning, likelihood Not Likely, impact Bad (Veridise issue #1289).
gnosed
force-pushed
the
audit/ver-004-ntt-representation-invariants
branch
from
August 26, 2026 11:15
1c144cd to
73b7a42
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Finding
Full tracking:
docs/audit/findings/VER-004-ntt-representation-invariants.md(this PR's branch)Description
The NTT implementation represents field elements as
u32values in scalar helpers and asu16values in polynomial arrays. A field element has multiple integer representatives congruent modulo Q, while its canonical representative lies in[0, Q). The implementation also uses two polynomial domains: coefficient and evaluation and two field encodings: natural and Montgomery.Most primitives in
ntt.rsrely on specific range, domain, and encoding invariants. When these preconditions hold, the functions produce correct canonical outputs in the documented domain and encoding. These preconditions are not documented consistently.Impact
Non-canonical inputs may violate arithmetic bounds, resulting in overflow, incorrect values, or non-canonical outputs. Likewise, passing a polynomial in the wrong domain or Montgomery representation may produce values that are valid field elements but do not represent the intended computation. Future refactors or code reuse could therefore pass values with an unsupported range, domain, or encoding. Such misuse can potentially lead to erroneous verification decisions.
Recommendation
For each of the functions document the conditions on the inputs and the resulting guarantees on the result precisely. The following functions should clearly document their input and output invariants:
field_add()andfield_sub()require canonicalxandyusing the same encoding, either natural or Montgomery. Their output is canonical and preserves that encoding.field_halve()requires canonicalxin either natural or Montgomery encoding. Its output is canonical and preserves the encoding.montgomery_mulrequiresxandyso thatx*yis bounded by2^16*Q. The result will be canonical.ntt_forwardrequiresato be a coefficient-domain polynomial with canonical entries using a consistent encoding, either natural or Montgomery. Its output is canonical, remains in the same encoding, and is in the evaluation domain.ntt_inverserequiresato be an evaluation-domain polynomial with canonical entries using a consistent encoding, either natural or Montgomery. Its output is canonical, remains in the same encoding, and is in the coefficient domain.poly_to_montgomeryrequiresfto contain canonical entries in natural encoding. Its output is canonical and Montgomery-encoded. Because the operation is pointwise, it preserves the polynomial domain.poly_subrequiresfandgto contain canonical entries and to use the same polynomial domain and encoding. Its output is canonical and preserves the other two properties.poly_prepare_for_mulrequireshto be a coefficient-domain polynomial with canonical entries in natural encoding. Its output is canonical, Montgomery-encoded, and in the evaluation domain.poly_pointwise_mul()requiresfandgto be evaluation-domain polynomials with canonical entries. Its output is canonical and remains in the evaluation domain. The encoding will depend on the encoding of the inputs.Developers Response
The developers have been notified of the issue, but not yet provided a response.
Fix
Documentation-only change to
contracts/falcon-512-core/src/ntt.rs:No executable code changed.
cargo testandcargo doc --no-deps(with-D warnings, to catch broken intra-doc links) both pass.