[Openvpn-devel,RFC,net-next,04/14] ovpn: make direct-key AEAD layout explicit

Message ID e120784b36e67749ead92d3ba1cdedac57738ecf.1782919654.git.ralf@mandelbit.com
State Superseded
Headers
Series ovpn: add epoch data channel keys |

Commit Message

Ralf Lici July 1, 2026, 3:43 p.m. UTC
  Some AEAD packet layout constants are currently named as DATA_V2
helpers. DATA_V2 is the opcode used by OpenVPN data packets, but the
layout represented by these constants is the direct-key AEAD layout:
opcode, 32-bit packet ID, prepended authentication tag, and payload.

Rename the helpers after the direct-key format they describe. This gives
the direct layout clear scope before adding another data-channel key
format that keeps the DATA_V2 opcode but uses different packet fields.

Signed-off-by: Ralf Lici <ralf@mandelbit.com>
---
 drivers/net/ovpn/crypto_aead.c | 38 +++++++++++++++-------------------
 drivers/net/ovpn/io.c          | 10 ++++-----
 drivers/net/ovpn/io.h          |  8 +++----
 drivers/net/ovpn/proto.h       | 30 +++++++++++++++++++++++++++
 4 files changed, 55 insertions(+), 31 deletions(-)
  

Patch

diff --git a/drivers/net/ovpn/crypto_aead.c b/drivers/net/ovpn/crypto_aead.c
index 9e34a553f59a..d2e3532934fb 100644
--- a/drivers/net/ovpn/crypto_aead.c
+++ b/drivers/net/ovpn/crypto_aead.c
@@ -24,9 +24,6 @@ 
 #include "proto.h"
 #include "skb.h"
 
-#define OVPN_AUTH_TAG_SIZE	16
-#define OVPN_AAD_SIZE		(OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE)
-
 #define ALG_NAME_AES		"gcm(aes)"
 #define ALG_NAME_CHACHAPOLY	"rfc7539(chacha20,poly1305)"
 #define OVPN_AEAD_DECRYPT_FAILURE_NOTIFY	BIT_ULL(35)
@@ -51,9 +48,7 @@  bool ovpn_aead_decrypt_failure_record(struct ovpn_crypto_key_slot *ks)
 
 static int ovpn_aead_encap_overhead(const struct ovpn_crypto_key_slot *ks)
 {
-	return  OVPN_OPCODE_SIZE +			/* OP header size */
-		sizeof(u32) +				/* Packet ID */
-		crypto_aead_authsize(ks->encrypt);	/* Auth Tag */
+	return OVPN_AEAD_DIRECT_AAD_SIZE + crypto_aead_authsize(ks->encrypt);
 }
 
 /**
@@ -163,6 +158,7 @@  int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	struct sk_buff *trailer;
 	struct scatterlist *sg;
 	int nfrags, ret;
+	u64 aead_blocks;
 	u32 pktid, op;
 	void *tmp;
 	u8 *iv;
@@ -205,7 +201,7 @@  int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	sg = ovpn_aead_crypto_req_sg(ks->encrypt, req);
 
 	/* sg table:
-	 * 0: op, wire nonce (AD, len=OVPN_OP_SIZE_V2+OVPN_NONCE_WIRE_SIZE),
+	 * 0: op, wire nonce (AD, len=OVPN_AEAD_DIRECT_AAD_SIZE),
 	 * 1, 2, 3, ..., n: payload,
 	 * n+1: auth_tag (len=tag_size)
 	 */
@@ -226,12 +222,11 @@  int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	/* obtain packet ID, which is used both as a first
 	 * 4 bytes of nonce and last 4 bytes of associated data.
 	 */
+	aead_blocks = ovpn_aead_limit_blocks(ks->cipher_alg,
+					     OVPN_AEAD_DIRECT_AAD_SIZE,
+					     plaintext_len);
 	ret = ovpn_pktid_xmit_next(&ks->pid_xmit, &ks->usage_xmit,
-				   &ks->usage_limit,
-				   ovpn_aead_limit_blocks(ks->cipher_alg,
-							  OVPN_AAD_SIZE,
-							  plaintext_len),
-				   &pktid);
+				   &ks->usage_limit, aead_blocks, &pktid);
 	if (unlikely(ret < 0))
 		return ret;
 	if (unlikely(ret > 0))
@@ -253,14 +248,14 @@  int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	*((__force __be32 *)skb->data) = htonl(op);
 
 	/* AEAD Additional data */
