Add explicit counter to DataPacket for out-of-order decryption

Session-layer encryption used an implicit nonce counter with no counter
on the wire, requiring packets to arrive in exact order. Under bulk
transfer load (e.g., SCP), UDP packet loss or reordering permanently
desynchronized sender/receiver counters, causing all subsequent
decryption to fail with no recovery.

Add an 8-byte counter field to the DataPacket wire format and switch
from implicit-counter decrypt() to decrypt_with_replay_check() which
uses the explicit wire counter plus a 2048-packet sliding replay
window — the same pattern already used at the link layer.

Wire format: msg_type(1) + flags(1) + counter(8) + payload_len(2) = 12
bytes (was 4). FIPS_OVERHEAD updated 127 → 135 bytes accordingly.
This commit is contained in:
Origami74
2026-02-17 00:33:01 +00:00
committed by Johnathan Corgan
parent 3ca2f9500a
commit d3477a7c0f
4 changed files with 51 additions and 33 deletions
+2 -2
View File
@@ -194,7 +194,7 @@ async fn test_coord_cache_warming_data_packet_with_coords() {
let src_coords = TreeCoordinate::from_addrs(vec![src_addr, root_addr]).unwrap();
let dest_coords = TreeCoordinate::from_addrs(vec![dest_addr, root_addr]).unwrap();
let data = DataPacket::new(vec![1, 2, 3, 4])
let data = DataPacket::new(0, vec![1, 2, 3, 4])
.with_coords(src_coords.clone(), dest_coords.clone());
let data_payload = data.encode();
@@ -229,7 +229,7 @@ async fn test_coord_cache_warming_opaque_data_packet() {
let dest_addr = make_node_addr(0x02);
// DataPacket without COORDS_PRESENT — no coords to cache
let data = DataPacket::new(vec![1, 2, 3, 4]);
let data = DataPacket::new(0, vec![1, 2, 3, 4]);
let data_payload = data.encode();
let dg = SessionDatagram::new(src_addr, dest_addr, data_payload);