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 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 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 * 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 * 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 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