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 */
17 struct 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) */
25 struct 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 */
33 struct ovpn_peer_key_reset {
34 enum ovpn_key_slot slot;
35 struct ovpn_key_config key;
36 };
37
38 struct 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
52 struct 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
ovpn_crypto_key_slot_hold(struct ovpn_crypto_key_slot * ks)60 static inline bool ovpn_crypto_key_slot_hold(struct ovpn_crypto_key_slot *ks)
61 {
62 return kref_get_unless_zero(&ks->refcount);
63 }
64
ovpn_crypto_state_init(struct ovpn_crypto_state * cs)65 static 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
73 static inline struct ovpn_crypto_key_slot *
ovpn_crypto_key_id_to_slot(const struct ovpn_crypto_state * cs,u8 key_id)74 ovpn_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;
102 out:
103 rcu_read_unlock();
104
105 return ks;
106 }
107
108 static inline struct ovpn_crypto_key_slot *
ovpn_crypto_key_slot_primary(const struct ovpn_crypto_state * cs)109 ovpn_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
122 void ovpn_crypto_key_slot_release(struct kref *kref);
123
ovpn_crypto_key_slot_put(struct ovpn_crypto_key_slot * ks)124 static 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
129 int ovpn_crypto_state_reset(struct ovpn_crypto_state *cs,
130 const struct ovpn_peer_key_reset *pkr);
131
132 void ovpn_crypto_key_slot_delete(struct ovpn_crypto_state *cs,
133 enum ovpn_key_slot slot);
134
135 void ovpn_crypto_state_release(struct ovpn_crypto_state *cs);
136
137 void ovpn_crypto_key_slots_swap(struct ovpn_crypto_state *cs);
138
139 int ovpn_crypto_config_get(struct ovpn_crypto_state *cs,
140 enum ovpn_key_slot slot,
141 struct ovpn_key_config *keyconf);
142
143 bool ovpn_crypto_kill_key(struct ovpn_crypto_state *cs, u8 key_id);
144
145 #endif /* _NET_OVPN_OVPNCRYPTO_H_ */
146