From 138804c2c18ca8bd1443dea173b3cc2643995919 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 17 Mar 2025 16:33:57 +0800 Subject: crypto: api - Ensure cra_type->destroy is done in process context Move the cra_type->destroy call out of crypto_alg_put and into crypto_unregister_alg and crypto_free_instance. This ensures that it's always done in process context so calls such as flush_work can be done. Signed-off-by: Herbert Xu --- crypto/api.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'crypto/api.c') diff --git a/crypto/api.c b/crypto/api.c index 3416e98128a059..2880aa04bb9930 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -703,15 +703,5 @@ void crypto_req_done(void *data, int err) } EXPORT_SYMBOL_GPL(crypto_req_done); -void crypto_destroy_alg(struct crypto_alg *alg) -{ - if (alg->cra_type && alg->cra_type->destroy) - alg->cra_type->destroy(alg); - - if (alg->cra_destroy) - alg->cra_destroy(alg); -} -EXPORT_SYMBOL_GPL(crypto_destroy_alg); - MODULE_DESCRIPTION("Cryptographic core API"); MODULE_LICENSE("GPL"); -- cgit 1.2.3-korg From f1440a90465bea1993f937ac7add592ce1e4ff44 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 12 Apr 2025 13:16:43 +0800 Subject: crypto: api - Add support for duplicating algorithms before registration If the bit CRYPTO_ALG_DUP_FIRST is set, an algorithm will be duplicated by kmemdup before registration. This is inteded for hardware-based algorithms that may be unplugged at will. Do not use this if the algorithm data structure is embedded in a bigger data structure. Perform the duplication in the driver instead. Signed-off-by: Herbert Xu --- crypto/acompress.c | 1 + crypto/aead.c | 1 + crypto/ahash.c | 1 + crypto/akcipher.c | 1 + crypto/algapi.c | 41 ++++++++++++++++++++++++++++------------- crypto/api.c | 9 +++++++++ crypto/internal.h | 5 ++++- crypto/kpp.c | 1 + crypto/lskcipher.c | 1 + crypto/rng.c | 1 + crypto/scompress.c | 1 + crypto/shash.c | 1 + crypto/sig.c | 1 + crypto/skcipher.c | 1 + include/linux/crypto.h | 9 +++++++++ 15 files changed, 61 insertions(+), 14 deletions(-) (limited to 'crypto/api.c') diff --git a/crypto/acompress.c b/crypto/acompress.c index d5605b0ad2664d..606d09a7fbfd24 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -150,6 +150,7 @@ static const struct crypto_type crypto_acomp_type = { .maskset = CRYPTO_ALG_TYPE_ACOMPRESS_MASK, .type = CRYPTO_ALG_TYPE_ACOMPRESS, .tfmsize = offsetof(struct crypto_acomp, base), + .algsize = offsetof(struct acomp_alg, base), }; struct crypto_acomp *crypto_alloc_acomp(const char *alg_name, u32 type, diff --git a/crypto/aead.c b/crypto/aead.c index 12f5b42171af35..5d14b775036eeb 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -186,6 +186,7 @@ static const struct crypto_type crypto_aead_type = { .maskset = CRYPTO_ALG_TYPE_MASK, .type = CRYPTO_ALG_TYPE_AEAD, .tfmsize = offsetof(struct crypto_aead, base), + .algsize = offsetof(struct aead_alg, base), }; int crypto_grab_aead(struct crypto_aead_spawn *spawn, diff --git a/crypto/ahash.c b/crypto/ahash.c index ba0a639144af75..7c9c0931197f74 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -792,6 +792,7 @@ static const struct crypto_type crypto_ahash_type = { .maskset = CRYPTO_ALG_TYPE_AHASH_MASK, .type = CRYPTO_ALG_TYPE_AHASH, .tfmsize = offsetof(struct crypto_ahash, base), + .algsize = offsetof(struct ahash_alg, halg.base), }; int crypto_grab_ahash(struct crypto_ahash_spawn *spawn, diff --git a/crypto/akcipher.c b/crypto/akcipher.c index 72c82d9aa07789..a36f50c8382787 100644 --- a/crypto/akcipher.c +++ b/crypto/akcipher.c @@ -97,6 +97,7 @@ static const struct crypto_type crypto_akcipher_type = { .maskset = CRYPTO_ALG_TYPE_AHASH_MASK, .type = CRYPTO_ALG_TYPE_AKCIPHER, .tfmsize = offsetof(struct crypto_akcipher, base), + .algsize = offsetof(struct akcipher_alg, base), }; int crypto_grab_akcipher(struct crypto_akcipher_spawn *spawn, diff --git a/crypto/algapi.c b/crypto/algapi.c index f368c0dc0d6d22..532d3efc3c7d00 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -66,13 +66,7 @@ static int crypto_check_alg(struct crypto_alg *alg) static void crypto_free_instance(struct crypto_instance *inst) { - struct crypto_alg *alg = &inst->alg; - const struct crypto_type *type; - - type = alg->cra_type; - if (type->destroy) - type->destroy(alg); - type->free(inst); + inst->alg.cra_type->free(inst); } static void crypto_destroy_instance_workfn(struct work_struct *w) @@ -424,6 +418,15 @@ void crypto_remove_final(struct list_head *list) } EXPORT_SYMBOL_GPL(crypto_remove_final); +static void crypto_free_alg(struct crypto_alg *alg) +{ + unsigned int algsize = alg->cra_type->algsize; + u8 *p = (u8 *)alg - algsize; + + crypto_destroy_alg(alg); + kfree(p); +} + int crypto_register_alg(struct crypto_alg *alg) { struct crypto_larval *larval; @@ -436,6 +439,19 @@ int crypto_register_alg(struct crypto_alg *alg) if (err) return err; + if (alg->cra_flags & CRYPTO_ALG_DUP_FIRST && + !WARN_ON_ONCE(alg->cra_destroy)) { + unsigned int algsize = alg->cra_type->algsize; + u8 *p = (u8 *)alg - algsize; + + p = kmemdup(p, algsize + sizeof(*alg), GFP_KERNEL); + if (!p) + return -ENOMEM; + + alg = (void *)(p + algsize); + alg->cra_destroy = crypto_free_alg; + } + down_write(&crypto_alg_sem); larval = __crypto_register_alg(alg, &algs_to_put); if (!IS_ERR_OR_NULL(larval)) { @@ -444,8 +460,10 @@ int crypto_register_alg(struct crypto_alg *alg) } up_write(&crypto_alg_sem); - if (IS_ERR(larval)) + if (IS_ERR(larval)) { + crypto_alg_put(alg); return PTR_ERR(larval); + } if (test_started) crypto_schedule_test(larval); @@ -481,12 +499,9 @@ void crypto_unregister_alg(struct crypto_alg *alg) if (WARN(ret, "Algorithm %s is not registered", alg->cra_driver_name)) return; - if (alg->cra_destroy) - crypto_alg_put(alg); - else if (!WARN_ON(refcount_read(&alg->cra_refcnt) != 1) && - alg->cra_type && alg->cra_type->destroy) - alg->cra_type->destroy(alg); + WARN_ON(!alg->cra_destroy && refcount_read(&alg->cra_refcnt) != 1); + list_add(&alg->cra_list, &list); crypto_remove_final(&list); } EXPORT_SYMBOL_GPL(crypto_unregister_alg); diff --git a/crypto/api.c b/crypto/api.c index 2880aa04bb9930..e427cc5662b5e5 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -703,5 +703,14 @@ void crypto_req_done(void *data, int err) } EXPORT_SYMBOL_GPL(crypto_req_done); +void crypto_destroy_alg(struct crypto_alg *alg) +{ + if (alg->cra_type && alg->cra_type->destroy) + alg->cra_type->destroy(alg); + if (alg->cra_destroy) + alg->cra_destroy(alg); +} +EXPORT_SYMBOL_GPL(crypto_destroy_alg); + MODULE_DESCRIPTION("Cryptographic core API"); MODULE_LICENSE("GPL"); diff --git a/crypto/internal.h b/crypto/internal.h index 2edefb546ad405..2ed79bf208ca28 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -46,6 +46,7 @@ struct crypto_type { unsigned int maskclear; unsigned int maskset; unsigned int tfmsize; + unsigned int algsize; }; enum { @@ -162,10 +163,12 @@ static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg) return alg; } +void crypto_destroy_alg(struct crypto_alg *alg); + static inline void crypto_alg_put(struct crypto_alg *alg) { if (refcount_dec_and_test(&alg->cra_refcnt)) - alg->cra_destroy(alg); + crypto_destroy_alg(alg); } static inline int crypto_tmpl_get(struct crypto_template *tmpl) diff --git a/crypto/kpp.c b/crypto/kpp.c index ecc63a1a948dfe..2e0cefe7a25f54 100644 --- a/crypto/kpp.c +++ b/crypto/kpp.c @@ -80,6 +80,7 @@ static const struct crypto_type crypto_kpp_type = { .maskset = CRYPTO_ALG_TYPE_MASK, .type = CRYPTO_ALG_TYPE_KPP, .tfmsize = offsetof(struct crypto_kpp, base), + .algsize = offsetof(struct kpp_alg, base), }; struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask) diff --git a/crypto/lskcipher.c b/crypto/lskcipher.c index cdb4897c63e6f9..c2e2c38b5aa8d8 100644 --- a/crypto/lskcipher.c +++ b/crypto/lskcipher.c @@ -294,6 +294,7 @@ static const struct crypto_type crypto_lskcipher_type = { .maskset = CRYPTO_ALG_TYPE_MASK, .type = CRYPTO_ALG_TYPE_LSKCIPHER, .tfmsize = offsetof(struct crypto_lskcipher, base), + .algsize = offsetof(struct lskcipher_alg, co.base), }; static void crypto_lskcipher_exit_tfm_sg(struct crypto_tfm *tfm) diff --git a/crypto/rng.c b/crypto/rng.c index 9d8804e464226d..b8ae6ebc091dd5 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -98,6 +98,7 @@ static const struct crypto_type crypto_rng_type = { .maskset = CRYPTO_ALG_TYPE_MASK, .type = CRYPTO_ALG_TYPE_RNG, .tfmsize = offsetof(struct crypto_rng, base), + .algsize = offsetof(struct rng_alg, base), }; struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask) diff --git a/crypto/scompress.c b/crypto/scompress.c index c330b81bc5a6bf..f7ce29b4cdb8d5 100644 --- a/crypto/scompress.c +++ b/crypto/scompress.c @@ -347,6 +347,7 @@ static const struct crypto_type crypto_scomp_type = { .maskset = CRYPTO_ALG_TYPE_MASK, .type = CRYPTO_ALG_TYPE_SCOMPRESS, .tfmsize = offsetof(struct crypto_scomp, base), + .algsize = offsetof(struct scomp_alg, base), }; static void scomp_prepare_alg(struct scomp_alg *alg) diff --git a/crypto/shash.c b/crypto/shash.c index 301ab42bf84991..a2a7d660917234 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -227,6 +227,7 @@ const struct crypto_type crypto_shash_type = { .maskset = CRYPTO_ALG_TYPE_MASK, .type = CRYPTO_ALG_TYPE_SHASH, .tfmsize = offsetof(struct crypto_shash, base), + .algsize = offsetof(struct shash_alg, base), }; int crypto_grab_shash(struct crypto_shash_spawn *spawn, diff --git a/crypto/sig.c b/crypto/sig.c index 53a3dd6fbe3fe6..beba745b640575 100644 --- a/crypto/sig.c +++ b/crypto/sig.c @@ -74,6 +74,7 @@ static const struct crypto_type crypto_sig_type = { .maskset = CRYPTO_ALG_TYPE_MASK, .type = CRYPTO_ALG_TYPE_SIG, .tfmsize = offsetof(struct crypto_sig, base), + .algsize = offsetof(struct sig_alg, base), }; struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask) diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 132075a905d99a..319215cfded56c 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -620,6 +620,7 @@ static const struct crypto_type crypto_skcipher_type = { .maskset = CRYPTO_ALG_TYPE_SKCIPHER_MASK, .type = CRYPTO_ALG_TYPE_SKCIPHER, .tfmsize = offsetof(struct crypto_skcipher, base), + .algsize = offsetof(struct skcipher_alg, base), }; int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 15476b085ce3ee..b89b1b348095ff 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -49,6 +49,15 @@ */ #define CRYPTO_ALG_NEED_FALLBACK 0x00000100 +/* + * Set if the algorithm data structure should be duplicated into + * kmalloc memory before registration. This is useful for hardware + * that can be disconnected at will. Do not use this if the data + * structure is embedded into a bigger one. Duplicate the overall + * data structure in the driver in that case. + */ +#define CRYPTO_ALG_DUP_FIRST 0x00000200 + /* * Set if the algorithm has passed automated run-time testing. Note that * if there is no run-time testing for a given algorithm it is considered -- cgit 1.2.3-korg From 19da081a28c95fe9b03ce952a2bf4a6f6bf5112c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 23 Apr 2025 17:22:28 +0800 Subject: crypto: api - Add crypto_request_clone and fb Add a helper to clone crypto requests and eliminate code duplication. Use kmemdup in the helper. Also add an fb field to crypto_tfm. This also happens to fix the existing implementations which were buggy. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202504230118.1CxUaUoX-lkp@intel.com/ Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202504230004.c7mrY0C6-lkp@intel.com/ Signed-off-by: Herbert Xu --- crypto/acompress.c | 29 +++-------------------------- crypto/ahash.c | 32 +++++--------------------------- crypto/api.c | 18 ++++++++++++++++++ include/crypto/acompress.h | 9 ++++++--- include/crypto/hash.h | 9 ++++++--- include/crypto/internal/acompress.h | 7 ++++++- include/crypto/internal/hash.h | 7 ++++++- include/linux/crypto.h | 11 ++++++++--- 8 files changed, 58 insertions(+), 64 deletions(-) (limited to 'crypto/api.c') diff --git a/crypto/acompress.c b/crypto/acompress.c index 4c665c6fb5d631..9dea76ed451358 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -11,15 +11,13 @@ #include #include #include -#include +#include #include #include -#include #include #include #include #include -#include #include #include #include @@ -79,7 +77,7 @@ static void crypto_acomp_exit_tfm(struct crypto_tfm *tfm) alg->exit(acomp); if (acomp_is_async(acomp)) - crypto_free_acomp(acomp->fb); + crypto_free_acomp(crypto_acomp_fb(acomp)); } static int crypto_acomp_init_tfm(struct crypto_tfm *tfm) @@ -89,8 +87,6 @@ static int crypto_acomp_init_tfm(struct crypto_tfm *tfm) struct crypto_acomp *fb = NULL; int err; - acomp->fb = acomp; - if (tfm->__crt_alg->cra_type != &crypto_acomp_type) return crypto_init_scomp_ops_async(tfm); @@ -104,7 +100,7 @@ static int crypto_acomp_init_tfm(struct crypto_tfm *tfm) if (crypto_acomp_reqsize(fb) > MAX_SYNC_COMP_REQSIZE) goto out_free_fb; - acomp->fb = fb; + tfm->fb = crypto_acomp_tfm(fb); } acomp->compress = alg->compress; @@ -570,24 +566,5 @@ int acomp_walk_virt(struct acomp_walk *__restrict walk, } EXPORT_SYMBOL_GPL(acomp_walk_virt); -struct acomp_req *acomp_request_clone(struct acomp_req *req, - size_t total, gfp_t gfp) -{ - struct crypto_acomp *tfm = crypto_acomp_reqtfm(req); - struct acomp_req *nreq; - - nreq = kmalloc(total, gfp); - if (!nreq) { - acomp_request_set_tfm(req, tfm->fb); - req->base.flags = CRYPTO_TFM_REQ_ON_STACK; - return req; - } - - memcpy(nreq, req, total); - acomp_request_set_tfm(req, tfm); - return req; -} -EXPORT_SYMBOL_GPL(acomp_request_clone); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Asynchronous compression type"); diff --git a/crypto/ahash.c b/crypto/ahash.c index 7a74092323b901..9b813f7b9177db 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -12,13 +12,11 @@ * Copyright (c) 2008 Loc Ho */ -#include #include #include #include #include #include -#include #include #include #include @@ -301,7 +299,8 @@ int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, err = alg->setkey(tfm, key, keylen); if (!err && ahash_is_async(tfm)) - err = crypto_ahash_setkey(tfm->fb, key, keylen); + err = crypto_ahash_setkey(crypto_ahash_fb(tfm), + key, keylen); if (unlikely(err)) { ahash_set_needkey(tfm, alg); return err; @@ -732,7 +731,7 @@ static void crypto_ahash_exit_tfm(struct crypto_tfm *tfm) tfm->__crt_alg->cra_exit(tfm); if (ahash_is_async(hash)) - crypto_free_ahash(hash->fb); + crypto_free_ahash(crypto_ahash_fb(hash)); } static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) @@ -745,8 +744,6 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) crypto_ahash_set_statesize(hash, alg->halg.statesize); crypto_ahash_set_reqsize(hash, crypto_tfm_alg_reqsize(tfm)); - hash->fb = hash; - if (tfm->__crt_alg->cra_type == &crypto_shash_type) return crypto_init_ahash_using_shash(tfm); @@ -756,7 +753,7 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) if (IS_ERR(fb)) return PTR_ERR(fb); - hash->fb = fb; + tfm->fb = crypto_ahash_tfm(fb); } ahash_set_needkey(hash, alg); @@ -1036,7 +1033,7 @@ EXPORT_SYMBOL_GPL(ahash_request_free); int crypto_hash_digest(struct crypto_ahash *tfm, const u8 *data, unsigned int len, u8 *out) { - HASH_REQUEST_ON_STACK(req, tfm->fb); + HASH_REQUEST_ON_STACK(req, crypto_ahash_fb(tfm)); int err; ahash_request_set_callback(req, 0, NULL, NULL); @@ -1049,24 +1046,5 @@ int crypto_hash_digest(struct crypto_ahash *tfm, const u8 *data, } EXPORT_SYMBOL_GPL(crypto_hash_digest); -struct ahash_request *ahash_request_clone(struct ahash_request *req, - size_t total, gfp_t gfp) -{ - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct ahash_request *nreq; - - nreq = kmalloc(total, gfp); - if (!nreq) { - ahash_request_set_tfm(req, tfm->fb); - req->base.flags = CRYPTO_TFM_REQ_ON_STACK; - return req; - } - - memcpy(nreq, req, total); - ahash_request_set_tfm(req, tfm); - return req; -} -EXPORT_SYMBOL_GPL(ahash_request_clone); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Asynchronous cryptographic hash type"); diff --git a/crypto/api.c b/crypto/api.c index e427cc5662b5e5..172e82f79c69a7 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -528,6 +528,7 @@ void *crypto_create_tfm_node(struct crypto_alg *alg, goto out; tfm = (struct crypto_tfm *)(mem + frontend->tfmsize); + tfm->fb = tfm; err = frontend->init_tfm(tfm); if (err) @@ -712,5 +713,22 @@ void crypto_destroy_alg(struct crypto_alg *alg) } EXPORT_SYMBOL_GPL(crypto_destroy_alg); +struct crypto_async_request *crypto_request_clone( + struct crypto_async_request *req, size_t total, gfp_t gfp) +{ + struct crypto_tfm *tfm = req->tfm; + struct crypto_async_request *nreq; + + nreq = kmemdup(req, total, gfp); + if (!nreq) { + req->tfm = tfm->fb; + return req; + } + + nreq->flags &= ~CRYPTO_TFM_REQ_ON_STACK; + return nreq; +} +EXPORT_SYMBOL_GPL(crypto_request_clone); + MODULE_DESCRIPTION("Cryptographic core API"); MODULE_LICENSE("GPL"); diff --git a/include/crypto/acompress.h b/include/crypto/acompress.h index 1b30290d63805d..933c48a4855bca 100644 --- a/include/crypto/acompress.h +++ b/include/crypto/acompress.h @@ -114,7 +114,6 @@ struct crypto_acomp { int (*compress)(struct acomp_req *req); int (*decompress)(struct acomp_req *req); unsigned int reqsize; - struct crypto_acomp *fb; struct crypto_tfm base; }; @@ -553,7 +552,11 @@ static inline struct acomp_req *acomp_request_on_stack_init( return req; } -struct acomp_req *acomp_request_clone(struct acomp_req *req, - size_t total, gfp_t gfp); +static inline struct acomp_req *acomp_request_clone(struct acomp_req *req, + size_t total, gfp_t gfp) +{ + return container_of(crypto_request_clone(&req->base, total, gfp), + struct acomp_req, base); +} #endif diff --git a/include/crypto/hash.h b/include/crypto/hash.h index 5f87d1040a7c78..68813a83443bcd 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -246,7 +246,6 @@ struct crypto_ahash { bool using_shash; /* Underlying algorithm is shash, not ahash */ unsigned int statesize; unsigned int reqsize; - struct crypto_ahash *fb; struct crypto_tfm base; }; @@ -1035,7 +1034,11 @@ static inline struct ahash_request *ahash_request_on_stack_init( return req; } -struct ahash_request *ahash_request_clone(struct ahash_request *req, - size_t total, gfp_t gfp); +static inline struct ahash_request *ahash_request_clone( + struct ahash_request *req, size_t total, gfp_t gfp) +{ + return container_of(crypto_request_clone(&req->base, total, gfp), + struct ahash_request, base); +} #endif /* _CRYPTO_HASH_H */ diff --git a/include/crypto/internal/acompress.h b/include/crypto/internal/acompress.h index 7eda3261902444..6550dad18e0fbb 100644 --- a/include/crypto/internal/acompress.h +++ b/include/crypto/internal/acompress.h @@ -220,13 +220,18 @@ static inline u32 acomp_request_flags(struct acomp_req *req) return crypto_request_flags(&req->base) & ~CRYPTO_ACOMP_REQ_PRIVATE; } +static inline struct crypto_acomp *crypto_acomp_fb(struct crypto_acomp *tfm) +{ + return __crypto_acomp_tfm(crypto_acomp_tfm(tfm)->fb); +} + static inline struct acomp_req *acomp_fbreq_on_stack_init( char *buf, struct acomp_req *old) { struct crypto_acomp *tfm = crypto_acomp_reqtfm(old); struct acomp_req *req = (void *)buf; - acomp_request_set_tfm(req, tfm->fb); + acomp_request_set_tfm(req, crypto_acomp_fb(tfm)); req->base.flags = CRYPTO_TFM_REQ_ON_STACK; acomp_request_set_callback(req, acomp_request_flags(old), NULL, NULL); req->base.flags &= ~CRYPTO_ACOMP_REQ_PRIVATE; diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h index 1e80dd084a231a..0bc0fefc9b3c73 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -272,13 +272,18 @@ static inline bool crypto_ahash_req_chain(struct crypto_ahash *tfm) return crypto_tfm_req_chain(&tfm->base); } +static inline struct crypto_ahash *crypto_ahash_fb(struct crypto_ahash *tfm) +{ + return __crypto_ahash_cast(crypto_ahash_tfm(tfm)->fb); +} + static inline struct ahash_request *ahash_fbreq_on_stack_init( char *buf, struct ahash_request *old) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(old); struct ahash_request *req = (void *)buf; - ahash_request_set_tfm(req, tfm->fb); + ahash_request_set_tfm(req, crypto_ahash_fb(tfm)); req->base.flags = CRYPTO_TFM_REQ_ON_STACK; ahash_request_set_callback(req, ahash_request_flags(old), NULL, NULL); req->base.flags &= ~CRYPTO_AHASH_REQ_PRIVATE; diff --git a/include/linux/crypto.h b/include/linux/crypto.h index f691ce01745eeb..fe75320ff9a35c 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include @@ -411,9 +411,11 @@ struct crypto_tfm { u32 crt_flags; int node; - + + struct crypto_tfm *fb; + void (*exit)(struct crypto_tfm *tfm); - + struct crypto_alg *__crt_alg; void *__crt_ctx[] CRYPTO_MINALIGN_ATTR; @@ -509,5 +511,8 @@ static inline void crypto_request_set_tfm(struct crypto_async_request *req, req->flags &= ~CRYPTO_TFM_REQ_ON_STACK; } +struct crypto_async_request *crypto_request_clone( + struct crypto_async_request *req, size_t total, gfp_t gfp); + #endif /* _LINUX_CRYPTO_H */ -- cgit 1.2.3-korg From 2cfe41630a1a4f24d46825aa9656a51a38fb7f7d Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 23 Apr 2025 17:22:31 +0800 Subject: crypto: hash - Fix clone error handling Do not copy the exit function in crypto_clone_tfm as it should only be set after init_tfm or clone_tfm has succeeded. Move the setting into crypto_clone_ahash and crypto_clone_shash instead. Also clone the fb if necessary. Signed-off-by: Herbert Xu --- crypto/ahash.c | 19 +++++++++++++++++-- crypto/api.c | 2 +- crypto/shash.c | 3 +++ 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'crypto/api.c') diff --git a/crypto/ahash.c b/crypto/ahash.c index 9b813f7b9177db..cc9885d5cfd265 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -877,6 +877,7 @@ struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash) { struct hash_alg_common *halg = crypto_hash_alg_common(hash); struct crypto_tfm *tfm = crypto_ahash_tfm(hash); + struct crypto_ahash *fb = NULL; struct crypto_ahash *nhash; struct ahash_alg *alg; int err; @@ -906,22 +907,36 @@ struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash) err = PTR_ERR(shash); goto out_free_nhash; } + crypto_ahash_tfm(nhash)->exit = crypto_exit_ahash_using_shash; nhash->using_shash = true; *nctx = shash; return nhash; } + if (ahash_is_async(hash)) { + fb = crypto_clone_ahash(crypto_ahash_fb(hash)); + err = PTR_ERR(fb); + if (IS_ERR(fb)) + goto out_free_nhash; + + crypto_ahash_tfm(nhash)->fb = crypto_ahash_tfm(fb); + } + err = -ENOSYS; alg = crypto_ahash_alg(hash); if (!alg->clone_tfm) - goto out_free_nhash; + goto out_free_fb; err = alg->clone_tfm(nhash, hash); if (err) - goto out_free_nhash; + goto out_free_fb; + + crypto_ahash_tfm(nhash)->exit = crypto_ahash_exit_tfm; return nhash; +out_free_fb: + crypto_free_ahash(fb); out_free_nhash: crypto_free_ahash(nhash); return ERR_PTR(err); diff --git a/crypto/api.c b/crypto/api.c index 172e82f79c69a7..5cd5ec105bb142 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -570,7 +570,7 @@ void *crypto_clone_tfm(const struct crypto_type *frontend, tfm = (struct crypto_tfm *)(mem + frontend->tfmsize); tfm->crt_flags = otfm->crt_flags; - tfm->exit = otfm->exit; + tfm->fb = tfm; out: return mem; diff --git a/crypto/shash.c b/crypto/shash.c index b6c79a4a044a15..c4a724e55d7a69 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -413,6 +413,9 @@ struct crypto_shash *crypto_clone_shash(struct crypto_shash *hash) } } + if (alg->exit_tfm) + crypto_shash_tfm(nhash)->exit = crypto_shash_exit_tfm; + return nhash; } EXPORT_SYMBOL_GPL(crypto_clone_shash); -- cgit 1.2.3-korg From 40b9969796bfa49ed1b0f7ddc254f48cb2ac6d2c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 5 May 2025 13:33:41 -0700 Subject: crypto: testmgr - replace CRYPTO_MANAGER_DISABLE_TESTS with CRYPTO_SELFTESTS The negative-sense of CRYPTO_MANAGER_DISABLE_TESTS is a longstanding mistake that regularly causes confusion. Especially bad is that you can have CRYPTO=n && CRYPTO_MANAGER_DISABLE_TESTS=n, which is ambiguous. Replace CRYPTO_MANAGER_DISABLE_TESTS with CRYPTO_SELFTESTS which has the expected behavior. The tests continue to be disabled by default. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- arch/arm/configs/milbeaut_m10v_defconfig | 2 +- arch/loongarch/configs/loongson3_defconfig | 2 +- arch/s390/configs/debug_defconfig | 2 +- arch/s390/configs/defconfig | 2 +- crypto/Kconfig | 24 +++++++++++++++--------- crypto/algapi.c | 4 ++-- crypto/algboss.c | 2 +- crypto/api.c | 3 +-- crypto/hkdf.c | 2 +- crypto/internal.h | 5 ++--- crypto/kdf_sp800108.c | 2 +- crypto/testmgr.c | 12 ++++++------ lib/crypto/Makefile | 9 +++------ lib/crypto/aescfb.c | 2 +- lib/crypto/aesgcm.c | 2 +- lib/crypto/blake2s.c | 2 +- lib/crypto/chacha20poly1305.c | 2 +- lib/crypto/curve25519.c | 2 +- 18 files changed, 41 insertions(+), 40 deletions(-) (limited to 'crypto/api.c') diff --git a/arch/arm/configs/milbeaut_m10v_defconfig b/arch/arm/configs/milbeaut_m10v_defconfig index 4ec21f477c633a..9dd47e1d90bb2f 100644 --- a/arch/arm/configs/milbeaut_m10v_defconfig +++ b/arch/arm/configs/milbeaut_m10v_defconfig @@ -94,7 +94,7 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y CONFIG_KEYS=y CONFIG_CRYPTO_MANAGER=y -# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +CONFIG_CRYPTO_SELFTESTS=y # CONFIG_CRYPTO_ECHAINIV is not set CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_SEQIV=m diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig index 90f21dfe22b13a..0d59af6007b7aa 100644 --- a/arch/loongarch/configs/loongson3_defconfig +++ b/arch/loongarch/configs/loongson3_defconfig @@ -1026,7 +1026,7 @@ CONFIG_SECURITY_APPARMOR=y CONFIG_SECURITY_YAMA=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_CRYPTO_USER=m -# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +CONFIG_CRYPTO_SELFTESTS=y CONFIG_CRYPTO_PCRYPT=m CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_ANUBIS=m diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index e6f7c8f4ee8b8d..bc960b1eabaef6 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -743,7 +743,7 @@ CONFIG_IMA_WRITE_POLICY=y CONFIG_IMA_APPRAISE=y CONFIG_BUG_ON_DATA_CORRUPTION=y CONFIG_CRYPTO_USER=m -# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +CONFIG_CRYPTO_SELFTESTS=y CONFIG_CRYPTO_PCRYPT=m CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_BENCHMARK=m diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index 7495bf8e483c6c..fda2f264e7d38c 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -729,7 +729,7 @@ CONFIG_IMA_APPRAISE=y CONFIG_BUG_ON_DATA_CORRUPTION=y CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_USER=m -# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +CONFIG_CRYPTO_SELFTESTS=y CONFIG_CRYPTO_PCRYPT=m CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_BENCHMARK=m diff --git a/crypto/Kconfig b/crypto/Kconfig index 08af9de30ff06a..d326d3c5544fcd 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -25,7 +25,7 @@ menu "Crypto core or helper" config CRYPTO_FIPS bool "FIPS 200 compliance" - depends on (CRYPTO_ANSI_CPRNG || CRYPTO_DRBG) && !CRYPTO_MANAGER_DISABLE_TESTS + depends on (CRYPTO_ANSI_CPRNG || CRYPTO_DRBG) && CRYPTO_SELFTESTS depends on (MODULE_SIG || !MODULES) help This option enables the fips boot option which is @@ -143,8 +143,8 @@ config CRYPTO_ACOMP config CRYPTO_HKDF tristate - select CRYPTO_SHA256 if !CONFIG_CRYPTO_MANAGER_DISABLE_TESTS - select CRYPTO_SHA512 if !CONFIG_CRYPTO_MANAGER_DISABLE_TESTS + select CRYPTO_SHA256 if CRYPTO_SELFTESTS + select CRYPTO_SHA512 if CRYPTO_SELFTESTS select CRYPTO_HASH2 config CRYPTO_MANAGER @@ -173,16 +173,22 @@ config CRYPTO_USER Userspace configuration for cryptographic instantiations such as cbc(aes). -config CRYPTO_MANAGER_DISABLE_TESTS - bool "Disable run-time self tests" - default y +config CRYPTO_SELFTESTS + bool "Enable cryptographic self-tests" + depends on DEBUG_KERNEL help - Disable run-time self tests that normally take place at - algorithm registration. + Enable the cryptographic self-tests. + + The cryptographic self-tests run at boot time, or at algorithm + registration time if algorithms are dynamically loaded later. + + This is primarily intended for developer use. It should not be + enabled in production kernels, unless you are trying to use these + tests to fulfill a FIPS testing requirement. config CRYPTO_MANAGER_EXTRA_TESTS bool "Enable extra run-time crypto self tests" - depends on DEBUG_KERNEL && !CRYPTO_MANAGER_DISABLE_TESTS && CRYPTO_MANAGER + depends on DEBUG_KERNEL && CRYPTO_SELFTESTS && CRYPTO_MANAGER help Enable extra run-time self tests of registered crypto algorithms, including randomized fuzz tests. diff --git a/crypto/algapi.c b/crypto/algapi.c index 532d3efc3c7d00..9030a30c89e84a 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -275,7 +275,7 @@ static struct crypto_larval *crypto_alloc_test_larval(struct crypto_alg *alg) struct crypto_larval *larval; if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER) || - IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) || + !IS_ENABLED(CONFIG_CRYPTO_SELFTESTS) || (alg->cra_flags & CRYPTO_ALG_INTERNAL)) return NULL; /* No self-test needed */ @@ -1059,7 +1059,7 @@ static void __init crypto_start_tests(void) if (!IS_BUILTIN(CONFIG_CRYPTO_ALGAPI)) return; - if (IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)) + if (!IS_ENABLED(CONFIG_CRYPTO_SELFTESTS)) return; set_crypto_boot_test_finished(); diff --git a/crypto/algboss.c b/crypto/algboss.c index ef5c73780fc78c..846f586889ee44 100644 --- a/crypto/algboss.c +++ b/crypto/algboss.c @@ -189,7 +189,7 @@ static int cryptomgr_schedule_test(struct crypto_alg *alg) struct task_struct *thread; struct crypto_test_param *param; - if (IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)) + if (!IS_ENABLED(CONFIG_CRYPTO_SELFTESTS)) return NOTIFY_DONE; if (!try_module_get(THIS_MODULE)) diff --git a/crypto/api.c b/crypto/api.c index 5cd5ec105bb142..133d9b62692272 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -31,8 +31,7 @@ EXPORT_SYMBOL_GPL(crypto_alg_sem); BLOCKING_NOTIFIER_HEAD(crypto_chain); EXPORT_SYMBOL_GPL(crypto_chain); -#if IS_BUILTIN(CONFIG_CRYPTO_ALGAPI) && \ - !IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) +#if IS_BUILTIN(CONFIG_CRYPTO_ALGAPI) && IS_ENABLED(CONFIG_CRYPTO_SELFTESTS) DEFINE_STATIC_KEY_FALSE(__crypto_boot_test_finished); #endif diff --git a/crypto/hkdf.c b/crypto/hkdf.c index 2434c5c425456c..f24c2a8d4df99a 100644 --- a/crypto/hkdf.c +++ b/crypto/hkdf.c @@ -543,7 +543,7 @@ static int __init crypto_hkdf_module_init(void) { int ret = 0, i; - if (IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)) + if (!IS_ENABLED(CONFIG_CRYPTO_SELFTESTS)) return 0; for (i = 0; i < ARRAY_SIZE(hkdf_sha256_tv); i++) { diff --git a/crypto/internal.h b/crypto/internal.h index 2ed79bf208ca28..b9afd68767c199 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -67,8 +67,7 @@ extern struct blocking_notifier_head crypto_chain; int alg_test(const char *driver, const char *alg, u32 type, u32 mask); -#if !IS_BUILTIN(CONFIG_CRYPTO_ALGAPI) || \ - IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) +#if !IS_BUILTIN(CONFIG_CRYPTO_ALGAPI) || !IS_ENABLED(CONFIG_CRYPTO_SELFTESTS) static inline bool crypto_boot_test_finished(void) { return true; @@ -87,7 +86,7 @@ static inline void set_crypto_boot_test_finished(void) static_branch_enable(&__crypto_boot_test_finished); } #endif /* !IS_BUILTIN(CONFIG_CRYPTO_ALGAPI) || - * IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) + * !IS_ENABLED(CONFIG_CRYPTO_SELFTESTS) */ #ifdef CONFIG_PROC_FS diff --git a/crypto/kdf_sp800108.c b/crypto/kdf_sp800108.c index c3f9938e1ad27f..b7a6bf9da773a7 100644 --- a/crypto/kdf_sp800108.c +++ b/crypto/kdf_sp800108.c @@ -127,7 +127,7 @@ static int __init crypto_kdf108_init(void) { int ret; - if (IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS)) + if (!IS_ENABLED(CONFIG_CRYPTO_SELFTESTS)) return 0; ret = kdf_test(&kdf_ctr_hmac_sha256_tv_template[0], "hmac(sha256)", diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 1c71616ae2cfa4..3a624c9b552595 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -55,7 +55,7 @@ module_param(fuzz_iterations, uint, 0644); MODULE_PARM_DESC(fuzz_iterations, "number of fuzz test iterations"); #endif -#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS +#ifndef CONFIG_CRYPTO_SELFTESTS /* a perfect nop */ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) @@ -321,10 +321,10 @@ struct testvec_config { /* * The following are the lists of testvec_configs to test for each algorithm - * type when the basic crypto self-tests are enabled, i.e. when - * CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is unset. They aim to provide good test - * coverage, while keeping the test time much shorter than the full fuzz tests - * so that the basic tests can be enabled in a wider range of circumstances. + * type when the basic crypto self-tests are enabled. They aim to provide good + * test coverage, while keeping the test time much shorter than the full fuzz + * tests so that the basic tests can be enabled in a wider range of + * circumstances. */ /* Configs for skciphers and aeads */ @@ -5899,6 +5899,6 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) return alg_fips_disabled(driver, alg); } -#endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */ +#endif /* CONFIG_CRYPTO_SELFTESTS */ EXPORT_SYMBOL_GPL(alg_test); diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index ff4aa22e5ccc74..599e61375938b3 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -25,9 +25,11 @@ obj-$(CONFIG_CRYPTO_LIB_GF128MUL) += gf128mul.o obj-y += libblake2s.o libblake2s-y := blake2s.o libblake2s-$(CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC) += blake2s-generic.o +libblake2s-$(CONFIG_CRYPTO_SELFTESTS) += blake2s-selftest.o obj-$(CONFIG_CRYPTO_LIB_CHACHA20POLY1305) += libchacha20poly1305.o libchacha20poly1305-y += chacha20poly1305.o +libchacha20poly1305-$(CONFIG_CRYPTO_SELFTESTS) += chacha20poly1305-selftest.o obj-$(CONFIG_CRYPTO_LIB_CURVE25519_GENERIC) += libcurve25519-generic.o libcurve25519-generic-y := curve25519-fiat32.o @@ -36,6 +38,7 @@ libcurve25519-generic-y += curve25519-generic.o obj-$(CONFIG_CRYPTO_LIB_CURVE25519) += libcurve25519.o libcurve25519-y += curve25519.o +libcurve25519-$(CONFIG_CRYPTO_SELFTESTS) += curve25519-selftest.o obj-$(CONFIG_CRYPTO_LIB_DES) += libdes.o libdes-y := des.o @@ -57,12 +60,6 @@ libsha256-y := sha256.o obj-$(CONFIG_CRYPTO_LIB_SHA256_GENERIC) += libsha256-generic.o libsha256-generic-y := sha256-generic.o -ifneq ($(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS),y) -libblake2s-y += blake2s-selftest.o -libchacha20poly1305-y += chacha20poly1305-selftest.o -libcurve25519-y += curve25519-selftest.o -endif - obj-$(CONFIG_MPILIB) += mpi/ obj-$(CONFIG_CRYPTO_MANAGER_EXTRA_TESTS) += simd.o diff --git a/lib/crypto/aescfb.c b/lib/crypto/aescfb.c index 749dc1258a44b7..437613265e14ff 100644 --- a/lib/crypto/aescfb.c +++ b/lib/crypto/aescfb.c @@ -99,7 +99,7 @@ MODULE_DESCRIPTION("Generic AES-CFB library"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL"); -#ifndef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS +#ifdef CONFIG_CRYPTO_SELFTESTS /* * Test code below. Vectors taken from crypto/testmgr.h diff --git a/lib/crypto/aesgcm.c b/lib/crypto/aesgcm.c index 902e49410aaf75..277824d6b4af71 100644 --- a/lib/crypto/aesgcm.c +++ b/lib/crypto/aesgcm.c @@ -199,7 +199,7 @@ MODULE_DESCRIPTION("Generic AES-GCM library"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL"); -#ifndef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS +#ifdef CONFIG_CRYPTO_SELFTESTS /* * Test code below. Vectors taken from crypto/testmgr.h diff --git a/lib/crypto/blake2s.c b/lib/crypto/blake2s.c index 71a316552cc5f5..b0f9a678300b34 100644 --- a/lib/crypto/blake2s.c +++ b/lib/crypto/blake2s.c @@ -60,7 +60,7 @@ EXPORT_SYMBOL(blake2s_final); static int __init blake2s_mod_init(void) { - if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) && + if (IS_ENABLED(CONFIG_CRYPTO_SELFTESTS) && WARN_ON(!blake2s_selftest())) return -ENODEV; return 0; diff --git a/lib/crypto/chacha20poly1305.c b/lib/crypto/chacha20poly1305.c index fbd3690e253165..e29eed49a5a14e 100644 --- a/lib/crypto/chacha20poly1305.c +++ b/lib/crypto/chacha20poly1305.c @@ -358,7 +358,7 @@ EXPORT_SYMBOL(chacha20poly1305_decrypt_sg_inplace); static int __init chacha20poly1305_init(void) { - if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) && + if (IS_ENABLED(CONFIG_CRYPTO_SELFTESTS) && WARN_ON(!chacha20poly1305_selftest())) return -ENODEV; return 0; diff --git a/lib/crypto/curve25519.c b/lib/crypto/curve25519.c index 064b352c6907b1..6850b76a80c9e3 100644 --- a/lib/crypto/curve25519.c +++ b/lib/crypto/curve25519.c @@ -15,7 +15,7 @@ static int __init curve25519_init(void) { - if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) && + if (IS_ENABLED(CONFIG_CRYPTO_SELFTESTS) && WARN_ON(!curve25519_selftest())) return -ENODEV; return 0; -- cgit 1.2.3-korg From 0a3cf32da469ff1df6e016f5f82b439a63d14461 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 19 May 2025 18:29:38 +0800 Subject: crypto: api - Redo lookup on EEXIST When two crypto algorithm lookups occur at the same time with different names for the same algorithm, e.g., ctr(aes-generic) and ctr(aes), they will both be instantiated. However, only one of them can be registered. The second instantiation will fail with EEXIST. Avoid failing the second lookup by making it retry, but only once because there are tricky names such as gcm_base(ctr(aes),ghash) that will always fail, despite triggering instantiation and EEXIST. Reported-by: Ingo Franzki Fixes: 2825982d9d66 ("[CRYPTO] api: Added event notification") Signed-off-by: Herbert Xu --- crypto/api.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'crypto/api.c') diff --git a/crypto/api.c b/crypto/api.c index 133d9b62692272..5724d62e9d0780 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -219,10 +219,19 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg, if (crypto_is_test_larval(larval)) crypto_larval_kill(larval); alg = ERR_PTR(-ETIMEDOUT); - } else if (!alg) { + } else if (!alg || PTR_ERR(alg) == -EEXIST) { + int err = alg ? -EEXIST : -EAGAIN; + + /* + * EEXIST is expected because two probes can be scheduled + * at the same time with one using alg_name and the other + * using driver_name. Do a re-lookup but do not retry in + * case we hit a quirk like gcm_base(ctr(aes),...) which + * will never match. + */ alg = &larval->alg; alg = crypto_alg_lookup(alg->cra_name, type, mask) ?: - ERR_PTR(-EAGAIN); + ERR_PTR(err); } else if (IS_ERR(alg)) ; else if (crypto_is_test_larval(larval) && -- cgit 1.2.3-korg