-	sg_set_buf(sg, skb->data, OVPN_AAD_SIZE);
+	sg_set_buf(sg, skb->data, OVPN_AEAD_DIRECT_AAD_SIZE);
 
 	/* setup async crypto operation */
 	aead_request_set_tfm(req, ks->encrypt);
 	aead_request_set_callback(req, 0, ovpn_encrypt_post, skb);
 	aead_request_set_crypt(req, sg, sg,
 			       skb->len - ovpn_aead_encap_overhead(ks), iv);
-	aead_request_set_ad(req, OVPN_AAD_SIZE);
+	aead_request_set_ad(req, OVPN_AEAD_DIRECT_AAD_SIZE);
 
 	/* encrypt it */
 	return crypto_aead_encrypt(req);
@@ -278,7 +273,7 @@  int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	void *tmp;
 	u8 *iv;
 
-	payload_offset = OVPN_AAD_SIZE + tag_size;
+	payload_offset = ovpn_aead_direct_payload_offset(tag_size);
 	payload_len = skb->len - payload_offset;
 
 	ovpn_skb_cb(skb)->payload_offset = payload_offset;
@@ -320,14 +315,14 @@  int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	sg = ovpn_aead_crypto_req_sg(ks->decrypt, req);
 
 	/* sg table:
-	 * 0: op, wire nonce (AD, len=OVPN_OPCODE_SIZE+OVPN_NONCE_WIRE_SIZE),
+	 * 0: op, wire nonce (AD, len=OVPN_AEAD_DIRECT_AAD_SIZE),
 	 * 1, 2, 3, ..., n: payload,
 	 * n+1: auth_tag (len=tag_size)
 	 */
 	sg_init_table(sg, nfrags + 2);
 
 	/* packet op is head of additional data */
-	sg_set_buf(sg, skb->data, OVPN_AAD_SIZE);
+	sg_set_buf(sg, skb->data, OVPN_AEAD_DIRECT_AAD_SIZE);
 
 	/* build scatterlist to decrypt packet payload */
 	ret = skb_to_sgvec_nomark(skb, sg + 1, payload_offset, payload_len);
@@ -338,10 +333,11 @@  int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	}
 
 	/* append auth_tag onto scatterlist */
-	sg_set_buf(sg + ret + 1, skb->data + OVPN_AAD_SIZE, tag_size);
+	sg_set_buf(sg + ret + 1, skb->data + OVPN_AEAD_DIRECT_TAG_OFFSET,
+		   tag_size);
 
 	/* copy nonce into IV buffer */
-	memcpy(iv, skb->data + OVPN_OPCODE_SIZE, OVPN_NONCE_WIRE_SIZE);
+	memcpy(iv, ovpn_aead_direct_wire_nonce(skb), OVPN_NONCE_WIRE_SIZE);
 	memcpy(iv + OVPN_NONCE_WIRE_SIZE, ks->nonce_tail_recv,
 	       OVPN_NONCE_TAIL_SIZE);
 
@@ -350,7 +346,7 @@  int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
 	aead_request_set_callback(req, 0, ovpn_decrypt_post, skb);
 	aead_request_set_crypt(req, sg, sg, payload_len + tag_size, iv);
 
-	aead_request_set_ad(req, OVPN_AAD_SIZE);
+	aead_request_set_ad(req, OVPN_AEAD_DIRECT_AAD_SIZE);
 
 	/* decrypt it */
 	return crypto_aead_decrypt(req);
@@ -380,7 +376,7 @@  static struct crypto_aead *ovpn_aead_init(const char *title,
 		goto error;
 	}
 
