fix(rekey): complete relay-path session rekey (#91) #92
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
femboy/yip!92
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/rekey-9a-relay-completion"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #91. Stacked on #90 (base =
feat/rekey-9a-session-rotation) — review #90 first.What this does
9a rotates each peer's Noise-IK session ~120s for forward secrecy, but relay-reached peers were gated out of rekey scheduling (
drive_rekey_schedulereturned early onrelay): rekey completion was only wired into the direct handshake handlers, so scheduling a relay rekey would have churned a never-completing ~1 Hz handshake (a DPI fingerprint). #91 wires relay-path completion, removes the gate, and proves it on the wire — so relay-only sessions now get forward-secrecy rotation too.The security-critical idempotent logic is single-sourced, not duplicated: relay paths reorder more than direct, which makes 9a's ephemeral-keyed convergence fix more load-bearing there, and a copy would be free to drift from it.
Changes
c388cb4,b459dde) —rekey_init_core/rekey_resp_core(.., via_relay: bool)+push_rekey_egress;handle_rekey_init/handle_rekey_respbecome thinvia_relay=falsewrappers. The direct path is byte-identical.push_rekey_egresstakes the fullEgressDatagramso the prime-emit preserves each packet's FECfate(review fix — a collapsedfatewould defeat GSO coalescing).e60b7ba) —relayed_handshake_init's Established arm andrelayed_handshake_resproute to the cores withvia_relay=true. The cold-startcached_resp_init_ephdedup is preserved, so a cold-start Init retransmit still resends the cached Resp instead of being misread as a rekey.2fbe21e) — relay peers now schedule rekeys, emitting the Init viarelay_wrap. Arelay_wrapNoneskips that send only; the round stays in flight and retries.b163430) —run-netns-rekey-relay.sh: three namespaces with no direct A↔B path, so traffic must traverse the blind relay.rekey_epoch_witnessgained an opt-inYIP_WITNESS_UNWRAP_RELAY=1mode that strips theRelaySend/RelayDeliverenvelope before counting distinct on-wire ephemerals (env-gated, so the 9a direct test is unaffected). Wired into CI, both drivers.004c138) — see below.Defect caught by the final review
Removing 9a's gate silently dropped an invariant it had been providing: relay and direct rekey completion were implicitly mutually exclusive. Without that, a direct peer completing a rekey via a relayed Init/Resp built the new epoch with
peer_addr = server_addr()whilepeers[idx].relaystayedfalse— andon_tundecides relay-wrapping frompeers[idx].relay, not the stamped address. Result: bare datagrams to the relay placeholder, dropped by the server, outbound black-holed for a full rekey interval. Reachable via a source-spoofed server address or a malicious relay, and with no attacker at all under asymmetric reachability (peer relays to us while we reach it directly).Fixed by gating completion on
peers[idx].relayat all four sites (fail-closedDispatchOut::Noneon mismatch). Therelayflag only flips on aHandshaking → Establishedtransition, never mid-session, so this cannot block a legitimate same-path rekey. Regression testdirect_peer_ignores_relayed_rekey_respwas confirmed failing before the fix.Verification
clippy -D warnings,cargo fmt— clean. Full workspace: 0 failures.relay-forwarded= 3147/3151 (the blind relay carried it),COMPLETED_ROUNDS= 10/10 distinct rekey rounds observed on the relayed wire.Known deferred
[HandshakeResp]can abandon an in-flight rekey — rekey-liveness only (currentuntouched, session survives, rotation delayed). Rides with #34 (authenticated endpoint).No wire-format change;
yip-crypto/yip-wire/handshake.rsuntouched apart from reusing the read-onlyhandshake::init_ephemeralhelper.