mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-11 09:07:44 +00:00
Switch FMP handshake from Noise IK to XX with version negotiation
Replace the 2-message IK handshake with a 3-message XX handshake for FMP link establishment. XX requires no prior knowledge of the peer's static key — both identities are revealed during the handshake (responder in msg2, initiator in msg3). This is the foundation for the forklift upgrade that enables rolling protocol upgrades. Changes: - Noise XX state machine alongside IK/XK (8 unit tests) - Protocol negotiation payload codec: format byte, packed version min/max, 64-bit feature bitfield, TLV extensions (11 unit tests) - FMP wire format version 0→1, msg3 header/builder, TCP stream framing - FMP handshake switched to XX: PeerConnection 3-message flow, handle_msg1 simplified (no identity), handle_msg2 sends msg3 and promotes initiator, new handle_msg3 promotes responder with restart/rekey/cross-connection detection - Rekey handshake switched to XX with negotiation payload hash chain fix (decrypt-and-discard in complete_rekey_msg2/msg3) - Negotiation payload in msg2/msg3 (FMP version [1,1], features=0) - Debug logging for handshake promotion paths - Integration test convergence timeouts adjusted for extra round-trip Squashed commits: - Add Noise XX state machine alongside IK/XK - Add protocol negotiation payload codec - FMP wire format prep: version 1, msg3 header support - Switch FMP handshake from Noise IK to XX - Increase convergence timeouts for XX 3-message handshake - Fix negotiation hash chain desync in rekey handshake
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
//! RX event loop and packet dispatch.
|
||||
|
||||
use crate::control::{commands, ControlSocket};
|
||||
use crate::control::queries;
|
||||
use crate::control::{ControlSocket, commands};
|
||||
use crate::node::wire::{
|
||||
COMMON_PREFIX_SIZE, CommonPrefix, FMP_VERSION, PHASE_ESTABLISHED, PHASE_MSG1, PHASE_MSG2,
|
||||
};
|
||||
use crate::node::{Node, NodeError};
|
||||
use crate::transport::ReceivedPacket;
|
||||
use crate::node::wire::{CommonPrefix, PHASE_ESTABLISHED, PHASE_MSG1, PHASE_MSG2, PHASE_MSG3, FMP_VERSION, COMMON_PREFIX_SIZE};
|
||||
use std::time::Duration;
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
@@ -18,6 +16,7 @@ impl Node {
|
||||
/// - Phase 0x0: Encrypted frame (session data)
|
||||
/// - Phase 0x1: Handshake message 1 (initiator -> responder)
|
||||
/// - Phase 0x2: Handshake message 2 (responder -> initiator)
|
||||
/// - Phase 0x3: Handshake message 3 (initiator -> responder, XX completion)
|
||||
///
|
||||
/// Also processes outbound IPv6 packets from the TUN reader for session
|
||||
/// encapsulation and routing through the mesh.
|
||||
@@ -31,7 +30,8 @@ impl Node {
|
||||
/// This method takes ownership of the packet_rx channel and runs
|
||||
/// until the channel is closed (typically when stop() is called).
|
||||
pub async fn run_rx_loop(&mut self) -> Result<(), NodeError> {
|
||||
let mut packet_rx = self.packet_rx.take().ok_or(NodeError::NotStarted)?;
|
||||
let mut packet_rx = self.packet_rx.take()
|
||||
.ok_or(NodeError::NotStarted)?;
|
||||
|
||||
// Take the TUN outbound receiver, or create a dummy channel that never
|
||||
// produces messages (when TUN is disabled). Holding the sender prevents
|
||||
@@ -54,12 +54,12 @@ impl Node {
|
||||
}
|
||||
};
|
||||
|
||||
let mut tick =
|
||||
tokio::time::interval(Duration::from_secs(self.config.node.tick_interval_secs));
|
||||
let mut tick = tokio::time::interval(Duration::from_secs(self.config.node.tick_interval_secs));
|
||||
|
||||
// Set up control socket channel
|
||||
let (control_tx, mut control_rx) =
|
||||
tokio::sync::mpsc::channel::<crate::control::ControlMessage>(32);
|
||||
let (control_tx, mut control_rx) = tokio::sync::mpsc::channel::<
|
||||
crate::control::ControlMessage,
|
||||
>(32);
|
||||
|
||||
if self.config.node.control.enabled {
|
||||
let config = self.config.node.control.clone();
|
||||
@@ -173,6 +173,9 @@ impl Node {
|
||||
PHASE_MSG2 => {
|
||||
self.handle_msg2(packet).await;
|
||||
}
|
||||
PHASE_MSG3 => {
|
||||
self.handle_msg3(packet).await;
|
||||
}
|
||||
_ => {
|
||||
debug!(
|
||||
phase = prefix.phase,
|
||||
|
||||
Reference in New Issue
Block a user