[RFC ovpn net-next 01/14] ovpn: prepare packet ID state for usage limits

Ralf Lici <[email protected]>
Newsgroups gmane.network.openvpn.devel
Message-ID <6c66a38af8ea53e4fbc587f087c594573fd8ee6a.1782919654.git.ralf@mandelbit.com>
OpenVPN needs packet-ID and cipher usage thresholds to decide when a
data-channel key should be renewed or stopped. The existing transmit
packet-ID helper only returns the next ID and has no way to request a
threshold notification.

Teach the transmit packet-ID helper to return 1 when the fixed OpenVPN
packet-ID soft threshold is crossed. The counter is monotonic, so the
exact crossing is naturally reported only once. The hard packet-ID wrap
check still stops TX; this only gives userspace a chance to rekey while
packet-ID space is still available.

Signed-off-by: Ralf Lici <[email protected]>
---
 drivers/net/ovpn/crypto_aead.c |  3 +++
 drivers/net/ovpn/netlink.c     |  4 ++--
 drivers/net/ovpn/pktid.h       | 31 +++++++++++++++++++++++++------
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ovpn/crypto_aead.c b/drivers/net/ovpn/crypto_aead.c
index 8f07c418622b..86b69aeddcf7 100644
--- a/drivers/net/ovpn/crypto_aead.c
+++ b/drivers/net/ovpn/crypto_aead.c
@@ -19,6 +19,7 @@
 #include "pktid.h"
 #include "crypto_aead.h"
 #include "crypto.h"
+#include "netlink.h"
 #include "peer.h"
 #include "proto.h"
 #include "skb.h"
@@ -207,6 +208,8 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	ret = ovpn_pktid_xmit_next(&ks->pid_xmit, &pktid);
 	if (unlikely(ret < 0))
 		return ret;
+	if (unlikely(ret > 0))
+		ovpn_nl_key_swap_notify(peer, ks->key_id);
 
 	/* concat 4 bytes packet id and 8 bytes nonce tail into 12 bytes
 	 * nonce
diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c
index 4c66c1ec497e..83d81a468b5a 100644
--- a/drivers/net/ovpn/netlink.c
+++ b/drivers/net/ovpn/netlink.c
@@ -1312,8 +1312,8 @@ int ovpn_nl_key_swap_notify(struct ovpn_peer *peer, u8 key_id)
 	int ret = -EMSGSIZE;
 	void *hdr;
 
-	netdev_info(peer->ovpn->dev, "peer with id %u must rekey - primary key unusable.\n",
-		    peer->id);
+	netdev_info(peer->ovpn->dev, "peer with id %u should rekey key %u\n",
+		    peer->id, key_id);
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
 	if (!msg)
diff --git a/drivers/net/ovpn/pktid.h b/drivers/net/ovpn/pktid.h
index 21845f353bc8..82f59256b4a3 100644
--- a/drivers/net/ovpn/pktid.h
+++ b/drivers/net/ovpn/pktid.h
@@ -17,6 +17,9 @@
  */
 #define PKTID_RECV_EXPIRE (30 * HZ)
 
+/* notify userspace when the packet ID space is close to wrapping */
+#define PKTID_XMIT_REKEY_NOTIFY 0xff000000U
+
 /* Packet-ID state for transmitter */
 struct ovpn_pktid_xmit {
 	atomic_t seq_num;
@@ -52,20 +55,36 @@ struct ovpn_pktid_recv {
 	spinlock_t lock;
 };
 
-/* Get the next packet ID for xmit */
+/**
+ * ovpn_pktid_xmit_next - allocate a transmit packet ID
+ * @pid: transmit packet ID state
+ * @pktid: location where the generated packet ID is stored
+ *
+ * The returned packet ID becomes part of the AEAD nonce, so the helper rejects
+ * the packet before the 32-bit packet-ID space wraps.
+ *
+ * The packet-ID soft threshold does not reject the packet. It returns 1 once
+ * so the caller can notify userspace to rekey while packet-ID space remains.
+ *
+ * Return: 1 if userspace should be notified, 0 if no notification is needed,
+ * or a negative error code otherwise.
+ */
 static inline int ovpn_pktid_xmit_next(struct ovpn_pktid_xmit *pid, u32 *pktid)
 {
 	const u32 seq_num = atomic_fetch_add_unless(&pid->seq_num, 1, 0);
-	/* when the 32bit space is over, we return an error because the packet
-	 * ID is used to create the cipher IV and we do not want to reuse the
-	 * same value more than once
-	 */
+	int ret = 0;
+
+	/* packet IDs are used to create cipher IVs and must not wrap */
 	if (unlikely(!seq_num))
 		return -ERANGE;
 
+	/* notify userspace before the packet ID space is close to wrapping */
+	if (unlikely(seq_num == PKTID_XMIT_REKEY_NOTIFY))
+		ret = 1;
+
 	*pktid = seq_num;
 
-	return 0;
+	return ret;
 }
 
 /* Write 12-byte AEAD IV to dest */
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.