Add LpConfig struct and AIDEV-NOTE documentation for KKT+PSQ
- Create config.rs with LpConfig struct (kem_algorithm, psk_ttl, enable_kkt) - Export LpConfig from lib.rs - Add AIDEV-NOTE to psk.rs explaining: - Why PSQ is embedded in Noise (single round-trip, PSK binding) - KEM migration path (X25519 → MlKem768 → XWing) - Add AIDEV-NOTE to state_machine.rs explaining protocol flow: - KKTExchange → Handshaking → Transport state transitions - PSK derivation formula (ECDH || PSQ || salt)
This commit is contained in:
committed by
Jędrzej Stuczyński
parent
b5f1bab87b
commit
bb76ff82bd
@@ -0,0 +1,79 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Configuration for LP protocol.
|
||||
//!
|
||||
//! AIDEV-NOTE: LP security stack = KKT (key fetch) → PSQ (PQ PSK) → Noise (transport).
|
||||
//! KEM algorithm selection affects only PSQ layer. Noise always uses X25519 DH.
|
||||
//! Migration to PQ KEMs (MlKem768, XWing) requires only config change.
|
||||
|
||||
use nym_kkt::ciphersuite::KEM;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Default PSK time-to-live (1 hour, matches psk.rs implementation).
|
||||
pub const DEFAULT_PSK_TTL_SECS: u64 = 3600;
|
||||
|
||||
/// Configuration for LP protocol.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LpConfig {
|
||||
/// KEM algorithm for PSQ key encapsulation.
|
||||
/// X25519 = classical (testing), MlKem768 = PQ, XWing = hybrid.
|
||||
#[serde(with = "kem_serde")]
|
||||
pub kem_algorithm: KEM,
|
||||
|
||||
/// PSK time-to-live in seconds.
|
||||
pub psk_ttl_secs: u64,
|
||||
|
||||
/// Enable KKT for authenticated key distribution.
|
||||
pub enable_kkt: bool,
|
||||
}
|
||||
|
||||
impl Default for LpConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
kem_algorithm: KEM::X25519,
|
||||
psk_ttl_secs: DEFAULT_PSK_TTL_SECS,
|
||||
enable_kkt: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LpConfig {
|
||||
/// Returns PSK TTL as Duration.
|
||||
pub fn psk_ttl(&self) -> Duration {
|
||||
Duration::from_secs(self.psk_ttl_secs)
|
||||
}
|
||||
}
|
||||
|
||||
mod kem_serde {
|
||||
use nym_kkt::ciphersuite::KEM;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
pub fn serialize<S>(kem: &KEM, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match kem {
|
||||
KEM::X25519 => "X25519",
|
||||
KEM::MlKem768 => "MlKem768",
|
||||
KEM::XWing => "XWing",
|
||||
KEM::McEliece => "McEliece",
|
||||
}
|
||||
.serialize(serializer)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<KEM, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
match s.as_str() {
|
||||
"X25519" => Ok(KEM::X25519),
|
||||
"MlKem768" => Ok(KEM::MlKem768),
|
||||
"XWing" => Ok(KEM::XWing),
|
||||
"McEliece" => Ok(KEM::McEliece),
|
||||
_ => Err(serde::de::Error::custom(format!("Unknown KEM: {}", s))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod codec;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod keypair;
|
||||
pub mod kkt_orchestrator;
|
||||
@@ -14,6 +15,7 @@ pub mod session;
|
||||
mod session_integration;
|
||||
pub mod session_manager;
|
||||
|
||||
pub use config::LpConfig;
|
||||
pub use error::LpError;
|
||||
pub use message::{ClientHelloData, LpMessage};
|
||||
pub use packet::{BOOTSTRAP_RECEIVER_IDX, LpPacket, OuterHeader};
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
//! This module implements identity-bound PSK derivation where both client and gateway
|
||||
//! derive the same PSK from their LP keypairs.
|
||||
//!
|
||||
//! AIDEV-NOTE: PSQ is embedded in Noise (not separate protocol) because:
|
||||
//! 1. Single round-trip: PSQ ciphertext piggybacks on Noise handshake messages
|
||||
//! 2. PSK binding: Noise XKpsk3 pattern authenticates both ECDH and PSQ-derived PSK
|
||||
//! 3. Simpler state machine: No separate PSQ negotiation phase needed
|
||||
//! 4. Atomic security: Session establishment either succeeds fully or fails completely
|
||||
//!
|
||||
//! Two approaches are supported:
|
||||
//! - **Legacy ECDH-only** (`derive_psk`) - Simple but no post-quantum security
|
||||
//! - **PSQ-enhanced** (`derive_psk_with_psq_*`) - Combines ECDH with post-quantum KEM
|
||||
@@ -140,7 +146,12 @@ pub fn derive_psk_with_psq_initiator(
|
||||
let ecdh_secret = local_x25519_private.diffie_hellman(remote_x25519_public);
|
||||
|
||||
// Step 2: PSQ encapsulation for post-quantum security
|
||||
// Extract X25519 public key from EncapsulationKey
|
||||
// AIDEV-NOTE: KEM algorithm migration path:
|
||||
// - X25519: Current default for testing/compatibility (no HNDL resistance)
|
||||
// - MlKem768: Future production default (NIST PQ Level 3, HNDL resistant)
|
||||
// - XWing: Maximum security option (hybrid X25519 + ML-KEM)
|
||||
// Migration: Update LpConfig.kem_algorithm, no protocol changes needed.
|
||||
// KKT protocol adapts automatically to different KEM key sizes.
|
||||
let kem_pk = match remote_kem_public {
|
||||
EncapsulationKey::X25519(pk) => pk,
|
||||
_ => {
|
||||
|
||||
@@ -2,6 +2,16 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Lewes Protocol State Machine for managing connection lifecycle.
|
||||
//!
|
||||
//! AIDEV-NOTE: LP protocol flow (KKT → PSQ → Noise):
|
||||
//! 1. KKTExchange: Client requests gateway's KEM public key (signed for MITM protection)
|
||||
//! 2. Handshaking: Noise XKpsk3 with PSQ-derived PSK embedded in handshake messages
|
||||
//! - PSQ ciphertext piggybacked on ClientHello (no extra round-trip)
|
||||
//! - PSK = Blake3(ECDH || PSQ_secret || salt) provides hybrid classical+PQ security
|
||||
//! 3. Transport: ChaCha20-Poly1305 authenticated encryption with derived keys
|
||||
//!
|
||||
//! State machine ensures protocol steps execute in correct order. Invalid transitions
|
||||
//! return LpError, preventing protocol violations.
|
||||
|
||||
use crate::{
|
||||
LpError,
|
||||
|
||||
Reference in New Issue
Block a user