mirror of
https://github.com/jmcorgan/fips.git
synced 2026-10-05 19:18:25 +00:00
A msg1 from an address whose entry named a pending inbound handshake was treated as a duplicate and answered with that handshake's stored msg2, whatever the msg1 said. XX msg2 is bound to the initiator's ephemeral key from msg1, so a msg2 made for another msg1 cannot be read by the sender. A handshake left pending at a peer's address by a replayed msg1, or by the peer's own abandoned attempt, therefore answered every genuine msg1 from that peer (a rekey, or a fresh dial after a restart) with a msg2 it could not read, until the stale handshake was reaped at the handshake timeout. Each inbound handshake now records the msg1 it answered, in the carrier slot an outbound handshake uses for its own msg1 (no msg1 resend path runs on an inbound handshake). A byte-identical msg1, which is what an initiator's resend sends, is still answered from the stored msg2. A different msg1 gets its own handshake, and the pending one is left for its msg3 or its reap: replacing it instead would let anyone able to send from the address discard a genuine handshake in the window between msg2 and msg3. When a handshake that another at the same address displaced is removed first, the newer one inherits the link it displaced, so the address entry still returns to a live peer link when the newer one goes. The cost is a new handshake per distinct msg1 where there was one per address. A sender spoofing an established peer's address is admitted even with inbound connections off and is metered on the established-link msg1 bucket; before, it held one handshake per spoofed address until the reap and further msg1s were answered from the stored msg2 at no crypto cost. Now each distinct msg1 costs the msg2 crypto, a session index, a link and a handshake machine, held until the handshake timeout, bounded by that bucket's burst and rate: at defaults (128 burst, 6.4 per second, 30 s timeout) about 320 handshakes at once, the same order as the stranger bucket already admits from arbitrary addresses. Tests send two distinct msg1s from one identity and check the second gets a msg2 it can read and completes, and check a stale handshake at a peer's address no longer blocks the peer's rekey, including the address entry once the stale handshake is reaped mid-rekey. Both fail without the fix; the existing duplicate-msg1 resend test is unchanged. No wire format change.