Skip to content

Commit

Permalink
ml-kem: Update to FIPS 203 (#47)
Browse files Browse the repository at this point in the history
* Add domain separation to K-PKE generation
* Clarify index ordering and remove cautionary comment
* Update documentation
* Update to use latest test vectors, in ACVP format
* Exclude test vectors from published crates
  • Loading branch information
bifurcation authored Aug 16, 2024
1 parent 19e8266 commit 26e8c8a
Show file tree
Hide file tree
Showing 12 changed files with 1,953 additions and 1,072 deletions.
18 changes: 12 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions ml-kem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "ml-kem"
description = """
Pure Rust implementation of the Module-Lattice-Based Key-Encapsulation Mechanism Standard
(formerly known as Kyber) as described in the FIPS 203 Initial Public Draft
(formerly known as Kyber) as described in FIPS 203
"""
version = "0.1.1"
edition = "2021"
Expand All @@ -13,6 +13,7 @@ homepage = "https://github.com/RustCrypto/KEMs/tree/master/ml-kem"
repository = "https://github.com/RustCrypto/KEMs"
categories = ["cryptography", "no-std"]
keywords = ["crypto", "kyber", "lattice", "post-quantum"]
exclude = ["tests/key-gen.rs", "tests/key-gen.json", "tests/encap-decap.rs", "tests/encap-decap.json"]

[features]
default = ["std"]
Expand All @@ -27,11 +28,13 @@ sha3 = { version = "0.10.8", default-features = false }

[dev-dependencies]
criterion = "0.5.1"
hex = "0.4.3"
hex = { version = "0.4.3", features = ["serde"] }
hex-literal = "0.4.1"
num-rational = { version = "0.4.2", default-features = false, features = ["num-bigint"] }
rand = "0.8.5"
crypto-common = { version = "0.1.6", features = ["rand_core"] }
serde = { version = "1.0.208", features = ["derive"] }
serde_json = "1.0.125"

[[bench]]
name = "mlkem"
Expand Down
4 changes: 2 additions & 2 deletions ml-kem/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[![Project Chat][chat-image]][chat-link]

Pure Rust implementation of the Module-Lattice-Based Key-Encapsulation Mechanism Standard
(formerly known as Kyber) as described in the [FIPS 203 Initial Public Draft].
(formerly known as Kyber) as described in [FIPS 203].

[Documentation][docs-link]

Expand Down Expand Up @@ -73,4 +73,4 @@ dual licensed as above, without any additional terms or conditions.
[//]: # (links)

[RustCrypto]: https://github.com/rustcrypto
[FIPS 203 Initial Public Draft]: https://csrc.nist.gov/pubs/fips/203/ipd
[FIPS 203]: https://csrc.nist.gov/pubs/fips/203/final
11 changes: 5 additions & 6 deletions ml-kem/src/algebra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ impl NttPolynomial {
// Note that the const environment here imposes some annoying conditions. Because operator
// overloading can't be const, we have to do all the reductions here manually. Because `for` loops
// are forbidden in `const` functions, we do them manually with `while` loops.
//
// The values computed here match those provided in Appendix A of FIPS 203. ZETA_POW_BITREV
// corresponds to the first table, and GAMMA to the second table.
#[allow(clippy::cast_possible_truncation)]
const ZETA_POW_BITREV: [FieldElement; 128] = {
const ZETA: u64 = 17;
Expand Down Expand Up @@ -398,14 +401,10 @@ impl NttPolynomial {
pub struct NttVector<K: ArraySize>(pub Array<NttPolynomial, K>);

impl<K: ArraySize> NttVector<K> {
// Note the transpose here: Apparently the specification is incorrect, and the proper order
// of indices is reversed.
//
// https://github.com/FiloSottile/mlkem768/blob/main/mlkem768.go#L110C4-L112C51
pub fn sample_uniform(rho: &B32, i: usize, transpose: bool) -> Self {
Self(Array::from_fn(|j| {
let (i, j) = if transpose { (i, j) } else { (j, i) };
let mut xof = XOF(rho, i.truncate(), j.truncate());
let (i, j) = if transpose { (j, i) } else { (i, j) };
let mut xof = XOF(rho, j.truncate(), i.truncate());
NttPolynomial::sample_uniform(&mut xof)
}))
}
Expand Down
3 changes: 2 additions & 1 deletion ml-kem/src/pke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ where
// Algorithm 12. K-PKE.KeyGen()
pub fn generate(d: &B32) -> (Self, EncryptionKey<P>) {
// Generate random seeds
let (rho, sigma) = G(&[d]);
let k = P::K::U8;
let (rho, sigma) = G(&[&d[..], &[k]]);

// Sample pseudo-random matrix and vectors
let A_hat: NttMatrix<P::K> = NttMatrix::sample_uniform(&rho, false);
Expand Down
18 changes: 18 additions & 0 deletions ml-kem/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
ML-KEM Test Vectors
===================

The tests in this directory validate that our ML-KEM implementation successfully
validates the NIST test vectors. The JSON test vector files are taken from the
[NIST ACVP repository]. Specifically, `key-gen.json` and `encap-decap.json` are
the "internal projection" files from the [ML-KEM key generation test
directory][keyGen] and [encap/decap test directory][encapDecap], respectively.

The current copies of these files were taken from commit [65370b8] of that repo.

The actual tests to be performed are described in the [ACVP documentation].

[NIST ACVP repository]: https://github.com/usnistgov/ACVP-Server/tree/master
[keyGen]: https://github.com/usnistgov/ACVP-Server/tree/master/gen-val/json-files/ML-KEM-keyGen-FIPS203
[encapDecap]: https://github.com/usnistgov/ACVP-Server/tree/master/gen-val/json-files/ML-KEM-encapDecap-FIPS203
[65370b8]: https://github.com/usnistgov/ACVP-Server/commit/65370b861b96efd30dfe0daae607bde26a78a5c8
[ACVP documentation]: https://github.com/usnistgov/ACVP/tree/2f786fac5b516733b58889d61a8473113ed62ee3/src/ml-kem/sections
Loading

0 comments on commit 26e8c8a

Please sign in to comment.