mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Make FSP session rekey hitless under packet loss and reordering
An FSP session rekey could leave the two endpoints holding different key sets for a brief window: if a handshake message was lost in transit, one side rotated to the new keys while the other did not. Traffic sealed in one key epoch then reached a peer still on the other epoch and failed to decrypt, producing bursts of AEAD decryption failures and dropped connectivity until a later rekey cycle reconverged the pair. Choreographing the cutover order cannot close this window: any fixed ordering still leaves a skew that packet reordering widens. Make rekey correctness independent of cutover timing by overlapping the key epochs on the receive path. During a rekey transition the receiver trial-decrypts each frame against every live session it holds: current, the not-yet-promoted pending session, and the draining previous session. The K-bit becomes a hint that orders the trial-decrypt cascade rather than a hard gate, and a frame that authenticates against the pending session is itself the cutover signal. No rotation ordering and no packet reordering can then cause a decryption failure. The pre-rekey Noise session is held in the `previous` slot until the peer has demonstrably moved off it. Its drain deadline is anchored on the most recent frame the peer authenticated against that slot, refreshed each time the trial-decrypt cascade lands there, rather than on a fixed wall-clock timer started unilaterally at the local cutover. A peer that never received the new keys keeps authenticating against `previous` and the slot stays live; without this, a fixed timer would erase the only key set that could decrypt the peer's frames, producing a permanent silent decrypt failure on a live data path. A peer that never catches up is handled by the existing FSP session liveness path rather than by silent decrypt failure. The lost-handshake liveness gap is closed separately by retransmitting the third rekey handshake message until the peer is confirmed on the new keys, with a bounded retry budget after which the rekey cycle is cleanly abandoned and retried on the next timer. Adds unit tests covering the trial-decrypt cascade (epoch selection, promotion on pending decrypt, reordered old-epoch stragglers after cutover, per-slot replay-window integrity), the msg3 retransmission lifecycle, and the peer-progress-aware drain retirement.
This commit is contained in:
@@ -416,17 +416,23 @@ FAILED=0
|
||||
|
||||
# FSP session rekey trails link-layer rekey in practice. Wait boundedly for
|
||||
# at least one initiator and responder cutover before the final assertions.
|
||||
wait_for_log_pattern_count "FSP rekey cutover complete" 1 "$FIRST_REKEY_TIMEOUT" || true
|
||||
wait_for_log_pattern_count "Peer FSP K-bit flip detected" 1 "$REKEY_SETTLE" || true
|
||||
#
|
||||
# The responder-side cutover is driven by the overlapping-epoch
|
||||
# trial-decrypt cascade: a frame that authenticates against the pending
|
||||
# session is itself the cutover signal, logged as "Peer FSP new-epoch
|
||||
# frame authenticated". The header K-bit is only an ordering hint now,
|
||||
# so there is no longer a standalone "K-bit flip detected" event.
|
||||
wait_for_log_pattern_count "FSP rekey cutover complete (initiator)" 1 "$FIRST_REKEY_TIMEOUT" || true
|
||||
wait_for_log_pattern_count "Peer FSP new-epoch frame authenticated" 1 "$REKEY_SETTLE" || true
|
||||
|
||||
# Positive checks: rekey machinery worked
|
||||
assert_min_count "Rekey cutover complete (initiator), K-bit flipped" 4 \
|
||||
"FMP rekey initiator cutovers (>= 2 cycles)"
|
||||
|
||||
# FSP rekey checks (sessions between non-adjacent nodes)
|
||||
assert_min_count "FSP rekey cutover complete" 1 \
|
||||
assert_min_count "FSP rekey cutover complete (initiator)" 1 \
|
||||
"FSP session rekey initiator cutovers"
|
||||
assert_min_count "Peer FSP K-bit flip detected" 1 \
|
||||
assert_min_count "Peer FSP new-epoch frame authenticated" 1 \
|
||||
"FSP session rekey responder cutovers"
|
||||
|
||||
# Negative checks: no bad things happened
|
||||
|
||||
Reference in New Issue
Block a user