-	ret = crypto_aead_setauthsize(aead, OVPN_AUTH_TAG_SIZE);
+	ret = crypto_aead_setauthsize(aead, OVPN_AEAD_TAG_SIZE);
 	if (ret) {
 		pr_err("%s crypto_aead_setauthsize failed, err=%d\n", title,
 		       ret);
diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c
index 8085cc345c59..6f3396f6f72e 100644
--- a/drivers/net/ovpn/io.c
+++ b/drivers/net/ovpn/io.c
@@ -114,7 +114,7 @@  void ovpn_decrypt_post(void *data, int ret)
 	struct ovpn_peer *peer;
 	u64 aead_blocks;
 	__be16 proto;
-	__be32 *pid;
+	u32 pktid;
 
 	/* crypto is happening asynchronously. this function will be called
 	 * again later by the crypto callback with a proper return code
@@ -138,9 +138,8 @@  void ovpn_decrypt_post(void *data, int ret)
 	if (unlikely(ret < 0))
 		goto drop;
 
-	/* PID sits after the op */
-	pid = (__force __be32 *)(skb->data + OVPN_OPCODE_SIZE);
-	ret = ovpn_pktid_recv(&ks->pid_recv, ntohl(*pid), 0);
+	pktid = ovpn_aead_direct_pktid(skb);
+	ret = ovpn_pktid_recv(&ks->pid_recv, pktid, 0);
 	if (unlikely(ret < 0)) {
 		net_err_ratelimited("%s: PKT ID RX error for peer %u: %d\n",
 				    netdev_name(peer->ovpn->dev), peer->id,
@@ -149,8 +148,7 @@  void ovpn_decrypt_post(void *data, int ret)
 	}
 
 	aead_blocks = ovpn_aead_limit_blocks(ks->cipher_alg,
-					     OVPN_OPCODE_SIZE +
-					     OVPN_NONCE_WIRE_SIZE,
+					     OVPN_AEAD_DIRECT_AAD_SIZE,
 					     skb->len - payload_offset);
 	if (unlikely(ovpn_pktid_recv_update_aead(&ks->pid_recv,
 						 &ks->usage_recv,
diff --git a/drivers/net/ovpn/io.h b/drivers/net/ovpn/io.h
index db9e10f9077c..fa795573c797 100644
--- a/drivers/net/ovpn/io.h
+++ b/drivers/net/ovpn/io.h
@@ -10,10 +10,10 @@ 
 #ifndef _NET_OVPN_OVPN_H_
 #define _NET_OVPN_OVPN_H_
 
-/* DATA_V2 header size with AEAD encryption */
-#define OVPN_HEAD_ROOM (OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE +	   \
-			16 /* AEAD TAG length */ +			   \
-			max(sizeof(struct udphdr), sizeof(struct tcphdr)) +\
+/* headroom needed by directly installed AEAD keys */
+#define OVPN_HEAD_ROOM (OVPN_AEAD_DIRECT_AAD_SIZE + \
+			OVPN_AEAD_TAG_SIZE + \
+			max(sizeof(struct udphdr), sizeof(struct tcphdr)) + \
 			max(sizeof(struct ipv6hdr), sizeof(struct iphdr)))
 
 /* max padding required by encryption */
diff --git a/drivers/net/ovpn/proto.h b/drivers/net/ovpn/proto.h
index b7d285b4d9c1..5fa053584b15 100644
--- a/drivers/net/ovpn/proto.h
+++ b/drivers/net/ovpn/proto.h
@@ -47,8 +47,38 @@ 
 #define OVPN_DATA_V1			6 /* data channel v1 packet */
 #define OVPN_DATA_V2			9 /* data channel v2 packet */
 
+/* direct-key AEAD packet layout */
+#define OVPN_AEAD_TAG_SIZE		16
+#define OVPN_AEAD_DIRECT_OP_OFFSET	0
+#define OVPN_AEAD_DIRECT_PKTID_OFFSET	(OVPN_AEAD_DIRECT_OP_OFFSET + \
+					 OVPN_OPCODE_SIZE)
+#define OVPN_AEAD_DIRECT_TAG_OFFSET	(OVPN_AEAD_DIRECT_PKTID_OFFSET + \
+					 OVPN_NONCE_WIRE_SIZE)
+#define OVPN_AEAD_DIRECT_AAD_SIZE	OVPN_AEAD_DIRECT_TAG_OFFSET
+
 #define OVPN_PEER_ID_UNDEF		0x00FFFFFF
 
+static inline unsigned int
+ovpn_aead_direct_payload_offset(unsigned int tag_size)
+{
+	return OVPN_AEAD_DIRECT_TAG_OFFSET + tag_size;
+}
+
+static inline u32 ovpn_aead_direct_pktid(const struct sk_buff *skb)
+{
+	const __be32 *pktid;
+
+	pktid = (__force const __be32 *)(skb->data +
+					 OVPN_AEAD_DIRECT_PKTID_OFFSET);
+
+	return be32_to_cpu(*pktid);
+}
+
+static inline u8 *ovpn_aead_direct_wire_nonce(struct sk_buff *skb)
+{
+	return skb->data + OVPN_AEAD_DIRECT_PKTID_OFFSET;
+}
+
 /**
  * ovpn_opcode_from_skb - extract OP code from skb at specified offset
  * @skb: the packet to extract the OP code from