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

Ralf Lici <[email protected]>
Newsgroups gmane.network.openvpn.devel
Message-ID <e120784b36e67749ead92d3ba1cdedac57738ecf.1782919654.git.ralf@mandelbit.com>
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 <[email protected]>
---
 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(-)

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