diff --git a/Cargo.lock b/Cargo.lock index 634e42e..050ea8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -658,10 +658,11 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45" +checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1" dependencies = [ + "ctutils", "subtle", "typenum", "zeroize", @@ -800,18 +801,17 @@ dependencies = [ "serde", "serde_json", "sha3", - "subtle", "zeroize", ] [[package]] name = "module-lattice" -version = "0.1.0" +version = "0.2.0-pre" dependencies = [ + "ctutils", "getrandom", "hybrid-array", "num-traits", - "subtle", "zeroize", ] diff --git a/ml-kem/Cargo.toml b/ml-kem/Cargo.toml index 5f5f074..b28860e 100644 --- a/ml-kem/Cargo.toml +++ b/ml-kem/Cargo.toml @@ -25,12 +25,11 @@ pkcs8 = ["dep:const-oid", "dep:pkcs8"] zeroize = ["module-lattice/zeroize", "dep:zeroize"] [dependencies] -array = { version = "0.4.7", package = "hybrid-array", features = ["extra-sizes", "subtle"] } -module-lattice = { version = "0.1", features = ["subtle"] } +array = { version = "0.4.8", package = "hybrid-array", features = ["ctutils", "extra-sizes"] } +module-lattice = { version = "0.2.0-pre", features = ["ctutils"] } kem = "0.3.0-rc.6" rand_core = "0.10" sha3 = { version = "0.11.0-rc.9", default-features = false } -subtle = { version = "2", default-features = false } # optional dependencies const-oid = { version = "0.10.1", optional = true, default-features = false, features = ["db"] } diff --git a/ml-kem/src/decapsulation_key.rs b/ml-kem/src/decapsulation_key.rs index 50e62af..a48f397 100644 --- a/ml-kem/src/decapsulation_key.rs +++ b/ml-kem/src/decapsulation_key.rs @@ -12,8 +12,8 @@ use kem::{ Ciphertext, Decapsulate, Decapsulator, Generate, InvalidKey, Kem, KeyExport, KeyInit, KeySizeUser, }; +use module_lattice::ctutils::{CtEq, CtSelect}; use rand_core::{TryCryptoRng, TryRng}; -use subtle::{ConditionallySelectable, ConstantTimeEq}; #[cfg(feature = "zeroize")] use zeroize::{Zeroize, ZeroizeOnDrop}; @@ -156,7 +156,7 @@ where let (Kp, rp) = G(&[&mp, &self.ek.h()]); let Kbar = J(&[self.z.as_slice(), encapsulated_key.as_ref()]); let cp = self.ek.ek_pke().encrypt(&mp, &rp); - B32::conditional_select(&Kbar, &Kp, cp.ct_eq(encapsulated_key)) + Kbar.ct_select(&Kp, cp.ct_eq(encapsulated_key)) } } diff --git a/ml-kem/src/pke.rs b/ml-kem/src/pke.rs index fae743b..d936078 100644 --- a/ml-kem/src/pke.rs +++ b/ml-kem/src/pke.rs @@ -8,8 +8,10 @@ use crate::crypto::{G, PRF}; use crate::param::{EncodedDecryptionKey, EncodedEncryptionKey, PkeParams}; use array::typenum::{U1, Unsigned}; use kem::{Ciphertext, InvalidKey}; -use module_lattice::Encode; -use subtle::{Choice, ConstantTimeEq}; +use module_lattice::{ + Encode, + ctutils::{Choice, CtEq}, +}; #[cfg(feature = "zeroize")] use zeroize::Zeroize; @@ -24,7 +26,7 @@ where s_hat: NttVector, } -impl

ConstantTimeEq for DecryptionKey

+impl

CtEq for DecryptionKey

where P: PkeParams, { diff --git a/module-lattice/Cargo.toml b/module-lattice/Cargo.toml index 4b6597a..a760e46 100644 --- a/module-lattice/Cargo.toml +++ b/module-lattice/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "module-lattice" description = """ -Functionality shared between the `ml-kem` and `ml-dsa` crates, including linear algebra with degree-256 polynomials over -a prime-order field, vectors of such polynomials, and NTT polynomials / vectors, as well as packing of polynomials into -coefficients with a specified number of bits. +Functionality shared between the `ml-kem` and `ml-dsa` crates, including linear algebra with +degree-256 polynomials over a prime-order field, vectors of such polynomials, and NTT polynomials + / vectors, as well as packing of polynomials into coefficients with a specified number of bits """ -version = "0.1.0" +version = "0.2.0-pre" edition = "2024" rust-version = "1.85" license = "Apache-2.0 OR MIT" @@ -16,18 +16,18 @@ categories = ["cryptography", "no-std"] keywords = ["crypto", "kyber", "lattice", "post-quantum"] [dependencies] -array = { version = "0.4.7", package = "hybrid-array", features = ["extra-sizes"] } +array = { version = "0.4.8", package = "hybrid-array", features = ["extra-sizes"] } num-traits = { version = "0.2", default-features = false } # optional dependencies -subtle = { version = "2", optional = true, default-features = false } +ctutils = { version = "0.4", optional = true } zeroize = { version = "1.8.1", optional = true, default-features = false } [dev-dependencies] getrandom = { version = "0.4", features = ["sys_rng"] } [features] -subtle = ["dep:subtle", "array/subtle"] +ctutils = ["dep:ctutils", "array/ctutils"] zeroize = ["array/zeroize", "dep:zeroize"] [lints] diff --git a/module-lattice/README.md b/module-lattice/README.md index 07bfdda..d74bb4e 100644 --- a/module-lattice/README.md +++ b/module-lattice/README.md @@ -18,8 +18,7 @@ these algorithms: - Linear algebra with degree-256 polynomials over a prime-order field, vectors of such polynomials, and NTT polynomials / vectors. - Packing of polynomials into coefficients with a specified number of bits. -- Utility functions such as truncating integers, flattening arrays of arrays, and unflattening arrays into arrays - of arrays. +- Utility functions such as truncating integers ## ⚠️ Warning: [Hazmat!][hazmat-link] diff --git a/module-lattice/src/algebra.rs b/module-lattice/src/algebra.rs index 2d4c818..9550f60 100644 --- a/module-lattice/src/algebra.rs +++ b/module-lattice/src/algebra.rs @@ -5,8 +5,8 @@ use core::fmt::Debug; use core::ops::{Add, Mul, Neg, Sub}; use num_traits::PrimInt; -#[cfg(feature = "subtle")] -use subtle::{Choice, ConstantTimeEq}; +#[cfg(feature = "ctutils")] +use ctutils::{Choice, CtEq, CtEqSlice}; #[cfg(feature = "zeroize")] use zeroize::Zeroize; @@ -104,16 +104,19 @@ impl Elem { } } -#[cfg(feature = "subtle")] -impl ConstantTimeEq for Elem +#[cfg(feature = "ctutils")] +impl CtEq for Elem where - F::Int: ConstantTimeEq, + F::Int: CtEq, { fn ct_eq(&self, other: &Self) -> Choice { self.0.ct_eq(&other.0) } } +#[cfg(feature = "ctutils")] +impl> CtEqSlice for Elem {} + #[cfg(feature = "zeroize")] impl Zeroize for Elem where @@ -392,16 +395,19 @@ impl From> for Array, U256> { } } -#[cfg(feature = "subtle")] -impl ConstantTimeEq for NttPolynomial +#[cfg(feature = "ctutils")] +impl CtEq for NttPolynomial where - F::Int: ConstantTimeEq, + F::Int: CtEq, { fn ct_eq(&self, other: &Self) -> Choice { self.0.ct_eq(&other.0) } } +#[cfg(feature = "ctutils")] +impl> CtEqSlice for NttPolynomial {} + #[cfg(feature = "zeroize")] impl Zeroize for NttPolynomial where @@ -427,16 +433,19 @@ impl NttVector { } } -#[cfg(feature = "subtle")] -impl ConstantTimeEq for NttVector +#[cfg(feature = "ctutils")] +impl CtEq for NttVector where - F::Int: ConstantTimeEq, + F::Int: CtEq, { fn ct_eq(&self, other: &Self) -> Choice { self.0.ct_eq(&other.0) } } +#[cfg(feature = "ctutils")] +impl, K: ArraySize> CtEqSlice for NttVector {} + #[cfg(feature = "zeroize")] impl Zeroize for NttVector where diff --git a/module-lattice/src/lib.rs b/module-lattice/src/lib.rs index 12722fc..9bdbc35 100644 --- a/module-lattice/src/lib.rs +++ b/module-lattice/src/lib.rs @@ -7,14 +7,13 @@ )] /// Linear algebra with degree-256 polynomials over a prime-order field, vectors of such -/// polynomials, and NTT polynomials / vectors +/// polynomials, and NTT polynomials / vectors. mod algebra; /// Packing of polynomials into coefficients with a specified number of bits. mod encoding; -/// Utility functions such as truncating integers, flattening arrays of arrays, and unflattening -/// arrays into arrays of arrays. +/// Integer truncation support. mod truncate; pub use algebra::{ @@ -25,3 +24,6 @@ pub use encoding::{ EncodedVectorSize, EncodingSize, VectorEncodingSize, byte_decode, byte_encode, }; pub use truncate::Truncate; + +#[cfg(feature = "ctutils")] +pub use ctutils; diff --git a/module-lattice/tests/algebra.rs b/module-lattice/tests/algebra.rs index 1be9adb..3b6e929 100644 --- a/module-lattice/tests/algebra.rs +++ b/module-lattice/tests/algebra.rs @@ -516,14 +516,11 @@ mod zeroize_tests { } } -// ======================================== -// ConstantTimeEq tests (require subtle feature) -// ======================================== - -#[cfg(feature = "subtle")] -mod subtle_tests { +/// `CtEq` tests (requires `ctutils` feature) +#[cfg(feature = "ctutils")] +mod ctutils_tests { use super::*; - use subtle::ConstantTimeEq; + use ctutils::CtEq; #[test] fn elem_ct_eq() {