OnNewPSKReady could be applied out of order: two exchanges for a peer can derive
concurrently (one over signal, one over the data path), and the callbacks run
outside the manager lock, so an older exchange's apply could land after a newer
one and restore a stale WireGuard PSK, splitting the tunnel.
Give each exchange a per-peer monotonic generation, assigned under the lock at
creation so a later exchange always carries a higher one, and pass it to
OnNewPSKReady. The host adapter records the newest generation applied per peer
and drops any callback that is not newer, with the check-and-record atomic so the
slow SetPresharedKey call stays off that lock.
Found in cubic review on #7098 (client/internal/pqkem/callbacks.go:12).
The OnRekeyFailed contract told the host to tear the peer connection down, but
the shipped adapter re-bootstraps over signalling and keeps the previous PSK.
State that recovery is host-defined so another implementation does not perform an
unnecessary teardown.
Found in cubic review on #7098 (client/internal/pqkem/callbacks.go:15).
OnNewPSKReady's doc claimed the responder fires it "on receiving the confirm",
but there is no confirm round: the responder fires it right after deriving the
PSK from the offer and before sending the answer. Say so, so a host does not
assume the peer has already confirmed the key.
Found in cubic review on #7098 (client/internal/pqkem/callbacks.go:11).
To ensure two peers agree on a key, we need asymmetry. one peer is
the controller ("initiator") the other is the "responder".
Otherwise imagine two offers in parallel driving two answers at the same time
A B
| <----B-OFFER----- |
| -----A-OFFER----> |
| |
| |
---------------------------------
|****** ICE + WG Handshake ****** |
---------------------------------
| |
| <----B-ANSWER---- |
| -----A-ANSWER---> |
PSK is derived on receive of offer, so A and B derive different PSKs.
When WG handshake takes place it picks misaligned PSKs.
So we impair the two nodes and only the offer of one of the two (the controller/initiator)
carries the KEM material.
This means that if the responder OFFER/ANSWER comes first, when the controller/initiator's one
completes (and the genuine PSK is shared between A and B, we need to force a new WG handshake with
the proper keys.