Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't use a prehashed version of ML-DSA #54

Open
brainhub opened this issue Dec 11, 2024 · 6 comments
Open

Don't use a prehashed version of ML-DSA #54

brainhub opened this issue Dec 11, 2024 · 6 comments

Comments

@brainhub
Copy link

NIST has recently clarified that one FIPS module can accept a hash of the message and use the "pure" or "normal" version of ML-DSA. ("pure ML-DSA" below). The method to use pure ML-DSA with a hash of the message is known as "external mu" method.

The method can be seen on lines 6-7 of Algorithm 8 in https://doi.org/10.6028/NIST.FIPS.204:

6: 𝑡𝑟 ← H(𝑝𝑘, 64)
7: 𝜇 ← (H(BytesToBits(𝑡𝑟)||𝑀 ′ , 64)) ▷ message representative that may optionally be computed in a different cryptographic module

Then the module, such as the one implementing this IP, takes the 64-byte "mu" as input (representing the hashed message).

The issues of prehashing is best to leave to the higher levels of firmware. In many cases, as e.g. in composite signatures, the messages passed to ML-DSA are very small, and the pure ML-DSA is used. This is just one example. The same is true for e.g. boot images where often short images are signed, that include hashes of larger images.

Therefore, to make the IP applicable to more use cases, and to simplify testing of the IP, it should stay with the pure version of ML-DSA.

This keeps the register message effectively the same. In this case of verification the register pk is not used. I don't see a strong need to hash the pk by IP itself, so this should not be a material issue.

@igilman0
Copy link

igilman0 commented Dec 11, 2024

If I understand the previous post correctly, it is now impossible to check the current Adam's Bridge (ABR) IP implementation correctness against the NIST-provided FIPS204 standard compliance Sign and Verify vectors. Correct?
These vectors have input "messages" (M in FIPS204 nomenclature) that are way longer than the ABR 64-byte MSG register so currently ABR couldn't even accept them.

Could you also confirm that the ABR IP in fact will be fixed to accept a 64-byte "mu" input into its MSG register (a.k.a., externally-hashed message representative "mu")?

@brainhub
Copy link
Author

I think I was asking for this 3518038 . @igilman0, so there is "pure ML-DSA" and "prehash ML-DSA" and they are binary incompatible. The test vectors will not match.

I propose to use the "external mu" interface to pure ML-DSA.

Could you also confirm that the ABR IP in fact will be fixed to accept a 64-byte "mu" input into its MSG register (a.k.a., externally-hashed message representative "mu")?

I am not sure to whom this question is directed, but because I advocate pure ML-DSA, the minimal change to the current interface is to accept the "mu". This will mean from functional point of view that the same properties of the HW interface are preserved, namely, that the input representative of a message is still a hash (broadly speaking), while this interface can be tested against standard pure ML-DSA test vectors.

@mojtaba-bisheh
Copy link
Collaborator

AdamsBridge doesn't support ExternalMu variant. This is pure MLDSA where the message size is limited to 512 bits based on Calitpra use model.
Caliptra performs a SHA512 over the data and passes the digest to AdamsBridge that works in Pure MLDSA mode.

@brainhub
Copy link
Author

Will you be able to find "official" test vectors for fixed-size-512-bit-message?

@mjosaarinen
Copy link

Comment from the sidelines :) The current behavior maps to the "IPD" draft version of FIPS 204, which allowed one to simply sign a hash as if it were a message. This is problematic cryptanalytically as the same signature is now valid for both SHA(message) and also its hash, interpreted as a 64-byte message (without hashing). HashML-DSA and additional domain separation were specifically introduced in the final version of FIPS 204 to overcome this EUF-CMA security problem. Thus I would not think that the current approach is FIPS-certifiable.

I've worked with Chris Celi of NIST little bit on this (to fix those test vectors), and the latest test vectors include ExternalMu cases, so one should be able to FIPS certify with that kind of API.

An ExternaMu interface would allow your module to support all modes and hash functions (pure and non-pure) with current external interfaces. It bypasses the domain separation padding steps altogether and 64-byte "msg" becomes:

You're trusting the caller to compute the hash so you could also trust that party to also format the hash with domain separation. Note the comment message representative that may optionally be computed in a different cryptographic module in the spec.

Cheers,
-markku

@mjosaarinen
Copy link

Btw the only bug in these test vectors was that the "rnd" parameter bytes need to reversed (or for Adams Bridge, not reversed, unlike everything else..) https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/bV_tuibsCWU/m/HrNpJ2sTAAAJ

To pass all test cases one needs four different APIs but you don't need to implement all of those; it's just to facilitate people having different kinds of APIs.

quote

Dec 5, 2024, 3:36 PM (13 days ago) to Christopher,
Thanks Chris,

With this byte reversal of "rnd", I am now passing all 360 ML-DSA sigGen test cases. It seems to work for preHash, externalMu, both external and internal interfaces, and all parameter sets.

This requires one to use four different signing interfaces to the ML-Dsa implementation:

  1. When "preHash" is set: Algorithm 4, HashML-DSA.Sign(sk, M, ctx, PH) interface, with the "PH" switch case extended with all of the additional OIDs and hashes in the test cases.
  2. When "externalMu" is set: Algorithm 7, ML-DSA.Sign_internal(sk, <M'>, rnd) is used with the additional parameter mu that is inserted in line 6 of the algorithm. Parameter M' is not used.
  3. when "signatureInterface" = "external": Algorithm 2 ML-DSA.Sign(sk, M, ctx).
  4. when "signatureInterface" = "internal": Algorithm 7, Algorithm 7, ML-DSA.Sign_internal(sk, M', rnd), where M' is the message.

My test code checks the various flags in that order; for example, if preHash is set, other cases are ignored.

Note again that in all cases, the rnd input bytes are reversed to pass the non-deterministic cases.

Cheers,

  • Markku

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

No branches or pull requests

4 participants