From b10fc220f3a286b7687da5c95a9f4381f1292455 Mon Sep 17 00:00:00 2001 From: riccardom Date: Mon, 19 Oct 2026 16:38:56 +0200 Subject: [PATCH] [client] pqkem: route PSK commits and data-path sends through helpers Preparation for authenticating data-path messages (security review of #7098, finding F-003). The authentication needs the existing PSK while a new one is being derived, to produce a MAC attached to the offers and their answers that proves they are authentic. So committing a new PSK must keep the previous one, and a reply must be sealed with the PSK that verified the offer rather than the one just committed. Today both operations are inlined at their call sites. Pure refactor, no behaviour change: the two PSK commit sites call commitPSKLocked, and pushDataPath delegates the endpoint lookup and send to sendDataPath. --- client/internal/pqkem/convergence.go | 4 ++-- client/internal/pqkem/manager.go | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/client/internal/pqkem/convergence.go b/client/internal/pqkem/convergence.go index 76a061bee..f30695426 100644 --- a/client/internal/pqkem/convergence.go +++ b/client/internal/pqkem/convergence.go @@ -160,7 +160,7 @@ func (m *Manager) processOffer(remoteID RemoteID, o *OfferMsg, via string) ([]by ex.state = stateAwaitingAck ex.lastSent = raw gen := ex.gen - m.psks[remoteID] = psk + m.commitPSKLocked(remoteID, psk) m.capable[remoteID] = true // a real KEM offer proves the peer runs the exchange m.mu.Unlock() @@ -255,7 +255,7 @@ func (m *Manager) processAnswer(remoteID RemoteID, a *AnswerMsg, via string) err cur.state = stateAwaitingRekey m.established[remoteID] = true m.failures[remoteID] = 0 - m.psks[remoteID] = psk + m.commitPSKLocked(remoteID, psk) m.capable[remoteID] = true // a real KEM answer proves the peer runs the exchange m.mu.Unlock() diff --git a/client/internal/pqkem/manager.go b/client/internal/pqkem/manager.go index 958b04748..a779d0443 100644 --- a/client/internal/pqkem/manager.go +++ b/client/internal/pqkem/manager.go @@ -567,9 +567,20 @@ func (m *Manager) OnDataPathDown(remoteID RemoteID) {} // ---- internals ---- -// pushDataPath resolves the peer's endpoint and sends over the data-path transport, -// erroring if the peer is unknown or no transport is set. +// commitPSKLocked records a freshly derived PSK as the peer's current one. Assumes m.mu +// is held. +func (m *Manager) commitPSKLocked(remoteID RemoteID, psk PSK) { + m.psks[remoteID] = psk +} + +// pushDataPath sends a message to the peer over the data-path transport. func (m *Manager) pushDataPath(remoteID RemoteID, msg []byte) error { + return m.sendDataPath(remoteID, msg) +} + +// sendDataPath resolves the peer's endpoint and sends over the data-path transport, +// erroring if the peer is unknown or no transport is set. +func (m *Manager) sendDataPath(remoteID RemoteID, msg []byte) error { m.mu.Lock() ep, ok := m.peerAddrs[remoteID] t := m.transport