helpers for Transport

This commit is contained in:
Jędrzej Stuczyński
2026-02-18 16:55:25 +00:00
parent 63582dd4e1
commit d56ca5fa78
7 changed files with 152 additions and 150 deletions
+3 -3
View File
@@ -81,8 +81,8 @@ impl KKTRequestPlaintext {
responder_pubkey: &DHPublicKey,
) -> Vec<u8> {
let mut mask = Vec::with_capacity(2 * x25519::PUBLIC_KEY_LENGTH);
mask.extend_from_slice(&initiator_pubkey.as_ref());
mask.extend_from_slice(&responder_pubkey.as_ref());
mask.extend_from_slice(initiator_pubkey.as_ref());
mask.extend_from_slice(responder_pubkey.as_ref());
mask
}
@@ -102,7 +102,7 @@ impl KKTRequestPlaintext {
pub(crate) fn to_bytes(&self) -> Vec<u8> {
let mut out = Vec::with_capacity(x25519::PUBLIC_KEY_LENGTH + MASKED_BYTE_LEN);
out.extend_from_slice(self.dh_pubkey.as_ref());
out.extend_from_slice(&self.masked_version_bytes.as_slice());
out.extend_from_slice(self.masked_version_bytes.as_slice());
out
}
+36 -13
View File
@@ -5,6 +5,7 @@ use crate::packet::{EncryptedLpPacket, InnerHeader, LpHeader, LpPacket, OuterHea
use crate::{LpError, LpMessage};
use bytes::BytesMut;
use libcrux_psq::Channel;
use nym_lp_transport::traits::LpTransport;
use tracing::error;
pub(crate) const CIPHERTEXT_OVERHEAD: usize = 25;
@@ -50,6 +51,39 @@ pub fn parse_lp_header_only(src: &[u8]) -> Result<OuterHeader, LpError> {
// // })
// }
pub(crate) fn encrypt_data(
plaintext: &[u8],
transport: &mut libcrux_psq::Transport,
) -> Result<Vec<u8>, LpError> {
let mut ciphertext = vec![0u8; plaintext.len() + CIPHERTEXT_OVERHEAD];
let n = transport.write_message(&*plaintext, &mut ciphertext)?;
if ciphertext.len() != n {
// TODO: check consistency
panic!("inconsistent ciphertext overhead")
}
// ciphertext.truncate(n);
Ok(ciphertext)
}
pub(crate) fn decrypt_data(
ciphertext: &[u8],
transport: &mut libcrux_psq::Transport,
) -> Result<Vec<u8>, LpError> {
if ciphertext.len() < CIPHERTEXT_OVERHEAD {
return Err(LpError::InsufficientBufferSize);
}
let mut plaintext = vec![0u8; ciphertext.len() - CIPHERTEXT_OVERHEAD];
let (_, n) = transport.read_message(&ciphertext, &mut plaintext)?;
if n != ciphertext.len() - CIPHERTEXT_OVERHEAD {
// TODO: check consistency
panic!("inconsistent ciphertext overhead")
}
Ok(plaintext)
}
pub fn encrypt_lp_packet(
packet: LpPacket,
transport: &mut libcrux_psq::Transport,
@@ -58,14 +92,7 @@ pub fn encrypt_lp_packet(
packet.header.inner.encode(&mut plaintext);
packet.message.encode_content(&mut plaintext);
let mut ciphertext = vec![0u8; plaintext.len() + CIPHERTEXT_OVERHEAD];
let n = transport.write_message(&*plaintext, &mut ciphertext)?;
if ciphertext.len() != n {
error!("inconsistent ciphertext overhead")
}
ciphertext.truncate(n);
let ciphertext = encrypt_data(plaintext.as_ref(), transport)?;
Ok(EncryptedLpPacket {
outer_header: packet.header.outer,
@@ -81,11 +108,7 @@ pub fn decrypt_lp_packet(
return Err(LpError::InsufficientBufferSize);
}
let mut plaintext = Vec::with_capacity(packet.ciphertext.len() - CIPHERTEXT_OVERHEAD);
let (_, n) = transport.read_message(&packet.ciphertext, &mut plaintext)?;
if n != packet.ciphertext.len() - CIPHERTEXT_OVERHEAD {
error!("inconsistent ciphertext overhead")
}
let plaintext = decrypt_data(&packet.ciphertext, transport)?;
let inner_header = InnerHeader::parse(&plaintext)?;
let payload = &plaintext[InnerHeader::SIZE..];
+7 -24
View File
@@ -165,6 +165,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::codec::{decrypt_data, encrypt_data};
use crate::peer::mock_peers;
use crate::psq::responder;
use nym_kkt::responder::KKTResponder;
@@ -261,10 +262,6 @@ mod tests {
let mut r_transport = responder.into_session().unwrap();
// test serialization, deserialization
let mut msg_channel = vec![0u8; 2048];
let mut payload_buf_responder = vec![0u8; 4096];
let mut payload_buf_initiator = vec![0u8; 4096];
let mut channel_i = session_init.active_transport();
let mut channel_r = r_transport.transport_channel().unwrap();
@@ -273,30 +270,16 @@ mod tests {
let app_data_i = b"Derived session hey".as_slice();
let app_data_r = b"Derived session ho".as_slice();
let len_i = channel_i
.write_message(app_data_i, &mut msg_channel)
.unwrap();
let ct_i = encrypt_data(app_data_i, &mut channel_i)?;
let pt_r = decrypt_data(&ct_i, &mut channel_r)?;
let (len_r_deserialized, len_r_payload) = channel_r
.read_message(&msg_channel, &mut payload_buf_responder)
.unwrap();
assert_eq!(app_data_i, pt_r);
// We read the same amount of data.
assert_eq!(len_r_deserialized, len_i);
assert_eq!(len_r_payload, app_data_i.len());
assert_eq!(&payload_buf_responder[0..len_r_payload], app_data_i);
let ct_r = encrypt_data(app_data_r, &mut channel_r)?;
let pt_i = decrypt_data(&ct_r, &mut channel_i)?;
let len_r = channel_r
.write_message(app_data_r, &mut msg_channel)
.unwrap();
assert_eq!(app_data_r, pt_i);
let (len_i_deserialized, len_i_payload) = channel_i
.read_message(&msg_channel, &mut payload_buf_initiator)
.unwrap();
assert_eq!(len_r, len_i_deserialized);
assert_eq!(app_data_r.len(), len_i_payload);
assert_eq!(&payload_buf_initiator[0..len_i_payload], app_data_r);
Ok(())
}
}
+28 -23
View File
@@ -102,6 +102,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::codec::{decrypt_data, encrypt_data};
use crate::peer::mock_peers;
use libcrux_psq::handshake::types::Authenticator;
use libcrux_psq::session::{Session, SessionBinding};
@@ -153,14 +154,33 @@ mod tests {
let (session_init, session_resp) = join!(init_fut, resp_fut);
let session_init = session_init???;
let session_resp = session_resp???;
let mut session_init = session_init???;
let mut session_resp = session_resp???;
assert_eq!(
session_init.session_identifier(),
session_resp.session_identifier()
);
// test serialization, deserialization
let mut channel_i = session_init.active_transport();
let mut channel_r = session_resp.active_transport();
assert_eq!(channel_i.identifier(), channel_r.identifier());
let app_data_i = b"Derived session hey".as_slice();
let app_data_r = b"Derived session ho".as_slice();
let ct_i = encrypt_data(app_data_i, &mut channel_i)?;
let pt_r = decrypt_data(&ct_i, &mut channel_r)?;
assert_eq!(app_data_i, pt_r);
let ct_r = encrypt_data(app_data_r, &mut channel_r)?;
let pt_i = decrypt_data(&ct_r, &mut channel_i)?;
assert_eq!(app_data_r, pt_i);
Ok(())
}
@@ -309,29 +329,14 @@ mod tests {
let app_data_i = b"Derived session hey".as_slice();
let app_data_r = b"Derived session ho".as_slice();
let len_i = channel_i
.write_message(app_data_i, &mut msg_channel)
.unwrap();
let ct_i = encrypt_data(app_data_i, &mut channel_i).unwrap();
let pt_r = decrypt_data(&ct_i, &mut channel_r).unwrap();
let (len_r_deserialized, len_r_payload) = channel_r
.read_message(&msg_channel, &mut payload_buf_responder)
.unwrap();
assert_eq!(app_data_i, pt_r);
// We read the same amount of data.
assert_eq!(len_r_deserialized, len_i);
assert_eq!(len_r_payload, app_data_i.len());
assert_eq!(&payload_buf_responder[0..len_r_payload], app_data_i);
let ct_r = encrypt_data(app_data_r, &mut channel_r).unwrap();
let pt_i = decrypt_data(&ct_r, &mut channel_i).unwrap();
let len_r = channel_r
.write_message(app_data_r, &mut msg_channel)
.unwrap();
let (len_i_deserialized, len_i_payload) = channel_i
.read_message(&msg_channel, &mut payload_buf_initiator)
.unwrap();
assert_eq!(len_r, len_i_deserialized);
assert_eq!(app_data_r.len(), len_i_payload);
assert_eq!(&payload_buf_initiator[0..len_i_payload], app_data_r);
assert_eq!(app_data_r, pt_i);
}
}
+7 -25
View File
@@ -179,6 +179,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::codec::{decrypt_data, encrypt_data};
use crate::peer::mock_peers;
use crate::psq::initiator;
use nym_kkt::initiator::KKTInitiator;
@@ -271,10 +272,6 @@ mod tests {
let mut i_transport = initiator.into_session().unwrap();
// test serialization, deserialization
let mut msg_channel = vec![0u8; 2048];
let mut payload_buf_responder = vec![0u8; 4096];
let mut payload_buf_initiator = vec![0u8; 4096];
let mut channel_i = i_transport.transport_channel().unwrap();
let mut channel_r = session_resp.active_transport();
@@ -283,30 +280,15 @@ mod tests {
let app_data_i = b"Derived session hey".as_slice();
let app_data_r = b"Derived session ho".as_slice();
let len_i = channel_i
.write_message(app_data_i, &mut msg_channel)
.unwrap();
let ct_i = encrypt_data(app_data_i, &mut channel_i)?;
let pt_r = decrypt_data(&ct_i, &mut channel_r)?;
let (len_r_deserialized, len_r_payload) = channel_r
.read_message(&msg_channel, &mut payload_buf_responder)
.unwrap();
assert_eq!(app_data_i, pt_r);
// We read the same amount of data.
assert_eq!(len_r_deserialized, len_i);
assert_eq!(len_r_payload, app_data_i.len());
assert_eq!(&payload_buf_responder[0..len_r_payload], app_data_i);
let ct_r = encrypt_data(app_data_r, &mut channel_r)?;
let pt_i = decrypt_data(&ct_r, &mut channel_i)?;
let len_r = channel_r
.write_message(app_data_r, &mut msg_channel)
.unwrap();
let (len_i_deserialized, len_i_payload) = channel_i
.read_message(&msg_channel, &mut payload_buf_initiator)
.unwrap();
assert_eq!(len_r, len_i_deserialized);
assert_eq!(app_data_r.len(), len_i_payload);
assert_eq!(&payload_buf_initiator[0..len_i_payload], app_data_r);
assert_eq!(app_data_r, pt_i);
Ok(())
}
+66 -62
View File
@@ -51,7 +51,7 @@ impl SessionManager {
#[cfg(test)]
fn get_state_machine_id(&self, lp_id: SessionId) -> Result<SessionId, LpError> {
self.with_state_machine(lp_id, |sm| sm.id())?
self.with_state_machine(lp_id, |sm| sm.session_identifier())?
}
pub fn get_state(&self, lp_id: SessionId) -> Result<LpStateBare, LpError> {
@@ -139,78 +139,82 @@ mod tests {
#[test]
fn test_session_manager_get() {
let mut manager = SessionManager::new();
let TODO = " for kem in kem_list() {";
let local_session = mock_session_for_test();
let id = local_session.id();
let sm_1_id = manager.create_session_state_machine(local_session);
assert_eq!(sm_1_id, id);
let retrieved = manager.state_machine_exists(id);
assert!(retrieved);
let not_found = manager.state_machine_exists(99);
assert!(!not_found);
todo!()
// let mut manager = SessionManager::new();
//
// let TODO = " for kem in kem_list() {";
//
// let local_session = mock_session_for_test();
// let id = local_session.id();
//
// let sm_1_id = manager.create_session_state_machine(local_session);
// assert_eq!(sm_1_id, id);
//
// let retrieved = manager.state_machine_exists(id);
// assert!(retrieved);
//
// let not_found = manager.state_machine_exists(99);
// assert!(!not_found);
}
#[test]
fn test_session_manager_remove() {
let mut manager = SessionManager::new();
let local_session = mock_session_for_test();
let TODO = " for kem in kem_list() {";
let sm_1_id = manager.create_session_state_machine(local_session);
let removed = manager.remove_state_machine(sm_1_id);
assert!(removed);
assert_eq!(manager.session_count(), 0);
let removed_again = manager.remove_state_machine(sm_1_id);
assert!(!removed_again);
todo!()
// let mut manager = SessionManager::new();
// let local_session = mock_session_for_test();
//
// let TODO = " for kem in kem_list() {";
//
// let sm_1_id = manager.create_session_state_machine(local_session);
//
// let removed = manager.remove_state_machine(sm_1_id);
// assert!(removed);
// assert_eq!(manager.session_count(), 0);
//
// let removed_again = manager.remove_state_machine(sm_1_id);
// assert!(!removed_again);
}
#[test]
fn test_multiple_sessions() {
let mut manager = SessionManager::new();
let TODO = " for kem in kem_list() {";
let session1 = SessionsMock::mock_post_handshake(123).initiator;
let session2 = SessionsMock::mock_post_handshake(124).initiator;
let session3 = SessionsMock::mock_post_handshake(125).initiator;
let sm_1 = manager.create_session_state_machine(session1);
let sm_2 = manager.create_session_state_machine(session2);
let sm_3 = manager.create_session_state_machine(session3);
assert_eq!(manager.session_count(), 3);
let retrieved1 = manager.get_state_machine_id(sm_1).unwrap();
let retrieved2 = manager.get_state_machine_id(sm_2).unwrap();
let retrieved3 = manager.get_state_machine_id(sm_3).unwrap();
assert_eq!(retrieved1, sm_1);
assert_eq!(retrieved2, sm_2);
assert_eq!(retrieved3, sm_3);
todo!()
// let mut manager = SessionManager::new();
//
// let TODO = " for kem in kem_list() {";
//
// let session1 = SessionsMock::mock_post_handshake(123).initiator;
// let session2 = SessionsMock::mock_post_handshake(124).initiator;
// let session3 = SessionsMock::mock_post_handshake(125).initiator;
//
// let sm_1 = manager.create_session_state_machine(session1);
// let sm_2 = manager.create_session_state_machine(session2);
// let sm_3 = manager.create_session_state_machine(session3);
//
// assert_eq!(manager.session_count(), 3);
//
// let retrieved1 = manager.get_state_machine_id(sm_1).unwrap();
// let retrieved2 = manager.get_state_machine_id(sm_2).unwrap();
// let retrieved3 = manager.get_state_machine_id(sm_3).unwrap();
//
// assert_eq!(retrieved1, sm_1);
// assert_eq!(retrieved2, sm_2);
// assert_eq!(retrieved3, sm_3);
}
#[test]
fn test_session_manager_create_session() {
let mut manager = SessionManager::new();
let TODO = " for kem in kem_list() {";
let sesion = mock_session_for_test();
let sm = manager.create_session_state_machine(sesion);
assert_eq!(manager.session_count(), 1);
let retrieved = manager.get_state_machine_id(sm);
assert!(retrieved.is_ok());
assert_eq!(retrieved.unwrap(), sm);
todo!()
// let mut manager = SessionManager::new();
//
// let TODO = " for kem in kem_list() {";
//
// let sesion = mock_session_for_test();
//
// let sm = manager.create_session_state_machine(sesion);
// assert_eq!(manager.session_count(), 1);
//
// let retrieved = manager.get_state_machine_id(sm);
// assert!(retrieved.is_ok());
// assert_eq!(retrieved.unwrap(), sm);
}
}
+5
View File
@@ -14,6 +14,7 @@
//! return LpError, preventing protocol violations.
use crate::packet::EncryptedLpPacket;
use crate::session::SessionId;
use crate::{LpError, message::LpMessage, packet::LpPacket, session::LpSession};
use bytes::{Buf, Bytes};
use num_enum::{IntoPrimitive, TryFromPrimitive};
@@ -194,6 +195,10 @@ impl LpStateMachine {
// Ok(self.session()?.id())
}
pub fn session_identifier(&self) -> Result<SessionId, LpError> {
Ok(self.session_identifier()?)
}
/// Creates a new state machine in `Transport` state post-KKT/PSQ handshake
pub fn new(session: LpSession) -> Self {
LpStateMachine {