Skip to content

PSQv2 #1048

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open

PSQv2 #1048

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cd72d4a
WIP PSQv2 Query mode
jschneider-bensch Jul 8, 2025
a247764
PSQv2 Query Mode
jschneider-bensch Jul 2, 2025
28b9c9a
WIP PSQv2 Registration Mode
jschneider-bensch Jul 2, 2025
7b42faa
Missing files
jschneider-bensch Jul 2, 2025
a4856f1
WIP
jschneider-bensch Jul 3, 2025
c108330
Implement TlsCodec for ML-KEM public keys and ciphertexts
jschneider-bensch Jul 7, 2025
5524762
Query mode roundtrip test
jschneider-bensch Jul 8, 2025
555b88d
Registration mode roundtrip test
jschneider-bensch Jul 7, 2025
75e432e
Registration Mode
jschneider-bensch Jul 8, 2025
077ee10
Use incremental hashing for transcript
jschneider-bensch Jul 8, 2025
6c9f251
Replace `From<&PrivateKey> for PublicKey` with `PrivateKey.to_public()`
jschneider-bensch Jul 9, 2025
e2452b1
Add documentation for `ecdh` module
jschneider-bensch Jul 9, 2025
2ed6963
Change visibility on `AEADKey` field
jschneider-bensch Jul 9, 2025
b542d8b
`serialize_encrypt`: Pass in output slice & return `Result`
jschneider-bensch Jul 9, 2025
92899bd
PQKeyPair wrapper
jschneider-bensch Jul 9, 2025
faf76df
KeyPair wrapper
jschneider-bensch Jul 9, 2025
88db90b
Fix clippy warnings
jschneider-bensch Jul 9, 2025
81fc3dc
Introduce `as_query_msg`, `as_registration_msg` on `InitiatorOuterPay…
jschneider-bensch Jul 9, 2025
68008e7
Address review comments
jschneider-bensch Jul 9, 2025
9ab032e
Add timestamp
jschneider-bensch Jul 9, 2025
6d9cadc
Inverted timestamp logic
jschneider-bensch Jul 9, 2025
c409510
wip API for query protocol
franziskuskiefer Jul 14, 2025
0e8a9b8
Merge remote-tracking branch 'origin/franziskus/psq-v2-api' into jona…
jschneider-bensch Jul 15, 2025
7e8a07d
Query mode API
jschneider-bensch Jul 16, 2025
8e3e716
WIP
jschneider-bensch Jul 16, 2025
c3b78c7
Registration mode
jschneider-bensch Jul 17, 2025
32b15c1
Propagate errors / expect panics
jschneider-bensch Jul 17, 2025
e9f0a0c
Add `is_initiator` and `is_handshake_finished` functions
jschneider-bensch Jul 17, 2025
b6a3a7b
Merge branch 'main' into jonas/psq-v2
jschneider-bensch Jul 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions libcrux-ml-kem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ libcrux-intrinsics = { version = "0.0.3", path = "../libcrux-intrinsics" }
libcrux-secrets = { version = "0.0.3", path = "../secrets" }
libcrux-traits = { version = "0.0.3", path = "../traits" }
hax-lib.workspace = true
tls_codec = { version = "0.4.2", features = ["derive"], default-features = false, optional = true}

[features]
# By default all variants and std are enabled.
default = ["default-no-std", "std"]
default-no-std = ["mlkem512", "mlkem768", "mlkem1024", "rand"]

# Serialization & Deserialization using tls_codec
codec = ["dep:tls_codec"]

# Hardware features can be force enabled.
# It is not recommended to use these. This crate performs CPU feature detection
# and enables the features when they are available.
Expand Down
5 changes: 4 additions & 1 deletion libcrux-ml-kem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ pub(crate) mod hax_utils;
// This is being tracked in https://github.com/hacspec/hacspec-v2/issues/27
pub(crate) mod constants;

#[cfg(all(feature = "alloc", feature = "incremental"))]
#[cfg(any(
all(feature = "alloc", feature = "incremental"),
all(feature = "alloc", feature = "codec")
))]
extern crate alloc;

/// Helpers for verification and extraction
Expand Down
79 changes: 79 additions & 0 deletions libcrux-ml-kem/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,85 @@ mod index_impls {
impl_index_impls_for_generic_struct!(MlKemPublicKey);
}

#[cfg(all(feature = "codec", feature = "alloc"))]
mod codec {
use super::*;

macro_rules! impl_tls_codec_for_generic_struct {
($name:ident) => {
impl<const SIZE: usize> tls_codec::SerializeBytes for $name<SIZE> {
fn tls_serialize(&self) -> Result<alloc::vec::Vec<u8>, tls_codec::Error> {
tls_codec::TlsByteVecU16::from_slice(self.as_ref()).tls_serialize()
}
}

impl<const SIZE: usize> tls_codec::Size for $name<SIZE> {
fn tls_serialized_len(&self) -> usize {
SIZE + 2
}
}

impl<const SIZE: usize> tls_codec::DeserializeBytes for $name<SIZE> {
fn tls_deserialize_bytes(
bytes: &[u8],
) -> Result<($name<SIZE>, &[u8]), tls_codec::Error> {
let (vec, rest) = tls_codec::TlsByteVecU16::tls_deserialize_bytes(bytes)?;
if vec.len() != SIZE {
Err(tls_codec::Error::InvalidVectorLength)
} else {
Ok((
$name::<SIZE>::try_from(vec.as_slice())
.expect("deserialized vector should have the length {SIZE}"),
rest,
))
}
}
}

impl<const SIZE: usize> tls_codec::SerializeBytes for &$name<SIZE> {
fn tls_serialize(&self) -> Result<alloc::vec::Vec<u8>, tls_codec::Error> {
tls_codec::TlsByteVecU16::from_slice(self.as_ref()).tls_serialize()
}
}

impl<const SIZE: usize> tls_codec::Size for &$name<SIZE> {
fn tls_serialized_len(&self) -> usize {
SIZE + 2
}
}
};
}

impl_tls_codec_for_generic_struct!(MlKemCiphertext);
impl_tls_codec_for_generic_struct!(MlKemPublicKey);

#[cfg(test)]
mod test {
use tls_codec::{DeserializeBytes, SerializeBytes, Size};

use super::*;

#[test]
fn ser_de() {
const SIZE: usize = 1568;
let test_struct = MlKemCiphertext::<SIZE>::default();

assert_eq!(test_struct.tls_serialized_len(), SIZE + 2);
let test_struct_serialized = test_struct.tls_serialize().unwrap();
assert_eq!(
test_struct_serialized.len(),
test_struct.tls_serialized_len()
);

let test_struct_deserialied =
MlKemCiphertext::<SIZE>::tls_deserialize_exact_bytes(&test_struct_serialized)
.unwrap();

assert_eq!(test_struct.as_ref(), test_struct_deserialied.as_ref())
}
}
}

/// An ML-KEM key pair
pub struct MlKemKeyPair<const PRIVATE_KEY_SIZE: usize, const PUBLIC_KEY_SIZE: usize> {
pub(crate) sk: MlKemPrivateKey<PRIVATE_KEY_SIZE>,
Expand Down
7 changes: 5 additions & 2 deletions libcrux-psq/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@ libcrux-kem = { version = "=0.0.3", path = "../libcrux-kem" }
libcrux-chacha20poly1305 = { version = "0.0.3", path = "../chacha20poly1305" }
libcrux-hkdf = { version = "=0.0.3", path = "../libcrux-hkdf" }
libcrux-hmac = { version = "=0.0.3", path = "../libcrux-hmac" }
libcrux-sha2 = { version = "=0.0.3", path = "../sha2" }
classic-mceliece-rust = { version = "3.1.0", features = [
"mceliece460896f",
"zeroize",
], optional = true }
rand = { version = "0.9" }
rand_old = { version = "0.8", package = "rand", optional = true }
libcrux-ecdh = { version = "0.0.3", path = "../libcrux-ecdh", optional = true }
libcrux-ecdh = { version = "0.0.3", path = "../libcrux-ecdh" }
libcrux-ml-kem = { version = "0.0.3", path = "../libcrux-ml-kem", features = ["codec"] }
libcrux-ed25519 = { version = "0.0.3", path = "../ed25519", features = [
"rand",
] }
tls_codec = { version = "0.4.2", features = ["derive"] }

[dev-dependencies]
libcrux-psq = { path = ".", features = ["test-utils"] }
Expand All @@ -43,7 +46,7 @@ classic-mceliece = ["dep:classic-mceliece-rust", "rand_old"]
# DO NOT USE: This feature enables implementations backed
# by non-post-quantum KEMs and should only be used for
# testing purposes and benchmark baselines.
test-utils = ["libcrux-ecdh"]
test-utils = []

[[bench]]
name = "psq"
Expand Down
5 changes: 5 additions & 0 deletions libcrux-psq/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ use std::array::TryFromSliceError;
#[derive(Debug)]
/// PSQ Errors.
pub enum Error {
/// An error during serialization.
Serialization,
/// The Initator message was stale
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// The Initator message was stale
/// The Initiator message was stale

TimestampElapsed,
/// An invalid public key was provided
InvalidPublicKey,
/// An invalid private key was provided
Expand Down Expand Up @@ -75,6 +79,7 @@ const PSK_LENGTH: usize = 32;
type Psk = [u8; PSK_LENGTH];

pub mod cred;
pub mod protocol;
pub mod psk_registration;

#[cfg(feature = "classic-mceliece")]
Expand Down
Loading
Loading