Skip to content

Commit

Permalink
more mlkem private functions
Browse files Browse the repository at this point in the history
  • Loading branch information
franziskuskiefer committed Oct 11, 2024
1 parent c13257a commit 76be581
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 82 deletions.
28 changes: 0 additions & 28 deletions libcrux-ml-kem/cg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,34 +45,6 @@ files:
monomorphizations_using:
- [libcrux_sha3, "*"]

# Header with types only

- name: libcrux_mlkem768_avx2_types
inline_static: true
api:
monomorphizations_exact:
- [ libcrux_ml_kem, mlkem768, avx2, unpacked, MlKem768KeyPairUnpacked ]
- [ libcrux_ml_kem, mlkem768, avx2, unpacked, MlKem768PublicKeyUnpacked ]
- [ libcrux_ml_kem, ind_cca, unpacked, MlKemPrivateKeyUnpacked_63 ]
- [ libcrux_ml_kem, ind_cca, unpacked, MlKemPublicKeyUnpacked_63 ]
- [ libcrux_ml_kem, ind_cpa, unpacked, IndCpaPrivateKeyUnpacked_63 ]
- [ libcrux_ml_kem, ind_cpa, unpacked, IndCpaPublicKeyUnpacked_63 ]
- [ libcrux_ml_kem, polynomial, PolynomialRingElement_f6 ]
- [ libcrux_ml_kem, vector, avx2, SIMD256Vector ]

- name: libcrux_mlkem768_portable_types
inline_static: true
api:
monomorphizations_exact:
- [ libcrux_ml_kem, mlkem768, portable, unpacked, MlKem768KeyPairUnpacked ]
- [ libcrux_ml_kem, mlkem768, portable, unpacked, MlKem768PublicKeyUnpacked ]
- [ libcrux_ml_kem, ind_cca, unpacked, MlKemPrivateKeyUnpacked_a0 ]
- [ libcrux_ml_kem, ind_cca, unpacked, MlKemPublicKeyUnpacked_a0 ]
- [ libcrux_ml_kem, ind_cpa, unpacked, IndCpaPrivateKeyUnpacked_a0 ]
- [ libcrux_ml_kem, ind_cpa, unpacked, IndCpaPublicKeyUnpacked_a0 ]
- [ libcrux_ml_kem, polynomial, PolynomialRingElement_1d ]
- [ libcrux_ml_kem, vector, portable, vector_type, PortableVector ]

# MLKEM: MISC NON-ARCHITECTURE SPECIFIC HEADERS
- name: libcrux_core
inline_static: true
Expand Down
112 changes: 67 additions & 45 deletions libcrux-ml-kem/src/ind_cca.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ fn validate_private_key<
>(
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
_ciphertext: &MlKemCiphertext<CIPHERTEXT_SIZE>,
) -> bool {
validate_private_key_only::<K, SECRET_KEY_SIZE, Hasher>(private_key)
}

/// Validate an ML-KEM private key.
///
/// This implements the Hash check in 7.3 3.
#[inline(always)]
fn validate_private_key_only<const K: usize, const SECRET_KEY_SIZE: usize, Hasher: Hash<K>>(
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
) -> bool {
// Eurydice can't access values directly on the types. We need to go to the
// `value` directly.
Expand Down Expand Up @@ -244,7 +254,7 @@ pub(crate) fn decapsulate<
ciphertext: &MlKemCiphertext<CIPHERTEXT_SIZE>,
) -> MlKemSharedSecret {
let (ind_cpa_secret_key, ind_cpa_public_key, ind_cpa_public_key_hash, implicit_rejection_value) =
unpack_private_key::<SECRET_KEY_SIZE, CPA_SECRET_KEY_SIZE, PUBLIC_KEY_SIZE>(private_key);
unpack_private_key::<CPA_SECRET_KEY_SIZE, PUBLIC_KEY_SIZE>(&private_key.value);

let decrypted = crate::ind_cpa::decrypt::<
K,
Expand Down Expand Up @@ -295,25 +305,6 @@ pub(crate) fn decapsulate<
)
}

/// Unpack an incoming private key into it's different parts.
fn unpack_private_key<
const SECRET_KEY_SIZE: usize,
const CPA_SECRET_KEY_SIZE: usize,
const PUBLIC_KEY_SIZE: usize,
>(
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
) -> (&[u8], &[u8], &[u8], &[u8]) {
let (ind_cpa_secret_key, secret_key) = private_key.value.split_at(CPA_SECRET_KEY_SIZE);
let (ind_cpa_public_key, secret_key) = secret_key.split_at(PUBLIC_KEY_SIZE);
let (ind_cpa_public_key_hash, implicit_rejection_value) = secret_key.split_at(H_DIGEST_SIZE);
(
ind_cpa_secret_key,
ind_cpa_public_key,
ind_cpa_public_key_hash,
implicit_rejection_value,
)
}

