(just a few nits here) 2024-12-11, 22:15:13 +0100, Antonio Quartulli wrote: > +static inline struct ovpn_crypto_key_slot * > +ovpn_crypto_key_id_to_slot(const struct ovpn_crypto_state *cs, u8 key_id) > +{ > + struct ovpn_crypto_key_slot *ks; > + u8 idx; > + > + if (unlikely(!cs)) > + return NULL; > + > + rcu_read_lock(); > + idx = cs->primary_idx; > + ks = rcu_dereference(cs->slots[idx]); > + if (ks && ks->key_id == key_id) { > + if (unlikely(!ovpn_crypto_key_slot_hold(ks))) > + ks = NULL; > + goto out; > + } > + > + ks = rcu_dereference(cs->slots[idx ^ 1]); nit: for consistency with the other uses of the secondary slot, I'd switch that to cs->slots[!idx] [...] > +int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks, > + struct sk_buff *skb) > +{ [...] > + /* add packet op as head of additional data */ > + op = ovpn_opcode_compose(OVPN_DATA_V2, ks->key_id, peer->id); > + __skb_push(skb, OVPN_OPCODE_SIZE); > + BUILD_BUG_ON(sizeof(op) != OVPN_OPCODE_SIZE); > + *((__force __be32 *)skb->data) = htonl(op); > + > + /* AEAD Additional data */ > + sg_set_buf(sg, skb->data, OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE); You could add #define OVPN_AAD_SIZE (OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE) and then use it in a few places in ovpn_aead_encrypt and ovpn_aead_decrypt. [...] > +int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks, > + struct sk_buff *skb) > +{ > + const unsigned int tag_size = crypto_aead_authsize(ks->decrypt); > + int ret, payload_len, nfrags; > + unsigned int payload_offset; > + struct aead_request *req; > + struct sk_buff *trailer; > + struct scatterlist *sg; > + u8 iv[OVPN_NONCE_SIZE]; > + unsigned int sg_len; > + > + payload_offset = OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE + tag_size; OVPN_AAD_SIZE + tag_size [...] > + sg_init_table(sg, nfrags + 2); > + > + /* packet op is head of additional data */ > + sg_len = OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE; This variable can probably be dropped if you add OVPN_AAD_SIZE. [...] > + /* setup async crypto operation */ > + aead_request_set_tfm(req, ks->decrypt); > + aead_request_set_callback(req, 0, ovpn_decrypt_post, skb); > + aead_request_set_crypt(req, sg, sg, payload_len + tag_size, iv); > + > + aead_request_set_ad(req, OVPN_NONCE_WIRE_SIZE + OVPN_OPCODE_SIZE); and this op is flipped but it's still OVPN_AAD_SIZE. > + > + /* decrypt it */ > + return crypto_aead_decrypt(req); > +free_sg: > + kfree(ovpn_skb_cb(skb)->sg); > + ovpn_skb_cb(skb)->sg = NULL; > + return ret; > +} > + [...] > @@ -80,7 +83,10 @@ static void ovpn_peer_release_rcu(struct rcu_head *head) > */ > static void ovpn_peer_release(struct ovpn_peer *peer) > { > + ovpn_crypto_state_release(&peer->crypto); > + spin_lock_bh(&peer->lock); > ovpn_bind_reset(peer, NULL); At this point in the series, ovpn_bind_reset also tries to take peer->lock (gets fixed in the "peer floating" patch). (but if you're tired of moving chunks around, I can live with it) > + spin_unlock_bh(&peer->lock); > netdev_put(peer->ovpn->dev, &peer->ovpn->dev_tracker); > call_rcu(&peer->rcu, ovpn_peer_release_rcu); > } -- Sabrina