diff --git a/client/internal/peer/conn.go b/client/internal/peer/conn.go index 7c6ba1215..41ccd60d0 100644 --- a/client/internal/peer/conn.go +++ b/client/internal/peer/conn.go @@ -93,6 +93,11 @@ type PQHandshaker interface { // SetRemotePort registers the peer's data-path endpoint from signalling: the peer's // WG overlay IP combined with its advertised pq UDP port. SetRemotePort(remoteKey string, overlayIP netip.Addr, port int) + // OnDataPathRekeyed signals a fresh WireGuard handshake for the peer; it clocks the + // next chained PSK rotation pushed over the data path. + OnDataPathRekeyed(remoteKey string) + // OnDataPathDown signals the peer's tunnel went down. + OnDataPathDown(remoteKey string) } // ConnConfig is a peer Connection configuration @@ -705,6 +710,10 @@ func (conn *Conn) onWGDisconnected(watcherCtx context.Context) { conn.Log.Warnf("WireGuard handshake timeout detected, closing current connection") + if conn.config.PQ != nil { + conn.config.PQ.OnDataPathDown(conn.config.Key) + } + // Close the active connection based on current priority switch conn.currentConnPriority { case conntype.Relay: @@ -970,6 +979,11 @@ func (conn *Conn) onWGCheckSuccess() { conn.mu.Lock() conn.wgTimeouts = 0 conn.mu.Unlock() + + // A fresh WireGuard handshake is the clock for the post-quantum PSK rotation. + if conn.config.PQ != nil { + conn.config.PQ.OnDataPathRekeyed(conn.config.Key) + } } // recordConnectionMetrics records connection stage timestamps as metrics diff --git a/client/internal/pqkem_adapter.go b/client/internal/pqkem_adapter.go index 4de9a0ab1..17d810d49 100644 --- a/client/internal/pqkem_adapter.go +++ b/client/internal/pqkem_adapter.go @@ -90,3 +90,13 @@ func (p pqHandshaker) SetRemotePort(remoteKey string, overlayIP netip.Addr, port } p.mgr.AddPeer(pqkem.RemoteID(remoteKey), netip.AddrPortFrom(overlayIP, uint16(port))) } + +// OnDataPathRekeyed clocks the next chained PSK rotation on a fresh WG handshake. +func (p pqHandshaker) OnDataPathRekeyed(remoteKey string) { + p.mgr.OnDataPathRekeyed(pqkem.RemoteID(remoteKey)) +} + +// OnDataPathDown signals the peer's tunnel went down. +func (p pqHandshaker) OnDataPathDown(remoteKey string) { + p.mgr.OnDataPathDown(pqkem.RemoteID(remoteKey)) +}