The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Eric Biggers <ebiggers@kernel.org>
Subject: [PATCH 33/33] net: tipc: Use AES-GCM library instead of crypto_aead
Date: Mon,  6 Jul 2026 22:35:03 -0700	[thread overview]
Message-ID: <20260707053503.209874-34-ebiggers@kernel.org> (raw)
In-Reply-To: <20260707053503.209874-1-ebiggers@kernel.org>

Now that there's a library API for AES-GCM, use it instead of a
"gcm(aes)" crypto_aead.  This significantly simplifies the code.

Notably, per-skb dynamic memory allocations and conversions to
scatterlists are eliminated.  For encryption the skb is linear, so just
call the one-shot function aes_gcm_encrypt().  For decryption, just
iterate through the skb's data and decrypt it directly.

There was also an unnecessary copy of the key being made (in a
crypto_aead object) for every CPU.  That is removed as well.  The
library en/decryption functions treat struct aes_gcm_key as read-only,
so it can be used by an unlimited number of threads with no contention.

Asynchronous en/decryption operations are no longer supported, as that
execution model for symmetric crypto has been found to be harmful.  It
generated endless bugs and didn't actually improve performance.

Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 net/tipc/Kconfig  |   4 +-
 net/tipc/crypto.c | 467 ++++++++--------------------------------------
 net/tipc/msg.h    |   3 -
 net/tipc/sysctl.c |   6 +
 4 files changed, 85 insertions(+), 395 deletions(-)

diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig
index 18f62135e47b..39fa54b04bb9 100644
--- a/net/tipc/Kconfig
+++ b/net/tipc/Kconfig
@@ -38,9 +38,7 @@ config TIPC_MEDIA_UDP
 config TIPC_CRYPTO
 	bool "TIPC encryption support"
 	depends on TIPC
-	select CRYPTO
-	select CRYPTO_AES
-	select CRYPTO_GCM
+	select CRYPTO_LIB_AES_GCM
 	default y
 	help
 	  Saying Y here will enable support for TIPC encryption.
diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c
index 16f1ed1f6b1b..e0040309a788 100644
--- a/net/tipc/crypto.c
+++ b/net/tipc/crypto.c
@@ -34,8 +34,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <crypto/aead.h>
-#include <crypto/aes.h>
+#include <crypto/aes-gcm.h>
 #include <crypto/rng.h>
 #include "crypto.h"
 #include "msg.h"
