diff --git a/libcrux-ml-dsa/benches/manual65.rs b/libcrux-ml-dsa/benches/manual65.rs index 18c6598dc..bec7eac45 100644 --- a/libcrux-ml-dsa/benches/manual65.rs +++ b/libcrux-ml-dsa/benches/manual65.rs @@ -8,6 +8,25 @@ use pqcrypto_dilithium; mod bench_utils; fn main() { - bench_group_libcrux!("65", ml_dsa_65, MLDSA65KeyPair, MLDSA65Signature); + bench_group_libcrux!( + "65 portable", + ml_dsa_65::portable, + MLDSA65KeyPair, + MLDSA65Signature + ); + #[cfg(feature = "simd128")] + bench_group_libcrux!( + "65 sim1d28", + ml_dsa_65::neon, + MLDSA65KeyPair, + MLDSA65Signature + ); + #[cfg(feature = "simd256")] + bench_group_libcrux!( + "65 simd256", + ml_dsa_65::avx2, + MLDSA65KeyPair, + MLDSA65Signature + ); bench_group_pqclean!("65", dilithium3); } diff --git a/libcrux-ml-dsa/benches/manual87.rs b/libcrux-ml-dsa/benches/manual87.rs index 4daf07f24..5b49f39c9 100644 --- a/libcrux-ml-dsa/benches/manual87.rs +++ b/libcrux-ml-dsa/benches/manual87.rs @@ -8,6 +8,25 @@ use pqcrypto_dilithium; mod bench_utils; fn main() { - bench_group_libcrux!("87", ml_dsa_87, MLDSA87KeyPair, MLDSA87Signature); + bench_group_libcrux!( + "87 portable", + ml_dsa_87::portable, + MLDSA87KeyPair, + MLDSA87Signature + ); + #[cfg(feature = "simd128")] + bench_group_libcrux!( + "87 sim1d28", + ml_dsa_87::neon, + MLDSA87KeyPair, + MLDSA87Signature + ); + #[cfg(feature = "simd256")] + bench_group_libcrux!( + "87 simd256", + ml_dsa_87::avx2, + MLDSA87KeyPair, + MLDSA87Signature + ); bench_group_pqclean!("87", dilithium5); } diff --git a/libcrux-ml-dsa/src/ml_dsa_65.rs b/libcrux-ml-dsa/src/ml_dsa_65.rs index 03164928b..9d8044471 100644 --- a/libcrux-ml-dsa/src/ml_dsa_65.rs +++ b/libcrux-ml-dsa/src/ml_dsa_65.rs @@ -1,4 +1,9 @@ -use crate::{constants::*, types::*, SigningError, VerificationError}; +use crate::{ + constants::*, + ml_dsa_generic::{self, multiplexing}, + types::*, + SigningError, VerificationError, +}; // ML-DSA-65-specific parameters @@ -62,35 +67,100 @@ pub type MLDSA65VerificationKey = MLDSAVerificationKey; pub type MLDSA65KeyPair = MLDSAKeyPair; pub type MLDSA65Signature = MLDSASignature; -// TODO: Multiplex more intelligently. -#[cfg(feature = "simd256")] -type SIMDUnit = crate::simd::avx2::AVX2SIMDUnit; -#[cfg(not(feature = "simd256"))] -type SIMDUnit = crate::simd::portable::PortableSIMDUnit; - -#[cfg(feature = "simd256")] -type Shake128X4 = crate::hash_functions::simd256::Shake128x4; -#[cfg(not(feature = "simd256"))] -type Shake128X4 = crate::hash_functions::portable::Shake128X4; +// Instantiate the different functions. +macro_rules! instantiate { + ($modp:ident, $p:path, $doc:expr) => { + #[doc = $doc] + pub mod $modp { + use super::*; + use $p as p; + + /// Generate an ML-DSA-65 Key Pair + pub fn generate_key_pair( + randomness: [u8; KEY_GENERATION_RANDOMNESS_SIZE], + ) -> MLDSA65KeyPair { + let (signing_key, verification_key) = p::generate_key_pair::< + ROWS_IN_A, + COLUMNS_IN_A, + ETA, + ERROR_RING_ELEMENT_SIZE, + SIGNING_KEY_SIZE, + VERIFICATION_KEY_SIZE, + >(randomness); + + MLDSA65KeyPair { + signing_key: MLDSASigningKey(signing_key), + verification_key: MLDSAVerificationKey(verification_key), + } + } + + /// Generate an ML-DSA-65 Signature + pub fn sign( + signing_key: &MLDSA65SigningKey, + message: &[u8], + randomness: [u8; SIGNING_RANDOMNESS_SIZE], + ) -> Result { + p::sign::< + ROWS_IN_A, + COLUMNS_IN_A, + ETA, + ERROR_RING_ELEMENT_SIZE, + GAMMA1_EXPONENT, + GAMMA2, + COMMITMENT_RING_ELEMENT_SIZE, + COMMITMENT_VECTOR_SIZE, + COMMITMENT_HASH_SIZE, + ONES_IN_VERIFIER_CHALLENGE, + MAX_ONES_IN_HINT, + GAMMA1_RING_ELEMENT_SIZE, + SIGNING_KEY_SIZE, + SIGNATURE_SIZE, + >(&signing_key.0, message, randomness) + } + + /// Verify an ML-DSA-65 Signature + pub fn verify( + verification_key: &MLDSA65VerificationKey, + message: &[u8], + signature: &MLDSA65Signature, + ) -> Result<(), VerificationError> { + p::verify::< + ROWS_IN_A, + COLUMNS_IN_A, + SIGNATURE_SIZE, + VERIFICATION_KEY_SIZE, + GAMMA1_EXPONENT, + GAMMA1_RING_ELEMENT_SIZE, + GAMMA2, + BETA, + COMMITMENT_RING_ELEMENT_SIZE, + COMMITMENT_VECTOR_SIZE, + COMMITMENT_HASH_SIZE, + ONES_IN_VERIFIER_CHALLENGE, + MAX_ONES_IN_HINT, + >(&verification_key.0, message, &signature.0) + } + } + }; +} -#[cfg(feature = "simd256")] -type Shake256X4 = crate::hash_functions::simd256::Shake256x4; -#[cfg(not(feature = "simd256"))] -type Shake256X4 = crate::hash_functions::portable::Shake256X4; +// Instantiations -// TODO: This is all portable for now. +instantiate! {portable, ml_dsa_generic::instantiations::portable, "Portable ML-DSA 65"} #[cfg(feature = "simd256")] -type Shake256 = crate::hash_functions::portable::Shake256; -#[cfg(not(feature = "simd256"))] -type Shake256 = crate::hash_functions::portable::Shake256; - -/// Generate an ML-DSA-65 Key Pair +instantiate! {avx2, ml_dsa_generic::instantiations::avx2, "AVX2 Optimised ML-DSA 65"} +#[cfg(feature = "simd128")] +instantiate! {neon, ml_dsa_generic::instantiations::neon, "Neon Optimised ML-DSA 65"} + +/// Generate an ML-DSA 65 Key Pair +/// +/// Generate an ML-DSA key pair. The input is a byte array of size +/// [`KEY_GENERATION_RANDOMNESS_SIZE`]. +/// +/// This function returns an [`MLDSA65KeyPair`]. +#[cfg(not(eurydice))] pub fn generate_key_pair(randomness: [u8; KEY_GENERATION_RANDOMNESS_SIZE]) -> MLDSA65KeyPair { - let (signing_key, verification_key) = crate::ml_dsa_generic::generate_key_pair::< - SIMDUnit, - Shake128X4, - Shake256, - Shake256X4, + let (signing_key, verification_key) = multiplexing::generate_key_pair::< ROWS_IN_A, COLUMNS_IN_A, ETA, @@ -105,17 +175,18 @@ pub fn generate_key_pair(randomness: [u8; KEY_GENERATION_RANDOMNESS_SIZE]) -> ML } } -/// Generate an ML-DSA-65 Signature +/// Sign with ML-DSA 65 +/// +/// Sign a `message` with the ML-DSA `signing_key`. +/// +/// This function returns an [`MLDSA65Signature`]. +#[cfg(not(eurydice))] pub fn sign( signing_key: &MLDSA65SigningKey, message: &[u8], randomness: [u8; SIGNING_RANDOMNESS_SIZE], ) -> Result { - crate::ml_dsa_generic::sign::< - SIMDUnit, - Shake128X4, - Shake256, - Shake256X4, + multiplexing::sign::< ROWS_IN_A, COLUMNS_IN_A, ETA, @@ -134,15 +205,16 @@ pub fn sign( } /// Verify an ML-DSA-65 Signature +/// +/// Returns `Ok` when the `signature` is valid for the `message` and +/// `verification_key`, and a [`VerificationError`] otherwise. +#[cfg(not(eurydice))] pub fn verify( verification_key: &MLDSA65VerificationKey, message: &[u8], signature: &MLDSA65Signature, ) -> Result<(), VerificationError> { - crate::ml_dsa_generic::verify::< - SIMDUnit, - Shake128X4, - Shake256, + multiplexing::verify::< ROWS_IN_A, COLUMNS_IN_A, SIGNATURE_SIZE, diff --git a/libcrux-ml-dsa/src/ml_dsa_87.rs b/libcrux-ml-dsa/src/ml_dsa_87.rs index eb02f21bc..48949c19b 100644 --- a/libcrux-ml-dsa/src/ml_dsa_87.rs +++ b/libcrux-ml-dsa/src/ml_dsa_87.rs @@ -1,4 +1,9 @@ -use crate::{constants::*, types::*, SigningError, VerificationError}; +use crate::{ + constants::*, + ml_dsa_generic::{self, multiplexing}, + types::*, + SigningError, VerificationError, +}; // ML-DSA-87 parameters @@ -65,35 +70,100 @@ pub type MLDSA87VerificationKey = MLDSAVerificationKey; pub type MLDSA87KeyPair = MLDSAKeyPair; pub type MLDSA87Signature = MLDSASignature; -// TODO: Multiplex more intelligently. -#[cfg(feature = "simd256")] -type SIMDUnit = crate::simd::avx2::AVX2SIMDUnit; -#[cfg(not(feature = "simd256"))] -type SIMDUnit = crate::simd::portable::PortableSIMDUnit; - -#[cfg(feature = "simd256")] -type Shake128X4 = crate::hash_functions::simd256::Shake128x4; -#[cfg(not(feature = "simd256"))] -type Shake128X4 = crate::hash_functions::portable::Shake128X4; +// Instantiate the different functions. +macro_rules! instantiate { + ($modp:ident, $p:path, $doc:expr) => { + #[doc = $doc] + pub mod $modp { + use super::*; + use $p as p; + + /// Generate an ML-DSA-87 Key Pair + pub fn generate_key_pair( + randomness: [u8; KEY_GENERATION_RANDOMNESS_SIZE], + ) -> MLDSA87KeyPair { + let (signing_key, verification_key) = p::generate_key_pair::< + ROWS_IN_A, + COLUMNS_IN_A, + ETA, + ERROR_RING_ELEMENT_SIZE, + SIGNING_KEY_SIZE, + VERIFICATION_KEY_SIZE, + >(randomness); + + MLDSA87KeyPair { + signing_key: MLDSASigningKey(signing_key), + verification_key: MLDSAVerificationKey(verification_key), + } + } + + /// Generate an ML-DSA-87 Signature + pub fn sign( + signing_key: &MLDSA87SigningKey, + message: &[u8], + randomness: [u8; SIGNING_RANDOMNESS_SIZE], + ) -> Result { + p::sign::< + ROWS_IN_A, + COLUMNS_IN_A, + ETA, + ERROR_RING_ELEMENT_SIZE, + GAMMA1_EXPONENT, + GAMMA2, + COMMITMENT_RING_ELEMENT_SIZE, + COMMITMENT_VECTOR_SIZE, + COMMITMENT_HASH_SIZE, + ONES_IN_VERIFIER_CHALLENGE, + MAX_ONES_IN_HINT, + GAMMA1_RING_ELEMENT_SIZE, + SIGNING_KEY_SIZE, + SIGNATURE_SIZE, + >(&signing_key.0, message, randomness) + } + + /// Verify an ML-DSA-87 Signature + pub fn verify( + verification_key: &MLDSA87VerificationKey, + message: &[u8], + signature: &MLDSA87Signature, + ) -> Result<(), VerificationError> { + p::verify::< + ROWS_IN_A, + COLUMNS_IN_A, + SIGNATURE_SIZE, + VERIFICATION_KEY_SIZE, + GAMMA1_EXPONENT, + GAMMA1_RING_ELEMENT_SIZE, + GAMMA2, + BETA, + COMMITMENT_RING_ELEMENT_SIZE, + COMMITMENT_VECTOR_SIZE, + COMMITMENT_HASH_SIZE, + ONES_IN_VERIFIER_CHALLENGE, + MAX_ONES_IN_HINT, + >(&verification_key.0, message, &signature.0) + } + } + }; +} -#[cfg(feature = "simd256")] -type Shake256X4 = crate::hash_functions::simd256::Shake256x4; -#[cfg(not(feature = "simd256"))] -type Shake256X4 = crate::hash_functions::portable::Shake256X4; +// Instantiations -// TODO: This is all portable for now. +instantiate! {portable, ml_dsa_generic::instantiations::portable, "Portable ML-DSA 87"} #[cfg(feature = "simd256")] -type Shake256 = crate::hash_functions::portable::Shake256; -#[cfg(not(feature = "simd256"))] -type Shake256 = crate::hash_functions::portable::Shake256; - -/// Generate an ML-DSA-87 Key Pair -pub fn generate_key_pair(randomness: [u8; 32]) -> MLDSA87KeyPair { - let (signing_key, verification_key) = crate::ml_dsa_generic::generate_key_pair::< - SIMDUnit, - Shake128X4, - Shake256, - Shake256X4, +instantiate! {avx2, ml_dsa_generic::instantiations::avx2, "AVX2 Optimised ML-DSA 87"} +#[cfg(feature = "simd128")] +instantiate! {neon, ml_dsa_generic::instantiations::neon, "Neon Optimised ML-DSA 87"} + +/// Generate an ML-DSA 87 Key Pair +/// +/// Generate an ML-DSA key pair. The input is a byte array of size +/// [`KEY_GENERATION_RANDOMNESS_SIZE`]. +/// +/// This function returns an [`MLDSA87KeyPair`]. +#[cfg(not(eurydice))] +pub fn generate_key_pair(randomness: [u8; KEY_GENERATION_RANDOMNESS_SIZE]) -> MLDSA87KeyPair { + let (signing_key, verification_key) = multiplexing::generate_key_pair::< ROWS_IN_A, COLUMNS_IN_A, ETA, @@ -108,17 +178,18 @@ pub fn generate_key_pair(randomness: [u8; 32]) -> MLDSA87KeyPair { } } -/// Generate an ML-DSA-87 Signature +/// Sign with ML-DSA 87 +/// +/// Sign a `message` with the ML-DSA `signing_key`. +/// +/// This function returns an [`MLDSA87Signature`]. +#[cfg(not(eurydice))] pub fn sign( signing_key: &MLDSA87SigningKey, message: &[u8], randomness: [u8; SIGNING_RANDOMNESS_SIZE], ) -> Result { - crate::ml_dsa_generic::sign::< - SIMDUnit, - Shake128X4, - Shake256, - Shake256X4, + multiplexing::sign::< ROWS_IN_A, COLUMNS_IN_A, ETA, @@ -137,15 +208,16 @@ pub fn sign( } /// Verify an ML-DSA-87 Signature +/// +/// Returns `Ok` when the `signature` is valid for the `message` and +/// `verification_key`, and a [`VerificationError`] otherwise. +#[cfg(not(eurydice))] pub fn verify( verification_key: &MLDSA87VerificationKey, message: &[u8], signature: &MLDSA87Signature, ) -> Result<(), VerificationError> { - crate::ml_dsa_generic::verify::< - SIMDUnit, - Shake128X4, - Shake256, + multiplexing::verify::< ROWS_IN_A, COLUMNS_IN_A, SIGNATURE_SIZE, diff --git a/libcrux-ml-dsa/src/ml_dsa_generic/instantiations.rs b/libcrux-ml-dsa/src/ml_dsa_generic/instantiations.rs index 6149e50f3..1ef02a3a2 100644 --- a/libcrux-ml-dsa/src/ml_dsa_generic/instantiations.rs +++ b/libcrux-ml-dsa/src/ml_dsa_generic/instantiations.rs @@ -129,7 +129,7 @@ instantiate! {portable, // AVX2 generic implementation. #[cfg(feature = "simd256")] instantiate! {avx2, - crate::simd::portable::PortableSIMDUnit, + crate::simd::avx2::AVX2SIMDUnit, crate::hash_functions::simd256::Shake128x4, crate::hash_functions::simd256::Shake256, crate::hash_functions::simd256::Shake256x4