mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-12 09:33:23 +00:00
The rekey marker's cross-connection arm declined to swap while a rekey of ours was in flight, reasoning that the swap rewrites the session and both indices while touching no rekey state, so it would orphan that rekey. The reasoning was one-sided and the arm was wrong: this is half of a two-sided tie-break whose other half reads only whether a peer exists and the address ordering, and cannot see our rekey. Declining here while the peer's outbound half swaps anyway leaves the two ends on four distinct indices with neither holding a pending session, dead both directions until the link-dead timer. Measured against the pre-marker tree, which converges: it holds the crossing dial as pending and adopts it at cutover. The orphaned-rekey hazard is real but belongs to the executor. The swap now abandons the rekey it displaces and frees that index first, exactly as the rekey-responder path already does when it loses the dual-rekey tie-break, so the classifier can take the arm unconditionally. Two further failure paths of the marker are tightened. A malformed marker tore the handshake down without freeing the index msg1 allocated, and that arm sits ahead of the ACL gate, so any peer able to complete a msg3 could grow the allocator set one entry at a time. A rekey with no session index to declare silently omitted the marker, which puts a real rekey back on the cross-connection path; it is unreachable today and is now asserted rather than skipped. On the test side, the marker's wire contract gains coverage: the accessor round-trips, an unknown TLV field leaves it alone in both directions, and a well-formed marker of the wrong length is an error rather than an absence, which is the case the container codec cannot see and the whole reason the accessor is fallible. Two node-level tests now assert both ends rather than one. A rekey fired by message count on a zero-age session is the mechanism behind the datagram drops, and nothing exercised it: it fails on the pre-marker tree and passes here. The mutual-dial test gains an index-pair assertion, since every per-end predicate it checked holds when the ends have diverged. One existing test had stopped reaching its own arm. Driving a bare second handshake into a rekey-disabled peer now lands on the cross-connection arm, which that flag does not gate, and every assertion held there too; it is retargeted onto a declared rekey, which is the real route to the duplicate arm, and asserts the session is left alone so the two arms are told apart. Documentation that described the removed session-age floor is rewritten around the declaration.