Skip to content

Conversation

@jakemas
Copy link
Collaborator

@jakemas jakemas commented Oct 30, 2025

Issues:

Resolves #V1982530715 and #V1982532566

Description of changes:

The reference implementation implements poly_chknorm in variables time. It argues that while the input coefficients itself are secret in some call sites, it is okay to leak which coefficient lead to rejection. It, hence, does absolute value computation in constant-time and then checks the bound using a conditional.

This approach appears safe, but somewhat unclean as it is still operating on secret data. When performing constant-time testing it also requires a number of declassifications.

This commit takes a more conservative approach and changes poly_chknorm to a constant-time implementation in the hope that the performance penalty is acceptable.

A minor change is that the API of poly_chknorm is changed to returning 0xFFFFFFFF in the case of failure to be able to re-use existing constant-time primitives.

Call-outs:

PR source adapted from: Upstream PR in pq-code-package/mldsa-native#392.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

Comment on lines 232 to 235
/* Reference: Leaks which polynomial violates the bound via a conditional.
* We are more conservative to reduce the number of declassifications in
* constant-time testing.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/* Reference: Leaks which polynomial violates the bound via a conditional.
* We are more conservative to reduce the number of declassifications in
* constant-time testing.
*/

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

removed!


/* FIPS 204: Algorithm 7 line 23 - Reject if either check fails (constant-time to avoid leaking
which check failed) */
if(z_invalid | w0_invalid) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the compiler can turn this into non-CT code, please use an appropriate constant_time_* function to get the branch condition.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Removed this check, added documentation and references to https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf section 5.5

@codecov-commenter
Copy link

codecov-commenter commented Oct 30, 2025

Codecov Report

❌ Patch coverage is 94.73684% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 78.42%. Comparing base (7e78d68) to head (16e8e62).

Files with missing lines Patch % Lines
crypto/fipsmodule/ml_dsa/ml_dsa_ref/poly.c 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2788      +/-   ##
==========================================
- Coverage   78.42%   78.42%   -0.01%     
==========================================
  Files         683      683              
  Lines      116283   116286       +3     
  Branches    16405    16403       -2     
==========================================
- Hits        91197    91195       -2     
- Misses      24210    24216       +6     
+ Partials      876      875       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines 262 to 264
/* FIPS 204: Algorithm 7 line 23 - Reject if either check fails (constant-time to avoid leaking
which check failed) */
if(z_invalid | w0_invalid) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar comment as above. We may want to harden this as defense-in-depth, but separate checks are OK from all we know -- and what is explicitly stated in 5.5 of https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf -- so the comment should be changed.

Copy link
Contributor

@hanno-becker hanno-becker left a comment

Choose a reason for hiding this comment

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

I'm fine with defense-in-depth hardening of poly_chknorm as already done in mldsa-native, but we should change the comment so it's not suggested that the implementation would be insecure otherwise.

I have reservations towards consolidating the validity checks. As mentioned in the comments, they too are explicitly documented in the Dilithium documentation as safe to be performed separately, and merging them comes at a meaningful performance penalty (~5%); see the test PR pq-code-package/mldsa-native#572.

@jakemas jakemas marked this pull request as ready for review November 3, 2025 19:53
@jakemas jakemas requested a review from a team as a code owner November 3, 2025 19:53
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