/// Types for the unpacked API.
pub(crate) mod unpacked {
use core::array::from_fn;
Expand Down Expand Up @@ -424,6 +415,55 @@ pub(crate) mod unpacked {
}
}

/// Take a serialized private key and generate an unpacked key pair from it.
#[inline(always)]
pub fn keys_from_private_key<
const K: usize,
const SECRET_KEY_SIZE: usize,
const CPA_SECRET_KEY_SIZE: usize,
const PUBLIC_KEY_SIZE: usize,
const BYTES_PER_RING_ELEMENT: usize,
const T_AS_NTT_ENCODED_SIZE: usize,
Vector: Operations,
>(
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
key_pair: &mut MlKemKeyPairUnpacked<K, Vector>,
) {
let (
ind_cpa_secret_key,
ind_cpa_public_key,
ind_cpa_public_key_hash,
implicit_rejection_value,
) = unpack_private_key::<CPA_SECRET_KEY_SIZE, PUBLIC_KEY_SIZE>(&private_key.value);
// // XXX: We need to copy_from_slice here because eurydice fails with
// // the assignment
// out.private_key
// .ind_cpa_private_key
// .secret_as_ntt
// .copy_from_slice(&ind_cpa::deserialize_secret_key::<K, Vector>(
// ind_cpa_secret_key,
// ));
key_pair.private_key.ind_cpa_private_key.secret_as_ntt =
ind_cpa::deserialize_secret_key::<K, Vector>(ind_cpa_secret_key);
ind_cpa::build_unpacked_public_key_mut::<K, T_AS_NTT_ENCODED_SIZE, Vector, PortableHash<K>>(
ind_cpa_public_key,
&mut key_pair.public_key.ind_cpa_public_key,
);
key_pair
.public_key
.public_key_hash
.copy_from_slice(ind_cpa_public_key_hash);
key_pair
.private_key
.implicit_rejection_value
.copy_from_slice(implicit_rejection_value);
key_pair
.public_key
.ind_cpa_public_key
.seed_for_A
.copy_from_slice(&ind_cpa_public_key[T_AS_NTT_ENCODED_SIZE..]);
}

impl<const K: usize, Vector: Operations> MlKemKeyPairUnpacked<K, Vector> {
/// Create a new empty unpacked key pair.
#[inline(always)]
Expand All @@ -432,10 +472,6 @@ pub(crate) mod unpacked {
}

/// Take a serialized private key and generate an unpacked key pair from it.
///
/// Note that we can't restore the seed for A. But it's not needed.
/// However, the unpacked public key in a key generated like this
/// is not fully usable (serializable).
#[inline(always)]
pub fn from_private_key<
const SECRET_KEY_SIZE: usize,
Expand All @@ -447,29 +483,15 @@ pub(crate) mod unpacked {
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
) -> Self {
let mut out = Self::default();
let (
ind_cpa_secret_key,
ind_cpa_public_key,
ind_cpa_public_key_hash,
implicit_rejection_value,
) = unpack_private_key::<SECRET_KEY_SIZE, CPA_SECRET_KEY_SIZE, PUBLIC_KEY_SIZE>(
private_key,
);
out.private_key.ind_cpa_private_key.secret_as_ntt =
ind_cpa::deserialize_secret_key::<K, Vector>(ind_cpa_secret_key);
ind_cpa::build_unpacked_public_key_mut::<
keys_from_private_key::<
K,
SECRET_KEY_SIZE,
CPA_SECRET_KEY_SIZE,
PUBLIC_KEY_SIZE,
BYTES_PER_RING_ELEMENT,
T_AS_NTT_ENCODED_SIZE,
Vector,
PortableHash<K>,
>(ind_cpa_public_key, &mut out.public_key.ind_cpa_public_key);
out.public_key
.public_key_hash
.copy_from_slice(ind_cpa_public_key_hash);
out.private_key
.implicit_rejection_value
.copy_from_slice(implicit_rejection_value);

>(private_key, &mut out);
out
}

Expand Down Expand Up @@ -610,14 +632,14 @@ pub(crate) mod unpacked {
}
}
out.public_key.ind_cpa_public_key.A = A;
out.private_key.implicit_rejection_value = implicit_rejection_value.try_into().unwrap();

