diff mbox series

[1/6] crypto: api - Add crypto_tfm_get

Message ID E1pmqNT-00FNV9-CK@formenos.hmeau.com (mailing list archive)
State Not Applicable
Headers show
Series crypto: api - Add support for cloning tfms | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Herbert Xu April 13, 2023, 6:24 a.m. UTC
Add a crypto_tfm_get interface to allow tfm objects to be shared.
They can still be freed in the usual way.

This should only be done with tfm objects with no keys.  You must
also not modify the tfm flags in any way once it becomes shared.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 crypto/api.c           |    4 ++++
 crypto/internal.h      |    6 ++++++
 include/linux/crypto.h |    1 +
 3 files changed, 11 insertions(+)

Comments

Simon Horman April 18, 2023, 12:27 p.m. UTC | #1
On Thu, Apr 13, 2023 at 02:24:15PM +0800, Herbert Xu wrote:
> Add a crypto_tfm_get interface to allow tfm objects to be shared.
> They can still be freed in the usual way.
> 
> This should only be done with tfm objects with no keys.  You must
> also not modify the tfm flags in any way once it becomes shared.
> 
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Reviewed-by: Simon Horman <simon.horman@corigine.com>
diff mbox series

Patch

diff --git a/crypto/api.c b/crypto/api.c
index e67cc63368ed..f509d73fa682 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -408,6 +408,7 @@  struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 		goto out_err;
 
 	tfm->__crt_alg = alg;
+	refcount_set(&tfm->refcnt, 1);
 
 	err = crypto_init_ops(tfm, type, mask);
 	if (err)
@@ -507,6 +508,7 @@  void *crypto_create_tfm_node(struct crypto_alg *alg,
 	tfm = (struct crypto_tfm *)(mem + tfmsize);
 	tfm->__crt_alg = alg;
 	tfm->node = node;
+	refcount_set(&tfm->refcnt, 1);
 
 	err = frontend->init_tfm(tfm);
 	if (err)
@@ -619,6 +621,8 @@  void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm)
 	if (IS_ERR_OR_NULL(mem))
 		return;
 
+	if (!refcount_dec_and_test(&tfm->refcnt))
+		return;
 	alg = tfm->__crt_alg;
 
 	if (!tfm->exit && alg->cra_exit)
diff --git a/crypto/internal.h b/crypto/internal.h
index f84dfe6491e5..5eee009ee494 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -10,6 +10,7 @@ 
 
 #include <crypto/algapi.h>
 #include <linux/completion.h>
+#include <linux/err.h>
 #include <linux/jump_label.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -186,5 +187,10 @@  static inline int crypto_is_test_larval(struct crypto_larval *larval)
 	return larval->alg.cra_driver_name[0];
 }
 
+static inline struct crypto_tfm *crypto_tfm_get(struct crypto_tfm *tfm)
+{
+	return refcount_inc_not_zero(&tfm->refcnt) ? tfm : ERR_PTR(-EOVERFLOW);
+}
+
 #endif	/* _CRYPTO_INTERNAL_H */
 
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index fdfa3e8eda43..fa310ac1db59 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -419,6 +419,7 @@  int crypto_has_alg(const char *name, u32 type, u32 mask);
  */
 
 struct crypto_tfm {
+	refcount_t refcnt;
 
 	u32 crt_flags;