[PATCH net-next v2 2/7] psp: support tx rekey operation
flat view
COOLING4d
From: Daniel Zahka <daniel.zahka@gmail.com>
Date: 2026-10-09 20:47:01
Also in:
linux-doc, linux-kselftest, lkml
Subsystem:
documentation, networking [general], psp security protocol, the rest · Maintainers:
Jonathan Corbet, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Daniel Zahka, Willem de Bruijn, Linus Torvalds
Revision v2 of 2 in this series.
Revisions (2)
- v1 [diff vs current]
- v2 current
The tx rekey operation creates a new psp_assoc with the same rx state, but with new tx state. The new association is spliced into the socket with RCU to be used immediately in the tx path. Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com> --- v2: - place new assoc on pas->assocs list instead of psd->active assocs list - reject tx rekey on SADB devices until deferred tx key deletion lands --- Documentation/networking/psp.rst | 26 +++++++++++++++++-- net/psp/psp_sock.c | 56 +++++++++++++++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 8 deletions(-)
diff --git a/Documentation/networking/psp.rst b/Documentation/networking/psp.rst
index 0f9b6b73f244..5c4e4215d906 100644
--- a/Documentation/networking/psp.rst
+++ b/Documentation/networking/psp.rst@@ -140,14 +140,36 @@ The PSP assoc state of a socket is not reset when the connection is torn down. ``connect()`` on a socket that has PSP assoc state will return ``-EINVAL``. +Rekeying +-------- + +A connection which has completed the exchange described above and is +in the "PSP Full" state can be rekeyed in place without being torn +down. The Tx and Rx directions are rekeyed separately using the same +netlink calls as in connection setup. + +``rx-assoc`` allocates a new Rx key and SPI, which should be passed +to the peer exactly as during the initial exchange. The SPI which was +in use before the rekey remains acceptable on the socket until the +next Rx rekey, so packets the peer sent before it learned the new SPI +are still received. + +``tx-assoc`` installs a new Tx key, which takes effect immediately. +The peer will accept data encrypted from the old and new SPI. + +A rekey is rejected with ``-EINVAL`` if it would change the PSP device +or the PSP version of the association. It is rejected with ``-EBUSY`` +if the socket has not completed its initial exchange in both +directions. + Rotation notifications ---------------------- The rotations of device key happen asynchronously and are usually performed by management daemons, not under application control. The PSP netlink family will generate a notification whenever keys -are rotated. The applications are expected to re-establish connections -before keys are rotated again. +are rotated. Applications are expected to rekey their connections, +as described above, before device keys are rotated again. Kernel implementation =====================
diff --git a/net/psp/psp_sock.c b/net/psp/psp_sock.c
index b5887171c84e..060149f3d72a 100644
--- a/net/psp/psp_sock.c
+++ b/net/psp/psp_sock.c@@ -283,6 +283,52 @@ psp_sock_set_tx_key(struct sock *sk, struct psp_dev *psd, struct psp_assoc *pas, return err; } +static int +psp_sock_tx_rekey(struct sock *sk, struct psp_dev *psd, struct psp_assoc *pas, + struct psp_key_parsed *key, struct netlink_ext_ack *extack) +{ + struct psp_assoc *new; + int err; + + if (psp_dev_has_sadb(psd)) { + NL_SET_ERR_MSG(extack, "Tx rekey not supported on this device"); + return -EOPNOTSUPP; + } + if (!pas->peer_tx) { + NL_SET_ERR_MSG(extack, "Socket PSP state is not fully established"); + return -EBUSY; + } + + new = kzalloc_flex(*new, drv_data, psd->caps->assoc_drv_spc, + GFP_KERNEL_ACCOUNT); + if (!new) + return -ENOMEM; + + new->psd = pas->psd; + new->dev_id = pas->dev_id; + new->generation = pas->generation; + new->version = pas->version; + new->peer_tx = 1; + new->prev_spi = pas->prev_spi; + new->prev_generation = pas->prev_generation; + refcount_set(&new->refcnt, 1); + memcpy(&new->rx, &pas->rx, sizeof(new->rx)); + + err = psp_assoc_set_tx(psd, new, key, extack); + if (err) { + kfree(new); + return err; + } + + psp_dev_get(new->psd); + list_add(&new->assocs_list, &pas->assocs_list); + + rcu_assign_pointer(sk->psp_assoc, new); + psp_assoc_put(pas); + + return 0; +} + int psp_sock_assoc_set_tx(struct sock *sk, struct psp_dev *psd, u32 version, struct psp_key_parsed *key, struct netlink_ext_ack *extack)
@@ -315,13 +361,11 @@ int psp_sock_assoc_set_tx(struct sock *sk, struct psp_dev *psd, err = -EINVAL; goto exit_unlock; } - if (pas->tx.spi) { - NL_SET_ERR_MSG(extack, "Tx key already set"); - err = -EBUSY; - goto exit_unlock; - } + if (pas->tx.spi) + err = psp_sock_tx_rekey(sk, psd, pas, key, extack); + else + err = psp_sock_set_tx_key(sk, psd, pas, key, extack); - err = psp_sock_set_tx_key(sk, psd, pas, key, extack); exit_unlock: release_sock(sk); return err;
--
2.52.0