ML-KEM repeated public key check during encapsulation
The ML-KEM encapsulation function contains two checks on the public key length and modulus. https://github.com/bcgit/bc-java/blob/5ce0d4d4536bcb622c1077a6b9157b02ad8adcc5/core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/MLKEMEngine.java#L289-L300
It does not follow the NIST recommendations FIPS 203 MODULE-LATTICE-BASED KEY-ENCAPSULATION MECHANISM
ML-KEM.Encaps shall not be run with an encapsulation key that has not been checked as above. However, checking of the encapsulation key need not be performed by the encapsulating party, nor with every execution of ML-KEM.Encaps. Instead, assurance that these checks have been performed can be acquired through other means (see SP 800-227 [1]).
And in SP 800-227:
- If the cryptographic module generated an input internally using an algorithm that ensures validity and stored that input in a manner that prevents modification, then the module is not required to check that input. For example, if the module gener- ated a decapsulation key dk via KeyGen and then stored dk in a manner that prevents modification, then the module can later invoke Decaps directly on dk without per- forming any input checking.629
- If the cryptographic module checks an input once and stores that input in a man- ner that prevents modification, then the module is not required to check that input again. For example, if the module performed input-checking on a given encapsula- tion key ek and stored it in a manner that prevents modification, then the module may invoke Encaps directly on ek (even repeatedly) without performing any further input checking.
My knowledge of the codebase is limited, but as far as I understand, the check could be moved to MLKEMPublicKeyParameters constructor to follow the standard.
Célian Glénaz (Quarkslab)
How do you propose to guarantee modification prevention in normal software Thai dies not run on a special isolated device, such add HSM?
Doing the check in MLKEMPublicKeyParameters constructor and using a MLKEMPublicKeyParameters as input could prevent to modify the public key after the checks by using the available API for example. I guess better modification prevention cannot be done in software but I don't think it is the meaning of SP 800-227.
Don't take my answer as a reference though, I'm not expert in this field.
Yes, I think moving to the constructor of MLKEMPublicKeyParameters was the answer. This has finally been done. If a public key is re-used a lot it seems to be a saving of about 5% per 1000 transactions, single use there's no penalty as then the check has effectively just moved.
Will appear in 1.82.