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