mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-12 01:27:32 +00:00
Add periodic Noise rekey with fresh DH for forward secrecy (FMP + FSP)
Implement periodic full rekey at both protocol layers using fresh DH key exchanges. Uses the existing K-bit flag (FLAG_KEY_EPOCH / FSP_FLAG_K) to coordinate cutover between peers. FMP layer (IK pattern): - ActivePeer gains rekey state: pending/previous sessions, K-bit epoch tracking, drain window, dampening timer - Handshake state stored on ActivePeer with msg1 sent on existing link - Encrypted frame handler detects K-bit flips, promotes pending sessions, falls back to previous session during drain - Handshake handlers distinguish rekey from new connections using addr_to_link lookup with identity-based fallback - Free all session indices (current, rekey, pending, previous) on peer removal FSP layer (XK pattern): - SessionEntry gains parallel rekey fields with XK-specific state for the 3-message handshake - Route availability check before FSP rekey initiation - Encrypted session handler adds K-bit flip detection and dual-session decrypt fallback - SessionSetup/Ack/Msg3 handlers extended for rekey paths Defense-in-depth: - Consecutive decryption failure detector (threshold=20) triggers forced peer removal instead of waiting for link-dead timeout - Identity-based rekey detection as fallback when addr_to_link doesn't match (e.g., TCP ephemeral ports) Configuration: RekeyConfig with enabled flag, after_secs (default 120), and after_messages (default 65536) thresholds. Logging: info for successful K-bit cutover completions, warn for failures, debug for intermediate handshake steps, trace for routine operations (resends, drain cleanup). Rekey lifecycle: 1. Timer/counter fires -> initiator starts new handshake 2. Old session continues handling traffic during handshake 3. Handshake completes -> initiator cuts over, flips K-bit 4. Responder sees flipped K-bit -> promotes new session 5. Both keep old session for 10s drain window 6. After drain, old session discarded Integration test: Docker-based multi-phase test exercising both FMP and FSP rekey with aggressive timers (35s). Verifies connectivity across all 20 directed pairs survives two consecutive rekey cycles. Includes rekey topology, docker-compose profile, and CI matrix entry. Increase ping test convergence wait from 3s to 5s for CI reliability.
This commit is contained in:
@@ -418,6 +418,42 @@ impl BuffersConfig {
|
||||
// ECN Congestion Signaling
|
||||
// ============================================================================
|
||||
|
||||
/// Rekey / session rekeying configuration (`node.rekey.*`).
|
||||
///
|
||||
/// Controls periodic full rekey for both FMP (link layer) and FSP
|
||||
/// (session layer) Noise sessions. Rekeying provides true forward secrecy
|
||||
/// with fresh DH randomness, nonce reset, and session index rotation.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RekeyConfig {
|
||||
/// Enable periodic rekey (`node.rekey.enabled`).
|
||||
#[serde(default = "RekeyConfig::default_enabled")]
|
||||
pub enabled: bool,
|
||||
|
||||
/// Initiate rekey after this many seconds (`node.rekey.after_secs`).
|
||||
#[serde(default = "RekeyConfig::default_after_secs")]
|
||||
pub after_secs: u64,
|
||||
|
||||
/// Initiate rekey after this many messages sent (`node.rekey.after_messages`).
|
||||
#[serde(default = "RekeyConfig::default_after_messages")]
|
||||
pub after_messages: u64,
|
||||
}
|
||||
|
||||
impl Default for RekeyConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled: true,
|
||||
after_secs: 120,
|
||||
after_messages: 1 << 16, // 65536
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RekeyConfig {
|
||||
fn default_enabled() -> bool { true }
|
||||
fn default_after_secs() -> u64 { 120 }
|
||||
fn default_after_messages() -> u64 { 1 << 16 }
|
||||
}
|
||||
|
||||
/// ECN congestion signaling configuration (`node.ecn.*`).
|
||||
///
|
||||
/// Controls the FMP CE relay chain: transit nodes detect congestion on outgoing
|
||||
@@ -541,6 +577,10 @@ pub struct NodeConfig {
|
||||
/// ECN congestion signaling (`node.ecn.*`).
|
||||
#[serde(default)]
|
||||
pub ecn: EcnConfig,
|
||||
|
||||
/// Rekey / session rekeying (`node.rekey.*`).
|
||||
#[serde(default)]
|
||||
pub rekey: RekeyConfig,
|
||||
}
|
||||
|
||||
impl Default for NodeConfig {
|
||||
@@ -565,6 +605,7 @@ impl Default for NodeConfig {
|
||||
mmp: MmpConfig::default(),
|
||||
session_mmp: SessionMmpConfig::default(),
|
||||
ecn: EcnConfig::default(),
|
||||
rekey: RekeyConfig::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user