Skip to content

fix: validate ML-DSA s1/s2 coefficient bounds in wc_dilithium_check_key#10254

Open
MarkAtwood wants to merge 3 commits into
wolfSSL:masterfrom
MarkAtwood:fix/mldsa-privkey-bounds
Open

fix: validate ML-DSA s1/s2 coefficient bounds in wc_dilithium_check_key#10254
MarkAtwood wants to merge 3 commits into
wolfSSL:masterfrom
MarkAtwood:fix/mldsa-privkey-bounds

Conversation

@MarkAtwood

Copy link
Copy Markdown
Contributor

Summary

dilithium_vec_decode_eta_bits performs no bounds checking — it decodes raw bit fields and applies the formula without rejecting out-of-range values. For eta=2, 3-bit fields 5/6/7 (valid range 0–4) produce coefficients outside [-2, +2]. For eta=4, 4-bit nibbles 9–15 (valid range 0–8) produce coefficients outside [-4, +4]. Both are out of spec per FIPS 204 §7.2.

wc_dilithium_check_key had no coefficient range validation after decode. The mathematical consistency check (As1 + s2 = t mod q) validates algebraic structure, not coefficient range — a malformed key with out-of-range s1/s2 can still pass it.

Commit 1: After decoding s1/s2, validate every coefficient is in [-eta, +eta]. Sets ret = PUBLIC_KEY_E on first violation.

Commit 2: Wrap the NTT/matrix-multiply pipeline in if (ret == 0) so invalid coefficients are never fed to the NTT after the bounds check has already failed.

Found via Wycheproof ML-DSA mldsa_*_sign_noseed_test.json InvalidPrivateKey vectors.

Test plan

  • Wycheproof ML-DSA InvalidPrivateKey vectors correctly rejected
  • Existing ML-DSA key check tests unaffected

/cc @wolfSSL-Fenrir-bot please review

@MarkAtwood MarkAtwood requested review from SparkiDev and Copilot April 17, 2026 22:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds explicit coefficient-bound validation for ML-DSA (Dilithium) private key components so malformed keys with out-of-range s1/s2 coefficients are rejected before running NTT/matrix checks.

Changes:

  • Validate decoded s1/s2 coefficients are within [-eta, +eta] in wc_dilithium_check_key.
  • Skip the NTT/matrix-multiply consistency pipeline when coefficient validation fails.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread wolfcrypt/src/wc_mldsa.c Outdated
Comment thread wolfcrypt/src/dilithium.c Outdated
Comment thread wolfcrypt/src/wc_mldsa.c
@github-actions

github-actions Bot commented Apr 18, 2026

Copy link
Copy Markdown

@dgarske

dgarske commented May 5, 2026

Copy link
Copy Markdown
Member

@MarkAtwood see copilot feedback. If you have fixed it or won't just mark it resolved and assign wolfssl-bot only indicating its ready for merge.

@dgarske

dgarske commented May 5, 2026

Copy link
Copy Markdown
Member

Jenkins retest this please

After decoding s1 and s2 from the private key, check that every
coefficient lies within [-eta, +eta].  3-bit values 5/6/7 (eta=2)
and 4-bit nibbles 9-15 (eta=4) are out of spec per FIPS 204 and
must be rejected.  Without this check, internally-consistent but
spec-invalid keys pass the mathematical consistency test.

Catches the InvalidPrivateKey case in Wycheproof ML-DSA
mldsa_*_sign_noseed_test.json vectors.
After the coefficient bounds check sets ret=PUBLIC_KEY_E, wrap the
subsequent NTT and matrix-multiply block in if (ret == 0) so that
invalid coefficient data is never passed to NTT functions.
@MarkAtwood MarkAtwood force-pushed the fix/mldsa-privkey-bounds branch from 3d992cc to 49a7603 Compare June 3, 2026 21:38
@MarkAtwood MarkAtwood force-pushed the fix/mldsa-privkey-bounds branch from 7c45d46 to e6d1b6d Compare June 9, 2026 15:23
@MarkAtwood MarkAtwood force-pushed the fix/mldsa-privkey-bounds branch from e6d1b6d to e4559ae Compare July 9, 2026 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants