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