let pk_serialized =
serialize_public_key::<K, BYTES_PER_RING_ELEMENT, PUBLIC_KEY_SIZE, Vector>(
&out.public_key.ind_cpa_public_key.t_as_ntt,
&out.public_key.ind_cpa_public_key.seed_for_A,
);
out.public_key.public_key_hash = Hasher::H(&pk_serialized);
out.private_key.implicit_rejection_value = implicit_rejection_value.try_into().unwrap();
}

// Encapsulate with Unpacked Public Key
Expand Down
43 changes: 41 additions & 2 deletions libcrux-ml-kem/src/ind_cca/instantiations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ macro_rules! instantiate {
>(randomness)
}

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

/// Portable private key validation
/// Private key validation
#[inline(always)]
pub(crate) fn validate_private_key<
const K: usize,
Expand All @@ -91,6 +91,17 @@ macro_rules! instantiate {
)
}

/// Private key validation
#[inline(always)]
pub(crate) fn validate_private_key_only<
const K: usize,
const SECRET_KEY_SIZE: usize,
>(
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
) -> bool {
crate::ind_cca::validate_private_key_only::<K, SECRET_KEY_SIZE, $hash>(private_key)
}

/// Portable encapsulate
#[cfg(feature = "kyber")]
pub(crate) fn kyber_encapsulate<
Expand Down Expand Up @@ -270,6 +281,7 @@ macro_rules! instantiate {
crate::ind_cca::unpacked::MlKemPublicKeyUnpacked<K, $vector>;

/// Get the unpacked public key.
#[inline(always)]
pub(crate) fn unpack_public_key<
const K: usize,
const T_AS_NTT_ENCODED_SIZE: usize,
Expand All @@ -289,7 +301,32 @@ macro_rules! instantiate {
>(public_key, unpacked_public_key)
}

/// Take a serialized private key and generate an unpacked key pair from it.
#[inline(always)]
pub(crate) fn keypair_from_private_key<
const K: usize,
const SECRET_KEY_SIZE: usize,
const CPA_SECRET_KEY_SIZE: usize,
const PUBLIC_KEY_SIZE: usize,
const BYTES_PER_RING_ELEMENT: usize,
const T_AS_NTT_ENCODED_SIZE: usize,
>(
private_key: &MlKemPrivateKey<SECRET_KEY_SIZE>,
key_pair: &mut MlKemKeyPairUnpacked<K>,
) {
crate::ind_cca::unpacked::keys_from_private_key::<
K,
SECRET_KEY_SIZE,
CPA_SECRET_KEY_SIZE,
PUBLIC_KEY_SIZE,
BYTES_PER_RING_ELEMENT,
T_AS_NTT_ENCODED_SIZE,
$vector,
>(private_key, key_pair);
}

/// Generate a key pair
#[inline(always)]
pub(crate) fn generate_keypair<
const K: usize,
const CPA_PRIVATE_KEY_SIZE: usize,
Expand Down Expand Up @@ -317,6 +354,7 @@ macro_rules! instantiate {
}

/// Unpacked encapsulate
#[inline(always)]
pub(crate) fn encapsulate<
const K: usize,
const CIPHERTEXT_SIZE: usize,
Expand Down Expand Up @@ -355,6 +393,7 @@ macro_rules! instantiate {
}

/// Unpacked decapsulate
#[inline(always)]
pub(crate) fn decapsulate<
const K: usize,
const SECRET_KEY_SIZE: usize,
Expand Down
1 change: 0 additions & 1 deletion libcrux-ml-kem/src/ind_cpa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ pub mod unpacked {
use crate::{polynomial::PolynomialRingElement, vector::traits::Operations};

/// An unpacked ML-KEM IND-CPA Private Key
#[derive(Clone)]
pub(crate) struct IndCpaPrivateKeyUnpacked<const K: usize, Vector: Operations> {
pub(crate) secret_as_ntt: [PolynomialRingElement<Vector>; K],
}
Expand Down
15 changes: 13 additions & 2 deletions libcrux-ml-kem/src/mlkem1024.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ macro_rules! instantiate {
>(private_key, ciphertext)
}

/// Validate the private key only.
///
/// Returns `true` if valid, and `false` otherwise.
pub fn validate_private_key_only(
private_key: &MlKem1024PrivateKey,
) -> bool {
p::validate_private_key_only::<
RANK_1024,
SECRET_KEY_SIZE_1024,
>(private_key)
}

/// Generate Kyber 1024 Key Pair
#[cfg(feature = "kyber")]
#[cfg_attr(docsrs, doc(cfg(feature = "kyber")))]
Expand Down Expand Up @@ -274,9 +286,8 @@ macro_rules! instantiate {
}

/// Get an unpacked key from a private key.
/// Note that this is missing the seed of A, which is unrecoverable.
pub fn key_pair_from_private_mut(private_key: &MlKem1024PrivateKey, key_pair: &mut MlKem1024KeyPairUnpacked) {
*key_pair = MlKem1024KeyPairUnpacked::from_private_key::<SECRET_KEY_SIZE_1024, CPA_PKE_SECRET_KEY_SIZE_1024, CPA_PKE_PUBLIC_KEY_SIZE_1024, RANKED_BYTES_PER_RING_ELEMENT_1024, T_AS_NTT_ENCODED_SIZE_1024>(private_key);
p::unpacked::keypair_from_private_key::<RANK_1024, SECRET_KEY_SIZE_1024, CPA_PKE_SECRET_KEY_SIZE_1024, CPA_PKE_PUBLIC_KEY_SIZE_1024, RANKED_BYTES_PER_RING_ELEMENT_1024, T_AS_NTT_ENCODED_SIZE_1024>(private_key, key_pair);
}

/// Get the unpacked public key.
Expand Down
15 changes: 13 additions & 2 deletions libcrux-ml-kem/src/mlkem512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ macro_rules! instantiate {
>(private_key, ciphertext)
}

/// Validate the private key only.
///
/// Returns `true` if valid, and `false` otherwise.
pub fn validate_private_key_only(
private_key: &MlKem512PrivateKey,
) -> bool {
p::validate_private_key_only::<
RANK_512,
SECRET_KEY_SIZE_512,
>(private_key)
}

/// Generate ML-KEM 512 Key Pair
pub fn generate_key_pair(
randomness: [u8; KEY_GENERATION_SEED_SIZE],
Expand Down Expand Up @@ -271,9 +283,8 @@ macro_rules! instantiate {
}

/// Get an unpacked key from a private key.
/// Note that this is missing the seed of A, which is unrecoverable.
pub fn key_pair_from_private_mut(private_key: &MlKem512PrivateKey, key_pair: &mut MlKem512KeyPairUnpacked) {
*key_pair = MlKem512KeyPairUnpacked::from_private_key::<SECRET_KEY_SIZE_512, CPA_PKE_SECRET_KEY_SIZE_512, CPA_PKE_PUBLIC_KEY_SIZE_512, RANKED_BYTES_PER_RING_ELEMENT_512, T_AS_NTT_ENCODED_SIZE_512>(private_key);
p::unpacked::keypair_from_private_key::<RANK_512, SECRET_KEY_SIZE_512, CPA_PKE_SECRET_KEY_SIZE_512, CPA_PKE_PUBLIC_KEY_SIZE_512, RANKED_BYTES_PER_RING_ELEMENT_512, T_AS_NTT_ENCODED_SIZE_512>(private_key, key_pair);
}

/// Get the unpacked public key.
Expand Down
15 changes: 13 additions & 2 deletions libcrux-ml-kem/src/mlkem768.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ macro_rules! instantiate {
>(private_key, ciphertext)
}

/// Validate the private key only.
///
/// Returns `true` if valid, and `false` otherwise.
pub fn validate_private_key_only(
private_key: &MlKem768PrivateKey,
) -> bool {
p::validate_private_key_only::<
RANK_768,
SECRET_KEY_SIZE_768,
>(private_key)
}

/// Generate ML-KEM 768 Key Pair
pub fn generate_key_pair(
randomness: [u8; KEY_GENERATION_SEED_SIZE],
Expand Down Expand Up @@ -267,9 +279,8 @@ macro_rules! instantiate {
}

/// Get an unpacked key from a private key.
/// Note that this is missing the seed of A, which is unrecoverable.
pub fn key_pair_from_private_mut(private_key: &MlKem768PrivateKey, key_pair: &mut MlKem768KeyPairUnpacked) {
*key_pair = MlKem768KeyPairUnpacked::from_private_key::<SECRET_KEY_SIZE_768, CPA_PKE_SECRET_KEY_SIZE_768, CPA_PKE_PUBLIC_KEY_SIZE_768, RANKED_BYTES_PER_RING_ELEMENT_768, T_AS_NTT_ENCODED_SIZE_768>(private_key);
p::unpacked::keypair_from_private_key::<RANK_768, SECRET_KEY_SIZE_768, CPA_PKE_SECRET_KEY_SIZE_768, CPA_PKE_PUBLIC_KEY_SIZE_768, RANKED_BYTES_PER_RING_ELEMENT_768, T_AS_NTT_ENCODED_SIZE_768>(private_key, key_pair);
}

/// Get the unpacked public key.
Expand Down
Loading

0 comments on commit 76be581

Please sign in to comment.