Skip to content

Commit

Permalink
Add private key validation function
Browse files Browse the repository at this point in the history
Fixes #536
  • Loading branch information
franziskuskiefer committed Aug 27, 2024
1 parent 4873df7 commit 264dbfd
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 116 deletions.
33 changes: 24 additions & 9 deletions libcrux-ml-kem/benches/ml-kem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ pub fn key_generation(c: &mut Criterion) {
#[cfg(all(
feature = "mlkem768",
feature = "pre-verification",
feature = "simd256"
feature = "simd256",
feature = "unpacked"
))]
c.bench_function("libcrux avx2 unpacked (external random)", |b| {
let mut seed = [0; 64];
Expand All @@ -71,7 +72,11 @@ pub fn key_generation(c: &mut Criterion) {
})
});

#[cfg(all(feature = "mlkem768", feature = "pre-verification"))]
#[cfg(all(
feature = "mlkem768",
feature = "pre-verification",
feature = "unpacked"
))]
c.bench_function("libcrux portable unpacked (external random)", |b| {
let mut seed = [0; 64];
rng.fill_bytes(&mut seed);
Expand All @@ -94,10 +99,10 @@ pub fn pk_validation(c: &mut Criterion) {
b.iter_batched(
|| {
let keypair = p::generate_key_pair(seed);
keypair.public_key().as_slice().into()
keypair
},
|public_key| {
let _valid = black_box(p::validate_public_key(public_key));
|keypair| {
let _valid = black_box(p::validate_public_key(keypair.public_key()));
},
BatchSize::SmallInput,
)
Expand Down Expand Up @@ -135,7 +140,11 @@ pub fn encapsulation(c: &mut Criterion) {
init!(mlkem768, "Encapsulation", c);
init!(mlkem1024, "Encapsulation", c);

#[cfg(all(feature = "mlkem768", feature = "pre-verification"))]
#[cfg(all(
feature = "mlkem768",
feature = "pre-verification",
feature = "unpacked"
))]
c.bench_function("libcrux unpacked portable (external random)", |b| {
let mut seed1 = [0; 64];
OsRng.fill_bytes(&mut seed1);
Expand Down Expand Up @@ -174,7 +183,8 @@ pub fn encapsulation(c: &mut Criterion) {
#[cfg(all(
feature = "mlkem768",
feature = "pre-verification",
feature = "simd256"
feature = "simd256",
feature = "unpacked"
))]
c.bench_function("libcrux unpacked avx2 (external random)", |b| {
let mut seed1 = [0; 64];
Expand Down Expand Up @@ -222,7 +232,11 @@ pub fn decapsulation(c: &mut Criterion) {
init!(mlkem768, "Decapsulation", c);
init!(mlkem1024, "Decapsulation", c);

#[cfg(all(feature = "mlkem768", feature = "pre-verification"))]
#[cfg(all(
feature = "mlkem768",
feature = "pre-verification",
feature = "unpacked"
))]
c.bench_function("libcrux unpacked portable", |b| {
let mut seed1 = [0; 64];
OsRng.fill_bytes(&mut seed1);
Expand Down Expand Up @@ -270,7 +284,8 @@ pub fn decapsulation(c: &mut Criterion) {
#[cfg(all(
feature = "mlkem768",
feature = "pre-verification",
feature = "simd256"
feature = "simd256",
feature = "unpacked"
))]
c.bench_function("libcrux unpacked avx2", |b| {
let mut seed1 = [0; 64];
Expand Down
28 changes: 28 additions & 0 deletions libcrux-ml-kem/src/ind_cca.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ fn serialize_kem_secret_key<const K: usize, const SERIALIZED_KEY_LEN: usize, Has
out
}

/// Validate an ML-KEM public key.
///
/// This implements the Modulus check in 7.2 2.
/// Note that the size check in 7.2 1 is covered by the `PUBLIC_KEY_SIZE` in the
/// `public_key` type.
#[inline(always)]
fn validate_public_key<
const K: usize,
Expand All @@ -107,6 +112,29 @@ fn validate_public_key<
*public_key == public_key_serialized
}

/// Validate an ML-KEM private key.
///
/// This implements the Hash check in 7.3 3.
/// Note that the size checks in 7.2 1 and 2 are covered by the `SECRET_KEY_SIZE`
/// and `CIPHERTEXT_SIZE` in the `private_key` and `ciphertext` types.
#[inline(always)]
fn validate_private_key<
const K: usize,
const SECRET_KEY_SIZE: usize,
const CIPHERTEXT_SIZE: usize,
Hasher: Hash<K>,
>(
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
_ciphertext: &MlKemCiphertext<CIPHERTEXT_SIZE>,
) -> bool {
// Eurydice can't access values directly on the types. We need to go to the
// `value` directly.

let t = Hasher::H(&private_key.value[384 * K..768 * K + 32]);
let expected = &private_key.value[768 * K + 32..768 * K + 64];
t == expected
}

/// Packed API
///
/// Generate a key pair.
Expand Down
17 changes: 17 additions & 0 deletions libcrux-ml-kem/src/ind_cca/instantiations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ macro_rules! instantiate {
}

/// Portable public key validation
#[inline(always)]
pub(crate) fn validate_public_key<
const K: usize,
const RANKED_BYTES_PER_RING_ELEMENT: usize,
Expand All @@ -81,6 +82,22 @@ macro_rules! instantiate {
>(public_key)
}

/// Portable private key validation
#[inline(always)]
pub(crate) fn validate_private_key<
const K: usize,
const SECRET_KEY_SIZE: usize,
const CIPHERTEXT_SIZE: usize,
>(
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
ciphertext: &MlKemCiphertext<CIPHERTEXT_SIZE>,
) -> bool {
crate::ind_cca::validate_private_key::<K, SECRET_KEY_SIZE, CIPHERTEXT_SIZE, $hash>(
private_key,
ciphertext,
)
}

/// Portable encapsulate
#[cfg(feature = "kyber")]
pub(crate) fn kyber_encapsulate<
Expand Down
36 changes: 22 additions & 14 deletions libcrux-ml-kem/src/ind_cca/multiplexing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::*;
#[cfg(feature = "simd256")]
use instantiations::avx2::{
decapsulate as decapsulate_avx2, encapsulate as encapsulate_avx2,
generate_keypair as generate_keypair_avx2, validate_public_key as validate_public_key_avx2,
generate_keypair as generate_keypair_avx2,
};

#[cfg(feature = "simd128")]
Expand All @@ -19,13 +19,13 @@ use instantiations::neon::{
#[cfg(not(feature = "simd256"))]
use instantiations::portable::{
decapsulate as decapsulate_avx2, encapsulate as encapsulate_avx2,
generate_keypair as generate_keypair_avx2, validate_public_key as validate_public_key_avx2,
generate_keypair as generate_keypair_avx2,
};

#[cfg(not(feature = "simd128"))]
use instantiations::portable::{
decapsulate as decapsulate_neon, encapsulate as encapsulate_neon,
generate_keypair as generate_keypair_neon, validate_public_key as validate_public_key_neon,
generate_keypair as generate_keypair_neon,
};

#[cfg(all(feature = "simd256", feature = "kyber"))]
Expand All @@ -52,24 +52,32 @@ use instantiations::portable::{
kyber_generate_keypair as kyber_generate_keypair_neon,
};

#[inline(always)]
pub(crate) fn validate_public_key<
const K: usize,
const RANKED_BYTES_PER_RING_ELEMENT: usize,
const PUBLIC_KEY_SIZE: usize,
>(
public_key: &[u8; PUBLIC_KEY_SIZE],
) -> bool {
if libcrux_platform::simd256_support() {
validate_public_key_avx2::<K, RANKED_BYTES_PER_RING_ELEMENT, PUBLIC_KEY_SIZE>(public_key)
} else if libcrux_platform::simd128_support() {
validate_public_key_neon::<K, RANKED_BYTES_PER_RING_ELEMENT, PUBLIC_KEY_SIZE>(public_key)
} else {
instantiations::portable::validate_public_key::<
K,
RANKED_BYTES_PER_RING_ELEMENT,
PUBLIC_KEY_SIZE,
>(public_key)
}
instantiations::portable::validate_public_key::<K, RANKED_BYTES_PER_RING_ELEMENT, PUBLIC_KEY_SIZE>(
public_key,
)
}

#[inline(always)]
pub(crate) fn validate_private_key<
const K: usize,
const SECRET_KEY_SIZE: usize,
const CIPHERTEXT_SIZE: usize,
>(
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
ciphertext: &MlKemCiphertext<CIPHERTEXT_SIZE>,
) -> bool {
instantiations::portable::validate_private_key::<K, SECRET_KEY_SIZE, CIPHERTEXT_SIZE>(
private_key,
ciphertext,
)
}

#[cfg(feature = "kyber")]
Expand Down
3 changes: 3 additions & 0 deletions libcrux-ml-kem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ cfg_pre_verification! {
pub use crate::mlkem512::kyber::decapsulate;
pub use crate::mlkem512::kyber::encapsulate;
pub use crate::mlkem512::validate_public_key;
pub use crate::mlkem512::validate_private_key;
}
}

Expand All @@ -158,6 +159,7 @@ cfg_pre_verification! {
pub use crate::mlkem768::kyber::decapsulate;
pub use crate::mlkem768::kyber::encapsulate;
pub use crate::mlkem768::validate_public_key;
pub use crate::mlkem768::validate_private_key;
}
}

Expand All @@ -170,6 +172,7 @@ cfg_pre_verification! {
pub use crate::mlkem1024::kyber::decapsulate;
pub use crate::mlkem1024::kyber::encapsulate;
pub use crate::mlkem1024::validate_public_key;
pub use crate::mlkem1024::validate_private_key;
}
}
}
Expand Down
53 changes: 35 additions & 18 deletions libcrux-ml-kem/src/mlkem1024.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,27 @@ macro_rules! instantiate {

/// Validate a public key.
///
/// Returns `Some(public_key)` if valid, and `None` otherwise.
pub fn validate_public_key(
public_key: MlKem1024PublicKey,
) -> Option<MlKem1024PublicKey> {
if p::validate_public_key::<
/// Returns `true` if valid, and `false` otherwise.
pub fn validate_public_key(public_key: &MlKem1024PublicKey) -> bool {
p::validate_public_key::<
RANK_1024,
RANKED_BYTES_PER_RING_ELEMENT_1024,
CPA_PKE_PUBLIC_KEY_SIZE_1024,
>(&public_key.value)
{
Some(public_key)
} else {
None
}
}

/// Validate a private key.
///
/// Returns `true` if valid, and `false` otherwise.
pub fn validate_private_key(
private_key: &MlKem1024PrivateKey,
ciphertext: &MlKem1024Ciphertext,
) -> bool {
p::validate_private_key::<
RANK_1024,
SECRET_KEY_SIZE_1024,
CPA_PKE_CIPHERTEXT_SIZE_1024,
>(private_key, ciphertext)
}

/// Generate Kyber 1024 Key Pair
Expand Down Expand Up @@ -331,19 +338,29 @@ instantiate! {neon, ind_cca::instantiations::neon, vector::SIMD128Vector, "Neon

/// Validate a public key.
///
/// Returns `Some(public_key)` if valid, and `None` otherwise.
/// Returns `true` if valid, and `false` otherwise.
#[cfg(not(eurydice))]
pub fn validate_public_key(public_key: MlKem1024PublicKey) -> Option<MlKem1024PublicKey> {
if multiplexing::validate_public_key::<
pub fn validate_public_key(public_key: &MlKem1024PublicKey) -> bool {
multiplexing::validate_public_key::<
RANK_1024,
RANKED_BYTES_PER_RING_ELEMENT_1024,
CPA_PKE_PUBLIC_KEY_SIZE_1024,
>(&public_key.value)
{
Some(public_key)
} else {
None
}
}

/// Validate a private key.
///
/// Returns `true` if valid, and `false` otherwise.
#[cfg(not(eurydice))]
pub fn validate_private_key(
private_key: &MlKem1024PrivateKey,
ciphertext: &MlKem1024Ciphertext,
) -> bool {
multiplexing::validate_private_key::<
RANK_1024,
SECRET_KEY_SIZE_1024,
CPA_PKE_CIPHERTEXT_SIZE_1024,
>(private_key, ciphertext)
}

/// Generate ML-KEM 1024 Key Pair
Expand Down
50 changes: 34 additions & 16 deletions libcrux-ml-kem/src/mlkem512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,27 @@ macro_rules! instantiate {

/// Validate a public key.
///
/// Returns `Some(public_key)` if valid, and `None` otherwise.
pub fn validate_public_key(public_key: MlKem512PublicKey) -> Option<MlKem512PublicKey> {
if p::validate_public_key::<
/// Returns `true` if valid, and `false` otherwise.
pub fn validate_public_key(public_key: &MlKem512PublicKey) -> bool {
p::validate_public_key::<
RANK_512,
RANKED_BYTES_PER_RING_ELEMENT_512,
CPA_PKE_PUBLIC_KEY_SIZE_512,
>(&public_key.value)
{
Some(public_key)
} else {
None
}
}

/// Validate a private key.
///
/// Returns `true` if valid, and `false` otherwise.
pub fn validate_private_key(
private_key: &MlKem512PrivateKey,
ciphertext: &MlKem512Ciphertext,
) -> bool {
p::validate_private_key::<
RANK_512,
SECRET_KEY_SIZE_512,
CPA_PKE_CIPHERTEXT_SIZE_512,
>(private_key, ciphertext)
}

/// Generate ML-KEM 512 Key Pair
Expand Down Expand Up @@ -324,19 +333,28 @@ instantiate! {neon, ind_cca::instantiations::neon, vector::SIMD128Vector, "Neon

/// Validate a public key.
///
/// Returns `Some(public_key)` if valid, and `None` otherwise.
/// Returns `true` if valid, and `false` otherwise.
#[cfg(not(eurydice))]
pub fn validate_public_key(public_key: MlKem512PublicKey) -> Option<MlKem512PublicKey> {
if multiplexing::validate_public_key::<
pub fn validate_public_key(public_key: &MlKem512PublicKey) -> bool {
multiplexing::validate_public_key::<
RANK_512,
RANKED_BYTES_PER_RING_ELEMENT_512,
CPA_PKE_PUBLIC_KEY_SIZE_512,
>(&public_key.value)
{
Some(public_key)
} else {
None
}
}

/// Validate a private key.
///
/// Returns `true` if valid, and `false` otherwise.
#[cfg(not(eurydice))]
pub fn validate_private_key(
private_key: &MlKem512PrivateKey,
ciphertext: &MlKem512Ciphertext,
) -> bool {
multiplexing::validate_private_key::<RANK_512, SECRET_KEY_SIZE_512, CPA_PKE_CIPHERTEXT_SIZE_512>(
private_key,
ciphertext,
)
}

/// Generate ML-KEM 512 Key Pair
Expand Down
Loading

0 comments on commit 264dbfd

Please sign in to comment.