@@ -69,9 +68,9 @@ enum {
 enum {
 	STAT_OK,
 	STAT_NOK,
-	STAT_ASYNC,
-	STAT_ASYNC_OK,
-	STAT_ASYNC_NOK,
+	STAT_ASYNC, /* no longer used */
+	STAT_ASYNC_OK, /* no longer used */
+	STAT_ASYNC_NOK, /* no longer used */
 	STAT_BADKEYS, /* tx only */
 	STAT_BADMSGS = STAT_BADKEYS, /* rx only */
 	STAT_NOKEYS,
@@ -121,19 +120,9 @@ struct tipc_key {
 	};
 };
 
-/**
- * struct tipc_tfm - TIPC TFM structure to form a list of TFMs
- * @tfm: cipher handle/key
- * @list: linked list of TFMs
- */
-struct tipc_tfm {
-	struct crypto_aead *tfm;
-	struct list_head list;
-};
-
 /**
  * struct tipc_aead - TIPC AEAD key structure
- * @tfm_entry: per-cpu pointer to one entry in TFM list
+ * @gcm_key: the AES-GCM key
  * @crypto: TIPC crypto owns this key
  * @cloned: reference to the source key in case cloning
  * @users: the number of the key users (TX/RX)
@@ -149,7 +138,7 @@ struct tipc_tfm {
  */
 struct tipc_aead {
 #define TIPC_AEAD_HINT_LEN (5)
-	struct tipc_tfm * __percpu *tfm_entry;
+	struct aes_gcm_key gcm_key;
 	struct tipc_crypto *crypto;
 	struct tipc_aead *cloned;
 	atomic_t users;
@@ -235,19 +224,6 @@ struct tipc_crypto {
 
 } ____cacheline_aligned;
 
-/* struct tipc_crypto_tx_ctx - TX context for callbacks */
-struct tipc_crypto_tx_ctx {
-	struct tipc_aead *aead;
-	struct tipc_bearer *bearer;
-	struct tipc_media_addr dst;
-};
-
-/* struct tipc_crypto_rx_ctx - RX context for callbacks */
-struct tipc_crypto_rx_ctx {
-	struct tipc_aead *aead;
-	struct tipc_bearer *bearer;
-};
-
 static struct tipc_aead *tipc_aead_get(struct tipc_aead __rcu *aead);
 static inline void tipc_aead_put(struct tipc_aead *aead);
 static void tipc_aead_free(struct rcu_head *rp);
@@ -255,22 +231,15 @@ static int tipc_aead_users(struct tipc_aead __rcu *aead);
 static void tipc_aead_users_inc(struct tipc_aead __rcu *aead, int lim);
 static void tipc_aead_users_dec(struct tipc_aead __rcu *aead, int lim);
 static void tipc_aead_users_set(struct tipc_aead __rcu *aead, int val);
-static struct crypto_aead *tipc_aead_tfm_next(struct tipc_aead *aead);
 static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey,
 			  u8 mode);
 static int tipc_aead_clone(struct tipc_aead **dst, struct tipc_aead *src);
-static void *tipc_aead_mem_alloc(struct crypto_aead *tfm,
-				 unsigned int crypto_ctx_size,
-				 u8 **iv, struct aead_request **req,
-				 struct scatterlist **sg, int nsg);
 static int tipc_aead_encrypt(struct tipc_aead *aead, struct sk_buff *skb,
 			     struct tipc_bearer *b,
 			     struct tipc_media_addr *dst,
 			     struct tipc_node *__dnode);
-static void tipc_aead_encrypt_done(void *data, int err);
 static int tipc_aead_decrypt(struct net *net, struct tipc_aead *aead,
 			     struct sk_buff *skb, struct tipc_bearer *b);
-static void tipc_aead_decrypt_done(void *data, int err);
 static inline int tipc_ehdr_size(struct tipc_ehdr *ehdr);
 static int tipc_ehdr_build(struct net *net, struct tipc_aead *aead,
 			   u8 tx_key, struct sk_buff *skb,
@@ -335,12 +304,6 @@ int tipc_aead_key_validate(struct tipc_aead_key *ukey, struct genl_info *info)
 {
 	int keylen;
 
-	/* Check if algorithm exists */
-	if (unlikely(!crypto_has_alg(ukey->alg_name, 0, 0))) {
-		GENL_SET_ERR_MSG(info, "unable to load the algorithm (module existed?)");
-		return -ENODEV;
-	}
-
 	/* Currently, we only support the "gcm(aes)" cipher algorithm */
 	if (strcmp(ukey->alg_name, "gcm(aes)")) {
 		GENL_SET_ERR_MSG(info, "not supported yet the algorithm");
@@ -391,30 +354,15 @@ static inline void tipc_aead_put(struct tipc_aead *aead)
 }
 
 /**
- * tipc_aead_free - Release AEAD key incl. all the TFMs in the list
+ * tipc_aead_free - Release AEAD key
  * @rp: rcu head pointer
  */
 static void tipc_aead_free(struct rcu_head *rp)
 {
 	struct tipc_aead *aead = container_of(rp, struct tipc_aead, rcu);
-	struct tipc_tfm *tfm_entry, *head, *tmp;
 
-	if (aead->cloned) {
+	if (aead->cloned)
 		tipc_aead_put(aead->cloned);
-	} else {
-		head = *get_cpu_ptr(aead->tfm_entry);
-		put_cpu_ptr(aead->tfm_entry);
-		list_for_each_entry_safe(tfm_entry, tmp, &head->list, list) {
-			crypto_free_aead(tfm_entry->tfm);
-			list_del(&tfm_entry->list);
-			kfree(tfm_entry);
-		}
-		/* Free the head */
-		crypto_free_aead(head->tfm);
-		list_del(&head->list);
-		kfree(head);
-	}
-	free_percpu(aead->tfm_entry);
 	kfree_sensitive(aead->key);
 	kfree_sensitive(aead);
 }
@@ -472,44 +420,21 @@ static void tipc_aead_users_set(struct tipc_aead __rcu *aead, int val)
 	rcu_read_unlock();
 }
 
-/**
- * tipc_aead_tfm_next - Move TFM entry to the next one in list and return it
- * @aead: the AEAD key pointer
- */
-static struct crypto_aead *tipc_aead_tfm_next(struct tipc_aead *aead)
-{
-	struct tipc_tfm **tfm_entry;
-	struct crypto_aead *tfm;
-
-	tfm_entry = get_cpu_ptr(aead->tfm_entry);
-	*tfm_entry = list_next_entry(*tfm_entry, list);
-	tfm = (*tfm_entry)->tfm;
-	put_cpu_ptr(tfm_entry);
-
-	return tfm;
-}
-
 /**
  * tipc_aead_init - Initiate TIPC AEAD
  * @aead: returned new TIPC AEAD key handle pointer
  * @ukey: pointer to user key data
  * @mode: the key mode
  *
- * Allocate a (list of) new cipher transformation (TFM) with the specific user
- * key data if valid. The number of the allocated TFMs can be set via the sysfs
- * "net/tipc/max_tfms" first.
- * Also, all the other AEAD data are also initialized.
+ * Allocate a new AEAD key container and prepare the AES-GCM key.
  *
  * Return: 0 if the initiation is successful, otherwise: < 0
  */
 static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey,
 			  u8 mode)
 {
-	struct tipc_tfm *tfm_entry, *head;
-	struct crypto_aead *tfm;
 	struct tipc_aead *tmp;
-	int keylen, err, cpu;
-	int tfm_cnt = 0;
+	int keylen, err;
 
 	if (unlikely(*aead))
 		return -EEXIST;
@@ -522,59 +447,9 @@ static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey,
 	/* The key consists of two parts: [AES-KEY][SALT] */
 	keylen = ukey->keylen - TIPC_AES_GCM_SALT_SIZE;
 
-	/* Allocate per-cpu TFM entry pointer */
-	tmp->tfm_entry = alloc_percpu(struct tipc_tfm *);
-	if (!tmp->tfm_entry) {
-		kfree_sensitive(tmp);
-		return -ENOMEM;
-	}
-
-	/* Make a list of TFMs with the user key data */
-	do {
-		tfm = crypto_alloc_aead(ukey->alg_name, 0, 0);
-		if (IS_ERR(tfm)) {
-			err = PTR_ERR(tfm);
-			break;
-		}
-
-		if (unlikely(!tfm_cnt &&
-			     crypto_aead_ivsize(tfm) != TIPC_AES_GCM_IV_SIZE)) {
-			crypto_free_aead(tfm);
-			err = -ENOTSUPP;
-			break;
-		}
-
-		err = crypto_aead_setauthsize(tfm, TIPC_AES_GCM_TAG_SIZE);
-		err |= crypto_aead_setkey(tfm, ukey->key, keylen);
-		if (unlikely(err)) {
-			crypto_free_aead(tfm);
-			break;
-		}
-
-		tfm_entry = kmalloc_obj(*tfm_entry);
-		if (unlikely(!tfm_entry)) {
-			crypto_free_aead(tfm);
-			err = -ENOMEM;
-			break;
-		}
-		INIT_LIST_HEAD(&tfm_entry->list);
-		tfm_entry->tfm = tfm;
-
-		/* First entry? */
-		if (!tfm_cnt) {
-			head = tfm_entry;
-			for_each_possible_cpu(cpu) {
-				*per_cpu_ptr(tmp->tfm_entry, cpu) = head;
-			}
-		} else {
-			list_add_tail(&tfm_entry->list, &head->list);
-		}
-
-	} while (++tfm_cnt < sysctl_tipc_max_tfms);
-
-	/* Not any TFM is allocated? */
-	if (!tfm_cnt) {
-		free_percpu(tmp->tfm_entry);
+	err = aes_gcm_preparekey(&tmp->gcm_key, ukey->key, keylen,
+				 TIPC_AES_GCM_TAG_SIZE);
+	if (unlikely(err)) {
 		kfree_sensitive(tmp);
 		return err;
 	}
@@ -606,10 +481,8 @@ static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey,
  * @dst: dest key for the cloning
  * @src: source key to clone from
  *
- * Make a "copy" of the source AEAD key data to the dest, the TFMs list is
- * common for the keys.
- * A reference to the source is hold in the "cloned" pointer for the later
- * freeing purposes.
+ * Make a "copy" of the source AEAD key data to the dest. A reference to the
+ * source is held in the "cloned" pointer for later freeing purposes.
  *
  * Note: this must be done in cluster-key mode only!
  * Return: 0 in case of success, otherwise < 0
@@ -617,7 +490,6 @@ static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey,
 static int tipc_aead_clone(struct tipc_aead **dst, struct tipc_aead *src)
 {
 	struct tipc_aead *aead;
-	int cpu;
 
 	if (!src)
 		return -ENOKEY;
@@ -632,16 +504,7 @@ static int tipc_aead_clone(struct tipc_aead **dst, struct tipc_aead *src)
 	if (unlikely(!aead))
 		return -ENOMEM;
 
-	aead->tfm_entry = alloc_percpu_gfp(struct tipc_tfm *, GFP_ATOMIC);
-	if (unlikely(!aead->tfm_entry)) {
-		kfree_sensitive(aead);
-		return -ENOMEM;
-	}
-
-	for_each_possible_cpu(cpu) {
-		*per_cpu_ptr(aead->tfm_entry, cpu) =
-				*per_cpu_ptr(src->tfm_entry, cpu);
-	}
+	aead->gcm_key = src->gcm_key;
 
 	memcpy(aead->hint, src->hint, sizeof(src->hint));
 	aead->mode = src->mode;
@@ -658,53 +521,54 @@ static int tipc_aead_clone(struct tipc_aead **dst, struct tipc_aead *src)
 	return 0;
 }
 
+static void tipc_decrypt_chunk(struct aes_gcm_ctx *ctx, u8 *data, size_t avail,
+			       size_t *assoc_len, size_t *crypt_len)
+{
+	size_t n;
+
+	if (*assoc_len && avail) {
+		/* Associated data */
+		n = min(avail, *assoc_len);
+		aes_gcm_auth_update(ctx, data, n);
+		data += n;
+		avail -= n;
+		*assoc_len -= n;
+	}
+
+	if (*crypt_len && avail) {
+		/* En/decrypted data */
+		n = min(avail, *crypt_len);
+		aes_gcm_decrypt_update(ctx, data, data, n);
+		*crypt_len -= n;
+	}
+}
+
 /**
- * tipc_aead_mem_alloc - Allocate memory for AEAD request operations
- * @tfm: cipher handle to be registered with the request
- * @crypto_ctx_size: size of crypto context for callback
- * @iv: returned pointer to IV data
- * @req: returned pointer to AEAD request data
- * @sg: returned pointer to SG lists
- * @nsg: number of SG lists to be allocated
+ * tipc_decrypt_skb() - Decrypt an skb in-place using AES-GCM
+ * @ctx: An AES-GCM context
+ * @skb: The socket buffer to process
+ * @assoc_len: Length of associated data
+ * @crypt_len: Length of payload data to encrypt or decrypt
  *
- * Allocate memory to store the crypto context data, AEAD request, IV and SG
- * lists, the memory layout is as follows:
- * crypto_ctx || iv || aead_req || sg[]
+ * Updates the given AES-GCM context with @assoc_len bytes of associated data
+ * from the skb, then decrypts @crypt_len bytes in-place.  Context
+ * initialization and finalization are handled by the caller.
  *
- * Return: the pointer to the memory areas in case of success, otherwise NULL
+ * The data (both associated and en/decrypted) is taken from the linear head and
+ * frag_list.  It is assumed that the @skb was processed by skb_cow_data(),
+ * meaning it has no page fragments (nr_frags == 0) and is writable.
  */
-static void *tipc_aead_mem_alloc(struct crypto_aead *tfm,
-				 unsigned int crypto_ctx_size,
-				 u8 **iv, struct aead_request **req,
-				 struct scatterlist **sg, int nsg)
+static void tipc_decrypt_skb(struct aes_gcm_ctx *ctx, struct sk_buff *skb,
+			     size_t assoc_len, size_t crypt_len)
 {
-	unsigned int iv_size, req_size;
-	unsigned int len;
-	u8 *mem;
-
-	iv_size = crypto_aead_ivsize(tfm);
-	req_size = sizeof(**req) + crypto_aead_reqsize(tfm);
-
-	len = crypto_ctx_size;
-	len += iv_size;
-	len += crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1);
-	len = ALIGN(len, crypto_tfm_ctx_alignment());
-	len += req_size;
-	len = ALIGN(len, __alignof__(struct scatterlist));
-	len += nsg * sizeof(**sg);
-
-	mem = kmalloc(len, GFP_ATOMIC);
-	if (!mem)
-		return NULL;
-
-	*iv = (u8 *)PTR_ALIGN(mem + crypto_ctx_size,
-			      crypto_aead_alignmask(tfm) + 1);
-	*req = (struct aead_request *)PTR_ALIGN(*iv + iv_size,
-						crypto_tfm_ctx_alignment());
-	*sg = (struct scatterlist *)PTR_ALIGN((u8 *)*req + req_size,
-					      __alignof__(struct scatterlist));
-
-	return (void *)mem;
+	struct sk_buff *frag_iter;
+
+	WARN_ON_ONCE(skb_shinfo(skb)->nr_frags);
+	tipc_decrypt_chunk(ctx, skb->data, skb_headlen(skb), &assoc_len,
+			   &crypt_len);
+	skb_walk_frags(skb, frag_iter)
+		tipc_decrypt_chunk(ctx, frag_iter->data, frag_iter->len,
+				   &assoc_len, &crypt_len);
 }
 
 /**
@@ -717,7 +581,6 @@ static void *tipc_aead_mem_alloc(struct crypto_aead *tfm,
  *
  * Return:
  * * 0                   : if the encryption has completed
- * * -EINPROGRESS/-EBUSY : if a callback will be performed
  * * < 0                 : the encryption has failed
  */
 static int tipc_aead_encrypt(struct tipc_aead *aead, struct sk_buff *skb,
@@ -725,16 +588,11 @@ static int tipc_aead_encrypt(struct tipc_aead *aead, struct sk_buff *skb,
 			     struct tipc_media_addr *dst,
 			     struct tipc_node *__dnode)
 {
-	struct crypto_aead *tfm = tipc_aead_tfm_next(aead);
-	struct tipc_crypto_tx_ctx *tx_ctx;
-	struct aead_request *req;
 	struct sk_buff *trailer;
-	struct scatterlist *sg;
 	struct tipc_ehdr *ehdr;
-	int ehsz, len, tailen, nsg, rc;
-	void *ctx;
+	int ehsz, len, tailen, nsg;
 	u32 salt;
-	u8 *iv;
+	u8 iv[TIPC_AES_GCM_IV_SIZE];
 
 	/* Make sure message len at least 4-byte aligned */
 	len = ALIGN(skb->len, 4);
@@ -760,20 +618,6 @@ static int tipc_aead_encrypt(struct tipc_aead *aead, struct sk_buff *skb,
 
 	pskb_put(skb, trailer, tailen);
 
-	/* Allocate memory for the AEAD operation */
-	ctx = tipc_aead_mem_alloc(tfm, sizeof(*tx_ctx), &iv, &req, &sg, nsg);
-	if (unlikely(!ctx))
-		return -ENOMEM;
-	TIPC_SKB_CB(skb)->crypto_ctx = ctx;
-
-	/* Map skb to the sg lists */
-	sg_init_table(sg, nsg);
-	rc = skb_to_sgvec(skb, sg, 0, skb->len);
-	if (unlikely(rc < 0)) {
-		pr_err("TX: skb_to_sgvec() returned %d, nsg %d!\n", rc, nsg);
-		goto exit;
-	}
-
 	/* Prepare IV: [SALT (4 octets)][SEQNO (8 octets)]
 	 * In case we're in cluster-key mode, SALT is varied by xor-ing with
 	 * the source address (or w0 of id), otherwise with the dest address
@@ -788,78 +632,12 @@ static int tipc_aead_encrypt(struct tipc_aead *aead, struct sk_buff *skb,
 	memcpy(iv, &salt, 4);
 	memcpy(iv + 4, (u8 *)&ehdr->seqno, 8);
 
-	/* Prepare request */
 	ehsz = tipc_ehdr_size(ehdr);
-	aead_request_set_tfm(req, tfm);
-	aead_request_set_ad(req, ehsz);
-	aead_request_set_crypt(req, sg, sg, len - ehsz, iv);
-
-	/* Set callback function & data */
-	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-				  tipc_aead_encrypt_done, skb);
-	tx_ctx = (struct tipc_crypto_tx_ctx *)ctx;
-	tx_ctx->aead = aead;
-	tx_ctx->bearer = b;
-	memcpy(&tx_ctx->dst, dst, sizeof(*dst));
-
-	/* Hold bearer */
-	if (unlikely(!tipc_bearer_hold(b))) {
-		rc = -ENODEV;
-		goto exit;
-	}
-
-	/* Get net to avoid freed tipc_crypto when delete namespace */
-	if (!maybe_get_net(aead->crypto->net)) {
-		tipc_bearer_put(b);
-		rc = -ENODEV;
-		goto exit;
-	}
-
-	/* Now, do encrypt */
-	rc = crypto_aead_encrypt(req);
-	if (rc == -EINPROGRESS || rc == -EBUSY)
-		return rc;
-
-	tipc_bearer_put(b);
-	put_net(aead->crypto->net);
-
-exit:
-	kfree(ctx);
-	TIPC_SKB_CB(skb)->crypto_ctx = NULL;
-	return rc;
-}
 
-static void tipc_aead_encrypt_done(void *data, int err)
-{
-	struct sk_buff *skb = data;
-	struct tipc_crypto_tx_ctx *tx_ctx = TIPC_SKB_CB(skb)->crypto_ctx;
-	struct tipc_bearer *b = tx_ctx->bearer;
-	struct tipc_aead *aead = tx_ctx->aead;
-	struct tipc_crypto *tx = aead->crypto;
-	struct net *net = tx->net;
-
-	switch (err) {
-	case 0:
-		this_cpu_inc(tx->stats->stat[STAT_ASYNC_OK]);
-		rcu_read_lock();
-		if (likely(test_bit(0, &b->up)))
-			b->media->send_msg(net, skb, b, &tx_ctx->dst);
-		else
-			kfree_skb(skb);
-		rcu_read_unlock();
-		break;
-	case -EINPROGRESS:
-		return;
-	default:
-		this_cpu_inc(tx->stats->stat[STAT_ASYNC_NOK]);
-		kfree_skb(skb);
-		break;
-	}
-
-	kfree(tx_ctx);
-	tipc_bearer_put(b);
-	tipc_aead_put(aead);
-	put_net(net);
+	/* Encrypt the skb in-place. */
+	aes_gcm_encrypt(skb->data + ehsz, skb->data + len, skb->data + ehsz,
+			len - ehsz, skb->data, ehsz, iv, &aead->gcm_key);
+	return 0;
 }
 
 /**
@@ -871,22 +649,18 @@ static void tipc_aead_encrypt_done(void *data, int err)
  *
  * Return:
  * * 0                   : if the decryption has completed
- * * -EINPROGRESS/-EBUSY : if a callback will be performed
  * * < 0                 : the decryption has failed
  */
 static int tipc_aead_decrypt(struct net *net, struct tipc_aead *aead,
 			     struct sk_buff *skb, struct tipc_bearer *b)
 {
-	struct tipc_crypto_rx_ctx *rx_ctx;
-	struct aead_request *req;
-	struct crypto_aead *tfm;
+	struct aes_gcm_ctx ctx;
 	struct sk_buff *unused;
-	struct scatterlist *sg;
 	struct tipc_ehdr *ehdr;
-	int ehsz, nsg, rc;
-	void *ctx;
+	int ehsz, nsg, rc, crypt_len;
 	u32 salt;
-	u8 *iv;
+	u8 iv[TIPC_AES_GCM_IV_SIZE];
+	u8 authtag[TIPC_AES_GCM_TAG_SIZE];
 
 	if (unlikely(!aead))
 		return -ENOKEY;
@@ -897,21 +671,6 @@ static int tipc_aead_decrypt(struct net *net, struct tipc_aead *aead,
 		return nsg;
 	}
 
-	/* Allocate memory for the AEAD operation */
-	tfm = tipc_aead_tfm_next(aead);
-	ctx = tipc_aead_mem_alloc(tfm, sizeof(*rx_ctx), &iv, &req, &sg, nsg);
-	if (unlikely(!ctx))
-		return -ENOMEM;
-	TIPC_SKB_CB(skb)->crypto_ctx = ctx;
-
-	/* Map skb to the sg lists */
-	sg_init_table(sg, nsg);
-	rc = skb_to_sgvec(skb, sg, 0, skb->len);
-	if (unlikely(rc < 0)) {
-		pr_err("RX: skb_to_sgvec() returned %d, nsg %d\n", rc, nsg);
-		goto exit;
-	}
-
 	/* Reconstruct IV: */
 	ehdr = (struct tipc_ehdr *)skb->data;
 	salt = aead->salt;
@@ -922,77 +681,19 @@ static int tipc_aead_decrypt(struct net *net, struct tipc_aead *aead,
 	memcpy(iv, &salt, 4);
 	memcpy(iv + 4, (u8 *)&ehdr->seqno, 8);
 
-	/* Prepare request */
 	ehsz = tipc_ehdr_size(ehdr);
-	aead_request_set_tfm(req, tfm);
-	aead_request_set_ad(req, ehsz);
-	aead_request_set_crypt(req, sg, sg, skb->len - ehsz, iv);
-
-	/* Set callback function & data */
-	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-				  tipc_aead_decrypt_done, skb);
-	rx_ctx = (struct tipc_crypto_rx_ctx *)ctx;
-	rx_ctx->aead = aead;
-	rx_ctx->bearer = b;
-
-	/* Hold bearer */
-	if (unlikely(!tipc_bearer_hold(b))) {
-		rc = -ENODEV;
-		goto exit;
-	}
+	crypt_len = skb->len - ehsz - aead->authsize;
+	if (unlikely(crypt_len < 0))
+		return -EBADMSG;
 
-	/* Get net to avoid freed tipc_crypto when delete namespace */
-	if (!maybe_get_net(net)) {
-		tipc_bearer_put(b);
-		rc = -ENODEV;
-		goto exit;
-	}
-
-	/* Now, do decrypt */
-	rc = crypto_aead_decrypt(req);
-	if (rc == -EINPROGRESS || rc == -EBUSY)
+	rc = skb_copy_bits(skb, skb->len - aead->authsize, authtag,
+			   aead->authsize);
+	if (unlikely(rc < 0))
 		return rc;
 
-	tipc_bearer_put(b);
-	put_net(net);
-
-exit:
-	kfree(ctx);
-	TIPC_SKB_CB(skb)->crypto_ctx = NULL;
-	return rc;
-}
-
-static void tipc_aead_decrypt_done(void *data, int err)
-{
-	struct sk_buff *skb = data;
-	struct tipc_crypto_rx_ctx *rx_ctx = TIPC_SKB_CB(skb)->crypto_ctx;
-	struct tipc_bearer *b = rx_ctx->bearer;
-	struct tipc_aead *aead = rx_ctx->aead;
-	struct tipc_crypto_stats __percpu *stats = aead->crypto->stats;
-	struct net *net = aead->crypto->net;
-
-	switch (err) {
-	case 0:
-		this_cpu_inc(stats->stat[STAT_ASYNC_OK]);
-		break;
-	case -EINPROGRESS:
-		return;
-	default:
-		this_cpu_inc(stats->stat[STAT_ASYNC_NOK]);
-		break;
-	}
-
-	kfree(rx_ctx);
-	tipc_crypto_rcv_complete(net, aead, b, &skb, err);
-	if (likely(skb)) {
-		if (likely(test_bit(0, &b->up)))
-			tipc_rcv(net, skb, b);
-		else
-			kfree_skb(skb);
-	}
-
-	tipc_bearer_put(b);
-	put_net(net);
+	aes_gcm_init(&ctx, iv, &aead->gcm_key);
+	tipc_decrypt_skb(&ctx, skb, ehsz, crypt_len);
+	return aes_gcm_decrypt_final(&ctx, authtag);
 }
 
 static inline int tipc_ehdr_size(struct tipc_ehdr *ehdr)
@@ -1680,7 +1381,6 @@ static inline void tipc_crypto_clone_msg(struct net *net, struct sk_buff *_skb,
  *
  * Return:
  * * 0                   : the encryption has succeeded (or no encryption)
- * * -EINPROGRESS/-EBUSY : the encryption is ongoing, a callback will be made
  * * -ENOKEK             : the encryption has failed due to no key
  * * -EKEYREVOKED        : the encryption has failed due to key revoked
  * * -ENOMEM             : the encryption has failed due to no memory
@@ -1769,11 +1469,6 @@ int tipc_crypto_xmit(struct net *net, struct sk_buff **skb,
 	case 0:
 		this_cpu_inc(stats->stat[STAT_OK]);
 		break;
-	case -EINPROGRESS:
-	case -EBUSY:
-		this_cpu_inc(stats->stat[STAT_ASYNC]);
-		*skb = NULL;
-		return rc;
 	default:
 		this_cpu_inc(stats->stat[STAT_NOK]);
 		if (rc == -ENOKEY)
@@ -1805,7 +1500,6 @@ int tipc_crypto_xmit(struct net *net, struct sk_buff **skb,
  *
  * Return:
  * * 0                   : the decryption has successfully completed
- * * -EINPROGRESS/-EBUSY : the decryption is ongoing, a callback will be made
  * * -ENOKEY             : the decryption has failed due to no key
  * * -EBADMSG            : the decryption has failed due to bad message
  * * -ENOMEM             : the decryption has failed due to no memory
@@ -1859,11 +1553,6 @@ int tipc_crypto_rcv(struct net *net, struct tipc_crypto *rx,
 	case 0:
 		this_cpu_inc(stats->stat[STAT_OK]);
 		break;
-	case -EINPROGRESS:
-	case -EBUSY:
-		this_cpu_inc(stats->stat[STAT_ASYNC]);
-		*skb = NULL;
-		return rc;
 	default:
 		this_cpu_inc(stats->stat[STAT_NOK]);
 		if (rc == -ENOKEY) {
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index c5eec16213d7..c7f0105148bb 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -138,9 +138,6 @@ struct tipc_skb_cb {
 		u8 flags;
 	};
 	u8 reserved;
-#ifdef CONFIG_TIPC_CRYPTO
-	void *crypto_ctx;
-#endif
 } __packed;
 
 #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
diff --git a/net/tipc/sysctl.c b/net/tipc/sysctl.c
index 30d2e06e3d8c..3e8d9def5674 100644
--- a/net/tipc/sysctl.c
+++ b/net/tipc/sysctl.c
@@ -67,6 +67,12 @@ static struct ctl_table tipc_table[] = {
 	},
 #ifdef CONFIG_TIPC_CRYPTO
 	{
+		/*
+		 * This sysctl no longer has any effect on the way that TIPC
+		 * uses the crypto subsystem.  However, a special value can
+		 * still be written to this to trigger debug commands.  See
+		 * tipc_crypto_do_cmd().
+		 */
 		.procname	= "max_tfms",
 		.data		= &sysctl_tipc_max_tfms,
 		.maxlen		= sizeof(sysctl_tipc_max_tfms),
-- 
2.54.0


      parent reply	other threads:[~2026-07-07  5:37 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07  5:34 [PATCH 00/33] Library APIs for AES encryption modes Eric Biggers
2026-07-07  5:34 ` [PATCH 01/33] crypto: xts - Split out __xts_verify_key() helper Eric Biggers
2026-07-07 13:20   ` Thomas Huth
2026-07-07  5:34 ` [PATCH 02/33] lib/crypto: aes: Add ECB support Eric Biggers
2026-07-07 13:59   ` Thomas Huth
2026-07-07 19:22     ` Eric Biggers
2026-07-08  5:29       ` Thomas Huth
2026-07-07  5:34 ` [PATCH 03/33] lib/crypto: aes: Add CBC and CBC-CTS support Eric Biggers
2026-07-07  5:34 ` [PATCH 04/33] lib/crypto: aes: Add CTR and XCTR support Eric Biggers
2026-07-07  5:34 ` [PATCH 05/33] lib/crypto: aes: Add XTS support Eric Biggers
2026-07-07  5:34 ` [PATCH 06/33] lib/crypto: aes: Add GCM support Eric Biggers
2026-07-07  5:34 ` [PATCH 07/33] lib/crypto: aes: Add CCM support Eric Biggers
2026-07-07  5:34 ` [PATCH 08/33] crypto: aes - Add ECB support using library Eric Biggers
2026-07-07  5:34 ` [PATCH 09/33] crypto: aes - Add CBC and CBC-CTS " Eric Biggers
2026-07-07  5:34 ` [PATCH 10/33] crypto: aes - Add CTR and XCTR " Eric Biggers
2026-07-07  5:34 ` [PATCH 11/33] crypto: aes - Add XTS " Eric Biggers
2026-07-07  5:34 ` [PATCH 12/33] crypto: aes - Add GCM " Eric Biggers
2026-07-07  5:34 ` [PATCH 13/33] crypto: aes - Add CCM " Eric Biggers
2026-07-07  5:34 ` [PATCH 14/33] x86/sev: Use new AES-GCM library Eric Biggers
2026-07-07  5:34 ` [PATCH 15/33] lib/crypto: aesgcm: Remove old " Eric Biggers
2026-07-07  5:34 ` [PATCH 16/33] crypto: aes - Remove AES-CBC-MAC support Eric Biggers
2026-07-07  5:34 ` [PATCH 17/33] lib/crypto: aes: Remove aes_cbcmac_* functions Eric Biggers
2026-07-07  5:34 ` [PATCH 18/33] fscrypt: Use aes_ecb_encrypt() for v1 key derivation Eric Biggers
2026-07-07  5:34 ` [PATCH 19/33] KEYS: encrypted: Use AES-CBC library instead of crypto_skcipher Eric Biggers
2026-07-07  5:34 ` [PATCH 20/33] KEYS: trusted: dcp: Use AES-GCM library instead of crypto_aead Eric Biggers
2026-07-07  5:34 ` [PATCH 21/33] libceph: Use AES-CBC library in ceph_aes_crypt() Eric Biggers
2026-07-07  5:34 ` [PATCH 22/33] libceph: Reimplement messenger v2 encryption using AES-GCM library Eric Biggers
2026-07-07  5:34 ` [PATCH 23/33] wifi: mac80211: Use AES-CTR library in fils_aead.c Eric Biggers
2026-07-07  5:34 ` [PATCH 24/33] wifi: mac80211: Use AES-GCM library for GMAC suite Eric Biggers
2026-07-07  5:34 ` [PATCH 25/33] wifi: mac80211: Use crypto libraries for GCMP and CCMP suites Eric Biggers
2026-07-07  5:34 ` [PATCH 26/33] macsec: Use AES-GCM library instead of crypto_aead Eric Biggers
2026-07-07  5:34 ` [PATCH 27/33] wifi: ipw2x00: Use AES-CCM library Eric Biggers
2026-07-07  5:34 ` [PATCH 28/33] mac802154: Use AES-CCM and AES-CTR libraries Eric Biggers
2026-07-07  5:34 ` [PATCH 29/33] bpf: crypto: Use AES-CBC and AES-ECB libraries Eric Biggers
2026-07-07 15:01   ` Vadim Fedorenko
2026-07-07 18:20     ` Eric Biggers
2026-07-07 22:50       ` Vadim Fedorenko
2026-07-07 23:16         ` Eric Biggers
2026-07-08 11:47           ` Vadim Fedorenko
2026-07-07  5:35 ` [PATCH 30/33] bpf: crypto: Add AES-GCM support Eric Biggers
2026-07-07 15:02   ` Vadim Fedorenko
2026-07-07  5:35 ` [PATCH 31/33] smb: client: Use AES-GCM and AES-CCM libraries Eric Biggers
2026-07-07  5:35 ` [PATCH 32/33] ksmbd: " Eric Biggers
2026-07-07 10:51   ` Namjae Jeon
2026-07-07  5:35 ` Eric Biggers [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260707053503.209874-34-ebiggers@kernel.org \
    --to=ebiggers@kernel.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox