From ba16486d79d44e3d07c713ff566be156292ed744 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 4 Jun 2026 10:21:17 +0800 Subject: [PATCH 001/122] rhashtable: Add workqueue/irq_work header inclusions Add inclusions for irq_work.h and workqueue.h to rhashtable.c rather than relying on indirect inclusions from elsewhere. Remove workqueue.h from rhashtable.h now that it uses IRQ work only. Signed-off-by: Herbert Xu --- include/linux/rhashtable.h | 1 - lib/rhashtable.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index 79f83b6eec27..57a2a29bef0e 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/lib/rhashtable.c b/lib/rhashtable.c index 40cfb38ac919..ef975510ec38 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #define HASH_DEFAULT_SIZE 64UL #define HASH_MIN_SIZE 4U From 3a5834db2b1ce25649f330e78efe1ccde78967fd Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Fri, 5 Jun 2026 14:23:51 +0300 Subject: [PATCH 002/122] hwrng: core - fix rng list on registration error hwrng_register(rng) does the following: 1. Checks if rng has name and read methods set 2. Checks if the name already exists 3. Adds rng to global rng_list 4. May try to set rng to current_rng If step 4 fails, it returns an error. However, it does not remove the rng from rng_list, causing a dangling reference which can result in use-after-free if the caller frees rng, since registration failed. Add a list_del_init() cleanup step. Fixes: 2bbb6983887f ("hwrng: use rng source with best quality") Signed-off-by: Manos Pitsidianakis Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 6931657ad2ca..e77af6578ab5 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -596,11 +596,13 @@ int hwrng_register(struct hwrng *rng) */ err = set_current_rng(rng); if (err) - goto out_unlock; + goto out_list_del; } } mutex_unlock(&rng_mutex); return 0; +out_list_del: + list_del_init(&rng->list); out_unlock: mutex_unlock(&rng_mutex); out: From cae575fc09fa824900939960e33bc49b8e964d80 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 6 Jun 2026 01:10:58 +0200 Subject: [PATCH 003/122] crypto: use 2-arg strscpy where destination size is known To simplify the code, drop explicit and hard-coded size arguments from strscpy() where the destination buffer has a fixed size and strscpy() can automatically determine it using sizeof(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- crypto/api.c | 2 +- crypto/crypto_user.c | 9 ++++----- crypto/hctr2.c | 3 +-- crypto/lrw.c | 2 +- crypto/lskcipher.c | 3 +-- crypto/xts.c | 3 ++- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/crypto/api.c b/crypto/api.c index 4349c2caa23a..24227582cfcf 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -116,7 +116,7 @@ struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask) larval->alg.cra_priority = -1; larval->alg.cra_destroy = crypto_larval_destroy; - strscpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME); + strscpy(larval->alg.cra_name, name); init_completion(&larval->completion); return larval; diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index e8b6ae75f31f..d3ccb507153b 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -87,11 +88,9 @@ static int crypto_report_one(struct crypto_alg *alg, { memset(ualg, 0, sizeof(*ualg)); - strscpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name)); - strscpy(ualg->cru_driver_name, alg->cra_driver_name, - sizeof(ualg->cru_driver_name)); - strscpy(ualg->cru_module_name, module_name(alg->cra_module), - sizeof(ualg->cru_module_name)); + strscpy(ualg->cru_name, alg->cra_name); + strscpy(ualg->cru_driver_name, alg->cra_driver_name); + strscpy(ualg->cru_module_name, module_name(alg->cra_module)); ualg->cru_type = 0; ualg->cru_mask = 0; diff --git a/crypto/hctr2.c b/crypto/hctr2.c index ad5edf9366ac..cfc2343bcc1c 100644 --- a/crypto/hctr2.c +++ b/crypto/hctr2.c @@ -354,8 +354,7 @@ static int hctr2_create_common(struct crypto_template *tmpl, struct rtattr **tb, err = -EINVAL; if (strncmp(xctr_alg->base.cra_name, "xctr(", 5)) goto err_free_inst; - len = strscpy(blockcipher_name, xctr_alg->base.cra_name + 5, - sizeof(blockcipher_name)); + len = strscpy(blockcipher_name, xctr_alg->base.cra_name + 5); if (len < 1) goto err_free_inst; if (blockcipher_name[len - 1] != ')') diff --git a/crypto/lrw.c b/crypto/lrw.c index aa31ab03a597..e306e85d7ced 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -359,7 +359,7 @@ static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb) if (!memcmp(cipher_name, "ecb(", 4)) { int len; - len = strscpy(ecb_name, cipher_name + 4, sizeof(ecb_name)); + len = strscpy(ecb_name, cipher_name + 4); if (len < 2) goto err_free_inst; diff --git a/crypto/lskcipher.c b/crypto/lskcipher.c index e4328df6e26c..d7ec215e2b3a 100644 --- a/crypto/lskcipher.c +++ b/crypto/lskcipher.c @@ -528,8 +528,7 @@ struct lskcipher_instance *lskcipher_alloc_instance_simple( int len; err = -EINVAL; - len = strscpy(ecb_name, &cipher_alg->co.base.cra_name[4], - sizeof(ecb_name)); + len = strscpy(ecb_name, &cipher_alg->co.base.cra_name[4]); if (len < 2) goto err_free_inst; diff --git a/crypto/xts.c b/crypto/xts.c index ad97c8091582..1dc948745444 100644 --- a/crypto/xts.c +++ b/crypto/xts.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -400,7 +401,7 @@ static int xts_create(struct crypto_template *tmpl, struct rtattr **tb) if (!memcmp(cipher_name, "ecb(", 4)) { int len; - len = strscpy(name, cipher_name + 4, sizeof(name)); + len = strscpy(name, cipher_name + 4); if (len < 2) goto err_free_inst; From 3c181f71cd715d52ee5a7192af343617b64c3c33 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 6 Jun 2026 01:10:59 +0200 Subject: [PATCH 004/122] crypto: cavium - use 2-arg strscpy where destination size is known To simplify the code, drop explicit and hard-coded size arguments from strscpy() where the destination buffer has a fixed size and strscpy() can automatically determine it using sizeof(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/cavium/nitrox/nitrox_hal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/cavium/nitrox/nitrox_hal.c b/drivers/crypto/cavium/nitrox/nitrox_hal.c index 1b5abdb6cc5e..e36c1741bb78 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_hal.c +++ b/drivers/crypto/cavium/nitrox/nitrox_hal.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include "nitrox_dev.h" #include "nitrox_csr.h" @@ -647,7 +648,7 @@ void nitrox_get_hwinfo(struct nitrox_device *ndev) ndev->hw.revision_id); /* copy partname */ - strscpy(ndev->hw.partname, name, sizeof(ndev->hw.partname)); + strscpy(ndev->hw.partname, name); } void enable_pf2vf_mbox_interrupts(struct nitrox_device *ndev) From 3c6ec632bc90dae0813df2186f681bd3bfce0983 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 6 Jun 2026 01:11:00 +0200 Subject: [PATCH 005/122] crypto: ccp - use 2-arg strscpy where destination size is known To simplify the code, drop explicit and hard-coded size arguments from strscpy() where the destination buffer has a fixed size and strscpy() can automatically determine it using sizeof(). Reviewed-by: Tom Lendacky Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-sha.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index 85058a89f35b..ff9bb253dbb2 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -426,7 +426,7 @@ static int ccp_register_hmac_alg(struct list_head *head, *ccp_alg = *base_alg; INIT_LIST_HEAD(&ccp_alg->entry); - strscpy(ccp_alg->child_alg, def->name, CRYPTO_MAX_ALG_NAME); + strscpy(ccp_alg->child_alg, def->name); alg = &ccp_alg->alg; alg->setkey = ccp_sha_setkey; From dea300a465ee8e1821f56fe758ab23ce2f118f75 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 6 Jun 2026 01:11:01 +0200 Subject: [PATCH 006/122] crypto: hisilicon - use 2-arg strscpy where destination size is known To simplify the code, drop explicit and hard-coded size arguments from strscpy() where the destination buffer has a fixed size and strscpy() can automatically determine it using sizeof(). Reviewed-by: Longfang Liu Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/qm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index a951d2ef7833..c01966a4a33f 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -2944,11 +2944,8 @@ static int qm_alloc_uacce(struct hisi_qm *qm) .flags = UACCE_DEV_SVA, .ops = &uacce_qm_ops, }; - int ret; - ret = strscpy(interface.name, dev_driver_string(&pdev->dev), - sizeof(interface.name)); - if (ret < 0) + if (strscpy(interface.name, dev_driver_string(&pdev->dev)) < 0) return -ENAMETOOLONG; uacce = uacce_alloc(&pdev->dev, &interface); From 4525ac14115d07c3e4c57a8cd5c154916e9d1172 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 6 Jun 2026 01:11:02 +0200 Subject: [PATCH 007/122] crypto: qat - use 2-arg strscpy where destination size is known To simplify the code, drop explicit and hard-coded size arguments from strscpy() where the destination buffer has a fixed size and strscpy() can automatically determine it using sizeof(). Acked-by: Giovanni Cabiddu Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_cfg.c | 7 ++++--- drivers/crypto/intel/qat/qat_common/adf_cfg_services.c | 2 +- drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c | 3 ++- drivers/crypto/intel/qat/qat_common/adf_transport_debug.c | 3 ++- drivers/crypto/intel/qat/qat_common/qat_compression.c | 3 ++- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.c b/drivers/crypto/intel/qat/qat_common/adf_cfg.c index ea5d72d5090c..d97ee1000045 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c @@ -2,6 +2,7 @@ /* Copyright(c) 2014 - 2020 Intel Corporation */ #include #include +#include #include #include #include "adf_accel_devices.h" @@ -284,13 +285,13 @@ int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, return -ENOMEM; INIT_LIST_HEAD(&key_val->list); - strscpy(key_val->key, key, sizeof(key_val->key)); + strscpy(key_val->key, key); if (type == ADF_DEC) { snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%ld", (*((long *)val))); } else if (type == ADF_STR) { - strscpy(key_val->val, (char *)val, sizeof(key_val->val)); + strscpy(key_val->val, (char *)val); } else if (type == ADF_HEX) { snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "0x%lx", (unsigned long)val); @@ -350,7 +351,7 @@ int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name) if (!sec) return -ENOMEM; - strscpy(sec->name, name, sizeof(sec->name)); + strscpy(sec->name, name); INIT_LIST_HEAD(&sec->param_head); down_write(&cfg->lock); list_add_tail(&sec->list, &cfg->sec_list); diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c index 1af6da8b263f..0cb6cb63e995 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c @@ -60,7 +60,7 @@ static int adf_service_string_to_mask(struct adf_accel_dev *accel_dev, const cha if (len > ADF_CFG_MAX_VAL_LEN_IN_BYTES - 1) return -EINVAL; - strscpy(services, buf, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + strscpy(services, buf); substr = services; while ((token = strsep(&substr, ADF_SERVICES_DELIMITER))) { diff --git a/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c b/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c index f9017e03ec0f..32aeb795cc03 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c +++ b/drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c @@ -2,6 +2,7 @@ /* Copyright(c) 2024 Intel Corporation */ #include +#include #include #include "adf_mstate_mgr.h" @@ -158,7 +159,7 @@ static struct adf_mstate_sect_h *adf_mstate_sect_add_header(struct adf_mstate_mg return NULL; } - strscpy(sect->id, id, sizeof(sect->id)); + strscpy(sect->id, id); sect->size = 0; sect->sub_sects = 0; mgr->state += sizeof(*sect); diff --git a/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c b/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c index a8f853516a3f..fc5d88a2bb17 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c +++ b/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c @@ -2,6 +2,7 @@ /* Copyright(c) 2014 - 2020 Intel Corporation */ #include #include +#include #include #include "adf_accel_devices.h" #include "adf_transport_internal.h" @@ -103,7 +104,7 @@ int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name) if (!ring_debug) return -ENOMEM; - strscpy(ring_debug->ring_name, name, sizeof(ring_debug->ring_name)); + strscpy(ring_debug->ring_name, name); snprintf(entry_name, sizeof(entry_name), "ring_%02d", ring->ring_number); diff --git a/drivers/crypto/intel/qat/qat_common/qat_compression.c b/drivers/crypto/intel/qat/qat_common/qat_compression.c index 1424d7a9bcd3..8129ad0c32d8 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_compression.c +++ b/drivers/crypto/intel/qat/qat_common/qat_compression.c @@ -2,6 +2,7 @@ /* Copyright(c) 2022 Intel Corporation */ #include #include +#include #include "adf_accel_devices.h" #include "adf_common_drv.h" #include "adf_transport.h" @@ -144,7 +145,7 @@ static int qat_compression_create_instances(struct adf_accel_dev *accel_dev) int i; INIT_LIST_HEAD(&accel_dev->compression_list); - strscpy(key, ADF_NUM_DC, sizeof(key)); + strscpy(key, ADF_NUM_DC); ret = adf_cfg_get_param_value(accel_dev, SEC, key, val); if (ret) return ret; From 91181aa5c228dd21a1d03ea41cab477d0b64e4c3 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 6 Jun 2026 01:11:03 +0200 Subject: [PATCH 008/122] crypto: octeontx - use 2-arg strscpy where destination size is known To simplify the code, drop explicit and hard-coded size arguments from strscpy() where the destination buffer has a fixed size and strscpy() can automatically determine it using sizeof(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c | 4 ++-- drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c index 205579a6ba2b..58dd996c7f3a 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c +++ b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c @@ -99,7 +99,7 @@ static int dev_supports_eng_type(struct otx_cpt_eng_grps *eng_grps, static void set_ucode_filename(struct otx_cpt_ucode *ucode, const char *filename) { - strscpy(ucode->filename, filename, OTX_CPT_UCODE_NAME_LENGTH); + strscpy(ucode->filename, filename); } static char *get_eng_type_str(int eng_type) @@ -140,7 +140,7 @@ static int get_ucode_type(struct otx_cpt_ucode_hdr *ucode_hdr, int *ucode_type) u32 i, val = 0; u8 nn; - strscpy(tmp_ver_str, ucode_hdr->ver_str, OTX_CPT_UCODE_VER_STR_SZ); + strscpy(tmp_ver_str, ucode_hdr->ver_str); for (i = 0; i < strlen(tmp_ver_str); i++) tmp_ver_str[i] = tolower(tmp_ver_str[i]); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c index 9b0887d7e62c..465f00e74623 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c @@ -74,7 +74,7 @@ static int is_2nd_ucode_used(struct otx2_cpt_eng_grp_info *eng_grp) static void set_ucode_filename(struct otx2_cpt_ucode *ucode, const char *filename) { - strscpy(ucode->filename, filename, OTX2_CPT_NAME_LENGTH); + strscpy(ucode->filename, filename); } static char *get_eng_type_str(int eng_type) @@ -130,7 +130,7 @@ static int get_ucode_type(struct device *dev, int i, val = 0; u8 nn; - strscpy(tmp_ver_str, ucode_hdr->ver_str, OTX2_CPT_UCODE_VER_STR_SZ); + strscpy(tmp_ver_str, ucode_hdr->ver_str); for (i = 0; i < strlen(tmp_ver_str); i++) tmp_ver_str[i] = tolower(tmp_ver_str[i]); From 54e56712f071b56e9945baa33545c9afd0f2b0bd Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 6 Jun 2026 15:17:54 +0200 Subject: [PATCH 009/122] hwrng: atmel - drop __maybe_unused from atmel_trng_pm_ops Since atmel_trng_driver keeps atmel_trng_pm_ops referenced and pm_ptr() uses IS_ENABLED(), which allows the compiler to optimize away unused variables, drop the redundant __maybe_unused annotation. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/atmel-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index 6ed24be3481d..10082add0886 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -186,7 +186,7 @@ static int __maybe_unused atmel_trng_runtime_resume(struct device *dev) return atmel_trng_init(trng); } -static const struct dev_pm_ops __maybe_unused atmel_trng_pm_ops = { +static const struct dev_pm_ops atmel_trng_pm_ops = { SET_RUNTIME_PM_OPS(atmel_trng_runtime_suspend, atmel_trng_runtime_resume, NULL) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, From 9deef9c5b8fcc702e69252bef46735d8b0d1f70c Mon Sep 17 00:00:00 2001 From: Fabian Blatter Date: Sun, 7 Jun 2026 13:24:35 +0200 Subject: [PATCH 010/122] crypto: ecc - Optimize vli additive operations using compiler builtins Replace the software carry flag emulation with compiler builtins. Even the newest compilers struggle with taking advantage of the hardware carry flag. Compiler builtins allow the compiler to much more easily achieve this while still remaining constant-time. This yields an approximately 6-7% performance improvement on the ecc_gen_privkey, ecc_make_pub_key and crypto_ecdh_shared_secret functions on x86_64 on all curve sizes. Additionally, the code becomes much more readable. Signed-off-by: Fabian Blatter Reviewed-by: Stefan Berger Signed-off-by: Herbert Xu --- crypto/ecc.c | 98 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/crypto/ecc.c b/crypto/ecc.c index 6eb4d97a5f0d..3250a464b852 100644 --- a/crypto/ecc.c +++ b/crypto/ecc.c @@ -279,6 +279,48 @@ static void vli_rshift1(u64 *vli, unsigned int ndigits) } } +#ifdef __has_builtin +#if __has_builtin(__builtin_addcll) +#define USE_BUILTIN_ADDC +#endif +#endif + +/* Computes result = left + right + carry_in and updates carry_out */ +static inline void add_carry(u64 left, u64 right, u64 *result, u64 carry_in, + u64 *carry_out) +{ +#ifdef USE_BUILTIN_ADDC + *result = __builtin_addcll(left, right, carry_in, carry_out); +#else + u64 sum1, sum2; + u64 c1 = __builtin_uaddll_overflow(left, right, &sum1); + u64 c2 = __builtin_uaddll_overflow(sum1, carry_in, &sum2); + *result = sum2; + *carry_out = c1 | c2; +#endif +} + +#ifdef __has_builtin +#if __has_builtin(__builtin_subcll) +#define USE_BUILTIN_SUBC +#endif +#endif + +/* Computes result = left - right - borrow_in and updates borrow_out */ +static inline void sub_borrow(u64 left, u64 right, u64 *result, u64 borrow_in, + u64 *borrow_out) +{ +#ifdef USE_BUILTIN_SUBC + *result = __builtin_subcll(left, right, borrow_in, borrow_out); +#else + u64 diff1, diff2; + u64 b1 = __builtin_usubll_overflow(left, right, &diff1); + u64 b2 = __builtin_usubll_overflow(diff1, borrow_in, &diff2); + *result = diff2; + *borrow_out = b1 | b2; +#endif +} + /* Computes result = left + right, returning carry. Can modify in place. */ static u64 vli_add(u64 *result, const u64 *left, const u64 *right, unsigned int ndigits) @@ -286,15 +328,8 @@ static u64 vli_add(u64 *result, const u64 *left, const u64 *right, u64 carry = 0; int i; - for (i = 0; i < ndigits; i++) { - u64 sum; - - sum = left[i] + right[i] + carry; - if (sum != left[i]) - carry = (sum < left[i]); - - result[i] = sum; - } + for (i = 0; i < ndigits; i++) + add_carry(left[i], right[i], &result[i], carry, &carry); return carry; } @@ -303,40 +338,29 @@ static u64 vli_add(u64 *result, const u64 *left, const u64 *right, static u64 vli_uadd(u64 *result, const u64 *left, u64 right, unsigned int ndigits) { - u64 carry = right; + u64 carry; int i; - for (i = 0; i < ndigits; i++) { - u64 sum; + if (ndigits == 0) + return right; - sum = left[i] + carry; - if (sum != left[i]) - carry = (sum < left[i]); - else - carry = !!carry; + carry = __builtin_uaddll_overflow(left[0], right, &result[0]); - result[i] = sum; - } + for (i = 1; i < ndigits; i++) + carry = __builtin_uaddll_overflow(left[i], carry, &result[i]); return carry; } /* Computes result = left - right, returning borrow. Can modify in place. */ u64 vli_sub(u64 *result, const u64 *left, const u64 *right, - unsigned int ndigits) + unsigned int ndigits) { u64 borrow = 0; int i; - for (i = 0; i < ndigits; i++) { - u64 diff; - - diff = left[i] - right[i] - borrow; - if (diff != left[i]) - borrow = (diff > left[i]); - - result[i] = diff; - } + for (i = 0; i < ndigits; i++) + sub_borrow(left[i], right[i], &result[i], borrow, &borrow); return borrow; } @@ -344,20 +368,18 @@ EXPORT_SYMBOL(vli_sub); /* Computes result = left - right, returning borrow. Can modify in place. */ static u64 vli_usub(u64 *result, const u64 *left, u64 right, - unsigned int ndigits) + unsigned int ndigits) { - u64 borrow = right; + u64 borrow; int i; - for (i = 0; i < ndigits; i++) { - u64 diff; + if (ndigits == 0) + return right; - diff = left[i] - borrow; - if (diff != left[i]) - borrow = (diff > left[i]); + borrow = __builtin_usubll_overflow(left[0], right, &result[0]); - result[i] = diff; - } + for (i = 1; i < ndigits; i++) + borrow = __builtin_usubll_overflow(left[i], borrow, &result[i]); return borrow; } From 455b0f3ac9e254edab9f5a873d337abe5e6e3604 Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Mon, 8 Jun 2026 15:59:40 +0100 Subject: [PATCH 011/122] crypto: qat - cancel work on re-enable SR-IOV timeout The QAT reset worker queues SR-IOV reenable work using a work_struct and completion embedded in an on-stack adf_sriov_dev_data. If the completion wait times out, the reset worker can return while device_sriov_wq still holds or executes the stack-backed work item. Cancel the work on the device_sriov_wq on timeout before the stack frame unwinds. Fixes: 4469f9b23468 ("crypto: qat - re-enable sriov after pf reset") Signed-off-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_aer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c index d58cd7fbf707..afded3030e9a 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_aer.c +++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c @@ -189,6 +189,8 @@ static void adf_device_reset_worker(struct work_struct *work) queue_work(device_sriov_wq, &sriov_data.sriov_work); if (wait_for_completion_timeout(&sriov_data.compl, wait_jiffies)) adf_pf2vf_notify_restarted(accel_dev); + else + cancel_work_sync(&sriov_data.sriov_work); adf_dev_restarted_notify(accel_dev); clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); From d41a9fcfb7f9ee36e4a4aaf5e7996bca6be1e7a9 Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Mon, 8 Jun 2026 16:04:20 +0100 Subject: [PATCH 012/122] crypto: qat - clear AES key schedule from stack qat_alg_xts_reverse_key() expands the forward XTS AES key on the stack. That schedule contains key material and can remain in the stack frame. Clear the temporary crypto_aes_ctx with memzero_explicit() after the copy. Fixes: 5106dfeaeabe ("crypto: qat - add AES-XTS support for QAT GEN4 devices") Signed-off-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/qat_algs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/intel/qat/qat_common/qat_algs.c b/drivers/crypto/intel/qat/qat_common/qat_algs.c index 7f638a62e3ad..91663805d9e6 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_algs.c @@ -405,6 +405,7 @@ static void qat_alg_xts_reverse_key(const u8 *key_forward, unsigned int keylen, memcpy(key_reverse + AES_BLOCK_SIZE, key - AES_BLOCK_SIZE, AES_BLOCK_SIZE); } + memzero_explicit(&aes_expanded, sizeof(aes_expanded)); } static void qat_alg_skcipher_init_dec(struct qat_alg_skcipher_ctx *ctx, From 0fd97bbda2842d7dcccee599ac2c0e9554bdddbc Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 8 Jun 2026 17:58:45 +0000 Subject: [PATCH 013/122] crypto: qcom-rng - Enable clock in hwrng case Fix qcom-rng.c to enable the clock before accessing the hardware. Fixes: f29cd5bb64c2 ("crypto: qcom-rng - Add hw_random interface support") Cc: stable@vger.kernel.org Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/qcom-rng.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c index 150e5802e351..f31a7fe07ba7 100644 --- a/drivers/crypto/qcom-rng.c +++ b/drivers/crypto/qcom-rng.c @@ -113,6 +113,13 @@ static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed, return 0; } +static int qcom_hwrng_init(struct hwrng *hwrng) +{ + struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng); + + return clk_prepare_enable(qrng->clk); +} + static int qcom_hwrng_read(struct hwrng *hwrng, void *data, size_t max, bool wait) { struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng); @@ -120,6 +127,13 @@ static int qcom_hwrng_read(struct hwrng *hwrng, void *data, size_t max, bool wai return qcom_rng_read(qrng, data, max); } +static void qcom_hwrng_cleanup(struct hwrng *hwrng) +{ + struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng); + + clk_disable_unprepare(qrng->clk); +} + static int qcom_rng_enable(struct qcom_rng *rng) { u32 val; @@ -208,7 +222,9 @@ static int qcom_rng_probe(struct platform_device *pdev) if (rng->match_data->hwrng_support) { rng->hwrng.name = "qcom_hwrng"; + rng->hwrng.init = qcom_hwrng_init; rng->hwrng.read = qcom_hwrng_read; + rng->hwrng.cleanup = qcom_hwrng_cleanup; rng->hwrng.quality = QCOM_TRNG_QUALITY; ret = devm_hwrng_register(&pdev->dev, &rng->hwrng); if (ret) { From 4ef04bdc0c9f98836d1638be516f6bf1bad55f69 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 8 Jun 2026 17:58:46 +0000 Subject: [PATCH 014/122] crypto: qcom-rng - Allow zero as a random number Zero is a valid random number and needs to be allowed. Otherwise the output is distinguishable from random. Fixes: f29cd5bb64c2 ("crypto: qcom-rng - Add hw_random interface support") Cc: stable@vger.kernel.org Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/qcom-rng.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c index f31a7fe07ba7..7058bd98f9e9 100644 --- a/drivers/crypto/qcom-rng.c +++ b/drivers/crypto/qcom-rng.c @@ -65,8 +65,6 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max) return ret; val = readl_relaxed(rng->base + PRNG_DATA_OUT); - if (!val) - return -EINVAL; if ((max - currsize) >= WORD_SZ) { memcpy(data, &val, WORD_SZ); From 2ecdf5c9910e20f73639bc322f0518a3439d17c0 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 8 Jun 2026 17:58:47 +0000 Subject: [PATCH 015/122] crypto: qcom-rng - Remove crypto_rng interface qcom-rng.c exposes the same hardware through two completely separate interfaces, crypto_rng and hwrng. However, the implementation of this is buggy because it permits generation operations from these interfaces to run concurrently with each other, accessing the same registers. That is, qcom_rng_generate() synchronizes with itself but not with qcom_hwrng_read(). This results in potential repetition of output from the RNG, output of non-random values, etc. Fortunately, there's actually no point in hardware RNG drivers implementing the crypto_rng interface. It's not actually used by anything besides the "rng" algorithm type of AF_ALG, which in turn is not actually used in practice. Other crypto_rng hardware drivers are likewise being phased out, leaving just the hwrng support. Thus, remove it to simplify the code and avoid conflict (and confusion) with the hwrng interface which is the one that actually matters. Fixes: f29cd5bb64c2 ("crypto: qcom-rng - Add hw_random interface support") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Reviewed-by: Dmitry Baryshkov Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 1 - drivers/crypto/qcom-rng.c | 158 +++++--------------------------------- 2 files changed, 19 insertions(+), 140 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 216a00bad5d7..eb834d15d614 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -641,7 +641,6 @@ config CRYPTO_DEV_QCOM_RNG tristate "Qualcomm Random Number Generator Driver" depends on ARCH_QCOM || COMPILE_TEST depends on HW_RANDOM - select CRYPTO_RNG help This driver provides support for the Random Number Generator hardware found on Qualcomm SoCs. diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c index 7058bd98f9e9..4d046caafe5b 100644 --- a/drivers/crypto/qcom-rng.c +++ b/drivers/crypto/qcom-rng.c @@ -3,10 +3,8 @@ // // Based on msm-rng.c and downstream driver -#include #include #include -#include #include #include #include @@ -32,24 +30,15 @@ #define QCOM_TRNG_QUALITY 1024 struct qcom_rng { - struct mutex lock; void __iomem *base; struct clk *clk; struct hwrng hwrng; - struct qcom_rng_match_data *match_data; -}; - -struct qcom_rng_ctx { - struct qcom_rng *rng; }; struct qcom_rng_match_data { - bool skip_init; bool hwrng_support; }; -static struct qcom_rng *qcom_rng_dev; - static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max) { unsigned int currsize = 0; @@ -80,37 +69,6 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max) return currsize; } -static int qcom_rng_generate(struct crypto_rng *tfm, - const u8 *src, unsigned int slen, - u8 *dstn, unsigned int dlen) -{ - struct qcom_rng_ctx *ctx = crypto_rng_ctx(tfm); - struct qcom_rng *rng = ctx->rng; - int ret; - - ret = clk_prepare_enable(rng->clk); - if (ret) - return ret; - - mutex_lock(&rng->lock); - - ret = qcom_rng_read(rng, dstn, dlen); - - mutex_unlock(&rng->lock); - clk_disable_unprepare(rng->clk); - - if (ret >= 0) - ret = 0; - - return ret; -} - -static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed, - unsigned int slen) -{ - return 0; -} - static int qcom_hwrng_init(struct hwrng *hwrng) { struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng); @@ -132,74 +90,26 @@ static void qcom_hwrng_cleanup(struct hwrng *hwrng) clk_disable_unprepare(qrng->clk); } -static int qcom_rng_enable(struct qcom_rng *rng) -{ - u32 val; - int ret; - - ret = clk_prepare_enable(rng->clk); - if (ret) - return ret; - - /* Enable PRNG only if it is not already enabled */ - val = readl_relaxed(rng->base + PRNG_CONFIG); - if (val & PRNG_CONFIG_HW_ENABLE) - goto already_enabled; - - val = readl_relaxed(rng->base + PRNG_LFSR_CFG); - val &= ~PRNG_LFSR_CFG_MASK; - val |= PRNG_LFSR_CFG_CLOCKS; - writel(val, rng->base + PRNG_LFSR_CFG); - - val = readl_relaxed(rng->base + PRNG_CONFIG); - val |= PRNG_CONFIG_HW_ENABLE; - writel(val, rng->base + PRNG_CONFIG); - -already_enabled: - clk_disable_unprepare(rng->clk); - - return 0; -} - -static int qcom_rng_init(struct crypto_tfm *tfm) -{ - struct qcom_rng_ctx *ctx = crypto_tfm_ctx(tfm); - - ctx->rng = qcom_rng_dev; - - if (!ctx->rng->match_data->skip_init) - return qcom_rng_enable(ctx->rng); - - return 0; -} - -static struct rng_alg qcom_rng_alg = { - .generate = qcom_rng_generate, - .seed = qcom_rng_seed, - .seedsize = 0, - .base = { - .cra_name = "stdrng", - .cra_driver_name = "qcom-rng", - .cra_flags = CRYPTO_ALG_TYPE_RNG, - .cra_priority = 300, - .cra_ctxsize = sizeof(struct qcom_rng_ctx), - .cra_module = THIS_MODULE, - .cra_init = qcom_rng_init, - } -}; - static int qcom_rng_probe(struct platform_device *pdev) { + const struct qcom_rng_match_data *match_data; struct qcom_rng *rng; int ret; + match_data = device_get_match_data(&pdev->dev); + if (match_data == NULL || !match_data->hwrng_support) { + dev_info(&pdev->dev, "TRNG support not detected\n"); + /* + * In this case the driver does nothing except the dev_info(), + * but bind the device anyway to avoid effects on GCC state. + */ + return 0; + } + rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); if (!rng) return -ENOMEM; - platform_set_drvdata(pdev, rng); - mutex_init(&rng->lock); - rng->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rng->base)) return PTR_ERR(rng->base); @@ -208,55 +118,26 @@ static int qcom_rng_probe(struct platform_device *pdev) if (IS_ERR(rng->clk)) return PTR_ERR(rng->clk); - rng->match_data = (struct qcom_rng_match_data *)device_get_match_data(&pdev->dev); - - qcom_rng_dev = rng; - ret = crypto_register_rng(&qcom_rng_alg); - if (ret) { - dev_err(&pdev->dev, "Register crypto rng failed: %d\n", ret); - qcom_rng_dev = NULL; - return ret; - } - - if (rng->match_data->hwrng_support) { - rng->hwrng.name = "qcom_hwrng"; - rng->hwrng.init = qcom_hwrng_init; - rng->hwrng.read = qcom_hwrng_read; - rng->hwrng.cleanup = qcom_hwrng_cleanup; - rng->hwrng.quality = QCOM_TRNG_QUALITY; - ret = devm_hwrng_register(&pdev->dev, &rng->hwrng); - if (ret) { - dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret); - qcom_rng_dev = NULL; - goto fail; - } - } - + rng->hwrng.name = "qcom_hwrng"; + rng->hwrng.init = qcom_hwrng_init; + rng->hwrng.read = qcom_hwrng_read; + rng->hwrng.cleanup = qcom_hwrng_cleanup; + rng->hwrng.quality = QCOM_TRNG_QUALITY; + ret = devm_hwrng_register(&pdev->dev, &rng->hwrng); + if (ret) + dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret); return ret; -fail: - crypto_unregister_rng(&qcom_rng_alg); - return ret; -} - -static void qcom_rng_remove(struct platform_device *pdev) -{ - crypto_unregister_rng(&qcom_rng_alg); - - qcom_rng_dev = NULL; } static struct qcom_rng_match_data qcom_prng_match_data = { - .skip_init = false, .hwrng_support = false, }; static struct qcom_rng_match_data qcom_prng_ee_match_data = { - .skip_init = true, .hwrng_support = false, }; static struct qcom_rng_match_data qcom_trng_match_data = { - .skip_init = true, .hwrng_support = true, }; @@ -276,7 +157,6 @@ MODULE_DEVICE_TABLE(of, qcom_rng_of_match); static struct platform_driver qcom_rng_driver = { .probe = qcom_rng_probe, - .remove = qcom_rng_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = qcom_rng_of_match, From 6727c44461f788bb49a37875fbc70654e8db30b2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 8 Jun 2026 17:58:48 +0000 Subject: [PATCH 016/122] hwrng: qcom - Move qcom-rng.c into drivers/char/hw_random/ Since this file just implements a hwrng driver, move it into drivers/char/hw_random/. Rename the kconfig option accordingly as well. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- arch/arm/configs/multi_v7_defconfig | 2 +- arch/arm/configs/qcom_defconfig | 2 +- arch/arm64/configs/defconfig | 2 +- drivers/char/hw_random/Kconfig | 11 +++++++++++ drivers/char/hw_random/Makefile | 1 + drivers/{crypto => char/hw_random}/qcom-rng.c | 0 drivers/crypto/Kconfig | 11 ----------- drivers/crypto/Makefile | 1 - drivers/gpu/drm/ci/arm64.config | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) rename drivers/{crypto => char/hw_random}/qcom-rng.c (100%) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 2de547c8b901..01e016752c4d 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -405,6 +405,7 @@ CONFIG_ASPEED_KCS_IPMI_BMC=m CONFIG_ASPEED_BT_IPMI_BMC=m CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_ST=y +CONFIG_HW_RANDOM_QCOM=m CONFIG_TCG_TPM=m CONFIG_TCG_TIS_I2C_INFINEON=m CONFIG_I2C_CHARDEV=y @@ -1321,7 +1322,6 @@ CONFIG_CRYPTO_DEV_ATMEL_TDES=m CONFIG_CRYPTO_DEV_ATMEL_SHA=m CONFIG_CRYPTO_DEV_MARVELL_CESA=m CONFIG_CRYPTO_DEV_QCE=m -CONFIG_CRYPTO_DEV_QCOM_RNG=m CONFIG_CRYPTO_DEV_ROCKCHIP=m CONFIG_CRYPTO_DEV_STM32_HASH=m CONFIG_CRYPTO_DEV_STM32_CRYP=m diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig index 03309b89ea4c..df0a0ce5b097 100644 --- a/arch/arm/configs/qcom_defconfig +++ b/arch/arm/configs/qcom_defconfig @@ -117,6 +117,7 @@ CONFIG_SERIAL_MSM=y CONFIG_SERIAL_MSM_CONSOLE=y CONFIG_SERIAL_DEV_BUS=y CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_QCOM=m CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_QUP=y @@ -296,7 +297,6 @@ CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m -CONFIG_CRYPTO_DEV_QCOM_RNG=m CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=64 CONFIG_PRINTK_TIME=y diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 654a102cb5bc..76ce07a08d5a 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -601,6 +601,7 @@ CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_VIRTIO=y CONFIG_HW_RANDOM_HISI_TRNG=m CONFIG_HW_RANDOM_XILINX=m +CONFIG_HW_RANDOM_QCOM=m CONFIG_TCG_TPM=y CONFIG_TCG_TIS=m CONFIG_TCG_TIS_SPI=m @@ -1940,7 +1941,6 @@ CONFIG_CRYPTO_DEV_SUN8I_CE=m CONFIG_CRYPTO_DEV_FSL_CAAM=m CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m CONFIG_CRYPTO_DEV_QCE=m -CONFIG_CRYPTO_DEV_QCOM_RNG=m CONFIG_CRYPTO_DEV_TEGRA=m CONFIG_CRYPTO_DEV_ZYNQMP_AES=m CONFIG_CRYPTO_DEV_ZYNQMP_SHA3=m diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index a5bcef4a54ee..b4c359abc4f9 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -636,6 +636,17 @@ config HW_RANDOM_XILINX To compile this driver as a module, choose M here: the module will be called xilinx-trng. +config HW_RANDOM_QCOM + tristate "Qualcomm True Random Number Generator Driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on HW_RANDOM + help + This driver provides support for the True Random Number + Generator hardware found on some Qualcomm SoCs. + + To compile this driver as a module, choose M here. The + module will be called qcom-rng. If unsure, say N. + endif # HW_RANDOM config UML_RANDOM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 95b5adb49560..8fce2aa6cf7d 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -54,3 +54,4 @@ obj-$(CONFIG_HW_RANDOM_POLARFIRE_SOC) += mpfs-rng.o obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o obj-$(CONFIG_HW_RANDOM_JH7110) += jh7110-trng.o obj-$(CONFIG_HW_RANDOM_XILINX) += xilinx-trng.o +obj-$(CONFIG_HW_RANDOM_QCOM) += qcom-rng.o diff --git a/drivers/crypto/qcom-rng.c b/drivers/char/hw_random/qcom-rng.c similarity index 100% rename from drivers/crypto/qcom-rng.c rename to drivers/char/hw_random/qcom-rng.c diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index eb834d15d614..03a8f7a1f75e 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -637,17 +637,6 @@ config CRYPTO_DEV_QCE_SW_MAX_LEN always processed by the software fallback, and all DES requests are done by the hardware. -config CRYPTO_DEV_QCOM_RNG - tristate "Qualcomm Random Number Generator Driver" - depends on ARCH_QCOM || COMPILE_TEST - depends on HW_RANDOM - help - This driver provides support for the Random Number - Generator hardware found on Qualcomm SoCs. - - To compile this driver as a module, choose M here. The - module will be called qcom-rng. If unsure, say N. - config CRYPTO_DEV_IMGTEC_HASH tristate "Imagination Technologies hardware hash accelerator" depends on MIPS || COMPILE_TEST diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 5a950c7abc39..2c33b83f3cfa 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -27,7 +27,6 @@ obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/ obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/ -obj-$(CONFIG_CRYPTO_DEV_QCOM_RNG) += qcom-rng.o obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/ obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o obj-$(CONFIG_CRYPTO_DEV_SA2UL) += sa2ul.o diff --git a/drivers/gpu/drm/ci/arm64.config b/drivers/gpu/drm/ci/arm64.config index 563a69669a7b..c46125c1f80f 100644 --- a/drivers/gpu/drm/ci/arm64.config +++ b/drivers/gpu/drm/ci/arm64.config @@ -78,7 +78,6 @@ CONFIG_INTERCONNECT_QCOM_MSM8996=y CONFIG_INTERCONNECT_QCOM_OSM_L3=y CONFIG_INTERCONNECT_QCOM_SC7180=y CONFIG_INTERCONNECT_QCOM_SM8350=y -CONFIG_CRYPTO_DEV_QCOM_RNG=y CONFIG_SC_DISPCC_7180=y CONFIG_SC_GPUCC_7180=y CONFIG_SM_GPUCC_8350=y @@ -189,6 +188,7 @@ CONFIG_GNSS=y CONFIG_GNSS_MTK_SERIAL=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_MTK=y +CONFIG_HW_RANDOM_QCOM=y CONFIG_MTK_DEVAPC=y CONFIG_PWM_MTK_DISP=y CONFIG_MTK_CMDQ=y From 4c7a4a34048eb3fd7fd5d1d7304278d742f99f1a Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 9 Jun 2026 12:05:53 +0200 Subject: [PATCH 017/122] crypto: atmel-i2c - improve comment in atmel_i2c_init_ecdh_cmd Clarify that a P-256 public key is encoded as two 32-byte coordinates. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-i2c.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index ff19857894d0..24bded47a32b 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -138,9 +138,8 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, cmd->param2 = cpu_to_le16(DATA_SLOT_2); /* - * The device only supports NIST P256 ECC keys. The public key size will - * always be the same. Use a macro for the key size to avoid unnecessary - * computations. + * The device only supports P-256. Its public key is encoded as + * two 32-byte coordinates. */ copied = sg_copy_to_buffer(pubkey, sg_nents_for_len(pubkey, From 3e84fb698abada239d3e35ed3d52a24dbfda5f6a Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 9 Jun 2026 12:05:54 +0200 Subject: [PATCH 018/122] crypto: atmel-ecc - clean up and improve ECDH comments Improve the kerneldoc for struct atmel_ecdh_ctx by removing the stale "unsupported curves" wording, since the device only supports a single curve (P-256), and move the set_secret() constraint to the description. In atmel_ecdh_set_secret(), clarify that the device generates the private key, and drop the redundant "only supports NIST P256" comment. In atmel_ecdh_done() and atmel_ecdh_generate_public_key(), clarify the truncation comments. Also note that a P-256 public key consists of two 32-byte coordinates in atmel_ecdh_compute_shared_secret(), and remove the unnecessary fall-through comment and other redundant comments. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 9da9dd6585df..87e25696400d 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -27,15 +27,14 @@ static struct atmel_ecc_driver_data driver_data; /** * struct atmel_ecdh_ctx - transformation context - * @client : pointer to i2c client device - * @fallback : used for unsupported curves or when user wants to use its own - * private key. - * @public_key : generated when calling set_secret(). It's the responsibility - * of the user to not call set_secret() while - * generate_public_key() or compute_shared_secret() are in flight. - * @curve_id : elliptic curve id - * @do_fallback: true when the device doesn't support the curve or when the user - * wants to use its own private key. + * @client: I2C client device + * @fallback: ECDH fallback used for caller-provided private keys + * @public_key: cached public key for the device-generated private key + * @curve_id: elliptic curve id + * @do_fallback: true when ECDH operations should use @fallback + * + * The caller must not invoke set_secret() while generate_public_key() + * or compute_shared_secret() are in flight. */ struct atmel_ecdh_ctx { struct i2c_client *client; @@ -55,7 +54,7 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq, if (status) goto free_work_data; - /* might want less than we've got */ + /* copy only as much as requested, capped at 32 bytes */ n_sz = min(ATMEL_ECC_NIST_P256_N_SIZE, req->dst_len); /* copy the shared secret */ @@ -64,15 +63,15 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *work_data, void *areq, if (copied != n_sz) status = -EINVAL; - /* fall through */ free_work_data: kfree_sensitive(work_data); kpp_request_complete(req, status); } /* - * A random private key is generated and stored in the device. The device - * returns the pair public key. + * If no private key is provided, generate one in the device and cache + * the corresponding public key. The generated private key never leaves + * the device. */ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, unsigned int len) @@ -83,9 +82,7 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, struct ecdh params; int ret = -ENOMEM; - /* free the old public key, if any */ kfree(ctx->public_key); - /* make sure you don't free the old public key twice */ ctx->public_key = NULL; if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0) { @@ -94,7 +91,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, } if (params.key_size) { - /* fallback to ecdh software implementation */ ctx->do_fallback = true; return crypto_kpp_set_secret(ctx->fallback, buf, len); } @@ -103,11 +99,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, if (!cmd) return -ENOMEM; - /* - * The device only supports NIST P256 ECC keys. The public key size will - * always be the same. Use a macro for the key size to avoid unnecessary - * computations. - */ public_key = kmalloc(ATMEL_ECC_PUBKEY_SIZE, GFP_KERNEL); if (!public_key) goto free_cmd; @@ -120,7 +111,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, if (ret) goto free_public_key; - /* save the public key */ memcpy(public_key, &cmd->data[RSP_DATA_IDX], ATMEL_ECC_PUBKEY_SIZE); ctx->public_key = public_key; @@ -149,7 +139,7 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req) if (!ctx->public_key) return -EINVAL; - /* might want less than we've got */ + /* copy only as much as requested, capped at 64 bytes */ nbytes = min(ATMEL_ECC_PUBKEY_SIZE, req->dst_len); /* public key was saved at private key generation */ @@ -175,7 +165,7 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_request *req) return crypto_kpp_compute_shared_secret(req); } - /* must have exactly two points to be on the curve */ + /* A P-256 public key must contain two 32-byte coordinates */ if (req->src_len != ATMEL_ECC_PUBKEY_SIZE) return -EINVAL; From bbf3f2787e8e911149c593206905fb1874e71b6b Mon Sep 17 00:00:00 2001 From: Chenghai Huang Date: Wed, 10 Jun 2026 09:34:37 +0800 Subject: [PATCH 019/122] MAINTAINERS: update hisilicon zip driver maintainer Add Chenghai Huang as the maintainer of the hisilicon zip driver, replacing Yang Shen. Signed-off-by: Chenghai Huang Reviewed-by: Longfang Liu Acked-by: Zhou Wang Signed-off-by: Herbert Xu --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a9..d1dbf2f07104 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11837,7 +11837,7 @@ W: http://www.hisilicon.com F: drivers/spi/spi-hisi-sfc-v3xx.c HISILICON ZIP Controller DRIVER -M: Yang Shen +M: Chenghai Huang M: Zhou Wang L: linux-crypto@vger.kernel.org S: Maintained From ba199bdaa80b09a7dd92f28751de7f3dbb06c510 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 11 Jun 2026 12:36:35 +0200 Subject: [PATCH 020/122] crypto: atmel-tdes - use scatterlist length before DMA mapping Using sg_dma_len() is only valid after mapping the scatterlist with dma_map_sg(). However, atmel_tdes_crypt_start() uses it before mapping to compare input/output lengths and to compute the transfer count. Use the original scatterlist lengths before DMA mapping to avoid reading stale or uninitialized DMA lengths when CONFIG_NEED_SG_DMA_LENGTH=y. Drop the output scatterlist length in the fast path since it is equal to ->in_sg->length and does not change the transfer count. Fixes: 13802005d8f2 ("crypto: atmel - add Atmel DES/TDES driver") Fixes: 1f858040c2f7 ("crypto: atmel-tdes - add support for latest release of the IP (0x700)") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 643e507f9c02..d380f6741a2c 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -463,14 +463,13 @@ static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd) IS_ALIGNED(dd->out_sg->length, dd->ctx->block_size); fast = in && out; - if (sg_dma_len(dd->in_sg) != sg_dma_len(dd->out_sg)) + if (dd->in_sg->length != dd->out_sg->length) fast = 0; } if (fast) { - count = min_t(size_t, dd->total, sg_dma_len(dd->in_sg)); - count = min_t(size_t, count, sg_dma_len(dd->out_sg)); + count = min_t(size_t, dd->total, dd->in_sg->length); err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); if (!err) { From f964df8a1229561c32d4fa76b91260822dc470f1 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 11 Jun 2026 12:52:01 +0200 Subject: [PATCH 021/122] crypto: atmel-ecc - drop unused curve id from atmel_ecdh_ctx ->curve_id is only set once, but never used - remove it. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 87e25696400d..51c865884055 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -30,7 +30,6 @@ static struct atmel_ecc_driver_data driver_data; * @client: I2C client device * @fallback: ECDH fallback used for caller-provided private keys * @public_key: cached public key for the device-generated private key - * @curve_id: elliptic curve id * @do_fallback: true when ECDH operations should use @fallback * * The caller must not invoke set_secret() while generate_public_key() @@ -40,7 +39,6 @@ struct atmel_ecdh_ctx { struct i2c_client *client; struct crypto_kpp *fallback; const u8 *public_key; - unsigned int curve_id; bool do_fallback; }; @@ -240,7 +238,6 @@ static int atmel_ecdh_init_tfm(struct crypto_kpp *tfm) struct crypto_kpp *fallback; struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); - ctx->curve_id = ECC_CURVE_NIST_P256; ctx->client = atmel_ecc_i2c_client_alloc(); if (IS_ERR(ctx->client)) { pr_err("tfm - i2c_client binding failed\n"); From f240f9b588f4e2de89822adebf560a96b5d263ed Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 11 Jun 2026 23:36:17 +0200 Subject: [PATCH 022/122] crypto: atmel-ecc - reject hardware ECDH without a public key The hardware ECDH path in atmel_ecdh_compute_shared_secret() uses the private key stored in the device. However, the public key is cached only after atmel_ecdh_set_secret() successfully generated that private key for the current tfm. atmel_ecdh_generate_public_key() already rejects requests when no public key is cached. Add the same check to atmel_ecdh_compute_shared_secret() to prevent the device from using a private key that was not generated for the current tfm. Fixes: 11105693fa05 ("crypto: atmel-ecc - introduce Microchip / Atmel ECC driver") Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 51c865884055..8e13aeccf011 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -163,6 +163,9 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_request *req) return crypto_kpp_compute_shared_secret(req); } + if (!ctx->public_key) + return -EINVAL; + /* A P-256 public key must contain two 32-byte coordinates */ if (req->src_len != ATMEL_ECC_PUBKEY_SIZE) return -EINVAL; From 72bbf11ba14bd7d5fbf31a1ec42fff608b657f74 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Sat, 13 Jun 2026 20:20:37 +0000 Subject: [PATCH 023/122] crypto: atmel-sha204a - fix heap info leak on I2C transfer failure The nonblocking RNG path allocates a work_data structure to track the state of an in-flight asynchronous I2C request. This pointer is stored in rng->priv and later consumed by the read path once the transaction completes. If the underlying I2C transfer fails, the completion callback is invoked with a non-zero status. In this case, the allocated work_data is not usable for producing RNG output and must not remain associated with the hwrng state. Previously, the failure path only logged a warning but left the pointer state uncleared, which can result in subsequent read attempts observing stale state and interpreting it as valid completion data. Fix this by freeing the pending work_data. The I2C transaction reports an error. This ensures that failed requests do not leave residual state behind that could be interpreted as valid RNG data on later reads. Clearing rng->priv is done at the subsequent call to nonblocking read. Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator") Signed-off-by: Lothar Rubusch Assisted-by: Gemini:1.5 Pro [google] Reviewed-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 4c9af737b33a..5eb76245347d 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -31,10 +31,14 @@ static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data, struct atmel_i2c_client_priv *i2c_priv = work_data->ctx; struct hwrng *rng = areq; - if (status) + if (status) { dev_warn_ratelimited(&i2c_priv->client->dev, "i2c transaction failed (%d)\n", status); + kfree(work_data); + atomic_dec(&i2c_priv->tfm_count); + return; + } rng->priv = (unsigned long)work_data; atomic_dec(&i2c_priv->tfm_count); From a2f5f62c5b0b97b1990161abe41ec80504dd6f91 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 13 Jun 2026 18:29:17 -0700 Subject: [PATCH 024/122] crypto: crypto4xx - move ioremapping up There's no need for devm_platform_ioremap_resource() to be so far down. In fact, putting it up allows direct return instead of having to goto some branch. Also, remove the error message as the function complains loudly itself. No need to duplicate. Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/amcc/crypto4xx_core.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 001da785af07..0271b5e4d923 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -1251,6 +1251,10 @@ static int crypto4xx_probe(struct platform_device *ofdev) if (!core_dev->dev) return -ENOMEM; + core_dev->dev->ce_base = devm_platform_ioremap_resource(ofdev, 0); + if (IS_ERR(core_dev->dev->ce_base)) + return PTR_ERR(core_dev->dev->ce_base); + /* * Older version of 460EX/GT have a hardware bug. * Hence they do not support H/W based security intr coalescing @@ -1286,13 +1290,6 @@ static int crypto4xx_probe(struct platform_device *ofdev) tasklet_init(&core_dev->tasklet, crypto4xx_bh_tasklet_cb, (unsigned long) dev); - core_dev->dev->ce_base = devm_platform_ioremap_resource(ofdev, 0); - if (IS_ERR(core_dev->dev->ce_base)) { - dev_err(&ofdev->dev, "failed to ioremap resource"); - rc = PTR_ERR(core_dev->dev->ce_base); - goto err_build_sdr; - } - /* Register for Crypto isr, Crypto Engine IRQ */ core_dev->irq = platform_get_irq(ofdev, 0); if (core_dev->irq < 0) { From 32ba5ea177207501c3bf201d9a8d0a77cbf26ca0 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 14 Jun 2026 17:26:07 +0200 Subject: [PATCH 025/122] crypto: qce - drop unused scatterlist traversal in qce_ahash_update Commit df12ef60c87b ("crypto: qce/sha - Do not modify scatterlist passed along with request") removed the only use of sg_last, rendering the scatterlist traversal useless. Remove it and its local variables. Also remove the redundant hash_later check, inline the source offset, and assign the number of complete blocks directly to req->nbytes. Signed-off-by: Thorsten Blum Reviewed-by: Bartosz Golaszewski Signed-off-by: Herbert Xu --- drivers/crypto/qce/sha.c | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index 1b37121cbcdc..13a1174d2175 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -187,10 +187,8 @@ static int qce_ahash_update(struct ahash_request *req) struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req); struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm); struct qce_device *qce = tmpl->qce; - struct scatterlist *sg_last, *sg; - unsigned int total, len; + unsigned int total; unsigned int hash_later; - unsigned int nbytes; unsigned int blocksize; blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); @@ -238,28 +236,8 @@ static int qce_ahash_update(struct ahash_request *req) if (!hash_later) hash_later = blocksize; - if (hash_later) { - unsigned int src_offset = req->nbytes - hash_later; - scatterwalk_map_and_copy(rctx->buf, req->src, src_offset, - hash_later, 0); - } - - /* here nbytes is multiple of blocksize */ - nbytes = total - hash_later; - - len = rctx->buflen; - sg = sg_last = req->src; - - while (len < nbytes && sg) { - if (len + sg_dma_len(sg) > nbytes) - break; - len += sg_dma_len(sg); - sg_last = sg; - sg = sg_next(sg); - } - - if (!sg_last) - return -EINVAL; + scatterwalk_map_and_copy(rctx->buf, req->src, req->nbytes - hash_later, + hash_later, 0); if (rctx->buflen) { sg_init_table(rctx->sg, 2); @@ -268,7 +246,8 @@ static int qce_ahash_update(struct ahash_request *req) req->src = rctx->sg; } - req->nbytes = nbytes; + /* hash only complete blocks */ + req->nbytes = total - hash_later; rctx->buflen = hash_later; return qce->async_req_enqueue(tmpl->qce, &req->base); From 2fdf279ccf1bdea919b7dfa56081047c7a8d5015 Mon Sep 17 00:00:00 2001 From: "Pratik R. Sampat" Date: Mon, 15 Jun 2026 15:23:15 +0000 Subject: [PATCH 026/122] crypto: ccp - Introduce SNP_VERIFY_MITIGATION command The SEV-SNP firmware provides the SNP_VERIFY_MITIGATION command, which can be used to query the status of currently supported vulnerability mitigations and to initiate mitigations within the firmware. This command is an explicit mechanism to ascertain if a firmware mitigation is applied without needing a full RMP re-build, which is most useful in a live firmware update scenario. The firmware supports two subcommands: STATUS and VERIFY. The STATUS subcommand is used to query the supported and verified mitigation bits. The VERIFY subcommand initiates the mitigation process within the FW for the specified vulnerability. Expose a userspace interface under: /sys/firmware/sev/vulnerabilities/ - supported_mitigations (read-only): supported mitigation vector mask - verified_mitigations (read/write): current verified mask; write a vector to request VERIFY for that bit The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using it are bug-specific. Information about supported mitigations and its corresponding vector is to be published as part of the AMD Security Bulletin. See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for more details. Reviewed-by: Tycho Andersen (AMD) Reviewed-by: Tom Lendacky Signed-off-by: Pratik R. Sampat Signed-off-by: Herbert Xu --- .../sysfs-firmware-sev-vulnerabilities | 19 ++ drivers/crypto/ccp/sev-dev.c | 177 ++++++++++++++++++ drivers/crypto/ccp/sev-dev.h | 3 + include/linux/psp-sev.h | 51 +++++ 4 files changed, 250 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities diff --git a/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities new file mode 100644 index 000000000000..964362558bb2 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities @@ -0,0 +1,19 @@ +What: /sys/firmware/sev/vulnerabilities/supported_mitigations +Date: June 2026 +Contact: linux-crypto@vger.kernel.org +Description: + Read-only interface that reports the vector of SEV-SNP + firmware vulnerability mitigations supported by the firmware. + +What: /sys/firmware/sev/vulnerabilities/verified_mitigations +Date: June 2026 +Contact: linux-crypto@vger.kernel.org +Description: + Read/write interface that reports the vector of SEV-SNP + firmware vulnerability mitigations already verified by the + firmware. Writing a vector value requests the firmware to + VERIFY the corresponding mitigation bit(s). + + The list of supported mitigations and the meaning of each + vector bit are both platform- and bug-specific and are + published as part of the AMD Security Bulletin. diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index ca473ca198b8..8be4dab05cbb 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -245,6 +245,7 @@ static int sev_cmd_buffer_len(int cmd) case SEV_CMD_SNP_LAUNCH_FINISH: return sizeof(struct sev_data_snp_launch_finish); case SEV_CMD_SNP_DBG_DECRYPT: return sizeof(struct sev_data_snp_dbg); case SEV_CMD_SNP_DBG_ENCRYPT: return sizeof(struct sev_data_snp_dbg); + case SEV_CMD_SNP_VERIFY_MITIGATION: return sizeof(struct sev_data_snp_verify_mitigation); case SEV_CMD_SNP_PAGE_UNSMASH: return sizeof(struct sev_data_snp_page_unsmash); case SEV_CMD_SNP_PLATFORM_STATUS: return sizeof(struct sev_data_snp_addr); case SEV_CMD_SNP_GUEST_REQUEST: return sizeof(struct sev_data_snp_guest_request); @@ -1352,6 +1353,162 @@ static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg) return 0; } +#ifdef CONFIG_SYSFS +static int snp_verify_mitigation(u16 command, u64 vector, + struct sev_data_snp_verify_mitigation_dst *dst) +{ + struct sev_data_snp_verify_mitigation_dst *mit_dst = NULL; + struct sev_data_snp_verify_mitigation data = {0}; + struct sev_device *sev = psp_master->sev_data; + int ret, error = 0; + + mit_dst = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO); + if (!mit_dst) + return -ENOMEM; + + data.length = sizeof(data); + data.subcommand = command; + data.vector = vector; + data.dst_paddr = __psp_pa(mit_dst); + data.dst_paddr_en = true; + + ret = sev_do_cmd(SEV_CMD_SNP_VERIFY_MITIGATION, &data, &error); + if (!ret) + memcpy(dst, mit_dst, sizeof(*mit_dst)); + else + dev_err(sev->dev, "SNP_VERIFY_MITIGATION command failed, ret = %d, error = %#x\n", + ret, error); + + snp_free_firmware_page(mit_dst); + + return ret; +} + +static ssize_t supported_mitigations_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct sev_data_snp_verify_mitigation_dst dst; + int ret; + + ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%llx\n", dst.mit_supported_vector); +} + +static struct kobj_attribute supported_attr = + __ATTR_RO_MODE(supported_mitigations, 0400); + +static ssize_t verified_mitigations_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct sev_data_snp_verify_mitigation_dst dst; + int ret; + + ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%llx\n", dst.mit_verified_vector); +} + +static ssize_t verified_mitigations_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct sev_data_snp_verify_mitigation_dst dst; + struct sev_device *sev = psp_master->sev_data; + u64 vector; + int ret; + + ret = kstrtoull(buf, 0, &vector); + if (ret) + return ret; + + /* + * The firmware verifies a single mitigation per call. Reject vectors + * with more than one bit set early to avoid a guaranteed-to-fail call + */ + if (hweight64(vector) != 1) + return -EINVAL; + + ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_VERIFY, vector, &dst); + if (ret) + return ret; + + if (dst.mit_failure_status) { + dev_err(sev->dev, "Verify Mitigation - failure status: 0x%x\n", + dst.mit_failure_status); + return -EINVAL; + } + + return count; +} + +static struct kobj_attribute verified_attr = + __ATTR_RW_MODE(verified_mitigations, 0600); + +static struct attribute *mitigation_attrs[] = { + &supported_attr.attr, + &verified_attr.attr, + NULL +}; + +static const struct attribute_group mit_attr_group = { + .attrs = mitigation_attrs, +}; + +static void sev_snp_register_verify_mitigation(struct sev_device *sev) +{ + int rc; + + if (!(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED) || + sev->verify_mit) + return; + + if (!sev->sev_kobj) { + sev->sev_kobj = kobject_create_and_add("sev", firmware_kobj); + if (!sev->sev_kobj) + return; + } + + sev->verify_mit = kobject_create_and_add("vulnerabilities", sev->sev_kobj); + if (!sev->verify_mit) + goto err_sev_kobj; + + rc = sysfs_create_group(sev->verify_mit, &mit_attr_group); + if (rc) + goto err_verify_mit; + + return; + +err_verify_mit: + kobject_put(sev->verify_mit); + sev->verify_mit = NULL; +err_sev_kobj: + kobject_put(sev->sev_kobj); + sev->sev_kobj = NULL; +} + +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) +{ + if (sev->verify_mit) { + sysfs_remove_group(sev->verify_mit, &mit_attr_group); + kobject_put(sev->verify_mit); + sev->verify_mit = NULL; + } + + if (sev->sev_kobj) { + kobject_put(sev->sev_kobj); + sev->sev_kobj = NULL; + } +} +#else // CONFIG_SYSFS +static void sev_snp_register_verify_mitigation(struct sev_device *sev) { } +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) { } +#endif // CONFIG_SYSFS + static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid) { struct sev_data_range_list *snp_range_list __free(kfree) = NULL; @@ -1675,6 +1832,17 @@ int sev_platform_init(struct sev_platform_init_args *args) rc = _sev_platform_init_locked(args); mutex_unlock(&sev_cmd_mutex); + /* + * Register the sysfs interface outside the sev_cmd_mutex. The + * _show()/_store() handlers issue SEV commands that acquire the + * sev_cmd_mutex, so creating (and on the shutdown path, removing) the + * sysfs group must stay outside that lock. sysfs provides its own + * synchronization between group creation/removal and concurrent + * attribute access. + */ + if (!rc) + sev_snp_register_verify_mitigation(psp_master->sev_data); + return rc; } EXPORT_SYMBOL_GPL(sev_platform_init); @@ -2769,6 +2937,15 @@ static void sev_firmware_shutdown(struct sev_device *sev) if (sev->tio_status) sev_tsm_uninit(sev); + /* + * Remove the sysfs interface before taking the sev_cmd_mutex. + * sysfs_remove_group() waits for in-flight _show()/_store() handlers + * to drain, and those handlers issue SNP_VERIFY_MITIGATION via + * sev_do_cmd() which acquires the sev_cmd_mutex. Removing the group + * while holding the mutex could therefore deadlock. + */ + sev_snp_unregister_verify_mitigation(sev); + mutex_lock(&sev_cmd_mutex); __sev_firmware_shutdown(sev, false); diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h index b1cd556bbbf6..d5e596606def 100644 --- a/drivers/crypto/ccp/sev-dev.h +++ b/drivers/crypto/ccp/sev-dev.h @@ -59,6 +59,9 @@ struct sev_device { bool snp_initialized; + struct kobject *sev_kobj; + struct kobject *verify_mit; + struct sev_user_data_status sev_plat_status; struct sev_user_data_snp_status snp_plat_status; diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index ce16bbc0b308..03a79786df1d 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -129,6 +129,7 @@ enum sev_cmd { SEV_CMD_SNP_LAUNCH_FINISH = 0x0A2, SEV_CMD_SNP_DBG_DECRYPT = 0x0B0, SEV_CMD_SNP_DBG_ENCRYPT = 0x0B1, + SEV_CMD_SNP_VERIFY_MITIGATION = 0x0B2, SEV_CMD_SNP_PAGE_SWAP_OUT = 0x0C0, SEV_CMD_SNP_PAGE_SWAP_IN = 0x0C1, SEV_CMD_SNP_PAGE_MOVE = 0x0C2, @@ -898,10 +899,60 @@ struct snp_feature_info { #define SNP_CIPHER_TEXT_HIDING_SUPPORTED BIT(3) #define SNP_AES_256_XTS_POLICY_SUPPORTED BIT(4) #define SNP_CXL_ALLOW_POLICY_SUPPORTED BIT(5) +#define SNP_VERIFY_MITIGATION_SUPPORTED BIT(13) /* Feature bits in EBX */ #define SNP_SEV_TIO_SUPPORTED BIT(1) +#define SNP_MIT_SUBCMD_REQ_STATUS 0x0 +#define SNP_MIT_SUBCMD_REQ_VERIFY 0x1 + +/** + * struct sev_data_snp_verify_mitigation - SNP_VERIFY_MITIGATION command params + * + * @length: Length of the command buffer read by the PSP + * @subcommand: Mitigation sub-command for the firmware to execute. + * REQ_STATUS: 0x0 - Request status about currently supported and + * verified mitigations + * REQ_VERIFY: 0x1 - Request to initiate verification mitigation + * operation on a specific mitigation + * @rsvd: Reserved + * @vector: Bit specifying the vulnerability mitigation to process + * @dst_paddr_en: Destination paddr enabled + * @src_paddr_en: Source paddr enabled + * @rsvd1: Reserved + * @rsvd2: Reserved + * @src_paddr: Source address for optional input data + * @dst_paddr: Destination address to write the result + * @rsvd3: Reserved + */ +struct sev_data_snp_verify_mitigation { + u32 length; + u16 subcommand; + u16 rsvd; + u64 vector; + u32 dst_paddr_en : 1, + src_paddr_en : 1, + rsvd1 : 30; + u8 rsvd2[4]; + u64 src_paddr; + u64 dst_paddr; + u8 rsvd3[24]; +} __packed; + +/** + * struct sev_data_snp_verify_mitigation_dst - mitigation result vectors + * + * @mit_verified_vector: Bit vector of vulnerability mitigations verified + * @mit_supported_vector: Bit vector of vulnerability mitigations supported + * @mit_failure_status: Status of the verification operation + */ +struct sev_data_snp_verify_mitigation_dst { + u64 mit_verified_vector; /* OUT */ + u64 mit_supported_vector; /* OUT */ + u32 mit_failure_status; /* OUT */ +} __packed; + /** * struct sev_snp_tcb_version_genoa_milan * From 011556f71d094da61379ae3672692cae2795304e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 15 Jun 2026 15:41:29 -0700 Subject: [PATCH 027/122] crypto: sun8i-ce - Remove crypto_rng interface Since the crypto_rng interface for hardware PRNGs is unused and is redundant with hwrng and the actual Linux RNG, it's being phased out. Most drivers for it were already removed. Go ahead and remove the sun8i-ce support which is one of the only remaining ones. Note that the sun8i-ce support for hwrng remains in place. That is the interface that actually matters. As usual for crypto_rng, this driver was also buggy: its ->generate() function had a use-after-free vulnerability due to using wait_for_completion_interruptible_timeout() without handling shutting down the DMA operation if a signal is sent. There's no point in fixing this separately only to remove the code anyway, so this commit is marked with Fixes and Cc stable. Fixes: 5eb7e9468884 ("crypto: sun8i-ce - Add support for the PRNG") Cc: stable@vger.kernel.org Cc: Corentin Labbe Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/allwinner/Kconfig | 8 - drivers/crypto/allwinner/sun8i-ce/Makefile | 1 - .../crypto/allwinner/sun8i-ce/sun8i-ce-core.c | 63 ------- .../crypto/allwinner/sun8i-ce/sun8i-ce-prng.c | 159 ------------------ drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h | 29 ---- 5 files changed, 260 deletions(-) delete mode 100644 drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c diff --git a/drivers/crypto/allwinner/Kconfig b/drivers/crypto/allwinner/Kconfig index 06ea0e9fe6f2..17bf9ead6ef2 100644 --- a/drivers/crypto/allwinner/Kconfig +++ b/drivers/crypto/allwinner/Kconfig @@ -70,14 +70,6 @@ config CRYPTO_DEV_SUN8I_CE_HASH help Say y to enable support for hash algorithms. -config CRYPTO_DEV_SUN8I_CE_PRNG - bool "Support for Allwinner Crypto Engine PRNG" - depends on CRYPTO_DEV_SUN8I_CE - select CRYPTO_RNG - help - Select this option if you want to provide kernel-side support for - the Pseudo-Random Number Generator found in the Crypto Engine. - config CRYPTO_DEV_SUN8I_CE_TRNG bool "Support for Allwinner Crypto Engine TRNG" depends on CRYPTO_DEV_SUN8I_CE diff --git a/drivers/crypto/allwinner/sun8i-ce/Makefile b/drivers/crypto/allwinner/sun8i-ce/Makefile index 0842eb2d9408..ea708b427e2e 100644 --- a/drivers/crypto/allwinner/sun8i-ce/Makefile +++ b/drivers/crypto/allwinner/sun8i-ce/Makefile @@ -1,5 +1,4 @@ obj-$(CONFIG_CRYPTO_DEV_SUN8I_CE) += sun8i-ce.o sun8i-ce-y += sun8i-ce-core.o sun8i-ce-cipher.o sun8i-ce-$(CONFIG_CRYPTO_DEV_SUN8I_CE_HASH) += sun8i-ce-hash.o -sun8i-ce-$(CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG) += sun8i-ce-prng.o sun8i-ce-$(CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG) += sun8i-ce-trng.o diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c index f3b58ed6aed0..c6402e87f8a0 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -49,7 +48,6 @@ static const struct ce_variant ce_h3_variant = { { "mod", 50000000, 0 }, }, .esr = ESR_H3, - .prng = CE_ALG_PRNG, .trng = CE_ID_NOTSUPP, }; @@ -66,7 +64,6 @@ static const struct ce_variant ce_h5_variant = { { "mod", 300000000, 0 }, }, .esr = ESR_H5, - .prng = CE_ALG_PRNG, .trng = CE_ID_NOTSUPP, }; @@ -80,7 +77,6 @@ static const struct ce_variant ce_h6_variant = { }, .cipher_t_dlen_in_bytes = true, .hash_t_dlen_in_bits = true, - .prng_t_dlen_in_bytes = true, .trng_t_dlen_in_bytes = true, .ce_clks = { { "bus", 0, 200000000 }, @@ -88,7 +84,6 @@ static const struct ce_variant ce_h6_variant = { { "ram", 0, 400000000 }, }, .esr = ESR_H6, - .prng = CE_ALG_PRNG_V2, .trng = CE_ALG_TRNG_V2, }; @@ -102,7 +97,6 @@ static const struct ce_variant ce_h616_variant = { }, .cipher_t_dlen_in_bytes = true, .hash_t_dlen_in_bits = true, - .prng_t_dlen_in_bytes = true, .trng_t_dlen_in_bytes = true, .needs_word_addresses = true, .ce_clks = { @@ -112,7 +106,6 @@ static const struct ce_variant ce_h616_variant = { { "trng", 0, 0 }, }, .esr = ESR_H6, - .prng = CE_ALG_PRNG_V2, .trng = CE_ALG_TRNG_V2, }; @@ -129,7 +122,6 @@ static const struct ce_variant ce_a64_variant = { { "mod", 300000000, 0 }, }, .esr = ESR_A64, - .prng = CE_ALG_PRNG, .trng = CE_ID_NOTSUPP, }; @@ -148,7 +140,6 @@ static const struct ce_variant ce_d1_variant = { { "trng", 0, 0 }, }, .esr = ESR_D1, - .prng = CE_ALG_PRNG, .trng = CE_ALG_TRNG, }; @@ -165,7 +156,6 @@ static const struct ce_variant ce_r40_variant = { { "mod", 300000000, 0 }, }, .esr = ESR_R40, - .prng = CE_ALG_PRNG, .trng = CE_ID_NOTSUPP, }; @@ -614,25 +604,6 @@ static struct sun8i_ce_alg_template ce_algs[] = { }, }, #endif -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG -{ - .type = CRYPTO_ALG_TYPE_RNG, - .alg.rng = { - .base = { - .cra_name = "stdrng", - .cra_driver_name = "sun8i-ce-prng", - .cra_priority = 300, - .cra_ctxsize = sizeof(struct sun8i_ce_rng_tfm_ctx), - .cra_module = THIS_MODULE, - .cra_init = sun8i_ce_prng_init, - .cra_exit = sun8i_ce_prng_exit, - }, - .generate = sun8i_ce_prng_generate, - .seed = sun8i_ce_prng_seed, - .seedsize = PRNG_SEED_SIZE, - } -}, -#endif }; static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) @@ -693,14 +664,6 @@ static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) seq_printf(seq, "\tFallback due to SG numbers: %lu\n", ce_algs[i].stat_fb_maxsg); break; -#endif -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG - case CRYPTO_ALG_TYPE_RNG: - seq_printf(seq, "%s %s reqs=%lu bytes=%lu\n", - ce_algs[i].alg.rng.base.cra_driver_name, - ce_algs[i].alg.rng.base.cra_name, - ce_algs[i].stat_req, ce_algs[i].stat_bytes); - break; #endif } } @@ -930,25 +893,6 @@ static int sun8i_ce_register_algs(struct sun8i_ce_dev *ce) return err; } break; -#endif -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG - case CRYPTO_ALG_TYPE_RNG: - if (ce->variant->prng == CE_ID_NOTSUPP) { - dev_info(ce->dev, - "DEBUG: Algo of %s not supported\n", - ce_algs[i].alg.rng.base.cra_name); - ce_algs[i].ce = NULL; - break; - } - dev_info(ce->dev, "Register %s\n", - ce_algs[i].alg.rng.base.cra_name); - err = crypto_register_rng(&ce_algs[i].alg.rng); - if (err) { - dev_err(ce->dev, "Fail to register %s\n", - ce_algs[i].alg.rng.base.cra_name); - ce_algs[i].ce = NULL; - } - break; #endif default: ce_algs[i].ce = NULL; @@ -977,13 +921,6 @@ static void sun8i_ce_unregister_algs(struct sun8i_ce_dev *ce) ce_algs[i].alg.hash.base.halg.base.cra_name); crypto_engine_unregister_ahash(&ce_algs[i].alg.hash); break; -#endif -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG - case CRYPTO_ALG_TYPE_RNG: - dev_info(ce->dev, "Unregister %d %s\n", i, - ce_algs[i].alg.rng.base.cra_name); - crypto_unregister_rng(&ce_algs[i].alg.rng); - break; #endif } } diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c deleted file mode 100644 index d0a1ac66738b..000000000000 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * sun8i-ce-prng.c - hardware cryptographic offloader for - * Allwinner H3/A64/H5/H2+/H6/R40 SoC - * - * Copyright (C) 2015-2020 Corentin Labbe - * - * This file handle the PRNG - * - * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst - */ -#include "sun8i-ce.h" -#include -#include -#include - -int sun8i_ce_prng_init(struct crypto_tfm *tfm) -{ - struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm); - - memset(ctx, 0, sizeof(struct sun8i_ce_rng_tfm_ctx)); - return 0; -} - -void sun8i_ce_prng_exit(struct crypto_tfm *tfm) -{ - struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm); - - kfree_sensitive(ctx->seed); - ctx->seed = NULL; - ctx->slen = 0; -} - -int sun8i_ce_prng_seed(struct crypto_rng *tfm, const u8 *seed, - unsigned int slen) -{ - struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm); - - if (ctx->seed && ctx->slen != slen) { - kfree_sensitive(ctx->seed); - ctx->slen = 0; - ctx->seed = NULL; - } - if (!ctx->seed) - ctx->seed = kmalloc(slen, GFP_KERNEL | GFP_DMA); - if (!ctx->seed) - return -ENOMEM; - - memcpy(ctx->seed, seed, slen); - ctx->slen = slen; - - return 0; -} - -int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dst, unsigned int dlen) -{ - struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm); - struct rng_alg *alg = crypto_rng_alg(tfm); - struct sun8i_ce_alg_template *algt; - struct sun8i_ce_dev *ce; - dma_addr_t dma_iv, dma_dst; - int err = 0; - int flow = 3; - unsigned int todo; - struct sun8i_ce_flow *chan; - struct ce_task *cet; - u32 common, sym; - void *d; - - algt = container_of(alg, struct sun8i_ce_alg_template, alg.rng); - ce = algt->ce; - - if (ctx->slen == 0) { - dev_err(ce->dev, "not seeded\n"); - return -EINVAL; - } - - /* we want dlen + seedsize rounded up to a multiple of PRNG_DATA_SIZE */ - todo = dlen + ctx->slen + PRNG_DATA_SIZE * 2; - todo -= todo % PRNG_DATA_SIZE; - - d = kzalloc(todo, GFP_KERNEL | GFP_DMA); - if (!d) { - err = -ENOMEM; - goto err_mem; - } - - dev_dbg(ce->dev, "%s PRNG slen=%u dlen=%u todo=%u multi=%u\n", __func__, - slen, dlen, todo, todo / PRNG_DATA_SIZE); - -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG - algt->stat_req++; - algt->stat_bytes += todo; -#endif - - dma_iv = dma_map_single(ce->dev, ctx->seed, ctx->slen, DMA_TO_DEVICE); - if (dma_mapping_error(ce->dev, dma_iv)) { - dev_err(ce->dev, "Cannot DMA MAP IV\n"); - err = -EFAULT; - goto err_iv; - } - - dma_dst = dma_map_single(ce->dev, d, todo, DMA_FROM_DEVICE); - if (dma_mapping_error(ce->dev, dma_dst)) { - dev_err(ce->dev, "Cannot DMA MAP DST\n"); - err = -EFAULT; - goto err_dst; - } - - err = pm_runtime_resume_and_get(ce->dev); - if (err < 0) - goto err_pm; - - mutex_lock(&ce->rnglock); - chan = &ce->chanlist[flow]; - - cet = &chan->tl[0]; - memset(cet, 0, sizeof(struct ce_task)); - - cet->t_id = cpu_to_le32(flow); - common = ce->variant->prng | CE_COMM_INT; - cet->t_common_ctl = cpu_to_le32(common); - - /* recent CE (H6) need length in bytes, in word otherwise */ - if (ce->variant->prng_t_dlen_in_bytes) - cet->t_dlen = cpu_to_le32(todo); - else - cet->t_dlen = cpu_to_le32(todo / 4); - - sym = PRNG_LD; - cet->t_sym_ctl = cpu_to_le32(sym); - cet->t_asym_ctl = 0; - - cet->t_key = desc_addr_val_le32(ce, dma_iv); - cet->t_iv = desc_addr_val_le32(ce, dma_iv); - - cet->t_dst[0].addr = desc_addr_val_le32(ce, dma_dst); - cet->t_dst[0].len = cpu_to_le32(todo / 4); - - err = sun8i_ce_run_task(ce, 3, "PRNG"); - mutex_unlock(&ce->rnglock); - - pm_runtime_put(ce->dev); - -err_pm: - dma_unmap_single(ce->dev, dma_dst, todo, DMA_FROM_DEVICE); -err_dst: - dma_unmap_single(ce->dev, dma_iv, ctx->slen, DMA_TO_DEVICE); - - if (!err) { - memcpy(dst, d, dlen); - memcpy(ctx->seed, d + dlen, ctx->slen); - } -err_iv: - kfree_sensitive(d); -err_mem: - return err; -} diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h index 71f5a0cd3d45..468d99bf5bf6 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -58,9 +57,7 @@ #define CE_ALG_SHA384 20 #define CE_ALG_SHA512 21 #define CE_ALG_TRNG 48 -#define CE_ALG_PRNG 49 #define CE_ALG_TRNG_V2 0x1c -#define CE_ALG_PRNG_V2 0x1d /* Used in ce_variant */ #define CE_ID_NOTSUPP 0xFF @@ -96,10 +93,6 @@ #define ESR_H6 4 #define ESR_D1 5 -#define PRNG_DATA_SIZE (160 / 8) -#define PRNG_SEED_SIZE DIV_ROUND_UP(175, 8) -#define PRNG_LD BIT(17) - #define CE_DIE_ID_SHIFT 16 #define CE_DIE_ID_MASK 0x07 @@ -136,13 +129,10 @@ struct ce_clock { * bytes or words * @hash_t_dlen_in_bytes: Does the request size for hash is in * bits or words - * @prng_t_dlen_in_bytes: Does the request size for PRNG is in - * bytes or words * @trng_t_dlen_in_bytes: Does the request size for TRNG is in * bytes or words * @ce_clks: list of clocks needed by this variant * @esr: The type of error register - * @prng: The CE_ALG_XXX value for the PRNG * @trng: The CE_ALG_XXX value for the TRNG */ struct ce_variant { @@ -151,12 +141,10 @@ struct ce_variant { u32 op_mode[CE_ID_OP_MAX]; bool cipher_t_dlen_in_bytes; bool hash_t_dlen_in_bits; - bool prng_t_dlen_in_bytes; bool trng_t_dlen_in_bytes; bool needs_word_addresses; struct ce_clock ce_clks[CE_MAX_CLOCKS]; int esr; - unsigned char prng; unsigned char trng; }; @@ -327,16 +315,6 @@ struct sun8i_ce_hash_reqctx { struct ahash_request fallback_req; // keep at the end }; -/* - * struct sun8i_ce_prng_ctx - context for PRNG TFM - * @seed: The seed to use - * @slen: The size of the seed - */ -struct sun8i_ce_rng_tfm_ctx { - void *seed; - unsigned int slen; -}; - /* * struct sun8i_ce_alg_template - crypto_alg template * @type: the CRYPTO_ALG_TYPE for this template @@ -357,7 +335,6 @@ struct sun8i_ce_alg_template { union { struct skcipher_engine_alg skcipher; struct ahash_engine_alg hash; - struct rng_alg rng; } alg; unsigned long stat_req; unsigned long stat_fb; @@ -398,11 +375,5 @@ int sun8i_ce_hash_finup(struct ahash_request *areq); int sun8i_ce_hash_digest(struct ahash_request *areq); int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq); -int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dst, unsigned int dlen); -int sun8i_ce_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen); -void sun8i_ce_prng_exit(struct crypto_tfm *tfm); -int sun8i_ce_prng_init(struct crypto_tfm *tfm); - int sun8i_ce_hwrng_register(struct sun8i_ce_dev *ce); void sun8i_ce_hwrng_unregister(struct sun8i_ce_dev *ce); From a78446ee6fae86ac8733f120e3ffce2e5d9384f5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 15 Jun 2026 15:41:30 -0700 Subject: [PATCH 028/122] crypto: sun8i-ss - Remove crypto_rng interface Since the crypto_rng interface for hardware PRNGs is unused and is redundant with hwrng and the actual Linux RNG, it's being phased out. Most drivers for it were already removed. Go ahead and remove the sun8i-ss support which is one of the only remaining ones. As usual for crypto_rng, this driver was also buggy: its ->generate() function had a use-after-free vulnerability due to using wait_for_completion_interruptible_timeout() without handling shutting down the DMA operation if a signal is sent. Also, it had a buffer overread bug in the line 'memcpy(ctx->seed, d + dlen, ctx->slen);'. There's no point in fixing these bugs separately only to remove the code anyway, so this commit is marked with Fixes and Cc stable. Fixes: ac2614d721de ("crypto: sun8i-ss - Add support for the PRNG") Cc: stable@vger.kernel.org Cc: Corentin Labbe Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/allwinner/Kconfig | 8 - drivers/crypto/allwinner/sun8i-ss/Makefile | 1 - .../crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 45 ----- .../crypto/allwinner/sun8i-ss/sun8i-ss-prng.c | 177 ------------------ drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 23 --- 5 files changed, 254 deletions(-) delete mode 100644 drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c diff --git a/drivers/crypto/allwinner/Kconfig b/drivers/crypto/allwinner/Kconfig index 17bf9ead6ef2..d86ae005fbe2 100644 --- a/drivers/crypto/allwinner/Kconfig +++ b/drivers/crypto/allwinner/Kconfig @@ -105,14 +105,6 @@ config CRYPTO_DEV_SUN8I_SS_DEBUG This will create /sys/kernel/debug/sun8i-ss/stats for displaying the number of requests per flow and per algorithm. -config CRYPTO_DEV_SUN8I_SS_PRNG - bool "Support for Allwinner Security System PRNG" - depends on CRYPTO_DEV_SUN8I_SS - select CRYPTO_RNG - help - Select this option if you want to provide kernel-side support for - the Pseudo-Random Number Generator found in the Security System. - config CRYPTO_DEV_SUN8I_SS_HASH bool "Enable support for hash on sun8i-ss" depends on CRYPTO_DEV_SUN8I_SS diff --git a/drivers/crypto/allwinner/sun8i-ss/Makefile b/drivers/crypto/allwinner/sun8i-ss/Makefile index aabfd893c817..2d6458a42e58 100644 --- a/drivers/crypto/allwinner/sun8i-ss/Makefile +++ b/drivers/crypto/allwinner/sun8i-ss/Makefile @@ -1,4 +1,3 @@ obj-$(CONFIG_CRYPTO_DEV_SUN8I_SS) += sun8i-ss.o sun8i-ss-y += sun8i-ss-core.o sun8i-ss-cipher.o -sun8i-ss-$(CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG) += sun8i-ss-prng.o sun8i-ss-$(CONFIG_CRYPTO_DEV_SUN8I_SS_HASH) += sun8i-ss-hash.o diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c index 59c9bc45ec0f..0b22fcddb882 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include @@ -283,25 +282,6 @@ static struct sun8i_ss_alg_template ss_algs[] = { .do_one_request = sun8i_ss_handle_cipher_request, }, }, -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG -{ - .type = CRYPTO_ALG_TYPE_RNG, - .alg.rng = { - .base = { - .cra_name = "stdrng", - .cra_driver_name = "sun8i-ss-prng", - .cra_priority = 300, - .cra_ctxsize = sizeof(struct sun8i_ss_rng_tfm_ctx), - .cra_module = THIS_MODULE, - .cra_init = sun8i_ss_prng_init, - .cra_exit = sun8i_ss_prng_exit, - }, - .generate = sun8i_ss_prng_generate, - .seed = sun8i_ss_prng_seed, - .seedsize = PRNG_SEED_SIZE, - } -}, -#endif #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH { .type = CRYPTO_ALG_TYPE_AHASH, .ss_algo_id = SS_ID_HASH_MD5, @@ -501,14 +481,6 @@ static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) seq_printf(seq, "\tFallback due to SG numbers: %lu\n", ss_algs[i].stat_fb_sgnum); break; -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG - case CRYPTO_ALG_TYPE_RNG: - seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n", - ss_algs[i].alg.rng.base.cra_driver_name, - ss_algs[i].alg.rng.base.cra_name, - ss_algs[i].stat_req, ss_algs[i].stat_bytes); - break; -#endif #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH case CRYPTO_ALG_TYPE_AHASH: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", @@ -711,16 +683,6 @@ static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) return err; } break; -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG - case CRYPTO_ALG_TYPE_RNG: - err = crypto_register_rng(&ss_algs[i].alg.rng); - if (err) { - dev_err(ss->dev, "Fail to register %s\n", - ss_algs[i].alg.rng.base.cra_name); - ss_algs[i].ss = NULL; - } - break; -#endif #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH case CRYPTO_ALG_TYPE_AHASH: id = ss_algs[i].ss_algo_id; @@ -764,13 +726,6 @@ static void sun8i_ss_unregister_algs(struct sun8i_ss_dev *ss) ss_algs[i].alg.skcipher.base.base.cra_name); crypto_engine_unregister_skcipher(&ss_algs[i].alg.skcipher); break; -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG - case CRYPTO_ALG_TYPE_RNG: - dev_info(ss->dev, "Unregister %d %s\n", i, - ss_algs[i].alg.rng.base.cra_name); - crypto_unregister_rng(&ss_algs[i].alg.rng); - break; -#endif #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH case CRYPTO_ALG_TYPE_AHASH: dev_info(ss->dev, "Unregister %d %s\n", i, diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c deleted file mode 100644 index a923cfc6553f..000000000000 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * sun8i-ss-prng.c - hardware cryptographic offloader for - * Allwinner A80/A83T SoC - * - * Copyright (C) 2015-2020 Corentin Labbe - * - * This file handle the PRNG found in the SS - * - * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst - */ -#include "sun8i-ss.h" -#include -#include -#include -#include -#include - -int sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, - unsigned int slen) -{ - struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm); - - if (ctx->seed && ctx->slen != slen) { - kfree_sensitive(ctx->seed); - ctx->slen = 0; - ctx->seed = NULL; - } - if (!ctx->seed) - ctx->seed = kmalloc(slen, GFP_KERNEL); - if (!ctx->seed) - return -ENOMEM; - - memcpy(ctx->seed, seed, slen); - ctx->slen = slen; - - return 0; -} - -int sun8i_ss_prng_init(struct crypto_tfm *tfm) -{ - struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm); - - memset(ctx, 0, sizeof(struct sun8i_ss_rng_tfm_ctx)); - return 0; -} - -void sun8i_ss_prng_exit(struct crypto_tfm *tfm) -{ - struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm); - - kfree_sensitive(ctx->seed); - ctx->seed = NULL; - ctx->slen = 0; -} - -int sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dst, unsigned int dlen) -{ - struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm); - struct rng_alg *alg = crypto_rng_alg(tfm); - struct sun8i_ss_alg_template *algt; - unsigned int todo_with_padding; - struct sun8i_ss_dev *ss; - dma_addr_t dma_iv, dma_dst; - unsigned int todo; - int err = 0; - int flow; - void *d; - u32 v; - - algt = container_of(alg, struct sun8i_ss_alg_template, alg.rng); - ss = algt->ss; - - if (ctx->slen == 0) { - dev_err(ss->dev, "The PRNG is not seeded\n"); - return -EINVAL; - } - - /* The SS does not give an updated seed, so we need to get a new one. - * So we will ask for an extra PRNG_SEED_SIZE data. - * We want dlen + seedsize rounded up to a multiple of PRNG_DATA_SIZE - */ - todo = dlen + PRNG_SEED_SIZE + PRNG_DATA_SIZE; - todo -= todo % PRNG_DATA_SIZE; - - todo_with_padding = ALIGN(todo, dma_get_cache_alignment()); - if (todo_with_padding < todo || todo < dlen) - return -EOVERFLOW; - - d = kzalloc(todo_with_padding, GFP_KERNEL); - if (!d) - return -ENOMEM; - - flow = sun8i_ss_get_engine_number(ss); - -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG - algt->stat_req++; - algt->stat_bytes += todo; -#endif - - v = SS_ALG_PRNG | SS_PRNG_CONTINUE | SS_START; - if (flow) - v |= SS_FLOW1; - else - v |= SS_FLOW0; - - dma_iv = dma_map_single(ss->dev, ctx->seed, ctx->slen, DMA_TO_DEVICE); - if (dma_mapping_error(ss->dev, dma_iv)) { - dev_err(ss->dev, "Cannot DMA MAP IV\n"); - err = -EFAULT; - goto err_free; - } - - dma_dst = dma_map_single(ss->dev, d, todo, DMA_FROM_DEVICE); - if (dma_mapping_error(ss->dev, dma_dst)) { - dev_err(ss->dev, "Cannot DMA MAP DST\n"); - err = -EFAULT; - goto err_iv; - } - - err = pm_runtime_resume_and_get(ss->dev); - if (err < 0) - goto err_pm; - err = 0; - - mutex_lock(&ss->mlock); - writel(dma_iv, ss->base + SS_IV_ADR_REG); - /* the PRNG act badly (failing rngtest) without SS_KEY_ADR_REG set */ - writel(dma_iv, ss->base + SS_KEY_ADR_REG); - writel(dma_dst, ss->base + SS_DST_ADR_REG); - writel(todo / 4, ss->base + SS_LEN_ADR_REG); - - reinit_completion(&ss->flows[flow].complete); - ss->flows[flow].status = 0; - /* Be sure all data is written before enabling the task */ - wmb(); - - writel(v, ss->base + SS_CTL_REG); - - wait_for_completion_interruptible_timeout(&ss->flows[flow].complete, - msecs_to_jiffies(todo)); - if (ss->flows[flow].status == 0) { - dev_err(ss->dev, "DMA timeout for PRNG (size=%u)\n", todo); - err = -EFAULT; - } - /* Since cipher and hash use the linux/cryptoengine and that we have - * a cryptoengine per flow, we are sure that they will issue only one - * request per flow. - * Since the cryptoengine wait for completion before submitting a new - * one, the mlock could be left just after the final writel. - * But cryptoengine cannot handle crypto_rng, so we need to be sure - * nothing will use our flow. - * The easiest way is to grab mlock until the hardware end our requests. - * We could have used a per flow lock, but this would increase - * complexity. - * The drawback is that no request could be handled for the other flow. - */ - mutex_unlock(&ss->mlock); - - pm_runtime_put(ss->dev); - -err_pm: - dma_unmap_single(ss->dev, dma_dst, todo, DMA_FROM_DEVICE); -err_iv: - dma_unmap_single(ss->dev, dma_iv, ctx->slen, DMA_TO_DEVICE); - - if (!err) { - memcpy(dst, d, dlen); - /* Update seed */ - memcpy(ctx->seed, d + dlen, ctx->slen); - } -err_free: - kfree_sensitive(d); - - return err; -} diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h index 3fc86225edaf..289fb22abfa2 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -27,7 +26,6 @@ #define SS_ALG_DES (1 << 2) #define SS_ALG_3DES (2 << 2) #define SS_ALG_MD5 (3 << 2) -#define SS_ALG_PRNG (4 << 2) #define SS_ALG_SHA1 (6 << 2) #define SS_ALG_SHA224 (7 << 2) #define SS_ALG_SHA256 (8 << 2) @@ -68,8 +66,6 @@ #define SS_FLOW0 BIT(30) #define SS_FLOW1 BIT(31) -#define SS_PRNG_CONTINUE BIT(18) - #define MAX_SG 8 #define MAXFLOW 2 @@ -79,9 +75,6 @@ #define SS_DIE_ID_SHIFT 20 #define SS_DIE_ID_MASK 0x07 -#define PRNG_DATA_SIZE (160 / 8) -#define PRNG_SEED_SIZE DIV_ROUND_UP(175, 8) - #define MAX_PAD_SIZE 4096 /* @@ -213,16 +206,6 @@ struct sun8i_cipher_tfm_ctx { struct crypto_skcipher *fallback_tfm; }; -/* - * struct sun8i_ss_prng_ctx - context for PRNG TFM - * @seed: The seed to use - * @slen: The size of the seed - */ -struct sun8i_ss_rng_tfm_ctx { - void *seed; - unsigned int slen; -}; - /* * struct sun8i_ss_hash_tfm_ctx - context for an ahash TFM * @fallback_tfm: pointer to the fallback TFM @@ -274,7 +257,6 @@ struct sun8i_ss_alg_template { struct sun8i_ss_dev *ss; union { struct skcipher_engine_alg skcipher; - struct rng_alg rng; struct ahash_engine_alg hash; } alg; unsigned long stat_req; @@ -300,11 +282,6 @@ int sun8i_ss_skencrypt(struct skcipher_request *areq); int sun8i_ss_get_engine_number(struct sun8i_ss_dev *ss); int sun8i_ss_run_task(struct sun8i_ss_dev *ss, struct sun8i_cipher_req_ctx *rctx, const char *name); -int sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dst, unsigned int dlen); -int sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen); -int sun8i_ss_prng_init(struct crypto_tfm *tfm); -void sun8i_ss_prng_exit(struct crypto_tfm *tfm); int sun8i_ss_hash_init_tfm(struct crypto_ahash *tfm); void sun8i_ss_hash_exit_tfm(struct crypto_ahash *tfm); From e9d76cd90c991e37642c0ba256d7e6076b7ff541 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 15 Jun 2026 15:41:31 -0700 Subject: [PATCH 029/122] crypto: caam - Remove crypto_rng interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the crypto_rng interface for hardware PRNGs is unused and is redundant with hwrng and the actual Linux RNG, it's being phased out. Most drivers for it were already removed. Go ahead and remove the CAAM support which is one of the only remaining ones. Note that the CAAM support for hwrng remains in place. That is the interface that actually matters. Note that this code also had several issues, including dlen > 65535 causing corruption of the CAAM descriptor. Cc: Gaurav Jain Cc: Horia Geantă Cc: Pankaj Gupta Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/caam/Kconfig | 9 -- drivers/crypto/caam/Makefile | 1 - drivers/crypto/caam/caamprng.c | 241 --------------------------------- drivers/crypto/caam/intern.h | 15 -- drivers/crypto/caam/jr.c | 2 - 5 files changed, 268 deletions(-) delete mode 100644 drivers/crypto/caam/caamprng.c diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index 05210a0edb8a..ec57bf6aaf6c 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -145,20 +145,11 @@ config CRYPTO_DEV_FSL_CAAM_PKC_API config CRYPTO_DEV_FSL_CAAM_RNG_API bool "Register caam device for hwrng API" default y - select CRYPTO_RNG select HW_RANDOM help Selecting this will register the SEC4 hardware rng to the hw_random API for supplying the kernel entropy pool. -config CRYPTO_DEV_FSL_CAAM_PRNG_API - bool "Register Pseudo random number generation implementation with Crypto API" - default y - select CRYPTO_RNG - help - Selecting this will register the SEC hardware prng to - the Crypto API. - config CRYPTO_DEV_FSL_CAAM_BLOB_GEN bool diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile index d2eaf5205b1c..a17e3cf14c61 100644 --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile @@ -20,7 +20,6 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o -caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API) += caamprng.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_BLOB_GEN) += blob_gen.o diff --git a/drivers/crypto/caam/caamprng.c b/drivers/crypto/caam/caamprng.c deleted file mode 100644 index 6e4c1191cb28..000000000000 --- a/drivers/crypto/caam/caamprng.c +++ /dev/null @@ -1,241 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver to expose SEC4 PRNG via crypto RNG API - * - * Copyright 2022 NXP - * - */ - -#include -#include -#include -#include -#include "compat.h" -#include "regs.h" -#include "intern.h" -#include "desc_constr.h" -#include "jr.h" -#include "error.h" - -/* - * Length of used descriptors, see caam_init_desc() - */ -#define CAAM_PRNG_MAX_DESC_LEN (CAAM_CMD_SZ + \ - CAAM_CMD_SZ + \ - CAAM_CMD_SZ + CAAM_PTR_SZ_MAX) - -/* prng per-device context */ -struct caam_prng_ctx { - int err; - struct completion done; -}; - -struct caam_prng_alg { - struct rng_alg rng; - bool registered; -}; - -static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err, - void *context) -{ - struct caam_prng_ctx *jctx = context; - - jctx->err = err ? caam_jr_strstatus(jrdev, err) : 0; - - complete(&jctx->done); -} - -static u32 *caam_init_reseed_desc(u32 *desc) -{ - init_job_desc(desc, 0); /* + 1 cmd_sz */ - /* Generate random bytes: + 1 cmd_sz */ - append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | - OP_ALG_AS_FINALIZE); - - print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS, - 16, 4, desc, desc_bytes(desc), 1); - - return desc; -} - -static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len) -{ - init_job_desc(desc, 0); /* + 1 cmd_sz */ - /* Generate random bytes: + 1 cmd_sz */ - append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG); - /* Store bytes: + 1 cmd_sz + caam_ptr_sz */ - append_fifo_store(desc, dst_dma, - len, FIFOST_TYPE_RNGSTORE); - - print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS, - 16, 4, desc, desc_bytes(desc), 1); - - return desc; -} - -static int caam_prng_generate(struct crypto_rng *tfm, - const u8 *src, unsigned int slen, - u8 *dst, unsigned int dlen) -{ - unsigned int aligned_dlen = ALIGN(dlen, dma_get_cache_alignment()); - struct caam_prng_ctx ctx; - struct device *jrdev; - dma_addr_t dst_dma; - u32 *desc; - u8 *buf; - int ret; - - if (aligned_dlen < dlen) - return -EOVERFLOW; - - buf = kzalloc(aligned_dlen, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - jrdev = caam_jr_alloc(); - ret = PTR_ERR_OR_ZERO(jrdev); - if (ret) { - pr_err("Job Ring Device allocation failed\n"); - kfree(buf); - return ret; - } - - desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL); - if (!desc) { - ret = -ENOMEM; - goto out1; - } - - dst_dma = dma_map_single(jrdev, buf, dlen, DMA_FROM_DEVICE); - if (dma_mapping_error(jrdev, dst_dma)) { - dev_err(jrdev, "Failed to map destination buffer memory\n"); - ret = -ENOMEM; - goto out; - } - - init_completion(&ctx.done); - ret = caam_jr_enqueue(jrdev, - caam_init_prng_desc(desc, dst_dma, dlen), - caam_prng_done, &ctx); - - if (ret == -EINPROGRESS) { - wait_for_completion(&ctx.done); - ret = ctx.err; - } - - dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE); - - if (!ret) - memcpy(dst, buf, dlen); -out: - kfree(desc); -out1: - caam_jr_free(jrdev); - kfree(buf); - return ret; -} - -static void caam_prng_exit(struct crypto_tfm *tfm) {} - -static int caam_prng_init(struct crypto_tfm *tfm) -{ - return 0; -} - -static int caam_prng_seed(struct crypto_rng *tfm, - const u8 *seed, unsigned int slen) -{ - struct caam_prng_ctx ctx; - struct device *jrdev; - u32 *desc; - int ret; - - if (slen) { - pr_err("Seed length should be zero\n"); - return -EINVAL; - } - - jrdev = caam_jr_alloc(); - ret = PTR_ERR_OR_ZERO(jrdev); - if (ret) { - pr_err("Job Ring Device allocation failed\n"); - return ret; - } - - desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL); - if (!desc) { - caam_jr_free(jrdev); - return -ENOMEM; - } - - init_completion(&ctx.done); - ret = caam_jr_enqueue(jrdev, - caam_init_reseed_desc(desc), - caam_prng_done, &ctx); - - if (ret == -EINPROGRESS) { - wait_for_completion(&ctx.done); - ret = ctx.err; - } - - kfree(desc); - caam_jr_free(jrdev); - return ret; -} - -static struct caam_prng_alg caam_prng_alg = { - .rng = { - .generate = caam_prng_generate, - .seed = caam_prng_seed, - .seedsize = 0, - .base = { - .cra_name = "stdrng", - .cra_driver_name = "prng-caam", - .cra_priority = 500, - .cra_ctxsize = sizeof(struct caam_prng_ctx), - .cra_module = THIS_MODULE, - .cra_init = caam_prng_init, - .cra_exit = caam_prng_exit, - }, - } -}; - -void caam_prng_unregister(void *data) -{ - if (caam_prng_alg.registered) - crypto_unregister_rng(&caam_prng_alg.rng); -} - -int caam_prng_register(struct device *ctrldev) -{ - struct caam_drv_private *priv = dev_get_drvdata(ctrldev); - u32 rng_inst; - int ret = 0; - - /* Check for available RNG blocks before registration */ - if (priv->era < 10) - rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) & - CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT; - else - rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK; - - if (!rng_inst) { - dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n"); - return ret; - } - - ret = crypto_register_rng(&caam_prng_alg.rng); - if (ret) { - dev_err(ctrldev, - "couldn't register rng crypto alg: %d\n", - ret); - return ret; - } - - caam_prng_alg.registered = true; - - dev_info(ctrldev, - "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_driver_name); - - return 0; -} diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index a88da0d31b23..6e48bf7d6054 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -212,21 +212,6 @@ static inline void caam_rng_exit(struct device *dev) {} #endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */ -#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API - -int caam_prng_register(struct device *dev); -void caam_prng_unregister(void *data); - -#else - -static inline int caam_prng_register(struct device *dev) -{ - return 0; -} - -static inline void caam_prng_unregister(void *data) {} -#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API */ - #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI int caam_qi_algapi_init(struct device *dev); diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index 0ef00df9730e..bddeaaaca487 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -40,7 +40,6 @@ static void register_algs(struct caam_drv_private_jr *jrpriv, caam_algapi_hash_init(dev); caam_pkc_init(dev); jrpriv->hwrng = !caam_rng_init(dev); - caam_prng_register(dev); caam_qi_algapi_init(dev); algs_unlock: @@ -55,7 +54,6 @@ static void unregister_algs(void) goto algs_unlock; caam_qi_algapi_exit(); - caam_prng_unregister(NULL); caam_pkc_exit(); caam_algapi_hash_exit(); caam_algapi_exit(); From d03f980a25853f6a380895119a572a3bb1194e8d Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Tue, 16 Jun 2026 08:46:27 +0800 Subject: [PATCH 030/122] crypto: sa2ul - stop probe if context pool creation fails sa_ul_probe() calls sa_init_mem() to create the DMA pool used for security context buffers, but ignores its return value. If pool creation fails, probe still continues with DMA setup, algorithm registration and child population even though later request setup depends on that pool. Stop probing when sa_init_mem() fails, and route that failure to the PM cleanup path without attempting to destroy an uncreated DMA pool. Fixes: 7694b6ca649f ("crypto: sa2ul - Add crypto driver") Signed-off-by: Pengpeng Hou Signed-off-by: Herbert Xu --- drivers/crypto/sa2ul.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c index 965a03d5b27a..d865fd4a098c 100644 --- a/drivers/crypto/sa2ul.c +++ b/drivers/crypto/sa2ul.c @@ -2395,7 +2395,10 @@ static int sa_ul_probe(struct platform_device *pdev) return ret; } - sa_init_mem(dev_data); + ret = sa_init_mem(dev_data); + if (ret) + goto disable_pm; + ret = sa_dma_init(dev_data); if (ret) goto destroy_dma_pool; @@ -2430,6 +2433,7 @@ static int sa_ul_probe(struct platform_device *pdev) destroy_dma_pool: dma_pool_destroy(dev_data->sc_pool); +disable_pm: pm_runtime_put_sync(dev); pm_runtime_disable(dev); From c5bcb084a9871e5b62afb5f48b60adfa13b5d9f8 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 21 Jun 2026 21:26:16 +0200 Subject: [PATCH 031/122] crypto: mxs-dcp - fix source scatterlist length access mxs_dcp_aes_block_crypt() uses sg_dma_len() without mapping the source scatterlist with dma_map_sg() first. Therefore, sg_dma_len() is invalid and could return zero or a stale DMA length, causing encryption and decryption to process the wrong number of bytes when CONFIG_NEED_SG_DMA_LENGTH=y. Use the original scatterlist length instead. Fixes: 15b59e7c3733 ("crypto: mxs - Add Freescale MXS DCP driver") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Reviewed-by: Frank Li Signed-off-by: Herbert Xu --- drivers/crypto/mxs-dcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c index 133ebc998236..595b2fd84667 100644 --- a/drivers/crypto/mxs-dcp.c +++ b/drivers/crypto/mxs-dcp.c @@ -353,7 +353,7 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq) for_each_sg(req->src, src, sg_nents(req->src), i) { src_buf = sg_virt(src); - len = sg_dma_len(src); + len = src->length; tlen += len; limit_hit = tlen > req->cryptlen; From 7e28b0a5c4b7d075b98ce6d8f5290a9d3deb5b92 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jun 2026 15:18:09 +0200 Subject: [PATCH 032/122] crypto: qce - Remove unsafe/deprecated algorithms Remove algorithms that are either unsafe or deprecated and have no in-kernel users that cannot be served by the ARM CE implementations. AES-ECB reveals plaintext patterns (identical plaintext blocks produce identical ciphertext blocks) and should not be exposed as a hardware- accelerated primitive. DES, Triple DES and HMAC-SHA1 have been deprecated for years. Remove sha1, ecb(aes), ecb(des), cbc(des), ecb(des3_ede), cbc(des3_ede), hmac(sha1) and all AEAD variants built on these primitives as well as authenc(hmac(sha256),cbc(des)). Also clean up the - now dead - code, flags and constants. Cc: stable@vger.kernel.org Acked-by: Eric Biggers Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Signed-off-by: Herbert Xu --- drivers/crypto/qce/aead.c | 56 +------------------- drivers/crypto/qce/common.c | 55 +++++--------------- drivers/crypto/qce/common.h | 16 ++---- drivers/crypto/qce/regs-v5.h | 4 -- drivers/crypto/qce/sha.c | 30 +---------- drivers/crypto/qce/sha.h | 1 - drivers/crypto/qce/skcipher.c | 97 +---------------------------------- 7 files changed, 20 insertions(+), 239 deletions(-) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 9cb11fada2c4..92d84941d3db 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -9,8 +9,6 @@ #include #include #include -#include -#include #include #include #include "aead.h" @@ -592,7 +590,6 @@ static int qce_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); struct crypto_authenc_keys authenc_keys; unsigned long flags = to_aead_tmpl(tfm)->alg_flags; - u32 _key[6]; int err; err = crypto_authenc_extractkeys(&authenc_keys, key, keylen); @@ -603,26 +600,7 @@ static int qce_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int authenc_keys.authkeylen > QCE_MAX_KEY_SIZE) return -EINVAL; - if (IS_DES(flags)) { - err = verify_aead_des_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen); - if (err) - return err; - } else if (IS_3DES(flags)) { - err = verify_aead_des3_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen); - if (err) - return err; - /* - * The crypto engine does not support any two keys - * being the same for triple des algorithms. The - * verify_skcipher_des3_key does not check for all the - * below conditions. Schedule fallback in this case. - */ - memcpy(_key, authenc_keys.enckey, DES3_EDE_KEY_SIZE); - if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || - !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || - !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) - ctx->need_fallback = true; - } else if (IS_AES(flags)) { + if (IS_AES(flags)) { /* No random key sizes */ if (authenc_keys.enckeylen != AES_KEYSIZE_128 && authenc_keys.enckeylen != AES_KEYSIZE_192 && @@ -693,38 +671,6 @@ struct qce_aead_def { }; static const struct qce_aead_def aead_def[] = { - { - .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC, - .name = "authenc(hmac(sha1),cbc(des))", - .drv_name = "authenc-hmac-sha1-cbc-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .maxauthsize = SHA1_DIGEST_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC, - .name = "authenc(hmac(sha1),cbc(des3_ede))", - .drv_name = "authenc-hmac-sha1-cbc-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .maxauthsize = SHA1_DIGEST_SIZE, - }, - { - .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, - .name = "authenc(hmac(sha256),cbc(des))", - .drv_name = "authenc-hmac-sha256-cbc-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .maxauthsize = SHA256_DIGEST_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, - .name = "authenc(hmac(sha256),cbc(des3_ede))", - .drv_name = "authenc-hmac-sha256-cbc-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .maxauthsize = SHA256_DIGEST_SIZE, - }, { .flags = QCE_ALG_AES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, .name = "authenc(hmac(sha256),cbc(aes))", diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c index 54a78a57f630..3081d765a0f2 100644 --- a/drivers/crypto/qce/common.c +++ b/drivers/crypto/qce/common.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "cipher.h" @@ -115,18 +114,16 @@ static u32 qce_auth_cfg(unsigned long flags, u32 key_size, u32 auth_size) cfg |= AUTH_KEY_SZ_AES256 << AUTH_KEY_SIZE_SHIFT; } - if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) - cfg |= AUTH_SIZE_SHA1 << AUTH_SIZE_SHIFT; - else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) + if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) cfg |= AUTH_SIZE_SHA256 << AUTH_SIZE_SHIFT; else if (IS_CMAC(flags)) cfg |= AUTH_SIZE_ENUM_16_BYTES << AUTH_SIZE_SHIFT; else if (IS_CCM(flags)) cfg |= (auth_size - 1) << AUTH_SIZE_SHIFT; - if (IS_SHA1(flags) || IS_SHA256(flags)) + if (IS_SHA256(flags)) cfg |= AUTH_MODE_HASH << AUTH_MODE_SHIFT; - else if (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags)) + else if (IS_SHA256_HMAC(flags)) cfg |= AUTH_MODE_HMAC << AUTH_MODE_SHIFT; else if (IS_CCM(flags)) cfg |= AUTH_MODE_CCM << AUTH_MODE_SHIFT; @@ -191,7 +188,7 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req) else qce_cpu_to_be32p_array(auth, rctx->digest, digestsize); - iv_words = (IS_SHA1(rctx->flags) || IS_SHA1_HMAC(rctx->flags)) ? 5 : 8; + iv_words = 8; qce_write_array(qce, REG_AUTH_IV0, (u32 *)auth, iv_words); if (rctx->first_blk) @@ -243,19 +240,8 @@ static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) if (IS_AES(flags)) cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; - else if (IS_DES(flags) || IS_3DES(flags)) - cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; - - if (IS_DES(flags)) - cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; - - if (IS_3DES(flags)) - cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; switch (flags & QCE_MODE_MASK) { - case QCE_MODE_ECB: - cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; - break; case QCE_MODE_CBC: cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; break; @@ -340,13 +326,7 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) encr_cfg = qce_encr_cfg(flags, keylen); - if (IS_DES(flags)) { - enciv_words = 2; - enckey_words = 2; - } else if (IS_3DES(flags)) { - enciv_words = 2; - enckey_words = 6; - } else if (IS_AES(flags)) { + if (IS_AES(flags)) { if (IS_XTS(flags)) qce_xtskey(qce, ctx->enc_key, ctx->enc_keylen, rctx->cryptlen); @@ -357,14 +337,12 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) qce_write_array(qce, REG_ENCR_KEY0, (u32 *)enckey, enckey_words); - if (!IS_ECB(flags)) { - if (IS_XTS(flags)) - qce_xts_swapiv(enciv, rctx->iv, ivsize); - else - qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize); + if (IS_XTS(flags)) + qce_xts_swapiv(enciv, rctx->iv, ivsize); + else + qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize); - qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words); - } + qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words); if (IS_ENCRYPT(flags)) encr_cfg |= BIT(ENCODE_SHIFT); @@ -393,10 +371,6 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) #endif #ifdef CONFIG_CRYPTO_DEV_QCE_AEAD -static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = { - SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0 -}; - static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = { SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7 @@ -473,13 +447,8 @@ static int qce_setup_regs_aead(struct crypto_async_request *async_req) /* Write initial authentication IV only for HMAC algorithms */ if (IS_SHA_HMAC(rctx->flags)) { /* Write default authentication iv */ - if (IS_SHA1_HMAC(rctx->flags)) { - auth_ivsize = SHA1_DIGEST_SIZE; - memcpy(authiv, std_iv_sha1, auth_ivsize); - } else if (IS_SHA256_HMAC(rctx->flags)) { - auth_ivsize = SHA256_DIGEST_SIZE; - memcpy(authiv, std_iv_sha256, auth_ivsize); - } + auth_ivsize = SHA256_DIGEST_SIZE; + memcpy(authiv, std_iv_sha256, auth_ivsize); authiv_words = auth_ivsize / sizeof(u32); qce_write_array(qce, REG_AUTH_IV0, (u32 *)authiv, authiv_words); } else if (IS_CCM(rctx->flags)) { diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h index 02e63ad9f245..9cd2e6ed8bbb 100644 --- a/drivers/crypto/qce/common.h +++ b/drivers/crypto/qce/common.h @@ -22,7 +22,7 @@ /* IV length in bytes */ #define QCE_AES_IV_LENGTH AES_BLOCK_SIZE -/* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ +/* max of AES_BLOCK_SIZE */ #define QCE_MAX_IV_SIZE AES_BLOCK_SIZE /* maximum nonce bytes */ @@ -33,14 +33,10 @@ #define QCE_MAX_ALIGN_SIZE 64 /* cipher algorithms */ -#define QCE_ALG_DES BIT(0) -#define QCE_ALG_3DES BIT(1) #define QCE_ALG_AES BIT(2) /* hash and hmac algorithms */ -#define QCE_HASH_SHA1 BIT(3) #define QCE_HASH_SHA256 BIT(4) -#define QCE_HASH_SHA1_HMAC BIT(5) #define QCE_HASH_SHA256_HMAC BIT(6) #define QCE_HASH_AES_CMAC BIT(7) @@ -58,21 +54,15 @@ #define QCE_ENCRYPT BIT(30) #define QCE_DECRYPT BIT(31) -#define IS_DES(flags) (flags & QCE_ALG_DES) -#define IS_3DES(flags) (flags & QCE_ALG_3DES) #define IS_AES(flags) (flags & QCE_ALG_AES) -#define IS_SHA1(flags) (flags & QCE_HASH_SHA1) #define IS_SHA256(flags) (flags & QCE_HASH_SHA256) -#define IS_SHA1_HMAC(flags) (flags & QCE_HASH_SHA1_HMAC) #define IS_SHA256_HMAC(flags) (flags & QCE_HASH_SHA256_HMAC) #define IS_CMAC(flags) (flags & QCE_HASH_AES_CMAC) -#define IS_SHA(flags) (IS_SHA1(flags) || IS_SHA256(flags)) -#define IS_SHA_HMAC(flags) \ - (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags)) +#define IS_SHA(flags) IS_SHA256(flags) +#define IS_SHA_HMAC(flags) IS_SHA256_HMAC(flags) #define IS_CBC(mode) (mode & QCE_MODE_CBC) -#define IS_ECB(mode) (mode & QCE_MODE_ECB) #define IS_CTR(mode) (mode & QCE_MODE_CTR) #define IS_XTS(mode) (mode & QCE_MODE_XTS) #define IS_CCM(mode) (mode & QCE_MODE_CCM) diff --git a/drivers/crypto/qce/regs-v5.h b/drivers/crypto/qce/regs-v5.h index d59ed2798906..431a7db1a4e7 100644 --- a/drivers/crypto/qce/regs-v5.h +++ b/drivers/crypto/qce/regs-v5.h @@ -203,7 +203,6 @@ #define AUTH_SIZE_SHIFT 9 #define AUTH_SIZE_MASK GENMASK(13, 9) -#define AUTH_SIZE_SHA1 0 #define AUTH_SIZE_SHA256 1 #define AUTH_SIZE_ENUM_1_BYTES 0 #define AUTH_SIZE_ENUM_2_BYTES 1 @@ -284,15 +283,12 @@ #define ENCR_KEY_SZ_SHIFT 3 #define ENCR_KEY_SZ_MASK GENMASK(5, 3) -#define ENCR_KEY_SZ_DES 0 -#define ENCR_KEY_SZ_3DES 1 #define ENCR_KEY_SZ_AES128 0 #define ENCR_KEY_SZ_AES256 2 #define ENCR_ALG_SHIFT 0 #define ENCR_ALG_MASK GENMASK(2, 0) #define ENCR_ALG_NONE 0 -#define ENCR_ALG_DES 1 #define ENCR_ALG_AES 2 #define ENCR_ALG_KASUMI 4 #define ENCR_ALG_SNOW_3G 5 diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index 13a1174d2175..eb8a5b0c4173 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -25,10 +25,6 @@ struct qce_sha_saved_state { static LIST_HEAD(ahash_algs); -static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = { - SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0 -}; - static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = { SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7 @@ -328,9 +324,7 @@ static int qce_ahash_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, return 0; } - if (digestsize == SHA1_DIGEST_SIZE) - alg_name = "sha1-qce"; - else if (digestsize == SHA256_DIGEST_SIZE) + if (digestsize == SHA256_DIGEST_SIZE) alg_name = "sha256-qce"; else return -EINVAL; @@ -391,15 +385,6 @@ struct qce_ahash_def { }; static const struct qce_ahash_def ahash_def[] = { - { - .flags = QCE_HASH_SHA1, - .name = "sha1", - .drv_name = "sha1-qce", - .digestsize = SHA1_DIGEST_SIZE, - .blocksize = SHA1_BLOCK_SIZE, - .statesize = sizeof(struct qce_sha_saved_state), - .std_iv = std_iv_sha1, - }, { .flags = QCE_HASH_SHA256, .name = "sha256", @@ -409,15 +394,6 @@ static const struct qce_ahash_def ahash_def[] = { .statesize = sizeof(struct qce_sha_saved_state), .std_iv = std_iv_sha256, }, - { - .flags = QCE_HASH_SHA1_HMAC, - .name = "hmac(sha1)", - .drv_name = "hmac-sha1-qce", - .digestsize = SHA1_DIGEST_SIZE, - .blocksize = SHA1_BLOCK_SIZE, - .statesize = sizeof(struct qce_sha_saved_state), - .std_iv = std_iv_sha1, - }, { .flags = QCE_HASH_SHA256_HMAC, .name = "hmac(sha256)", @@ -455,9 +431,7 @@ static int qce_ahash_register_one(const struct qce_ahash_def *def, alg->halg.digestsize = def->digestsize; alg->halg.statesize = def->statesize; - if (IS_SHA1(def->flags)) - tmpl->hash_zero = sha1_zero_message_hash; - else if (IS_SHA256(def->flags)) + if (IS_SHA256(def->flags)) tmpl->hash_zero = sha256_zero_message_hash; base = &alg->halg.base; diff --git a/drivers/crypto/qce/sha.h b/drivers/crypto/qce/sha.h index a22695361f16..cb822fc334dc 100644 --- a/drivers/crypto/qce/sha.h +++ b/drivers/crypto/qce/sha.h @@ -7,7 +7,6 @@ #define _SHA_H_ #include -#include #include #include "common.h" diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index db0b648a56eb..ff4ee9541f7c 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "cipher.h" @@ -209,51 +208,6 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, return ret; } -static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, - unsigned int keylen) -{ - struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); - int err; - - err = verify_skcipher_des_key(ablk, key); - if (err) - return err; - - ctx->enc_keylen = keylen; - memcpy(ctx->enc_key, key, keylen); - return 0; -} - -static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, - unsigned int keylen) -{ - struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); - u32 _key[6]; - int err; - - err = verify_skcipher_des3_key(ablk, key); - if (err) - return err; - - /* - * The crypto engine does not support any two keys - * being the same for triple des algorithms. The - * verify_skcipher_des3_key does not check for all the - * below conditions. Return -ENOKEY in case any two keys - * are the same. Revisit to see if a fallback cipher - * is needed to handle this condition. - */ - memcpy(_key, key, DES3_EDE_KEY_SIZE); - if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || - !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || - !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) - return -ENOKEY; - - ctx->enc_keylen = keylen; - memcpy(ctx->enc_key, key, keylen); - return 0; -} - static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); @@ -276,7 +230,7 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) * ECB and CBC algorithms require message lengths to be * multiples of block size. */ - if (IS_ECB(rctx->flags) || IS_CBC(rctx->flags)) + if (IS_CBC(rctx->flags)) if (!IS_ALIGNED(req->cryptlen, blocksize)) return -EINVAL; @@ -359,15 +313,6 @@ struct qce_skcipher_def { }; static const struct qce_skcipher_def skcipher_def[] = { - { - .flags = QCE_ALG_AES | QCE_MODE_ECB, - .name = "ecb(aes)", - .drv_name = "ecb-aes-qce", - .blocksize = AES_BLOCK_SIZE, - .ivsize = 0, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - }, { .flags = QCE_ALG_AES | QCE_MODE_CBC, .name = "cbc(aes)", @@ -396,42 +341,6 @@ static const struct qce_skcipher_def skcipher_def[] = { .min_keysize = AES_MIN_KEY_SIZE * 2, .max_keysize = AES_MAX_KEY_SIZE * 2, }, - { - .flags = QCE_ALG_DES | QCE_MODE_ECB, - .name = "ecb(des)", - .drv_name = "ecb-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = 0, - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - }, - { - .flags = QCE_ALG_DES | QCE_MODE_CBC, - .name = "cbc(des)", - .drv_name = "cbc-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_ECB, - .name = "ecb(des3_ede)", - .drv_name = "ecb-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = 0, - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_CBC, - .name = "cbc(des3_ede)", - .drv_name = "cbc-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - }, }; static int qce_skcipher_register_one(const struct qce_skcipher_def *def, @@ -455,9 +364,7 @@ static int qce_skcipher_register_one(const struct qce_skcipher_def *def, alg->ivsize = def->ivsize; alg->min_keysize = def->min_keysize; alg->max_keysize = def->max_keysize; - alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : - IS_DES(def->flags) ? qce_des_setkey : - qce_skcipher_setkey; + alg->setkey = qce_skcipher_setkey; alg->encrypt = qce_skcipher_encrypt; alg->decrypt = qce_skcipher_decrypt; From 2f204fe718f5bf519013cc2536ad7bb2cbb51661 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jun 2026 16:48:03 -0700 Subject: [PATCH 033/122] crypto: af_alg - Add af_alg_restrict sysctl, defaulting to 1 AF_ALG is a frequent source of vulnerabilities and a maintenance nightmare. It exposes far more functionality to userspace than ever should have been exposed, especially to unprivileged processes. Recent exploits have targeted kernel internal implementation details like "authencesn" that have zero use case for userspace access. Fortunately, AF_ALG is rarely used in practice, as userspace crypto libraries exist. And when it is used, only some functionality is known to be used, and many users are known to hold capabilities already. iwd for example requires CAP_NET_ADMIN and has a known algorithm list (https://lore.kernel.org/linux-crypto/bcbbef00-5881-421b-8892-7be6c04b832d@gmail.com/). Thus, let's restrict the set of allowed algorithms by default, depending on the capabilities held. Add a sysctl /proc/sys/crypto/af_alg_restrict with meaning: 0: unrestricted 1: limited functionality 2: completely disabled Set the default value to 1, which enables an algorithm allowlist for unprivileged processes and a slightly longer allowlist for privileged processes. Note that the list may be tweaked in the future. However, the common use cases such as iwd and bluez are taken into account already. I've tested that iwd still works with the default value of 1. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- Documentation/admin-guide/sysctl/crypto.rst | 36 +++++++++++ Documentation/crypto/userspace-if.rst | 13 +++- crypto/af_alg.c | 72 +++++++++++++++++++-- crypto/algif_aead.c | 11 ++++ crypto/algif_hash.c | 24 +++++++ crypto/algif_rng.c | 9 +++ crypto/algif_skcipher.c | 20 ++++++ include/crypto/if_alg.h | 8 +++ 8 files changed, 184 insertions(+), 9 deletions(-) diff --git a/Documentation/admin-guide/sysctl/crypto.rst b/Documentation/admin-guide/sysctl/crypto.rst index b707bd314a64..9a1bd53287f4 100644 --- a/Documentation/admin-guide/sysctl/crypto.rst +++ b/Documentation/admin-guide/sysctl/crypto.rst @@ -7,6 +7,42 @@ kernel configuration: .. contents:: :local: +.. _af_alg_restrict: + +af_alg_restrict +=============== + +Controls the level of restriction of AF_ALG. + +AF_ALG is a deprecated and rarely-used userspace interface that is a +frequent source of vulnerabilities. It also unnecessarily exposes a +large number of kernel implementation details. For more information +about AF_ALG, see :ref:`Documentation/crypto/userspace-if.rst +`. + +Starting in Linux v7.3, AF_ALG supports only a limited set of +algorithms by default. This sysctl allows the system administrator to +remove this restriction when needed for compatibility reasons, or to +go further and disable AF_ALG entirely. The default value is 1. + +=== ================================================================== +0 AF_ALG is unrestricted. + +1 AF_ALG is supported with a limited list of algorithms. The list + is designed for compatibility with known users such as iwd and + bluez that haven't yet been fixed to use userspace crypto code. + + Specifically, there is an allowlist for unprivileged processes + and a somewhat longer allowlist for processes that hold + CAP_SYS_ADMIN or CAP_NET_ADMIN in the initial user namespace. + + Attempts to bind() an AF_ALG socket with a disallowed algorithm + fail with ENOENT. + +2 AF_ALG is completely disabled. Attempts to create an AF_ALG + socket fail with EAFNOSUPPORT. +=== ================================================================== + fips_enabled ============ diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst index ab93300c8e04..d6194346e366 100644 --- a/Documentation/crypto/userspace-if.rst +++ b/Documentation/crypto/userspace-if.rst @@ -1,3 +1,5 @@ +.. _crypto_userspace_interface: + User Space Interface ==================== @@ -12,9 +14,14 @@ AF_ALG is insecure and is deprecated. Originally added to the kernel in 2010, most kernel developers now consider it to be a mistake. Support for hardware accelerators, which was the original purpose of AF_ALG, has been removed. -AF_ALG continues to be supported only for backwards compatibility. On systems -where no programs using AF_ALG remain, the support for it should be disabled by -disabling ``CONFIG_CRYPTO_USER_API_*``. +AF_ALG continues to be supported only for backwards compatibility. + +Starting in Linux v7.3, the set of algorithms supported by AF_ALG is limited by +default. See :ref:`/proc/sys/crypto/af_alg_restrict `. + +On systems where no programs using AF_ALG remain, the support for it should be +disabled entirely by setting ``/proc/sys/crypto/af_alg_restrict`` to 2 or by +disabling ``CONFIG_CRYPTO_USER_API_*`` in the kernel configuration. Deprecation ----------- diff --git a/crypto/af_alg.c b/crypto/af_alg.c index cce000e8590e..34b801568fba 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -22,10 +23,28 @@ #include #include #include +#include +#include #include #include #include +static int af_alg_restrict = 1; + +static const struct ctl_table af_alg_table[] = { + { + .procname = "af_alg_restrict", + .data = &af_alg_restrict, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_TWO, + }, +}; + +static struct ctl_table_header *af_alg_header; + struct alg_type_list { const struct af_alg_type *type; struct list_head list; @@ -110,6 +129,39 @@ int af_alg_unregister_type(const struct af_alg_type *type) } EXPORT_SYMBOL_GPL(af_alg_unregister_type); +static bool af_alg_capable(void) +{ + return ns_capable_noaudit(&init_user_ns, CAP_NET_ADMIN) || + capable(CAP_SYS_ADMIN); +} + +int af_alg_check_restriction(const char *name, + const struct af_alg_allowlist_entry allowlist[]) +{ + int level = READ_ONCE(af_alg_restrict); + + if (level == 0) + return 0; + if (level == 1) { + for (const struct af_alg_allowlist_entry *ent = allowlist; + ent->name; ent++) { + if (strcmp(name, ent->name) == 0 && + (!ent->privileged || af_alg_capable())) + return 0; + } + } + /* + * Use -ENOENT (the error code for "algorithm not found") instead of + * -EACCES or -EPERM, for the highest chance of correctly triggering + * fallback code paths in userspace programs. + * + * Don't log a warning, since it would be noisy. iwd tries to bind a + * bunch of algorithms that it never uses. + */ + return -ENOENT; +} +EXPORT_SYMBOL_GPL(af_alg_check_restriction); + static void alg_do_release(const struct af_alg_type *type, void *private) { if (!type) @@ -506,6 +558,9 @@ static int alg_create(struct net *net, struct socket *sock, int protocol, struct sock *sk; int err; + if (READ_ONCE(af_alg_restrict) == 2) + return -EAFNOSUPPORT; + if (sock->type != SOCK_SEQPACKET) return -ESOCKTNOSUPPORT; if (protocol != 0) @@ -1222,27 +1277,32 @@ EXPORT_SYMBOL_GPL(af_alg_get_rsgl); static int __init af_alg_init(void) { - int err = proto_register(&alg_proto, 0); + int err; + af_alg_header = register_sysctl("crypto", af_alg_table); + + err = proto_register(&alg_proto, 0); if (err) - goto out; + goto out_unregister_sysctl; err = sock_register(&alg_family); - if (err != 0) + if (err) goto out_unregister_proto; -out: - return err; + return 0; out_unregister_proto: proto_unregister(&alg_proto); - goto out; +out_unregister_sysctl: + unregister_sysctl_table(af_alg_header); + return err; } static void __exit af_alg_exit(void) { sock_unregister(PF_ALG); proto_unregister(&alg_proto); + unregister_sysctl_table(af_alg_header); } module_init(af_alg_init); diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 787aac8aeb24..b9217f9086aa 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -34,6 +34,11 @@ #include #include +static const struct af_alg_allowlist_entry aead_allowlist[] = { + { "ccm(aes)", true }, /* bluez */ + {}, +}; + static inline bool aead_sufficient_data(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); @@ -344,6 +349,12 @@ static struct proto_ops algif_aead_ops_nokey = { static void *aead_bind(const char *name) { + int err; + + err = af_alg_check_restriction(name, aead_allowlist); + if (err) + return ERR_PTR(err); + return crypto_alloc_aead(name, 0, AF_ALG_CRYPTOAPI_MASK); } diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 5452ad6c1506..a8d958d51ece 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -16,6 +16,24 @@ #include #include +static const struct af_alg_allowlist_entry hash_allowlist[] = { + { "cmac(aes)", true }, /* iwd, bluez */ + { "hmac(md5)", true }, /* iwd */ + { "hmac(sha1)", true }, /* iwd */ + { "hmac(sha224)", true }, /* iwd */ + { "hmac(sha256)", true }, /* iwd */ + { "hmac(sha384)", true }, /* iwd */ + { "hmac(sha512)", true }, /* iwd, sha512hmac */ + { "md4", true }, /* iwd */ + { "md5", true }, /* iwd */ + { "sha1", false }, /* iwd, iproute2 < 7.0 */ + { "sha224", true }, /* iwd */ + { "sha256", true }, /* iwd */ + { "sha384", true }, /* iwd */ + { "sha512", true }, /* iwd */ + {}, +}; + struct hash_ctx { struct af_alg_sgl sgl; @@ -382,6 +400,12 @@ static struct proto_ops algif_hash_ops_nokey = { static void *hash_bind(const char *name) { + int err; + + err = af_alg_check_restriction(name, hash_allowlist); + if (err) + return ERR_PTR(err); + return crypto_alloc_ahash(name, 0, AF_ALG_CRYPTOAPI_MASK); } diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c index 4dfe7899f8fa..bd522915d56d 100644 --- a/crypto/algif_rng.c +++ b/crypto/algif_rng.c @@ -50,6 +50,10 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stephan Mueller "); MODULE_DESCRIPTION("User-space interface for random number generators"); +static const struct af_alg_allowlist_entry rng_allowlist[] = { + {}, +}; + struct rng_ctx { #define MAXSIZE 128 unsigned int len; @@ -201,6 +205,11 @@ static void *rng_bind(const char *name) { struct rng_parent_ctx *pctx; struct crypto_rng *rng; + int err; + + err = af_alg_check_restriction(name, rng_allowlist); + if (err) + return ERR_PTR(err); pctx = kzalloc_obj(*pctx); if (!pctx) diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index df20bdfe1f1f..2b8069667974 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -34,6 +34,20 @@ #include #include +static const struct af_alg_allowlist_entry skcipher_allowlist[] = { + { "adiantum(xchacha12,aes)", false }, /* cryptsetup */ + { "adiantum(xchacha20,aes)", false }, /* cryptsetup */ + { "cbc(aes)", true }, /* iwd */ + { "cbc(des)", true }, /* iwd */ + { "cbc(des3_ede)", true }, /* iwd */ + { "ctr(aes)", true }, /* iwd */ + { "ecb(aes)", true }, /* iwd, bluez */ + { "ecb(des)", true }, /* iwd */ + { "hctr2(aes)", false }, /* cryptsetup */ + { "xts(aes)", false }, /* cryptsetup benchmark */ + {}, +}; + static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) { @@ -309,6 +323,12 @@ static struct proto_ops algif_skcipher_ops_nokey = { static void *skcipher_bind(const char *name) { + int err; + + err = af_alg_check_restriction(name, skcipher_allowlist); + if (err) + return ERR_PTR(err); + return crypto_alloc_skcipher(name, 0, AF_ALG_CRYPTOAPI_MASK); } diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index 7643ba954125..4e9ed8e73403 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -161,9 +161,17 @@ struct af_alg_ctx { unsigned int inflight; }; +struct af_alg_allowlist_entry { + const char *name; + bool privileged; +}; + int af_alg_register_type(const struct af_alg_type *type); int af_alg_unregister_type(const struct af_alg_type *type); +int af_alg_check_restriction(const char *name, + const struct af_alg_allowlist_entry allowlist[]); + int af_alg_release(struct socket *sock); void af_alg_release_parent(struct sock *sk); int af_alg_accept(struct sock *sk, struct socket *newsock, From ba088974419326daf46c5dc03e2cf6ab6ab701f7 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Tue, 23 Jun 2026 14:07:27 +0800 Subject: [PATCH 034/122] hwrng: xilinx-trng - propagate timeout before any data is read xtrng_readblock32() polls for 16-byte chunks but returns the number of bytes read even when the first poll times out. Its caller then treats a zero return as a short successful read, and partial reads for full 32-byte blocks can make the tail copy use a fixed block offset rather than the amount already produced. Return the poll error when no data has been read, preserve partial positive returns after some data is available, stop the generator on all collection exits, and append tail bytes at the current output count. Fixes: 8979744aca80 ("crypto: xilinx - Add TRNG driver for Versal") Signed-off-by: Pengpeng Hou Signed-off-by: Herbert Xu --- drivers/char/hw_random/xilinx-trng.c | 32 +++++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/char/hw_random/xilinx-trng.c b/drivers/char/hw_random/xilinx-trng.c index f615d5adddde..4a1a168bb46a 100644 --- a/drivers/char/hw_random/xilinx-trng.c +++ b/drivers/char/hw_random/xilinx-trng.c @@ -87,8 +87,8 @@ static void xtrng_softreset(struct xilinx_rng *rng) xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 0); } -/* Return no. of bytes read */ -static size_t xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks32, bool wait) +/* Return no. of bytes read or a negative error before any data is read. */ +static int xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks32, bool wait) { int read = 0, ret; int timeout = 1; @@ -103,8 +103,11 @@ static size_t xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks3 ret = readl_poll_timeout(rng_base + TRNG_STATUS_OFFSET, val, (val & TRNG_STATUS_QCNT_MASK) == TRNG_STATUS_QCNT_16_BYTES, !!wait, timeout); - if (ret) + if (ret) { + if (!read) + return ret; break; + } for (idx = 0; idx < TRNG_READ_4_WORD; idx++) { *(buf + read) = cpu_to_be32(ioread32(rng_base + TRNG_CORE_OUTPUT_OFFSET)); @@ -119,27 +122,40 @@ static int xtrng_collect_random_data(struct xilinx_rng *rng, u8 *rand_gen_buf, { u8 randbuf[TRNG_SEC_STRENGTH_BYTES]; int byteleft, blocks, count = 0; + int full_blocks_bytes; int ret; byteleft = no_of_random_bytes & (TRNG_SEC_STRENGTH_BYTES - 1); blocks = no_of_random_bytes >> TRNG_SEC_STRENGTH_SHIFT; + full_blocks_bytes = blocks * TRNG_SEC_STRENGTH_BYTES; xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK, TRNG_CTRL_PRNGSTART_MASK); if (blocks) { ret = xtrng_readblock32(rng->rng_base, (__be32 *)rand_gen_buf, blocks, wait); - if (!ret) - return 0; + if (ret <= 0) { + count = ret; + goto out_stop; + } count += ret; + if (ret < full_blocks_bytes) + goto out_stop; } if (byteleft) { ret = xtrng_readblock32(rng->rng_base, (__be32 *)randbuf, 1, wait); + if (ret < 0) { + if (!count) + count = ret; + goto out_stop; + } if (!ret) - return count; - memcpy(rand_gen_buf + (blocks * TRNG_SEC_STRENGTH_BYTES), randbuf, byteleft); - count += byteleft; + goto out_stop; + ret = min(ret, no_of_random_bytes - count); + memcpy(rand_gen_buf + count, randbuf, ret); + count += ret; } +out_stop: xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGSTART_MASK, 0U); From f8c24e6899e263073fbbeb07fadc1af85ec492f5 Mon Sep 17 00:00:00 2001 From: Myeonghun Pak Date: Tue, 23 Jun 2026 17:42:23 +0900 Subject: [PATCH 035/122] hwrng: omap - Fix probe error path cleanup omap_rng_probe() enables runtime PM before acquiring and enabling the functional clocks. Several later error paths returned or unwound without undoing all state acquired so far. If pm_runtime_resume_and_get() failed, the driver returned through the generic ioremap error label and left runtime PM enabled. If either clock lookup returned -EPROBE_DEFER, the function returned directly and skipped the runtime PM cleanup; the register clock defer path could also leave the already enabled functional clock prepared. Route these failures through the existing unwind labels so each path only undoes resources that were acquired successfully. Keep the resume failure path limited to pm_runtime_disable(), and use the later labels only after the runtime PM usage count or clocks have been acquired. This issue was identified during our ongoing static-analysis research while reviewing kernel code. Fixes: 61dc0a446e5d ("hwrng: omap - Fix assumption that runtime_get_sync will always succeed") Fixes: 43ec540e6f9b ("hwrng: omap - move clock related code to omap_rng_probe()") Fixes: b166be004491 ("hwrng: omap - Fix clock resource by adding a register clock") Co-developed-by: Ijae Kim Signed-off-by: Ijae Kim Signed-off-by: Myeonghun Pak Signed-off-by: Herbert Xu --- drivers/char/hw_random/omap-rng.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 5e8b50f15db7..a8c0b3dfb133 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -455,32 +455,40 @@ static int omap_rng_probe(struct platform_device *pdev) ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "Failed to runtime_get device: %d\n", ret); - goto err_ioremap; + goto err_pm_disable; } priv->clk = devm_clk_get(&pdev->dev, NULL); - if (PTR_ERR(priv->clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; + if (PTR_ERR(priv->clk) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto err_pm_put; + } if (!IS_ERR(priv->clk)) { ret = clk_prepare_enable(priv->clk); if (ret) { dev_err(&pdev->dev, "Unable to enable the clk: %d\n", ret); - goto err_register; + goto err_pm_put; } + } else { + priv->clk = NULL; } priv->clk_reg = devm_clk_get(&pdev->dev, "reg"); - if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER) - return -EPROBE_DEFER; + if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto err_clk; + } if (!IS_ERR(priv->clk_reg)) { ret = clk_prepare_enable(priv->clk_reg); if (ret) { dev_err(&pdev->dev, "Unable to enable the register clk: %d\n", ret); - goto err_register; + goto err_clk; } + } else { + priv->clk_reg = NULL; } ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) : @@ -498,12 +506,14 @@ static int omap_rng_probe(struct platform_device *pdev) return 0; err_register: + clk_disable_unprepare(priv->clk_reg); +err_clk: + clk_disable_unprepare(priv->clk); +err_pm_put: priv->base = NULL; pm_runtime_put_sync(&pdev->dev); +err_pm_disable: pm_runtime_disable(&pdev->dev); - - clk_disable_unprepare(priv->clk_reg); - clk_disable_unprepare(priv->clk); err_ioremap: dev_err(dev, "initialization failed.\n"); return ret; From ae150db7826f21e8d19e54fb6243169628809c4d Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Tue, 23 Jun 2026 21:55:28 +0800 Subject: [PATCH 036/122] crypto: rk3288 - fail ahash requests on HASH idle timeout rk_hash_run() waits for RK_CRYPTO_HASH_STS to become idle after the final DMA transfer, but ignores the poll result. If the hash engine never becomes idle, the driver still reads the digest registers and finalizes the request with the previous success value. Store the poll result and finalize the request with the timeout error before reading the digest registers. Fixes: 37bc22159c45 ("crypto: rockchip - use read_poll_timeout") Signed-off-by: Pengpeng Hou Signed-off-by: Herbert Xu --- drivers/crypto/rockchip/rk3288_crypto_ahash.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c index b9f5a8b42e66..d3482619aa2f 100644 --- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c +++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c @@ -324,7 +324,12 @@ static int rk_hash_run(struct crypto_engine *engine, void *breq) * efficiency, and make it response quickly when dma * complete. */ - readl_poll_timeout(rkc->reg + RK_CRYPTO_HASH_STS, v, v == 0, 10, 1000); + err = readl_poll_timeout(rkc->reg + RK_CRYPTO_HASH_STS, v, + v == 0, 10, 1000); + if (err) { + dev_err(rkc->dev, "HASH idle timeout\n"); + goto theend; + } for (i = 0; i < crypto_ahash_digestsize(tfm) / 4; i++) { v = readl(rkc->reg + RK_CRYPTO_HASH_DOUT_0 + i * 4); From e264401ce4776a288524e5b87593d4d864147115 Mon Sep 17 00:00:00 2001 From: Myeonghun Pak Date: Wed, 24 Jun 2026 16:15:49 +0900 Subject: [PATCH 037/122] crypto: keembay - Fix AEAD unregister count in error path register_aes_algs() registers the AEAD algorithms before registering the skcipher algorithms. If skcipher registration fails, the function unwinds the earlier AEAD registration with crypto_engine_unregister_aeads(), but it passes ARRAY_SIZE(algs), which is the skcipher table size. Use ARRAY_SIZE(algs_aead) for the AEAD unwind path so the unregister helper iterates over the same table that was registered. Also clarify the nearby comment: the crypto registration helpers clean up algorithms registered within the same call, while this function must still unwind earlier successful registration steps. Fixes: 885743324513 ("crypto: keembay - Add support for Keem Bay OCS AES/SM4") Co-developed-by: Ijae Kim Signed-off-by: Ijae Kim Signed-off-by: Myeonghun Pak Signed-off-by: Herbert Xu --- drivers/crypto/intel/keembay/keembay-ocs-aes-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c index 8a8f6c81e010..0e424024224e 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c @@ -1541,7 +1541,7 @@ static int register_aes_algs(struct ocs_aes_dev *aes_dev) /* * If any algorithm fails to register, all preceding algorithms that - * were successfully registered will be automatically unregistered. + * were registered in the same call are automatically unregistered. */ ret = crypto_engine_register_aeads(algs_aead, ARRAY_SIZE(algs_aead)); if (ret) @@ -1549,7 +1549,7 @@ static int register_aes_algs(struct ocs_aes_dev *aes_dev) ret = crypto_engine_register_skciphers(algs, ARRAY_SIZE(algs)); if (ret) - crypto_engine_unregister_aeads(algs_aead, ARRAY_SIZE(algs)); + crypto_engine_unregister_aeads(algs_aead, ARRAY_SIZE(algs_aead)); return ret; } From b0e7ec0dab242c5e480121ba12400d0513e37ca2 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Tue, 2 Jun 2026 15:36:34 -0700 Subject: [PATCH 038/122] crypto: ccp - Fix possible deadlock in SEV init failure path __sev_platform_init_handle_init_ex_path() calls rmp_mark_pages_firmware() with locked=false while the parent function of init_ex_path already acquired the sev_cmd_mutex. In the case of an RMPUPDATE failure for any page after the first, the cleanup path would invoke reclaim pages which would result in a deadlock in sev_do_cmd. Pass locked=true to honor the lock status of the parent function. Fixes: 7364a6fbca45 ("crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled") Reported-by: Chris Mason Assisted-by: Claude:claude-opus-4-6 Fixes: 7364a6fbca45 ("crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled") Reviewed-by: Tom Lendacky Signed-off-by: Atish Patra Acked-by: Herbert Xu Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 8be4dab05cbb..80687be4b579 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1719,7 +1719,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev) unsigned long npages; npages = 1UL << get_order(NV_LENGTH); - if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, false)) { + if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, true)) { dev_err(sev->dev, "SEV: INIT_EX NV memory page state change failed.\n"); return -ENOMEM; } From c8e53ada20d352b0f1bdc3e58405a9edab897a2e Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Tue, 2 Jun 2026 15:36:35 -0700 Subject: [PATCH 039/122] crypto: ccp - Fix memory leak in SEV INIT_EX path allocated pages in _init_ext_path are never freed and sev_init_ex_buffer is left pointing at the leaked memory in case of any failures during the function.. Fix by adding an error path that frees the pages and clears sev_init_ex_buffer. Make sure we only free the memory if the failure happens before the conversion. Otherwise, we may end up trying to free up converted pages in case of reclaim failure. rmp_mark_pages_firmware failures should be rare enough to avoid more code complexity to track down which pages were reclaimed/leaked vs which are not. Fixes: 7364a6fbca45 ("crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled") Reported-by: Sashiko Reviewed-by: Tom Lendacky Signed-off-by: Atish Patra Acked-by: Herbert Xu Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sev-dev.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 80687be4b579..4f91b5a2408f 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1702,7 +1702,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev) if (sev_init_ex_buffer) return 0; - page = alloc_pages(GFP_KERNEL, get_order(NV_LENGTH)); + page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(NV_LENGTH)); if (!page) { dev_err(sev->dev, "SEV: INIT_EX NV memory allocation failed\n"); return -ENOMEM; @@ -1712,7 +1712,7 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev) rc = sev_read_init_ex_file(); if (rc) - return rc; + goto err_free; /* If SEV-SNP is initialized, transition to firmware page. */ if (sev->snp_initialized) { @@ -1721,11 +1721,22 @@ static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev) npages = 1UL << get_order(NV_LENGTH); if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, true)) { dev_err(sev->dev, "SEV: INIT_EX NV memory page state change failed.\n"); - return -ENOMEM; + rc = -ENOMEM; + /* + * Pages can be in an inconsistent state, don't release them back to the + * system. + */ + goto err_reset; } } return 0; + +err_free: + __free_pages(page, get_order(NV_LENGTH)); +err_reset: + sev_init_ex_buffer = NULL; + return rc; } static int __sev_platform_init_locked(int *error) From 3d1ce470e65a37abb925afd2b715599e6a9d792c Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Sun, 28 Jun 2026 23:44:35 -0700 Subject: [PATCH 040/122] dt-bindings: crypto: qcom,prng: Document Maili TRNG Maili SoC has the True Random Number Generator (TRNG) which is compatible with the baseline IP "qcom,trng". Hence, document the compatible as such. Acked-by: Krzysztof Kozlowski Signed-off-by: Jingyi Wang Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom,prng.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml index dc270c8aedf3..6116289ec413 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml @@ -23,6 +23,7 @@ properties: - qcom,ipq5424-trng - qcom,ipq9574-trng - qcom,kaanapali-trng + - qcom,maili-trng - qcom,milos-trng - qcom,nord-trng - qcom,qcs615-trng From 79f831559757625a56b932d125b40d1a84c98e38 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Sun, 28 Jun 2026 23:44:36 -0700 Subject: [PATCH 041/122] dt-bindings: crypto: qcom,inline-crypto-engine: Document Maili ICE The Inline Crypto Engine found on Maili SoC is compatible with the common baseline IP 'qcom,inline-crypto-engine' and requires the UFS_PHY_GDSC power-domain and iface clock. Hence, document the compatible as such. Signed-off-by: Jingyi Wang Acked-by: Rob Herring (Arm) Signed-off-by: Herbert Xu --- .../devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index db895c50e2d2..d80f8445393b 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -16,6 +16,7 @@ properties: - qcom,eliza-inline-crypto-engine - qcom,hawi-inline-crypto-engine - qcom,kaanapali-inline-crypto-engine + - qcom,maili-inline-crypto-engine - qcom,milos-inline-crypto-engine - qcom,qcs8300-inline-crypto-engine - qcom,sa8775p-inline-crypto-engine @@ -62,6 +63,7 @@ allOf: contains: enum: - qcom,eliza-inline-crypto-engine + - qcom,maili-inline-crypto-engine - qcom,milos-inline-crypto-engine then: From 3b67be254bd3d5dbd4360bdabc900fdcbf642d08 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Sun, 28 Jun 2026 23:44:37 -0700 Subject: [PATCH 042/122] dt-bindings: crypto: qcom,ice: Fix missing power-domain and iface clk on Hawi Fix the DT bindings for inline-crypto engine to require the UFS_PHY_GDSC power-domain and iface clock on Qualcomm Hawi platform. Fixes: d273b258d8d58 ("dt-bindings: crypto: qcom,inline-crypto-engine: Document Hawi ICE") Signed-off-by: Jingyi Wang Acked-by: Rob Herring (Arm) Signed-off-by: Herbert Xu --- .../devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index d80f8445393b..a67a4eb88007 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -63,6 +63,7 @@ allOf: contains: enum: - qcom,eliza-inline-crypto-engine + - qcom,hawi-inline-crypto-engine - qcom,maili-inline-crypto-engine - qcom,milos-inline-crypto-engine From 1c17b601fafb09c9ec074fd097737d20eafe7d63 Mon Sep 17 00:00:00 2001 From: Yuho Choi Date: Thu, 2 Jul 2026 19:39:21 -0400 Subject: [PATCH 043/122] hwrng: ks-sa - Fix runtime PM cleanup on registration failure ks_sa_rng_probe() enables runtime PM and resumes the device before registering the hwrng. If devm_hwrng_register() fails, probe returns without dropping the runtime PM usage count or disabling runtime PM. Unwind the runtime PM state on the registration failure path, matching the cleanup done by remove(). Fixes: eb428ee0e3ca ("hwrng: ks-sa - add hw_random driver") Signed-off-by: Yuho Choi Signed-off-by: Herbert Xu --- drivers/char/hw_random/ks-sa-rng.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/char/hw_random/ks-sa-rng.c b/drivers/char/hw_random/ks-sa-rng.c index 9e408144a10c..4494f1e4ab4d 100644 --- a/drivers/char/hw_random/ks-sa-rng.c +++ b/drivers/char/hw_random/ks-sa-rng.c @@ -242,7 +242,14 @@ static int ks_sa_rng_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to enable SA power-domain\n"); } - return devm_hwrng_register(&pdev->dev, &ks_sa_rng->rng); + ret = devm_hwrng_register(dev, &ks_sa_rng->rng); + if (ret) { + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + return ret; + } + + return 0; } static void ks_sa_rng_remove(struct platform_device *pdev) From 5f78264028ed63906cf8f9b44d7348182bb18c7f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 4 Jul 2026 08:44:08 +0800 Subject: [PATCH 044/122] dt-bindings: crypto: qcom,inline-crypto-engine: Document Nord ICE Document Inline Crypto Engine (ICE) on Qualcomm Nord SoC. Acked-by: Krzysztof Kozlowski Reviewed-by: Harshal Dev Signed-off-by: Shawn Guo Signed-off-by: Herbert Xu --- .../devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index a67a4eb88007..7be14e99be28 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -18,6 +18,7 @@ properties: - qcom,kaanapali-inline-crypto-engine - qcom,maili-inline-crypto-engine - qcom,milos-inline-crypto-engine + - qcom,nord-inline-crypto-engine - qcom,qcs8300-inline-crypto-engine - qcom,sa8775p-inline-crypto-engine - qcom,sc7180-inline-crypto-engine @@ -66,6 +67,7 @@ allOf: - qcom,hawi-inline-crypto-engine - qcom,maili-inline-crypto-engine - qcom,milos-inline-crypto-engine + - qcom,nord-inline-crypto-engine then: required: From 1e5004d5a3a801951a377e8a715c54d47f50e338 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Sat, 4 Jul 2026 20:15:24 +0800 Subject: [PATCH 045/122] crypto: ixp4xx - add missing MODULE_DEVICE_TABLE() The driver has an OF match table wired to .of_match_table, but does not export the table with MODULE_DEVICE_TABLE(). Add the missing MODULE_DEVICE_TABLE(of, ...) entry so module alias information is generated for OF based module autoloading. This is a source-level fix. It does not claim dynamic hardware reproduction; the evidence is the driver-owned match table, its use by the platform driver, and the missing module alias publication. Signed-off-by: Pengpeng Hou Reviewed-by: Linus Walleij Signed-off-by: Herbert Xu --- drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c index 5b90cf0fb0e4..fdda04672454 100644 --- a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c +++ b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c @@ -1591,6 +1591,7 @@ static const struct of_device_id ixp4xx_crypto_of_match[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, ixp4xx_crypto_of_match); static struct platform_driver ixp_crypto_driver = { .probe = ixp_crypto_probe, From b73b71df4cb4ca241165ad31218c82dfe489147c Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Sat, 4 Jul 2026 20:46:09 +0800 Subject: [PATCH 046/122] crypto: keembay - add missing MODULE_DEVICE_TABLE() The driver has an OF match table wired to .of_match_table, but does not export the table with MODULE_DEVICE_TABLE(). Add the missing MODULE_DEVICE_TABLE(of, ...) entry so module alias information is generated for OF based module autoloading. This is a source-level fix. It does not claim dynamic hardware reproduction; the evidence is the driver-owned match table, its use by the platform driver, and the missing module alias publication. Signed-off-by: Pengpeng Hou Signed-off-by: Herbert Xu --- drivers/crypto/intel/keembay/keembay-ocs-ecc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c index e61a95f66a0c..9e555b02086c 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c @@ -978,6 +978,7 @@ static const struct of_device_id kmb_ocs_ecc_of_match[] = { }, {} }; +MODULE_DEVICE_TABLE(of, kmb_ocs_ecc_of_match); /* The OCS driver is a platform device. */ static struct platform_driver kmb_ocs_ecc_driver = { From 34fd0e7c90e9108b734c4e1d37041d871d83d5e9 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 5 Jul 2026 15:38:39 +0200 Subject: [PATCH 047/122] crypto: qat - use strscpy_pad to simplify adf_service_string_to_mask Use strscpy_pad() to copy buf and zero-pad any trailing bytes instead of zero-initializing the local services buffer and then using strscpy() to copy into it. Also use the strscpy_pad() return value to detect string truncation instead of checking the caller-provided length. Remove the now-unused length parameters from adf_service_string_to_mask() and adf_parse_service_string(). Also remove the redundant strnlen() call in adf_get_service_mask(), which only computed the removed length argument. Signed-off-by: Thorsten Blum Reviewed-by: Thomas Huth Signed-off-by: Herbert Xu --- .../intel/qat/qat_common/adf_cfg_services.c | 15 ++++++--------- .../intel/qat/qat_common/adf_cfg_services.h | 2 +- drivers/crypto/intel/qat/qat_common/adf_sysfs.c | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c index 0cb6cb63e995..f7237c7ef2b1 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c @@ -49,18 +49,17 @@ static_assert(sizeof(ADF_CFG_SYM ADF_SERVICES_DELIMITER ADF_CFG_DCC) < ADF_CFG_MAX_VAL_LEN_IN_BYTES); static int adf_service_string_to_mask(struct adf_accel_dev *accel_dev, const char *buf, - size_t len, unsigned long *out_mask) + unsigned long *out_mask) { struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); - char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { }; + char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; unsigned long mask = 0; char *substr, *token; int id, num_svc = 0; - if (len > ADF_CFG_MAX_VAL_LEN_IN_BYTES - 1) + if (strscpy_pad(services, buf) < 0) return -EINVAL; - strscpy(services, buf); substr = services; while ((token = strsep(&substr, ADF_SERVICES_DELIMITER))) { @@ -103,12 +102,12 @@ static int adf_service_mask_to_string(unsigned long mask, char *buf, size_t len) } int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in, - size_t in_len, char *out, size_t out_len) + char *out, size_t out_len) { unsigned long mask; int ret; - ret = adf_service_string_to_mask(accel_dev, in, in_len, &mask); + ret = adf_service_string_to_mask(accel_dev, in, &mask); if (ret) return ret; @@ -121,7 +120,6 @@ int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in, int adf_get_service_mask(struct adf_accel_dev *accel_dev, unsigned long *mask) { char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { }; - size_t len; int ret; ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, @@ -132,8 +130,7 @@ int adf_get_service_mask(struct adf_accel_dev *accel_dev, unsigned long *mask) return ret; } - len = strnlen(services, ADF_CFG_MAX_VAL_LEN_IN_BYTES); - ret = adf_service_string_to_mask(accel_dev, services, len, mask); + ret = adf_service_string_to_mask(accel_dev, services, mask); if (ret) dev_err(&GET_DEV(accel_dev), "Invalid value of %s param: %s\n", ADF_SERVICES_ENABLED, services); diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.h index 913d717280af..89be2f2c7233 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_services.h +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_services.h @@ -35,7 +35,7 @@ enum { #define MAX_NUM_CONCURR_SVC ADF_THREE_SERVICES int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in, - size_t in_len, char *out, size_t out_len); + char *out, size_t out_len); int adf_get_service_enabled(struct adf_accel_dev *accel_dev); int adf_get_service_mask(struct adf_accel_dev *accel_dev, unsigned long *mask); enum adf_cfg_service_type adf_srv_to_cfg_svc_type(enum adf_base_services svc); diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c index 79c63dfa8ff3..8daa69a76b01 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c +++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c @@ -125,7 +125,7 @@ static ssize_t cfg_services_store(struct device *dev, struct device_attribute *a if (!accel_dev) return -EINVAL; - ret = adf_parse_service_string(accel_dev, buf, count, services, + ret = adf_parse_service_string(accel_dev, buf, services, ADF_CFG_MAX_VAL_LEN_IN_BYTES); if (ret) return ret; From 9ad6f337888ec85f66dd095015454cd449f68429 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 5 Jul 2026 11:44:19 -0700 Subject: [PATCH 048/122] crypto: af_alg - Allow additional ciphers for cryptsetup Add "xts(camellia)", "xts(serpent)", and "xts(twofish)" to the allowlist for af_alg_restrict=1. These niche AES alternatives have continued to see rare but persistent use via cryptsetup, which has historically relied on the AF_ALG support for these ciphers in XTS mode for performing the keyslot encryption. (cryptsetup v2.8.7 and later fall back to a temporary dm-crypt mapping, but that requires root.) Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/algif_skcipher.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 2b8069667974..49ae779b3b6b 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -45,6 +45,9 @@ static const struct af_alg_allowlist_entry skcipher_allowlist[] = { { "ecb(des)", true }, /* iwd */ { "hctr2(aes)", false }, /* cryptsetup */ { "xts(aes)", false }, /* cryptsetup benchmark */ + { "xts(camellia)", false }, /* cryptsetup */ + { "xts(serpent)", false }, /* cryptsetup */ + { "xts(twofish)", false }, /* cryptsetup */ {}, }; From 3edc28c9ade06410a7f435331f40b3e71b19abb4 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 6 Jul 2026 17:04:05 +0200 Subject: [PATCH 049/122] crypto: atmel-tdes - simplify fast path in crypt_start Fold all fast path conditions into a single boolean expression and drop any redundant checks. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index d380f6741a2c..d9cc4f657481 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -451,25 +451,19 @@ static int atmel_tdes_crypt_dma(struct atmel_tdes_dev *dd, static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd) { - int err, fast = 0, in, out; + bool fast; + int err; size_t count; dma_addr_t addr_in, addr_out; - if ((!dd->in_offset) && (!dd->out_offset)) { - /* check for alignment */ - in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32)) && - IS_ALIGNED(dd->in_sg->length, dd->ctx->block_size); - out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32)) && - IS_ALIGNED(dd->out_sg->length, dd->ctx->block_size); - fast = in && out; + fast = !dd->in_offset && !dd->out_offset && + dd->in_sg->length == dd->out_sg->length && + IS_ALIGNED(dd->in_sg->offset, sizeof(u32)) && + IS_ALIGNED(dd->out_sg->offset, sizeof(u32)) && + IS_ALIGNED(dd->in_sg->length, dd->ctx->block_size); - if (dd->in_sg->length != dd->out_sg->length) - fast = 0; - } - - - if (fast) { - count = min_t(size_t, dd->total, dd->in_sg->length); + if (fast) { + count = min(dd->total, dd->in_sg->length); err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); if (!err) { From ea4a50c0b5bb2d3b0c98b900b753dec9ad6fa457 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 6 Jul 2026 17:04:06 +0200 Subject: [PATCH 050/122] crypto: atmel-tdes - use __get_free_page in buff_init Replace __get_free_pages(..., 0) with __get_free_page(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index d9cc4f657481..32f0acae46e3 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -313,8 +313,8 @@ static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd) { int err = -ENOMEM; - dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0); - dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, 0); + dd->buf_in = (void *)__get_free_page(GFP_KERNEL); + dd->buf_out = (void *)__get_free_page(GFP_KERNEL); dd->buflen = PAGE_SIZE; dd->buflen &= ~(DES_BLOCK_SIZE - 1); From ae69d42541633bdf5edef0ab02acd208e482ec62 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 6 Jul 2026 17:04:07 +0200 Subject: [PATCH 051/122] crypto: atmel-tdes - drop redundant return variable in crypt_pdc_stop In atmel_tdes_crypt_pdc_stop(), remove the redundant return variable and return the error directly. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 32f0acae46e3..00a0b9694a26 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -285,7 +285,6 @@ static int atmel_tdes_write_ctrl(struct atmel_tdes_dev *dd) static int atmel_tdes_crypt_pdc_stop(struct atmel_tdes_dev *dd) { - int err = 0; size_t count; atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS); @@ -297,16 +296,15 @@ static int atmel_tdes_crypt_pdc_stop(struct atmel_tdes_dev *dd) dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out, dd->dma_size, DMA_FROM_DEVICE); - /* copy data */ count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset, dd->buf_out, dd->buflen, dd->dma_size, 1); if (count != dd->dma_size) { - err = -EINVAL; dev_dbg(dd->dev, "not all data converted: %zu\n", count); + return -EINVAL; } } - return err; + return 0; } static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd) From ddec4aa7c20e4e99f9a5328fa5ccb10f8c19e8dd Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 6 Jul 2026 17:04:08 +0200 Subject: [PATCH 052/122] crypto: atmel-tdes - drop redundant if check in crypt_dma_stop The call site already checks dd->flags & TDES_FLAGS_DMA before calling atmel_tdes_crypt_dma_stop(). Remove the redundant check, return early on error, and drop the now-obsolete return variable. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 00a0b9694a26..208910d0d08d 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -601,28 +601,25 @@ static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd, static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd) { - int err = -EINVAL; size_t count; - if (dd->flags & TDES_FLAGS_DMA) { - err = 0; - if (dd->flags & TDES_FLAGS_FAST) { - dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE); - dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); - } else { - dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out, - dd->dma_size, DMA_FROM_DEVICE); + if (dd->flags & TDES_FLAGS_FAST) { + dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE); + dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); + } else { + dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out, dd->dma_size, + DMA_FROM_DEVICE); - /* copy data */ - count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset, - dd->buf_out, dd->buflen, dd->dma_size, 1); - if (count != dd->dma_size) { - err = -EINVAL; - dev_dbg(dd->dev, "not all data converted: %zu\n", count); - } + count = atmel_tdes_sg_copy(&dd->out_sg, &dd->out_offset, + dd->buf_out, dd->buflen, + dd->dma_size, 1); + if (count != dd->dma_size) { + dev_dbg(dd->dev, "not all data converted: %zu\n", count); + return -EINVAL; } } - return err; + + return 0; } static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode) From 21d04ac27e7419d1a4530b198525a08b0ac46538 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 8 Jul 2026 17:04:00 +0200 Subject: [PATCH 053/122] crypto: atmel-sha204a - clear RNG data from memory In atmel_sha204a_rng_read(), use memzero_explicit() to clear the local stack variable cmd before it goes out of scope, since cmd.data may still hold the last 32 random bytes. Since atmel_sha204a_rng_done() caches work_data in hwrng::priv, and its response data is later used as RNG entropy, use kfree_sensitive() to clear the cached data on transaction failure and device removal. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha204a.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 5eb76245347d..21a84c29c9b7 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include "atmel-i2c.h" @@ -35,7 +36,7 @@ static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data, dev_warn_ratelimited(&i2c_priv->client->dev, "i2c transaction failed (%d)\n", status); - kfree(work_data); + kfree_sensitive(work_data); atomic_dec(&i2c_priv->tfm_count); return; } @@ -95,12 +96,15 @@ static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max, ret = atmel_i2c_send_receive(i2c_priv->client, &cmd); if (ret) - return ret; + goto out; max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); memcpy(data, &cmd.data[RSP_DATA_IDX], max); + ret = max; - return max; +out: + memzero_explicit(&cmd, sizeof(cmd)); + return ret; } static int atmel_sha204a_otp_read(struct i2c_client *client, u16 addr, u8 *otp) @@ -209,7 +213,7 @@ static void atmel_sha204a_remove(struct i2c_client *client) devm_hwrng_unregister(&client->dev, &i2c_priv->hwrng); atmel_i2c_flush_queue(); - kfree((void *)i2c_priv->hwrng.priv); + kfree_sensitive((void *)i2c_priv->hwrng.priv); } static const struct of_device_id atmel_sha204a_dt_ids[] = { From f07a0d251db7606e4792d2610788fbcc7b2c0d12 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 8 Jul 2026 22:42:48 +0200 Subject: [PATCH 054/122] crypto: atmel-ecc - avoid stale fallback key after set_secret failure Clear ->do_fallback before decoding a new ECDH secret and enable it only after the software fallback accepts a caller-provided private key. This avoids using a stale fallback key should crypto_kpp_set_secret() fail. Fixes: 11105693fa05 ("crypto: atmel-ecc - introduce Microchip / Atmel ECC driver") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 8e13aeccf011..4add3b2ddd0b 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -82,6 +82,7 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, kfree(ctx->public_key); ctx->public_key = NULL; + ctx->do_fallback = false; if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0) { dev_err(&ctx->client->dev, "crypto_ecdh_decode_key failed\n"); @@ -89,8 +90,9 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, } if (params.key_size) { - ctx->do_fallback = true; - return crypto_kpp_set_secret(ctx->fallback, buf, len); + ret = crypto_kpp_set_secret(ctx->fallback, buf, len); + ctx->do_fallback = !ret; + return ret; } cmd = kmalloc_obj(*cmd); @@ -101,8 +103,6 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, if (!public_key) goto free_cmd; - ctx->do_fallback = false; - atmel_i2c_init_genkey_cmd(cmd, DATA_SLOT_2); ret = atmel_i2c_send_receive(ctx->client, cmd); From 52cd75d8f5a024cad9643f4755dbe6bff1e5aec8 Mon Sep 17 00:00:00 2001 From: Manuel Ebner Date: Thu, 9 Jul 2026 16:38:37 +0200 Subject: [PATCH 055/122] crypto: doc - Remove extra parenthesis Remove needless ')' from code block. Fixes: 3b72c814a8e8 ("crypto: doc - convert crypto API documentation to Sphinx") Signed-off-by: Manuel Ebner Acked-by: Randy Dunlap Signed-off-by: Herbert Xu --- Documentation/crypto/architecture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/crypto/architecture.rst b/Documentation/crypto/architecture.rst index 249b54d0849f..ec2e99d99aff 100644 --- a/Documentation/crypto/architecture.rst +++ b/Documentation/crypto/architecture.rst @@ -95,7 +95,7 @@ additional templates may enclose other templates, such as :: - template1(template2(single block cipher))) + template1(template2(single block cipher)) The kernel crypto API may provide multiple implementations of a template From 3ae59a2eba64b3648f069aa52eeaaeefdfe4bb2f Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 10 Jul 2026 09:42:17 +0200 Subject: [PATCH 056/122] crypto: sl3516 - drop invalid sg_dma_len checks before DMA mapping sg_dma_len() is only valid after mapping the scatterlist with dma_map_sg(). However, sl3516_ce_need_fallback() checks it before the source and destination scatterlists are mapped. Thus, a stale DMA length that is not a multiple of 16 could incorrectly force a software fallback when CONFIG_NEED_SG_DMA_LENGTH=y. Remove the invalid checks; the existing scatterlist length checks are sufficient. Fixes: 46c5338db7bd ("crypto: sl3516 - Add sl3516 crypto engine") Signed-off-by: Thorsten Blum Acked-by: Linus Walleij Signed-off-by: Herbert Xu --- drivers/crypto/gemini/sl3516-ce-cipher.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/crypto/gemini/sl3516-ce-cipher.c b/drivers/crypto/gemini/sl3516-ce-cipher.c index 583010b2d007..02ec4282333b 100644 --- a/drivers/crypto/gemini/sl3516-ce-cipher.c +++ b/drivers/crypto/gemini/sl3516-ce-cipher.c @@ -56,10 +56,6 @@ static bool sl3516_ce_need_fallback(struct skcipher_request *areq) ce->fallback_mod16++; return true; } - if ((sg_dma_len(sg) % 16) != 0) { - ce->fallback_mod16++; - return true; - } if (!IS_ALIGNED(sg->offset, 16)) { ce->fallback_align16++; return true; @@ -72,10 +68,6 @@ static bool sl3516_ce_need_fallback(struct skcipher_request *areq) ce->fallback_mod16++; return true; } - if ((sg_dma_len(sg) % 16) != 0) { - ce->fallback_mod16++; - return true; - } if (!IS_ALIGNED(sg->offset, 16)) { ce->fallback_align16++; return true; From cad76142aaa46a8a9e1a2f9b473b7792c733969b Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 10 Jul 2026 18:53:06 +0800 Subject: [PATCH 057/122] hwrng: drivers - Remove redundant dev_err()/dev_err_probe() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() and dev_err_probe() calls. Signed-off-by: Pan Chuang Signed-off-by: Herbert Xu --- drivers/char/hw_random/airoha-trng.c | 4 +--- drivers/char/hw_random/cctrng.c | 2 +- drivers/char/hw_random/imx-rngc.c | 2 +- drivers/char/hw_random/jh7110-trng.c | 3 +-- drivers/char/hw_random/omap-rng.c | 5 +---- drivers/char/hw_random/xgene-rng.c | 2 +- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/char/hw_random/airoha-trng.c b/drivers/char/hw_random/airoha-trng.c index 9a648f6d9fd4..1541c38a2f4b 100644 --- a/drivers/char/hw_random/airoha-trng.c +++ b/drivers/char/hw_random/airoha-trng.c @@ -187,10 +187,8 @@ static int airoha_trng_probe(struct platform_device *pdev) airoha_trng_irq_mask(trng); ret = devm_request_irq(&pdev->dev, irq, airoha_trng_irq, 0, pdev->name, (void *)trng); - if (ret) { - dev_err(dev, "Can't get interrupt working.\n"); + if (ret) return ret; - } init_completion(&trng->rng_op_done); diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c index a5be9258037f..a6925211c3b5 100644 --- a/drivers/char/hw_random/cctrng.c +++ b/drivers/char/hw_random/cctrng.c @@ -509,7 +509,7 @@ static int cctrng_probe(struct platform_device *pdev) /* register the driver isr function */ rc = devm_request_irq(dev, irq, cc_isr, IRQF_SHARED, "cctrng", drvdata); if (rc) - return dev_err_probe(dev, rc, "Could not register to interrupt %d\n", irq); + return rc; dev_dbg(dev, "Registered to IRQ: %d\n", irq); /* Clear all pending interrupts */ diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index 241664a9b5d9..fb43894a906b 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -297,7 +297,7 @@ static int __init imx_rngc_probe(struct platform_device *pdev) irq, imx_rngc_irq, 0, pdev->name, (void *)rngc); if (ret) { clk_disable_unprepare(rngc->clk); - return dev_err_probe(&pdev->dev, ret, "Can't get interrupt working.\n"); + return ret; } if (self_test) { diff --git a/drivers/char/hw_random/jh7110-trng.c b/drivers/char/hw_random/jh7110-trng.c index 4712c3c530e4..aee12caab578 100644 --- a/drivers/char/hw_random/jh7110-trng.c +++ b/drivers/char/hw_random/jh7110-trng.c @@ -303,8 +303,7 @@ static int starfive_trng_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, irq, starfive_trng_irq, 0, pdev->name, (void *)trng); if (ret) - return dev_err_probe(&pdev->dev, ret, - "Failed to register interrupt handler\n"); + return ret; trng->hclk = devm_clk_get(&pdev->dev, "hclk"); if (IS_ERR(trng->hclk)) diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index a8c0b3dfb133..9f0545c67774 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -391,11 +391,8 @@ static int of_get_omap_rng_device_details(struct omap_rng_dev *priv, err = devm_request_irq(dev, irq, omap4_rng_irq, IRQF_TRIGGER_NONE, dev_name(dev), priv); - if (err) { - dev_err(dev, "unable to request irq %d, err = %d\n", - irq, err); + if (err) return err; - } /* * On OMAP4, enabling the shutdown_oflo interrupt is diff --git a/drivers/char/hw_random/xgene-rng.c b/drivers/char/hw_random/xgene-rng.c index 709a36507145..97e505c2fcd1 100644 --- a/drivers/char/hw_random/xgene-rng.c +++ b/drivers/char/hw_random/xgene-rng.c @@ -337,7 +337,7 @@ static int xgene_rng_probe(struct platform_device *pdev) rc = devm_request_irq(&pdev->dev, ctx->irq, xgene_rng_irq_handler, 0, dev_name(&pdev->dev), ctx); if (rc) - return dev_err_probe(&pdev->dev, rc, "Could not request RNG alarm IRQ\n"); + return rc; /* Enable IP clock */ clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); From eed5fde79651c66e0e24ba3d78a92afb63a76215 Mon Sep 17 00:00:00 2001 From: Narasimharao Vadlamudi Date: Fri, 10 Jul 2026 16:37:29 +0530 Subject: [PATCH 058/122] crypto: aspeed - Propagate platform_get_irq() errors platform_get_irq() returns a positive IRQ number on success and a negative error code on failure. aspeed_acry_probe() and aspeed_hace_probe() already detect negative returns, but both convert every failure to -ENXIO. Return the original error code so callers can handle errors such as -EPROBE_DEFER correctly. Fixes: 2f1cf4e50c95 ("crypto: aspeed - Add ACRY RSA driver") Fixes: 70513e1d6559 ("crypto: aspeed - Fix check for platform_get_irq() errors") Signed-off-by: Narasimharao Vadlamudi Signed-off-by: Herbert Xu --- drivers/crypto/aspeed/aspeed-acry.c | 2 +- drivers/crypto/aspeed/aspeed-hace.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/aspeed/aspeed-acry.c b/drivers/crypto/aspeed/aspeed-acry.c index 5993bcba9716..301612556a76 100644 --- a/drivers/crypto/aspeed/aspeed-acry.c +++ b/drivers/crypto/aspeed/aspeed-acry.c @@ -728,7 +728,7 @@ static int aspeed_acry_probe(struct platform_device *pdev) /* Get irq number and register it */ acry_dev->irq = platform_get_irq(pdev, 0); if (acry_dev->irq < 0) - return -ENXIO; + return acry_dev->irq; rc = devm_request_irq(dev, acry_dev->irq, aspeed_acry_irq, 0, dev_name(dev), acry_dev); diff --git a/drivers/crypto/aspeed/aspeed-hace.c b/drivers/crypto/aspeed/aspeed-hace.c index 3fe644bfe037..1f9afa002ae8 100644 --- a/drivers/crypto/aspeed/aspeed-hace.c +++ b/drivers/crypto/aspeed/aspeed-hace.c @@ -127,7 +127,7 @@ static int aspeed_hace_probe(struct platform_device *pdev) /* Get irq number and register it */ hace_dev->irq = platform_get_irq(pdev, 0); if (hace_dev->irq < 0) - return -ENXIO; + return hace_dev->irq; rc = devm_request_irq(&pdev->dev, hace_dev->irq, aspeed_hace_irq, 0, dev_name(&pdev->dev), hace_dev); From 8fbd4a0f506fe029510a982717c63cf64b0bc27b Mon Sep 17 00:00:00 2001 From: "Miquel Raynal (Schneider Electric)" Date: Fri, 10 Jul 2026 20:20:32 +0200 Subject: [PATCH 059/122] dt-bindings: rng: Rename the title of the EIP-76 file Be a little more precise in the title by giving the family name and the own name of the hardware block. Despite the original compatibles, this file describes a SafeXcel EIP-76 hardware random number generator. Signed-off-by: Miquel Raynal (Schneider Electric) Acked-by: Rob Herring (Arm) Acked-by: Wolfram Sang Signed-off-by: Herbert Xu --- .../devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml b/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml index f501fc7691c6..92d906998211 100644 --- a/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml +++ b/Documentation/devicetree/bindings/rng/inside-secure,safexcel-eip76.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/rng/inside-secure,safexcel-eip76.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Inside-Secure HWRNG Module +title: Inside-Secure SafeXcel EIP-76 HWRNG Module maintainers: - Jayesh Choudhary From 86c7771a2e88a805d56abfa18545bdc0274f8d41 Mon Sep 17 00:00:00 2001 From: "Miquel Raynal (Schneider Electric)" Date: Fri, 10 Jul 2026 20:20:33 +0200 Subject: [PATCH 060/122] hwrng: omap - Enable on Renesas RZ/N1D The Kconfig symbol and associated seem to be badly named as they have nothing OMAP specific but instead refer to Inside Secure Safexcel devices which have been used in many SoCs from different manufacturers (like OMAP, Marvell but also eg. Renesas). The Renesas RZ/N1D features this IP, so add this architecture to the dependency allow list. In practice this dependency list does not seem very relevant and could be entirely dropped, given the fact that this IP has been implemented by many different vendors and seems to be architecture agnostic. Signed-off-by: Miquel Raynal (Schneider Electric) Reviewed-by: Wolfram Sang Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index b4c359abc4f9..1bf5e3f8a557 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -193,7 +193,7 @@ config HW_RANDOM_IXP4XX config HW_RANDOM_OMAP tristate "OMAP Random Number Generator support" - depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || ARCH_MVEBU || ARCH_K3 || COMPILE_TEST + depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || ARCH_MVEBU || ARCH_K3 || ARCH_RZN1 || COMPILE_TEST default HW_RANDOM help This driver provides kernel-side support for the Random Number From d4e273a5065f81ca86eca48cb3fed55867cc0115 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 11 Jul 2026 16:52:17 +0200 Subject: [PATCH 061/122] crypto: powerpc/aes - use bool for encryption/decryption flag Use bool for the CBC encryption/decryption flag passed through p8_aes_cbc_crypt() to aes_p8_cbc_encrypt(). Signed-off-by: Thorsten Blum Reviewed-by: Breno Leitao Signed-off-by: Herbert Xu --- arch/powerpc/crypto/aes_cbc.c | 6 +++--- include/crypto/aes.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/crypto/aes_cbc.c b/arch/powerpc/crypto/aes_cbc.c index 4a9f285f0970..9c271b4642c8 100644 --- a/arch/powerpc/crypto/aes_cbc.c +++ b/arch/powerpc/crypto/aes_cbc.c @@ -72,7 +72,7 @@ static int p8_aes_cbc_setkey(struct crypto_skcipher *tfm, const u8 *key, return ret ? -EINVAL : 0; } -static int p8_aes_cbc_crypt(struct skcipher_request *req, int enc) +static int p8_aes_cbc_crypt(struct skcipher_request *req, bool enc) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); const struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); @@ -110,12 +110,12 @@ static int p8_aes_cbc_crypt(struct skcipher_request *req, int enc) static int p8_aes_cbc_encrypt(struct skcipher_request *req) { - return p8_aes_cbc_crypt(req, 1); + return p8_aes_cbc_crypt(req, true); } static int p8_aes_cbc_decrypt(struct skcipher_request *req) { - return p8_aes_cbc_crypt(req, 0); + return p8_aes_cbc_crypt(req, false); } struct skcipher_alg p8_aes_cbc_alg = { diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 16fbfd93e2bd..3279cfa54608 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -259,7 +259,7 @@ int aes_p8_set_decrypt_key(const u8 *userKey, const int bits, void aes_p8_encrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); void aes_p8_decrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); void aes_p8_cbc_encrypt(const u8 *in, u8 *out, size_t len, - const struct p8_aes_key *key, u8 *iv, const int enc); + const struct p8_aes_key *key, u8 *iv, bool enc); void aes_p8_ctr32_encrypt_blocks(const u8 *in, u8 *out, size_t len, const struct p8_aes_key *key, const u8 *iv); void aes_p8_xts_encrypt(const u8 *in, u8 *out, size_t len, From df373d39c6f038d176af303ae72f02c7c70b953d Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Sun, 12 Jul 2026 17:31:31 -0400 Subject: [PATCH 062/122] crypto: qce - Mark QCE as BROKEN This driver is harmful: - It is much slower than the CPU [1] [2]. - It Has a history of bugs [2] [3]. - It does not have exclusive access to the hardware [4], causing races with the secure world. - It register its implementations with too low a cra_priority for them to be actually used [5]. Therefore, disable it to ensure that nobody builds it into kernels they intend to ship. In the future, the driver will be used for processing restricted media content. However, the kernel does not currently support this. Since the driver will have future uses, allow building it if COMPILE_TEST is enabled. [1]: https://lore.kernel.org/r/20250704070322.20692-1-ebiggers@kernel.org/ [2]: https://lore.kernel.org/r/20250615031807.GA81869@sol/ [3]: https://lore.kernel.org/r/20260706-qce-fix-self-tests-v5-0-86f461ff1829@oss.qualcomm.com/ [4]: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-0-56f67da84c05@oss.qualcomm.com/ [5]: https://lore.kernel.org/r/20260524204537.GB110177@quark/ Fixes: ec8f5d8f6f76 ("crypto: qce - Qualcomm crypto engine driver") Signed-off-by: Demi Marie Obenour Acked-by: Eric Biggers Signed-off-by: Herbert Xu --- arch/arm/configs/multi_v7_defconfig | 1 - arch/arm64/configs/defconfig | 1 - drivers/crypto/Kconfig | 6 +++++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 01e016752c4d..13d85a0e8580 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -1321,7 +1321,6 @@ CONFIG_CRYPTO_DEV_ATMEL_AES=m CONFIG_CRYPTO_DEV_ATMEL_TDES=m CONFIG_CRYPTO_DEV_ATMEL_SHA=m CONFIG_CRYPTO_DEV_MARVELL_CESA=m -CONFIG_CRYPTO_DEV_QCE=m CONFIG_CRYPTO_DEV_ROCKCHIP=m CONFIG_CRYPTO_DEV_STM32_HASH=m CONFIG_CRYPTO_DEV_STM32_CRYP=m diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 76ce07a08d5a..c624cdd122d1 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1940,7 +1940,6 @@ CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRYPTO_DEV_SUN8I_CE=m CONFIG_CRYPTO_DEV_FSL_CAAM=m CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m -CONFIG_CRYPTO_DEV_QCE=m CONFIG_CRYPTO_DEV_TEGRA=m CONFIG_CRYPTO_DEV_ZYNQMP_AES=m CONFIG_CRYPTO_DEV_ZYNQMP_SHA3=m diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 03a8f7a1f75e..0189dfdcbbe1 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -528,13 +528,17 @@ source "drivers/crypto/intel/Kconfig" config CRYPTO_DEV_QCE tristate "Qualcomm crypto engine accelerator" - depends on ARCH_QCOM || COMPILE_TEST + depends on (BROKEN && ARCH_QCOM) || COMPILE_TEST depends on HAS_IOMEM help This driver supports Qualcomm crypto engine accelerator hardware. To compile this driver as a module, choose M here. The module will be called qcrypto. + This driver does not have exclusive access to the + hardware, causing races with the secure world. It + is also slower than the CPU. + config CRYPTO_DEV_QCE_SKCIPHER bool depends on CRYPTO_DEV_QCE From fce20289dd622cc7ab78d72c8a979a9f8b7cb10e Mon Sep 17 00:00:00 2001 From: Linmao Li Date: Tue, 14 Jul 2026 11:30:15 +0800 Subject: [PATCH 063/122] crypto: keembay - Initialize completion before requesting IRQ kmb_ocs_aes_probe() requests the device IRQ before initializing irq_completion. Once the handler is registered it can run immediately, and ocs_aes_irq_handler() unconditionally calls complete(). An interrupt in this window would therefore use an uninitialized completion. Initialize the completion before requesting the IRQ, as the sibling OCS HCU and ECC drivers already do. Fixes: 885743324513 ("crypto: keembay - Add support for Keem Bay OCS AES/SM4") Signed-off-by: Linmao Li Signed-off-by: Herbert Xu --- drivers/crypto/intel/keembay/keembay-ocs-aes-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c index 0e424024224e..460a943cca22 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c @@ -1602,6 +1602,8 @@ static int kmb_ocs_aes_probe(struct platform_device *pdev) if (IS_ERR(aes_dev->base_reg)) return PTR_ERR(aes_dev->base_reg); + init_completion(&aes_dev->irq_completion); + /* Get and request IRQ */ aes_dev->irq = platform_get_irq(pdev, 0); if (aes_dev->irq < 0) @@ -1619,8 +1621,6 @@ static int kmb_ocs_aes_probe(struct platform_device *pdev) list_add_tail(&aes_dev->list, &ocs_aes.dev_list); spin_unlock(&ocs_aes.lock); - init_completion(&aes_dev->irq_completion); - /* Initialize crypto engine */ aes_dev->engine = crypto_engine_alloc_init(dev, true); if (!aes_dev->engine) { From 3360fa7604259a0341a9bdbb0a8cb0fd7f3109de Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 14 Jul 2026 15:35:12 +0530 Subject: [PATCH 064/122] dt-bindings: crypto: qcom,inline-crypto-engine: Fix legacy/new SoC strictness split Couple of already merged SoCs(like sc7280, sm8750, kaanapali etc.) describe ICE as single clock historically which are recently updated with mandatory 2 clocks. Keep only the known legacy compatibles flexible, and make strict validation default(of power-domains and 2 clocks) for all other Soc compatibles. This ensures old DTs are valid while ensuring any new SoC (like hawi, milos, eliza, nord, maili or any upcoming ones) must follow latest requirements by default. Signed-off-by: Kuldeep Singh Reviewed-by: Krzysztof Kozlowski Reviewed-by: Bartosz Golaszewski Signed-off-by: Herbert Xu --- .../crypto/qcom,inline-crypto-engine.yaml | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index 7be14e99be28..cce21aae6499 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -57,17 +57,25 @@ required: additionalProperties: false +# Do not extend the list. +# Legacy SoCs are allowed for single clock. +# New SoCs must provide both clocks and power domains. allOf: - if: - properties: - compatible: - contains: - enum: - - qcom,eliza-inline-crypto-engine - - qcom,hawi-inline-crypto-engine - - qcom,maili-inline-crypto-engine - - qcom,milos-inline-crypto-engine - - qcom,nord-inline-crypto-engine + not: + properties: + compatible: + contains: + enum: + - qcom,kaanapali-inline-crypto-engine + - qcom,qcs8300-inline-crypto-engine + - qcom,sa8775p-inline-crypto-engine + - qcom,sc7180-inline-crypto-engine + - qcom,sc7280-inline-crypto-engine + - qcom,sm8450-inline-crypto-engine + - qcom,sm8550-inline-crypto-engine + - qcom,sm8650-inline-crypto-engine + - qcom,sm8750-inline-crypto-engine then: required: From bcfea926aa3ed65309f16a1501d2c1aebf3ae26c Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 14 Jul 2026 15:35:13 +0530 Subject: [PATCH 065/122] dt-bindings: crypto: qcom,inline-crypto-engine: Document Shikra ICE Document the Inline Crypto Engine (ICE) on the Qualcomm Shikra platform. Signed-off-by: Kuldeep Singh Reviewed-by: Bartosz Golaszewski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- .../devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index cce21aae6499..ed2dd99eb1b1 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -23,6 +23,7 @@ properties: - qcom,sa8775p-inline-crypto-engine - qcom,sc7180-inline-crypto-engine - qcom,sc7280-inline-crypto-engine + - qcom,shikra-inline-crypto-engine - qcom,sm8450-inline-crypto-engine - qcom,sm8550-inline-crypto-engine - qcom,sm8650-inline-crypto-engine From 3c4ba9d03be3d12cf01b2f61ce382aa34d3da21f Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 14 Jul 2026 15:35:14 +0530 Subject: [PATCH 066/122] dt-bindings: crypto: qcom,prng: Document Shikra TRNG Document shikra compatible for the True Random Number Generator. Signed-off-by: Kuldeep Singh Reviewed-by: Bartosz Golaszewski Acked-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom,prng.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml index 6116289ec413..de323969fe64 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml @@ -31,6 +31,7 @@ properties: - qcom,sa8255p-trng - qcom,sa8775p-trng - qcom,sc7280-trng + - qcom,shikra-trng - qcom,sm8450-trng - qcom,sm8550-trng - qcom,sm8650-trng From 45834ff95a6fa1986898f2ef62b984d9736cf4e1 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 14 Jul 2026 15:35:15 +0530 Subject: [PATCH 067/122] dt-bindings: crypto: qcom-qce: Document the Shikra crypto engine Document the crypto engine on the Qualcomm Shikra platform. Signed-off-by: Kuldeep Singh Reviewed-by: Bartosz Golaszewski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/crypto/qcom-qce.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml index 08febd66c22b..5a653757ee75 100644 --- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml @@ -54,6 +54,7 @@ properties: - qcom,qcs8300-qce - qcom,sa8775p-qce - qcom,sc7280-qce + - qcom,shikra-qce - qcom,sm6350-qce - qcom,sm8250-qce - qcom,sm8350-qce From 0a94091e29f914e4f233a208599ca4055882c01b Mon Sep 17 00:00:00 2001 From: Can Peng Date: Tue, 14 Jul 2026 21:14:42 +0800 Subject: [PATCH 068/122] crypto: keembay - publish OF module alias for OCS AES/SM4 The Keem Bay OCS AES/SM4 driver has an OF match table wired to .of_match_table, but does not export the table with MODULE_DEVICE_TABLE(). Although the match table lives in keembay-ocs-aes-core.o, that object is part of the composite keembay-ocs-aes module. Add the missing MODULE_DEVICE_TABLE(of, ...) entry so modpost can generate OF module alias information for OF based module autoloading. This is a source-level fix. It does not claim dynamic hardware reproduction; the evidence is the driver-owned match table, its use by the platform driver, and the missing module alias publication. Fixes: 885743324513 ("crypto: keembay - Add support for Keem Bay OCS AES/SM4") Signed-off-by: Can Peng Signed-off-by: Herbert Xu --- drivers/crypto/intel/keembay/keembay-ocs-aes-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c index 460a943cca22..419f88af1031 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c @@ -1561,6 +1561,7 @@ static const struct of_device_id kmb_ocs_aes_of_match[] = { }, {} }; +MODULE_DEVICE_TABLE(of, kmb_ocs_aes_of_match); static void kmb_ocs_aes_remove(struct platform_device *pdev) { From 83418a2c5bc1c9a7f4c109fd58c583c8c3f37964 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 14 Jul 2026 18:15:33 -0700 Subject: [PATCH 069/122] crypto: hisilicon/sec - use devm_platform_ioremap_resource in sec_map_io Replace the open-coded platform_get_resource() plus devm_ioremap() sequence in the SEC_NUM_ADDR_REGIONS loop with devm_platform_ioremap_resource(), which fetches the resource, requests the region and maps it in one call. Switch the error check to IS_ERR()/PTR_ERR() and drop the now-unused struct resource pointer. The driver only maps indices 0 and 1 (SEC_COMMON, SEC_SAA). On hip07 the corresponding reg regions (0xd0000000, 0xd2000000) are 0x10000 each and disjoint, so the region reservation added by devm_ioremap_resource() is exclusive and does not introduce overlap failures. Built for arm64 (drivers/crypto/hisilicon/sec/sec_drv.o) with LLVM=1. Assisted-by: opencode:hy3-free Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/sec/sec_drv.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/hisilicon/sec/sec_drv.c b/drivers/crypto/hisilicon/sec/sec_drv.c index 129cb6faa0b7..2514a5e1f9b4 100644 --- a/drivers/crypto/hisilicon/sec/sec_drv.c +++ b/drivers/crypto/hisilicon/sec/sec_drv.c @@ -1010,25 +1010,12 @@ static void sec_queue_base_init(struct sec_dev_info *info, static int sec_map_io(struct sec_dev_info *info, struct platform_device *pdev) { - struct resource *res; int i; for (i = 0; i < SEC_NUM_ADDR_REGIONS; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - - if (!res) { - dev_err(info->dev, "Memory resource %d not found\n", i); - return -EINVAL; - } - - info->regs[i] = devm_ioremap(info->dev, res->start, - resource_size(res)); - if (!info->regs[i]) { - dev_err(info->dev, - "Memory resource %d could not be remapped\n", - i); - return -EINVAL; - } + info->regs[i] = devm_platform_ioremap_resource(pdev, i); + if (IS_ERR(info->regs[i])) + return PTR_ERR(info->regs[i]); } return 0; From 6e6a89b930ca3ea1a85170cb05b784d76a5001a1 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 15 Jul 2026 14:58:48 -0700 Subject: [PATCH 070/122] crypto: omap-aes - use devm_platform_get_and_ioremap_resource Replace the open-coded omap_aes_get_res_of()/omap_aes_get_res_pdev() helpers and the #ifdef CONFIG_OF machinery with the managed devm_platform_get_and_ioremap_resource(), platform_get_irq() and device_get_match_data() helpers. The omap_aes_pdata_omap2 fallback is kept for the non-DT (legacy platform_device) case, and the now-unused err_res label is removed. Assisted-by: opencode:hy3-free Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/omap-aes.c | 84 ++++++--------------------------------- 1 file changed, 12 insertions(+), 72 deletions(-) diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index f31555c0d715..a5fce216de34 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -952,65 +951,8 @@ static const struct of_device_id omap_aes_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, omap_aes_of_match); - -static int omap_aes_get_res_of(struct omap_aes_dev *dd, - struct device *dev, struct resource *res) -{ - struct device_node *node = dev->of_node; - int err = 0; - - dd->pdata = of_device_get_match_data(dev); - if (!dd->pdata) { - dev_err(dev, "no compatible OF match\n"); - err = -EINVAL; - goto err; - } - - err = of_address_to_resource(node, 0, res); - if (err < 0) { - dev_err(dev, "can't translate OF node address\n"); - err = -EINVAL; - goto err; - } - -err: - return err; -} -#else -static const struct of_device_id omap_aes_of_match[] = { - {}, -}; - -static int omap_aes_get_res_of(struct omap_aes_dev *dd, - struct device *dev, struct resource *res) -{ - return -EINVAL; -} #endif -static int omap_aes_get_res_pdev(struct omap_aes_dev *dd, - struct platform_device *pdev, struct resource *res) -{ - struct device *dev = &pdev->dev; - struct resource *r; - int err = 0; - - /* Get the base address */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(dev, "no MEM resource info\n"); - err = -ENODEV; - goto err; - } - memcpy(res, r, sizeof(*res)); - - /* Only OMAP2/3 can be non-DT */ - dd->pdata = &omap_aes_pdata_omap2; - -err: - return err; -} - static ssize_t fallback_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1109,10 +1051,15 @@ static int omap_aes_probe(struct platform_device *pdev) struct omap_aes_dev *dd; struct skcipher_engine_alg *algp; struct aead_engine_alg *aalg; - struct resource res; + struct resource *res; + void __iomem *io_base; int err = -ENOMEM, i, j, irq = -1; u32 reg; + io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(io_base)) + return PTR_ERR(io_base); + dd = devm_kzalloc(dev, sizeof(struct omap_aes_dev), GFP_KERNEL); if (dd == NULL) { dev_err(dev, "unable to alloc data struct.\n"); @@ -1123,17 +1070,12 @@ static int omap_aes_probe(struct platform_device *pdev) aead_init_queue(&dd->aead_queue, OMAP_AES_QUEUE_LENGTH); - err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) : - omap_aes_get_res_pdev(dd, pdev, &res); - if (err) - goto err_res; + dd->pdata = device_get_match_data(dev); + if (!dd->pdata) + dd->pdata = &omap_aes_pdata_omap2; - dd->io_base = devm_ioremap_resource(dev, &res); - if (IS_ERR(dd->io_base)) { - err = PTR_ERR(dd->io_base); - goto err_res; - } - dd->phys_base = res.start; + dd->io_base = io_base; + dd->phys_base = res->start; pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY); @@ -1244,8 +1186,6 @@ static int omap_aes_probe(struct platform_device *pdev) cancel_work_sync(&dd->done_task); err_pm_disable: pm_runtime_disable(dev); -err_res: - dd = NULL; err_data: dev_err(dev, "initialization failed.\n"); return err; @@ -1294,7 +1234,7 @@ static struct platform_driver omap_aes_driver = { .driver = { .name = "omap-aes", .pm = &omap_aes_pm_ops, - .of_match_table = omap_aes_of_match, + .of_match_table = of_match_ptr(omap_aes_of_match), .dev_groups = omap_aes_groups, }, }; From f13b83d881254cabbf925ba0e039226bd9fb468e Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 15 Jul 2026 15:00:13 -0700 Subject: [PATCH 071/122] crypto: omap-sham - use devm_platform_get_and_ioremap_resource Replace the open-coded omap_sham_get_res_of()/omap_sham_get_res_pdev() helpers and the #ifdef CONFIG_OF machinery with the managed devm_platform_get_and_ioremap_resource(), platform_get_irq() and device_get_match_data() helpers. The omap_sham_pdata_omap2 fallback is kept for the non-DT (legacy platform_device) case. This removes the manual resource copy and ioremap, simplifying probe. Assisted-by: opencode:hy3-free Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/omap-sham.c | 104 +++++++------------------------------ 1 file changed, 18 insertions(+), 86 deletions(-) diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index be1ac640ee59..e8e111bd438a 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -30,8 +30,6 @@ #include #include #include -#include -#include #include #include #include @@ -1896,79 +1894,8 @@ static const struct of_device_id omap_sham_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, omap_sham_of_match); - -static int omap_sham_get_res_of(struct omap_sham_dev *dd, - struct device *dev, struct resource *res) -{ - struct device_node *node = dev->of_node; - int err = 0; - - dd->pdata = of_device_get_match_data(dev); - if (!dd->pdata) { - dev_err(dev, "no compatible OF match\n"); - err = -EINVAL; - goto err; - } - - err = of_address_to_resource(node, 0, res); - if (err < 0) { - dev_err(dev, "can't translate OF node address\n"); - err = -EINVAL; - goto err; - } - - dd->irq = irq_of_parse_and_map(node, 0); - if (!dd->irq) { - dev_err(dev, "can't translate OF irq value\n"); - err = -EINVAL; - goto err; - } - -err: - return err; -} -#else -static const struct of_device_id omap_sham_of_match[] = { - {}, -}; - -static int omap_sham_get_res_of(struct omap_sham_dev *dd, - struct device *dev, struct resource *res) -{ - return -EINVAL; -} #endif -static int omap_sham_get_res_pdev(struct omap_sham_dev *dd, - struct platform_device *pdev, struct resource *res) -{ - struct device *dev = &pdev->dev; - struct resource *r; - int err = 0; - - /* Get the base address */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(dev, "no MEM resource info\n"); - err = -ENODEV; - goto err; - } - memcpy(res, r, sizeof(*res)); - - /* Get the IRQ */ - dd->irq = platform_get_irq(pdev, 0); - if (dd->irq < 0) { - err = dd->irq; - goto err; - } - - /* Only OMAP2/3 can be non-DT */ - dd->pdata = &omap_sham_pdata_omap2; - -err: - return err; -} - static ssize_t fallback_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -2060,11 +1987,20 @@ static int omap_sham_probe(struct platform_device *pdev) { struct omap_sham_dev *dd; struct device *dev = &pdev->dev; - struct resource res; + void __iomem *io_base; + struct resource *res; dma_cap_mask_t mask; - int err, i, j; + int err, i, j, irq; u32 rev; + io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(io_base)) + return PTR_ERR(io_base); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + dd = devm_kzalloc(dev, sizeof(struct omap_sham_dev), GFP_KERNEL); if (dd == NULL) { dev_err(dev, "unable to alloc data struct.\n"); @@ -2078,17 +2014,13 @@ static int omap_sham_probe(struct platform_device *pdev) INIT_WORK(&dd->done_task, omap_sham_done_task); crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH); - err = (dev->of_node) ? omap_sham_get_res_of(dd, dev, &res) : - omap_sham_get_res_pdev(dd, pdev, &res); - if (err) - goto data_err; + dd->pdata = device_get_match_data(dev); + if (!dd->pdata) + dd->pdata = &omap_sham_pdata_omap2; - dd->io_base = devm_ioremap_resource(dev, &res); - if (IS_ERR(dd->io_base)) { - err = PTR_ERR(dd->io_base); - goto data_err; - } - dd->phys_base = res.start; + dd->irq = irq; + dd->io_base = io_base; + dd->phys_base = res->start; err = devm_request_irq(dev, dd->irq, dd->pdata->intr_hdlr, IRQF_TRIGGER_NONE, dev_name(dev), dd); @@ -2213,7 +2145,7 @@ static struct platform_driver omap_sham_driver = { .remove = omap_sham_remove, .driver = { .name = "omap-sham", - .of_match_table = omap_sham_of_match, + .of_match_table = of_match_ptr(omap_sham_of_match), .dev_groups = omap_sham_groups, }, }; From 1d39231ee9ee5efd2e879f8295aa6714848b8d9d Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:15 +0800 Subject: [PATCH 072/122] crypto: allwinner - Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Signed-off-by: Herbert Xu --- drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c | 4 +--- drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c index c6402e87f8a0..21762bd408e5 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c @@ -976,10 +976,8 @@ static int sun8i_ce_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, irq, ce_irq_handler, 0, "sun8i-ce-ns", ce); - if (err) { - dev_err(ce->dev, "Cannot request CryptoEngine Non-secure IRQ (err=%d)\n", err); + if (err) goto error_pm; - } err = sun8i_ce_register_algs(ce); if (err) diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c index 0b22fcddb882..2167dd9f44c7 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c @@ -824,10 +824,8 @@ static int sun8i_ss_probe(struct platform_device *pdev) goto error_pm; err = devm_request_irq(&pdev->dev, irq, ss_irq_handler, 0, "sun8i-ss", ss); - if (err) { - dev_err(ss->dev, "Cannot request SecuritySystem IRQ (err=%d)\n", err); + if (err) goto error_irq; - } err = sun8i_ss_register_algs(ss); if (err) From c32dd3367b975ac2c59e0fec6a8c100522f51c1c Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:16 +0800 Subject: [PATCH 073/122] crypto: amlogic - Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Signed-off-by: Herbert Xu --- drivers/crypto/amlogic/amlogic-gxl-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/amlogic/amlogic-gxl-core.c b/drivers/crypto/amlogic/amlogic-gxl-core.c index 6cb33949915f..169c6eeb51e5 100644 --- a/drivers/crypto/amlogic/amlogic-gxl-core.c +++ b/drivers/crypto/amlogic/amlogic-gxl-core.c @@ -257,10 +257,8 @@ static int meson_crypto_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, mc->irqs[i], meson_irq_handler, 0, "gxl-crypto", mc); - if (err < 0) { - dev_err(mc->dev, "Cannot request IRQ for flow %d\n", i); + if (err < 0) return err; - } } err = clk_prepare_enable(mc->busclk); From 9d3c82be49130081392efc7fd769e7301675abcf Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:17 +0800 Subject: [PATCH 074/122] crypto: aspeed - Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Reviewed-by: Andrew Jeffery Signed-off-by: Herbert Xu --- drivers/crypto/aspeed/aspeed-acry.c | 4 +--- drivers/crypto/aspeed/aspeed-hace.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/aspeed/aspeed-acry.c b/drivers/crypto/aspeed/aspeed-acry.c index 301612556a76..97327ba2c24b 100644 --- a/drivers/crypto/aspeed/aspeed-acry.c +++ b/drivers/crypto/aspeed/aspeed-acry.c @@ -732,10 +732,8 @@ static int aspeed_acry_probe(struct platform_device *pdev) rc = devm_request_irq(dev, acry_dev->irq, aspeed_acry_irq, 0, dev_name(dev), acry_dev); - if (rc) { - dev_err(dev, "Failed to request irq.\n"); + if (rc) return rc; - } acry_dev->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(acry_dev->clk)) { diff --git a/drivers/crypto/aspeed/aspeed-hace.c b/drivers/crypto/aspeed/aspeed-hace.c index 1f9afa002ae8..6555d7b2afe5 100644 --- a/drivers/crypto/aspeed/aspeed-hace.c +++ b/drivers/crypto/aspeed/aspeed-hace.c @@ -131,10 +131,8 @@ static int aspeed_hace_probe(struct platform_device *pdev) rc = devm_request_irq(&pdev->dev, hace_dev->irq, aspeed_hace_irq, 0, dev_name(&pdev->dev), hace_dev); - if (rc) { - dev_err(&pdev->dev, "Failed to request interrupt\n"); + if (rc) return rc; - } /* Get clk and enable it */ hace_dev->clk = devm_clk_get(&pdev->dev, NULL); From 53fa9d8d97ee77befedbd4ca9cebd7b9a658dc40 Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:18 +0800 Subject: [PATCH 075/122] crypto: drivers - Remove redundant dev_err()/dev_err_probe() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() and dev_err_probe() calls. Signed-off-by: Pan Chuang Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes.c | 4 +--- drivers/crypto/atmel-sha.c | 4 +--- drivers/crypto/atmel-tdes.c | 4 +--- drivers/crypto/img-hash.c | 4 +--- drivers/crypto/mxs-dcp.c | 8 ++------ drivers/crypto/omap-aes.c | 4 +--- drivers/crypto/omap-des.c | 4 +--- drivers/crypto/omap-sham.c | 5 +---- drivers/crypto/sahara.c | 3 +-- 9 files changed, 10 insertions(+), 30 deletions(-) diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index b393689400b4..1bf00df864e8 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -2369,10 +2369,8 @@ static int atmel_aes_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, aes_dd->irq, atmel_aes_irq, IRQF_SHARED, "atmel-aes", aes_dd); - if (err) { - dev_err(dev, "unable to request aes irq.\n"); + if (err) goto err_tasklet_kill; - } /* Initializing the clock */ aes_dd->iclk = devm_clk_get_prepared(&pdev->dev, "aes_clk"); diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 8e3b8efa8109..e856309bd02b 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -2605,10 +2605,8 @@ static int atmel_sha_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, sha_dd->irq, atmel_sha_irq, IRQF_SHARED, "atmel-sha", sha_dd); - if (err) { - dev_err(dev, "unable to request sha irq.\n"); + if (err) goto err_tasklet_kill; - } /* Initializing the clock */ sha_dd->iclk = devm_clk_get_prepared(&pdev->dev, "sha_clk"); diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 208910d0d08d..1a00e7224644 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -968,10 +968,8 @@ static int atmel_tdes_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, tdes_dd->irq, atmel_tdes_irq, IRQF_SHARED, "atmel-tdes", tdes_dd); - if (err) { - dev_err(dev, "unable to request tdes irq.\n"); + if (err) goto err_tasklet_kill; - } /* Initializing the clock */ tdes_dd->iclk = devm_clk_get(&pdev->dev, "tdes_clk"); diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c index c0467185ee42..62e03677079a 100644 --- a/drivers/crypto/img-hash.c +++ b/drivers/crypto/img-hash.c @@ -967,10 +967,8 @@ static int img_hash_probe(struct platform_device *pdev) err = devm_request_irq(dev, irq, img_irq_handler, 0, dev_name(dev), hdev); - if (err) { - dev_err(dev, "unable to request irq\n"); + if (err) goto res_err; - } dev_dbg(dev, "using IRQ channel %d\n", irq); hdev->hash_clk = devm_clk_get_enabled(&pdev->dev, "hash"); diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c index 595b2fd84667..c75a06999787 100644 --- a/drivers/crypto/mxs-dcp.c +++ b/drivers/crypto/mxs-dcp.c @@ -1085,17 +1085,13 @@ static int mxs_dcp_probe(struct platform_device *pdev) ret = devm_request_irq(dev, dcp_vmi_irq, mxs_dcp_irq, 0, "dcp-vmi-irq", sdcp); - if (ret) { - dev_err(dev, "Failed to claim DCP VMI IRQ!\n"); + if (ret) return ret; - } ret = devm_request_irq(dev, dcp_irq, mxs_dcp_irq, 0, "dcp-irq", sdcp); - if (ret) { - dev_err(dev, "Failed to claim DCP IRQ!\n"); + if (ret) return ret; - } /* Allocate coherent helper block. */ sdcp->coh = devm_kzalloc(dev, sizeof(*sdcp->coh) + DCP_ALIGNMENT, diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index a5fce216de34..d40074e5a142 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -1114,10 +1114,8 @@ static int omap_aes_probe(struct platform_device *pdev) err = devm_request_irq(dev, irq, omap_aes_irq, 0, dev_name(dev), dd); - if (err) { - dev_err(dev, "Unable to grab omap-aes IRQ\n"); + if (err) goto err_irq; - } } spin_lock_init(&dd->lock); diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c index dfaf831dd8ec..3b7104cb4487 100644 --- a/drivers/crypto/omap-des.c +++ b/drivers/crypto/omap-des.c @@ -1017,10 +1017,8 @@ static int omap_des_probe(struct platform_device *pdev) err = devm_request_irq(dev, irq, omap_des_irq, 0, dev_name(dev), dd); - if (err) { - dev_err(dev, "Unable to grab omap-des IRQ\n"); + if (err) goto err_irq; - } } diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index e8e111bd438a..6d2dd0b88f15 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -2024,11 +2024,8 @@ static int omap_sham_probe(struct platform_device *pdev) err = devm_request_irq(dev, dd->irq, dd->pdata->intr_hdlr, IRQF_TRIGGER_NONE, dev_name(dev), dd); - if (err) { - dev_err(dev, "unable to request irq %d, err = %d\n", - dd->irq, err); + if (err) goto data_err; - } dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 533080b0cddc..d586f1315de1 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -1305,8 +1305,7 @@ static int sahara_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, irq, sahara_irq_handler, 0, dev_name(&pdev->dev), dev); if (err) - return dev_err_probe(&pdev->dev, err, - "failed to request irq\n"); + return err; /* clocks */ dev->clk_ipg = devm_clk_get_enabled(&pdev->dev, "ipg"); From f9a1dd7a57c8482edaf63acdf6281e39186934bb Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:20 +0800 Subject: [PATCH 076/122] crypto: ccree - Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_driver.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index 061e68a31c36..28a23cd572d6 100644 --- a/drivers/crypto/ccree/cc_driver.c +++ b/drivers/crypto/ccree/cc_driver.c @@ -471,10 +471,8 @@ static int init_cc_resources(struct platform_device *plat_dev) /* register the driver isr function */ rc = devm_request_irq(dev, irq, cc_isr, IRQF_SHARED, "ccree", new_drvdata); - if (rc) { - dev_err(dev, "Could not register to interrupt %d\n", irq); + if (rc) goto post_pm_err; - } dev_dbg(dev, "Registered to IRQ: %d\n", irq); init_cc_cache_params(new_drvdata); From a63a547e26aaed490254e94f904544b49444e3aa Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:21 +0800 Subject: [PATCH 077/122] crypto: sl3516 - Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Reviewed-by: Linus Walleij Signed-off-by: Herbert Xu --- drivers/crypto/gemini/sl3516-ce-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/gemini/sl3516-ce-core.c b/drivers/crypto/gemini/sl3516-ce-core.c index f7e0e3fea15c..c1df5f96ea42 100644 --- a/drivers/crypto/gemini/sl3516-ce-core.c +++ b/drivers/crypto/gemini/sl3516-ce-core.c @@ -414,10 +414,8 @@ static int sl3516_ce_probe(struct platform_device *pdev) return irq; err = devm_request_irq(&pdev->dev, irq, ce_irq_handler, 0, "crypto", ce); - if (err) { - dev_err(ce->dev, "Cannot request Crypto Engine IRQ (err=%d)\n", err); + if (err) return err; - } ce->reset = devm_reset_control_get(&pdev->dev, NULL); if (IS_ERR(ce->reset)) From 80283c1e1b87236b73ceed9c57ef56a9fbc7484f Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:22 +0800 Subject: [PATCH 078/122] crypto: safexcel - Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_threaded_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index 52809e57361a..71b920e17e98 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -1172,10 +1172,8 @@ static int safexcel_request_ring_irq(void *pdev, int irqid, ret = devm_request_threaded_irq(dev, irq, handler, threaded_handler, IRQF_ONESHOT, dev_name(dev), ring_irq_priv); - if (ret) { - dev_err(dev, "unable to request IRQ %d\n", irq); + if (ret) return ret; - } /* Set affinity */ cpu = cpumask_local_spread(ring_id, NUMA_NO_NODE); From ac2ad1af8a1071eadbee57854ba0aea9b00cf7f5 Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:23 +0800 Subject: [PATCH 079/122] crypto: keembay - Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_threaded_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Signed-off-by: Herbert Xu --- drivers/crypto/intel/keembay/keembay-ocs-aes-core.c | 4 +--- drivers/crypto/intel/keembay/keembay-ocs-ecc.c | 4 +--- drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c index 419f88af1031..cc22561c30fe 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c @@ -1612,10 +1612,8 @@ static int kmb_ocs_aes_probe(struct platform_device *pdev) rc = devm_request_threaded_irq(dev, aes_dev->irq, ocs_aes_irq_handler, NULL, 0, "keembay-ocs-aes", aes_dev); - if (rc < 0) { - dev_err(dev, "Could not request IRQ\n"); + if (rc < 0) return rc; - } INIT_LIST_HEAD(&aes_dev->list); spin_lock(&ocs_aes.lock); diff --git a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c index 9e555b02086c..9bdee39dc4e1 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c @@ -900,10 +900,8 @@ static int kmb_ocs_ecc_probe(struct platform_device *pdev) rc = devm_request_threaded_irq(dev, ecc_dev->irq, ocs_ecc_irq_handler, NULL, 0, "keembay-ocs-ecc", ecc_dev); - if (rc < 0) { - dev_err(dev, "Could not request IRQ\n"); + if (rc < 0) goto list_del; - } /* Add device to the list of OCS ECC devices. */ spin_lock(&ocs_ecc.lock); diff --git a/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c b/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c index 48281d882260..3cd5e511854d 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c @@ -1205,10 +1205,8 @@ static int kmb_ocs_hcu_probe(struct platform_device *pdev) rc = devm_request_threaded_irq(&pdev->dev, hcu_dev->irq, ocs_hcu_irq_handler, NULL, 0, "keembay-ocs-hcu", hcu_dev); - if (rc < 0) { - dev_err(dev, "Could not request IRQ.\n"); + if (rc < 0) return rc; - } INIT_LIST_HEAD(&hcu_dev->list); From 1222a24f79cad1c187a7c92bf104f94f8e0fcfa1 Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:24 +0800 Subject: [PATCH 080/122] crypto: octeontx2 - Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Signed-off-by: Herbert Xu --- drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c index f6f47f4e5d83..79f6c2bb9d8b 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c @@ -430,11 +430,8 @@ static int cptpf_register_afpf_mbox_intr(struct otx2_cptpf_dev *cptpf) /* Register AF-PF mailbox interrupt handler */ ret = devm_request_irq(dev, irq, otx2_cptpf_afpf_mbox_intr, 0, "CPTAFPF Mbox", cptpf); - if (ret) { - dev_err(dev, - "IRQ registration failed for PFAF mbox irq\n"); + if (ret) return ret; - } /* Clear interrupt if any, to avoid spurious interrupts */ otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT, 0x1ULL); /* Enable AF-PF interrupt */ From 01138b819507b0bf9820c6bb03e5cf7b58f66a2f Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:25 +0800 Subject: [PATCH 081/122] crypto: rockchip - Remove redundant dev_err() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Signed-off-by: Herbert Xu --- drivers/crypto/rockchip/rk3288_crypto.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c index b77bdce8e7fc..7cb1316b6f18 100644 --- a/drivers/crypto/rockchip/rk3288_crypto.c +++ b/drivers/crypto/rockchip/rk3288_crypto.c @@ -365,10 +365,8 @@ static int rk_crypto_probe(struct platform_device *pdev) rk_crypto_irq_handle, IRQF_SHARED, "rk-crypto", pdev); - if (err) { - dev_err(&pdev->dev, "irq request failed.\n"); + if (err) goto err_crypto; - } crypto_info->engine = crypto_engine_alloc_init(&pdev->dev, true); if (!crypto_info->engine) { From b0b85837193b106ab4d7beef5991d442694c66da Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 16:00:26 +0800 Subject: [PATCH 082/122] crypto: stm32 - Remove redundant dev_err() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_threaded_irq() automatically logs detailed error messages on failure. Remove the now-redundant driver-specific dev_err() calls. Signed-off-by: Pan Chuang Acked-by: Maxime Méré Signed-off-by: Herbert Xu --- drivers/crypto/stm32/stm32-cryp.c | 4 +--- drivers/crypto/stm32/stm32-hash.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c index b79877099942..3fc2db290b0f 100644 --- a/drivers/crypto/stm32/stm32-cryp.c +++ b/drivers/crypto/stm32/stm32-cryp.c @@ -2590,10 +2590,8 @@ static int stm32_cryp_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, irq, stm32_cryp_irq, stm32_cryp_irq_thread, IRQF_ONESHOT, dev_name(dev), cryp); - if (ret) { - dev_err(dev, "Cannot grab IRQ\n"); + if (ret) return ret; - } cryp->clk = devm_clk_get(dev, NULL); if (IS_ERR(cryp->clk)) { diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index dada5951082c..e6a1e9b9f88d 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -2356,10 +2356,8 @@ static int stm32_hash_probe(struct platform_device *pdev) stm32_hash_irq_thread, IRQF_ONESHOT, dev_name(dev), hdev); - if (ret) { - dev_err(dev, "Cannot grab IRQ\n"); + if (ret) return ret; - } } else { dev_info(dev, "No IRQ, use polling mode\n"); hdev->polled = true; From 67ca4ac78f37b91bffab1c30a0c8afca024eecf4 Mon Sep 17 00:00:00 2001 From: Chenghai Huang Date: Sat, 18 Jul 2026 11:05:12 +0800 Subject: [PATCH 083/122] crypto: hisilicon/sec2 - fix uninitialized type_supported in sec_create_qp_ctx sec_create_qp_ctx() reads ctx->type_supported to pick its callback, but sec_skcipher_init() and sec_aead_init() set it after sec_ctx_base_init() has already walked the qp_ctx loop, so the value is uninitialized when first consumed. Set type_supported in sec_ctx_base_init() before the loop; the alg init paths now just select req_op from it. Signed-off-by: Chenghai Huang Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/sec2/sec_crypto.c | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c index 77e0e03cbcab..5c2b9f710be0 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -672,6 +672,11 @@ static int sec_ctx_base_init(struct sec_ctx *ctx) ctx->hlf_q_num = sec->ctx_q_num >> 1; ctx->pbuf_supported = ctx->sec->iommu_used; + if (sec->qm.ver < QM_HW_V3) + ctx->type_supported = SEC_BD_TYPE2; + else + ctx->type_supported = SEC_BD_TYPE3; + ctx->qp_ctx = kzalloc_objs(struct sec_qp_ctx, sec->ctx_q_num); if (!ctx->qp_ctx) { ret = -ENOMEM; @@ -2067,13 +2072,10 @@ static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm) if (!ctx->qps) return 0; - if (ctx->sec->qm.ver < QM_HW_V3) { - ctx->type_supported = SEC_BD_TYPE2; - ctx->req_op = &sec_skcipher_req_ops; - } else { - ctx->type_supported = SEC_BD_TYPE3; + if (ctx->type_supported == SEC_BD_TYPE3) ctx->req_op = &sec_skcipher_req_ops_v3; - } + else + ctx->req_op = &sec_skcipher_req_ops; return 0; } @@ -2100,13 +2102,11 @@ static int sec_aead_init(struct crypto_aead *tfm) ret = sec_ctx_base_init(ctx); if (ret) return ret; - if (ctx->sec->qm.ver < QM_HW_V3) { - ctx->type_supported = SEC_BD_TYPE2; - ctx->req_op = &sec_aead_req_ops; - } else { - ctx->type_supported = SEC_BD_TYPE3; + + if (ctx->type_supported == SEC_BD_TYPE3) ctx->req_op = &sec_aead_req_ops_v3; - } + else + ctx->req_op = &sec_aead_req_ops; ret = sec_auth_init(ctx); if (ret) From a7e2dfb7dafc8fb750b7ba0caec59043f5b73e00 Mon Sep 17 00:00:00 2001 From: Chenghai Huang Date: Sat, 18 Jul 2026 11:05:13 +0800 Subject: [PATCH 084/122] crypto: hisilicon/sec2 - remove unused sec_ctx.hlf_q_num hlf_q_num is set but never read; drop the field and its assignment. Signed-off-by: Chenghai Huang Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/sec2/sec.h | 3 --- drivers/crypto/hisilicon/sec2/sec_crypto.c | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/crypto/hisilicon/sec2/sec.h b/drivers/crypto/hisilicon/sec2/sec.h index adf95795dffe..c12a39a8a9d4 100644 --- a/drivers/crypto/hisilicon/sec2/sec.h +++ b/drivers/crypto/hisilicon/sec2/sec.h @@ -181,9 +181,6 @@ struct sec_ctx { const struct sec_req_op *req_op; struct hisi_qp **qps; - /* Half queues for encipher, and half for decipher */ - u32 hlf_q_num; - /* Current cyclic index to select a queue for encipher */ atomic_t enc_qcyclic; diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c index 5c2b9f710be0..01eb76f616fc 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -669,7 +669,6 @@ static int sec_ctx_base_init(struct sec_ctx *ctx) sec = container_of(ctx->qps[0]->qm, struct sec_dev, qm); ctx->sec = sec; ctx->dev = &sec->qm.pdev->dev; - ctx->hlf_q_num = sec->ctx_q_num >> 1; ctx->pbuf_supported = ctx->sec->iommu_used; if (sec->qm.ver < QM_HW_V3) From 1163a476a568f6c0f852d469c8e4c5a5f805adac Mon Sep 17 00:00:00 2001 From: Can Peng Date: Sat, 18 Jul 2026 11:29:37 +0800 Subject: [PATCH 085/122] hwrng: stm32 - Fix runtime PM cleanup on registration failure stm32_rng_probe() enables autosuspend and runtime PM before registering the hwrng. If devm_hwrng_register() fails, probe returns with runtime PM left enabled and autosuspend still selected. The remove callback also only disables runtime PM and does not undo pm_runtime_use_autosuspend(). Use devm_pm_runtime_enable() so runtime PM is unwound automatically on probe failure and driver detach. Since the managed cleanup also disables runtime PM,drop the remove callback. Fixes: c6a97c42e399 ("hwrng: stm32 - add support for STM32 HW RNG") Cc: stable@vger.kernel.org Signed-off-by: Can Peng Reviewed-by: Linus Walleij Signed-off-by: Herbert Xu --- drivers/char/hw_random/stm32-rng.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index 9a8c00586ab0..f5bfe54c01dc 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -368,11 +368,6 @@ static int stm32_rng_init(struct hwrng *rng) return 0; } -static void stm32_rng_remove(struct platform_device *ofdev) -{ - pm_runtime_disable(&ofdev->dev); -} - static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev) { struct stm32_rng_private *priv = dev_get_drvdata(dev); @@ -590,7 +585,9 @@ static int stm32_rng_probe(struct platform_device *ofdev) pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); - pm_runtime_enable(dev); + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; return devm_hwrng_register(dev, &priv->rng); } @@ -602,7 +599,6 @@ static struct platform_driver stm32_rng_driver = { .of_match_table = stm32_rng_match, }, .probe = stm32_rng_probe, - .remove = stm32_rng_remove, }; module_platform_driver(stm32_rng_driver); From 8b1fea9dda01d0ee7ac0b7ec87dbb9fabbf244aa Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Jul 2026 16:17:42 -0700 Subject: [PATCH 086/122] crypto: cesa - manage SRAM teardown with devm mv_cesa_put_sram() is called explicitly from both the probe error path and mv_cesa_remove(). The non-pool ioremap is already devm-managed, but dma_map_resource() and gen_pool_dma_alloc() have no devm helpers, so the mapping is released by hand. This is error-prone: the error path iterates over every engine and can dma_unmap_resource() an uninitialized/zero address for engines that were never set up. Convert the teardown into a devm_add_action_or_reset() callback registered only after a mapping is successfully established. The callback fires automatically on probe failure (devres rollback) and on device detach, after mv_cesa_remove() has already stopped the engine and freed the IRQ, so the unmap still happens in a safe order. This deletes the explicit mv_cesa_put_sram() calls and the uninitialized-engine bug at once. Add a struct mv_cesa_dev back-pointer to struct mv_cesa_engine so the callback can reach cesa->dev and cesa->sram_size from the engine alone. Assisted-by: opencode:hy3-free Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cesa/cesa.c | 55 ++++++++++++------------------ drivers/crypto/marvell/cesa/cesa.h | 2 ++ 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/drivers/crypto/marvell/cesa/cesa.c b/drivers/crypto/marvell/cesa/cesa.c index 75d8ba23d9a2..4859ad2e86b4 100644 --- a/drivers/crypto/marvell/cesa/cesa.c +++ b/drivers/crypto/marvell/cesa/cesa.c @@ -366,6 +366,8 @@ static int mv_cesa_dev_dma_init(struct mv_cesa_dev *cesa) return 0; } +static void mv_cesa_release_sram(void *data); + static int mv_cesa_get_sram(struct platform_device *pdev, int idx) { struct mv_cesa_dev *cesa = platform_get_drvdata(pdev); @@ -378,11 +380,13 @@ static int mv_cesa_get_sram(struct platform_device *pdev, int idx) engine->sram_pool = gen_pool_dma_alloc(engine->pool, cesa->sram_size, &engine->sram_dma); - if (engine->sram_pool) - return 0; + if (!engine->sram_pool) { + engine->pool = NULL; + return -ENOMEM; + } - engine->pool = NULL; - return -ENOMEM; + return devm_add_action_or_reset(cesa->dev, mv_cesa_release_sram, + engine); } engine->sram = devm_platform_get_and_ioremap_resource(pdev, idx, &res); @@ -395,13 +399,13 @@ static int mv_cesa_get_sram(struct platform_device *pdev, int idx) if (dma_mapping_error(cesa->dev, engine->sram_dma)) return -ENOMEM; - return 0; + return devm_add_action_or_reset(cesa->dev, mv_cesa_release_sram, engine); } -static void mv_cesa_put_sram(struct platform_device *pdev, int idx) +static void mv_cesa_release_sram(void *data) { - struct mv_cesa_dev *cesa = platform_get_drvdata(pdev); - struct mv_cesa_engine *engine = &cesa->engines[idx]; + struct mv_cesa_engine *engine = data; + struct mv_cesa_dev *cesa = engine->cesa; if (engine->pool) gen_pool_free(engine->pool, (unsigned long)engine->sram_pool, @@ -465,17 +469,16 @@ static int mv_cesa_probe(struct platform_device *pdev) char res_name[16]; engine->id = i; + engine->cesa = cesa; spin_lock_init(&engine->lock); ret = mv_cesa_get_sram(pdev, i); if (ret) - goto err_cleanup; + return ret; irq = platform_get_irq(pdev, i); - if (irq < 0) { - ret = irq; - goto err_cleanup; - } + if (irq < 0) + return irq; engine->irq = irq; @@ -487,18 +490,14 @@ static int mv_cesa_probe(struct platform_device *pdev) engine->clk = devm_clk_get_optional_enabled(dev, res_name); if (IS_ERR(engine->clk)) { engine->clk = devm_clk_get_optional_enabled(dev, NULL); - if (IS_ERR(engine->clk)) { - ret = PTR_ERR(engine->clk); - goto err_cleanup; - } + if (IS_ERR(engine->clk)) + return PTR_ERR(engine->clk); } snprintf(res_name, sizeof(res_name), "cesaz%u", i); engine->zclk = devm_clk_get_optional_enabled(dev, res_name); - if (IS_ERR(engine->zclk)) { - ret = PTR_ERR(engine->zclk); - goto err_cleanup; - } + if (IS_ERR(engine->zclk)) + return PTR_ERR(engine->zclk); engine->regs = cesa->regs + CESA_ENGINE_OFF(i); @@ -516,7 +515,7 @@ static int mv_cesa_probe(struct platform_device *pdev) dev_name(&pdev->dev), engine); if (ret) - goto err_cleanup; + return ret; /* Set affinity */ cpu = cpumask_local_spread(engine->id, NUMA_NO_NODE); @@ -532,29 +531,19 @@ static int mv_cesa_probe(struct platform_device *pdev) ret = mv_cesa_add_algs(cesa); if (ret) { cesa_dev = NULL; - goto err_cleanup; + return ret; } dev_info(dev, "CESA device successfully registered\n"); return 0; - -err_cleanup: - for (i = 0; i < caps->nengines; i++) - mv_cesa_put_sram(pdev, i); - - return ret; } static void mv_cesa_remove(struct platform_device *pdev) { struct mv_cesa_dev *cesa = platform_get_drvdata(pdev); - int i; mv_cesa_remove_algs(cesa); - - for (i = 0; i < cesa->caps->nengines; i++) - mv_cesa_put_sram(pdev, i); } static const struct platform_device_id mv_cesa_plat_id_table[] = { diff --git a/drivers/crypto/marvell/cesa/cesa.h b/drivers/crypto/marvell/cesa/cesa.h index 18f9f28040a6..44351b252861 100644 --- a/drivers/crypto/marvell/cesa/cesa.h +++ b/drivers/crypto/marvell/cesa/cesa.h @@ -415,6 +415,7 @@ struct mv_cesa_dev_dma { * @zclk: engine zclk * @max_req_len: maximum chunk length (useful to create the TDMA chain) * @int_mask: interrupt mask cache + * @cesa: back-pointer to the parent CESA device * @pool: memory pool pointing to the memory region reserved in * SRAM * @queue: fifo of the pending crypto requests @@ -441,6 +442,7 @@ struct mv_cesa_engine { struct clk *zclk; size_t max_req_len; u32 int_mask; + struct mv_cesa_dev *cesa; struct gen_pool *pool; struct crypto_queue queue; atomic_t load; From 37b70fa01b909b2d4d247789dbc41eaf4562e2ea Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 21 Jul 2026 01:22:50 +0200 Subject: [PATCH 087/122] crypto: bcm - use memcpy_and_pad in ahash_hmac_setkey Use memcpy_and_pad() instead of memcpy() followed by memset() to simplify ahash_hmac_setkey(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/bcm/cipher.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c index 240b40ae9cd6..e9d9ca7441b6 100644 --- a/drivers/crypto/bcm/cipher.c +++ b/drivers/crypto/bcm/cipher.c @@ -2387,9 +2387,7 @@ static int ahash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key, * outer hashing in software. */ if (iproc_priv.spu.spu_type == SPU_TYPE_SPUM) { - memcpy(ctx->ipad, ctx->authkey, ctx->authkeylen); - memset(ctx->ipad + ctx->authkeylen, 0, - blocksize - ctx->authkeylen); + memcpy_and_pad(ctx->ipad, blocksize, ctx->authkey, ctx->authkeylen, 0); ctx->authkeylen = 0; unsafe_memcpy(ctx->opad, ctx->ipad, blocksize, "fortified memcpy causes -Wrestrict warning"); From 567fa6076cd1038171f5827a7a5d19d718cd0baf Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 21 Jul 2026 01:27:17 +0200 Subject: [PATCH 088/122] crypto: qce - drop redundant variable in qce_skcipher_done Remove the local ret variable and return the result directly. Signed-off-by: Thorsten Blum Reviewed-by: Bartosz Golaszewski Signed-off-by: Herbert Xu --- drivers/crypto/qce/skcipher.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index ff4ee9541f7c..4931b064f10e 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -216,7 +216,6 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); unsigned int blocksize = crypto_skcipher_blocksize(tfm); int keylen; - int ret; rctx->flags = tmpl->alg_flags; rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; @@ -254,9 +253,8 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) req->base.data); skcipher_request_set_crypt(&rctx->fallback_req, req->src, req->dst, req->cryptlen, req->iv); - ret = encrypt ? crypto_skcipher_encrypt(&rctx->fallback_req) : - crypto_skcipher_decrypt(&rctx->fallback_req); - return ret; + return encrypt ? crypto_skcipher_encrypt(&rctx->fallback_req) : + crypto_skcipher_decrypt(&rctx->fallback_req); } return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); From 83f11e115207fecd03b1ac5fe57b614ef9e09d6c Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 23 Jul 2026 18:33:25 +0200 Subject: [PATCH 089/122] crypto: octeontx - simplify get_{eng,ucode}_type_str helpers Remove the local variables, add default cases, and return the strings directly. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- .../crypto/marvell/octeontx/otx_cptpf_ucode.c | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c index 58dd996c7f3a..c66cd322994f 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c +++ b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c @@ -104,34 +104,26 @@ static void set_ucode_filename(struct otx_cpt_ucode *ucode, static char *get_eng_type_str(int eng_type) { - char *str = "unknown"; - switch (eng_type) { case OTX_CPT_SE_TYPES: - str = "SE"; - break; - + return "SE"; case OTX_CPT_AE_TYPES: - str = "AE"; - break; + return "AE"; + default: + return "unknown"; } - return str; } static char *get_ucode_type_str(int ucode_type) { - char *str = "unknown"; - switch (ucode_type) { case (1 << OTX_CPT_SE_TYPES): - str = "SE"; - break; - + return "SE"; case (1 << OTX_CPT_AE_TYPES): - str = "AE"; - break; + return "AE"; + default: + return "unknown"; } - return str; } static int get_ucode_type(struct otx_cpt_ucode_hdr *ucode_hdr, int *ucode_type) From 57e599da2d3be1366214bd1d302a352dfc08d40a Mon Sep 17 00:00:00 2001 From: Sang-Heon Jeon Date: Fri, 24 Jul 2026 03:45:20 +0900 Subject: [PATCH 090/122] crypto: drivers - remove conditional return with no effect Both branches of the check return the same value, so the check has no effect. Remove it and return the value directly. This is the result of running the Coccinelle script from scripts/coccinelle/misc/cond_return_no_effect.cocci. Signed-off-by: Sang-Heon Jeon Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_gen2_config.c | 8 ++------ drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c | 7 +------ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen2_config.c b/drivers/crypto/intel/qat/qat_common/adf_gen2_config.c index c27ff6d18e11..57025bffee73 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen2_config.c +++ b/drivers/crypto/intel/qat/qat_common/adf_gen2_config.c @@ -155,12 +155,8 @@ static int adf_gen2_comp_dev_config(struct adf_accel_dev *accel_dev) } val = i; - ret = adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_DC, - &val, ADF_DEC); - if (ret) - return ret; - - return ret; + return adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, + ADF_NUM_DC, &val, ADF_DEC); err: dev_err(&GET_DEV(accel_dev), "Failed to add configuration for compression\n"); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c index 95f3de3a34eb..1542a110ba37 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c @@ -235,7 +235,6 @@ int otx2_cpt_lf_reset_msg(struct otx2_cptlfs_info *lfs, int slot) struct otx2_mbox *mbox = lfs->mbox; struct pci_dev *pdev = lfs->pdev; struct cpt_lf_rst_req *req; - int ret; req = (struct cpt_lf_rst_req *)otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req), sizeof(struct msg_rsp)); @@ -248,11 +247,7 @@ int otx2_cpt_lf_reset_msg(struct otx2_cptlfs_info *lfs, int slot) req->hdr.sig = OTX2_MBOX_REQ_SIG; req->hdr.pcifunc = 0; req->slot = slot; - ret = otx2_cpt_send_mbox_msg(mbox, pdev); - if (ret) - return ret; - - return ret; + return otx2_cpt_send_mbox_msg(mbox, pdev); } EXPORT_SYMBOL_NS_GPL(otx2_cpt_lf_reset_msg, "CRYPTO_DEV_OCTEONTX2_CPT"); From a264cb967dbdbf9544c4de80e2f7188214b93f77 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 24 Jul 2026 18:42:53 -0700 Subject: [PATCH 091/122] crypto: af_alg - clean up kernel-doc warnings - add missing struct member @wait, drop @completion - convert function comments to kernel-doc format - for af_alg_readable(), change comments from "writable" to "readable" Warning: include/crypto/if_alg.h:161 struct member 'wait' not described in 'af_alg_ctx' Warning: include/crypto/if_alg.h:161 Excess struct member 'completion' description in 'af_alg_ctx' Warning: include/crypto/if_alg.h:187 This comment starts with '/**', but isn't a kernel-doc comment. * Size of available buffer for sending data from user space to kernel. Warning: include/crypto/if_alg.h:202 This comment starts with '/**', but isn't a kernel-doc comment. * Can the send buffer still be written to? Warning: include/crypto/if_alg.h:213 This comment starts with '/**', but isn't a kernel-doc comment. * Size of available buffer used by kernel for the RX user space operation. Warning: include/crypto/if_alg.h:228 This comment starts with '/**', but isn't a kernel-doc comment. * Can the RX buffer still be written to? Signed-off-by: Randy Dunlap Signed-off-by: Herbert Xu --- include/crypto/if_alg.h | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index 4e9ed8e73403..dbf6a97c72a2 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -121,7 +121,7 @@ struct af_alg_async_req { * @iv: IV for cipher operation * @state: Existing state for continuing operation * @aead_assoclen: Length of AAD for AEAD cipher operations - * @completion: Work queue for synchronous operation + * @wait: For waiting for completion of async crypto ops * @used: TX bytes sent to kernel. This variable is used to * ensure that user space cannot cause the kernel * to allocate too much memory in sendmsg operation. @@ -185,10 +185,11 @@ static inline struct alg_sock *alg_sk(struct sock *sk) } /** - * Size of available buffer for sending data from user space to kernel. + * af_alg_sndbuf - Size of available buffer for sending data from user space to kernel. * - * @sk socket of connection to user space - * @return number of bytes still available + * @sk: socket of connection to user space + * + * Returns: number of bytes still available */ static inline int af_alg_sndbuf(struct sock *sk) { @@ -200,10 +201,11 @@ static inline int af_alg_sndbuf(struct sock *sk) } /** - * Can the send buffer still be written to? + * af_alg_writable - Can the send buffer still be written to? * - * @sk socket of connection to user space - * @return true => writable, false => not writable + * @sk: socket of connection to user space + * + * Returns: true => writable, false => not writable */ static inline bool af_alg_writable(struct sock *sk) { @@ -211,10 +213,11 @@ static inline bool af_alg_writable(struct sock *sk) } /** - * Size of available buffer used by kernel for the RX user space operation. + * af_alg_rcvbuf - Size of available buffer used by kernel for the RX user space operation. * - * @sk socket of connection to user space - * @return number of bytes still available + * @sk: socket of connection to user space + * + * Returns: number of bytes still available */ static inline int af_alg_rcvbuf(struct sock *sk) { @@ -226,10 +229,11 @@ static inline int af_alg_rcvbuf(struct sock *sk) } /** - * Can the RX buffer still be written to? + * af_alg_readable - Can the RX buffer still be read from? * - * @sk socket of connection to user space - * @return true => writable, false => not writable + * @sk: socket of connection to user space + * + * Returns: true => readable, false => not readable */ static inline bool af_alg_readable(struct sock *sk) { From 006fb75aa3e460eeb74e76c7eb2c3efdc0338a5b Mon Sep 17 00:00:00 2001 From: Wenjia Zhang Date: Tue, 28 Jul 2026 17:53:55 +0800 Subject: [PATCH 092/122] dt-bindings: crypto: qcom,inline-crypto-engine: Add x1e80100 support Document the compatible string for inline crypto engine found on the Qualcomm X1E80100 SoC, used by the Hamoa IoT EVK board. Signed-off-by: Wenjia Zhang Acked-by: Krzysztof Kozlowski Signed-off-by: Herbert Xu --- .../devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index ed2dd99eb1b1..23bf98c2b9fa 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -28,6 +28,7 @@ properties: - qcom,sm8550-inline-crypto-engine - qcom,sm8650-inline-crypto-engine - qcom,sm8750-inline-crypto-engine + - qcom,x1e80100-inline-crypto-engine - const: qcom,inline-crypto-engine reg: From bda65642eba73bb8254405394aa7afafe3d98d3b Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 28 Jul 2026 22:58:26 +0200 Subject: [PATCH 093/122] crypto: atmel-ecc - simplify control flow in atmel_ecdh_set_secret Free the public key directly on I2C transaction failure and remove the free_public_key label to simplify the code. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 4add3b2ddd0b..252c28a2ecec 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -106,17 +106,14 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, atmel_i2c_init_genkey_cmd(cmd, DATA_SLOT_2); ret = atmel_i2c_send_receive(ctx->client, cmd); - if (ret) - goto free_public_key; + if (ret) { + kfree(public_key); + goto free_cmd; + } memcpy(public_key, &cmd->data[RSP_DATA_IDX], ATMEL_ECC_PUBKEY_SIZE); ctx->public_key = public_key; - kfree(cmd); - return 0; - -free_public_key: - kfree(public_key); free_cmd: kfree(cmd); return ret; From dc9e9023adb53d8ae84673cdbc20566e7836c0bd Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 28 Jul 2026 22:58:27 +0200 Subject: [PATCH 094/122] crypto: atmel-ecc - drop redundant return variable In atmel_ecdh_generate_public_key(), drop the redundant return variable and return -EINVAL and 0 directly. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 252c28a2ecec..075f38a67935 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -124,7 +124,6 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req) struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm); size_t copied, nbytes; - int ret = 0; if (ctx->do_fallback) { kpp_request_set_tfm(req, ctx->fallback); @@ -142,9 +141,9 @@ static int atmel_ecdh_generate_public_key(struct kpp_request *req) sg_nents_for_len(req->dst, nbytes), ctx->public_key, nbytes); if (copied != nbytes) - ret = -EINVAL; + return -EINVAL; - return ret; + return 0; } static int atmel_ecdh_compute_shared_secret(struct kpp_request *req) From 4a1c7518cc31430b96458202b6a5b4064ff0cfa0 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 28 Jul 2026 20:02:31 -0700 Subject: [PATCH 095/122] crypto: talitos - Use platform_get_irq() to retrieve interrupt Remove the need to call irq_dispose_mapping as needed by irq_of_parse_and_map(). Simplify the function as a result. No need for gotos anymore. Add a missing free_irq. Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 584508963241..eca4d7f46f11 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -192,7 +192,7 @@ static int reset_device(struct device *dev) && --timeout) cpu_relax(); - if (priv->irq[1]) { + if (priv->irq[1] > 0) { mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3; setbits32(priv->reg + TALITOS_MCR, mcr); } @@ -3242,13 +3242,11 @@ static void talitos_remove(struct platform_device *ofdev) talitos_unregister_rng(dev); for (i = 0; i < 2; i++) - if (priv->irq[i]) { + if (priv->irq[i] > 0) free_irq(priv->irq[i], dev); - irq_dispose_mapping(priv->irq[i]); - } tasklet_kill(&priv->done_task[0]); - if (priv->irq[1]) + if (priv->irq[1] > 0) tasklet_kill(&priv->done_task[1]); } @@ -3354,26 +3352,26 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, static int talitos_probe_irq(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; - struct device_node *np = ofdev->dev.of_node; struct talitos_private *priv = dev_get_drvdata(dev); int err; bool is_sec1 = has_ftr_sec1(priv); - priv->irq[0] = irq_of_parse_and_map(np, 0); - if (!priv->irq[0]) { - dev_err(dev, "failed to map irq\n"); - return -EINVAL; - } + priv->irq[0] = platform_get_irq(ofdev, 0); + if (priv->irq[0] < 0) + return priv->irq[0]; + if (is_sec1) { err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0, dev_driver_string(dev), dev); goto primary_out; } - priv->irq[1] = irq_of_parse_and_map(np, 1); + priv->irq[1] = platform_get_irq_optional(ofdev, 1); + if (priv->irq[1] == -EPROBE_DEFER) + return priv->irq[1]; /* get the primary irq line */ - if (!priv->irq[1]) { + if (priv->irq[1] < 0) { err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0, dev_driver_string(dev), dev); goto primary_out; @@ -3389,7 +3387,6 @@ static int talitos_probe_irq(struct platform_device *ofdev) dev_driver_string(dev), dev); if (err) { dev_err(dev, "failed to request secondary irq\n"); - irq_dispose_mapping(priv->irq[1]); priv->irq[1] = 0; } @@ -3398,7 +3395,6 @@ static int talitos_probe_irq(struct platform_device *ofdev) primary_out: if (err) { dev_err(dev, "failed to request primary irq\n"); - irq_dispose_mapping(priv->irq[0]); priv->irq[0] = 0; } @@ -3499,7 +3495,7 @@ static int talitos_probe(struct platform_device *ofdev) tasklet_init(&priv->done_task[0], talitos1_done_4ch, (unsigned long)dev); } else { - if (priv->irq[1]) { + if (priv->irq[1] > 0) { tasklet_init(&priv->done_task[0], talitos2_done_ch0_2, (unsigned long)dev); tasklet_init(&priv->done_task[1], talitos2_done_ch1_3, @@ -3517,7 +3513,7 @@ static int talitos_probe(struct platform_device *ofdev) for (i = 0; i < priv->num_channels; i++) { priv->chan[i].reg = priv->reg + stride * (i + 1); - if (!priv->irq[1] || !(i & 1)) + if (priv->irq[1] < 0 || !(i & 1)) priv->chan[i].reg += TALITOS_CH_BASE_OFFSET; spin_lock_init(&priv->chan[i].head_lock); From 6f5569203bb6fff31234736a16bfe34bbbd1818b Mon Sep 17 00:00:00 2001 From: Udit Tiwari Date: Wed, 29 Jul 2026 16:34:55 +0530 Subject: [PATCH 096/122] crypto: qce - Add runtime PM and interconnect bandwidth scaling support The Qualcomm Crypto Engine (QCE) driver currently lacks support for runtime power management (PM) and interconnect bandwidth control. As a result, the hardware remains fully powered and clocks stay enabled even when the device is idle. Additionally, static interconnect bandwidth votes are held indefinitely, preventing the system from reclaiming unused bandwidth. Address this by enabling runtime PM and dynamic interconnect bandwidth scaling to allow the system to suspend the device when idle and scale interconnect usage based on actual demand. Improve overall system efficiency by reducing power usage and optimizing interconnect resource allocation. Signed-off-by: Udit Tiwari Tested-by: Pankaj Patil Signed-off-by: Kuldeep Singh Acked-by: Bartosz Golaszewski Tested-by: Bartosz Golaszewski Signed-off-by: Herbert Xu --- drivers/crypto/qce/core.c | 99 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index 7f005d1fca40..31ffdee80168 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -88,7 +90,12 @@ static int qce_handle_queue(struct qce_device *qce, struct crypto_async_request *req) { struct crypto_async_request *async_req, *backlog; - int ret = 0, err; + int ret, err; + + PM_RUNTIME_ACQUIRE_AUTOSUSPEND(qce->dev, pm); + ret = PM_RUNTIME_ACQUIRE_ERR(&pm); + if (ret) + return ret; scoped_guard(mutex, &qce->lock) { if (req) @@ -207,23 +214,33 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret < 0) return ret; - qce->core = devm_clk_get_optional_enabled(qce->dev, "core"); + qce->core = devm_clk_get_optional(qce->dev, "core"); if (IS_ERR(qce->core)) return PTR_ERR(qce->core); - qce->iface = devm_clk_get_optional_enabled(qce->dev, "iface"); + qce->iface = devm_clk_get_optional(qce->dev, "iface"); if (IS_ERR(qce->iface)) return PTR_ERR(qce->iface); - qce->bus = devm_clk_get_optional_enabled(qce->dev, "bus"); + qce->bus = devm_clk_get_optional(qce->dev, "bus"); if (IS_ERR(qce->bus)) return PTR_ERR(qce->bus); - qce->mem_path = devm_of_icc_get(qce->dev, "memory"); + qce->mem_path = devm_of_icc_get(dev, "memory"); if (IS_ERR(qce->mem_path)) return PTR_ERR(qce->mem_path); - ret = icc_set_bw(qce->mem_path, QCE_DEFAULT_MEM_BANDWIDTH, QCE_DEFAULT_MEM_BANDWIDTH); + /* + * Enable runtime PM after clocks and ICC path are acquired so that + * the resume callback can enable clocks and apply the ICC bandwidth + * vote before any hardware access takes place. + */ + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + + PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm); + ret = PM_RUNTIME_ACQUIRE_ERR(&pm); if (ret) return ret; @@ -245,9 +262,76 @@ static int qce_crypto_probe(struct platform_device *pdev) qce->async_req_enqueue = qce_async_request_enqueue; qce->async_req_done = qce_async_request_done; - return devm_qce_register_algs(qce); + ret = devm_qce_register_algs(qce); + if (ret) + return ret; + + /* Configure autosuspend after successful init */ + pm_runtime_set_autosuspend_delay(dev, 100); + pm_runtime_use_autosuspend(dev); + pm_runtime_mark_last_busy(dev); + + return 0; } +static int qce_runtime_suspend(struct device *dev) +{ + struct qce_device *qce = dev_get_drvdata(dev); + int ret; + + clk_disable_unprepare(qce->core); + clk_disable_unprepare(qce->iface); + clk_disable_unprepare(qce->bus); + + ret = icc_set_bw(qce->mem_path, 0, 0); + if (ret) { + clk_prepare_enable(qce->bus); + clk_prepare_enable(qce->iface); + clk_prepare_enable(qce->core); + return ret; + } + + return 0; +} + +static int qce_runtime_resume(struct device *dev) +{ + struct qce_device *qce = dev_get_drvdata(dev); + int ret; + + ret = icc_set_bw(qce->mem_path, QCE_DEFAULT_MEM_BANDWIDTH, + QCE_DEFAULT_MEM_BANDWIDTH); + if (ret) + return ret; + + ret = clk_prepare_enable(qce->core); + if (ret) + goto err_core; + + ret = clk_prepare_enable(qce->iface); + if (ret) + goto err_iface; + + ret = clk_prepare_enable(qce->bus); + if (ret) + goto err_bus; + + return 0; + +err_bus: + clk_disable_unprepare(qce->iface); +err_iface: + clk_disable_unprepare(qce->core); +err_core: + icc_set_bw(qce->mem_path, 0, 0); + return ret; +} + +static const struct dev_pm_ops qce_crypto_pm_ops = { + RUNTIME_PM_OPS(qce_runtime_suspend, qce_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) +}; + static const struct of_device_id qce_crypto_of_match[] = { { .compatible = "qcom,crypto-v5.1", }, { .compatible = "qcom,crypto-v5.4", }, @@ -261,6 +345,7 @@ static struct platform_driver qce_crypto_driver = { .driver = { .name = KBUILD_MODNAME, .of_match_table = qce_crypto_of_match, + .pm = pm_ptr(&qce_crypto_pm_ops), }, }; module_platform_driver(qce_crypto_driver); From 389a3c294ae914efd1681f5355b07ed8b439678d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 29 Jul 2026 22:17:10 -0700 Subject: [PATCH 097/122] crypto: ccp - don't abuse kernel-doc comment format Use plain C "/*" notation for comments that are not in kernel-doc format to avoid kernel-doc warnings: Warning: include/uapi/linux/psp-sfs.h:18 expecting prototype for SFS(). Prototype was for PAYLOAD_NAME_SIZE() instead Warning: include/uapi/linux/psp-sfs.h:46 This comment starts with '/**', but isn't a kernel-doc comment. * Seamless Firmware Support (SFS) IOC Fixes: 648dbccc03a0 ("crypto: ccp - Add AMD Seamless Firmware Servicing (SFS) driver") Signed-off-by: Randy Dunlap Acked-by: Tom Lendacky Signed-off-by: Herbert Xu --- include/uapi/linux/psp-sfs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/psp-sfs.h b/include/uapi/linux/psp-sfs.h index 94e51670383c..fe9402c8a575 100644 --- a/include/uapi/linux/psp-sfs.h +++ b/include/uapi/linux/psp-sfs.h @@ -12,7 +12,7 @@ #include -/** +/* * SFS: AMD Seamless Firmware Support (SFS) interface */ @@ -43,7 +43,7 @@ struct sfs_user_update_package { __u32 sfs_extended_status; } __packed; -/** +/* * Seamless Firmware Support (SFS) IOC * * possible return codes for all SFS IOCTLs: From 967cfc046d7403de9c423a06ec1b0caecdb74463 Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 30 Jul 2026 17:48:41 +0200 Subject: [PATCH 098/122] crypto: ecdsa - Fix typo in function documentation Fix the misspelling of 'validate' in crypto_ecdh_shared_secret() and ecc_is_pubkey_valid_partial() documentation. Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- include/crypto/internal/ecc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h index a4b48d76f53a..d67fe13a543a 100644 --- a/include/crypto/internal/ecc.h +++ b/include/crypto/internal/ecc.h @@ -149,7 +149,7 @@ int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits, * @curve: elliptic curve domain parameters * @pk: public key as a point * - * Valdiate public key according to SP800-56A section 5.6.2.3.4 ECC Partial + * Validate public key according to SP800-56A section 5.6.2.3.4 ECC Partial * Public-Key Validation Routine. * * Note: There is no check that the public key is in the correct elliptic curve @@ -166,7 +166,7 @@ int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve, * @curve: elliptic curve domain parameters * @pk: public key as a point * - * Valdiate public key according to SP800-56A section 5.6.2.3.3 ECC Full + * Validate public key according to SP800-56A section 5.6.2.3.3 ECC Full * Public-Key Validation Routine. * * Return: 0 if validation is successful, -EINVAL if validation is failed. From e5658c60414627502ed1e9aea77a3086d53e100a Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 30 Jul 2026 12:00:29 -0700 Subject: [PATCH 099/122] crypto: cesa - clear cesa_dev on _remove This is already done on probe failure. cesa_dev should be set to NULL as the driver checks that it is not and errors saying that only one device is authorized. Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/marvell/cesa/cesa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/marvell/cesa/cesa.c b/drivers/crypto/marvell/cesa/cesa.c index 4859ad2e86b4..564b09773507 100644 --- a/drivers/crypto/marvell/cesa/cesa.c +++ b/drivers/crypto/marvell/cesa/cesa.c @@ -544,6 +544,8 @@ static void mv_cesa_remove(struct platform_device *pdev) struct mv_cesa_dev *cesa = platform_get_drvdata(pdev); mv_cesa_remove_algs(cesa); + + cesa_dev = NULL; } static const struct platform_device_id mv_cesa_plat_id_table[] = { From aacf3a6c47b30e7e32cf2ed954c19730a32dbe5f Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 30 Jul 2026 12:14:20 -0700 Subject: [PATCH 100/122] crypto: amcc - fix racy teardown with devm_request_irq The driver uses devm_request_irq() for the IRQ, but cleans up the tasklet and DMA rings inside the remove function. Since devres frees the IRQ only after the remove function returns, a window exists where a pending hardware interrupt can reschedule the tasklet after it has been killed, leading to use-after-free of the descriptor rings. Fix by switching to plain request_irq() and adding the corresponding free_irq() calls in the remove function and the probe error path before tasklet_kill(), ensuring the IRQ is fully torn down before the tasklet is killed. Rename goto error path to err_tasklet as that's more descriptive. Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/amcc/crypto4xx_core.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 0271b5e4d923..fd010bfb7020 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -1294,14 +1294,14 @@ static int crypto4xx_probe(struct platform_device *ofdev) core_dev->irq = platform_get_irq(ofdev, 0); if (core_dev->irq < 0) { rc = core_dev->irq; - goto err_iomap; + goto err_tasklet; } - rc = devm_request_irq(&ofdev->dev, core_dev->irq, - is_revb ? crypto4xx_ce_interrupt_handler_revb : - crypto4xx_ce_interrupt_handler, - 0, KBUILD_MODNAME, dev); + rc = request_irq(core_dev->irq, + is_revb ? crypto4xx_ce_interrupt_handler_revb : + crypto4xx_ce_interrupt_handler, + 0, KBUILD_MODNAME, dev); if (rc) - goto err_iomap; + goto err_tasklet; /* need to setup pdr, rdr, gdr and sdr before this */ crypto4xx_hw_init(core_dev->dev); @@ -1310,12 +1310,14 @@ static int crypto4xx_probe(struct platform_device *ofdev) rc = crypto4xx_register_alg(core_dev->dev, crypto4xx_alg, ARRAY_SIZE(crypto4xx_alg)); if (rc) - goto err_iomap; + goto err_irq; ppc4xx_trng_probe(core_dev); return 0; -err_iomap: +err_irq: + free_irq(core_dev->irq, dev); +err_tasklet: tasklet_kill(&core_dev->tasklet); err_build_sdr: crypto4xx_destroy_sdr(core_dev->dev); @@ -1331,6 +1333,11 @@ static void crypto4xx_remove(struct platform_device *ofdev) ppc4xx_trng_remove(core_dev); + /* + * Free IRQ before killing the tasklet to prevent the interrupt + * handler from rescheduling the tasklet after it has been killed. + */ + free_irq(core_dev->irq, dev); tasklet_kill(&core_dev->tasklet); /* Un-register with Linux CryptoAPI */ crypto4xx_unregister_alg(core_dev->dev); From 9a955c0a7d116240db52c29eca133efcb1f6d72a Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 30 Jul 2026 13:47:22 -0700 Subject: [PATCH 101/122] crypto: caam - simplify probe resource and IRQ handling Convert the interrupt acquisition from irq_of_parse_and_map() to platform_get_irq(), which resolves the IRQ from the device's interrupts property via of_irq_get(). Flip the error check from testing for zero to testing for a negative errno, and drop the now-unused caam_jr_irq_dispose_mapping() callback and its devm_add_action_or_reset() cleanup, since platform_get_irq() manages the mapping internally. Replace the open-coded platform_get_resource() plus devm_ioremap() sequence with devm_platform_ioremap_resource(), which fetches the resource, requests the region and maps it in one call. Each fsl,sec-*-job-ring node has a distinct 0x10000 reg region and interrupts property, so the region reservation added by devm_ioremap_resource() is exclusive and does not introduce overlap failures. Assisted-by: opencode:hy3-free Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/caam/jr.c | 46 +++++++++++----------------------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index bddeaaaca487..239469f6882e 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -574,23 +574,25 @@ static int caam_jr_init(struct device *dev) return error; } -static void caam_jr_irq_dispose_mapping(void *data) -{ - irq_dispose_mapping((unsigned long)data); -} - /* * Probe routine for each detected JobR subsystem. */ static int caam_jr_probe(struct platform_device *pdev) { struct device *jrdev; - struct device_node *nprop; - struct caam_job_ring __iomem *ctrl; struct caam_drv_private_jr *jrpriv; static int total_jobrs; - struct resource *r; + void __iomem *ctrl; int error; + int irq; + + ctrl = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ctrl)) + return PTR_ERR(ctrl); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; jrdev = &pdev->dev; jrpriv = devm_kzalloc(jrdev, sizeof(*jrpriv), GFP_KERNEL); @@ -602,22 +604,7 @@ static int caam_jr_probe(struct platform_device *pdev) /* save ring identity relative to detection */ jrpriv->ridx = total_jobrs++; - nprop = pdev->dev.of_node; - /* Get configuration properties from device tree */ - /* First, get register page */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(jrdev, "platform_get_resource() failed\n"); - return -ENOMEM; - } - - ctrl = devm_ioremap(jrdev, r->start, resource_size(r)); - if (!ctrl) { - dev_err(jrdev, "devm_ioremap() failed\n"); - return -ENOMEM; - } - - jrpriv->rregs = (struct caam_job_ring __iomem __force *)ctrl; + jrpriv->rregs = ctrl; error = dma_set_mask_and_coherent(jrdev, caam_get_dma_mask(jrdev)); if (error) { @@ -647,16 +634,7 @@ static int caam_jr_probe(struct platform_device *pdev) } /* Identify the interrupt */ - jrpriv->irq = irq_of_parse_and_map(nprop, 0); - if (!jrpriv->irq) { - dev_err(jrdev, "irq_of_parse_and_map failed\n"); - return -EINVAL; - } - - error = devm_add_action_or_reset(jrdev, caam_jr_irq_dispose_mapping, - (void *)(unsigned long)jrpriv->irq); - if (error) - return error; + jrpriv->irq = irq; /* Now do the platform independent part */ error = caam_jr_init(jrdev); /* now turn on hardware */ From bf3285b7a7f8690f6b0c4c2fcfb8d30f19549db2 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 31 Jul 2026 12:25:32 +0200 Subject: [PATCH 102/122] crypto: qce - simplify devm_qce_register_algs Drop the redundant ret = -ENODEV initialization. Use a while loop and reuse the local index variable i on the error path. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/qce/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index 31ffdee80168..e8d5f5a65f00 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -54,14 +54,14 @@ static void qce_unregister_algs(void *data) static int devm_qce_register_algs(struct qce_device *qce) { const struct qce_algo_ops *ops; - int i, j, ret = -ENODEV; + int i, ret; for (i = 0; i < ARRAY_SIZE(qce_ops); i++) { ops = qce_ops[i]; ret = ops->register_algs(qce); if (ret) { - for (j = i - 1; j >= 0; j--) - qce_ops[j]->unregister_algs(qce); + while (i--) + qce_ops[i]->unregister_algs(qce); return ret; } } From ebd1071c217a6813050a5fd3561fd453ffd152f2 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 31 Jul 2026 12:25:33 +0200 Subject: [PATCH 103/122] crypto: qce - simplify qce_handle_request Simplify the for loop's control flow and return the results directly. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/qce/core.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index e8d5f5a65f00..f50bffa7e0aa 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -71,19 +71,17 @@ static int devm_qce_register_algs(struct qce_device *qce) static int qce_handle_request(struct crypto_async_request *async_req) { - int ret = -EINVAL, i; + int i; const struct qce_algo_ops *ops; u32 type = crypto_tfm_alg_type(async_req->tfm); for (i = 0; i < ARRAY_SIZE(qce_ops); i++) { ops = qce_ops[i]; - if (type != ops->type) - continue; - ret = ops->async_req_handle(async_req); - break; + if (type == ops->type) + return ops->async_req_handle(async_req); } - return ret; + return -EINVAL; } static int qce_handle_queue(struct qce_device *qce, From 61135c1597af56eb454d53c9d7cda90d5e5dc566 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Fri, 31 Jul 2026 13:48:32 +0100 Subject: [PATCH 104/122] crypto: qat - remove dead ADF_HEX code The ADF_HEX value type is defined in the adf_cfg_val_type enum and handled in adf_cfg_add_key_value_param(), but no caller in the tree uses it. Remove the unused ADF_HEX enum value and its dead handling code. Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework") Reviewed-by: Giovanni Cabiddu Reviewed-by: Svyatoslav Pankratov Signed-off-by: Ahsan Atta Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_cfg.c | 3 --- drivers/crypto/intel/qat/qat_common/adf_cfg_common.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.c b/drivers/crypto/intel/qat/qat_common/adf_cfg.c index d97ee1000045..b88febf53a19 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c @@ -292,9 +292,6 @@ int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, "%ld", (*((long *)val))); } else if (type == ADF_STR) { strscpy(key_val->val, (char *)val); - } else if (type == ADF_HEX) { - snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES, - "0x%lx", (unsigned long)val); } else { dev_err(&GET_DEV(accel_dev), "Unknown type given.\n"); kfree(key_val); diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h index d63f4dcccbb5..5922d018f5b9 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h @@ -28,7 +28,6 @@ enum adf_cfg_service_type { enum adf_cfg_val_type { ADF_DEC, - ADF_HEX, ADF_STR }; From 188bb9ad86c3b2d527385328a30c1d9510253202 Mon Sep 17 00:00:00 2001 From: Yuho Choi Date: Sun, 2 Aug 2026 18:22:59 -0400 Subject: [PATCH 105/122] hwrng: imx-rngc - Disable clock on registration failure The RNGC clock is enabled manually before runtime PM is configured. If devm_hwrng_register() fails, probe returns without disabling the clock. The devm_pm_runtime_enable() cleanup only disables runtime PM and does not call imx_rngc_suspend(). Disable the clock before returning from this failure path. Fixes: 7a96a64e8689 ("hwrng: imx-rngc - add runtime pm") Signed-off-by: Yuho Choi Reviewed-by: Martin Kaiser Signed-off-by: Herbert Xu --- drivers/char/hw_random/imx-rngc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index fb43894a906b..63fe76f01d26 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -314,8 +314,10 @@ static int __init imx_rngc_probe(struct platform_device *pdev) devm_pm_runtime_enable(&pdev->dev); ret = devm_hwrng_register(&pdev->dev, &rngc->rng); - if (ret) + if (ret) { + clk_disable_unprepare(rngc->clk); return dev_err_probe(&pdev->dev, ret, "hwrng registration failed\n"); + } dev_info(&pdev->dev, "Freescale RNG%c registered (HW revision %d.%02d)\n", From d9506e82ced5784c220a1ff77c24b6b7d6e4de08 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 2 Aug 2026 16:00:53 -0700 Subject: [PATCH 106/122] crypto: af_alg - Make cbc(paes) privileged-only So far the only reported use cases for cbc(paes) have involved processes running as root. Therefore, make af_alg_restrict=1 allow only privileged use of this algorithm for now. Fixes: 947d62c09436 ("Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6") Signed-off-by: Eric Biggers Reviewed-by: Richard Weinberger Signed-off-by: Herbert Xu --- crypto/algif_skcipher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 4c86b1993bde..68b48d805e92 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -41,7 +41,7 @@ static const struct af_alg_allowlist_entry skcipher_allowlist[] = { { "cbc(aes)", true }, /* iwd */ { "cbc(des)", true }, /* iwd */ { "cbc(des3_ede)", true }, /* iwd */ - { "cbc(paes)", false }, /* caam and others */ + { "cbc(paes)", true }, /* caam and others */ { "ctr(aes)", true }, /* iwd */ { "ecb(aes)", true }, /* iwd, bluez */ { "ecb(des)", true }, /* iwd */ From 185c67edbb7cb7233de57168b612c08cdec8f1ac Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 2 Aug 2026 16:00:54 -0700 Subject: [PATCH 107/122] crypto: af_alg - Replace 'bool privileged' with flags It isn't obvious what false/true mean at the definition sites, so let's replace it with flags instead. Also flip the polarity to make the default zero-initialized value be the secure (privileged-only) value. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/af_alg.c | 3 ++- crypto/algif_aead.c | 2 +- crypto/algif_hash.c | 28 ++++++++++++++-------------- crypto/algif_skcipher.c | 28 ++++++++++++++-------------- include/crypto/if_alg.h | 6 +++++- 5 files changed, 36 insertions(+), 31 deletions(-) diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 34b801568fba..1e5da61b315c 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -146,7 +146,8 @@ int af_alg_check_restriction(const char *name, for (const struct af_alg_allowlist_entry *ent = allowlist; ent->name; ent++) { if (strcmp(name, ent->name) == 0 && - (!ent->privileged || af_alg_capable())) + ((ent->flags & AF_ALG_UNPRIVILEGED) || + af_alg_capable())) return 0; } } diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index b9217f9086aa..5574e2d70539 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -35,7 +35,7 @@ #include static const struct af_alg_allowlist_entry aead_allowlist[] = { - { "ccm(aes)", true }, /* bluez */ + { "ccm(aes)" }, /* bluez */ {}, }; diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index a8d958d51ece..6e8b5fb82a7f 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -17,20 +17,20 @@ #include static const struct af_alg_allowlist_entry hash_allowlist[] = { - { "cmac(aes)", true }, /* iwd, bluez */ - { "hmac(md5)", true }, /* iwd */ - { "hmac(sha1)", true }, /* iwd */ - { "hmac(sha224)", true }, /* iwd */ - { "hmac(sha256)", true }, /* iwd */ - { "hmac(sha384)", true }, /* iwd */ - { "hmac(sha512)", true }, /* iwd, sha512hmac */ - { "md4", true }, /* iwd */ - { "md5", true }, /* iwd */ - { "sha1", false }, /* iwd, iproute2 < 7.0 */ - { "sha224", true }, /* iwd */ - { "sha256", true }, /* iwd */ - { "sha384", true }, /* iwd */ - { "sha512", true }, /* iwd */ + { "cmac(aes)" }, /* iwd, bluez */ + { "hmac(md5)" }, /* iwd */ + { "hmac(sha1)" }, /* iwd */ + { "hmac(sha224)" }, /* iwd */ + { "hmac(sha256)" }, /* iwd */ + { "hmac(sha384)" }, /* iwd */ + { "hmac(sha512)" }, /* iwd, sha512hmac */ + { "md4" }, /* iwd */ + { "md5" }, /* iwd */ + { "sha1", AF_ALG_UNPRIVILEGED }, /* iwd, iproute2 < 7.0 */ + { "sha224" }, /* iwd */ + { "sha256" }, /* iwd */ + { "sha384" }, /* iwd */ + { "sha512" }, /* iwd */ {}, }; diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 68b48d805e92..1e61fe6e24b9 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -36,20 +36,20 @@ #include static const struct af_alg_allowlist_entry skcipher_allowlist[] = { - { "adiantum(xchacha12,aes)", false }, /* cryptsetup */ - { "adiantum(xchacha20,aes)", false }, /* cryptsetup */ - { "cbc(aes)", true }, /* iwd */ - { "cbc(des)", true }, /* iwd */ - { "cbc(des3_ede)", true }, /* iwd */ - { "cbc(paes)", true }, /* caam and others */ - { "ctr(aes)", true }, /* iwd */ - { "ecb(aes)", true }, /* iwd, bluez */ - { "ecb(des)", true }, /* iwd */ - { "hctr2(aes)", false }, /* cryptsetup */ - { "xts(aes)", false }, /* cryptsetup benchmark */ - { "xts(camellia)", false }, /* cryptsetup */ - { "xts(serpent)", false }, /* cryptsetup */ - { "xts(twofish)", false }, /* cryptsetup */ + { "adiantum(xchacha12,aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "adiantum(xchacha20,aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "cbc(aes)" }, /* iwd */ + { "cbc(des)" }, /* iwd */ + { "cbc(des3_ede)" }, /* iwd */ + { "cbc(paes)" }, /* caam and others */ + { "ctr(aes)" }, /* iwd */ + { "ecb(aes)" }, /* iwd, bluez */ + { "ecb(des)" }, /* iwd */ + { "hctr2(aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "xts(aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup benchmark */ + { "xts(camellia)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "xts(serpent)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "xts(twofish)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ {}, }; diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index dbf6a97c72a2..0d51428c1da4 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -8,6 +8,7 @@ #ifndef _CRYPTO_IF_ALG_H #define _CRYPTO_IF_ALG_H +#include #include #include #include @@ -161,9 +162,12 @@ struct af_alg_ctx { unsigned int inflight; }; +/* Flags for af_alg_allowlist_entry::flags: */ +#define AF_ALG_UNPRIVILEGED BIT(0) /* Unprivileged use is allowed */ + struct af_alg_allowlist_entry { const char *name; - bool privileged; + u32 flags; }; int af_alg_register_type(const struct af_alg_type *type); From 68554337b4aa63d8299edd58f5059d8470bc721b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 2 Aug 2026 16:00:55 -0700 Subject: [PATCH 108/122] crypto: af_alg - Stop after finding name in allowlist If the algorithm name is found in the allowlist and the privilege check doesn't pass, there's no need to consider remaining entries since the list contains (and is intended to contain) at most one entry per name. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/af_alg.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 1e5da61b315c..ab84c4488a15 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -145,10 +145,13 @@ int af_alg_check_restriction(const char *name, if (level == 1) { for (const struct af_alg_allowlist_entry *ent = allowlist; ent->name; ent++) { - if (strcmp(name, ent->name) == 0 && - ((ent->flags & AF_ALG_UNPRIVILEGED) || - af_alg_capable())) - return 0; + if (strcmp(name, ent->name) == 0) { + if ((ent->flags & AF_ALG_UNPRIVILEGED) || + af_alg_capable()) + return 0; + /* List contains at most one entry per name. */ + break; + } } } /* From f7d53dd3f267e46a784f219a75072f2f400d42b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sebastian=20G=C3=B6tte?= Date: Mon, 3 Aug 2026 21:26:21 +0200 Subject: [PATCH 109/122] crypto: krb5 - use kfree_sensitive() for derived key buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crypto_krb5_prepare_encryption() and crypto_krb5_prepare_checksum() free the buffer holding the freshly derived keys with plain kfree(), leaving the key material behind in the freed slab object. Fixes: 3936f02bf2d3 ("crypto/krb5: Implement Kerberos crypto core") Cc: stable@vger.kernel.org Signed-off-by: Jan Sebastian Götte Signed-off-by: Herbert Xu --- crypto/krb5/krb5_api.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto/krb5/krb5_api.c b/crypto/krb5/krb5_api.c index 03395b89cc61..b377f4f7558d 100644 --- a/crypto/krb5/krb5_api.c +++ b/crypto/krb5/krb5_api.c @@ -263,10 +263,10 @@ struct crypto_aead *crypto_krb5_prepare_encryption(const struct krb5_enctype *kr goto err; } - kfree(keys.data); + kfree_sensitive(keys.data); return ci; err: - kfree(keys.data); + kfree_sensitive(keys.data); return ERR_PTR(ret); } EXPORT_SYMBOL(crypto_krb5_prepare_encryption); @@ -333,10 +333,10 @@ struct crypto_shash *crypto_krb5_prepare_checksum(const struct krb5_enctype *krb goto err; } - kfree(keys.data); + kfree_sensitive(keys.data); return ci; err: - kfree(keys.data); + kfree_sensitive(keys.data); return ERR_PTR(ret); } EXPORT_SYMBOL(crypto_krb5_prepare_checksum); From ce64a0e7e619a9bdc10c69810efdecc319a6c8ee Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 3 Aug 2026 15:40:28 -0700 Subject: [PATCH 110/122] crypto: eip93 - use struct_size() and flexible array for ring allocation Embed the single ring as a flexible array member in eip93_device instead of allocating it separately. This simplifies the probe path and uses struct_size() for a single allocation. Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- .../crypto/inside-secure/eip93/eip93-main.c | 6 +---- .../crypto/inside-secure/eip93/eip93-main.h | 22 +++++++++---------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/inside-secure/eip93/eip93-main.c b/drivers/crypto/inside-secure/eip93/eip93-main.c index 1a8dabc4ada4..e62785952b0d 100644 --- a/drivers/crypto/inside-secure/eip93/eip93-main.c +++ b/drivers/crypto/inside-secure/eip93/eip93-main.c @@ -415,7 +415,7 @@ static int eip93_crypto_probe(struct platform_device *pdev) u32 ver, algo_flags; int ret; - eip93 = devm_kzalloc(dev, sizeof(*eip93), GFP_KERNEL); + eip93 = devm_kzalloc(dev, struct_size(eip93, ring, 1), GFP_KERNEL); if (!eip93) return -ENOMEM; @@ -436,10 +436,6 @@ static int eip93_crypto_probe(struct platform_device *pdev) if (ret) return ret; - eip93->ring = devm_kcalloc(eip93->dev, 1, sizeof(*eip93->ring), GFP_KERNEL); - if (!eip93->ring) - return -ENOMEM; - ret = eip93_desc_init(eip93); if (ret) return ret; diff --git a/drivers/crypto/inside-secure/eip93/eip93-main.h b/drivers/crypto/inside-secure/eip93/eip93-main.h index 990c2401b7ce..5f0f51081743 100644 --- a/drivers/crypto/inside-secure/eip93/eip93-main.h +++ b/drivers/crypto/inside-secure/eip93/eip93-main.h @@ -92,17 +92,6 @@ EIP93_HASH_SHA224 | \ EIP93_HASH_SHA256)) -/** - * struct eip93_device - crypto engine device structure - */ -struct eip93_device { - void __iomem *base; - struct device *dev; - struct clk *clk; - int irq; - struct eip93_ring *ring; -}; - struct eip93_desc_ring { void *base; void *base_end; @@ -131,6 +120,17 @@ struct eip93_ring { struct idr crypto_async_idr; }; +/** + * struct eip93_device - crypto engine device structure + */ +struct eip93_device { + void __iomem *base; + struct device *dev; + struct clk *clk; + int irq; + struct eip93_ring ring[]; +}; + enum eip93_alg_type { EIP93_ALG_TYPE_AEAD, EIP93_ALG_TYPE_SKCIPHER, From b82f60be50c87b3d75e207852c5ca74fa18f66cf Mon Sep 17 00:00:00 2001 From: Zhushuai Yin Date: Tue, 4 Aug 2026 10:22:07 +0800 Subject: [PATCH 111/122] crypto: hisilicon/sec2 - fix CCM algorithm long packet failure In the CCM B0 block the message-length field Q spans L bytes, where L (cl in the driver) is derived from the cipher IV flags byte as c_ivin[0] + 1. set_aead_auth_iv() hardcoded writing only the last 2 bytes of a_ivin with cryptlen, implicitly assuming cl = 2. When cl = 3 (a shorter nonce yielding a 3-byte length field) and the packet is longer than 65535 bytes, cryptlen no longer fits in 2 bytes. The dropped high byte made the auth IV built by the driver differ from the one consumed by the hardware, so the software/hardware comparison failed and the CCM request errored out. Write the last cl bytes of a_ivin in a loop driven by the IV's CL value, so the length-field width always matches the algorithm configuration instead of assuming a fixed 2-byte field. Fixes: c16a70c1f253 ("crypto: hisilicon/sec - add new algorithm mode for AEAD") Signed-off-by: Zhushuai Yin Signed-off-by: Chenghai Huang Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/sec2/sec_crypto.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c index 01eb76f616fc..0a2f7c8b44fc 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -96,7 +96,6 @@ #define IV_FLAGS_OFFSET 0x6 #define IV_CM_OFFSET 0x3 #define IV_LAST_BYTE1 1 -#define IV_LAST_BYTE2 2 #define IV_LAST_BYTE_MASK 0xFF #define IV_CTR_INIT 0x1 #define IV_BYTE_OFFSET 0x8 @@ -1700,7 +1699,7 @@ static void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req) struct sec_cipher_req *c_req = &req->c_req; u32 data_size = aead_req->cryptlen; u8 flage = 0; - u8 cm, cl; + u8 cm, cl, i; /* the specification has been checked in aead_iv_demension_check() */ cl = c_req->c_ivin[0] + 1; @@ -1724,15 +1723,16 @@ static void set_aead_auth_iv(struct sec_ctx *ctx, struct sec_req *req) * the last 32bit is counter's initial number, * but the nonce uses the first 16bit * the tail 16bit fill with the cipher length + * When CL is 3, the tail 24bit fill with the cipher length. */ if (!c_req->encrypt) data_size = aead_req->cryptlen - authsize; - a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE1] = - data_size & IV_LAST_BYTE_MASK; - data_size >>= IV_BYTE_OFFSET; - a_req->a_ivin[ctx->c_ctx.ivsize - IV_LAST_BYTE2] = + for (i = 1; i <= cl; i++) { + a_req->a_ivin[ctx->c_ctx.ivsize - i] = data_size & IV_LAST_BYTE_MASK; + data_size >>= IV_BYTE_OFFSET; + } } static void sec_aead_set_iv(struct sec_ctx *ctx, struct sec_req *req) From b1c0e120977f97f550ef12a8d32161aa4f0f8284 Mon Sep 17 00:00:00 2001 From: "Thomas Richard (TI)" Date: Tue, 4 Aug 2026 12:01:09 +0200 Subject: [PATCH 112/122] hwrng: core - Stop/start hwrng_fillfn() kthread before/after suspend-resume The hwrng_fillfn() kernel thread accesses the RNG device directly. During suspend and resume sequences, hwrng_fillfn() may attempt to access the RNG device while it is suspended. To address this, the hwrng_fillfn() kernel thread is stopped before suspend, and restarted after resume. This is done using the pm_notifier mechanism. Issue was found while doing suspend-to-ram on J721S2 EVM board with omap-rng driver. echo mem > /sys/power/state [ 27.922259] PM: suspend entry (deep) [ 27.927191] Filesystems sync: 0.000 seconds [ 27.933858] Freezing user space processes [ 27.939119] Freezing user space processes completed (elapsed 0.001 seconds) [ 27.946090] OOM killer disabled. [ 27.949315] Freezing remaining freezable tasks [ 27.954887] Freezing remaining freezable tasks completed (elapsed 0.001 seconds) [ 27.963337] GFP mask restricted [ 27.967069] omap_rng 4e10000.rng: PM: calling platform_pm_suspend @ 195, parent: 4e00000.crypto [ 27.967072] mmcblk mmc1:9fb0: PM: calling mmc_bus_suspend @ 122, parent: mmc1 [ 27.968636] mmcblk mmc1:9fb0: PM: mmc_bus_suspend returned 0 after 1546 usecs [ 27.975778] omap_rng 4e10000.rng: PM: platform_pm_suspend returned 0 after 3 usecs ... [ 33.510667] ti-sci 44083000.system-controller: PM: ti_sci_suspend_noirq returned 0 after 0 usecs [ 33.510671] SError Interrupt on CPU0, code 0x00000000bf000000 -- SError [ 33.510681] CPU: 0 UID: 0 PID: 132 Comm: hwrng Tainted: G M W 7.0.0-12695-g8923b7a6e11d #19 PREEMPT [ 33.510690] Tainted: [M]=MACHINE_CHECK, [W]=WARN [ 33.510693] Hardware name: Texas Instruments J721S2 EVM (DT) [ 33.510697] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 33.510701] pc : omap_rng_do_read+0x3c/0xe0 [ 33.510709] lr : omap_rng_do_read+0x58/0xe0 [ 33.510712] sp : ffff80008942be00 [ 33.510713] x29: ffff80008942be00 x28: 0000000000000000 x27: 0000000000000000 [ 33.510719] x26: 0000000000000010 x25: 0000000000000010 x24: ffff0008065644e8 [ 33.510724] x23: ffff8000878b3370 x22: ffff00080148b2c0 x21: 0000000000000000 [ 33.510728] x20: ffff000806564480 x19: 0000000000000064 x18: 0000000000000000 [ 33.510732] x17: 6573752031207265 x16: 7466612030206465 x15: 6e72757465722071 [ 33.510737] x14: ffff0008062c8080 x13: 000031702bc0da42 x12: 0000000000000001 [ 33.510741] x11: 00000000000000c0 x10: 0000000000000b30 x9 : ffff80008942bc80 [ 33.510745] x8 : ffff0008062c8b90 x7 : ffff000b7dfa34c0 x6 : 0000000805ca16c1 [ 33.510749] x5 : 0000000000000000 x4 : ffff800080e17bfc x3 : ffff800087389c68 [ 33.510753] x2 : 0000000000000000 x1 : 0000000000000010 x0 : 000000000000a7c6 [ 33.510759] Kernel panic - not syncing: Asynchronous SError Interrupt [ 33.510762] CPU: 0 UID: 0 PID: 132 Comm: hwrng Tainted: G M W 7.0.0-12695-g8923b7a6e11d #19 PREEMPT [ 33.510767] Tainted: [M]=MACHINE_CHECK, [W]=WARN [ 33.510768] Hardware name: Texas Instruments J721S2 EVM (DT) [ 33.510770] Call trace: [ 33.510772] show_stack+0x18/0x24 (C) [ 33.510780] dump_stack_lvl+0x34/0x8c [ 33.510788] dump_stack+0x18/0x24 [ 33.510792] vpanic+0x47c/0x4dc [ 33.510799] do_panic_on_target_cpu+0x0/0x1c [ 33.510803] add_taint+0x0/0xbc [ 33.510807] arm64_serror_panic+0x70/0x80 [ 33.510812] do_serror+0x3c/0x70 [ 33.510815] el1h_64_error_handler+0x34/0x50 [ 33.510823] el1h_64_error+0x6c/0x70 [ 33.510827] omap_rng_do_read+0x3c/0xe0 (P) [ 33.510831] hwrng_fillfn+0x98/0x330 [ 33.510834] kthread+0x130/0x13c [ 33.510845] ret_from_fork+0x10/0x20 [ 33.510850] SMP: stopping secondary CPUs [ 33.519442] Kernel Offset: disabled [ 33.519444] CPU features: 0x04000000,800a0008,00040001,0400421b [ 33.519448] Memory Limit: none [ 33.732904] ---[ end Kernel panic - not syncing: Asynchronous SError Interrupt ]--- Signed-off-by: Thomas Richard (TI) Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 101 +++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 15 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index e77af6578ab5..57eeefe90da9 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -17,14 +17,17 @@ #include #include #include +#include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -45,6 +48,8 @@ static DEFINE_MUTEX(rng_mutex); static DEFINE_MUTEX(reading_mutex); static int data_avail; static u8 *rng_buffer, *rng_fillbuf; +/* Set to true during suspend-resume by PM notifier, protected by rng_mutex */ +static bool hwrng_fillfn_stopped; static unsigned short current_quality; static unsigned short default_quality = 1024; /* default to maximum */ @@ -57,6 +62,8 @@ MODULE_PARM_DESC(default_quality, static int hwrng_init(struct hwrng *rng); static int hwrng_fillfn(void *unused); +static void hwrng_start_hwrng_fillfn(void); +static void hwrng_stop_hwrng_fillfn(void); static size_t rng_buffer_size(void) { @@ -114,13 +121,7 @@ static int set_current_rng(struct hwrng *rng) } /* if necessary, start hwrng thread */ - if (!hwrng_fill) { - hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng"); - if (IS_ERR(hwrng_fill)) { - pr_err("hwrng_fill thread creation failed\n"); - hwrng_fill = NULL; - } - } + hwrng_start_hwrng_fillfn(); return 0; } @@ -137,10 +138,7 @@ static void drop_current_rng(void) RCU_INIT_POINTER(current_rng, NULL); synchronize_rcu(); - if (hwrng_fill) { - kthread_stop(hwrng_fill); - hwrng_fill = NULL; - } + hwrng_stop_hwrng_fillfn(); /* decrease last reference for triggering the cleanup */ kref_put(&rng->ref, cleanup_rng); @@ -506,6 +504,36 @@ static struct attribute *rng_dev_attrs[] = { ATTRIBUTE_GROUPS(rng_dev); +static void hwrng_start_hwrng_fillfn(void) +{ + lockdep_assert_held(&rng_mutex); + + /* + * PM notifier stopped the hwrng_fillfn kthread, prevent userspace to + * restart it until kernel freezes threads. + */ + if (hwrng_fillfn_stopped) + return; + + if (!hwrng_fill) { + hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng"); + if (IS_ERR(hwrng_fill)) { + pr_err("hwrng_fill thread creation failed\n"); + hwrng_fill = NULL; + } + } +} + +static void hwrng_stop_hwrng_fillfn(void) +{ + lockdep_assert_held(&rng_mutex); + + if (hwrng_fill) { + kthread_stop(hwrng_fill); + hwrng_fill = NULL; + } +} + static int hwrng_fillfn(void *unused) { size_t entropy, entropy_credit = 0; /* in 1/1024 of a bit */ @@ -559,6 +587,37 @@ static int hwrng_fillfn(void *unused) return 0; } +static int hwrng_pm_notifier(struct notifier_block *nb, unsigned long action, + void *data) +{ + switch (action) { + case PM_SUSPEND_PREPARE: + case PM_HIBERNATION_PREPARE: + case PM_RESTORE_PREPARE: + mutex_lock(&rng_mutex); + hwrng_stop_hwrng_fillfn(); + hwrng_fillfn_stopped = true; + mutex_unlock(&rng_mutex); + break; + + case PM_POST_SUSPEND: + case PM_POST_HIBERNATION: + case PM_POST_RESTORE: + mutex_lock(&rng_mutex); + hwrng_fillfn_stopped = false; + if (rcu_access_pointer(current_rng)) + hwrng_start_hwrng_fillfn(); + mutex_unlock(&rng_mutex); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block hwrng_pm_nb = { + .notifier_call = hwrng_pm_notifier, +}; + int hwrng_register(struct hwrng *rng) { int err = -EINVAL; @@ -707,10 +766,20 @@ static int __init hwrng_modinit(void) } ret = misc_register(&rng_miscdev); - if (ret) { - kfree(rng_fillbuf); - kfree(rng_buffer); - } + if (ret) + goto misc_err; + + ret = register_pm_notifier(&hwrng_pm_nb); + if (ret) + goto pm_err; + + return 0; + +pm_err: + misc_deregister(&rng_miscdev); +misc_err: + kfree(rng_fillbuf); + kfree(rng_buffer); return ret; } @@ -723,6 +792,8 @@ static void __exit hwrng_modexit(void) kfree(rng_fillbuf); mutex_unlock(&rng_mutex); + unregister_pm_notifier(&hwrng_pm_nb); + misc_deregister(&rng_miscdev); } From c7fdfd2bee1cf1448e5244da1a734e680f634b02 Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Wed, 5 Aug 2026 14:19:23 -0700 Subject: [PATCH 113/122] crypto: iaa - fall back to software for multi-entry scatterlists IAA cannot process source or destination scatterlists with more than one entry directly. Instead of failing these requests, route them through a separate deflate acomp transform and keep the request alive in software. The IAA driver has never handled multi-entry scatterlists, but the limitation was latent until commit e2c3b6b21c77 ("mm: zswap: use SG list decompression APIs from zsmalloc") made zswap pass the raw zsmalloc SG list directly to crypto drivers, so objects spanning multiple pages now reach IAA as multi-entry sources and would otherwise fail decompression. Fallback to the generic DEFLATE implementation for scatterlists with more than one entry. After the multi-entry cases fall back early, simplify the DMA mapping path to a single scatterlist entry and fall back on mapping failure as well. Add counters to track the number of requests processed by the software implementation on the compression direction. Fixes: 2ec6761df889 ("crypto: iaa - Add support for deflate-iaa compression algorithm") Fixes: e2c3b6b21c77 ("mm: zswap: use SG list decompression APIs from zsmalloc") Cc: stable@vger.kernel.org Signed-off-by: Giovanni Cabiddu Signed-off-by: Vinicius Costa Gomes Signed-off-by: Herbert Xu --- drivers/crypto/intel/iaa/iaa_crypto_main.c | 111 +++++++++++--------- drivers/crypto/intel/iaa/iaa_crypto_stats.c | 9 ++ drivers/crypto/intel/iaa/iaa_crypto_stats.h | 2 + 3 files changed, 71 insertions(+), 51 deletions(-) diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c index f62b994e18e5..904d9413ba18 100644 --- a/drivers/crypto/intel/iaa/iaa_crypto_main.c +++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c @@ -2,6 +2,7 @@ /* Copyright(c) 2021 Intel Corporation. All rights rsvd. */ #include +#include #include #include #include @@ -996,6 +997,19 @@ static int deflate_generic_decompress(struct acomp_req *req) return ret; } +static int deflate_generic_compress(struct acomp_req *req) +{ + ACOMP_FBREQ_ON_STACK(fbreq, req); + int ret; + + ret = crypto_acomp_compress(fbreq); + req->dlen = fbreq->dlen; + + update_total_sw_comp_calls(); + + return ret; +} + static int iaa_remap_for_verify(struct device *dev, struct iaa_wq *iaa_wq, struct acomp_req *req, dma_addr_t *src_addr, dma_addr_t *dst_addr); @@ -1472,7 +1486,7 @@ static int iaa_comp_acompress(struct acomp_req *req) struct iaa_compression_ctx *compression_ctx; struct crypto_tfm *tfm = req->base.tfm; dma_addr_t src_addr, dst_addr; - int nr_sgs, cpu, ret = 0; + int cpu, ret = 0; struct iaa_wq *iaa_wq; struct idxd_wq *wq; struct device *dev; @@ -1484,11 +1498,15 @@ static int iaa_comp_acompress(struct acomp_req *req) return -ENODEV; } - if (!req->src || !req->slen) { - pr_debug("invalid src, not compressing\n"); + if (!req->src || !req->slen || !req->dst) { + pr_debug("invalid req, not compressing\n"); return -EINVAL; } + /* Fall back to software if src or dst has multiple sg entries */ + if (sg_nents(req->src) > 1 || sg_nents(req->dst) > 1) + return deflate_generic_compress(req); + cpu = get_cpu(); wq = wq_table_next_wq(cpu); put_cpu(); @@ -1507,30 +1525,25 @@ static int iaa_comp_acompress(struct acomp_req *req) dev = &wq->idxd->pdev->dev; - nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE); - if (nr_sgs <= 0 || nr_sgs > 1) { - dev_dbg(dev, "couldn't map src sg for iaa device %d," - " wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id, - iaa_wq->wq->id, ret); - ret = -EIO; - goto out; + if (!dma_map_sg(dev, req->src, 1, DMA_TO_DEVICE)) { + dev_dbg(dev, "couldn't map src sg for iaa device %d, wq %d\n", + iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id); + iaa_wq_put(wq); + return deflate_generic_compress(req); } src_addr = sg_dma_address(req->src); - dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p," - " req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs, + dev_dbg(dev, "map src %llx req->src %p slen %d sg_len %d\n", src_addr, req->src, req->slen, sg_dma_len(req->src)); - nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE); - if (nr_sgs <= 0 || nr_sgs > 1) { - dev_dbg(dev, "couldn't map dst sg for iaa device %d," - " wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id, - iaa_wq->wq->id, ret); - ret = -EIO; - goto err_map_dst; + if (!dma_map_sg(dev, req->dst, 1, DMA_FROM_DEVICE)) { + dev_dbg(dev, "couldn't map dst sg for iaa device %d, wq %d\n", + iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id); + dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE); + iaa_wq_put(wq); + return deflate_generic_compress(req); } dst_addr = sg_dma_address(req->dst); - dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p," - " req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs, + dev_dbg(dev, "map dst %llx req->dst %p dlen %d sg_len %d\n", dst_addr, req->dst, req->dlen, sg_dma_len(req->dst)); ret = iaa_compress(tfm, req, wq, src_addr, req->slen, dst_addr, @@ -1550,8 +1563,8 @@ static int iaa_comp_acompress(struct acomp_req *req) if (ret) dev_dbg(dev, "asynchronous compress verification failed ret=%d\n", ret); - dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_TO_DEVICE); - dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_FROM_DEVICE); + dma_unmap_sg(dev, req->dst, 1, DMA_TO_DEVICE); + dma_unmap_sg(dev, req->src, 1, DMA_FROM_DEVICE); goto out; } @@ -1559,9 +1572,8 @@ static int iaa_comp_acompress(struct acomp_req *req) if (ret) dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret); - dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE); -err_map_dst: - dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE); + dma_unmap_sg(dev, req->dst, 1, DMA_FROM_DEVICE); + dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE); out: iaa_wq_put(wq); @@ -1572,7 +1584,7 @@ static int iaa_comp_adecompress(struct acomp_req *req) { struct crypto_tfm *tfm = req->base.tfm; dma_addr_t src_addr, dst_addr; - int nr_sgs, cpu, ret = 0; + int cpu, ret = 0; struct iaa_wq *iaa_wq; struct device *dev; struct idxd_wq *wq; @@ -1582,11 +1594,15 @@ static int iaa_comp_adecompress(struct acomp_req *req) return -ENODEV; } - if (!req->src || !req->slen) { - pr_debug("invalid src, not decompressing\n"); + if (!req->src || !req->slen || !req->dst) { + pr_debug("invalid req, not decompressing\n"); return -EINVAL; } + /* Fall back to software if src or dst has multiple sg entries */ + if (sg_nents(req->src) > 1 || sg_nents(req->dst) > 1) + return deflate_generic_decompress(req); + cpu = get_cpu(); wq = wq_table_next_wq(cpu); put_cpu(); @@ -1605,30 +1621,25 @@ static int iaa_comp_adecompress(struct acomp_req *req) dev = &wq->idxd->pdev->dev; - nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE); - if (nr_sgs <= 0 || nr_sgs > 1) { - dev_dbg(dev, "couldn't map src sg for iaa device %d," - " wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id, - iaa_wq->wq->id, ret); - ret = -EIO; - goto out; + if (!dma_map_sg(dev, req->src, 1, DMA_TO_DEVICE)) { + dev_dbg(dev, "couldn't map src sg for iaa device %d, wq %d\n", + iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id); + iaa_wq_put(wq); + return deflate_generic_decompress(req); } src_addr = sg_dma_address(req->src); - dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p," - " req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs, + dev_dbg(dev, "map src %llx req->src %p slen %d sg_len %d\n", src_addr, req->src, req->slen, sg_dma_len(req->src)); - nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE); - if (nr_sgs <= 0 || nr_sgs > 1) { - dev_dbg(dev, "couldn't map dst sg for iaa device %d," - " wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id, - iaa_wq->wq->id, ret); - ret = -EIO; - goto err_map_dst; + if (!dma_map_sg(dev, req->dst, 1, DMA_FROM_DEVICE)) { + dev_dbg(dev, "couldn't map dst sg for iaa device %d, wq %d\n", + iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id); + dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE); + iaa_wq_put(wq); + return deflate_generic_decompress(req); } dst_addr = sg_dma_address(req->dst); - dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p," - " req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs, + dev_dbg(dev, "map dst %llx req->dst %p dlen %d sg_len %d\n", dst_addr, req->dst, req->dlen, sg_dma_len(req->dst)); ret = iaa_decompress(tfm, req, wq, src_addr, req->slen, @@ -1639,10 +1650,8 @@ static int iaa_comp_adecompress(struct acomp_req *req) if (ret != 0) dev_dbg(dev, "asynchronous decompress failed ret=%d\n", ret); - dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE); -err_map_dst: - dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE); -out: + dma_unmap_sg(dev, req->dst, 1, DMA_FROM_DEVICE); + dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE); iaa_wq_put(wq); return ret; diff --git a/drivers/crypto/intel/iaa/iaa_crypto_stats.c b/drivers/crypto/intel/iaa/iaa_crypto_stats.c index f5cc3d29ca19..2f2ed88c8812 100644 --- a/drivers/crypto/intel/iaa/iaa_crypto_stats.c +++ b/drivers/crypto/intel/iaa/iaa_crypto_stats.c @@ -19,6 +19,7 @@ static atomic64_t total_comp_calls; static atomic64_t total_decomp_calls; +static atomic64_t total_sw_comp_calls; static atomic64_t total_sw_decomp_calls; static atomic64_t total_comp_bytes_out; static atomic64_t total_decomp_bytes_in; @@ -43,6 +44,11 @@ void update_total_decomp_calls(void) atomic64_inc(&total_decomp_calls); } +void update_total_sw_comp_calls(void) +{ + atomic64_inc(&total_sw_comp_calls); +} + void update_total_sw_decomp_calls(void) { atomic64_inc(&total_sw_decomp_calls); @@ -104,6 +110,7 @@ static void reset_iaa_crypto_stats(void) { atomic64_set(&total_comp_calls, 0); atomic64_set(&total_decomp_calls, 0); + atomic64_set(&total_sw_comp_calls, 0); atomic64_set(&total_sw_decomp_calls, 0); atomic64_set(&total_comp_bytes_out, 0); atomic64_set(&total_decomp_bytes_in, 0); @@ -174,6 +181,8 @@ static int global_stats_show(struct seq_file *m, void *v) atomic64_read(&total_comp_calls)); seq_printf(m, " total_decomp_calls: %llu\n", atomic64_read(&total_decomp_calls)); + seq_printf(m, " total_sw_comp_calls: %llu\n", + atomic64_read(&total_sw_comp_calls)); seq_printf(m, " total_sw_decomp_calls: %llu\n", atomic64_read(&total_sw_decomp_calls)); seq_printf(m, " total_comp_bytes_out: %llu\n", diff --git a/drivers/crypto/intel/iaa/iaa_crypto_stats.h b/drivers/crypto/intel/iaa/iaa_crypto_stats.h index 3787a5f507eb..6e0c6f9939bf 100644 --- a/drivers/crypto/intel/iaa/iaa_crypto_stats.h +++ b/drivers/crypto/intel/iaa/iaa_crypto_stats.h @@ -11,6 +11,7 @@ void iaa_crypto_debugfs_cleanup(void); void update_total_comp_calls(void); void update_total_comp_bytes_out(int n); void update_total_decomp_calls(void); +void update_total_sw_comp_calls(void); void update_total_sw_decomp_calls(void); void update_total_decomp_bytes_in(int n); void update_completion_einval_errs(void); @@ -29,6 +30,7 @@ static inline void iaa_crypto_debugfs_cleanup(void) {} static inline void update_total_comp_calls(void) {} static inline void update_total_comp_bytes_out(int n) {} static inline void update_total_decomp_calls(void) {} +static inline void update_total_sw_comp_calls(void) {} static inline void update_total_sw_decomp_calls(void) {} static inline void update_total_decomp_bytes_in(int n) {} static inline void update_completion_einval_errs(void) {} From 659f52ff0ca6c5c927d06e5dad0b7f7082757ec8 Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Wed, 5 Aug 2026 14:19:24 -0700 Subject: [PATCH 114/122] crypto: iaa - avoid counting fallback decompression bytes When decompression falls back to deflate-generic after an analytics error, the request no longer completes through IAA. Move decompression byte accounting into the successful IAA completion path in both the synchronous and asynchronous flows so decomp_bytes only reflects bytes actually processed by IAA. Signed-off-by: Giovanni Cabiddu Signed-off-by: Vinicius Costa Gomes Reviewed-by: Dave Jiang Signed-off-by: Herbert Xu --- drivers/crypto/intel/iaa/iaa_crypto_main.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c index 904d9413ba18..9505ca23e6f3 100644 --- a/drivers/crypto/intel/iaa/iaa_crypto_main.c +++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c @@ -1071,15 +1071,17 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc, } } else { ctx->req->dlen = idxd_desc->iax_completion->output_size; + + if (!ctx->compress) { + update_total_decomp_bytes_in(ctx->req->slen); + update_wq_decomp_bytes(iaa_wq->wq, ctx->req->slen); + } } /* Update stats */ if (ctx->compress) { update_total_comp_bytes_out(ctx->req->dlen); update_wq_comp_bytes(iaa_wq->wq, ctx->req->dlen); - } else { - update_total_decomp_bytes_in(ctx->req->slen); - update_wq_decomp_bytes(iaa_wq->wq, ctx->req->slen); } if (ctx->compress && compression_ctx->verify_compress) { @@ -1462,16 +1464,16 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req, } } else { req->dlen = idxd_desc->iax_completion->output_size; + + /* Update stats */ + update_total_decomp_bytes_in(slen); + update_wq_decomp_bytes(wq, slen); } *dlen = req->dlen; if (!ctx->async_mode) idxd_free_desc(wq, idxd_desc); - - /* Update stats */ - update_total_decomp_bytes_in(slen); - update_wq_decomp_bytes(wq, slen); out: return ret; err: From a229e50741de3d78d7acdd952b70509ab971215d Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Wed, 5 Aug 2026 14:19:25 -0700 Subject: [PATCH 115/122] crypto: iaa - use bounce buffer for multi-sg decompress input Since commit e2c3b6b21c77 ("mm: zswap: use SG list decompression APIs from zsmalloc"), zswap passes the raw zsmalloc SG list directly to crypto drivers, so a compressed object spanning multiple pages reaches IAA as a multi-entry source. Such requests currently fall back to software decompression. As IAA hardware requires a single DMA source buffer, linearize small multi-entry sources into a pre-allocated bounce page and submit that to the hardware instead of falling back to software. Keep the software fallback only for multi-entry destinations. This recovers most of the performance lost by using the software fallback. Store the bounce-page state in the acomp request context alongside the existing compression CRC, free it through a shared source-unmap helper, and back the pages with a small module-wide mempool so the path remains available in reclaim-driven callers. Signed-off-by: Giovanni Cabiddu Signed-off-by: Vinicius Costa Gomes Signed-off-by: Herbert Xu --- drivers/crypto/intel/iaa/iaa_crypto_main.c | 128 +++++++++++++++++---- 1 file changed, 106 insertions(+), 22 deletions(-) diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c index 9505ca23e6f3..51547c5fcf70 100644 --- a/drivers/crypto/intel/iaa/iaa_crypto_main.c +++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -157,6 +158,16 @@ static bool async_mode; /* Use interrupts */ static bool use_irq; +struct iaa_req_ctx { + u32 compression_crc; + struct page *bounce_src; + dma_addr_t bounce_src_dma; + unsigned int bounce_src_len; +}; + +static mempool_t *iaa_bounce_pool; +#define IAA_BOUNCE_POOL_SIZE 128 + /** * set_iaa_sync_mode - Set IAA sync mode * @name: The name of the sync mode @@ -984,6 +995,23 @@ static inline int check_completion(struct device *dev, return ret; } +static void iaa_unmap_src(struct device *dev, struct acomp_req *req) +{ + struct iaa_req_ctx *req_ctx = acomp_request_ctx(req); + + if (req_ctx->bounce_src) { + dma_unmap_page(dev, req_ctx->bounce_src_dma, + req_ctx->bounce_src_len, DMA_TO_DEVICE); + mempool_free(req_ctx->bounce_src, iaa_bounce_pool); + req_ctx->bounce_src = NULL; + req_ctx->bounce_src_dma = 0; + req_ctx->bounce_src_len = 0; + return; + } + + dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE); +} + static int deflate_generic_decompress(struct acomp_req *req) { ACOMP_FBREQ_ON_STACK(fbreq, req); @@ -1027,6 +1055,7 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc, struct iaa_device_compression_mode *active_compression_mode; struct iaa_compression_ctx *compression_ctx; struct crypto_ctx *ctx = __ctx; + struct iaa_req_ctx *req_ctx = acomp_request_ctx(ctx->req); struct iaa_device *iaa_device; struct idxd_device *idxd; struct iaa_wq *iaa_wq; @@ -1085,10 +1114,9 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc, } if (ctx->compress && compression_ctx->verify_compress) { - u32 *compression_crc = acomp_request_ctx(ctx->req); dma_addr_t src_addr, dst_addr; - *compression_crc = idxd_desc->iax_completion->crc; + req_ctx->compression_crc = idxd_desc->iax_completion->crc; ret = iaa_remap_for_verify(dev, iaa_wq, ctx->req, &src_addr, &dst_addr); if (ret) { @@ -1111,7 +1139,7 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc, } err: dma_unmap_sg(dev, ctx->req->dst, sg_nents(ctx->req->dst), DMA_FROM_DEVICE); - dma_unmap_sg(dev, ctx->req->src, sg_nents(ctx->req->src), DMA_TO_DEVICE); + iaa_unmap_src(dev, ctx->req); out: if (ret != 0) dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret); @@ -1131,7 +1159,7 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req, { struct iaa_device_compression_mode *active_compression_mode; struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm); - u32 *compression_crc = acomp_request_ctx(req); + struct iaa_req_ctx *req_ctx = acomp_request_ctx(req); struct iaa_device *iaa_device; struct idxd_desc *idxd_desc; struct iax_hw_desc *desc; @@ -1222,7 +1250,7 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req, update_total_comp_bytes_out(*dlen); update_wq_comp_bytes(wq, *dlen); - *compression_crc = idxd_desc->iax_completion->crc; + req_ctx->compression_crc = idxd_desc->iax_completion->crc; if (!ctx->async_mode) idxd_free_desc(wq, idxd_desc); @@ -1282,7 +1310,7 @@ static int iaa_compress_verify(struct crypto_tfm *tfm, struct acomp_req *req, { struct iaa_device_compression_mode *active_compression_mode; struct iaa_compression_ctx *ctx = crypto_tfm_ctx(tfm); - u32 *compression_crc = acomp_request_ctx(req); + struct iaa_req_ctx *req_ctx = acomp_request_ctx(req); struct iaa_device *iaa_device; struct idxd_desc *idxd_desc; struct iax_hw_desc *desc; @@ -1342,10 +1370,10 @@ static int iaa_compress_verify(struct crypto_tfm *tfm, struct acomp_req *req, goto err; } - if (*compression_crc != idxd_desc->iax_completion->crc) { + if (req_ctx->compression_crc != idxd_desc->iax_completion->crc) { ret = -EINVAL; - dev_dbg(dev, "(verify) iaa comp/decomp crc mismatch:" - " comp=0x%x, decomp=0x%x\n", *compression_crc, + dev_dbg(dev, "(verify) iaa comp/decomp crc mismatch: comp=0x%x, decomp=0x%x\n", + req_ctx->compression_crc, idxd_desc->iax_completion->crc); print_hex_dump(KERN_INFO, "cmp-rec: ", DUMP_PREFIX_OFFSET, 8, 1, idxd_desc->iax_completion, 64, 0); @@ -1485,6 +1513,7 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req, static int iaa_comp_acompress(struct acomp_req *req) { + struct iaa_req_ctx *req_ctx = acomp_request_ctx(req); struct iaa_compression_ctx *compression_ctx; struct crypto_tfm *tfm = req->base.tfm; dma_addr_t src_addr, dst_addr; @@ -1493,6 +1522,10 @@ static int iaa_comp_acompress(struct acomp_req *req) struct idxd_wq *wq; struct device *dev; + req_ctx->bounce_src = NULL; + req_ctx->bounce_src_dma = 0; + req_ctx->bounce_src_len = 0; + compression_ctx = crypto_tfm_ctx(tfm); if (!iaa_crypto_enabled) { @@ -1584,12 +1617,19 @@ static int iaa_comp_acompress(struct acomp_req *req) static int iaa_comp_adecompress(struct acomp_req *req) { + struct iaa_req_ctx *req_ctx = acomp_request_ctx(req); struct crypto_tfm *tfm = req->base.tfm; dma_addr_t src_addr, dst_addr; + bool use_bounce_src = false; int cpu, ret = 0; struct iaa_wq *iaa_wq; struct device *dev; struct idxd_wq *wq; + struct page *page; + + req_ctx->bounce_src = NULL; + req_ctx->bounce_src_dma = 0; + req_ctx->bounce_src_len = 0; if (!iaa_crypto_enabled) { pr_debug("iaa_crypto disabled, not decompressing\n"); @@ -1601,10 +1641,16 @@ static int iaa_comp_adecompress(struct acomp_req *req) return -EINVAL; } - /* Fall back to software if src or dst has multiple sg entries */ - if (sg_nents(req->src) > 1 || sg_nents(req->dst) > 1) + /* Fall back to software if dst has multiple sg entries */ + if (sg_nents(req->dst) > 1) return deflate_generic_decompress(req); + if (sg_nents(req->src) > 1) { + if (req->slen > PAGE_SIZE) + return deflate_generic_decompress(req); + use_bounce_src = true; + } + cpu = get_cpu(); wq = wq_table_next_wq(cpu); put_cpu(); @@ -1623,20 +1669,47 @@ static int iaa_comp_adecompress(struct acomp_req *req) dev = &wq->idxd->pdev->dev; - if (!dma_map_sg(dev, req->src, 1, DMA_TO_DEVICE)) { - dev_dbg(dev, "couldn't map src sg for iaa device %d, wq %d\n", - iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id); - iaa_wq_put(wq); - return deflate_generic_decompress(req); + if (unlikely(use_bounce_src)) { + page = mempool_alloc(iaa_bounce_pool, GFP_ATOMIC); + if (!page) { + iaa_wq_put(wq); + return deflate_generic_decompress(req); + } + + if (sg_copy_to_buffer(req->src, sg_nents(req->src), + page_address(page), req->slen) != req->slen) { + mempool_free(page, iaa_bounce_pool); + iaa_wq_put(wq); + return deflate_generic_decompress(req); + } + + src_addr = dma_map_page(dev, page, 0, req->slen, DMA_TO_DEVICE); + if (dma_mapping_error(dev, src_addr)) { + mempool_free(page, iaa_bounce_pool); + iaa_wq_put(wq); + return deflate_generic_decompress(req); + } + + req_ctx->bounce_src = page; + req_ctx->bounce_src_dma = src_addr; + req_ctx->bounce_src_len = req->slen; + } else { + if (!dma_map_sg(dev, req->src, 1, DMA_TO_DEVICE)) { + dev_dbg(dev, "couldn't map src sg for iaa device %d, wq %d\n", + iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id); + iaa_wq_put(wq); + return deflate_generic_decompress(req); + } + + src_addr = sg_dma_address(req->src); + dev_dbg(dev, "map src %llx req->src %p slen %d sg_len %d\n", src_addr, + req->src, req->slen, sg_dma_len(req->src)); } - src_addr = sg_dma_address(req->src); - dev_dbg(dev, "map src %llx req->src %p slen %d sg_len %d\n", src_addr, - req->src, req->slen, sg_dma_len(req->src)); if (!dma_map_sg(dev, req->dst, 1, DMA_FROM_DEVICE)) { dev_dbg(dev, "couldn't map dst sg for iaa device %d, wq %d\n", iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id); - dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE); + iaa_unmap_src(dev, req); iaa_wq_put(wq); return deflate_generic_decompress(req); } @@ -1653,7 +1726,7 @@ static int iaa_comp_adecompress(struct acomp_req *req) dev_dbg(dev, "asynchronous decompress failed ret=%d\n", ret); dma_unmap_sg(dev, req->dst, 1, DMA_FROM_DEVICE); - dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE); + iaa_unmap_src(dev, req); iaa_wq_put(wq); return ret; @@ -1687,7 +1760,7 @@ static struct acomp_alg iaa_acomp_fixed_deflate = { .cra_driver_name = "deflate-iaa", .cra_flags = CRYPTO_ALG_ASYNC, .cra_ctxsize = sizeof(struct iaa_compression_ctx), - .cra_reqsize = sizeof(u32), + .cra_reqsize = sizeof(struct iaa_req_ctx), .cra_module = THIS_MODULE, .cra_priority = IAA_ALG_PRIORITY, } @@ -1886,6 +1959,12 @@ static int __init iaa_crypto_init_module(void) goto err_aecs_init; } + iaa_bounce_pool = mempool_create_page_pool(IAA_BOUNCE_POOL_SIZE, 0); + if (!iaa_bounce_pool) { + ret = -ENOMEM; + goto err_bounce_pool; + } + ret = idxd_driver_register(&iaa_crypto_driver); if (ret) { pr_debug("IAA wq sub-driver registration failed\n"); @@ -1919,6 +1998,9 @@ static int __init iaa_crypto_init_module(void) err_verify_attr_create: idxd_driver_unregister(&iaa_crypto_driver); err_driver_reg: + mempool_destroy(iaa_bounce_pool); + iaa_bounce_pool = NULL; +err_bounce_pool: iaa_aecs_cleanup_fixed(); err_aecs_init: @@ -1935,6 +2017,8 @@ static void __exit iaa_crypto_cleanup_module(void) driver_remove_file(&iaa_crypto_driver.drv, &driver_attr_verify_compress); idxd_driver_unregister(&iaa_crypto_driver); + mempool_destroy(iaa_bounce_pool); + iaa_bounce_pool = NULL; iaa_aecs_cleanup_fixed(); pr_debug("cleaned up\n"); From 94a25930477113730372e0fa2985da4c5ac95c9a Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Wed, 5 Aug 2026 14:19:26 -0700 Subject: [PATCH 116/122] crypto: iaa - unmap dst before software fallback on decompress On a hardware analytics error, decompress retries through the software fallback, which writes req->dst with the CPU while it is still mapped DMA_FROM_DEVICE. With SWIOTLB active the later dma_unmap_sg() copies the stale bounce buffer over req->dst, corrupting the result. Unmap before the fallback runs. The async path unmaps inline; the sync path signals the retry with -EAGAIN so iaa_comp_adecompress() runs the fallback after unmapping. Fixes: 2ec6761df889 ("crypto: iaa - Add support for deflate-iaa compression algorithm") Cc: stable@vger.kernel.org Signed-off-by: Vinicius Costa Gomes Signed-off-by: Herbert Xu --- drivers/crypto/intel/iaa/iaa_crypto_main.c | 35 +++++++++++----------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c index 51547c5fcf70..c9ab4b83ae02 100644 --- a/drivers/crypto/intel/iaa/iaa_crypto_main.c +++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c @@ -995,6 +995,11 @@ static inline int check_completion(struct device *dev, return ret; } +static bool iaa_error_should_retry(struct idxd_desc *idxd_desc) +{ + return idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR; +} + static void iaa_unmap_src(struct device *dev, struct acomp_req *req) { struct iaa_req_ctx *req_ctx = acomp_request_ctx(req); @@ -1082,18 +1087,21 @@ static void iaa_desc_complete(struct idxd_desc *idxd_desc, ctx->compress, false); if (ret) { dev_dbg(dev, "%s: check_completion failed ret=%d\n", __func__, ret); - if (!ctx->compress && - idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR) { + if (!ctx->compress && iaa_error_should_retry(idxd_desc)) { pr_warn("%s: falling back to deflate-generic decompress, " "analytics error code %x\n", __func__, idxd_desc->iax_completion->error_code); + dma_unmap_sg(dev, ctx->req->dst, sg_nents(ctx->req->dst), + DMA_FROM_DEVICE); + iaa_unmap_src(dev, ctx->req); + ret = deflate_generic_decompress(ctx->req); if (ret) { dev_dbg(dev, "%s: deflate-generic failed ret=%d\n", __func__, ret); err = -EIO; - goto err; } + goto out; } else { err = -EIO; goto err; @@ -1477,19 +1485,9 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req, ret = check_completion(dev, idxd_desc->iax_completion, false, false); if (ret) { dev_dbg(dev, "%s: check_completion failed ret=%d\n", __func__, ret); - if (idxd_desc->iax_completion->status == IAA_ANALYTICS_ERROR) { - pr_warn("%s: falling back to deflate-generic decompress, " - "analytics error code %x\n", __func__, - idxd_desc->iax_completion->error_code); - ret = deflate_generic_decompress(req); - if (ret) { - dev_dbg(dev, "%s: deflate-generic failed ret=%d\n", - __func__, ret); - goto err; - } - } else { - goto err; - } + if (iaa_error_should_retry(idxd_desc)) + ret = -EAGAIN; + goto err; } else { req->dlen = idxd_desc->iax_completion->output_size; @@ -1722,13 +1720,16 @@ static int iaa_comp_adecompress(struct acomp_req *req) if (ret == -EINPROGRESS) return ret; - if (ret != 0) + if (ret != 0 && ret != -EAGAIN) dev_dbg(dev, "asynchronous decompress failed ret=%d\n", ret); dma_unmap_sg(dev, req->dst, 1, DMA_FROM_DEVICE); iaa_unmap_src(dev, req); iaa_wq_put(wq); + if (ret == -EAGAIN) + ret = deflate_generic_decompress(req); + return ret; } From 7f2345f47dd189625f657cd72437179ab4170ee1 Mon Sep 17 00:00:00 2001 From: Md Sadre Alam Date: Fri, 7 Aug 2026 12:24:54 +0530 Subject: [PATCH 117/122] crypto: qce - fix CCM AAD buffer underallocation The AAD buffer allocated in qce_aead_ccm_prepare_buf_assoclen() can be smaller than the length later programmed into the DMA scatterlist. The allocation size is currently calculated as: ALIGN(assoclen, 16) + MAX_CCM_ADATA_HEADER_LEN while the DMA length is set to: ALIGN(assoclen + adata_header_len, 16) Since ALIGN() does not distribute over addition, the allocation can be smaller than the DMA length. For example, when assoclen = 32 and adata_header_len = 2: allocation = ALIGN(32, 16) + 6 = 38 DMA length = ALIGN(32 + 2, 16) = 48 As a result, the QCE hardware can read beyond the allocated buffer while computing the CBC-MAC over the associated data. The extra bytes are folded into the authentication tag, resulting in an incorrect tag and causing CCM self-test failures such as: alg: aead: ccm-aes-qce encryption test failed (wrong result) on test vector 8 Fix the allocation by adding the maximum possible AAD header length before alignment: ALIGN(assoclen + MAX_CCM_ADATA_HEADER_LEN, 16) This guarantees that the allocated buffer is large enough for the fully padded AAD data for all supported header sizes. Cc: stable@vger.kernel.org Fixes: 9363efb4181c ("crypto: qce - Add support for AEAD algorithms") Signed-off-by: Md Sadre Alam Reviewed-by: Bartosz Golaszewski Signed-off-by: Herbert Xu --- drivers/crypto/qce/aead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 92d84941d3db..a9642c67f476 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -196,7 +196,7 @@ qce_aead_ccm_prepare_buf_assoclen(struct aead_request *req) /* Get the msg */ msg_sg = scatterwalk_ffwd(__sg, req->src, req->assoclen); - rctx->adata = kzalloc((ALIGN(assoclen, 16) + MAX_CCM_ADATA_HEADER_LEN) * + rctx->adata = kzalloc(ALIGN(assoclen + MAX_CCM_ADATA_HEADER_LEN, 16) * sizeof(unsigned char), GFP_ATOMIC); if (!rctx->adata) return -ENOMEM; From 528bc53c3bfa1c745f0f7510dd56bb63be1dd5d1 Mon Sep 17 00:00:00 2001 From: "Pawel Zalewski (The Capable Hub)" Date: Fri, 7 Aug 2026 12:26:09 +0100 Subject: [PATCH 118/122] hwrng: drivers - use named initializers for acpi_device_id Use a named initializer for the acpi_device_id fields which makes the code more readable and consistent with how lists are initialized in the rest of the kernel code base. Also drop explicitly setting fields to 0 where it is redundant. Signed-off-by: Pawel Zalewski (The Capable Hub) Signed-off-by: Herbert Xu --- drivers/char/hw_random/hisi-trng-v2.c | 2 +- drivers/char/hw_random/xgene-rng.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/hw_random/hisi-trng-v2.c b/drivers/char/hw_random/hisi-trng-v2.c index 6584ed051e09..9e0ecea56ad6 100644 --- a/drivers/char/hw_random/hisi-trng-v2.c +++ b/drivers/char/hw_random/hisi-trng-v2.c @@ -77,7 +77,7 @@ static int hisi_trng_probe(struct platform_device *pdev) } static const struct acpi_device_id hisi_trng_acpi_match[] = { - { "HISI02B3", 0 }, + { .id = "HISI02B3" }, { } }; MODULE_DEVICE_TABLE(acpi, hisi_trng_acpi_match); diff --git a/drivers/char/hw_random/xgene-rng.c b/drivers/char/hw_random/xgene-rng.c index 97e505c2fcd1..33708dfa21e2 100644 --- a/drivers/char/hw_random/xgene-rng.c +++ b/drivers/char/hw_random/xgene-rng.c @@ -297,7 +297,7 @@ static int xgene_rng_init(struct hwrng *rng) #ifdef CONFIG_ACPI static const struct acpi_device_id xgene_rng_acpi_match[] = { - { "APMC0D18", }, + { .id = "APMC0D18" }, { } }; MODULE_DEVICE_TABLE(acpi, xgene_rng_acpi_match); From 7064af16d2b418d61571dba9bb0116a547ade124 Mon Sep 17 00:00:00 2001 From: "David C.C.M. Gall" Date: Fri, 7 Aug 2026 17:44:16 +0200 Subject: [PATCH 119/122] crypto: sa2ul - use crypto_memneq() to compare AEAD tag Use crypto_memneq() for a constant-time comparison. sa_aead_dma_in_callback() compares the computed authentication tag against the received tag with memcmp(), which short-circuits on the first differing byte. An attacker who can submit decrypt requests and observe completion latency could recover the expected tag byte by byte. Valid tag forgery for AEAD breaks the INT-CTXT guarantee. Assisted-by: gregkh_clanker_t1000 Signed-off-by: David C.C.M. Gall Signed-off-by: Herbert Xu --- drivers/crypto/sa2ul.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c index d865fd4a098c..9846cbeb3449 100644 --- a/drivers/crypto/sa2ul.c +++ b/drivers/crypto/sa2ul.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -1688,7 +1689,7 @@ static void sa_aead_dma_in_callback(void *data) scatterwalk_map_and_copy(auth_tag, req->src, start, authsize, 0); - err = memcmp(&mdptr[4], auth_tag, authsize) ? -EBADMSG : 0; + err = crypto_memneq(&mdptr[4], auth_tag, authsize) ? -EBADMSG : 0; } sa_free_sa_rx_data(rxd); From 353b3a85136f2a0cf3e872acf8ad6c1dec0b7a8e Mon Sep 17 00:00:00 2001 From: "David C.C.M. Gall" Date: Fri, 7 Aug 2026 18:13:52 +0200 Subject: [PATCH 120/122] crypto: keembay - use crypto_memneq() to compare GCM AEAD tags Use crypto_memneq() for constant-time comparison. The GCM path in keembay-ocs-aes-core.c verifes the received authentication tag with memcmp(), which returns early on the first mismatched byte. This leaks valid-prefix length and allows for valid tag forgery which violates the INT-CTXT guarantee of AEAD. Assisted-by: gregkh_clanker_t1000 Signed-off-by: David C.C.M. Gall Signed-off-by: Herbert Xu --- drivers/crypto/intel/keembay/keembay-ocs-aes-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c index cc22561c30fe..660830c36e14 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -919,7 +920,7 @@ static int kmb_ocs_aead_run(struct aead_request *req) /* For GCM decrypt, we have to compare in_tag with out_tag. */ if (rctx->instruction == OCS_DECRYPT) { - rc = memcmp(rctx->in_tag, rctx->out_tag, tag_size) ? + rc = crypto_memneq(rctx->in_tag, rctx->out_tag, tag_size) ? -EBADMSG : 0; goto exit; } From ff2ac77a034e03b64e2ba34f775097427dfa5547 Mon Sep 17 00:00:00 2001 From: "David C.C.M. Gall" Date: Fri, 7 Aug 2026 18:22:00 +0200 Subject: [PATCH 121/122] crypto: keembay - use crypto_memneq() to compare CCM AEAD tags Use crypto_memneq() for constant-time comparison. The CCM path in ocs-aes.c verifes the received authentication tag with memcmp(), which returns early on the first mismatched byte. This leaks valid-prefix length and allows for valid tag forgery which violates the INT-CTXT guarantee of AEAD. Assisted-by: gregkh_clanker_t1000 Signed-off-by: David C.C.M. Gall Signed-off-by: Herbert Xu --- drivers/crypto/intel/keembay/ocs-aes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/intel/keembay/ocs-aes.c b/drivers/crypto/intel/keembay/ocs-aes.c index bb6f33f6b4d3..13ba7573617f 100644 --- a/drivers/crypto/intel/keembay/ocs-aes.c +++ b/drivers/crypto/intel/keembay/ocs-aes.c @@ -17,6 +17,7 @@ #include #include +#include #include "ocs-aes.h" @@ -1283,7 +1284,7 @@ static inline int ccm_compare_tag_to_yr(struct ocs_aes_dev *aes_dev, (i * sizeof(u32))); } - return memcmp(tag, yr, tag_size_bytes) ? -EBADMSG : 0; + return crypto_memneq(tag, yr, tag_size_bytes) ? -EBADMSG : 0; } /** From 7537036a2e6fe96f8ed82034f755c54714a0e417 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 8 Aug 2026 13:48:48 +0200 Subject: [PATCH 122/122] crypto: lskcipher - propagate errors from unaligned crypt The while loop declares a second err variable that shadows the outer one. When the crypt callback fails, the goto out path returns the outer err, which still holds the -ENOMEM value assigned before the successful allocation check. The real error from the cipher is discarded and the caller sees -ENOMEM instead. Drop the inner declaration so the callback error reaches the caller. Verified with a test module that registers an lskcipher whose encrypt callback fails with -EIO and calls it through a misaligned buffer. An unpatched kernel returns -ENOMEM, a patched kernel returns -EIO. Found with Clang's -Wshadow. Fixes: 31865c4c4db2b ("crypto: skcipher - Add lskcipher") Assisted-by: Claude:claude-fable-5 Signed-off-by: Karl Mehltretter Signed-off-by: Herbert Xu --- crypto/lskcipher.c | 1 - 1 file changed, 1 deletion(-) diff --git a/crypto/lskcipher.c b/crypto/lskcipher.c index d7ec215e2b3a..a8b07594005d 100644 --- a/crypto/lskcipher.c +++ b/crypto/lskcipher.c @@ -95,7 +95,6 @@ static int crypto_lskcipher_crypt_unaligned( while (len >= bs) { unsigned chunk = min((unsigned)PAGE_SIZE, len); - int err; if (chunk > cs) chunk &= ~(cs - 1);