Skip to content

Commit e788510

Browse files
kuba-mooPaolo Abeni
authored andcommitted
psp: track generations of device key
There is a (somewhat theoretical in absence of multi-host support) possibility that another entity will rotate the key and we won't know. This may lead to accepting packets with matching SPI but which used different crypto keys than we expected. The PSP Architecture specification mentions that an implementation should track device key generation when device keys are managed by the NIC. Some PSP implementations may opt to include this key generation state in decryption metadata each time a device key is used to decrypt a packet. If that is the case, that key generation counter can also be used when policy checking a decrypted skb against a psp_assoc. This is an optional feature that is not explicitly part of the PSP spec, but can provide additional security in the case where an attacker may have the ability to force key rotations faster than rekeying can occur. Since we're tracking "key generations" more explicitly now, maintain different lists for associations from different generations. This way we can catch stale associations (the user space should listen to rotation notifications and change the keys). Drivers can "opt out" of generation tracking by setting the generation value to 0. Reviewed-by: Willem de Bruijn <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Daniel Zahka <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent e972692 commit e788510

File tree

5 files changed

+42
-1
lines changed

5 files changed

+42
-1
lines changed

include/net/psp/types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ struct psp_dev_config {
5050
* @lock: instance lock, protects all fields
5151
* @refcnt: reference count for the instance
5252
* @id: instance id
53+
* @generation: current generation of the device key
5354
* @config: current device configuration
5455
* @active_assocs: list of registered associations
56+
* @prev_assocs: associations which use old (but still usable)
57+
* device key
58+
* @stale_assocs: associations which use a rotated out key
5559
*
5660
* @rcu: RCU head for freeing the structure
5761
*/
@@ -67,13 +71,19 @@ struct psp_dev {
6771

6872
u32 id;
6973

74+
u8 generation;
75+
7076
struct psp_dev_config config;
7177

7278
struct list_head active_assocs;
79+
struct list_head prev_assocs;
80+
struct list_head stale_assocs;
7381

7482
struct rcu_head rcu;
7583
};
7684

85+
#define PSP_GEN_VALID_MASK 0x7f
86+
7787
/**
7888
* struct psp_dev_caps - PSP device capabilities
7989
*/

net/psp/psp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ int psp_sock_assoc_set_rx(struct sock *sk, struct psp_assoc *pas,
2727
int psp_sock_assoc_set_tx(struct sock *sk, struct psp_dev *psd,
2828
u32 version, struct psp_key_parsed *key,
2929
struct netlink_ext_ack *extack);
30+
void psp_assocs_key_rotated(struct psp_dev *psd);
3031

3132
static inline void psp_dev_get(struct psp_dev *psd)
3233
{

net/psp/psp_main.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ psp_dev_create(struct net_device *netdev,
7272

7373
mutex_init(&psd->lock);
7474
INIT_LIST_HEAD(&psd->active_assocs);
75+
INIT_LIST_HEAD(&psd->prev_assocs);
76+
INIT_LIST_HEAD(&psd->stale_assocs);
7577
refcount_set(&psd->refcnt, 1);
7678

7779
mutex_lock(&psp_devs_lock);
@@ -125,7 +127,9 @@ void psp_dev_unregister(struct psp_dev *psd)
125127
xa_store(&psp_devs, psd->id, NULL, GFP_KERNEL);
126128
mutex_unlock(&psp_devs_lock);
127129

128-
list_for_each_entry_safe(pas, next, &psd->active_assocs, assocs_list)
130+
list_splice_init(&psd->active_assocs, &psd->prev_assocs);
131+
list_splice_init(&psd->prev_assocs, &psd->stale_assocs);
132+
list_for_each_entry_safe(pas, next, &psd->stale_assocs, assocs_list)
129133
psp_dev_tx_key_del(psd, pas);
130134

131135
rcu_assign_pointer(psd->main_netdev->psp_dev, NULL);

net/psp/psp_nl.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ int psp_nl_key_rotate_doit(struct sk_buff *skb, struct genl_info *info)
230230
struct psp_dev *psd = info->user_ptr[0];
231231
struct genl_info ntf_info;
232232
struct sk_buff *ntf, *rsp;
233+
u8 prev_gen;
233234
int err;
234235

235236
rsp = psp_nl_reply_new(info);
@@ -249,10 +250,19 @@ int psp_nl_key_rotate_doit(struct sk_buff *skb, struct genl_info *info)
249250
goto err_free_ntf;
250251
}
251252

253+
/* suggest the next gen number, driver can override */
254+
prev_gen = psd->generation;
255+
psd->generation = (prev_gen + 1) & PSP_GEN_VALID_MASK;
256+
252257
err = psd->ops->key_rotate(psd, info->extack);
253258
if (err)
254259
goto err_free_ntf;
255260

261+
WARN_ON_ONCE((psd->generation && psd->generation == prev_gen) ||
262+
psd->generation & ~PSP_GEN_VALID_MASK);
263+
264+
psp_assocs_key_rotated(psd);
265+
256266
nlmsg_end(ntf, (struct nlmsghdr *)ntf->data);
257267
genlmsg_multicast_netns(&psp_nl_family, dev_net(psd->main_netdev), ntf,
258268
0, PSP_NLGRP_USE, GFP_KERNEL);

net/psp/psp_sock.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct psp_assoc *psp_assoc_create(struct psp_dev *psd)
6060

6161
pas->psd = psd;
6262
pas->dev_id = psd->id;
63+
pas->generation = psd->generation;
6364
psp_dev_get(psd);
6465
refcount_set(&pas->refcnt, 1);
6566

@@ -248,6 +249,21 @@ int psp_sock_assoc_set_tx(struct sock *sk, struct psp_dev *psd,
248249
return err;
249250
}
250251

252+
void psp_assocs_key_rotated(struct psp_dev *psd)
253+
{
254+
struct psp_assoc *pas, *next;
255+
256+
/* Mark the stale associations as invalid, they will no longer
257+
* be able to Rx any traffic.
258+
*/
259+
list_for_each_entry_safe(pas, next, &psd->prev_assocs, assocs_list)
260+
pas->generation |= ~PSP_GEN_VALID_MASK;
261+
list_splice_init(&psd->prev_assocs, &psd->stale_assocs);
262+
list_splice_init(&psd->active_assocs, &psd->prev_assocs);
263+
264+
/* TODO: we should inform the sockets that got shut down */
265+
}
266+
251267
void psp_twsk_init(struct inet_timewait_sock *tw, const struct sock *sk)
252268
{
253269
struct psp_assoc *pas = psp_sk_assoc(sk);

0 commit comments

Comments
 (0)