File Index
Files and directories
Sign in
FILE

crypto.h

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ovpn/crypto.h C
  1/* SPDX-License-Identifier: GPL-2.0-only */
  2/*  OpenVPN data channel offload
  3 *
  4 *  Copyright (C) 2020-2025 OpenVPN, Inc.
  5 *
  6 *  Author:	James Yonan <james@openvpn.net>
  7 *		Antonio Quartulli <antonio@openvpn.net>
  8 */
  9
 10#ifndef _NET_OVPN_OVPNCRYPTO_H_
 11#define _NET_OVPN_OVPNCRYPTO_H_
 12
 13#include "pktid.h"
 14#include "proto.h"
 15
 16/* info needed for both encrypt and decrypt directions */
 17struct ovpn_key_direction {
 18	const u8 *cipher_key;
 19	size_t cipher_key_size;
 20	const u8 *nonce_tail; /* only needed for GCM modes */
 21	size_t nonce_tail_size; /* only needed for GCM modes */
 22};
 23
 24/* all info for a particular symmetric key (primary or secondary) */
 25struct ovpn_key_config {
 26	enum ovpn_cipher_alg cipher_alg;
 27	u8 key_id;
 28	struct ovpn_key_direction encrypt;
 29	struct ovpn_key_direction decrypt;
 30};
 31
 32/* used to pass settings from netlink to the crypto engine */
 33struct ovpn_peer_key_reset {
 34	enum ovpn_key_slot slot;
 35	struct ovpn_key_config key;
 36};
 37
 38struct ovpn_crypto_key_slot {
 39	u8 key_id;
 40
 41	struct crypto_aead *encrypt;
 42	struct crypto_aead *decrypt;
 43	u8 nonce_tail_xmit[OVPN_NONCE_TAIL_SIZE];
 44	u8 nonce_tail_recv[OVPN_NONCE_TAIL_SIZE];
 45
 46	struct ovpn_pktid_recv pid_recv ____cacheline_aligned_in_smp;
 47	struct ovpn_pktid_xmit pid_xmit ____cacheline_aligned_in_smp;
 48	struct kref refcount;
 49	struct rcu_head rcu;
 50};
 51
 52struct ovpn_crypto_state {
 53	struct ovpn_crypto_key_slot __rcu *slots[2];
 54	u8 primary_idx;
 55
 56	/* protects primary and secondary slots */
 57	spinlock_t lock;
 58};
 59
 60static inline bool ovpn_crypto_key_slot_hold(struct ovpn_crypto_key_slot *ks)
 61{
 62	return kref_get_unless_zero(&ks->refcount);
 63}
 64
 65static inline void ovpn_crypto_state_init(struct ovpn_crypto_state *cs)
 66{
 67	RCU_INIT_POINTER(cs->slots[0], NULL);
 68	RCU_INIT_POINTER(cs->slots[1], NULL);
 69	cs->primary_idx = 0;
 70	spin_lock_init(&cs->lock);
 71}
 72
 73static inline struct ovpn_crypto_key_slot *
 74ovpn_crypto_key_id_to_slot(const struct ovpn_crypto_state *cs, u8 key_id)
 75{
 76	struct ovpn_crypto_key_slot *ks;
 77	u8 idx;
 78
 79	if (unlikely(!cs))
 80		return NULL;
 81
 82	rcu_read_lock();
 83	idx = READ_ONCE(cs->primary_idx);
 84	ks = rcu_dereference(cs->slots[idx]);
 85	if (ks && ks->key_id == key_id) {
 86		if (unlikely(!ovpn_crypto_key_slot_hold(ks)))
 87			ks = NULL;
 88		goto out;
 89	}
 90
 91	ks = rcu_dereference(cs->slots[!idx]);
 92	if (ks && ks->key_id == key_id) {
 93		if (unlikely(!ovpn_crypto_key_slot_hold(ks)))
 94			ks = NULL;
 95		goto out;
 96	}
 97
 98	/* when both key slots are occupied but no matching key ID is found, ks
 99	 * has to be reset to NULL to avoid carrying a stale pointer
100	 */
101	ks = NULL;
102out:
103	rcu_read_unlock();
104
105	return ks;
106}
107
108static inline struct ovpn_crypto_key_slot *
109ovpn_crypto_key_slot_primary(const struct ovpn_crypto_state *cs)
110{
111	struct ovpn_crypto_key_slot *ks;
112
113	rcu_read_lock();
114	ks = rcu_dereference(cs->slots[cs->primary_idx]);
115	if (unlikely(ks && !ovpn_crypto_key_slot_hold(ks)))
116		ks = NULL;
117	rcu_read_unlock();
118
119	return ks;
120}
121
122void ovpn_crypto_key_slot_release(struct kref *kref);
123
124static inline void ovpn_crypto_key_slot_put(struct ovpn_crypto_key_slot *ks)
125{
126	kref_put(&ks->refcount, ovpn_crypto_key_slot_release);
127}
128
129int ovpn_crypto_state_reset(struct ovpn_crypto_state *cs,
130			    const struct ovpn_peer_key_reset *pkr);
131
132void ovpn_crypto_key_slot_delete(struct ovpn_crypto_state *cs,
133				 enum ovpn_key_slot slot);
134
135void ovpn_crypto_state_release(struct ovpn_crypto_state *cs);
136
137void ovpn_crypto_key_slots_swap(struct ovpn_crypto_state *cs);
138
139int ovpn_crypto_config_get(struct ovpn_crypto_state *cs,
140			   enum ovpn_key_slot slot,
141			   struct ovpn_key_config *keyconf);
142
143bool ovpn_crypto_kill_key(struct ovpn_crypto_state *cs, u8 key_id);
144
145#endif /* _NET_OVPN_OVPNCRYPTO_H_ */
~/ Read-only file preview.