Skip to content

Conversation

@tob-scott-a
Copy link
Contributor

This was originally disclosed as a security advisory but @tarcieri said a public PR was fine.

Summary

A timing side-channel was discovered in the Decompose algorithm which is used during ML-DSA signing to generate hints for the signature.

Details

The analysis was performed using a constant-time analyzer that examines compiled assembly code for instructions with data-dependent timing behavior. The analyzer flags:

  • UDIV/SDIV instructions: Hardware division instructions have early termination optimizations where execution time depends on operand values.

The decompose function used a hardware division instruction to compute r1.0 / TwoGamma2::U32. This function is called during signing through high_bits() and low_bits(), which process values derived from secret key components:

  • (&w - &cs2).low_bits() where cs2 is derived from secret key component s2
  • Hint::new() calls high_bits() on values derived from secret key component t0

Original Code:

fn decompose<TwoGamma2: Unsigned>(self) -> (Elem, Elem) {
    // ...
    let mut r1 = r_plus - r0;
    r1.0 /= TwoGamma2::U32;  // Variable-time division on secret-derived data
    (r1, r0)
}

Impact

The dividend (r1.0) is derived from secret key material. An attacker with precise timing measurements could extract information about the signing key by observing timing variations in the division operation.

Mitigation

Replacing division with constant-time Barrett reduction mitigates this risk. Since TwoGamma2 is a compile-time constant, we precompute the multiplicative inverse.

See our blog post on how we avoided side-channels in our Go implementation of ML-DSA for more information.

(The loop decomposition change isn't strictly speaking necessary, but the loop bounds do create false positives for my testing utility that looks at the compiled output. Let me know if you'd prefer that removed.)

@tob-scott-a tob-scott-a changed the title fix: timing side-channels in ML-DSA ml-dsa: use Barrett reduction instead of integer division to prevent side-channels Jan 8, 2026
@tarcieri tarcieri merged commit 035d9ee into RustCrypto:master Jan 9, 2026
9 checks passed
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.

2 participants