From 8b74759f496599820264c6705cfa0b56536b52d7 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:29:56 +0200 Subject: [PATCH 001/146] crypto: Provide a wrapper function for zeroizing crypto_aes_ctx Several crypto drivers need to zeroize their local crypto_aes_ctx structures after use to avoid leaking key material on the stack. Currently some call sites do this with their own memzero_explicit() call, which is error-prone since it is easy to miss a return path (what already happened in some drivers). Some other call sites miss to clear crypto_aes_ctx completely. Provide an aes_zeroize_ctx() helper that can be used with __cleanup() to automatically zeroize the context when it goes out of scope. Acked-by: Eric Biggers Signed-off-by: Thomas Huth Signed-off-by: Herbert Xu --- include/crypto/aes.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 3279cfa54608..e70607249ae5 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -159,6 +159,19 @@ static inline int aes_check_keylen(size_t keylen) int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, unsigned int key_len); +/** + * aes_zeroize_ctx - Clear a crypto_aes_ctx structure + * @ctx: The location of the context that should be zeroized + * + * Explicitly fills the crypto_aes_ctx with zeroes. This should be done + * once the context is not required anymore to avoid that its contents + * are leaked on the stack or heap (if not using kfree_sensitive()). + */ +static inline void aes_zeroize_ctx(struct crypto_aes_ctx *ctx) +{ + memzero_explicit(ctx, sizeof(*ctx)); +} + /* * The following functions are temporarily exported for use by the AES mode * implementations in arch/$(SRCARCH)/crypto/. These exports will go away when From 26b845b7e190a6a996f86c7b221cbcbd651a2f2b Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:29:57 +0200 Subject: [PATCH 002/146] crypto: aspeed - clear the crypto_aes_ctx when done Declare the gen_aes_key with __cleanup(aes_zeroize_ctx) to avoid that its contents could be leaking via the stack when the function returns. And since it is only required in one branch of the if-statement there, move it to that block, too. Signed-off-by: Thomas Huth Signed-off-by: Herbert Xu --- drivers/crypto/aspeed/aspeed-hace-crypto.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/aspeed/aspeed-hace-crypto.c b/drivers/crypto/aspeed/aspeed-hace-crypto.c index fa201dae1f81..e7d3f611df05 100644 --- a/drivers/crypto/aspeed/aspeed-hace-crypto.c +++ b/drivers/crypto/aspeed/aspeed-hace-crypto.c @@ -576,7 +576,6 @@ static int aspeed_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, { struct aspeed_cipher_ctx *ctx = crypto_skcipher_ctx(cipher); struct aspeed_hace_dev *hace_dev = ctx->hace_dev; - struct crypto_aes_ctx gen_aes_key; CIPHER_DBG(hace_dev, "keylen: %d bits\n", (keylen * 8)); @@ -585,9 +584,9 @@ static int aspeed_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, return -EINVAL; if (ctx->hace_dev->version == AST2500_VERSION) { + struct crypto_aes_ctx gen_aes_key __cleanup(aes_zeroize_ctx); aes_expandkey(&gen_aes_key, key, keylen); memcpy(ctx->key, gen_aes_key.key_enc, AES_MAX_KEYLENGTH); - } else { memcpy(ctx->key, key, keylen); } From cafba3d6787a6ce847045edfd5a6fedd388943e4 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:29:58 +0200 Subject: [PATCH 003/146] crypto: padlock-aes - clear the crypto_aes_ctx when done Clear the crypto_aes_ctx structure via __cleanup(aes_zeroize_ctx) when we're done with it to avoid that key data could leak on the stack. And since __cleanup() (and __free()) should not be mixed with "gotos" in the same function, turn the goto statement here into a proper block of the related if-statement. Signed-off-by: Thomas Huth Signed-off-by: Herbert Xu --- drivers/crypto/padlock-aes.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 1be549a07a21..400a889e924d 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -109,7 +109,7 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, { struct aes_ctx *ctx = aes_ctx(tfm); const __le32 *key = (const __le32 *)in_key; - struct crypto_aes_ctx gen_aes; + struct crypto_aes_ctx gen_aes __cleanup(aes_zeroize_ctx); int cpu; if (key_len % 8) @@ -137,20 +137,18 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, ctx->cword.decrypt.ksize = ctx->cword.encrypt.ksize; /* Don't generate extended keys if the hardware can do it. */ - if (aes_hw_extkey_available(key_len)) - goto ok; + if (!aes_hw_extkey_available(key_len)) { + ctx->D = ctx->d_data; + ctx->cword.encrypt.keygen = 1; + ctx->cword.decrypt.keygen = 1; - ctx->D = ctx->d_data; - ctx->cword.encrypt.keygen = 1; - ctx->cword.decrypt.keygen = 1; + if (aes_expandkey(&gen_aes, in_key, key_len)) + return -EINVAL; - if (aes_expandkey(&gen_aes, in_key, key_len)) - return -EINVAL; + memcpy(ctx->E, gen_aes.key_enc, AES_MAX_KEYLENGTH); + memcpy(ctx->D, gen_aes.key_dec, AES_MAX_KEYLENGTH); + } - memcpy(ctx->E, gen_aes.key_enc, AES_MAX_KEYLENGTH); - memcpy(ctx->D, gen_aes.key_dec, AES_MAX_KEYLENGTH); - -ok: for_each_online_cpu(cpu) if (&ctx->cword.encrypt == per_cpu(paes_last_cword, cpu) || &ctx->cword.decrypt == per_cpu(paes_last_cword, cpu)) From 846b7a178608165c606a58d5333d9d373e574787 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:29:59 +0200 Subject: [PATCH 004/146] crypto: sa2ul - clear the crypto_aes_ctx when done Clear the crypto_aes_ctx structure via __cleanup(aes_zeroize_ctx) when we're done with it to avoid that key data could leak on the stack. Signed-off-by: Thomas Huth Signed-off-by: Herbert Xu --- drivers/crypto/sa2ul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c index 9846cbeb3449..0dce2b98886a 100644 --- a/drivers/crypto/sa2ul.c +++ b/drivers/crypto/sa2ul.c @@ -466,7 +466,7 @@ static void sa_prepare_iopads(struct algo_data *data, const u8 *key, /* Derive the inverse key used in AES-CBC decryption operation */ static inline int sa_aes_inv_key(u8 *inv_key, const u8 *key, u16 key_sz) { - struct crypto_aes_ctx ctx; + struct crypto_aes_ctx ctx __cleanup(aes_zeroize_ctx); int key_pos; if (aes_expandkey(&ctx, key, key_sz)) { From b77228e9463a19437b5be2049ba4ead922713c05 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:30:00 +0200 Subject: [PATCH 005/146] crypto: arm/aes-neonbs - clear the crypto_aes_ctx when done Clear the crypto_aes_ctx structure via __cleanup(aes_zeroize_ctx) when we're done with it to avoid that key data could leak on the stack. Signed-off-by: Thomas Huth Signed-off-by: Herbert Xu --- arch/arm/crypto/aes-neonbs-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c index c49ddafc54f3..f0c8bfd2ac8f 100644 --- a/arch/arm/crypto/aes-neonbs-glue.c +++ b/arch/arm/crypto/aes-neonbs-glue.c @@ -60,7 +60,7 @@ static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { struct aesbs_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_aes_ctx rk; + struct crypto_aes_ctx rk __cleanup(aes_zeroize_ctx); int err; err = aes_expandkey(&rk, in_key, key_len); From 52a78e326369de366153f07e2304a6aec888f452 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:30:01 +0200 Subject: [PATCH 006/146] crypto: arm64/aes-neonbs - clear the crypto_aes_ctx when done Clear the crypto_aes_ctx structure via __cleanup(aes_zeroize_ctx) when we're done with it to avoid that key data could leak on the stack. Signed-off-by: Thomas Huth Signed-off-by: Herbert Xu --- arch/arm64/crypto/aes-neonbs-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/crypto/aes-neonbs-glue.c b/arch/arm64/crypto/aes-neonbs-glue.c index 5bcbac979893..c2f3eac0ca66 100644 --- a/arch/arm64/crypto/aes-neonbs-glue.c +++ b/arch/arm64/crypto/aes-neonbs-glue.c @@ -247,7 +247,7 @@ static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_aes_ctx rk; + struct crypto_aes_ctx rk __cleanup(aes_zeroize_ctx); int err; err = xts_verify_key(tfm, in_key, key_len); From 8f2b1310ac4531f8c10e0c9b8c435ae7ac57a77a Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:30:02 +0200 Subject: [PATCH 007/146] crypto: qat - zeroize crypto_aes_ctx with __cleanup(aes_zeroize_ctx) A recent patch by Giovanni Cabiddu already added a memzero_explicit() for the crypto_aes_ctx in the qat_alg_xts_reverse_key() function, but since we introduced __cleanup(aes_zeroize_ctx) markers in previous commits in many spots of the code already, let's use it here now, too, to have the same code pattern everywhere. Signed-off-by: Thomas Huth Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/qat_algs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/qat_algs.c b/drivers/crypto/intel/qat/qat_common/qat_algs.c index 91663805d9e6..cb669fb66162 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_algs.c @@ -388,7 +388,7 @@ static void qat_alg_skcipher_init_enc(struct qat_alg_skcipher_ctx *ctx, static void qat_alg_xts_reverse_key(const u8 *key_forward, unsigned int keylen, u8 *key_reverse) { - struct crypto_aes_ctx aes_expanded; + struct crypto_aes_ctx aes_expanded __cleanup(aes_zeroize_ctx); int nrounds; u8 *key; @@ -405,7 +405,6 @@ 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 41d39d6f2b1b95c0887345a928b2a53f4f660db6 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:30:03 +0200 Subject: [PATCH 008/146] crypto: safexcel - Simplify the check for a valid AES key safexcel_aead_setkey() currently uses aes_expandkey() to check for a valid AES key, but then does not use the crypto_aes_ctx afterwards anymore, i.e. this is just a wasteful way of checking the key length, and thus aes_check_keylen() should be used instead. This also fixes a potential leak of sensitive data via the stack, since this function forgot to zeroize crypto_aes_ctx before returning to the caller. Suggested-by: Antoine Tenart Signed-off-by: Thomas Huth Acked-by: Antoine Tenart Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel_cipher.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index a8349b684693..f07d043c67d4 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -407,7 +407,6 @@ static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key, struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct safexcel_crypto_priv *priv = ctx->base.priv; struct crypto_authenc_keys keys; - struct crypto_aes_ctx aes; int err = -EINVAL, i; const char *alg; @@ -438,7 +437,7 @@ static int safexcel_aead_setkey(struct crypto_aead *ctfm, const u8 *key, goto badkey; break; case SAFEXCEL_AES: - err = aes_expandkey(&aes, keys.enckey, keys.enckeylen); + err = aes_check_keylen(keys.enckeylen); if (unlikely(err)) goto badkey; break; From 001c53ae358ba864b1ce5de85751cff3617b5f84 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:30:04 +0200 Subject: [PATCH 009/146] crypto: safexcel - zeroize crypto_aes_ctx with __cleanup(aes_zeroize_ctx) The code clears the crypto_aes_ctx in most cases already with memzero_explicit(), but safexcel_skcipher_aesxts_setkey() runs aes_expandkey() twice, and in case the second call fails, the context from the first call is leaked. To fix this issue and to avoid future similar problems, let's use the new __cleanup(aes_zeroize_ctx) mechanism to make sure that we always clear the crypto_aes_ctx in all cases. Acked-by: Antoine Tenart Signed-off-by: Thomas Huth Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel_cipher.c | 13 ++++--------- drivers/crypto/inside-secure/safexcel_hash.c | 3 +-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index f07d043c67d4..b031cb9652ec 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -375,7 +375,7 @@ static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm, struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct safexcel_crypto_priv *priv = ctx->base.priv; - struct crypto_aes_ctx aes; + struct crypto_aes_ctx aes __cleanup(aes_zeroize_ctx); int ret, i; ret = aes_expandkey(&aes, key, len); @@ -396,7 +396,6 @@ static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm, ctx->key_len = len; - memzero_explicit(&aes, sizeof(aes)); return 0; } @@ -1361,7 +1360,7 @@ static int safexcel_skcipher_aesctr_setkey(struct crypto_skcipher *ctfm, struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct safexcel_crypto_priv *priv = ctx->base.priv; - struct crypto_aes_ctx aes; + struct crypto_aes_ctx aes __cleanup(aes_zeroize_ctx); int ret, i; unsigned int keylen; @@ -1387,7 +1386,6 @@ static int safexcel_skcipher_aesctr_setkey(struct crypto_skcipher *ctfm, ctx->key_len = keylen; - memzero_explicit(&aes, sizeof(aes)); return 0; } @@ -2541,7 +2539,7 @@ static int safexcel_skcipher_aesxts_setkey(struct crypto_skcipher *ctfm, struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct safexcel_crypto_priv *priv = ctx->base.priv; - struct crypto_aes_ctx aes; + struct crypto_aes_ctx aes __cleanup(aes_zeroize_ctx); int ret, i; unsigned int keylen; @@ -2589,7 +2587,6 @@ static int safexcel_skcipher_aesxts_setkey(struct crypto_skcipher *ctfm, ctx->key_len = keylen << 1; - memzero_explicit(&aes, sizeof(aes)); return 0; } @@ -2755,12 +2752,11 @@ static int safexcel_aead_ccm_setkey(struct crypto_aead *ctfm, const u8 *key, struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct safexcel_crypto_priv *priv = ctx->base.priv; - struct crypto_aes_ctx aes; + struct crypto_aes_ctx aes __cleanup(aes_zeroize_ctx); int ret, i; ret = aes_expandkey(&aes, key, len); if (ret) { - memzero_explicit(&aes, sizeof(aes)); return ret; } @@ -2789,7 +2785,6 @@ static int safexcel_aead_ccm_setkey(struct crypto_aead *ctfm, const u8 *key, else ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; - memzero_explicit(&aes, sizeof(aes)); return 0; } diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c index 3402e570d045..20c17eb09495 100644 --- a/drivers/crypto/inside-secure/safexcel_hash.c +++ b/drivers/crypto/inside-secure/safexcel_hash.c @@ -1905,7 +1905,7 @@ static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int len) { struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); - struct crypto_aes_ctx aes; + struct crypto_aes_ctx aes __cleanup(aes_zeroize_ctx); int ret, i; ret = aes_expandkey(&aes, key, len); @@ -1928,7 +1928,6 @@ static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, } ctx->cbcmac = true; - memzero_explicit(&aes, sizeof(aes)); return 0; } From e1df9bb6dc67c8d846ce3559a8f65256835a35d5 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 10 Aug 2026 11:30:05 +0200 Subject: [PATCH 010/146] crypto: eip93 - Simplify the check for a valid AES key eip93_aead_setkey() currently uses aes_expandkey() to check for a valid AES key, but then does not use the crypto_aes_ctx afterwards anymore, i.e. this is just a wasteful way of checking the key length, and thus aes_check_keylen() should be used instead. This also fixes a potential leak of sensitive data via the stack, since this function forgot to zeroize crypto_aes_ctx before returning to the caller. Suggested-by: Antoine Tenart Signed-off-by: Thomas Huth Reviewed-by: Antoine Tenart Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/eip93/eip93-aead.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/inside-secure/eip93/eip93-aead.c b/drivers/crypto/inside-secure/eip93/eip93-aead.c index 2bbd0af7b0e0..0b7a899b14d7 100644 --- a/drivers/crypto/inside-secure/eip93/eip93-aead.c +++ b/drivers/crypto/inside-secure/eip93/eip93-aead.c @@ -92,7 +92,6 @@ static int eip93_aead_setkey(struct crypto_aead *ctfm, const u8 *key, struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm); struct crypto_authenc_keys keys; - struct crypto_aes_ctx aes; struct sa_record *sa_record = ctx->sa_record; u32 nonce = 0; int ret; @@ -126,7 +125,7 @@ static int eip93_aead_setkey(struct crypto_aead *ctfm, const u8 *key, break; case EIP93_ALG_AES: - ret = aes_expandkey(&aes, keys.enckey, keys.enckeylen); + ret = aes_check_keylen(keys.enckeylen); if (ret) return ret; From 93cc48a000831cc0cef4790af23db72ad63daee2 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 10 Aug 2026 12:15:59 -0700 Subject: [PATCH 011/146] crypto: crypto4xx - get irq and ioremap resource first These functions can return -EPROBE_DEFER and require no special setup other than the platform_device which is already provided. Avoids doing extra work when not needed. Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/amcc/crypto4xx_core.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index fd010bfb7020..1a327d62d464 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -1206,9 +1206,19 @@ static int crypto4xx_probe(struct platform_device *ofdev) struct device *dev = &ofdev->dev; struct crypto4xx_core_device *core_dev; struct device_node *np; + void __iomem *ce_base; + int irq; u32 pvr; bool is_revb = true; + irq = platform_get_irq(ofdev, 0); + if (irq < 0) + return irq; + + ce_base = devm_platform_ioremap_resource(ofdev, 0); + if (IS_ERR(ce_base)) + return PTR_ERR(ce_base); + np = of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-crypto"); if (np) { mtdcri(SDR0, PPC460EX_SDR0_SRST, @@ -1251,9 +1261,7 @@ 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); + core_dev->dev->ce_base = ce_base; /* * Older version of 460EX/GT have a hardware bug. @@ -1291,11 +1299,7 @@ static int crypto4xx_probe(struct platform_device *ofdev) (unsigned long) dev); /* Register for Crypto isr, Crypto Engine IRQ */ - core_dev->irq = platform_get_irq(ofdev, 0); - if (core_dev->irq < 0) { - rc = core_dev->irq; - goto err_tasklet; - } + core_dev->irq = irq; rc = request_irq(core_dev->irq, is_revb ? crypto4xx_ce_interrupt_handler_revb : crypto4xx_ce_interrupt_handler, From a97e714abb75c6c94c674468092356dcf805772b Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 10 Aug 2026 21:33:58 -0700 Subject: [PATCH 012/146] crypto: s5p-sss - pass s5p_aes_dev to irq handler The threaded irq handler takes the platform device and calls platform_get_drvdata() to recover the driver data. Pass the driver data directly as the devm_request_threaded_irq() argument instead, dropping the platform_get_drvdata() call. Assisted-by: opencode:deepseek-v4-flash-free Signed-off-by: Rosen Penev Reviewed-by: Thomas Huth Reviewed-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index bdda7b39af85..f20c02e9d646 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -638,8 +638,7 @@ static int s5p_hash_rx(struct s5p_aes_dev *dev) static irqreturn_t s5p_aes_interrupt(int irq, void *dev_id) { - struct platform_device *pdev = dev_id; - struct s5p_aes_dev *dev = platform_get_drvdata(pdev); + struct s5p_aes_dev *dev = dev_id; struct skcipher_request *req; int err_dma_tx = 0; int err_dma_rx = 0; @@ -2221,7 +2220,7 @@ static int s5p_aes_probe(struct platform_device *pdev) } err = devm_request_threaded_irq(dev, pdata->irq_fc, NULL, s5p_aes_interrupt, IRQF_ONESHOT, - pdev->name, pdev); + pdev->name, pdata); if (err < 0) { dev_warn(dev, "feed control interrupt is not available.\n"); goto err_irq; From 7702659bc3a95fc153934f17d51b72fae510260e Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 10 Aug 2026 21:49:16 -0700 Subject: [PATCH 013/146] crypto: rockchip - pass crypto_info to irq handler The irq handler takes the platform device and calls platform_get_drvdata() to recover the driver data. Pass the driver data directly as the devm_request_irq() argument instead, dropping the platform_get_drvdata() call. Assisted-by: opencode:deepseek-v4-flash-free Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/rockchip/rk3288_crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c index 7cb1316b6f18..b2b629fffc05 100644 --- a/drivers/crypto/rockchip/rk3288_crypto.c +++ b/drivers/crypto/rockchip/rk3288_crypto.c @@ -163,7 +163,7 @@ static void rk_crypto_pm_exit(struct rk_crypto_info *rkdev) static irqreturn_t rk_crypto_irq_handle(int irq, void *dev_id) { - struct rk_crypto_info *dev = platform_get_drvdata(dev_id); + struct rk_crypto_info *dev = dev_id; u32 interrupt_status; interrupt_status = CRYPTO_READ(dev, RK_CRYPTO_INTSTS); @@ -363,7 +363,7 @@ static int rk_crypto_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, crypto_info->irq, rk_crypto_irq_handle, IRQF_SHARED, - "rk-crypto", pdev); + "rk-crypto", crypto_info); if (err) goto err_crypto; From 3244eef8b5cf120ec5428b2b8172c7a87bc64862 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 12 Aug 2026 12:15:55 -0700 Subject: [PATCH 014/146] crypto: crypto4xx - pass core_dev to request_irq Instead of using a get_drvdata function to get the proper struct, just pass the proper thing directly. Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/amcc/crypto4xx_core.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 1a327d62d464..a044dce65cf4 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -1046,8 +1046,7 @@ static void crypto4xx_bh_tasklet_cb(unsigned long data) static inline irqreturn_t crypto4xx_interrupt_handler(int irq, void *data, u32 clr_val) { - struct device *dev = data; - struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); + struct crypto4xx_core_device *core_dev = data; writel(clr_val, core_dev->dev->ce_base + CRYPTO4XX_INT_CLR); tasklet_schedule(&core_dev->tasklet); @@ -1303,7 +1302,7 @@ static int crypto4xx_probe(struct platform_device *ofdev) rc = request_irq(core_dev->irq, is_revb ? crypto4xx_ce_interrupt_handler_revb : crypto4xx_ce_interrupt_handler, - 0, KBUILD_MODNAME, dev); + 0, KBUILD_MODNAME, core_dev); if (rc) goto err_tasklet; @@ -1320,7 +1319,7 @@ static int crypto4xx_probe(struct platform_device *ofdev) return 0; err_irq: - free_irq(core_dev->irq, dev); + free_irq(core_dev->irq, core_dev); err_tasklet: tasklet_kill(&core_dev->tasklet); err_build_sdr: @@ -1341,7 +1340,7 @@ static void crypto4xx_remove(struct platform_device *ofdev) * 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); + free_irq(core_dev->irq, core_dev); tasklet_kill(&core_dev->tasklet); /* Un-register with Linux CryptoAPI */ crypto4xx_unregister_alg(core_dev->dev); From 58d27c41542be6c40edac4f91f35a1dd8bf0d2c2 Mon Sep 17 00:00:00 2001 From: Ruoyu Wang Date: Fri, 14 Aug 2026 21:39:33 +0800 Subject: [PATCH 015/146] hwrng: cctrng - Fix runtime PM usage counter leak pm_runtime_get_sync() increments the device usage counter even when runtime resume fails. cctrng_read() propagates errors from cc_trng_pm_get() without scheduling the work that later drops the counter, so a clock or reset-completion failure in cctrng_resume() leaves the counter elevated. Use pm_runtime_resume_and_get(), which drops the usage counter when resume fails and returns zero on success. This preserves the existing success path while balancing the error path. This issue was found by a static analysis checker and confirmed by manual source review. Fixes: a583ed310bb6 ("hwrng: cctrng - introduce Arm CryptoCell driver") Signed-off-by: Ruoyu Wang Signed-off-by: Herbert Xu --- drivers/char/hw_random/cctrng.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c index a6925211c3b5..51290ea345c3 100644 --- a/drivers/char/hw_random/cctrng.c +++ b/drivers/char/hw_random/cctrng.c @@ -86,12 +86,7 @@ static inline u32 cc_ioread(struct cctrng_drvdata *drvdata, u32 reg) static int cc_trng_pm_get(struct device *dev) { - int rc = 0; - - rc = pm_runtime_get_sync(dev); - - /* pm_runtime_get_sync() can return 1 as a valid return code */ - return (rc == 1 ? 0 : rc); + return pm_runtime_resume_and_get(dev); } static void cc_trng_pm_put_suspend(struct device *dev) From 4333ab90aaaea54f51af04025dc6f12f87e83f2d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 15 Aug 2026 16:24:07 +1000 Subject: [PATCH 016/146] rhashtable: use private lockdep class for all locks. This patch builds on Commit: 060d4e94b8d4 ("rhashtable: give each instance its own lockdep class") to allow lockdep to see each rhashtable as unique with respect to all of the locks, not just the ht->mutex. This is needed if rhashtable is to be used tracepoint BPF which could run while an rhashtable lock (in a different table) is held - see Link below. Rather then adding extra keys for the other locks, we use distinct sub-classes for the different locks. rhashtable->lock uses class 0 rhashtable->mutex uses class 1 bucket bitlocks, which are the only ones that are ever nested, use classes 2 and 3. Currently rht_lock() and rht_lock_nested() are quite separate code despite the near-identical function. This patch moves rht_lock() to after rht_lock_nested(), and simply calls that other function with a nesting level of zero. Link: https://lore.kernel.org/all/20260801-fix-rhashtable-bucket-lockdep-v1-1-15a0f8ae094c@gmail.com/ Closes: https://syzkaller.appspot.com/bug?extid=ef8d17bae14efb960935 Tested-by: quanyeyang Signed-off-by: NeilBrown Signed-off-by: Herbert Xu --- include/linux/rhashtable-types.h | 3 +++ include/linux/rhashtable.h | 22 +++++++++------------- lib/rhashtable.c | 14 +++++++++++--- lib/test_rhashtable.c | 2 +- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h index 57c11ec9dc64..0e1b172a4f6c 100644 --- a/include/linux/rhashtable-types.h +++ b/include/linux/rhashtable-types.h @@ -97,6 +97,9 @@ struct rhashtable { #ifdef CONFIG_MEM_ALLOC_PROFILING struct alloc_tag *alloc_tag; #endif +#ifdef CONFIG_LOCKDEP + struct lock_class_key *lockdep_key; +#endif }; /** diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index 57a2a29bef0e..6c5e6d9accba 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h @@ -319,18 +319,6 @@ static inline struct rhash_lock_head __rcu **rht_bucket_insert( * When we write to a bucket without unlocking, we use rht_assign_locked(). */ -static inline unsigned long rht_lock(struct bucket_table *tbl, - struct rhash_lock_head __rcu **bkt) - __acquires(__bitlock(0, bkt)) -{ - unsigned long flags; - - local_irq_save(flags); - bit_spin_lock(0, (unsigned long *)bkt); - lock_map_acquire(&tbl->dep_map); - return flags; -} - static inline unsigned long rht_lock_nested(struct bucket_table *tbl, struct rhash_lock_head __rcu **bucket, unsigned int subclass) @@ -340,10 +328,18 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl, local_irq_save(flags); bit_spin_lock(0, (unsigned long *)bucket); - lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_); + /* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */ + lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_); return flags; } +static inline unsigned long rht_lock(struct bucket_table *tbl, + struct rhash_lock_head __rcu **bkt) + __acquires(__bitlock(0, bkt)) +{ + return rht_lock_nested(tbl, bkt, 0); +} + static inline void rht_unlock(struct bucket_table *tbl, struct rhash_lock_head __rcu **bkt, unsigned long flags) diff --git a/lib/rhashtable.c b/lib/rhashtable.c index 6362896e4f09..5da0e53a8d42 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -191,7 +191,6 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht, struct bucket_table *tbl = NULL; size_t size; int i; - static struct lock_class_key __key; tbl = alloc_hooks_tag(ht->alloc_tag, kvmalloc_node_align_noprof(struct_size(tbl, buckets, nbuckets), @@ -207,7 +206,10 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht, if (tbl == NULL) return NULL; - lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", &__key, 0); +#ifdef CONFIG_LOCKDEP + /* bitlocks must use nesting level 2 or more */ + lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", ht->lockdep_key, 0); +#endif tbl->size = size; @@ -430,7 +432,7 @@ static void rht_deferred_worker(struct work_struct *work) int err = 0; ht = container_of(work, struct rhashtable, run_work); - mutex_lock(&ht->mutex); + mutex_lock_nested(&ht->mutex, 1); tbl = rht_dereference(ht->tbl, ht); tbl = rhashtable_last_table(ht, tbl); @@ -1174,8 +1176,14 @@ int __rhashtable_init_noprof(struct rhashtable *ht, return -EINVAL; memset(ht, 0, sizeof(*ht)); + /* mutex_lock must use nesting level 1 */ mutex_init_with_key(&ht->mutex, key); spin_lock_init(&ht->lock); + /* spin_lock can use nesting level 0 */ + lockdep_set_class(&ht->lock, key); +#ifdef CONFIG_LOCKDEP + ht->lockdep_key = key; +#endif memcpy(&ht->p, params, sizeof(*params)); alloc_tag_record(ht->alloc_tag); diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c index b767a38a74f9..85a615e74591 100644 --- a/lib/test_rhashtable.c +++ b/lib/test_rhashtable.c @@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt) ht = &rhlt->ht; /* Take the mutex to avoid RCU warning */ - mutex_lock(&ht->mutex); + mutex_lock_nested(&ht->mutex, 1); tbl = rht_dereference(ht->tbl, ht); for (i = 0; i < tbl->size; i++) { struct rhash_head *pos, *next; From 37d550172c2d3cdb3a5ace3e6cb0625967d86349 Mon Sep 17 00:00:00 2001 From: Fabrice Derepas Date: Sat, 15 Aug 2026 16:00:19 +0200 Subject: [PATCH 017/146] crypto: asymmetric_keys - fix OOB read in pefile_parse_binary pefile_parse_binary() reads the size field of the certificate table's data-directory entry, which sits at fixed index 4 of the PE optional header's data directory: ctx->certs_size = ddir->certs.size; but nothing ensures index 4 is present. n_data_dirents (the untrusted NumberOfRvaAndSizes) is only upper-bounded against header_size and may be 0, and header_size need only satisfy cursor < header_size < datalen. A crafted PE with n_data_dirents = 0 and a tiny header_size therefore causes the ddir->certs.size read to land past the end of the image (CWE-125). The chkaddr() that bounds the certificate blob runs only after this read. verify_pefile_signature() is reached from kexec_file_load() (the lockdown/secure-boot enforced PE-image signature path), and the image is parsed before its signature is checked. The trigger needs CAP_SYS_BOOT and the access is out-of-bounds read only (no write). Require the certificate table's data-directory entry (index 4) to be present; the existing upper-bound check then keeps ddir->certs within [cursor, header_size). Fixes: 26d1164be37f ("pefile: Parse a PE binary to find a key and a signature contained therein") Assisted-by: copilot-cli:claude-opus-4-6 frama-c Signed-off-by: Fabrice Derepas Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/verify_pefile.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index cec99db14129..1efd5c0d0e9c 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -87,6 +87,11 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen, if (ctx->n_data_dirents > (ctx->header_size - cursor) / sizeof(*dde)) return -ELIBBAD; + /* the certificate table entry must be present in the data directory */ + if (ctx->n_data_dirents <= + offsetof(struct data_directory, certs) / sizeof(*dde)) + return -ELIBBAD; + ddir = pebuf + cursor; cursor += sizeof(*dde) * ctx->n_data_dirents; From aacc136b895c5d365eb02c488490d1fac9ee14ac Mon Sep 17 00:00:00 2001 From: Fabrice Derepas Date: Sat, 15 Aug 2026 16:00:20 +0200 Subject: [PATCH 018/146] crypto: asymmetric_keys - add KUnit tests for the PE parser Add self-contained KUnit tests for pefile_parse_binary(), exercised through verify_pefile_signature() -- which parses the image before any signature check, so no keyring or real signature is needed. The cases build small malformed PE images in memory: - a PE declaring 0 data-directory entries: the certificate table entry at fixed index 4 is absent and must be rejected (-ELIBBAD), not read out of bounds; - a PE declaring 5 entries with a zero (unsigned) certificate entry gets past the directory bound and is rejected as unsigned (-ENODATA). verify_pefile_signature() is not exported, so the test is built-in only (bool, not tristate). Signed-off-by: Fabrice Derepas Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/Kconfig | 12 +++ crypto/asymmetric_keys/Makefile | 2 + crypto/asymmetric_keys/verify_pefile_test.c | 100 ++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 crypto/asymmetric_keys/verify_pefile_test.c diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 6a2f664046ef..c73979b2e98e 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -114,4 +114,16 @@ config FIPS_SIGNATURE_SELFTEST_ECDSA depends on CRYPTO_SHA256=y || CRYPTO_SHA256=FIPS_SIGNATURE_SELFTEST depends on CRYPTO_ECDSA=y || CRYPTO_ECDSA=FIPS_SIGNATURE_SELFTEST +config VERIFY_PEFILE_KUNIT_TEST + bool "KUnit tests for signed PE file parsing" if !KUNIT_ALL_TESTS + depends on KUNIT=y && SIGNED_PE_FILE_VERIFICATION + default KUNIT_ALL_TESTS + help + Enable KUnit tests for the PE binary parser used by signed PE file + signature verification. The tests build small malformed PE images in + memory and check that pefile_parse_binary() rejects them instead of + reading out of bounds. + + If unsure, say N. + endif # ASYMMETRIC_KEY_TYPE diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index bc65d3b98dcb..35172685c533 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -79,3 +79,5 @@ verify_signed_pefile-y := \ $(obj)/mscode_parser.o: $(obj)/mscode.asn1.h $(obj)/mscode.asn1.h $(obj)/mscode.asn1.o: $(obj)/mscode.asn1.c $(obj)/mscode.asn1.h + +obj-$(CONFIG_VERIFY_PEFILE_KUNIT_TEST) += verify_pefile_test.o diff --git a/crypto/asymmetric_keys/verify_pefile_test.c b/crypto/asymmetric_keys/verify_pefile_test.c new file mode 100644 index 000000000000..8b42eb41edd5 --- /dev/null +++ b/crypto/asymmetric_keys/verify_pefile_test.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * KUnit tests for the signed PE binary parser in verify_pefile.c. + * + * The cases build small malformed PE images in memory and call + * verify_pefile_signature(), which parses the image before any signature + * check, so the parser is exercised without a keyring or a real signature. + */ +#include +#include +#include +#include + +/* + * Build a minimal PE32 image whose optional header declares @data_dirs data + * directory entries. header_size is sized to hold them and the image is a few + * bytes larger. With @data_dirs < 5 the certificate table entry (fixed index + * 4) lies outside the declared directory. + */ +static void *build_pe32(u16 data_dirs, unsigned int *out_len) +{ + size_t cursor = sizeof(struct mz_hdr) + sizeof(struct pe_hdr) + + sizeof(struct pe32_opt_hdr); + size_t header_size = cursor + ((size_t)data_dirs + 1) * + sizeof(struct data_dirent); + size_t pelen = header_size + 8; + struct mz_hdr *mz; + struct pe_hdr *pe; + struct pe32_opt_hdr *opt; + void *buf = kzalloc(pelen, GFP_KERNEL); + + if (!buf) + return NULL; + + mz = buf; + mz->magic = IMAGE_DOS_SIGNATURE; + mz->peaddr = sizeof(struct mz_hdr); + + pe = buf + sizeof(struct mz_hdr); + pe->magic = IMAGE_NT_SIGNATURE; + + opt = buf + sizeof(struct mz_hdr) + sizeof(struct pe_hdr); + opt->magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC; + opt->header_size = header_size; + opt->data_dirs = data_dirs; + + *out_len = pelen; + return buf; +} + +/* + * data_dirs = 0: the certificate table entry (index 4) is absent, so the + * parser must reject the image instead of reading ddir->certs past the end. + */ +static void pefile_missing_certs_dirent(struct kunit *test) +{ + unsigned int len; + void *buf = build_pe32(0, &len); + int ret; + + KUNIT_ASSERT_NOT_NULL(test, buf); + ret = verify_pefile_signature(buf, len, NULL, + VERIFYING_KEXEC_PE_SIGNATURE); + KUNIT_EXPECT_EQ(test, ret, -ELIBBAD); + kfree(buf); +} + +/* + * data_dirs = 5: the certificate table entry is present (and zero, i.e. + * unsigned), so the parser gets past the directory bound and rejects the image + * as unsigned (-ENODATA) rather than -ELIBBAD. + */ +static void pefile_present_certs_dirent(struct kunit *test) +{ + unsigned int len; + void *buf = build_pe32(5, &len); + int ret; + + KUNIT_ASSERT_NOT_NULL(test, buf); + ret = verify_pefile_signature(buf, len, NULL, + VERIFYING_KEXEC_PE_SIGNATURE); + KUNIT_EXPECT_EQ(test, ret, -ENODATA); + kfree(buf); +} + +static struct kunit_case verify_pefile_cases[] = { + KUNIT_CASE(pefile_missing_certs_dirent), + KUNIT_CASE(pefile_present_certs_dirent), + {} +}; + +static struct kunit_suite verify_pefile_suite = { + .name = "verify_pefile", + .test_cases = verify_pefile_cases, +}; + +kunit_test_suite(verify_pefile_suite); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("KUnit tests for the signed PE binary parser"); From 844de214375b213cd20a38198594b9c5321ed2eb Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 15 Aug 2026 17:09:47 +0200 Subject: [PATCH 019/146] crypto: qce - simplify control flow in register functions Remove the goto statements and handle errors directly to simplify the control flow in qce_aead_register(), qce_ahash_register(), and qce_skcipher_register(). Signed-off-by: Thorsten Blum Reviewed-by: Bartosz Golaszewski Signed-off-by: Herbert Xu --- drivers/crypto/qce/aead.c | 9 ++++----- drivers/crypto/qce/sha.c | 9 ++++----- drivers/crypto/qce/skcipher.c | 9 ++++----- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index a9642c67f476..37eb6d556df5 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -769,14 +769,13 @@ static int qce_aead_register(struct qce_device *qce) for (i = 0; i < ARRAY_SIZE(aead_def); i++) { ret = qce_aead_register_one(&aead_def[i], qce); - if (ret) - goto err; + if (ret) { + qce_aead_unregister(qce); + return ret; + } } return 0; -err: - qce_aead_unregister(qce); - return ret; } const struct qce_algo_ops aead_ops = { diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index eb8a5b0c4173..b67d749db05f 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -480,14 +480,13 @@ static int qce_ahash_register(struct qce_device *qce) for (i = 0; i < ARRAY_SIZE(ahash_def); i++) { ret = qce_ahash_register_one(&ahash_def[i], qce); - if (ret) - goto err; + if (ret) { + qce_ahash_unregister(qce); + return ret; + } } return 0; -err: - qce_ahash_unregister(qce); - return ret; } const struct qce_algo_ops ahash_ops = { diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 4931b064f10e..03a3cec2bb90 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -416,14 +416,13 @@ static int qce_skcipher_register(struct qce_device *qce) for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { ret = qce_skcipher_register_one(&skcipher_def[i], qce); - if (ret) - goto err; + if (ret) { + qce_skcipher_unregister(qce); + return ret; + } } return 0; -err: - qce_skcipher_unregister(qce); - return ret; } const struct qce_algo_ops skcipher_ops = { From aaab22844300556823474f57aa7622e87606afb0 Mon Sep 17 00:00:00 2001 From: "David C.C.M. Gall" Date: Sat, 15 Aug 2026 19:08:21 +0200 Subject: [PATCH 020/146] crypto: octeontx2 - use crypto_memneq() to check HMAC for cipher_null authenc validate_hmac_cipher_null() compares the computed and received HMAC with memcmp(), which short-circuits on the first differing byte and leaks tag-match length via timing. Use crypto_memneq() instead. Because for cipher_null the validated payload is un-encrypted, this valid prefix leak allows for authenticated message forgery. Assisted-by: gregkh_clanker_t1000 Signed-off-by: David C.C.M. Gall Signed-off-by: Herbert Xu --- drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c index 8d9f394d6b50..3ccf17d031c6 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include "otx2_cptvf.h" @@ -90,9 +91,9 @@ static inline int validate_hmac_cipher_null(struct otx2_cpt_req_info *cpt_req) req = container_of(cpt_req->areq, struct aead_request, base); tfm = crypto_aead_reqtfm(req); rctx = aead_request_ctx_dma(req); - if (memcmp(rctx->fctx.hmac.s.hmac_calc, - rctx->fctx.hmac.s.hmac_recv, - crypto_aead_authsize(tfm)) != 0) + if (crypto_memneq(rctx->fctx.hmac.s.hmac_calc, + rctx->fctx.hmac.s.hmac_recv, + crypto_aead_authsize(tfm))) return -EBADMSG; return 0; From caad4d7cbca42f075be867490cfad8d204f40710 Mon Sep 17 00:00:00 2001 From: "David C.C.M. Gall" Date: Sat, 15 Aug 2026 19:09:14 +0200 Subject: [PATCH 021/146] crypto: octeontx - use crypto_memneq() to check HMAC validate_hmac_cipher_null() compares the computed and received HMAC with memcmp(), which short-circuits on the first differing byte and leaks tag-match length via timing. Use crypto_memneq() instead. Because for cipher_null the validated payload is un-encrypted, this valid prefix leak allows for authenticated message forgery. Assisted-by: gregkh_clanker_t1000 Signed-off-by: David C.C.M. Gall Signed-off-by: Herbert Xu --- drivers/crypto/marvell/octeontx/otx_cptvf_algs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c b/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c index 096be42e9d03..70befbdd442b 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c +++ b/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -105,9 +106,9 @@ static inline int validate_hmac_cipher_null(struct otx_cpt_req_info *cpt_req) req = container_of(cpt_req->areq, struct aead_request, base); tfm = crypto_aead_reqtfm(req); rctx = aead_request_ctx_dma(req); - if (memcmp(rctx->fctx.hmac.s.hmac_calc, - rctx->fctx.hmac.s.hmac_recv, - crypto_aead_authsize(tfm)) != 0) + if (crypto_memneq(rctx->fctx.hmac.s.hmac_calc, + rctx->fctx.hmac.s.hmac_recv, + crypto_aead_authsize(tfm))) return -EBADMSG; return 0; From 97e5869514bd4800593d5b13dc01c42f7d6a1ccc Mon Sep 17 00:00:00 2001 From: "David C.C.M. Gall" Date: Sat, 15 Aug 2026 19:09:58 +0200 Subject: [PATCH 022/146] crypto: ccree - use crypto_memneq() to compare AEAD tag cc_aead_complete() compares the computed MAC against the received ICV with memcmp(), which short-circuits on the first differing byte and leaks tag-match length via timing. Use crypto_memneq() instead. Assisted-by: gregkh_clanker_t1000 Signed-off-by: David C.C.M. Gall Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_aead.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c index 088c4603047f..d57a98f89e53 100644 --- a/drivers/crypto/ccree/cc_aead.c +++ b/drivers/crypto/ccree/cc_aead.c @@ -226,8 +226,8 @@ static void cc_aead_complete(struct device *dev, void *cc_req, int err) goto done; if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) { - if (memcmp(areq_ctx->mac_buf, areq_ctx->icv_virt_addr, - ctx->authsize) != 0) { + if (crypto_memneq(areq_ctx->mac_buf, areq_ctx->icv_virt_addr, + ctx->authsize)) { dev_dbg(dev, "Payload authentication failure, (auth-size=%d, cipher=%d)\n", ctx->authsize, ctx->cipher_mode); /* In case of payload authentication failure, MUST NOT From 5358248961ae23f7253d010ddfde1cfd2556ce22 Mon Sep 17 00:00:00 2001 From: Jiawen Liu <1298662399@qq.com> Date: Tue, 18 Aug 2026 17:25:44 +0400 Subject: [PATCH 023/146] crypto: starfive - handle clock enable failures Return error from failed clock enable. starfive_cryp_probe ignores clk_prepare_enable return for hclk/ahb, then remove/error paths unconditionally clk_disable_unprepare both clocks. Check consecutive clk_prepare_enable(cryp->hclk)/cryp->ahb returns in starfive_cryp_probe. Signed-off-by: Jiawen Liu <1298662399@qq.com> Signed-off-by: Herbert Xu --- drivers/crypto/starfive/jh7110-cryp.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/starfive/jh7110-cryp.c b/drivers/crypto/starfive/jh7110-cryp.c index 842f76b0f114..c3830a7c1810 100644 --- a/drivers/crypto/starfive/jh7110-cryp.c +++ b/drivers/crypto/starfive/jh7110-cryp.c @@ -120,8 +120,15 @@ static int starfive_cryp_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst), "Error getting hardware reset line\n"); - clk_prepare_enable(cryp->hclk); - clk_prepare_enable(cryp->ahb); + ret = clk_prepare_enable(cryp->hclk); + if (ret) + return ret; + + ret = clk_prepare_enable(cryp->ahb); + if (ret) { + clk_disable_unprepare(cryp->hclk); + return ret; + } reset_control_deassert(cryp->rst); spin_lock(&dev_list.lock); From 40ea0a15f20ca2f2b2038400dece17d26cb008ab Mon Sep 17 00:00:00 2001 From: Chenghai Huang Date: Wed, 19 Aug 2026 15:53:53 +0800 Subject: [PATCH 024/146] crypto: hisilicon/sec - remove SEC crypto block cipher accelerator The Hisilicon SEC crypto cipher accelerator has been superseded by the newer SEC2 driver (drivers/crypto/hisilicon/sec2/). SEC2 provides wider algorithm coverage and is the maintained path forward, and users have migrated to it. The legacy SEC driver has had no active users for some time, and its primary maintainer, Jonathan Cameron, has moved on from Huawei and is no longer in a position to maintain it. With thanks to Jonathan for his contributions to this driver over the years, and with no one left to keep it up to date, remove it from the tree. This drops the legacy SEC driver together with all of its residual configuration, devicetree binding and board description references: - drivers/crypto/hisilicon/sec/ - CONFIG_CRYPTO_DEV_HISI_SEC Kconfig option - sec/ entry from drivers/crypto/hisilicon/Makefile - Documentation/devicetree/bindings/crypto/hisilicon,hip06-sec.yaml - hisilicon,hip07-sec device nodes and their supporting mbigen_alg / smmu_alg infrastructure from arch/arm64/boot/dts/hisilicon/hip07.dtsi Signed-off-by: Chenghai Huang Reviewed-by: Longfang Liu Acked-by: Eric Biggers Acked-by: Wei Xu Reviewed-by: Jonathan Cameron Signed-off-by: Herbert Xu --- .../bindings/crypto/hisilicon,hip06-sec.yaml | 134 -- arch/arm64/boot/dts/hisilicon/hip07.dtsi | 280 ---- drivers/crypto/hisilicon/Kconfig | 14 - drivers/crypto/hisilicon/Makefile | 1 - drivers/crypto/hisilicon/sec/Makefile | 3 - drivers/crypto/hisilicon/sec/sec_algs.c | 1122 -------------- drivers/crypto/hisilicon/sec/sec_drv.c | 1307 ----------------- drivers/crypto/hisilicon/sec/sec_drv.h | 428 ------ 8 files changed, 3289 deletions(-) delete mode 100644 Documentation/devicetree/bindings/crypto/hisilicon,hip06-sec.yaml delete mode 100644 drivers/crypto/hisilicon/sec/Makefile delete mode 100644 drivers/crypto/hisilicon/sec/sec_algs.c delete mode 100644 drivers/crypto/hisilicon/sec/sec_drv.c delete mode 100644 drivers/crypto/hisilicon/sec/sec_drv.h diff --git a/Documentation/devicetree/bindings/crypto/hisilicon,hip06-sec.yaml b/Documentation/devicetree/bindings/crypto/hisilicon,hip06-sec.yaml deleted file mode 100644 index 2bfac9d1c020..000000000000 --- a/Documentation/devicetree/bindings/crypto/hisilicon,hip06-sec.yaml +++ /dev/null @@ -1,134 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/crypto/hisilicon,hip06-sec.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Hisilicon hip06/hip07 Security Accelerator - -maintainers: - - Jonathan Cameron - -properties: - compatible: - enum: - - hisilicon,hip06-sec - - hisilicon,hip07-sec - - reg: - items: - - description: Registers for backend processing engines - - description: Registers for common functionality - - description: Registers for queue 0 - - description: Registers for queue 1 - - description: Registers for queue 2 - - description: Registers for queue 3 - - description: Registers for queue 4 - - description: Registers for queue 5 - - description: Registers for queue 6 - - description: Registers for queue 7 - - description: Registers for queue 8 - - description: Registers for queue 9 - - description: Registers for queue 10 - - description: Registers for queue 11 - - description: Registers for queue 12 - - description: Registers for queue 13 - - description: Registers for queue 14 - - description: Registers for queue 15 - - interrupts: - items: - - description: SEC unit error queue interrupt - - description: Completion interrupt for queue 0 - - description: Error interrupt for queue 0 - - description: Completion interrupt for queue 1 - - description: Error interrupt for queue 1 - - description: Completion interrupt for queue 2 - - description: Error interrupt for queue 2 - - description: Completion interrupt for queue 3 - - description: Error interrupt for queue 3 - - description: Completion interrupt for queue 4 - - description: Error interrupt for queue 4 - - description: Completion interrupt for queue 5 - - description: Error interrupt for queue 5 - - description: Completion interrupt for queue 6 - - description: Error interrupt for queue 6 - - description: Completion interrupt for queue 7 - - description: Error interrupt for queue 7 - - description: Completion interrupt for queue 8 - - description: Error interrupt for queue 8 - - description: Completion interrupt for queue 9 - - description: Error interrupt for queue 9 - - description: Completion interrupt for queue 10 - - description: Error interrupt for queue 10 - - description: Completion interrupt for queue 11 - - description: Error interrupt for queue 11 - - description: Completion interrupt for queue 12 - - description: Error interrupt for queue 12 - - description: Completion interrupt for queue 13 - - description: Error interrupt for queue 13 - - description: Completion interrupt for queue 14 - - description: Error interrupt for queue 14 - - description: Completion interrupt for queue 15 - - description: Error interrupt for queue 15 - - dma-coherent: true - - iommus: - maxItems: 1 - -required: - - compatible - - reg - - interrupts - - dma-coherent - -additionalProperties: false - -examples: - - | - bus { - #address-cells = <2>; - #size-cells = <2>; - - crypto@400d2000000 { - compatible = "hisilicon,hip07-sec"; - reg = <0x400 0xd0000000 0x0 0x10000 - 0x400 0xd2000000 0x0 0x10000 - 0x400 0xd2010000 0x0 0x10000 - 0x400 0xd2020000 0x0 0x10000 - 0x400 0xd2030000 0x0 0x10000 - 0x400 0xd2040000 0x0 0x10000 - 0x400 0xd2050000 0x0 0x10000 - 0x400 0xd2060000 0x0 0x10000 - 0x400 0xd2070000 0x0 0x10000 - 0x400 0xd2080000 0x0 0x10000 - 0x400 0xd2090000 0x0 0x10000 - 0x400 0xd20a0000 0x0 0x10000 - 0x400 0xd20b0000 0x0 0x10000 - 0x400 0xd20c0000 0x0 0x10000 - 0x400 0xd20d0000 0x0 0x10000 - 0x400 0xd20e0000 0x0 0x10000 - 0x400 0xd20f0000 0x0 0x10000 - 0x400 0xd2100000 0x0 0x10000>; - interrupts = <576 4>, - <577 1>, <578 4>, - <579 1>, <580 4>, - <581 1>, <582 4>, - <583 1>, <584 4>, - <585 1>, <586 4>, - <587 1>, <588 4>, - <589 1>, <590 4>, - <591 1>, <592 4>, - <593 1>, <594 4>, - <595 1>, <596 4>, - <597 1>, <598 4>, - <599 1>, <600 4>, - <601 1>, <602 4>, - <603 1>, <604 4>, - <605 1>, <606 4>, - <607 1>, <608 4>; - dma-coherent; - iommus = <&p1_smmu_alg_a 0x600>; - }; - }; diff --git a/arch/arm64/boot/dts/hisilicon/hip07.dtsi b/arch/arm64/boot/dts/hisilicon/hip07.dtsi index 00a6bfa7478c..d175e242ee96 100644 --- a/arch/arm64/boot/dts/hisilicon/hip07.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip07.dtsi @@ -1113,74 +1113,6 @@ num-pins = <2>; }; }; - p0_mbigen_alg_a:interrupt-controller@d0080000 { - compatible = "hisilicon,mbigen-v2"; - reg = <0x0 0xd0080000 0x0 0x10000>; - - p0_mbigen_sec_a: intc_sec { - msi-parent = <&p0_its_dsa_a 0x40400>; - interrupt-controller; - #interrupt-cells = <2>; - num-pins = <33>; - }; - p0_mbigen_smmu_alg_a: intc_smmu_alg { - msi-parent = <&p0_its_dsa_a 0x40b1b>; - interrupt-controller; - #interrupt-cells = <2>; - num-pins = <3>; - }; - }; - p0_mbigen_alg_b:interrupt-controller@8,d0080000 { - compatible = "hisilicon,mbigen-v2"; - reg = <0x8 0xd0080000 0x0 0x10000>; - - p0_mbigen_sec_b: intc_sec { - msi-parent = <&p0_its_dsa_b 0x42400>; - interrupt-controller; - #interrupt-cells = <2>; - num-pins = <33>; - }; - p0_mbigen_smmu_alg_b: intc_smmu_alg { - msi-parent = <&p0_its_dsa_b 0x42b1b>; - interrupt-controller; - #interrupt-cells = <2>; - num-pins = <3>; - }; - }; - p1_mbigen_alg_a:interrupt-controller@400,d0080000 { - compatible = "hisilicon,mbigen-v2"; - reg = <0x400 0xd0080000 0x0 0x10000>; - - p1_mbigen_sec_a: intc_sec { - msi-parent = <&p1_its_dsa_a 0x44400>; - interrupt-controller; - #interrupt-cells = <2>; - num-pins = <33>; - }; - p1_mbigen_smmu_alg_a: intc_smmu_alg { - msi-parent = <&p1_its_dsa_a 0x44b1b>; - interrupt-controller; - #interrupt-cells = <2>; - num-pins = <3>; - }; - }; - p1_mbigen_alg_b:interrupt-controller@408,d0080000 { - compatible = "hisilicon,mbigen-v2"; - reg = <0x408 0xd0080000 0x0 0x10000>; - - p1_mbigen_sec_b: intc_sec { - msi-parent = <&p1_its_dsa_b 0x46400>; - interrupt-controller; - #interrupt-cells = <2>; - num-pins = <33>; - }; - p1_mbigen_smmu_alg_b: intc_smmu_alg { - msi-parent = <&p1_its_dsa_b 0x46b1b>; - interrupt-controller; - #interrupt-cells = <2>; - num-pins = <3>; - }; - }; p0_mbigen_dsa_a: interrupt-controller@c0080000 { compatible = "hisilicon,mbigen-v2"; reg = <0x0 0xc0080000 0x0 0x10000>; @@ -1237,54 +1169,6 @@ hisilicon,broken-prefetch-cmd; status = "disabled"; }; - p0_smmu_alg_a: iommu@d0040000 { - compatible = "arm,smmu-v3"; - reg = <0x0 0xd0040000 0x0 0x20000>; - interrupt-parent = <&p0_mbigen_smmu_alg_a>; - interrupts = <733 1>, - <734 1>, - <735 1>; - interrupt-names = "eventq", "gerror", "priq"; - #iommu-cells = <1>; - dma-coherent; - hisilicon,broken-prefetch-cmd; - }; - p0_smmu_alg_b: iommu@8d0040000 { - compatible = "arm,smmu-v3"; - reg = <0x8 0xd0040000 0x0 0x20000>; - interrupt-parent = <&p0_mbigen_smmu_alg_b>; - interrupts = <733 1>, - <734 1>, - <735 1>; - interrupt-names = "eventq", "gerror", "priq"; - #iommu-cells = <1>; - dma-coherent; - hisilicon,broken-prefetch-cmd; - }; - p1_smmu_alg_a: iommu@400d0040000 { - compatible = "arm,smmu-v3"; - reg = <0x400 0xd0040000 0x0 0x20000>; - interrupt-parent = <&p1_mbigen_smmu_alg_a>; - interrupts = <733 1>, - <734 1>, - <735 1>; - interrupt-names = "eventq", "gerror", "priq"; - #iommu-cells = <1>; - dma-coherent; - hisilicon,broken-prefetch-cmd; - }; - p1_smmu_alg_b: iommu@408d0040000 { - compatible = "arm,smmu-v3"; - reg = <0x408 0xd0040000 0x0 0x20000>; - interrupt-parent = <&p1_mbigen_smmu_alg_b>; - interrupts = <733 1>, - <734 1>, - <735 1>; - interrupt-names = "eventq", "gerror", "priq"; - #iommu-cells = <1>; - dma-coherent; - hisilicon,broken-prefetch-cmd; - }; soc { compatible = "simple-bus"; @@ -1745,170 +1629,6 @@ 0x0 0 0 4 &mbigen_pcie2_a 671 4>; status = "disabled"; }; - p0_sec_a: crypto@d0000000 { - compatible = "hisilicon,hip07-sec"; - reg = <0x0 0xd0000000 0x0 0x10000>, - <0x0 0xd2000000 0x0 0x10000>, - <0x0 0xd2010000 0x0 0x10000>, - <0x0 0xd2020000 0x0 0x10000>, - <0x0 0xd2030000 0x0 0x10000>, - <0x0 0xd2040000 0x0 0x10000>, - <0x0 0xd2050000 0x0 0x10000>, - <0x0 0xd2060000 0x0 0x10000>, - <0x0 0xd2070000 0x0 0x10000>, - <0x0 0xd2080000 0x0 0x10000>, - <0x0 0xd2090000 0x0 0x10000>, - <0x0 0xd20a0000 0x0 0x10000>, - <0x0 0xd20b0000 0x0 0x10000>, - <0x0 0xd20c0000 0x0 0x10000>, - <0x0 0xd20d0000 0x0 0x10000>, - <0x0 0xd20e0000 0x0 0x10000>, - <0x0 0xd20f0000 0x0 0x10000>, - <0x0 0xd2100000 0x0 0x10000>; - interrupt-parent = <&p0_mbigen_sec_a>; - iommus = <&p0_smmu_alg_a 0x600>; - dma-coherent; - interrupts = <576 4>, - <577 1>, <578 4>, - <579 1>, <580 4>, - <581 1>, <582 4>, - <583 1>, <584 4>, - <585 1>, <586 4>, - <587 1>, <588 4>, - <589 1>, <590 4>, - <591 1>, <592 4>, - <593 1>, <594 4>, - <595 1>, <596 4>, - <597 1>, <598 4>, - <599 1>, <600 4>, - <601 1>, <602 4>, - <603 1>, <604 4>, - <605 1>, <606 4>, - <607 1>, <608 4>; - }; - p0_sec_b: crypto@8d0000000 { - compatible = "hisilicon,hip07-sec"; - reg = <0x8 0xd0000000 0x0 0x10000>, - <0x8 0xd2000000 0x0 0x10000>, - <0x8 0xd2010000 0x0 0x10000>, - <0x8 0xd2020000 0x0 0x10000>, - <0x8 0xd2030000 0x0 0x10000>, - <0x8 0xd2040000 0x0 0x10000>, - <0x8 0xd2050000 0x0 0x10000>, - <0x8 0xd2060000 0x0 0x10000>, - <0x8 0xd2070000 0x0 0x10000>, - <0x8 0xd2080000 0x0 0x10000>, - <0x8 0xd2090000 0x0 0x10000>, - <0x8 0xd20a0000 0x0 0x10000>, - <0x8 0xd20b0000 0x0 0x10000>, - <0x8 0xd20c0000 0x0 0x10000>, - <0x8 0xd20d0000 0x0 0x10000>, - <0x8 0xd20e0000 0x0 0x10000>, - <0x8 0xd20f0000 0x0 0x10000>, - <0x8 0xd2100000 0x0 0x10000>; - interrupt-parent = <&p0_mbigen_sec_b>; - iommus = <&p0_smmu_alg_b 0x600>; - dma-coherent; - interrupts = <576 4>, - <577 1>, <578 4>, - <579 1>, <580 4>, - <581 1>, <582 4>, - <583 1>, <584 4>, - <585 1>, <586 4>, - <587 1>, <588 4>, - <589 1>, <590 4>, - <591 1>, <592 4>, - <593 1>, <594 4>, - <595 1>, <596 4>, - <597 1>, <598 4>, - <599 1>, <600 4>, - <601 1>, <602 4>, - <603 1>, <604 4>, - <605 1>, <606 4>, - <607 1>, <608 4>; - }; - p1_sec_a: crypto@400d0000000 { - compatible = "hisilicon,hip07-sec"; - reg = <0x400 0xd0000000 0x0 0x10000>, - <0x400 0xd2000000 0x0 0x10000>, - <0x400 0xd2010000 0x0 0x10000>, - <0x400 0xd2020000 0x0 0x10000>, - <0x400 0xd2030000 0x0 0x10000>, - <0x400 0xd2040000 0x0 0x10000>, - <0x400 0xd2050000 0x0 0x10000>, - <0x400 0xd2060000 0x0 0x10000>, - <0x400 0xd2070000 0x0 0x10000>, - <0x400 0xd2080000 0x0 0x10000>, - <0x400 0xd2090000 0x0 0x10000>, - <0x400 0xd20a0000 0x0 0x10000>, - <0x400 0xd20b0000 0x0 0x10000>, - <0x400 0xd20c0000 0x0 0x10000>, - <0x400 0xd20d0000 0x0 0x10000>, - <0x400 0xd20e0000 0x0 0x10000>, - <0x400 0xd20f0000 0x0 0x10000>, - <0x400 0xd2100000 0x0 0x10000>; - interrupt-parent = <&p1_mbigen_sec_a>; - iommus = <&p1_smmu_alg_a 0x600>; - dma-coherent; - interrupts = <576 4>, - <577 1>, <578 4>, - <579 1>, <580 4>, - <581 1>, <582 4>, - <583 1>, <584 4>, - <585 1>, <586 4>, - <587 1>, <588 4>, - <589 1>, <590 4>, - <591 1>, <592 4>, - <593 1>, <594 4>, - <595 1>, <596 4>, - <597 1>, <598 4>, - <599 1>, <600 4>, - <601 1>, <602 4>, - <603 1>, <604 4>, - <605 1>, <606 4>, - <607 1>, <608 4>; - }; - p1_sec_b: crypto@408d0000000 { - compatible = "hisilicon,hip07-sec"; - reg = <0x408 0xd0000000 0x0 0x10000>, - <0x408 0xd2000000 0x0 0x10000>, - <0x408 0xd2010000 0x0 0x10000>, - <0x408 0xd2020000 0x0 0x10000>, - <0x408 0xd2030000 0x0 0x10000>, - <0x408 0xd2040000 0x0 0x10000>, - <0x408 0xd2050000 0x0 0x10000>, - <0x408 0xd2060000 0x0 0x10000>, - <0x408 0xd2070000 0x0 0x10000>, - <0x408 0xd2080000 0x0 0x10000>, - <0x408 0xd2090000 0x0 0x10000>, - <0x408 0xd20a0000 0x0 0x10000>, - <0x408 0xd20b0000 0x0 0x10000>, - <0x408 0xd20c0000 0x0 0x10000>, - <0x408 0xd20d0000 0x0 0x10000>, - <0x408 0xd20e0000 0x0 0x10000>, - <0x408 0xd20f0000 0x0 0x10000>, - <0x408 0xd2100000 0x0 0x10000>; - interrupt-parent = <&p1_mbigen_sec_b>; - iommus = <&p1_smmu_alg_b 0x600>; - dma-coherent; - interrupts = <576 4>, - <577 1>, <578 4>, - <579 1>, <580 4>, - <581 1>, <582 4>, - <583 1>, <584 4>, - <585 1>, <586 4>, - <587 1>, <588 4>, - <589 1>, <590 4>, - <591 1>, <592 4>, - <593 1>, <594 4>, - <595 1>, <596 4>, - <597 1>, <598 4>, - <599 1>, <600 4>, - <601 1>, <602 4>, - <603 1>, <604 4>, - <605 1>, <606 4>, - <607 1>, <608 4>; - }; }; }; diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig index aeff08ccbadd..e38a71d96201 100644 --- a/drivers/crypto/hisilicon/Kconfig +++ b/drivers/crypto/hisilicon/Kconfig @@ -1,19 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -config CRYPTO_DEV_HISI_SEC - tristate "Support for Hisilicon SEC crypto block cipher accelerator" - select CRYPTO_SKCIPHER - select CRYPTO_ALGAPI - select CRYPTO_LIB_DES - select SG_SPLIT - depends on ARM64 || COMPILE_TEST - depends on HAS_IOMEM - help - Support for Hisilicon SEC Engine in Hip06 and Hip07 - - To compile this as a module, choose M here: the module - will be called hisi_sec. - config CRYPTO_DEV_HISI_SEC2 tristate "Support for HiSilicon SEC2 crypto block cipher accelerator" select CRYPTO_SKCIPHER diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile index e1068ee9f973..a62965be8633 100644 --- a/drivers/crypto/hisilicon/Makefile +++ b/drivers/crypto/hisilicon/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_HISI_HPRE) += hpre/ -obj-$(CONFIG_CRYPTO_DEV_HISI_SEC) += sec/ obj-$(CONFIG_CRYPTO_DEV_HISI_SEC2) += sec2/ obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += hisi_qm.o hisi_qm-objs = qm.o sgl.o debugfs.o diff --git a/drivers/crypto/hisilicon/sec/Makefile b/drivers/crypto/hisilicon/sec/Makefile deleted file mode 100644 index a55b698e0c27..000000000000 --- a/drivers/crypto/hisilicon/sec/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_CRYPTO_DEV_HISI_SEC) += hisi_sec.o -hisi_sec-y = sec_algs.o sec_drv.o diff --git a/drivers/crypto/hisilicon/sec/sec_algs.c b/drivers/crypto/hisilicon/sec/sec_algs.c deleted file mode 100644 index 85eecbb40e7e..000000000000 --- a/drivers/crypto/hisilicon/sec/sec_algs.c +++ /dev/null @@ -1,1122 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2016-2017 HiSilicon Limited. */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "sec_drv.h" - -#define SEC_MAX_CIPHER_KEY 64 -#define SEC_REQ_LIMIT SZ_32M - -struct sec_c_alg_cfg { - unsigned c_alg : 3; - unsigned c_mode : 3; - unsigned key_len : 2; - unsigned c_width : 2; -}; - -static const struct sec_c_alg_cfg sec_c_alg_cfgs[] = { - [SEC_C_DES_ECB_64] = { - .c_alg = SEC_C_ALG_DES, - .c_mode = SEC_C_MODE_ECB, - .key_len = SEC_KEY_LEN_DES, - }, - [SEC_C_DES_CBC_64] = { - .c_alg = SEC_C_ALG_DES, - .c_mode = SEC_C_MODE_CBC, - .key_len = SEC_KEY_LEN_DES, - }, - [SEC_C_3DES_ECB_192_3KEY] = { - .c_alg = SEC_C_ALG_3DES, - .c_mode = SEC_C_MODE_ECB, - .key_len = SEC_KEY_LEN_3DES_3_KEY, - }, - [SEC_C_3DES_ECB_192_2KEY] = { - .c_alg = SEC_C_ALG_3DES, - .c_mode = SEC_C_MODE_ECB, - .key_len = SEC_KEY_LEN_3DES_2_KEY, - }, - [SEC_C_3DES_CBC_192_3KEY] = { - .c_alg = SEC_C_ALG_3DES, - .c_mode = SEC_C_MODE_CBC, - .key_len = SEC_KEY_LEN_3DES_3_KEY, - }, - [SEC_C_3DES_CBC_192_2KEY] = { - .c_alg = SEC_C_ALG_3DES, - .c_mode = SEC_C_MODE_CBC, - .key_len = SEC_KEY_LEN_3DES_2_KEY, - }, - [SEC_C_AES_ECB_128] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_ECB, - .key_len = SEC_KEY_LEN_AES_128, - }, - [SEC_C_AES_ECB_192] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_ECB, - .key_len = SEC_KEY_LEN_AES_192, - }, - [SEC_C_AES_ECB_256] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_ECB, - .key_len = SEC_KEY_LEN_AES_256, - }, - [SEC_C_AES_CBC_128] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_CBC, - .key_len = SEC_KEY_LEN_AES_128, - }, - [SEC_C_AES_CBC_192] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_CBC, - .key_len = SEC_KEY_LEN_AES_192, - }, - [SEC_C_AES_CBC_256] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_CBC, - .key_len = SEC_KEY_LEN_AES_256, - }, - [SEC_C_AES_CTR_128] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_CTR, - .key_len = SEC_KEY_LEN_AES_128, - }, - [SEC_C_AES_CTR_192] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_CTR, - .key_len = SEC_KEY_LEN_AES_192, - }, - [SEC_C_AES_CTR_256] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_CTR, - .key_len = SEC_KEY_LEN_AES_256, - }, - [SEC_C_AES_XTS_128] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_XTS, - .key_len = SEC_KEY_LEN_AES_128, - }, - [SEC_C_AES_XTS_256] = { - .c_alg = SEC_C_ALG_AES, - .c_mode = SEC_C_MODE_XTS, - .key_len = SEC_KEY_LEN_AES_256, - }, - [SEC_C_NULL] = { - }, -}; - -/* - * Mutex used to ensure safe operation of reference count of - * alg providers - */ -static DEFINE_MUTEX(algs_lock); -static unsigned int active_devs; - -static void sec_alg_skcipher_init_template(struct sec_alg_tfm_ctx *ctx, - struct sec_bd_info *req, - enum sec_cipher_alg alg) -{ - const struct sec_c_alg_cfg *cfg = &sec_c_alg_cfgs[alg]; - - memset(req, 0, sizeof(*req)); - req->w0 |= cfg->c_mode << SEC_BD_W0_C_MODE_S; - req->w1 |= cfg->c_alg << SEC_BD_W1_C_ALG_S; - req->w3 |= cfg->key_len << SEC_BD_W3_C_KEY_LEN_S; - req->w0 |= cfg->c_width << SEC_BD_W0_C_WIDTH_S; - - req->cipher_key_addr_lo = lower_32_bits(ctx->pkey); - req->cipher_key_addr_hi = upper_32_bits(ctx->pkey); -} - -static void sec_alg_skcipher_init_context(struct crypto_skcipher *atfm, - const u8 *key, - unsigned int keylen, - enum sec_cipher_alg alg) -{ - struct crypto_tfm *tfm = crypto_skcipher_tfm(atfm); - struct sec_alg_tfm_ctx *ctx = crypto_tfm_ctx(tfm); - - ctx->cipher_alg = alg; - memcpy(ctx->key, key, keylen); - sec_alg_skcipher_init_template(ctx, &ctx->req_template, - ctx->cipher_alg); -} - -static void sec_free_hw_sgl(struct sec_hw_sgl *hw_sgl, - dma_addr_t psec_sgl, struct sec_dev_info *info) -{ - struct sec_hw_sgl *sgl_current, *sgl_next; - dma_addr_t sgl_next_dma; - - sgl_current = hw_sgl; - while (sgl_current) { - sgl_next = sgl_current->next; - sgl_next_dma = sgl_current->next_sgl; - - dma_pool_free(info->hw_sgl_pool, sgl_current, psec_sgl); - - sgl_current = sgl_next; - psec_sgl = sgl_next_dma; - } -} - -static int sec_alloc_and_fill_hw_sgl(struct sec_hw_sgl **sec_sgl, - dma_addr_t *psec_sgl, - struct scatterlist *sgl, - int count, - struct sec_dev_info *info, - gfp_t gfp) -{ - struct sec_hw_sgl *sgl_current = NULL; - struct sec_hw_sgl *sgl_next; - dma_addr_t sgl_next_dma; - struct scatterlist *sg; - int ret, sge_index, i; - - if (!count) - return -EINVAL; - - for_each_sg(sgl, sg, count, i) { - sge_index = i % SEC_MAX_SGE_NUM; - if (sge_index == 0) { - sgl_next = dma_pool_zalloc(info->hw_sgl_pool, - gfp, &sgl_next_dma); - if (!sgl_next) { - ret = -ENOMEM; - goto err_free_hw_sgls; - } - - if (!sgl_current) { /* First one */ - *psec_sgl = sgl_next_dma; - *sec_sgl = sgl_next; - } else { /* Chained */ - sgl_current->entry_sum_in_sgl = SEC_MAX_SGE_NUM; - sgl_current->next_sgl = sgl_next_dma; - sgl_current->next = sgl_next; - } - sgl_current = sgl_next; - } - sgl_current->sge_entries[sge_index].buf = sg_dma_address(sg); - sgl_current->sge_entries[sge_index].len = sg_dma_len(sg); - sgl_current->data_bytes_in_sgl += sg_dma_len(sg); - } - sgl_current->entry_sum_in_sgl = count % SEC_MAX_SGE_NUM; - sgl_current->next_sgl = 0; - (*sec_sgl)->entry_sum_in_chain = count; - - return 0; - -err_free_hw_sgls: - sec_free_hw_sgl(*sec_sgl, *psec_sgl, info); - *psec_sgl = 0; - - return ret; -} - -static int sec_alg_skcipher_setkey(struct crypto_skcipher *tfm, - const u8 *key, unsigned int keylen, - enum sec_cipher_alg alg) -{ - struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - struct device *dev = ctx->queue->dev_info->dev; - - mutex_lock(&ctx->lock); - if (ctx->key) { - /* rekeying */ - memset(ctx->key, 0, SEC_MAX_CIPHER_KEY); - } else { - /* new key */ - ctx->key = dma_alloc_coherent(dev, SEC_MAX_CIPHER_KEY, - &ctx->pkey, GFP_KERNEL); - if (!ctx->key) { - mutex_unlock(&ctx->lock); - return -ENOMEM; - } - } - mutex_unlock(&ctx->lock); - sec_alg_skcipher_init_context(tfm, key, keylen, alg); - - return 0; -} - -static int sec_alg_skcipher_setkey_aes_ecb(struct crypto_skcipher *tfm, - const u8 *key, unsigned int keylen) -{ - enum sec_cipher_alg alg; - - switch (keylen) { - case AES_KEYSIZE_128: - alg = SEC_C_AES_ECB_128; - break; - case AES_KEYSIZE_192: - alg = SEC_C_AES_ECB_192; - break; - case AES_KEYSIZE_256: - alg = SEC_C_AES_ECB_256; - break; - default: - return -EINVAL; - } - - return sec_alg_skcipher_setkey(tfm, key, keylen, alg); -} - -static int sec_alg_skcipher_setkey_aes_cbc(struct crypto_skcipher *tfm, - const u8 *key, unsigned int keylen) -{ - enum sec_cipher_alg alg; - - switch (keylen) { - case AES_KEYSIZE_128: - alg = SEC_C_AES_CBC_128; - break; - case AES_KEYSIZE_192: - alg = SEC_C_AES_CBC_192; - break; - case AES_KEYSIZE_256: - alg = SEC_C_AES_CBC_256; - break; - default: - return -EINVAL; - } - - return sec_alg_skcipher_setkey(tfm, key, keylen, alg); -} - -static int sec_alg_skcipher_setkey_aes_ctr(struct crypto_skcipher *tfm, - const u8 *key, unsigned int keylen) -{ - enum sec_cipher_alg alg; - - switch (keylen) { - case AES_KEYSIZE_128: - alg = SEC_C_AES_CTR_128; - break; - case AES_KEYSIZE_192: - alg = SEC_C_AES_CTR_192; - break; - case AES_KEYSIZE_256: - alg = SEC_C_AES_CTR_256; - break; - default: - return -EINVAL; - } - - return sec_alg_skcipher_setkey(tfm, key, keylen, alg); -} - -static int sec_alg_skcipher_setkey_aes_xts(struct crypto_skcipher *tfm, - const u8 *key, unsigned int keylen) -{ - enum sec_cipher_alg alg; - int ret; - - ret = xts_verify_key(tfm, key, keylen); - if (ret) - return ret; - - switch (keylen) { - case AES_KEYSIZE_128 * 2: - alg = SEC_C_AES_XTS_128; - break; - case AES_KEYSIZE_256 * 2: - alg = SEC_C_AES_XTS_256; - break; - default: - return -EINVAL; - } - - return sec_alg_skcipher_setkey(tfm, key, keylen, alg); -} - -static int sec_alg_skcipher_setkey_des_ecb(struct crypto_skcipher *tfm, - const u8 *key, unsigned int keylen) -{ - return verify_skcipher_des_key(tfm, key) ?: - sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_ECB_64); -} - -static int sec_alg_skcipher_setkey_des_cbc(struct crypto_skcipher *tfm, - const u8 *key, unsigned int keylen) -{ - return verify_skcipher_des_key(tfm, key) ?: - sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_CBC_64); -} - -static int sec_alg_skcipher_setkey_3des_ecb(struct crypto_skcipher *tfm, - const u8 *key, unsigned int keylen) -{ - return verify_skcipher_des3_key(tfm, key) ?: - sec_alg_skcipher_setkey(tfm, key, keylen, - SEC_C_3DES_ECB_192_3KEY); -} - -static int sec_alg_skcipher_setkey_3des_cbc(struct crypto_skcipher *tfm, - const u8 *key, unsigned int keylen) -{ - return verify_skcipher_des3_key(tfm, key) ?: - sec_alg_skcipher_setkey(tfm, key, keylen, - SEC_C_3DES_CBC_192_3KEY); -} - -static void sec_alg_free_el(struct sec_request_el *el, - struct sec_dev_info *info) -{ - sec_free_hw_sgl(el->out, el->dma_out, info); - sec_free_hw_sgl(el->in, el->dma_in, info); - kfree(el->sgl_in); - kfree(el->sgl_out); - kfree(el); -} - -/* queuelock must be held */ -static int sec_send_request(struct sec_request *sec_req, struct sec_queue *queue) -{ - struct sec_request_el *el, *temp; - int ret = 0; - - mutex_lock(&sec_req->lock); - list_for_each_entry_safe(el, temp, &sec_req->elements, head) { - /* - * Add to hardware queue only under following circumstances - * 1) Software and hardware queue empty so no chain dependencies - * 2) No dependencies as new IV - (check software queue empty - * to maintain order) - * 3) No dependencies because the mode does no chaining. - * - * In other cases first insert onto the software queue which - * is then emptied as requests complete - */ - if (!queue->havesoftqueue || - (kfifo_is_empty(&queue->softqueue) && - sec_queue_empty(queue))) { - ret = sec_queue_send(queue, &el->req, sec_req); - if (ret == -EAGAIN) { - /* Wait unti we can send then try again */ - /* DEAD if here - should not happen */ - ret = -EBUSY; - goto err_unlock; - } - } else { - kfifo_put(&queue->softqueue, el); - } - } -err_unlock: - mutex_unlock(&sec_req->lock); - - return ret; -} - -static void sec_skcipher_alg_callback(struct sec_bd_info *sec_resp, - struct crypto_async_request *req_base) -{ - struct skcipher_request *skreq = container_of(req_base, - struct skcipher_request, - base); - struct sec_request *sec_req = skcipher_request_ctx(skreq); - struct sec_request *backlog_req; - struct sec_request_el *sec_req_el, *nextrequest; - struct sec_alg_tfm_ctx *ctx = sec_req->tfm_ctx; - struct crypto_skcipher *atfm = crypto_skcipher_reqtfm(skreq); - struct device *dev = ctx->queue->dev_info->dev; - int icv_or_skey_en, ret; - bool done; - - sec_req_el = list_first_entry(&sec_req->elements, struct sec_request_el, - head); - icv_or_skey_en = (sec_resp->w0 & SEC_BD_W0_ICV_OR_SKEY_EN_M) >> - SEC_BD_W0_ICV_OR_SKEY_EN_S; - if (sec_resp->w1 & SEC_BD_W1_BD_INVALID || icv_or_skey_en == 3) { - dev_err(dev, "Got an invalid answer %lu %d\n", - sec_resp->w1 & SEC_BD_W1_BD_INVALID, - icv_or_skey_en); - sec_req->err = -EINVAL; - /* - * We need to muddle on to avoid getting stuck with elements - * on the queue. Error will be reported so requester so - * it should be able to handle appropriately. - */ - } - - spin_lock_bh(&ctx->queue->queuelock); - /* Put the IV in place for chained cases */ - switch (ctx->cipher_alg) { - case SEC_C_AES_CBC_128: - case SEC_C_AES_CBC_192: - case SEC_C_AES_CBC_256: - if (sec_req_el->req.w0 & SEC_BD_W0_DE) - sg_pcopy_to_buffer(sec_req_el->sgl_out, - sg_nents(sec_req_el->sgl_out), - skreq->iv, - crypto_skcipher_ivsize(atfm), - sec_req_el->el_length - - crypto_skcipher_ivsize(atfm)); - else - sg_pcopy_to_buffer(sec_req_el->sgl_in, - sg_nents(sec_req_el->sgl_in), - skreq->iv, - crypto_skcipher_ivsize(atfm), - sec_req_el->el_length - - crypto_skcipher_ivsize(atfm)); - /* No need to sync to the device as coherent DMA */ - break; - case SEC_C_AES_CTR_128: - case SEC_C_AES_CTR_192: - case SEC_C_AES_CTR_256: - crypto_inc(skreq->iv, 16); - break; - default: - /* Do not update */ - break; - } - - if (ctx->queue->havesoftqueue && - !kfifo_is_empty(&ctx->queue->softqueue) && - sec_queue_empty(ctx->queue)) { - ret = kfifo_get(&ctx->queue->softqueue, &nextrequest); - if (ret <= 0) - dev_err(dev, - "Error getting next element from kfifo %d\n", - ret); - else - /* We know there is space so this cannot fail */ - sec_queue_send(ctx->queue, &nextrequest->req, - nextrequest->sec_req); - } else if (!list_empty(&ctx->backlog)) { - /* Need to verify there is room first */ - backlog_req = list_first_entry(&ctx->backlog, - typeof(*backlog_req), - backlog_head); - if (sec_queue_can_enqueue(ctx->queue, - backlog_req->num_elements) || - (ctx->queue->havesoftqueue && - kfifo_avail(&ctx->queue->softqueue) > - backlog_req->num_elements)) { - sec_send_request(backlog_req, ctx->queue); - crypto_request_complete(backlog_req->req_base, - -EINPROGRESS); - list_del(&backlog_req->backlog_head); - } - } - spin_unlock_bh(&ctx->queue->queuelock); - - mutex_lock(&sec_req->lock); - list_del(&sec_req_el->head); - mutex_unlock(&sec_req->lock); - sec_alg_free_el(sec_req_el, ctx->queue->dev_info); - - /* - * Request is done. - * The dance is needed as the lock is freed in the completion - */ - mutex_lock(&sec_req->lock); - done = list_empty(&sec_req->elements); - mutex_unlock(&sec_req->lock); - if (done) { - if (crypto_skcipher_ivsize(atfm)) { - dma_unmap_single(dev, sec_req->dma_iv, - crypto_skcipher_ivsize(atfm), - DMA_TO_DEVICE); - } - dma_unmap_sg(dev, skreq->src, sec_req->len_in, - DMA_BIDIRECTIONAL); - if (skreq->src != skreq->dst) - dma_unmap_sg(dev, skreq->dst, sec_req->len_out, - DMA_BIDIRECTIONAL); - skcipher_request_complete(skreq, sec_req->err); - } -} - -void sec_alg_callback(struct sec_bd_info *resp, void *shadow) -{ - struct sec_request *sec_req = shadow; - - sec_req->cb(resp, sec_req->req_base); -} - -static int sec_alg_alloc_and_calc_split_sizes(int length, size_t **split_sizes, - int *steps, gfp_t gfp) -{ - size_t *sizes; - int i; - - /* Split into suitable sized blocks */ - *steps = roundup(length, SEC_REQ_LIMIT) / SEC_REQ_LIMIT; - sizes = kzalloc_objs(*sizes, *steps, gfp); - if (!sizes) - return -ENOMEM; - - for (i = 0; i < *steps - 1; i++) - sizes[i] = SEC_REQ_LIMIT; - sizes[*steps - 1] = length - SEC_REQ_LIMIT * (*steps - 1); - *split_sizes = sizes; - - return 0; -} - -static int sec_map_and_split_sg(struct scatterlist *sgl, size_t *split_sizes, - int steps, struct scatterlist ***splits, - int **splits_nents, - int sgl_len_in, - struct device *dev, gfp_t gfp) -{ - int ret, count; - - count = dma_map_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL); - if (!count) - return -EINVAL; - - *splits = kzalloc_objs(struct scatterlist *, steps, gfp); - if (!*splits) { - ret = -ENOMEM; - goto err_unmap_sg; - } - *splits_nents = kzalloc_objs(int, steps, gfp); - if (!*splits_nents) { - ret = -ENOMEM; - goto err_free_splits; - } - - /* output the scatter list before and after this */ - ret = sg_split(sgl, count, 0, steps, split_sizes, - *splits, *splits_nents, gfp); - if (ret) { - ret = -ENOMEM; - goto err_free_splits_nents; - } - - return 0; - -err_free_splits_nents: - kfree(*splits_nents); -err_free_splits: - kfree(*splits); -err_unmap_sg: - dma_unmap_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL); - - return ret; -} - -/* - * Reverses the sec_map_and_split_sg call for messages not yet added to - * the queues. - */ -static void sec_unmap_sg_on_err(struct scatterlist *sgl, int steps, - struct scatterlist **splits, int *splits_nents, - int sgl_len_in, struct device *dev) -{ - int i; - - for (i = 0; i < steps; i++) - kfree(splits[i]); - kfree(splits_nents); - kfree(splits); - - dma_unmap_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL); -} - -static struct sec_request_el -*sec_alg_alloc_and_fill_el(struct sec_bd_info *template, int encrypt, - int el_size, bool different_dest, - struct scatterlist *sgl_in, int n_ents_in, - struct scatterlist *sgl_out, int n_ents_out, - struct sec_dev_info *info, gfp_t gfp) -{ - struct sec_request_el *el; - struct sec_bd_info *req; - int ret; - - el = kzalloc_obj(*el, gfp); - if (!el) - return ERR_PTR(-ENOMEM); - el->el_length = el_size; - req = &el->req; - memcpy(req, template, sizeof(*req)); - - req->w0 &= ~SEC_BD_W0_CIPHER_M; - if (encrypt) - req->w0 |= SEC_CIPHER_ENCRYPT << SEC_BD_W0_CIPHER_S; - else - req->w0 |= SEC_CIPHER_DECRYPT << SEC_BD_W0_CIPHER_S; - - req->w0 &= ~SEC_BD_W0_C_GRAN_SIZE_19_16_M; - req->w0 |= ((el_size >> 16) << SEC_BD_W0_C_GRAN_SIZE_19_16_S) & - SEC_BD_W0_C_GRAN_SIZE_19_16_M; - - req->w0 &= ~SEC_BD_W0_C_GRAN_SIZE_21_20_M; - req->w0 |= ((el_size >> 20) << SEC_BD_W0_C_GRAN_SIZE_21_20_S) & - SEC_BD_W0_C_GRAN_SIZE_21_20_M; - - /* Writing whole u32 so no need to take care of masking */ - req->w2 = ((1 << SEC_BD_W2_GRAN_NUM_S) & SEC_BD_W2_GRAN_NUM_M) | - ((el_size << SEC_BD_W2_C_GRAN_SIZE_15_0_S) & - SEC_BD_W2_C_GRAN_SIZE_15_0_M); - - req->w3 &= ~SEC_BD_W3_CIPHER_LEN_OFFSET_M; - req->w1 |= SEC_BD_W1_ADDR_TYPE; - - el->sgl_in = sgl_in; - - ret = sec_alloc_and_fill_hw_sgl(&el->in, &el->dma_in, el->sgl_in, - n_ents_in, info, gfp); - if (ret) - goto err_free_el; - - req->data_addr_lo = lower_32_bits(el->dma_in); - req->data_addr_hi = upper_32_bits(el->dma_in); - - if (different_dest) { - el->sgl_out = sgl_out; - ret = sec_alloc_and_fill_hw_sgl(&el->out, &el->dma_out, - el->sgl_out, - n_ents_out, info, gfp); - if (ret) - goto err_free_hw_sgl_in; - - req->w0 |= SEC_BD_W0_DE; - req->cipher_destin_addr_lo = lower_32_bits(el->dma_out); - req->cipher_destin_addr_hi = upper_32_bits(el->dma_out); - - } else { - req->w0 &= ~SEC_BD_W0_DE; - req->cipher_destin_addr_lo = lower_32_bits(el->dma_in); - req->cipher_destin_addr_hi = upper_32_bits(el->dma_in); - } - - return el; - -err_free_hw_sgl_in: - sec_free_hw_sgl(el->in, el->dma_in, info); -err_free_el: - kfree(el); - - return ERR_PTR(ret); -} - -static int sec_alg_skcipher_crypto(struct skcipher_request *skreq, - bool encrypt) -{ - struct crypto_skcipher *atfm = crypto_skcipher_reqtfm(skreq); - struct crypto_tfm *tfm = crypto_skcipher_tfm(atfm); - struct sec_alg_tfm_ctx *ctx = crypto_tfm_ctx(tfm); - struct sec_queue *queue = ctx->queue; - struct sec_request *sec_req = skcipher_request_ctx(skreq); - struct sec_dev_info *info = queue->dev_info; - int i, ret, steps; - size_t *split_sizes; - struct scatterlist **splits_in; - struct scatterlist **splits_out = NULL; - int *splits_in_nents; - int *splits_out_nents = NULL; - struct sec_request_el *el, *temp; - bool split = skreq->src != skreq->dst; - gfp_t gfp = skreq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; - - mutex_init(&sec_req->lock); - sec_req->req_base = &skreq->base; - sec_req->err = 0; - /* SGL mapping out here to allow us to break it up as necessary */ - sec_req->len_in = sg_nents(skreq->src); - - ret = sec_alg_alloc_and_calc_split_sizes(skreq->cryptlen, &split_sizes, - &steps, gfp); - if (ret) - return ret; - sec_req->num_elements = steps; - ret = sec_map_and_split_sg(skreq->src, split_sizes, steps, &splits_in, - &splits_in_nents, sec_req->len_in, - info->dev, gfp); - if (ret) - goto err_free_split_sizes; - - if (split) { - sec_req->len_out = sg_nents(skreq->dst); - ret = sec_map_and_split_sg(skreq->dst, split_sizes, steps, - &splits_out, &splits_out_nents, - sec_req->len_out, info->dev, gfp); - if (ret) - goto err_unmap_in_sg; - } - /* Shared info stored in seq_req - applies to all BDs */ - sec_req->tfm_ctx = ctx; - sec_req->cb = sec_skcipher_alg_callback; - INIT_LIST_HEAD(&sec_req->elements); - - /* - * Future optimization. - * In the chaining case we can't use a dma pool bounce buffer - * but in the case where we know there is no chaining we can - */ - if (crypto_skcipher_ivsize(atfm)) { - sec_req->dma_iv = dma_map_single(info->dev, skreq->iv, - crypto_skcipher_ivsize(atfm), - DMA_TO_DEVICE); - if (dma_mapping_error(info->dev, sec_req->dma_iv)) { - ret = -ENOMEM; - goto err_unmap_out_sg; - } - } - - /* Set them all up then queue - cleaner error handling. */ - for (i = 0; i < steps; i++) { - el = sec_alg_alloc_and_fill_el(&ctx->req_template, - encrypt ? 1 : 0, - split_sizes[i], - skreq->src != skreq->dst, - splits_in[i], splits_in_nents[i], - split ? splits_out[i] : NULL, - split ? splits_out_nents[i] : 0, - info, gfp); - if (IS_ERR(el)) { - ret = PTR_ERR(el); - goto err_free_elements; - } - el->req.cipher_iv_addr_lo = lower_32_bits(sec_req->dma_iv); - el->req.cipher_iv_addr_hi = upper_32_bits(sec_req->dma_iv); - el->sec_req = sec_req; - list_add_tail(&el->head, &sec_req->elements); - } - - /* - * Only attempt to queue if the whole lot can fit in the queue - - * we can't successfully cleanup after a partial queing so this - * must succeed or fail atomically. - * - * Big hammer test of both software and hardware queues - could be - * more refined but this is unlikely to happen so no need. - */ - - /* Grab a big lock for a long time to avoid concurrency issues */ - spin_lock_bh(&queue->queuelock); - - /* - * Can go on to queue if we have space in either: - * 1) The hardware queue and no software queue - * 2) The software queue - * AND there is nothing in the backlog. If there is backlog we - * have to only queue to the backlog queue and return busy. - */ - if ((!sec_queue_can_enqueue(queue, steps) && - (!queue->havesoftqueue || - kfifo_avail(&queue->softqueue) > steps)) || - !list_empty(&ctx->backlog)) { - ret = -EBUSY; - if ((skreq->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { - list_add_tail(&sec_req->backlog_head, &ctx->backlog); - spin_unlock_bh(&queue->queuelock); - goto out; - } - - spin_unlock_bh(&queue->queuelock); - goto err_free_elements; - } - ret = sec_send_request(sec_req, queue); - spin_unlock_bh(&queue->queuelock); - if (ret) - goto err_free_elements; - - ret = -EINPROGRESS; -out: - /* Cleanup - all elements in pointer arrays have been copied */ - kfree(splits_in_nents); - kfree(splits_in); - kfree(splits_out_nents); - kfree(splits_out); - kfree(split_sizes); - return ret; - -err_free_elements: - list_for_each_entry_safe(el, temp, &sec_req->elements, head) { - list_del(&el->head); - sec_alg_free_el(el, info); - } - if (crypto_skcipher_ivsize(atfm)) - dma_unmap_single(info->dev, sec_req->dma_iv, - crypto_skcipher_ivsize(atfm), - DMA_TO_DEVICE); -err_unmap_out_sg: - if (split) - sec_unmap_sg_on_err(skreq->dst, steps, splits_out, - splits_out_nents, sec_req->len_out, - info->dev); -err_unmap_in_sg: - sec_unmap_sg_on_err(skreq->src, steps, splits_in, splits_in_nents, - sec_req->len_in, info->dev); -err_free_split_sizes: - kfree(split_sizes); - - return ret; -} - -static int sec_alg_skcipher_encrypt(struct skcipher_request *req) -{ - return sec_alg_skcipher_crypto(req, true); -} - -static int sec_alg_skcipher_decrypt(struct skcipher_request *req) -{ - return sec_alg_skcipher_crypto(req, false); -} - -static int sec_alg_skcipher_init(struct crypto_skcipher *tfm) -{ - struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - - mutex_init(&ctx->lock); - INIT_LIST_HEAD(&ctx->backlog); - crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_request)); - - ctx->queue = sec_queue_alloc_start_safe(); - if (IS_ERR(ctx->queue)) - return PTR_ERR(ctx->queue); - - spin_lock_init(&ctx->queue->queuelock); - ctx->queue->havesoftqueue = false; - - return 0; -} - -static void sec_alg_skcipher_exit(struct crypto_skcipher *tfm) -{ - struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - struct device *dev = ctx->queue->dev_info->dev; - - if (ctx->key) { - memzero_explicit(ctx->key, SEC_MAX_CIPHER_KEY); - dma_free_coherent(dev, SEC_MAX_CIPHER_KEY, ctx->key, - ctx->pkey); - } - sec_queue_stop_release(ctx->queue); -} - -static int sec_alg_skcipher_init_with_queue(struct crypto_skcipher *tfm) -{ - struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - int ret; - - ret = sec_alg_skcipher_init(tfm); - if (ret) - return ret; - - INIT_KFIFO(ctx->queue->softqueue); - ret = kfifo_alloc(&ctx->queue->softqueue, 512, GFP_KERNEL); - if (ret) { - sec_alg_skcipher_exit(tfm); - return ret; - } - ctx->queue->havesoftqueue = true; - - return 0; -} - -static void sec_alg_skcipher_exit_with_queue(struct crypto_skcipher *tfm) -{ - struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - - kfifo_free(&ctx->queue->softqueue); - sec_alg_skcipher_exit(tfm); -} - -static struct skcipher_alg sec_algs[] = { - { - .base = { - .cra_name = "ecb(aes)", - .cra_driver_name = "hisi_sec_aes_ecb", - .cra_priority = 4001, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - }, - .init = sec_alg_skcipher_init, - .exit = sec_alg_skcipher_exit, - .setkey = sec_alg_skcipher_setkey_aes_ecb, - .decrypt = sec_alg_skcipher_decrypt, - .encrypt = sec_alg_skcipher_encrypt, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = 0, - }, { - .base = { - .cra_name = "cbc(aes)", - .cra_driver_name = "hisi_sec_aes_cbc", - .cra_priority = 4001, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - }, - .init = sec_alg_skcipher_init_with_queue, - .exit = sec_alg_skcipher_exit_with_queue, - .setkey = sec_alg_skcipher_setkey_aes_cbc, - .decrypt = sec_alg_skcipher_decrypt, - .encrypt = sec_alg_skcipher_encrypt, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - }, { - .base = { - .cra_name = "ctr(aes)", - .cra_driver_name = "hisi_sec_aes_ctr", - .cra_priority = 4001, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - }, - .init = sec_alg_skcipher_init_with_queue, - .exit = sec_alg_skcipher_exit_with_queue, - .setkey = sec_alg_skcipher_setkey_aes_ctr, - .decrypt = sec_alg_skcipher_decrypt, - .encrypt = sec_alg_skcipher_encrypt, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - }, { - .base = { - .cra_name = "xts(aes)", - .cra_driver_name = "hisi_sec_aes_xts", - .cra_priority = 4001, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - }, - .init = sec_alg_skcipher_init, - .exit = sec_alg_skcipher_exit, - .setkey = sec_alg_skcipher_setkey_aes_xts, - .decrypt = sec_alg_skcipher_decrypt, - .encrypt = sec_alg_skcipher_encrypt, - .min_keysize = 2 * AES_MIN_KEY_SIZE, - .max_keysize = 2 * AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - }, { - /* Unable to find any test vectors so untested */ - .base = { - .cra_name = "ecb(des)", - .cra_driver_name = "hisi_sec_des_ecb", - .cra_priority = 4001, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - }, - .init = sec_alg_skcipher_init, - .exit = sec_alg_skcipher_exit, - .setkey = sec_alg_skcipher_setkey_des_ecb, - .decrypt = sec_alg_skcipher_decrypt, - .encrypt = sec_alg_skcipher_encrypt, - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - .ivsize = 0, - }, { - .base = { - .cra_name = "cbc(des)", - .cra_driver_name = "hisi_sec_des_cbc", - .cra_priority = 4001, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - }, - .init = sec_alg_skcipher_init_with_queue, - .exit = sec_alg_skcipher_exit_with_queue, - .setkey = sec_alg_skcipher_setkey_des_cbc, - .decrypt = sec_alg_skcipher_decrypt, - .encrypt = sec_alg_skcipher_encrypt, - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - .ivsize = DES_BLOCK_SIZE, - }, { - .base = { - .cra_name = "cbc(des3_ede)", - .cra_driver_name = "hisi_sec_3des_cbc", - .cra_priority = 4001, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = DES3_EDE_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - }, - .init = sec_alg_skcipher_init_with_queue, - .exit = sec_alg_skcipher_exit_with_queue, - .setkey = sec_alg_skcipher_setkey_3des_cbc, - .decrypt = sec_alg_skcipher_decrypt, - .encrypt = sec_alg_skcipher_encrypt, - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - }, { - .base = { - .cra_name = "ecb(des3_ede)", - .cra_driver_name = "hisi_sec_3des_ecb", - .cra_priority = 4001, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = DES3_EDE_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - }, - .init = sec_alg_skcipher_init, - .exit = sec_alg_skcipher_exit, - .setkey = sec_alg_skcipher_setkey_3des_ecb, - .decrypt = sec_alg_skcipher_decrypt, - .encrypt = sec_alg_skcipher_encrypt, - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - .ivsize = 0, - } -}; - -int sec_algs_register(void) -{ - int ret = 0; - - mutex_lock(&algs_lock); - if (++active_devs != 1) - goto unlock; - - ret = crypto_register_skciphers(sec_algs, ARRAY_SIZE(sec_algs)); - if (ret) - --active_devs; -unlock: - mutex_unlock(&algs_lock); - - return ret; -} - -void sec_algs_unregister(void) -{ - mutex_lock(&algs_lock); - if (--active_devs != 0) - goto unlock; - crypto_unregister_skciphers(sec_algs, ARRAY_SIZE(sec_algs)); - -unlock: - mutex_unlock(&algs_lock); -} diff --git a/drivers/crypto/hisilicon/sec/sec_drv.c b/drivers/crypto/hisilicon/sec/sec_drv.c deleted file mode 100644 index 2514a5e1f9b4..000000000000 --- a/drivers/crypto/hisilicon/sec/sec_drv.c +++ /dev/null @@ -1,1307 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Driver for the HiSilicon SEC units found on Hip06 Hip07 - * - * Copyright (c) 2016-2017 HiSilicon Limited. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sec_drv.h" - -#define SEC_QUEUE_AR_FROCE_ALLOC 0 -#define SEC_QUEUE_AR_FROCE_NOALLOC 1 -#define SEC_QUEUE_AR_FROCE_DIS 2 - -#define SEC_QUEUE_AW_FROCE_ALLOC 0 -#define SEC_QUEUE_AW_FROCE_NOALLOC 1 -#define SEC_QUEUE_AW_FROCE_DIS 2 - -/* SEC_ALGSUB registers */ -#define SEC_ALGSUB_CLK_EN_REG 0x03b8 -#define SEC_ALGSUB_CLK_DIS_REG 0x03bc -#define SEC_ALGSUB_CLK_ST_REG 0x535c -#define SEC_ALGSUB_RST_REQ_REG 0x0aa8 -#define SEC_ALGSUB_RST_DREQ_REG 0x0aac -#define SEC_ALGSUB_RST_ST_REG 0x5a54 -#define SEC_ALGSUB_RST_ST_IS_RST BIT(0) - -#define SEC_ALGSUB_BUILD_RST_REQ_REG 0x0ab8 -#define SEC_ALGSUB_BUILD_RST_DREQ_REG 0x0abc -#define SEC_ALGSUB_BUILD_RST_ST_REG 0x5a5c -#define SEC_ALGSUB_BUILD_RST_ST_IS_RST BIT(0) - -#define SEC_SAA_BASE 0x00001000UL - -/* SEC_SAA registers */ -#define SEC_SAA_CTRL_REG(x) ((x) * SEC_SAA_ADDR_SIZE) -#define SEC_SAA_CTRL_GET_QM_EN BIT(0) - -#define SEC_ST_INTMSK1_REG 0x0200 -#define SEC_ST_RINT1_REG 0x0400 -#define SEC_ST_INTSTS1_REG 0x0600 -#define SEC_BD_MNG_STAT_REG 0x0800 -#define SEC_PARSING_STAT_REG 0x0804 -#define SEC_LOAD_TIME_OUT_CNT_REG 0x0808 -#define SEC_CORE_WORK_TIME_OUT_CNT_REG 0x080c -#define SEC_BACK_TIME_OUT_CNT_REG 0x0810 -#define SEC_BD1_PARSING_RD_TIME_OUT_CNT_REG 0x0814 -#define SEC_BD1_PARSING_WR_TIME_OUT_CNT_REG 0x0818 -#define SEC_BD2_PARSING_RD_TIME_OUT_CNT_REG 0x081c -#define SEC_BD2_PARSING_WR_TIME_OUT_CNT_REG 0x0820 -#define SEC_SAA_ACC_REG 0x083c -#define SEC_BD_NUM_CNT_IN_SEC_REG 0x0858 -#define SEC_LOAD_WORK_TIME_CNT_REG 0x0860 -#define SEC_CORE_WORK_WORK_TIME_CNT_REG 0x0864 -#define SEC_BACK_WORK_TIME_CNT_REG 0x0868 -#define SEC_SAA_IDLE_TIME_CNT_REG 0x086c -#define SEC_SAA_CLK_CNT_REG 0x0870 - -/* SEC_COMMON registers */ -#define SEC_CLK_EN_REG 0x0000 -#define SEC_CTRL_REG 0x0004 - -#define SEC_COMMON_CNT_CLR_CE_REG 0x0008 -#define SEC_COMMON_CNT_CLR_CE_CLEAR BIT(0) -#define SEC_COMMON_CNT_CLR_CE_SNAP_EN BIT(1) - -#define SEC_SECURE_CTRL_REG 0x000c -#define SEC_AXI_CACHE_CFG_REG 0x0010 -#define SEC_AXI_QOS_CFG_REG 0x0014 -#define SEC_IPV4_MASK_TABLE_REG 0x0020 -#define SEC_IPV6_MASK_TABLE_X_REG(x) (0x0024 + (x) * 4) -#define SEC_FSM_MAX_CNT_REG 0x0064 - -#define SEC_CTRL2_REG 0x0068 -#define SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_M GENMASK(3, 0) -#define SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_S 0 -#define SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_M GENMASK(6, 4) -#define SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_S 4 -#define SEC_CTRL2_CLK_GATE_EN BIT(7) -#define SEC_CTRL2_ENDIAN_BD BIT(8) -#define SEC_CTRL2_ENDIAN_BD_TYPE BIT(9) - -#define SEC_CNT_PRECISION_CFG_REG 0x006c -#define SEC_DEBUG_BD_CFG_REG 0x0070 -#define SEC_DEBUG_BD_CFG_WB_NORMAL BIT(0) -#define SEC_DEBUG_BD_CFG_WB_EN BIT(1) - -#define SEC_Q_SIGHT_SEL 0x0074 -#define SEC_Q_SIGHT_HIS_CLR 0x0078 -#define SEC_Q_VMID_CFG_REG(q) (0x0100 + (q) * 4) -#define SEC_Q_WEIGHT_CFG_REG(q) (0x200 + (q) * 4) -#define SEC_STAT_CLR_REG 0x0a00 -#define SEC_SAA_IDLE_CNT_CLR_REG 0x0a04 -#define SEC_QM_CPL_Q_IDBUF_DFX_CFG_REG 0x0b00 -#define SEC_QM_CPL_Q_IDBUF_DFX_RESULT_REG 0x0b04 -#define SEC_QM_BD_DFX_CFG_REG 0x0b08 -#define SEC_QM_BD_DFX_RESULT_REG 0x0b0c -#define SEC_QM_BDID_DFX_RESULT_REG 0x0b10 -#define SEC_QM_BD_DFIFO_STATUS_REG 0x0b14 -#define SEC_QM_BD_DFX_CFG2_REG 0x0b1c -#define SEC_QM_BD_DFX_RESULT2_REG 0x0b20 -#define SEC_QM_BD_IDFIFO_STATUS_REG 0x0b18 -#define SEC_QM_BD_DFIFO_STATUS2_REG 0x0b28 -#define SEC_QM_BD_IDFIFO_STATUS2_REG 0x0b2c - -#define SEC_HASH_IPV4_MASK 0xfff00000 -#define SEC_MAX_SAA_NUM 0xa -#define SEC_SAA_ADDR_SIZE 0x1000 - -#define SEC_Q_INIT_REG 0x0 -#define SEC_Q_INIT_WO_STAT_CLEAR 0x2 -#define SEC_Q_INIT_AND_STAT_CLEAR 0x3 - -#define SEC_Q_CFG_REG 0x8 -#define SEC_Q_CFG_REORDER BIT(0) - -#define SEC_Q_PROC_NUM_CFG_REG 0x10 -#define SEC_QUEUE_ENB_REG 0x18 - -#define SEC_Q_DEPTH_CFG_REG 0x50 -#define SEC_Q_DEPTH_CFG_DEPTH_M GENMASK(11, 0) -#define SEC_Q_DEPTH_CFG_DEPTH_S 0 - -#define SEC_Q_BASE_HADDR_REG 0x54 -#define SEC_Q_BASE_LADDR_REG 0x58 -#define SEC_Q_WR_PTR_REG 0x5c -#define SEC_Q_OUTORDER_BASE_HADDR_REG 0x60 -#define SEC_Q_OUTORDER_BASE_LADDR_REG 0x64 -#define SEC_Q_OUTORDER_RD_PTR_REG 0x68 -#define SEC_Q_OT_TH_REG 0x6c - -#define SEC_Q_ARUSER_CFG_REG 0x70 -#define SEC_Q_ARUSER_CFG_FA BIT(0) -#define SEC_Q_ARUSER_CFG_FNA BIT(1) -#define SEC_Q_ARUSER_CFG_RINVLD BIT(2) -#define SEC_Q_ARUSER_CFG_PKG BIT(3) - -#define SEC_Q_AWUSER_CFG_REG 0x74 -#define SEC_Q_AWUSER_CFG_FA BIT(0) -#define SEC_Q_AWUSER_CFG_FNA BIT(1) -#define SEC_Q_AWUSER_CFG_PKG BIT(2) - -#define SEC_Q_ERR_BASE_HADDR_REG 0x7c -#define SEC_Q_ERR_BASE_LADDR_REG 0x80 -#define SEC_Q_CFG_VF_NUM_REG 0x84 -#define SEC_Q_SOFT_PROC_PTR_REG 0x88 -#define SEC_Q_FAIL_INT_MSK_REG 0x300 -#define SEC_Q_FLOW_INT_MKS_REG 0x304 -#define SEC_Q_FAIL_RINT_REG 0x400 -#define SEC_Q_FLOW_RINT_REG 0x404 -#define SEC_Q_FAIL_INT_STATUS_REG 0x500 -#define SEC_Q_FLOW_INT_STATUS_REG 0x504 -#define SEC_Q_STATUS_REG 0x600 -#define SEC_Q_RD_PTR_REG 0x604 -#define SEC_Q_PRO_PTR_REG 0x608 -#define SEC_Q_OUTORDER_WR_PTR_REG 0x60c -#define SEC_Q_OT_CNT_STATUS_REG 0x610 -#define SEC_Q_INORDER_BD_NUM_ST_REG 0x650 -#define SEC_Q_INORDER_GET_FLAG_ST_REG 0x654 -#define SEC_Q_INORDER_ADD_FLAG_ST_REG 0x658 -#define SEC_Q_INORDER_TASK_INT_NUM_LEFT_ST_REG 0x65c -#define SEC_Q_RD_DONE_PTR_REG 0x660 -#define SEC_Q_CPL_Q_BD_NUM_ST_REG 0x700 -#define SEC_Q_CPL_Q_PTR_ST_REG 0x704 -#define SEC_Q_CPL_Q_H_ADDR_ST_REG 0x708 -#define SEC_Q_CPL_Q_L_ADDR_ST_REG 0x70c -#define SEC_Q_CPL_TASK_INT_NUM_LEFT_ST_REG 0x710 -#define SEC_Q_WRR_ID_CHECK_REG 0x714 -#define SEC_Q_CPLQ_FULL_CHECK_REG 0x718 -#define SEC_Q_SUCCESS_BD_CNT_REG 0x800 -#define SEC_Q_FAIL_BD_CNT_REG 0x804 -#define SEC_Q_GET_BD_CNT_REG 0x808 -#define SEC_Q_IVLD_CNT_REG 0x80c -#define SEC_Q_BD_PROC_GET_CNT_REG 0x810 -#define SEC_Q_BD_PROC_DONE_CNT_REG 0x814 -#define SEC_Q_LAT_CLR_REG 0x850 -#define SEC_Q_PKT_LAT_MAX_REG 0x854 -#define SEC_Q_PKT_LAT_AVG_REG 0x858 -#define SEC_Q_PKT_LAT_MIN_REG 0x85c -#define SEC_Q_ID_CLR_CFG_REG 0x900 -#define SEC_Q_1ST_BD_ERR_ID_REG 0x904 -#define SEC_Q_1ST_AUTH_FAIL_ID_REG 0x908 -#define SEC_Q_1ST_RD_ERR_ID_REG 0x90c -#define SEC_Q_1ST_ECC2_ERR_ID_REG 0x910 -#define SEC_Q_1ST_IVLD_ID_REG 0x914 -#define SEC_Q_1ST_BD_WR_ERR_ID_REG 0x918 -#define SEC_Q_1ST_ERR_BD_WR_ERR_ID_REG 0x91c -#define SEC_Q_1ST_BD_MAC_WR_ERR_ID_REG 0x920 - -struct sec_debug_bd_info { -#define SEC_DEBUG_BD_INFO_SOFT_ERR_CHECK_M GENMASK(22, 0) - u32 soft_err_check; -#define SEC_DEBUG_BD_INFO_HARD_ERR_CHECK_M GENMASK(9, 0) - u32 hard_err_check; - u32 icv_mac1st_word; -#define SEC_DEBUG_BD_INFO_GET_ID_M GENMASK(19, 0) - u32 sec_get_id; - /* W4---W15 */ - u32 reserv_left[12]; -}; - -struct sec_out_bd_info { -#define SEC_OUT_BD_INFO_Q_ID_M GENMASK(11, 0) -#define SEC_OUT_BD_INFO_ECC_2BIT_ERR BIT(14) - u16 data; -}; - -#define SEC_MAX_DEVICES 8 -static struct sec_dev_info *sec_devices[SEC_MAX_DEVICES]; -static DEFINE_MUTEX(sec_id_lock); - -static int sec_queue_map_io(struct sec_queue *queue) -{ - struct device *dev = queue->dev_info->dev; - struct resource *res; - - res = platform_get_resource(to_platform_device(dev), - IORESOURCE_MEM, - 2 + queue->queue_id); - if (!res) { - dev_err(dev, "Failed to get queue %u memory resource\n", - queue->queue_id); - return -ENOMEM; - } - queue->regs = ioremap(res->start, resource_size(res)); - if (!queue->regs) - return -ENOMEM; - - return 0; -} - -static void sec_queue_unmap_io(struct sec_queue *queue) -{ - iounmap(queue->regs); -} - -static int sec_queue_ar_pkgattr(struct sec_queue *queue, u32 ar_pkg) -{ - void __iomem *addr = queue->regs + SEC_Q_ARUSER_CFG_REG; - u32 regval; - - regval = readl_relaxed(addr); - if (ar_pkg) - regval |= SEC_Q_ARUSER_CFG_PKG; - else - regval &= ~SEC_Q_ARUSER_CFG_PKG; - writel_relaxed(regval, addr); - - return 0; -} - -static int sec_queue_aw_pkgattr(struct sec_queue *queue, u32 aw_pkg) -{ - void __iomem *addr = queue->regs + SEC_Q_AWUSER_CFG_REG; - u32 regval; - - regval = readl_relaxed(addr); - regval |= SEC_Q_AWUSER_CFG_PKG; - writel_relaxed(regval, addr); - - return 0; -} - -static int sec_clk_en(struct sec_dev_info *info) -{ - void __iomem *base = info->regs[SEC_COMMON]; - u32 i = 0; - - writel_relaxed(0x7, base + SEC_ALGSUB_CLK_EN_REG); - do { - usleep_range(1000, 10000); - if ((readl_relaxed(base + SEC_ALGSUB_CLK_ST_REG) & 0x7) == 0x7) - return 0; - i++; - } while (i < 10); - dev_err(info->dev, "sec clock enable fail!\n"); - - return -EIO; -} - -static int sec_clk_dis(struct sec_dev_info *info) -{ - void __iomem *base = info->regs[SEC_COMMON]; - u32 i = 0; - - writel_relaxed(0x7, base + SEC_ALGSUB_CLK_DIS_REG); - do { - usleep_range(1000, 10000); - if ((readl_relaxed(base + SEC_ALGSUB_CLK_ST_REG) & 0x7) == 0) - return 0; - i++; - } while (i < 10); - dev_err(info->dev, "sec clock disable fail!\n"); - - return -EIO; -} - -static int sec_reset_whole_module(struct sec_dev_info *info) -{ - void __iomem *base = info->regs[SEC_COMMON]; - bool is_reset, b_is_reset; - u32 i = 0; - - writel_relaxed(1, base + SEC_ALGSUB_RST_REQ_REG); - writel_relaxed(1, base + SEC_ALGSUB_BUILD_RST_REQ_REG); - while (1) { - usleep_range(1000, 10000); - is_reset = readl_relaxed(base + SEC_ALGSUB_RST_ST_REG) & - SEC_ALGSUB_RST_ST_IS_RST; - b_is_reset = readl_relaxed(base + SEC_ALGSUB_BUILD_RST_ST_REG) & - SEC_ALGSUB_BUILD_RST_ST_IS_RST; - if (is_reset && b_is_reset) - break; - i++; - if (i > 10) { - dev_err(info->dev, "Reset req failed\n"); - return -EIO; - } - } - - i = 0; - writel_relaxed(1, base + SEC_ALGSUB_RST_DREQ_REG); - writel_relaxed(1, base + SEC_ALGSUB_BUILD_RST_DREQ_REG); - while (1) { - usleep_range(1000, 10000); - is_reset = readl_relaxed(base + SEC_ALGSUB_RST_ST_REG) & - SEC_ALGSUB_RST_ST_IS_RST; - b_is_reset = readl_relaxed(base + SEC_ALGSUB_BUILD_RST_ST_REG) & - SEC_ALGSUB_BUILD_RST_ST_IS_RST; - if (!is_reset && !b_is_reset) - break; - - i++; - if (i > 10) { - dev_err(info->dev, "Reset dreq failed\n"); - return -EIO; - } - } - - return 0; -} - -static void sec_bd_endian_little(struct sec_dev_info *info) -{ - void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL2_REG; - u32 regval; - - regval = readl_relaxed(addr); - regval &= ~(SEC_CTRL2_ENDIAN_BD | SEC_CTRL2_ENDIAN_BD_TYPE); - writel_relaxed(regval, addr); -} - -/* - * sec_cache_config - configure optimum cache placement - */ -static void sec_cache_config(struct sec_dev_info *info) -{ - struct iommu_domain *domain; - void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL_REG; - - domain = iommu_get_domain_for_dev(info->dev); - - /* Check that translation is occurring */ - if (domain && (domain->type & __IOMMU_DOMAIN_PAGING)) - writel_relaxed(0x44cf9e, addr); - else - writel_relaxed(0x4cfd9, addr); -} - -static void sec_data_axiwr_otsd_cfg(struct sec_dev_info *info, u32 cfg) -{ - void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL2_REG; - u32 regval; - - regval = readl_relaxed(addr); - regval &= ~SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_M; - regval |= (cfg << SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_S) & - SEC_CTRL2_DATA_AXI_WR_OTSD_CFG_M; - writel_relaxed(regval, addr); -} - -static void sec_data_axird_otsd_cfg(struct sec_dev_info *info, u32 cfg) -{ - void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL2_REG; - u32 regval; - - regval = readl_relaxed(addr); - regval &= ~SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_M; - regval |= (cfg << SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_S) & - SEC_CTRL2_DATA_AXI_RD_OTSD_CFG_M; - writel_relaxed(regval, addr); -} - -static void sec_clk_gate_en(struct sec_dev_info *info, bool clkgate) -{ - void __iomem *addr = info->regs[SEC_SAA] + SEC_CTRL2_REG; - u32 regval; - - regval = readl_relaxed(addr); - if (clkgate) - regval |= SEC_CTRL2_CLK_GATE_EN; - else - regval &= ~SEC_CTRL2_CLK_GATE_EN; - writel_relaxed(regval, addr); -} - -static void sec_comm_cnt_cfg(struct sec_dev_info *info, bool clr_ce) -{ - void __iomem *addr = info->regs[SEC_SAA] + SEC_COMMON_CNT_CLR_CE_REG; - u32 regval; - - regval = readl_relaxed(addr); - if (clr_ce) - regval |= SEC_COMMON_CNT_CLR_CE_CLEAR; - else - regval &= ~SEC_COMMON_CNT_CLR_CE_CLEAR; - writel_relaxed(regval, addr); -} - -static void sec_commsnap_en(struct sec_dev_info *info, bool snap_en) -{ - void __iomem *addr = info->regs[SEC_SAA] + SEC_COMMON_CNT_CLR_CE_REG; - u32 regval; - - regval = readl_relaxed(addr); - if (snap_en) - regval |= SEC_COMMON_CNT_CLR_CE_SNAP_EN; - else - regval &= ~SEC_COMMON_CNT_CLR_CE_SNAP_EN; - writel_relaxed(regval, addr); -} - -static void sec_ipv6_hashmask(struct sec_dev_info *info, u32 hash_mask[]) -{ - void __iomem *base = info->regs[SEC_SAA]; - int i; - - for (i = 0; i < 10; i++) - writel_relaxed(hash_mask[0], - base + SEC_IPV6_MASK_TABLE_X_REG(i)); -} - -static int sec_ipv4_hashmask(struct sec_dev_info *info, u32 hash_mask) -{ - if (hash_mask & SEC_HASH_IPV4_MASK) { - dev_err(info->dev, "Sec Ipv4 Hash Mask Input Error!\n"); - return -EINVAL; - } - - writel_relaxed(hash_mask, - info->regs[SEC_SAA] + SEC_IPV4_MASK_TABLE_REG); - - return 0; -} - -static void sec_set_dbg_bd_cfg(struct sec_dev_info *info, u32 cfg) -{ - void __iomem *addr = info->regs[SEC_SAA] + SEC_DEBUG_BD_CFG_REG; - u32 regval; - - regval = readl_relaxed(addr); - /* Always disable write back of normal bd */ - regval &= ~SEC_DEBUG_BD_CFG_WB_NORMAL; - - if (cfg) - regval &= ~SEC_DEBUG_BD_CFG_WB_EN; - else - regval |= SEC_DEBUG_BD_CFG_WB_EN; - - writel_relaxed(regval, addr); -} - -static void sec_saa_getqm_en(struct sec_dev_info *info, u32 saa_indx, u32 en) -{ - void __iomem *addr = info->regs[SEC_SAA] + SEC_SAA_BASE + - SEC_SAA_CTRL_REG(saa_indx); - u32 regval; - - regval = readl_relaxed(addr); - if (en) - regval |= SEC_SAA_CTRL_GET_QM_EN; - else - regval &= ~SEC_SAA_CTRL_GET_QM_EN; - writel_relaxed(regval, addr); -} - -static void sec_saa_int_mask(struct sec_dev_info *info, u32 saa_indx, - u32 saa_int_mask) -{ - writel_relaxed(saa_int_mask, - info->regs[SEC_SAA] + SEC_SAA_BASE + SEC_ST_INTMSK1_REG + - saa_indx * SEC_SAA_ADDR_SIZE); -} - -static void sec_streamid(struct sec_dev_info *info, int i) -{ - #define SEC_SID 0x600 - #define SEC_VMID 0 - - writel_relaxed((SEC_VMID | ((SEC_SID & 0xffff) << 8)), - info->regs[SEC_SAA] + SEC_Q_VMID_CFG_REG(i)); -} - -static void sec_queue_ar_alloc(struct sec_queue *queue, u32 alloc) -{ - void __iomem *addr = queue->regs + SEC_Q_ARUSER_CFG_REG; - u32 regval; - - regval = readl_relaxed(addr); - if (alloc == SEC_QUEUE_AR_FROCE_ALLOC) { - regval |= SEC_Q_ARUSER_CFG_FA; - regval &= ~SEC_Q_ARUSER_CFG_FNA; - } else { - regval &= ~SEC_Q_ARUSER_CFG_FA; - regval |= SEC_Q_ARUSER_CFG_FNA; - } - - writel_relaxed(regval, addr); -} - -static void sec_queue_aw_alloc(struct sec_queue *queue, u32 alloc) -{ - void __iomem *addr = queue->regs + SEC_Q_AWUSER_CFG_REG; - u32 regval; - - regval = readl_relaxed(addr); - if (alloc == SEC_QUEUE_AW_FROCE_ALLOC) { - regval |= SEC_Q_AWUSER_CFG_FA; - regval &= ~SEC_Q_AWUSER_CFG_FNA; - } else { - regval &= ~SEC_Q_AWUSER_CFG_FA; - regval |= SEC_Q_AWUSER_CFG_FNA; - } - - writel_relaxed(regval, addr); -} - -static void sec_queue_reorder(struct sec_queue *queue, bool reorder) -{ - void __iomem *base = queue->regs; - u32 regval; - - regval = readl_relaxed(base + SEC_Q_CFG_REG); - if (reorder) - regval |= SEC_Q_CFG_REORDER; - else - regval &= ~SEC_Q_CFG_REORDER; - writel_relaxed(regval, base + SEC_Q_CFG_REG); -} - -static void sec_queue_depth(struct sec_queue *queue, u32 depth) -{ - void __iomem *addr = queue->regs + SEC_Q_DEPTH_CFG_REG; - u32 regval; - - regval = readl_relaxed(addr); - regval &= ~SEC_Q_DEPTH_CFG_DEPTH_M; - regval |= (depth << SEC_Q_DEPTH_CFG_DEPTH_S) & SEC_Q_DEPTH_CFG_DEPTH_M; - - writel_relaxed(regval, addr); -} - -static void sec_queue_cmdbase_addr(struct sec_queue *queue, u64 addr) -{ - writel_relaxed(upper_32_bits(addr), queue->regs + SEC_Q_BASE_HADDR_REG); - writel_relaxed(lower_32_bits(addr), queue->regs + SEC_Q_BASE_LADDR_REG); -} - -static void sec_queue_outorder_addr(struct sec_queue *queue, u64 addr) -{ - writel_relaxed(upper_32_bits(addr), - queue->regs + SEC_Q_OUTORDER_BASE_HADDR_REG); - writel_relaxed(lower_32_bits(addr), - queue->regs + SEC_Q_OUTORDER_BASE_LADDR_REG); -} - -static void sec_queue_errbase_addr(struct sec_queue *queue, u64 addr) -{ - writel_relaxed(upper_32_bits(addr), - queue->regs + SEC_Q_ERR_BASE_HADDR_REG); - writel_relaxed(lower_32_bits(addr), - queue->regs + SEC_Q_ERR_BASE_LADDR_REG); -} - -static void sec_queue_irq_disable(struct sec_queue *queue) -{ - writel_relaxed((u32)~0, queue->regs + SEC_Q_FLOW_INT_MKS_REG); -} - -static void sec_queue_irq_enable(struct sec_queue *queue) -{ - writel_relaxed(0, queue->regs + SEC_Q_FLOW_INT_MKS_REG); -} - -static void sec_queue_abn_irq_disable(struct sec_queue *queue) -{ - writel_relaxed((u32)~0, queue->regs + SEC_Q_FAIL_INT_MSK_REG); -} - -static void sec_queue_stop(struct sec_queue *queue) -{ - disable_irq(queue->task_irq); - sec_queue_irq_disable(queue); - writel_relaxed(0x0, queue->regs + SEC_QUEUE_ENB_REG); -} - -static void sec_queue_start(struct sec_queue *queue) -{ - sec_queue_irq_enable(queue); - enable_irq(queue->task_irq); - queue->expected = 0; - writel_relaxed(SEC_Q_INIT_AND_STAT_CLEAR, queue->regs + SEC_Q_INIT_REG); - writel_relaxed(0x1, queue->regs + SEC_QUEUE_ENB_REG); -} - -static struct sec_queue *sec_alloc_queue(struct sec_dev_info *info) -{ - int i; - - mutex_lock(&info->dev_lock); - - /* Get the first idle queue in SEC device */ - for (i = 0; i < SEC_Q_NUM; i++) - if (!info->queues[i].in_use) { - info->queues[i].in_use = true; - info->queues_in_use++; - mutex_unlock(&info->dev_lock); - - return &info->queues[i]; - } - mutex_unlock(&info->dev_lock); - - return ERR_PTR(-ENODEV); -} - -static int sec_queue_free(struct sec_queue *queue) -{ - struct sec_dev_info *info = queue->dev_info; - - if (queue->queue_id >= SEC_Q_NUM) { - dev_err(info->dev, "No queue %u\n", queue->queue_id); - return -ENODEV; - } - - if (!queue->in_use) { - dev_err(info->dev, "Queue %u is idle\n", queue->queue_id); - return -ENODEV; - } - - mutex_lock(&info->dev_lock); - queue->in_use = false; - info->queues_in_use--; - mutex_unlock(&info->dev_lock); - - return 0; -} - -static irqreturn_t sec_isr_handle_th(int irq, void *q) -{ - sec_queue_irq_disable(q); - return IRQ_WAKE_THREAD; -} - -static irqreturn_t sec_isr_handle(int irq, void *q) -{ - struct sec_queue *queue = q; - struct sec_queue_ring_cmd *msg_ring = &queue->ring_cmd; - struct sec_queue_ring_cq *cq_ring = &queue->ring_cq; - struct sec_out_bd_info *outorder_msg; - struct sec_bd_info *msg; - u32 ooo_read, ooo_write; - void __iomem *base = queue->regs; - int q_id; - - ooo_read = readl(base + SEC_Q_OUTORDER_RD_PTR_REG); - ooo_write = readl(base + SEC_Q_OUTORDER_WR_PTR_REG); - outorder_msg = cq_ring->vaddr + ooo_read; - q_id = outorder_msg->data & SEC_OUT_BD_INFO_Q_ID_M; - msg = msg_ring->vaddr + q_id; - - while ((ooo_write != ooo_read) && msg->w0 & SEC_BD_W0_DONE) { - /* - * Must be before callback otherwise blocks adding other chained - * elements - */ - set_bit(q_id, queue->unprocessed); - if (q_id == queue->expected) - while (test_bit(queue->expected, queue->unprocessed)) { - clear_bit(queue->expected, queue->unprocessed); - msg = msg_ring->vaddr + queue->expected; - msg->w0 &= ~SEC_BD_W0_DONE; - msg_ring->callback(msg, - queue->shadow[queue->expected]); - queue->shadow[queue->expected] = NULL; - queue->expected = (queue->expected + 1) % - SEC_QUEUE_LEN; - atomic_dec(&msg_ring->used); - } - - ooo_read = (ooo_read + 1) % SEC_QUEUE_LEN; - writel(ooo_read, base + SEC_Q_OUTORDER_RD_PTR_REG); - ooo_write = readl(base + SEC_Q_OUTORDER_WR_PTR_REG); - outorder_msg = cq_ring->vaddr + ooo_read; - q_id = outorder_msg->data & SEC_OUT_BD_INFO_Q_ID_M; - msg = msg_ring->vaddr + q_id; - } - - sec_queue_irq_enable(queue); - - return IRQ_HANDLED; -} - -static int sec_queue_irq_init(struct sec_queue *queue) -{ - struct sec_dev_info *info = queue->dev_info; - int irq = queue->task_irq; - int ret; - - ret = request_threaded_irq(irq, sec_isr_handle_th, sec_isr_handle, - IRQF_TRIGGER_RISING, queue->name, queue); - if (ret) { - dev_err(info->dev, "request irq(%d) failed %d\n", irq, ret); - return ret; - } - disable_irq(irq); - - return 0; -} - -static int sec_queue_irq_uninit(struct sec_queue *queue) -{ - free_irq(queue->task_irq, queue); - - return 0; -} - -static struct sec_dev_info *sec_device_get(void) -{ - struct sec_dev_info *sec_dev = NULL; - struct sec_dev_info *this_sec_dev; - int least_busy_n = SEC_Q_NUM + 1; - int i; - - /* Find which one is least busy and use that first */ - for (i = 0; i < SEC_MAX_DEVICES; i++) { - this_sec_dev = sec_devices[i]; - if (this_sec_dev && - this_sec_dev->queues_in_use < least_busy_n) { - least_busy_n = this_sec_dev->queues_in_use; - sec_dev = this_sec_dev; - } - } - - return sec_dev; -} - -static struct sec_queue *sec_queue_alloc_start(struct sec_dev_info *info) -{ - struct sec_queue *queue; - - queue = sec_alloc_queue(info); - if (IS_ERR(queue)) { - dev_err(info->dev, "alloc sec queue failed! %ld\n", - PTR_ERR(queue)); - return queue; - } - - sec_queue_start(queue); - - return queue; -} - -/** - * sec_queue_alloc_start_safe - get a hw queue from appropriate instance - * - * This function does extremely simplistic load balancing. It does not take into - * account NUMA locality of the accelerator, or which cpu has requested the - * queue. Future work may focus on optimizing this in order to improve full - * machine throughput. - */ -struct sec_queue *sec_queue_alloc_start_safe(void) -{ - struct sec_dev_info *info; - struct sec_queue *queue = ERR_PTR(-ENODEV); - - mutex_lock(&sec_id_lock); - info = sec_device_get(); - if (!info) - goto unlock; - - queue = sec_queue_alloc_start(info); - -unlock: - mutex_unlock(&sec_id_lock); - - return queue; -} - -/** - * sec_queue_stop_release() - free up a hw queue for reuse - * @queue: The queue we are done with. - * - * This will stop the current queue, terminanting any transactions - * that are inflight an return it to the pool of available hw queuess - */ -int sec_queue_stop_release(struct sec_queue *queue) -{ - struct device *dev = queue->dev_info->dev; - int ret; - - sec_queue_stop(queue); - - ret = sec_queue_free(queue); - if (ret) - dev_err(dev, "Releasing queue failed %d\n", ret); - - return ret; -} - -/** - * sec_queue_empty() - Is this hardware queue currently empty. - * @queue: The queue to test - * - * We need to know if we have an empty queue for some of the chaining modes - * as if it is not empty we may need to hold the message in a software queue - * until the hw queue is drained. - */ -bool sec_queue_empty(struct sec_queue *queue) -{ - struct sec_queue_ring_cmd *msg_ring = &queue->ring_cmd; - - return !atomic_read(&msg_ring->used); -} - -/** - * sec_queue_send() - queue up a single operation in the hw queue - * @queue: The queue in which to put the message - * @msg: The message - * @ctx: Context to be put in the shadow array and passed back to cb on result. - * - * This function will return -EAGAIN if the queue is currently full. - */ -int sec_queue_send(struct sec_queue *queue, struct sec_bd_info *msg, void *ctx) -{ - struct sec_queue_ring_cmd *msg_ring = &queue->ring_cmd; - void __iomem *base = queue->regs; - u32 write, read; - - mutex_lock(&msg_ring->lock); - read = readl(base + SEC_Q_RD_PTR_REG); - write = readl(base + SEC_Q_WR_PTR_REG); - if (write == read && atomic_read(&msg_ring->used) == SEC_QUEUE_LEN) { - mutex_unlock(&msg_ring->lock); - return -EAGAIN; - } - memcpy(msg_ring->vaddr + write, msg, sizeof(*msg)); - queue->shadow[write] = ctx; - write = (write + 1) % SEC_QUEUE_LEN; - - /* Ensure content updated before queue advance */ - wmb(); - writel(write, base + SEC_Q_WR_PTR_REG); - - atomic_inc(&msg_ring->used); - mutex_unlock(&msg_ring->lock); - - return 0; -} - -bool sec_queue_can_enqueue(struct sec_queue *queue, int num) -{ - struct sec_queue_ring_cmd *msg_ring = &queue->ring_cmd; - - return SEC_QUEUE_LEN - atomic_read(&msg_ring->used) >= num; -} - -static void sec_queue_hw_init(struct sec_queue *queue) -{ - sec_queue_ar_alloc(queue, SEC_QUEUE_AR_FROCE_NOALLOC); - sec_queue_aw_alloc(queue, SEC_QUEUE_AW_FROCE_NOALLOC); - sec_queue_ar_pkgattr(queue, 1); - sec_queue_aw_pkgattr(queue, 1); - - /* Enable out of order queue */ - sec_queue_reorder(queue, true); - - /* Interrupt after a single complete element */ - writel_relaxed(1, queue->regs + SEC_Q_PROC_NUM_CFG_REG); - - sec_queue_depth(queue, SEC_QUEUE_LEN - 1); - - sec_queue_cmdbase_addr(queue, queue->ring_cmd.paddr); - - sec_queue_outorder_addr(queue, queue->ring_cq.paddr); - - sec_queue_errbase_addr(queue, queue->ring_db.paddr); - - writel_relaxed(0x100, queue->regs + SEC_Q_OT_TH_REG); - - sec_queue_abn_irq_disable(queue); - sec_queue_irq_disable(queue); - writel_relaxed(SEC_Q_INIT_AND_STAT_CLEAR, queue->regs + SEC_Q_INIT_REG); -} - -static int sec_hw_init(struct sec_dev_info *info) -{ - struct iommu_domain *domain; - u32 sec_ipv4_mask = 0; - u32 sec_ipv6_mask[10] = {}; - int ret; - u32 i; - - domain = iommu_get_domain_for_dev(info->dev); - - /* - * Enable all available processing unit clocks. - * Only the first cluster is usable with translations. - */ - if (domain && (domain->type & __IOMMU_DOMAIN_PAGING)) - info->num_saas = 5; - - else - info->num_saas = 10; - - writel_relaxed(GENMASK(info->num_saas - 1, 0), - info->regs[SEC_SAA] + SEC_CLK_EN_REG); - - /* 32 bit little endian */ - sec_bd_endian_little(info); - - sec_cache_config(info); - - /* Data axi port write and read outstanding config as per datasheet */ - sec_data_axiwr_otsd_cfg(info, 0x7); - sec_data_axird_otsd_cfg(info, 0x7); - - /* Enable clock gating */ - sec_clk_gate_en(info, true); - - /* Set CNT_CYC register not read clear */ - sec_comm_cnt_cfg(info, false); - - /* Enable CNT_CYC */ - sec_commsnap_en(info, false); - - writel_relaxed((u32)~0, info->regs[SEC_SAA] + SEC_FSM_MAX_CNT_REG); - - ret = sec_ipv4_hashmask(info, sec_ipv4_mask); - if (ret) { - dev_err(info->dev, "Failed to set ipv4 hashmask %d\n", ret); - return -EIO; - } - - sec_ipv6_hashmask(info, sec_ipv6_mask); - - /* do not use debug bd */ - sec_set_dbg_bd_cfg(info, 0); - - if (domain && (domain->type & __IOMMU_DOMAIN_PAGING)) { - for (i = 0; i < SEC_Q_NUM; i++) { - sec_streamid(info, i); - /* Same QoS for all queues */ - writel_relaxed(0x3f, - info->regs[SEC_SAA] + - SEC_Q_WEIGHT_CFG_REG(i)); - } - } - - for (i = 0; i < info->num_saas; i++) { - sec_saa_getqm_en(info, i, 1); - sec_saa_int_mask(info, i, 0); - } - - return 0; -} - -static void sec_hw_exit(struct sec_dev_info *info) -{ - int i; - - for (i = 0; i < SEC_MAX_SAA_NUM; i++) { - sec_saa_int_mask(info, i, (u32)~0); - sec_saa_getqm_en(info, i, 0); - } -} - -static void sec_queue_base_init(struct sec_dev_info *info, - struct sec_queue *queue, int queue_id) -{ - queue->dev_info = info; - queue->queue_id = queue_id; - snprintf(queue->name, sizeof(queue->name), - "%s_%d", dev_name(info->dev), queue->queue_id); -} - -static int sec_map_io(struct sec_dev_info *info, struct platform_device *pdev) -{ - int i; - - for (i = 0; i < SEC_NUM_ADDR_REGIONS; i++) { - info->regs[i] = devm_platform_ioremap_resource(pdev, i); - if (IS_ERR(info->regs[i])) - return PTR_ERR(info->regs[i]); - } - - return 0; -} - -static int sec_base_init(struct sec_dev_info *info, - struct platform_device *pdev) -{ - int ret; - - ret = sec_map_io(info, pdev); - if (ret) - return ret; - - ret = sec_clk_en(info); - if (ret) - return ret; - - ret = sec_reset_whole_module(info); - if (ret) - goto sec_clk_disable; - - ret = sec_hw_init(info); - if (ret) - goto sec_clk_disable; - - return 0; - -sec_clk_disable: - sec_clk_dis(info); - - return ret; -} - -static void sec_base_exit(struct sec_dev_info *info) -{ - sec_hw_exit(info); - sec_clk_dis(info); -} - -#define SEC_Q_CMD_SIZE \ - round_up(SEC_QUEUE_LEN * sizeof(struct sec_bd_info), PAGE_SIZE) -#define SEC_Q_CQ_SIZE \ - round_up(SEC_QUEUE_LEN * sizeof(struct sec_out_bd_info), PAGE_SIZE) -#define SEC_Q_DB_SIZE \ - round_up(SEC_QUEUE_LEN * sizeof(struct sec_debug_bd_info), PAGE_SIZE) - -static int sec_queue_res_cfg(struct sec_queue *queue) -{ - struct device *dev = queue->dev_info->dev; - struct sec_queue_ring_cmd *ring_cmd = &queue->ring_cmd; - struct sec_queue_ring_cq *ring_cq = &queue->ring_cq; - struct sec_queue_ring_db *ring_db = &queue->ring_db; - int ret; - - ring_cmd->vaddr = dma_alloc_coherent(dev, SEC_Q_CMD_SIZE, - &ring_cmd->paddr, GFP_KERNEL); - if (!ring_cmd->vaddr) - return -ENOMEM; - - atomic_set(&ring_cmd->used, 0); - mutex_init(&ring_cmd->lock); - ring_cmd->callback = sec_alg_callback; - - ring_cq->vaddr = dma_alloc_coherent(dev, SEC_Q_CQ_SIZE, - &ring_cq->paddr, GFP_KERNEL); - if (!ring_cq->vaddr) { - ret = -ENOMEM; - goto err_free_ring_cmd; - } - - ring_db->vaddr = dma_alloc_coherent(dev, SEC_Q_DB_SIZE, - &ring_db->paddr, GFP_KERNEL); - if (!ring_db->vaddr) { - ret = -ENOMEM; - goto err_free_ring_cq; - } - queue->task_irq = platform_get_irq(to_platform_device(dev), - queue->queue_id * 2 + 1); - if (queue->task_irq < 0) { - ret = queue->task_irq; - goto err_free_ring_db; - } - - return 0; - -err_free_ring_db: - dma_free_coherent(dev, SEC_Q_DB_SIZE, queue->ring_db.vaddr, - queue->ring_db.paddr); -err_free_ring_cq: - dma_free_coherent(dev, SEC_Q_CQ_SIZE, queue->ring_cq.vaddr, - queue->ring_cq.paddr); -err_free_ring_cmd: - dma_free_coherent(dev, SEC_Q_CMD_SIZE, queue->ring_cmd.vaddr, - queue->ring_cmd.paddr); - - return ret; -} - -static void sec_queue_free_ring_pages(struct sec_queue *queue) -{ - struct device *dev = queue->dev_info->dev; - - dma_free_coherent(dev, SEC_Q_DB_SIZE, queue->ring_db.vaddr, - queue->ring_db.paddr); - dma_free_coherent(dev, SEC_Q_CQ_SIZE, queue->ring_cq.vaddr, - queue->ring_cq.paddr); - dma_free_coherent(dev, SEC_Q_CMD_SIZE, queue->ring_cmd.vaddr, - queue->ring_cmd.paddr); -} - -static int sec_queue_config(struct sec_dev_info *info, struct sec_queue *queue, - int queue_id) -{ - int ret; - - sec_queue_base_init(info, queue, queue_id); - - ret = sec_queue_res_cfg(queue); - if (ret) - return ret; - - ret = sec_queue_map_io(queue); - if (ret) { - dev_err(info->dev, "Queue map failed %d\n", ret); - sec_queue_free_ring_pages(queue); - return ret; - } - - sec_queue_hw_init(queue); - - return 0; -} - -static void sec_queue_unconfig(struct sec_dev_info *info, - struct sec_queue *queue) -{ - sec_queue_unmap_io(queue); - sec_queue_free_ring_pages(queue); -} - -static int sec_id_alloc(struct sec_dev_info *info) -{ - int ret = 0; - int i; - - mutex_lock(&sec_id_lock); - - for (i = 0; i < SEC_MAX_DEVICES; i++) - if (!sec_devices[i]) - break; - if (i == SEC_MAX_DEVICES) { - ret = -ENOMEM; - goto unlock; - } - info->sec_id = i; - sec_devices[info->sec_id] = info; - -unlock: - mutex_unlock(&sec_id_lock); - - return ret; -} - -static void sec_id_free(struct sec_dev_info *info) -{ - mutex_lock(&sec_id_lock); - sec_devices[info->sec_id] = NULL; - mutex_unlock(&sec_id_lock); -} - -static int sec_probe(struct platform_device *pdev) -{ - struct sec_dev_info *info; - struct device *dev = &pdev->dev; - int i, j; - int ret; - - ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); - if (ret) { - dev_err(dev, "Failed to set 64 bit dma mask %d", ret); - return -ENODEV; - } - - info = devm_kzalloc(dev, (sizeof(*info)), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->dev = dev; - mutex_init(&info->dev_lock); - - info->hw_sgl_pool = dmam_pool_create("sgl", dev, - sizeof(struct sec_hw_sgl), 64, 0); - if (!info->hw_sgl_pool) { - dev_err(dev, "Failed to create sec sgl dma pool\n"); - return -ENOMEM; - } - - ret = sec_base_init(info, pdev); - if (ret) { - dev_err(dev, "Base initialization fail! %d\n", ret); - return ret; - } - - for (i = 0; i < SEC_Q_NUM; i++) { - ret = sec_queue_config(info, &info->queues[i], i); - if (ret) - goto queues_unconfig; - - ret = sec_queue_irq_init(&info->queues[i]); - if (ret) { - sec_queue_unconfig(info, &info->queues[i]); - goto queues_unconfig; - } - } - - ret = sec_algs_register(); - if (ret) { - dev_err(dev, "Failed to register algorithms with crypto %d\n", - ret); - goto queues_unconfig; - } - - platform_set_drvdata(pdev, info); - - ret = sec_id_alloc(info); - if (ret) - goto algs_unregister; - - return 0; - -algs_unregister: - sec_algs_unregister(); -queues_unconfig: - for (j = i - 1; j >= 0; j--) { - sec_queue_irq_uninit(&info->queues[j]); - sec_queue_unconfig(info, &info->queues[j]); - } - sec_base_exit(info); - - return ret; -} - -static void sec_remove(struct platform_device *pdev) -{ - struct sec_dev_info *info = platform_get_drvdata(pdev); - int i; - - /* Unexpose as soon as possible, reuse during remove is fine */ - sec_id_free(info); - - sec_algs_unregister(); - - for (i = 0; i < SEC_Q_NUM; i++) { - sec_queue_irq_uninit(&info->queues[i]); - sec_queue_unconfig(info, &info->queues[i]); - } - - sec_base_exit(info); -} - -static const __maybe_unused struct of_device_id sec_match[] = { - { .compatible = "hisilicon,hip06-sec" }, - { .compatible = "hisilicon,hip07-sec" }, - {} -}; -MODULE_DEVICE_TABLE(of, sec_match); - -static const __maybe_unused struct acpi_device_id sec_acpi_match[] = { - { "HISI02C1", 0 }, - { } -}; -MODULE_DEVICE_TABLE(acpi, sec_acpi_match); - -static struct platform_driver sec_driver = { - .probe = sec_probe, - .remove = sec_remove, - .driver = { - .name = "hisi_sec_platform_driver", - .of_match_table = sec_match, - .acpi_match_table = ACPI_PTR(sec_acpi_match), - }, -}; -module_platform_driver(sec_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("HiSilicon Security Accelerators"); -MODULE_AUTHOR("Zaibo Xu "); diff --git a/drivers/crypto/hisilicon/sec/sec_drv.h b/drivers/crypto/hisilicon/sec/sec_drv.h deleted file mode 100644 index e2a50bf2234b..000000000000 --- a/drivers/crypto/hisilicon/sec/sec_drv.h +++ /dev/null @@ -1,428 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2016-2017 HiSilicon Limited. */ - -#ifndef _SEC_DRV_H_ -#define _SEC_DRV_H_ - -#include -#include - -#define SEC_MAX_SGE_NUM 64 -#define SEC_HW_RING_NUM 3 - -#define SEC_CMD_RING 0 -#define SEC_OUTORDER_RING 1 -#define SEC_DBG_RING 2 - -/* A reasonable length to balance memory use against flexibility */ -#define SEC_QUEUE_LEN 512 - -#define SEC_MAX_SGE_NUM 64 - -struct sec_bd_info { -#define SEC_BD_W0_T_LEN_M GENMASK(4, 0) -#define SEC_BD_W0_T_LEN_S 0 - -#define SEC_BD_W0_C_WIDTH_M GENMASK(6, 5) -#define SEC_BD_W0_C_WIDTH_S 5 -#define SEC_C_WIDTH_AES_128BIT 0 -#define SEC_C_WIDTH_AES_8BIT 1 -#define SEC_C_WIDTH_AES_1BIT 2 -#define SEC_C_WIDTH_DES_64BIT 0 -#define SEC_C_WIDTH_DES_8BIT 1 -#define SEC_C_WIDTH_DES_1BIT 2 - -#define SEC_BD_W0_C_MODE_M GENMASK(9, 7) -#define SEC_BD_W0_C_MODE_S 7 -#define SEC_C_MODE_ECB 0 -#define SEC_C_MODE_CBC 1 -#define SEC_C_MODE_CTR 4 -#define SEC_C_MODE_CCM 5 -#define SEC_C_MODE_GCM 6 -#define SEC_C_MODE_XTS 7 - -#define SEC_BD_W0_SEQ BIT(10) -#define SEC_BD_W0_DE BIT(11) -#define SEC_BD_W0_DAT_SKIP_M GENMASK(13, 12) -#define SEC_BD_W0_DAT_SKIP_S 12 -#define SEC_BD_W0_C_GRAN_SIZE_19_16_M GENMASK(17, 14) -#define SEC_BD_W0_C_GRAN_SIZE_19_16_S 14 - -#define SEC_BD_W0_CIPHER_M GENMASK(19, 18) -#define SEC_BD_W0_CIPHER_S 18 -#define SEC_CIPHER_NULL 0 -#define SEC_CIPHER_ENCRYPT 1 -#define SEC_CIPHER_DECRYPT 2 - -#define SEC_BD_W0_AUTH_M GENMASK(21, 20) -#define SEC_BD_W0_AUTH_S 20 -#define SEC_AUTH_NULL 0 -#define SEC_AUTH_MAC 1 -#define SEC_AUTH_VERIF 2 - -#define SEC_BD_W0_AI_GEN BIT(22) -#define SEC_BD_W0_CI_GEN BIT(23) -#define SEC_BD_W0_NO_HPAD BIT(24) -#define SEC_BD_W0_HM_M GENMASK(26, 25) -#define SEC_BD_W0_HM_S 25 -#define SEC_BD_W0_ICV_OR_SKEY_EN_M GENMASK(28, 27) -#define SEC_BD_W0_ICV_OR_SKEY_EN_S 27 - -/* Multi purpose field - gran size bits for send, flag for recv */ -#define SEC_BD_W0_FLAG_M GENMASK(30, 29) -#define SEC_BD_W0_C_GRAN_SIZE_21_20_M GENMASK(30, 29) -#define SEC_BD_W0_FLAG_S 29 -#define SEC_BD_W0_C_GRAN_SIZE_21_20_S 29 - -#define SEC_BD_W0_DONE BIT(31) - u32 w0; - -#define SEC_BD_W1_AUTH_GRAN_SIZE_M GENMASK(21, 0) -#define SEC_BD_W1_AUTH_GRAN_SIZE_S 0 -#define SEC_BD_W1_M_KEY_EN BIT(22) -#define SEC_BD_W1_BD_INVALID BIT(23) -#define SEC_BD_W1_ADDR_TYPE BIT(24) - -#define SEC_BD_W1_A_ALG_M GENMASK(28, 25) -#define SEC_BD_W1_A_ALG_S 25 -#define SEC_A_ALG_SHA1 0 -#define SEC_A_ALG_SHA256 1 -#define SEC_A_ALG_MD5 2 -#define SEC_A_ALG_SHA224 3 -#define SEC_A_ALG_HMAC_SHA1 8 -#define SEC_A_ALG_HMAC_SHA224 10 -#define SEC_A_ALG_HMAC_SHA256 11 -#define SEC_A_ALG_HMAC_MD5 12 -#define SEC_A_ALG_AES_XCBC 13 -#define SEC_A_ALG_AES_CMAC 14 - -#define SEC_BD_W1_C_ALG_M GENMASK(31, 29) -#define SEC_BD_W1_C_ALG_S 29 -#define SEC_C_ALG_DES 0 -#define SEC_C_ALG_3DES 1 -#define SEC_C_ALG_AES 2 - - u32 w1; - -#define SEC_BD_W2_C_GRAN_SIZE_15_0_M GENMASK(15, 0) -#define SEC_BD_W2_C_GRAN_SIZE_15_0_S 0 -#define SEC_BD_W2_GRAN_NUM_M GENMASK(31, 16) -#define SEC_BD_W2_GRAN_NUM_S 16 - u32 w2; - -#define SEC_BD_W3_AUTH_LEN_OFFSET_M GENMASK(9, 0) -#define SEC_BD_W3_AUTH_LEN_OFFSET_S 0 -#define SEC_BD_W3_CIPHER_LEN_OFFSET_M GENMASK(19, 10) -#define SEC_BD_W3_CIPHER_LEN_OFFSET_S 10 -#define SEC_BD_W3_MAC_LEN_M GENMASK(24, 20) -#define SEC_BD_W3_MAC_LEN_S 20 -#define SEC_BD_W3_A_KEY_LEN_M GENMASK(29, 25) -#define SEC_BD_W3_A_KEY_LEN_S 25 -#define SEC_BD_W3_C_KEY_LEN_M GENMASK(31, 30) -#define SEC_BD_W3_C_KEY_LEN_S 30 -#define SEC_KEY_LEN_AES_128 0 -#define SEC_KEY_LEN_AES_192 1 -#define SEC_KEY_LEN_AES_256 2 -#define SEC_KEY_LEN_DES 1 -#define SEC_KEY_LEN_3DES_3_KEY 1 -#define SEC_KEY_LEN_3DES_2_KEY 3 - u32 w3; - - /* W4,5 */ - union { - u32 authkey_addr_lo; - u32 authiv_addr_lo; - }; - union { - u32 authkey_addr_hi; - u32 authiv_addr_hi; - }; - - /* W6,7 */ - u32 cipher_key_addr_lo; - u32 cipher_key_addr_hi; - - /* W8,9 */ - u32 cipher_iv_addr_lo; - u32 cipher_iv_addr_hi; - - /* W10,11 */ - u32 data_addr_lo; - u32 data_addr_hi; - - /* W12,13 */ - u32 mac_addr_lo; - u32 mac_addr_hi; - - /* W14,15 */ - u32 cipher_destin_addr_lo; - u32 cipher_destin_addr_hi; -}; - -enum sec_mem_region { - SEC_COMMON = 0, - SEC_SAA, - SEC_NUM_ADDR_REGIONS -}; - -#define SEC_NAME_SIZE 64 -#define SEC_Q_NUM 16 - - -/** - * struct sec_queue_ring_cmd - store information about a SEC HW cmd ring - * @used: Local counter used to cheaply establish if the ring is empty. - * @lock: Protect against simultaneous adjusting of the read and write pointers. - * @vaddr: Virtual address for the ram pages used for the ring. - * @paddr: Physical address of the dma mapped region of ram used for the ring. - * @callback: Callback function called on a ring element completing. - */ -struct sec_queue_ring_cmd { - atomic_t used; - struct mutex lock; - struct sec_bd_info *vaddr; - dma_addr_t paddr; - void (*callback)(struct sec_bd_info *resp, void *ctx); -}; - -struct sec_debug_bd_info; -struct sec_queue_ring_db { - struct sec_debug_bd_info *vaddr; - dma_addr_t paddr; -}; - -struct sec_out_bd_info; -struct sec_queue_ring_cq { - struct sec_out_bd_info *vaddr; - dma_addr_t paddr; -}; - -struct sec_dev_info; - -enum sec_cipher_alg { - SEC_C_DES_ECB_64, - SEC_C_DES_CBC_64, - - SEC_C_3DES_ECB_192_3KEY, - SEC_C_3DES_ECB_192_2KEY, - - SEC_C_3DES_CBC_192_3KEY, - SEC_C_3DES_CBC_192_2KEY, - - SEC_C_AES_ECB_128, - SEC_C_AES_ECB_192, - SEC_C_AES_ECB_256, - - SEC_C_AES_CBC_128, - SEC_C_AES_CBC_192, - SEC_C_AES_CBC_256, - - SEC_C_AES_CTR_128, - SEC_C_AES_CTR_192, - SEC_C_AES_CTR_256, - - SEC_C_AES_XTS_128, - SEC_C_AES_XTS_256, - - SEC_C_NULL, -}; - -/** - * struct sec_alg_tfm_ctx - hardware specific tranformation context - * @cipher_alg: Cipher algorithm enabled include encryption mode. - * @key: Key storage if required. - * @pkey: DMA address for the key storage. - * @req_template: Request template to save time on setup. - * @queue: The hardware queue associated with this tfm context. - * @lock: Protect key and pkey to ensure they are consistent - * @auth_buf: Current context buffer for auth operations. - * @backlog: The backlog queue used for cases where our buffers aren't - * large enough. - */ -struct sec_alg_tfm_ctx { - enum sec_cipher_alg cipher_alg; - u8 *key; - dma_addr_t pkey; - struct sec_bd_info req_template; - struct sec_queue *queue; - struct mutex lock; - u8 *auth_buf; - struct list_head backlog; -}; - -/** - * struct sec_request - data associate with a single crypto request - * @elements: List of subparts of this request (hardware size restriction) - * @num_elements: The number of subparts (used as an optimization) - * @lock: Protect elements of this structure against concurrent change. - * @tfm_ctx: hardware specific context. - * @len_in: length of in sgl from upper layers - * @len_out: length of out sgl from upper layers - * @dma_iv: initialization vector - phsyical address - * @err: store used to track errors across subelements of this request. - * @req_base: pointer to base element of associate crypto context. - * This is needed to allow shared handling skcipher, ahash etc. - * @cb: completion callback. - * @backlog_head: list head to allow backlog maintenance. - * - * The hardware is limited in the maximum size of data that it can - * process from a single BD. Typically this is fairly large (32MB) - * but still requires the complexity of splitting the incoming - * skreq up into a number of elements complete with appropriate - * iv chaining. - */ -struct sec_request { - struct list_head elements; - int num_elements; - struct mutex lock; - struct sec_alg_tfm_ctx *tfm_ctx; - int len_in; - int len_out; - dma_addr_t dma_iv; - int err; - struct crypto_async_request *req_base; - void (*cb)(struct sec_bd_info *resp, struct crypto_async_request *req); - struct list_head backlog_head; -}; - -/** - * struct sec_request_el - A subpart of a request. - * @head: allow us to attach this to the list in the sec_request - * @req: hardware block descriptor corresponding to this request subpart - * @in: hardware sgl for input - virtual address - * @dma_in: hardware sgl for input - physical address - * @sgl_in: scatterlist for this request subpart - * @out: hardware sgl for output - virtual address - * @dma_out: hardware sgl for output - physical address - * @sgl_out: scatterlist for this request subpart - * @sec_req: The request which this subpart forms a part of - * @el_length: Number of bytes in this subpart. Needed to locate - * last ivsize chunk for iv chaining. - */ -struct sec_request_el { - struct list_head head; - struct sec_bd_info req; - struct sec_hw_sgl *in; - dma_addr_t dma_in; - struct scatterlist *sgl_in; - struct sec_hw_sgl *out; - dma_addr_t dma_out; - struct scatterlist *sgl_out; - struct sec_request *sec_req; - size_t el_length; -}; - -/** - * struct sec_queue - All the information about a HW queue - * @dev_info: The parent SEC device to which this queue belongs. - * @task_irq: Completion interrupt for the queue. - * @name: Human readable queue description also used as irq name. - * @ring: The several HW rings associated with one queue. - * @regs: The iomapped device registers - * @queue_id: Index of the queue used for naming and resource selection. - * @in_use: Flag to say if the queue is in use. - * @expected: The next expected element to finish assuming we were in order. - * @uprocessed: A bitmap to track which OoO elements are done but not handled. - * @softqueue: A software queue used when chaining requirements prevent direct - * use of the hardware queues. - * @havesoftqueue: A flag to say we have a queues - as we may need one for the - * current mode. - * @queuelock: Protect the soft queue from concurrent changes to avoid some - * potential loss of data races. - * @shadow: Pointers back to the shadow copy of the hardware ring element - * need because we can't store any context reference in the bd element. - */ -struct sec_queue { - struct sec_dev_info *dev_info; - int task_irq; - char name[SEC_NAME_SIZE]; - struct sec_queue_ring_cmd ring_cmd; - struct sec_queue_ring_cq ring_cq; - struct sec_queue_ring_db ring_db; - void __iomem *regs; - u32 queue_id; - bool in_use; - int expected; - - DECLARE_BITMAP(unprocessed, SEC_QUEUE_LEN); - DECLARE_KFIFO_PTR(softqueue, typeof(struct sec_request_el *)); - bool havesoftqueue; - spinlock_t queuelock; - void *shadow[SEC_QUEUE_LEN]; -}; - -/** - * struct sec_hw_sge: Track each of the 64 element SEC HW SGL entries - * @buf: The IOV dma address for this entry. - * @len: Length of this IOV. - * @pad: Reserved space. - */ -struct sec_hw_sge { - dma_addr_t buf; - unsigned int len; - unsigned int pad; -}; - -/** - * struct sec_hw_sgl: One hardware SGL entry. - * @next_sgl: The next entry if we need to chain dma address. Null if last. - * @entry_sum_in_chain: The full count of SGEs - only matters for first SGL. - * @entry_sum_in_sgl: The number of SGEs in this SGL element. - * @flag: Unused in skciphers. - * @serial_num: Unsued in skciphers. - * @cpuid: Currently unused. - * @data_bytes_in_sgl: Count of bytes from all SGEs in this SGL. - * @next: Virtual address used to stash the next sgl - useful in completion. - * @reserved: A reserved field not currently used. - * @sge_entries: The (up to) 64 Scatter Gather Entries, representing IOVs. - * @node: Currently unused. - */ -struct sec_hw_sgl { - dma_addr_t next_sgl; - u16 entry_sum_in_chain; - u16 entry_sum_in_sgl; - u32 flag; - u64 serial_num; - u32 cpuid; - u32 data_bytes_in_sgl; - struct sec_hw_sgl *next; - u64 reserved; - struct sec_hw_sge sge_entries[SEC_MAX_SGE_NUM]; - u8 node[16]; -}; - -struct dma_pool; - -/** - * struct sec_dev_info: The full SEC unit comprising queues and processors. - * @sec_id: Index used to track which SEC this is when more than one is present. - * @num_saas: The number of backed processors enabled. - * @regs: iomapped register regions shared by whole SEC unit. - * @dev_lock: Protects concurrent queue allocation / freeing for the SEC. - * @queues: The 16 queues that this SEC instance provides. - * @dev: Device pointer. - * @hw_sgl_pool: DMA pool used to mimise mapping for the scatter gather lists. - */ -struct sec_dev_info { - int sec_id; - int num_saas; - void __iomem *regs[SEC_NUM_ADDR_REGIONS]; - struct mutex dev_lock; - int queues_in_use; - struct sec_queue queues[SEC_Q_NUM]; - struct device *dev; - struct dma_pool *hw_sgl_pool; -}; - -int sec_queue_send(struct sec_queue *queue, struct sec_bd_info *msg, void *ctx); -bool sec_queue_can_enqueue(struct sec_queue *queue, int num); -int sec_queue_stop_release(struct sec_queue *queue); -struct sec_queue *sec_queue_alloc_start_safe(void); -bool sec_queue_empty(struct sec_queue *queue); - -/* Algorithm specific elements from sec_algs.c */ -void sec_alg_callback(struct sec_bd_info *resp, void *ctx); -int sec_algs_register(void); -void sec_algs_unregister(void); - -#endif /* _SEC_DRV_H_ */ From 5c87bcb2f98dbfe08efa016af037b0f9701ba381 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 19 Aug 2026 17:18:45 +0200 Subject: [PATCH 025/146] crypto: inside-secure - Zeroize temporary arrays on stack with sensitive data key_tmp[] in safexcel_xcbcmac_setkey() and consts[] / _const[] in safexcel_cmac_setkey() contain crypto key material that should not get exposed to the outside once the function is done. Scrub the arrays with memzero_explicit() to avoid that the data could leak via the stack. Reported-by: Sashiko Link: https://sashiko.dev/#/patchset/20260813134953.979481-1-thuth%40redhat.com Fixes: 38f21b4bab11f ("crypto: inside-secure - Added support for the AES XCBC ahash") Fixes: 7a627db9cafdb ("crypto: inside-secure - Added support for the AES-CMAC ahash") Acked-by: Antoine Tenart Signed-off-by: Thomas Huth Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/safexcel_hash.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c index 20c17eb09495..8f107da66685 100644 --- a/drivers/crypto/inside-secure/safexcel_hash.c +++ b/drivers/crypto/inside-secure/safexcel_hash.c @@ -1992,6 +1992,7 @@ static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, ret = aes_prepareenckey(ctx->aes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, AES_MIN_KEY_SIZE); + memzero_explicit(key_tmp, sizeof(key_tmp)); if (ret) return ret; @@ -2103,6 +2104,8 @@ static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, } ctx->cbcmac = false; + memzero_explicit(consts, sizeof(consts)); + memzero_explicit(_const, sizeof(_const)); return 0; } From e5f3b9b7a1bd333eae910a385947912159fb46f4 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 19 Aug 2026 22:59:02 +0300 Subject: [PATCH 026/146] MAINTAINERS: Add Qualcomm Inline Crypto Engine entry Add an entry for the Qualcomm Inline Crypto Engine driver and its device tree bindings. List myself as maintainer to keep an eye on it. Signed-off-by: Abel Vesa Acked-by: Eric Biggers Signed-off-by: Herbert Xu --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3a19da74d00c..85ba874d6579 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22483,6 +22483,15 @@ S: Maintained F: Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml F: drivers/i2c/busses/i2c-qcom-cci.c +QUALCOMM INLINE CRYPTO ENGINE DRIVER +M: Abel Vesa +L: linux-arm-msm@vger.kernel.org +L: linux-crypto@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +F: drivers/soc/qcom/ice.c +F: include/soc/qcom/ice.h + QUALCOMM INTERCONNECT BWMON DRIVER M: Krzysztof Kozlowski L: linux-arm-msm@vger.kernel.org From f07d34f2083a7a292abbc918e90209d5c9f7e2f3 Mon Sep 17 00:00:00 2001 From: Triet Hoang Date: Thu, 20 Aug 2026 11:51:27 +0700 Subject: [PATCH 027/146] hwrng: omap - Convert to DEFINE_SIMPLE_DEV_PM_OPS() Convert the deprecated SIMPLE_DEV_PM_OPS to DEFINE_SIMPLE_DEV_PM_OPS and pm_sleep_ptr(). This lets us drop the __maybe_unused annotations from its suspend and resume callbacks, and reduces kernel size in case CONFIG_PM or CONFIG_PM_SLEEP is disabled. Signed-off-by: Triet Hoang Signed-off-by: Herbert Xu --- drivers/char/hw_random/omap-rng.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 9f0545c67774..22cde35ebe5d 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -530,7 +530,7 @@ static void omap_rng_remove(struct platform_device *pdev) clk_disable_unprepare(priv->clk_reg); } -static int __maybe_unused omap_rng_suspend(struct device *dev) +static int omap_rng_suspend(struct device *dev) { struct omap_rng_dev *priv = dev_get_drvdata(dev); @@ -540,7 +540,7 @@ static int __maybe_unused omap_rng_suspend(struct device *dev) return 0; } -static int __maybe_unused omap_rng_resume(struct device *dev) +static int omap_rng_resume(struct device *dev) { struct omap_rng_dev *priv = dev_get_drvdata(dev); int ret; @@ -556,12 +556,12 @@ static int __maybe_unused omap_rng_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume); static struct platform_driver omap_rng_driver = { .driver = { .name = "omap_rng", - .pm = &omap_rng_pm, + .pm = pm_sleep_ptr(&omap_rng_pm), .of_match_table = of_match_ptr(omap_rng_of_match), }, .probe = omap_rng_probe, From 6c2373dd818b777d0a81eb02acebc03940552dcd Mon Sep 17 00:00:00 2001 From: Mohamad Raizudeen Date: Sat, 22 Aug 2026 14:15:08 +0530 Subject: [PATCH 028/146] crypto: amlogic - Fix DMA memory leak in cipher error path A DMA memory leak occurs in meson_cipher() on the mapping error paths. The driver jumps to the end of the function without unmapping the previously mapped source scatterlist and key/IV buffer when the destination apping fails. Additionally, a memory leak occurs when a scatterlist mapping succeeds but the returned count exceeds the driver's MAXDESC limit. In this case, the driver rejects the mapping without unmapping it. The BIDIRECTIONAL mapping branch also lacks the required 'MAXDESC -3' upper bound check. Fix this by introducing proper error labels, error_src and error_keyiv and unmap resources immediately inside the calidation checks to ensure all successfully mapped resources are cleaned up before returning the error. Fixes: 48fe583fe541 ("crypto: amlogic - Add crypto accelerator for amlogic GXL") Signed-off-by: Mohamad Raizudeen Signed-off-by: Herbert Xu --- drivers/crypto/amlogic/amlogic-gxl-cipher.c | 25 ++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/amlogic/amlogic-gxl-cipher.c b/drivers/crypto/amlogic/amlogic-gxl-cipher.c index 29048da6f50a..d78815b0547d 100644 --- a/drivers/crypto/amlogic/amlogic-gxl-cipher.c +++ b/drivers/crypto/amlogic/amlogic-gxl-cipher.c @@ -177,10 +177,13 @@ static int meson_cipher(struct skcipher_request *areq) if (areq->src == areq->dst) { nr_sgs = dma_map_sg(mc->dev, areq->src, sg_nents(areq->src), DMA_BIDIRECTIONAL); - if (!nr_sgs) { - dev_err(mc->dev, "Invalid SG count %d\n", nr_sgs); + if (!nr_sgs || nr_sgs > MAXDESC - 3) { + dev_err(mc->dev, "Invalid BIDIR SG count %d\n", nr_sgs); err = -EINVAL; - goto theend; + + if (nr_sgs) + dma_unmap_sg(mc->dev, areq->src, sg_nents(areq->src), DMA_BIDIRECTIONAL); + goto error_keyiv; } nr_sgd = nr_sgs; } else { @@ -189,14 +192,20 @@ static int meson_cipher(struct skcipher_request *areq) if (!nr_sgs || nr_sgs > MAXDESC - 3) { dev_err(mc->dev, "Invalid SG count %d\n", nr_sgs); err = -EINVAL; - goto theend; + + if (nr_sgs) + dma_unmap_sg(mc->dev, areq->src, sg_nents(areq->src), DMA_TO_DEVICE); + goto error_keyiv; } nr_sgd = dma_map_sg(mc->dev, areq->dst, sg_nents(areq->dst), DMA_FROM_DEVICE); if (!nr_sgd || nr_sgd > MAXDESC - 3) { dev_err(mc->dev, "Invalid SG count %d\n", nr_sgd); err = -EINVAL; - goto theend; + + if (nr_sgd) + dma_unmap_sg(mc->dev, areq->dst, sg_nents(areq->dst), DMA_FROM_DEVICE); + goto error_src; } } @@ -251,6 +260,12 @@ static int meson_cipher(struct skcipher_request *areq) ivsize, 0); } } + goto theend; + +error_src: + dma_unmap_sg(mc->dev, areq->src, sg_nents(areq->src), DMA_TO_DEVICE); +error_keyiv: + dma_unmap_single(mc->dev, phykeyiv, keyivlen, DMA_TO_DEVICE); theend: kfree_sensitive(bkeyiv); kfree_sensitive(backup_iv); From ac508238898058f0b09b18a7891fb31279617781 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Mon, 24 Aug 2026 11:17:44 +0100 Subject: [PATCH 029/146] crypto: qat - avoid OOB read when stripping RSA leading zeros The logical AND operator uses short-circuit evaluation: the first operand is always evaluated, while the second is evaluated only if the first is true. Because the first operand dereferences a pointer, it may cause an out-of-bounds access before the bounds check in the second operand is evaluated. Resolve this by checking the vlen prior to the pointer being dereferenced. Fixes: a990532023b9 ("crypto: qat - Add support for RSA algorithm") Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/qat_asym_algs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c index 75c15c8e41db..aa2ea563f25f 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c @@ -987,7 +987,7 @@ static int qat_rsa_set_n(struct qat_rsa_ctx *ctx, const char *value, const char *ptr = value; int ret; - while (!*ptr && vlen) { + while (vlen && !*ptr) { ptr++; vlen--; } @@ -1018,7 +1018,7 @@ static int qat_rsa_set_e(struct qat_rsa_ctx *ctx, const char *value, struct device *dev = &GET_DEV(inst->accel_dev); const char *ptr = value; - while (!*ptr && vlen) { + while (vlen && !*ptr) { ptr++; vlen--; } @@ -1044,7 +1044,7 @@ static int qat_rsa_set_d(struct qat_rsa_ctx *ctx, const char *value, const char *ptr = value; int ret; - while (!*ptr && vlen) { + while (vlen && !*ptr) { ptr++; vlen--; } @@ -1067,7 +1067,7 @@ err: static void qat_rsa_drop_leading_zeros(const char **ptr, unsigned int *len) { - while (!**ptr && *len) { + while (*len && !**ptr) { (*ptr)++; (*len)--; } From 0db478c2e26f1e6428ee86d11d7401a75fadd677 Mon Sep 17 00:00:00 2001 From: Usama Arif Date: Tue, 25 Aug 2026 15:06:01 -0700 Subject: [PATCH 030/146] crypto: zstd - Avoid redundant cstream initialization zstd_compress() initializes the shared workspace as a CStream before entering the walk loop. If the first source and destination fragments each span the whole request it then hands off to zstd_compress_one(), which initializes that same ctx->wksp as a CCtx, discarding the CStream setup without having compressed a byte. zswap always takes this one-shot path when storing, so every page it stores paid for both. Neither is cheap: zstd_init_cstream() redoes the cwksp layout, zeroes the ZSTD_CCtx, probes for BMI2 through ZSTD_cpuid(), then resets the session and parameters and replays ten validated ZSTD_CCtx_setParameter() calls. Defer the CStream initialization to the first walk iteration that needs it, guarded by a flag because that iteration can be reached more than once. The first inner iteration either takes the one-shot path and returns or initializes the CStream, so the trailing zstd_end_stream() cannot pick up the stale context left in ctx->cctx by an earlier request. Unlike the old call site the new one runs with the walk's fragments mapped, so it has to release them before failing. For a 4 KB crypto_acomp benchmark for compression, twelve runs of nine 30K operation rounds, on the bare-metal host the median per-round mean request time fell from 52,283 ns to 51,038 ns (2.4%). In the one-vCPU KVM guest it fell from 16,675 ns to 15,050 ns (9.8%). The larger improvement in guest is because of the pair of CPUID instructions in ZSTD_cpuid() that the removed initialization runs. Signed-off-by: Usama Arif Signed-off-by: Herbert Xu --- crypto/zstd.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/crypto/zstd.c b/crypto/zstd.c index 556f5d2bdd5f..d64472f3e11e 100644 --- a/crypto/zstd.c +++ b/crypto/zstd.c @@ -96,6 +96,7 @@ static int zstd_compress_one(struct acomp_req *req, struct zstd_ctx *ctx, static int zstd_compress(struct acomp_req *req) { + bool stream_initialized = false; struct crypto_acomp_stream *s; unsigned int pos, scur, dcur; unsigned int total_out = 0; @@ -115,12 +116,6 @@ static int zstd_compress(struct acomp_req *req) if (ret) goto out; - ctx->cctx = zstd_init_cstream(&ctx->params, 0, ctx->wksp, ctx->wksp_size); - if (!ctx->cctx) { - ret = -EINVAL; - goto out; - } - do { dcur = acomp_walk_next_dst(&walk); if (!dcur) { @@ -142,6 +137,19 @@ static int zstd_compress(struct acomp_req *req) goto out; } + if (!stream_initialized) { + ctx->cctx = zstd_init_cstream(&ctx->params, 0, + ctx->wksp, ctx->wksp_size); + if (!ctx->cctx) { + /* Release in the reverse of the map order. */ + acomp_walk_done_src(&walk, 0); + acomp_walk_done_dst(&walk, 0); + ret = -EINVAL; + goto out; + } + stream_initialized = true; + } + if (scur) { inbuf.pos = 0; inbuf.src = walk.src.virt.addr; From 57818119c9eb90a616c50c40dc8eca74a3def4ab Mon Sep 17 00:00:00 2001 From: Usama Arif Date: Tue, 25 Aug 2026 15:06:02 -0700 Subject: [PATCH 031/146] crypto: zstd - Avoid redundant dstream initialization zstd_decompress() initializes the shared workspace as a DStream before entering the walk loop. If the first source and destination fragments each span the whole request it then hands off to zstd_decompress_one(), which initializes that same ctx->wksp as a DCtx, discarding the DStream setup without having decompressed a byte. The two are in fact the same routine, as ZSTD_initStaticDStream() is a tail call to ZSTD_initStaticDCtx() and zstd_init_dstream() discards its max_window_size argument, so the work was done twice byte for byte. zswap takes this path whenever the stored object lies within a single zsmalloc page, which is the common case; an object straddling a page boundary comes back from zs_obj_read_sg_begin() as a two-entry source scatterlist and streams instead. Defer the DStream initialization to the first walk iteration that reaches the streaming path, guarded by a flag because that iteration can be reached more than once. Within this function ctx->dctx is read only by the zstd_decompress_stream() call immediately below, so no stale context can be picked up. As in the previous patch the new call site runs with the walk's fragments mapped and has to release them before failing. For a 4 KB crypto_acomp benchmark for decompression, twelve runs of nine 30K operation rounds, on the bare-metal host the median per-round mean request time fell from 2,317 ns to 1,998 ns (13.8%). In the one-vCPU KVM guest it fell from 3,516 ns to 2,265 ns (35.6%). Signed-off-by: Usama Arif Signed-off-by: Herbert Xu --- crypto/zstd.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/crypto/zstd.c b/crypto/zstd.c index d64472f3e11e..76bdaca32733 100644 --- a/crypto/zstd.c +++ b/crypto/zstd.c @@ -215,6 +215,7 @@ static int zstd_decompress_one(struct acomp_req *req, struct zstd_ctx *ctx, static int zstd_decompress(struct acomp_req *req) { + bool stream_initialized = false; struct crypto_acomp_stream *s; unsigned int total_out = 0; unsigned int scur, dcur; @@ -232,12 +233,6 @@ static int zstd_decompress(struct acomp_req *req) if (ret) goto out; - ctx->dctx = zstd_init_dstream(ZSTD_MAX_SIZE, ctx->wksp, ctx->wksp_size); - if (!ctx->dctx) { - ret = -EINVAL; - goto out; - } - do { scur = acomp_walk_next_src(&walk); if (scur) { @@ -263,6 +258,19 @@ static int zstd_decompress(struct acomp_req *req) goto out; } + if (!stream_initialized) { + ctx->dctx = zstd_init_dstream(ZSTD_MAX_SIZE, ctx->wksp, + ctx->wksp_size); + if (!ctx->dctx) { + /* Release in the reverse of the map order. */ + acomp_walk_done_dst(&walk, 0); + acomp_walk_done_src(&walk, 0); + ret = -EINVAL; + goto out; + } + stream_initialized = true; + } + outbuf.pos = 0; outbuf.dst = (u8 *)walk.dst.virt.addr; outbuf.size = dcur; From 307e27d3e07f58b6d42a8c64d31304aa614ab7d2 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 26 Aug 2026 10:39:31 +0100 Subject: [PATCH 032/146] crypto: qat - release instance on DH fallback allocation failure qat_dh_init_tfm() acquires a QAT crypto instance before allocating the software fallback transform. If fallback allocation fails, the instance reference is leaked and the device remains permanently in use. Release the instance before returning the allocation error. Fixes: 5d5bd24f4155 ("crypto: qat - implement dh fallback for primes > 4K") Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/qat_asym_algs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c index aa2ea563f25f..1049c583f84f 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c @@ -535,8 +535,10 @@ static int qat_dh_init_tfm(struct crypto_kpp *tfm) return -EINVAL; ctx->ftfm = crypto_alloc_kpp(alg, 0, CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(ctx->ftfm)) + if (IS_ERR(ctx->ftfm)) { + qat_crypto_put_instance(inst); return PTR_ERR(ctx->ftfm); + } crypto_kpp_set_flags(ctx->ftfm, crypto_kpp_get_flags(tfm)); From 4cf50332b5384ea13f6f896d5cf84e05b5b6484a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Jean?= Date: Wed, 26 Aug 2026 10:37:43 +0000 Subject: [PATCH 033/146] crypto: rsassa-pkcs1 - reject undersized keys when signing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rsassa_pkcs1_sign() subtracts 11 from the unsigned key size before checking that the key is large enough for PKCS#1 v1.5 padding: if (slen + hash_prefix->size > ctx->key_size - 11) return -EOVERFLOW; If the RSA modulus is shorter than 11 bytes, the subtraction wraps. With a one-byte key and hash=none, the padding memset() writes past the output buffer. KASAN reports: BUG: KASAN: slab-out-of-bounds in rsassa_pkcs1_sign+0x1ad/0x3b0 Write of size 4294967294 at addr ... The buggy address is located 0 bytes to the right of allocated 1-byte region [...] Reject keys shorter than the minimum encoded message size. Fixes: 3d5b1ecdea6f ("crypto: rsa - RSA padding algorithm") Assisted-by: Codex:gpt-5 Signed-off-by: Jérémy Jean Reviewed-by: Sudhakar Kuppusamy Signed-off-by: Herbert Xu --- crypto/rsassa-pkcs1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c index 94fa5e9600e7..d0e4a885397f 100644 --- a/crypto/rsassa-pkcs1.c +++ b/crypto/rsassa-pkcs1.c @@ -169,7 +169,7 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm, u8 *in_buf; int err; - if (!ctx->key_size) + if (ctx->key_size < 11) return -EINVAL; if (dlen < ctx->key_size) From 364e520095b26fa551a8e92f52119d0f38a4177b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Jean?= Date: Wed, 26 Aug 2026 10:37:44 +0000 Subject: [PATCH 034/146] crypto: rsassa-pkcs1 - reject undersized keys when verifying MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rsassa_pkcs1_verify() accepts any nonzero key size. With a one-byte key and a zero RSA result, the leading-zero handling decrements dst_len to zero and advances out_buf past the allocation. The next out_buf[0] access reads out of bounds. KASAN reports: BUG: KASAN: slab-out-of-bounds in rsassa_pkcs1_verify+0x79d/0x900 Read of size 1 at addr ... The buggy address is located 0 bytes to the right of allocated 73-byte region [...] Reject keys shorter than the minimum PKCS#1 v1.5 encoded message size. Fixes: 3d5b1ecdea6f ("crypto: rsa - RSA padding algorithm") Assisted-by: Codex:gpt-5 Signed-off-by: Jérémy Jean Reviewed-by: Sudhakar Kuppusamy Signed-off-by: Herbert Xu --- crypto/rsassa-pkcs1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c index d0e4a885397f..39137476ce81 100644 --- a/crypto/rsassa-pkcs1.c +++ b/crypto/rsassa-pkcs1.c @@ -231,7 +231,7 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm, int err; /* RFC 8017 sec 8.2.2 step 1 - length checking */ - if (!ctx->key_size || + if (ctx->key_size < 11 || slen != ctx->key_size || rsassa_pkcs1_invalid_hash_len(dlen, hash_prefix)) return -EINVAL; From 9c53c82cefcd4668e8bed2d4029e24546aa89daf Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Thu, 27 Aug 2026 08:51:20 -0700 Subject: [PATCH 035/146] crypto: keembay - Remove bouncing maintainer The email for Mark Gross is bouncing. Remove the entry. Signed-off-by: Dave Hansen Cc: Prabhjot Khurana Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Signed-off-by: Herbert Xu --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 85ba874d6579..b8caac12d7c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13283,7 +13283,6 @@ F: drivers/crypto/intel/keembay/ocs-aes.h INTEL KEEM BAY OCS ECC CRYPTO DRIVER M: Prabhjot Khurana -M: Mark Gross S: Maintained F: Documentation/devicetree/bindings/crypto/intel,keembay-ocs-ecc.yaml F: drivers/crypto/intel/keembay/Kconfig From 8ba2b068e1b3607289ba5778e4c27c167fdbfee6 Mon Sep 17 00:00:00 2001 From: Li Youhong Date: Fri, 28 Aug 2026 10:54:23 +0800 Subject: [PATCH 036/146] hwrng: imx-rngc - check clk_prepare_enable() return value The driver ignored clk_prepare_enable() failures during probe and resume. If enabling the RNG clock fails, subsequent register accesses or resume after system sleep may not work while the driver still reports success. Signed-off-by: Li Youhong Reviewed-by: Frank Li Reviewed-by: Martin Kaiser Signed-off-by: Herbert Xu --- drivers/char/hw_random/imx-rngc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index 7693328f1056..0545a1870146 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -266,7 +266,9 @@ static int __init imx_rngc_probe(struct platform_device *pdev) if (irq < 0) return irq; - clk_prepare_enable(rngc->clk); + ret = clk_prepare_enable(rngc->clk); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Cannot enable rng_clk\n"); ver_id = readl(rngc->base + RNGC_VER_ID); rng_type = FIELD_GET(RNG_TYPE, ver_id); @@ -338,9 +340,7 @@ static int imx_rngc_resume(struct device *dev) { struct imx_rngc *rngc = dev_get_drvdata(dev); - clk_prepare_enable(rngc->clk); - - return 0; + return clk_prepare_enable(rngc->clk); } static const struct dev_pm_ops imx_rngc_pm_ops = { From ac1d6a65a1e1f069f119df42c6b57dbdff5f6be8 Mon Sep 17 00:00:00 2001 From: Linmao Li Date: Fri, 28 Aug 2026 17:32:09 +0800 Subject: [PATCH 037/146] crypto: mxs-dcp - handle zero-length skcipher requests Zero-length skcipher requests are valid no-ops, but MXS-DCP queues them. When such a request reaches the worker, last_out_len remains zero. The CBC completion path then subtracts AES_BLOCK_SIZE from this unsigned value when updating the IV, causing the offset to underflow. On decryption, the resulting source address precedes aes_in_buf. Return success before enqueueing zero-length requests. This avoids the invalid source access and leaves the IV unchanged for a no-op. Fixes: fadd7a6e616b ("crypto: mxs-dcp - Fix AES issues") Signed-off-by: Linmao Li Signed-off-by: Herbert Xu --- drivers/crypto/mxs-dcp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c index c75a06999787..d104d958cb61 100644 --- a/drivers/crypto/mxs-dcp.c +++ b/drivers/crypto/mxs-dcp.c @@ -473,6 +473,9 @@ static int mxs_dcp_aes_enqueue(struct skcipher_request *req, int enc, int ecb) struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req); int ret; + if (!req->cryptlen) + return 0; + if (unlikely(actx->key_len != AES_KEYSIZE_128 && !actx->key_referenced)) return mxs_dcp_block_fallback(req, enc); From dbe70508d507acd677e67eaf029040f5e3a3b2b3 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 29 Aug 2026 05:58:21 +0200 Subject: [PATCH 038/146] crypto: atmel-tdes - zero-initialize device state Commit c659d07f11a3 ("crypto: atmel-tdes - Switch to managed version of kzalloc") accidentally replaced kzalloc() with devm_kmalloc(), so the device state is no longer zeroed. atmel_tdes_hw_init() tests dd->flags during probe: a stale TDES_FLAGS_INIT skips the hardware reset, and a stale TDES_FLAGS_BUSY makes atmel_tdes_handle_queue() treat the engine as permanently busy, leaving every request queued and never dispatched. Seen on a SAM9X75 Curiosity: the first TDES request after boot never completes and the TDES interrupt count stays at zero, while the AES and SHA engines on the same SoC work normally. Switch to devm_kzalloc(), matching the Atmel AES and SHA drivers. Fixes: c659d07f11a3 ("crypto: atmel-tdes - Switch to managed version of kzalloc") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Karl Mehltretter Reviewed-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index ffea1db74651..2756dab3f4c7 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -933,7 +933,7 @@ static int atmel_tdes_probe(struct platform_device *pdev) struct resource *tdes_res; int err; - tdes_dd = devm_kmalloc(&pdev->dev, sizeof(*tdes_dd), GFP_KERNEL); + tdes_dd = devm_kzalloc(&pdev->dev, sizeof(*tdes_dd), GFP_KERNEL); if (!tdes_dd) return -ENOMEM; From 0dd8cded0e6f8c9635fe1d79d60dc7b2599b099b Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 29 Aug 2026 06:26:04 +0200 Subject: [PATCH 039/146] crypto: atmel-aes - fix AADLENR for standalone GHASH atmel_aes_gcm_ghash_init() writes dd->total, the request's text length, to AES_AADLENR. But the GHASH it runs hashes the dd->datalen bytes passed in: the 16-byte length block, or the padded IV when the IV is not 96 bits. The data sheet requires AES_AADLENR to hold the length of that input. With empty plaintext and empty AAD, dd->total is 0 and the tag comes out wrong. Later requests only pass because dd->total still holds the previous request's length. This is testmgr's first gcm(aes) vector, so CONFIG_CRYPTO_SELFTESTS=y fails at boot: alg: aead: atmel-gcm-aes encryption test failed (wrong result) on test vector 0, cfg="in-place (one sglist)" Without selftests the broken atmel-gcm-aes is preferred at priority 300. Seen on a SAM9X75 Curiosity with 6.18 and current mainline. Write dd->datalen instead. Fixes: d4419548dba9 ("crypto: atmel-aes - add support to GCM mode") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Karl Mehltretter Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 50d97cef75b8..8e4de859cadc 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -1267,7 +1267,7 @@ static int atmel_aes_gcm_ghash_init(struct atmel_aes_dev *dd) struct atmel_aes_gcm_ctx *ctx = atmel_aes_gcm_ctx_cast(dd->ctx); /* Set the data length. */ - atmel_aes_write(dd, AES_AADLENR, dd->total); + atmel_aes_write(dd, AES_AADLENR, dd->datalen); atmel_aes_write(dd, AES_CLENR, 0); /* If needed, overwrite the GCM Intermediate Hash Word Registers */ From 38ed7182f3491ec1449ff246551e11ad82adba45 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 29 Aug 2026 11:18:49 +0200 Subject: [PATCH 040/146] lib/842: reject output overflows from index and short data The output length passed to sw842_decompress() is the caller's buffer capacity. Indexed copies write 2, 4 or 8 bytes and short-data templates write up to 7, but neither checks that capacity before writing and decrementing p->olen. Overwriting an undersized destination then underflows p->olen, which is unsigned, so every later bounds check in the stream passes. Subsequent operations keep writing past the destination, and a matching CRC lets sw842_decompress() return success with an output length larger than the capacity the caller supplied. This is reachable through zram's compressed writeback path. With 842 selected, targeted corruption of the compressed data on its backing device made a KASAN kernel report vmalloc-out-of-bounds writes in __do_index() and sw842_decompress() when zram read the page back. Check the remaining output before both operations and return -ENOSPC, matching the other output-producing templates. Fixes: 2da572c959dd ("lib: add software 842 compression/decompression") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Karl Mehltretter Signed-off-by: Herbert Xu --- lib/842/842_decompress.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/842/842_decompress.c b/lib/842/842_decompress.c index 582085ef8b49..87d1e0f8a492 100644 --- a/lib/842/842_decompress.c +++ b/lib/842/842_decompress.c @@ -165,6 +165,9 @@ static int __do_index(struct sw842_param *p, u8 size, u8 bits, u64 fsize) u64 index, offset, total = round_down(p->out - p->ostart, 8); int ret; + if (size > p->olen) + return -ENOSPC; + ret = next_bits(p, &index, bits); if (ret) return ret; @@ -344,6 +347,8 @@ int sw842_decompress(const u8 *in, unsigned int ilen, if (!bytes || bytes > SHORT_DATA_BITS_MAX) return -EINVAL; + if (bytes > p.olen) + return -ENOSPC; while (bytes-- > 0) { ret = next_bits(&p, &tmp, 8); From deb631649882bbf43f7c2fc79b5990139fd744ba Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 29 Aug 2026 11:18:50 +0200 Subject: [PATCH 041/146] lib/842: require a complete history block for repeat templates An 842 repeat template copies the preceding eight-byte output block. The decoder rejects a repeat only when no output has been produced. A short-data operation can produce between one and seven bytes before a repeat. Such a stream makes the repeat copy read before the start of the output buffer. Depending on the surrounding mapping, this can fault or bring preceding memory into the decompressed data. This is also reachable through zram's compressed writeback path. With 842 selected, targeted corruption of the compressed data on its backing device to a short-data-then-repeat stream made a KASAN kernel report a vmalloc-out-of-bounds read when zram read the page back. Require at least one complete output block before accepting a repeat. Fixes: 2da572c959dd ("lib: add software 842 compression/decompression") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Karl Mehltretter Signed-off-by: Herbert Xu --- lib/842/842_decompress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/842/842_decompress.c b/lib/842/842_decompress.c index 87d1e0f8a492..45a9815abd63 100644 --- a/lib/842/842_decompress.c +++ b/lib/842/842_decompress.c @@ -309,7 +309,7 @@ int sw842_decompress(const u8 *in, unsigned int ilen, if (ret) return ret; - if (p.out == out) /* no previous bytes */ + if (p.out - p.ostart < 8) /* no complete previous block */ return -EINVAL; /* copy rep + 1 */ From cca072cb1423191c753b428dd5d179a5162c9cda Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 29 Aug 2026 11:18:51 +0200 Subject: [PATCH 042/146] lib/842: add KUnit tests for the decompressor Add table-driven tests for the 842 decompressor's output and history validation. Three malformed streams cover an indexed copy larger than the remaining output, short data larger than the remaining output, and a repeat after fewer than eight output bytes. Every case checks the return value, output length and fixed guard bands on both sides of the output. Successful cases also check complete contents from a poison-filled destination. The repeat vector's CRC includes the leading guard byte, so the unfixed decoder successfully validates the CRC after reading before the buffer. Three valid streams cover the same boundaries at equality: an I8 index consuming the final eight bytes, five short-data bytes consuming the final five, and a repeat with exactly one block of history. On an unmodified baseline the malformed cases fail and the boundary cases pass; with the preceding fixes all six pass. Assisted-by: LLM Signed-off-by: Karl Mehltretter Signed-off-by: Herbert Xu --- MAINTAINERS | 1 + lib/Kconfig.debug | 15 ++++ lib/tests/842_decompress_kunit.c | 144 +++++++++++++++++++++++++++++++ lib/tests/Makefile | 1 + 4 files changed, 161 insertions(+) create mode 100644 lib/tests/842_decompress_kunit.c diff --git a/MAINTAINERS b/MAINTAINERS index b8caac12d7c4..c3bcdcaa9b92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12459,6 +12459,7 @@ F: drivers/crypto/nx/Makefile F: drivers/crypto/nx/nx-842* F: include/linux/sw842.h F: lib/842/ +F: lib/tests/842_decompress_kunit.c IBM Power in-Nest Crypto Acceleration M: Breno Leitão diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 134b15a44625..48201092b3df 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2225,6 +2225,21 @@ menuconfig RUNTIME_TESTING_MENU if RUNTIME_TESTING_MENU +config 842_DECOMPRESS_KUNIT_TEST + tristate "KUnit tests for the 842 decompressor" if !KUNIT_ALL_TESTS + depends on KUNIT + select 842_DECOMPRESS + default KUNIT_ALL_TESTS + help + Enable stream-validation and boundary tests for the software 842 + decompressor. The tests exercise indexed copies, short data and + repeat operations at valid and invalid output or history boundaries. + + For more information on KUnit and unit tests in general, refer to + Documentation/dev-tools/kunit/. + + If unsure, say N. + config TEST_DHRY tristate "Dhrystone benchmark test" help diff --git a/lib/tests/842_decompress_kunit.c b/lib/tests/842_decompress_kunit.c new file mode 100644 index 000000000000..11202ba9539b --- /dev/null +++ b/lib/tests/842_decompress_kunit.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +#define SW842_GUARD_SIZE 8 +#define SW842_MAX_OUTPUT 16 +#define SW842_GUARD_BYTE 0x42 +#define SW842_OUTPUT_POISON 0x5a + +/* ZEROS, I8(0), END, CRC32. */ +static const u8 sw842_index_exact_fit[] = { + 0xe6, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, +}; + +/* D8(eight zero bytes), I8(0), END, CRC32. */ +static const u8 sw842_index_output_overflow[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, +}; + +/* ZEROS, SHORT_DATA(01 02 03 04 05), END, CRC32. */ +static const u8 sw842_short_data_exact_fit[] = { + 0xe7, 0x68, 0x08, 0x10, 0x18, 0x20, + 0x2f, 0xa9, 0x67, 0xfc, 0x07, 0xc0, +}; + +/* ZEROS, SHORT_DATA(five zero bytes), END, CRC32. */ +static const u8 sw842_short_data_output_overflow[] = { + 0xe7, 0x48, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, +}; + +/* ZEROS, REPEAT(one block), END, CRC32. */ +static const u8 sw842_repeat_exact_history[] = { + 0xe6, 0xc0, 0xf0, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * SHORT_DATA(seven zero bytes), REPEAT(one block), END, CRC32. + * CRC32 includes SW842_GUARD_BYTE copied from before output into byte 7. + */ +static const u8 sw842_repeat_without_full_history[] = { + 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xd8, 0x1e, 0x09, 0xa3, 0x1d, 0xd6, +}; + +static const u8 sw842_zero_output[SW842_MAX_OUTPUT]; +static const u8 sw842_short_data_output[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, +}; + +struct sw842_decompress_test_case { + const char *name; + const u8 *compressed; + unsigned int compressed_len; + const u8 *expected_output; + unsigned int output_capacity; + int expected_ret; +}; + +#define SW842_DECOMPRESS_CASE(_name, _compressed, _compressed_len, _expected, \ + _capacity, _ret) \ + { \ + .name = _name, \ + .compressed = _compressed, \ + .compressed_len = _compressed_len, \ + .expected_output = _expected, \ + .output_capacity = _capacity, \ + .expected_ret = _ret, \ + } + +static const struct sw842_decompress_test_case sw842_decompress_cases[] = { + SW842_DECOMPRESS_CASE("index_exact_fit", sw842_index_exact_fit, + ARRAY_SIZE(sw842_index_exact_fit), + sw842_zero_output, 16, 0), + SW842_DECOMPRESS_CASE("index_output_overflow", + sw842_index_output_overflow, + ARRAY_SIZE(sw842_index_output_overflow), + sw842_zero_output, 8, -ENOSPC), + SW842_DECOMPRESS_CASE("short_data_exact_fit", + sw842_short_data_exact_fit, + ARRAY_SIZE(sw842_short_data_exact_fit), + sw842_short_data_output, + sizeof(sw842_short_data_output), 0), + SW842_DECOMPRESS_CASE("short_data_output_overflow", + sw842_short_data_output_overflow, + ARRAY_SIZE(sw842_short_data_output_overflow), + sw842_zero_output, 8, -ENOSPC), + SW842_DECOMPRESS_CASE("repeat_exact_history", + sw842_repeat_exact_history, + ARRAY_SIZE(sw842_repeat_exact_history), + sw842_zero_output, 16, 0), + SW842_DECOMPRESS_CASE("repeat_without_full_history", + sw842_repeat_without_full_history, + ARRAY_SIZE(sw842_repeat_without_full_history), + sw842_zero_output, 15, -EINVAL), +}; + +KUNIT_ARRAY_PARAM_DESC(sw842_decompress, sw842_decompress_cases, name); + +static void sw842_decompress_test(struct kunit *test) +{ + const struct sw842_decompress_test_case *test_case = test->param_value; + u8 storage[SW842_GUARD_SIZE + SW842_MAX_OUTPUT + SW842_GUARD_SIZE]; + u8 expected_guard[SW842_GUARD_SIZE]; + u8 *output = storage + SW842_GUARD_SIZE; + unsigned int output_len = test_case->output_capacity; + int ret; + + KUNIT_ASSERT_LE(test, test_case->output_capacity, SW842_MAX_OUTPUT); + memset(storage, SW842_GUARD_BYTE, sizeof(storage)); + memset(expected_guard, SW842_GUARD_BYTE, sizeof(expected_guard)); + memset(output, SW842_OUTPUT_POISON, test_case->output_capacity); + + ret = sw842_decompress(test_case->compressed, + test_case->compressed_len, output, &output_len); + + KUNIT_EXPECT_EQ(test, ret, test_case->expected_ret); + /* Every successful case is an exact-fit boundary test. */ + KUNIT_EXPECT_EQ(test, output_len, + test_case->expected_ret ? 0U : test_case->output_capacity); + if (!test_case->expected_ret) + KUNIT_EXPECT_MEMEQ(test, output, test_case->expected_output, + test_case->output_capacity); + KUNIT_EXPECT_MEMEQ(test, storage, expected_guard, SW842_GUARD_SIZE); + KUNIT_EXPECT_MEMEQ(test, output + test_case->output_capacity, + expected_guard, SW842_GUARD_SIZE); +} + +static struct kunit_case sw842_decompress_test_cases[] = { + KUNIT_CASE_PARAM(sw842_decompress_test, sw842_decompress_gen_params), + {} +}; + +static struct kunit_suite sw842_decompress_test_suite = { + .name = "842-decompress", + .test_cases = sw842_decompress_test_cases, +}; + +kunit_test_suite(sw842_decompress_test_suite); + +MODULE_DESCRIPTION("Software 842 decompressor KUnit tests"); +MODULE_LICENSE("GPL"); diff --git a/lib/tests/Makefile b/lib/tests/Makefile index 3cac3b63a752..89ce3acad9c3 100644 --- a/lib/tests/Makefile +++ b/lib/tests/Makefile @@ -4,6 +4,7 @@ # KUnit tests CFLAGS_bitfield_kunit.o := $(DISABLE_STRUCTLEAK_PLUGIN) +obj-$(CONFIG_842_DECOMPRESS_KUNIT_TEST) += 842_decompress_kunit.o obj-$(CONFIG_BASE64_KUNIT) += base64_kunit.o obj-$(CONFIG_BITOPS_KUNIT) += bitops_kunit.o obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o From 347c5e29a58cc146949185244b69512e1624eb0e Mon Sep 17 00:00:00 2001 From: lizhi Date: Sat, 29 Aug 2026 17:49:24 +0800 Subject: [PATCH 043/146] crypto: hisilicon/zip - enable auto clock gating for DAE Enable auto clock gating for the DAE module. The clock gating is enabled after DAE initialization is completed, so the device can reduce power consumption when idle. Signed-off-by: lizhi Signed-off-by: Chenghai Huang Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/zip/dae_main.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/hisilicon/zip/dae_main.c b/drivers/crypto/hisilicon/zip/dae_main.c index 68aebd02fc84..57ea836a265e 100644 --- a/drivers/crypto/hisilicon/zip/dae_main.c +++ b/drivers/crypto/hisilicon/zip/dae_main.c @@ -39,6 +39,8 @@ #define DAE_AM_RETURN_MASK 0x3 #define DAE_AXI_CFG_OFFSET 0x331000 #define DAE_AXI_SHUTDOWN_EN_MASK (BIT(0) | BIT(5)) +#define DAE_AUTO_CG_EN_OFFSET 0x331070 +#define DAE_AUTO_CG_EN_MASK (~(BIT_ULL(4) | BIT_ULL(18) | BIT_ULL(19))) struct hisi_dae_hw_error { u32 int_msk; @@ -61,6 +63,17 @@ static inline bool dae_is_support(struct hisi_qm *qm) return false; } +static void hisi_dae_set_clock_gating(struct hisi_qm *qm, bool enable) +{ + if (qm->ver < QM_HW_V5) + return; + + if (enable) + writeq(DAE_AUTO_CG_EN_MASK, qm->io_base + DAE_AUTO_CG_EN_OFFSET); + else + writeq(0, qm->io_base + DAE_AUTO_CG_EN_OFFSET); +} + int hisi_dae_set_user_domain(struct hisi_qm *qm) { u32 val; @@ -69,16 +82,22 @@ int hisi_dae_set_user_domain(struct hisi_qm *qm) if (!dae_is_support(qm)) return 0; + hisi_dae_set_clock_gating(qm, false); + val = readl(qm->io_base + DAE_MEM_START_OFFSET); val |= DAE_MEM_START_MASK; writel(val, qm->io_base + DAE_MEM_START_OFFSET); ret = readl_relaxed_poll_timeout(qm->io_base + DAE_MEM_DONE_OFFSET, val, val & DAE_MEM_DONE_MASK, DAE_REG_RD_INTVRL_US, DAE_REG_RD_TMOUT_US); - if (ret) + if (ret) { pci_err(qm->pdev, "failed to init dae memory!\n"); + return ret; + } - return ret; + hisi_dae_set_clock_gating(qm, true); + + return 0; } int hisi_dae_set_alg(struct hisi_qm *qm) From ba871255f796d1f599ba710f03e1803d1b374a75 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 29 Aug 2026 21:43:14 +0200 Subject: [PATCH 044/146] crypto: lskcipher - preserve state across unaligned chunks crypto_lskcipher_crypt_unaligned() splits a request into page-sized chunks but never sets CRYPTO_LSKCIPHER_FLAG_CONT, so a stateful algorithm restarts from its keyed state at every page boundary. It also marks every chunk CRYPTO_LSKCIPHER_FLAG_FINAL, which is wrong but harmless: chunks are trimmed to a multiple of the chunk size, so the trailing partial block that FINAL guards against is caught after the loop instead. ARC4 is the only lskcipher with internal state, and cbc, the other in-tree user of the direct API, never passes more than one block, so this went unnoticed. bpf_crypto_crypt() however hands __bpf_dynptr_data() to crypto_lskcipher_encrypt() unchecked, leaving both alignment and length to the BPF program. An 8192-byte ARC4 request offset by one byte comes back with its second page identical to its first: the keystream is reused. Set FINAL only on the last chunk and CONT after the first, mirroring the progression used by crypto_lskcipher_crypt_sg(). Fixes: 0ae4dcc1ebf6 ("crypto: skcipher - Add internal state support") Assisted-by: LLM Signed-off-by: Karl Mehltretter Signed-off-by: Herbert Xu --- crypto/lskcipher.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crypto/lskcipher.c b/crypto/lskcipher.c index a8b07594005d..6c30436a1135 100644 --- a/crypto/lskcipher.c +++ b/crypto/lskcipher.c @@ -75,6 +75,7 @@ static int crypto_lskcipher_crypt_unaligned( unsigned ivsize = crypto_lskcipher_ivsize(tfm); unsigned bs = crypto_lskcipher_blocksize(tfm); unsigned cs = crypto_lskcipher_chunksize(tfm); + u32 flags = 0; int err; u8 *tiv; u8 *p; @@ -98,13 +99,16 @@ static int crypto_lskcipher_crypt_unaligned( if (chunk > cs) chunk &= ~(cs - 1); + if (chunk == len) + flags |= CRYPTO_LSKCIPHER_FLAG_FINAL; memcpy(p, src, chunk); - err = crypt(tfm, p, p, chunk, tiv, CRYPTO_LSKCIPHER_FLAG_FINAL); + err = crypt(tfm, p, p, chunk, tiv, flags); if (err) goto out; memcpy(dst, p, chunk); + flags |= CRYPTO_LSKCIPHER_FLAG_CONT; src += chunk; dst += chunk; len -= chunk; From e9b1d168f2a70c0764d5748893fdf631c504c171 Mon Sep 17 00:00:00 2001 From: Runyu Xiao Date: Sun, 30 Aug 2026 09:51:04 +0800 Subject: [PATCH 045/146] crypto: ccp - Initialize DBC ioctl mutex before registering device dbc_dev_init() registers the DBC misc device before initializing ioctl_mutex. Once misc_register() publishes the device, userspace can open it and invoke dbc_ioctl() while the mutex is still uninitialized. Initialize ioctl_mutex before calling misc_register() so the published ioctl callback always sees an initialized mutex. Fixes: c04cf9e14f10 ("crypto: ccp - Add support for fetching a nonce for dynamic boost control") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/all/20260829133410.1708684-1-runyu.xiao@seu.edu.cn/ Signed-off-by: Runyu Xiao Assisted-by: Codex:GPT-5 Reviewed-by: Tom Lendacky Reviewed-by: Mario Limonciello (AMD) > --- Signed-off-by: Herbert Xu --- drivers/crypto/ccp/dbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/ccp/dbc.c b/drivers/crypto/ccp/dbc.c index 410084a9039c..4db49a14550c 100644 --- a/drivers/crypto/ccp/dbc.c +++ b/drivers/crypto/ccp/dbc.c @@ -236,6 +236,8 @@ int dbc_dev_init(struct psp_device *psp) goto cleanup_mbox; } + mutex_init(&dbc_dev->ioctl_mutex); + dbc_dev->char_dev.minor = MISC_DYNAMIC_MINOR; dbc_dev->char_dev.name = "dbc"; dbc_dev->char_dev.fops = &dbc_fops; @@ -244,8 +246,6 @@ int dbc_dev_init(struct psp_device *psp) if (ret) goto cleanup_mbox; - mutex_init(&dbc_dev->ioctl_mutex); - return 0; cleanup_mbox: From e619f9b991482220c52489a94caeddffe278e256 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 31 Aug 2026 00:01:51 +0200 Subject: [PATCH 046/146] dt-bindings: trivial-devices: add atmel,atecc608a Add an entry for ATECC608A. Signed-off-by: Thorsten Blum Acked-by: Conor Dooley Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/trivial-devices.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index 2de8eb09cb7d..3b7876c5a45d 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -69,6 +69,8 @@ properties: - asteralabs,pt5161l # ATECC508A - i2c h/w elliptic curve crypto module - atmel,atecc508a + # ATECC608A - i2c h/w elliptic curve crypto module + - atmel,atecc608a # ATECC608B - i2c h/w elliptic curve crypto module - atmel,atecc608b # ATSHA204 - i2c h/w symmetric crypto module From 9e06d371730b841ad8fe79ebfccf0def9470201f Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 31 Aug 2026 00:01:52 +0200 Subject: [PATCH 047/146] crypto: atmel-ecc - add support for atecc608a The driver already supports the ATECC508A and ATECC608B and uses only commands shared by these devices. Microchip documents the ATECC608B as a backwards-compatible, functional drop-in replacement for the ATECC608A, with the same device structure and command interface [1]. Therefore, add support for the ATECC608A. ATECC608A hardware was not available for testing. Signed-off-by: Thorsten Blum Link: https://ww1.microchip.com/downloads/en/Appnotes/Migrating-from-the-ATECC608A-to-the-ATECC608B-DS40002237A.pdf [1] Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 075f38a67935..0904bb47fd0a 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -348,6 +348,7 @@ static void atmel_ecc_remove(struct i2c_client *client) static const struct of_device_id atmel_ecc_dt_ids[] = { { .compatible = "atmel,atecc508a", }, + { .compatible = "atmel,atecc608a", }, { .compatible = "atmel,atecc608b", }, { } }; @@ -355,6 +356,7 @@ MODULE_DEVICE_TABLE(of, atmel_ecc_dt_ids); static const struct i2c_device_id atmel_ecc_id[] = { { .name = "atecc508a" }, + { .name = "atecc608a" }, { .name = "atecc608b" }, { } }; From f66452a888e60fec5046c7fbdea1da1fcdaff98b Mon Sep 17 00:00:00 2001 From: Nitesh Venkatesh Date: Mon, 31 Aug 2026 06:32:33 +0000 Subject: [PATCH 048/146] crypto: qat - allow KPT disable when service is not asym The KPT (Key Protection Technology) enable sysfs attribute rejects any write when the currently enabled service is not 'asym', including writes that disable KPT. This blocks a legitimate recovery flow: 1. Configure the 'asym' service and enable KPT. 2. Bring the device up, then down. 3. Reconfigure the service to 'sym' and bring the device up. 4. KPT is still reported as enabled, but is not active because the asymmetric service is no longer configured. 5. Bring the device back down so the KPT enable attribute becomes writable. 6. Writing '0' to the KPT enable attribute to clear the stale flag fails with: "KPT can only be enabled when the asymmetric service is enabled" The asym-service check is only meaningful when enabling KPT; disabling must always be permitted so a stale enable flag can be cleared after the service configuration has changed. Parse the user-supplied boolean before the service check and gate the check on the enable direction. Disable requests are now accepted regardless of the currently configured service, provided the device is in the down state (which the attribute already requires for any write). Fixes: fb98254a5eb9 ("crypto: qat - add KPT support for GEN6 devices") Signed-off-by: Nitesh Venkatesh Reviewed-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Signed-off-by: Herbert Xu --- .../intel/qat/qat_common/adf_sysfs_kpt.c | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.c index 1f733ae80bdf..a0db98f33f1f 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.c +++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs_kpt.c @@ -31,6 +31,7 @@ static ssize_t enable_store(struct device *dev, struct device_attribute *attr, struct adf_hw_device_data *hw_data; struct adf_accel_dev *accel_dev; bool enable; + int svc; int ret; accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); @@ -38,14 +39,25 @@ static ssize_t enable_store(struct device *dev, struct device_attribute *attr, return -EINVAL; if (adf_dev_started(accel_dev)) { - dev_info(dev, "Device qat_dev%d must be down before enabling KPT\n", + dev_info(dev, "Device qat_dev%d must be down before changing KPT state\n", accel_dev->accel_id); return -EINVAL; } - if (adf_get_service_enabled(accel_dev) != SVC_ASYM) { - dev_info(dev, "KPT can only be enabled when the asymmetric service is enabled\n"); - return -EINVAL; + ret = kstrtobool(buf, &enable); + if (ret) + return ret; + + if (enable) { + svc = adf_get_service_enabled(accel_dev); + if (svc < 0) + return svc; + + if (svc != SVC_ASYM) { + dev_info(dev, + "KPT can only be enabled when the asymmetric crypto service is enabled\n"); + return -EINVAL; + } } hw_data = GET_HW_DATA(accel_dev); @@ -59,10 +71,6 @@ static ssize_t enable_store(struct device *dev, struct device_attribute *attr, if (!hw_data->accel_capabilities_mask) return -EINVAL; - ret = kstrtobool(buf, &enable); - if (ret) - return ret; - user_data = GET_KPT_USER_DATA(accel_dev); user_data->enable = enable; From 1b364f648ec67ca3589c0eb5a3937268942c2940 Mon Sep 17 00:00:00 2001 From: Nitesh Venkatesh Date: Mon, 31 Aug 2026 06:32:34 +0000 Subject: [PATCH 049/146] Documentation: qat: clarify KPT enable device-state requirement The ABI description for /sys/bus/pci/devices//qat_kpt/enable did not mention that the device must be in the down state before the KPT enable attribute can be written. This requirement is enforced by the driver for both enabling and disabling KPT, but was not reflected in the ABI documentation, leaving users to discover it via -EINVAL. Update the description to note that the device must be in the down state before changing the KPT state. Signed-off-by: Nitesh Venkatesh Reviewed-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Signed-off-by: Herbert Xu --- Documentation/ABI/testing/sysfs-driver-qat_kpt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-driver-qat_kpt b/Documentation/ABI/testing/sysfs-driver-qat_kpt index c6480ea1fa4f..80831ce3d2ca 100644 --- a/Documentation/ABI/testing/sysfs-driver-qat_kpt +++ b/Documentation/ABI/testing/sysfs-driver-qat_kpt @@ -14,7 +14,8 @@ Contact: qat-linux@intel.com Description: (RW) Enables or disables Key Protection Technology (KPT). - Write 1 to enable KPT, or 0 to disable it. + Write 1 to enable KPT, or 0 to disable it. The device must be + in the down state before changing the KPT state. Example usage:: From b2bfe391b8847db567d670d7e3090092af6b8182 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 1 Sep 2026 10:11:27 +0200 Subject: [PATCH 050/146] crypto: atmel-ecc - simplify atmel_ecdh_compute_shared_secret Free work_data and return ret directly to simplify the control flow. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-ecc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 0904bb47fd0a..b538e818a26f 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -177,16 +177,14 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_request *req) work_data->client = ctx->client; ret = atmel_i2c_init_ecdh_cmd(&work_data->cmd, req->src); - if (ret) - goto free_work_data; + if (ret) { + kfree(work_data); + return ret; + } atmel_i2c_enqueue(work_data, atmel_ecdh_done, req); return -EINPROGRESS; - -free_work_data: - kfree(work_data); - return ret; } static struct i2c_client *atmel_ecc_i2c_client_alloc(void) From 75ed7550da436aeefbe86c1d3e46d9d7e4fcc940 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 1 Sep 2026 11:54:38 -0700 Subject: [PATCH 051/146] crypto: ccp - repair all kernel-doc comments Eliminate all kernel-doc warnings in : - add Returns: for function return values - use the enum keyword when describing an enum in kernel-doc - add missing enum value descriptions - add or repair missing struct member descriptions - use nested struct notation as needed Warning: include/linux/ccp.h:30 No description found for return value of 'ccp_present' Warning: include/linux/ccp.h:42 No description found for return value of 'ccp_version' Warning: include/linux/ccp.h:67 No description found for return value of 'ccp_enqueue_cmd' Warning: include/linux/ccp.h:97 cannot understand function prototype: 'enum ccp_aes_type' Warning: include/linux/ccp.h:114 cannot understand function prototype: 'enum ccp_aes_mode' Warning: include/linux/ccp.h:128 Enum value 'CCP_AES_MODE_GHASH' not described in enum 'ccp_aes_mode' Warning: include/linux/ccp.h:128 Enum value 'CCP_AES_MODE_GCTR' not described in enum 'ccp_aes_mode' Warning: include/linux/ccp.h:128 Enum value 'CCP_AES_MODE_GCM' not described in enum 'ccp_aes_mode' Warning: include/linux/ccp.h:128 Enum value 'CCP_AES_MODE_GMAC' not described in enum 'ccp_aes_mode' Warning: include/linux/ccp.h:134 cannot understand function prototype: 'enum ccp_aes_action' Warning: include/linux/ccp.h:190 struct member 'authsize' not described in 'ccp_aes_engine' Warning: include/linux/ccp.h:190 struct member 'aad_len' not described in 'ccp_aes_engine' Warning: include/linux/ccp.h:202 cannot understand function prototype: 'enum ccp_xts_aes_unit_size' Warning: include/linux/ccp.h:245 struct member 'type' not described in 'ccp_xts_aes_engine' Warning: include/linux/ccp.h:255 cannot understand function prototype: 'enum ccp_sha_type' Warning: include/linux/ccp.h:394 cannot understand function prototype: 'enum ccp_passthru_bitwise' Warning: include/linux/ccp.h:410 cannot understand function prototype: 'enum ccp_passthru_byteswap' Warning: include/linux/ccp.h:472 struct member 'src_dma' not described in 'ccp_passthru_nomap_engine' Warning: include/linux/ccp.h:472 struct member 'dst_dma' not described in 'ccp_passthru_nomap_engine' Warning: include/linux/ccp.h:472 Excess struct member 'src' description in 'ccp_passthru_nomap_engine' (did you mean one of: 'src_len', 'src_dma') Warning: include/linux/ccp.h:472 Excess struct member 'dst' description in 'ccp_passthru_nomap_engine' (did you mean one of: 'dst_dma') Warning: include/linux/ccp.h:489 cannot understand function prototype: 'enum ccp_ecc_function' Warning: include/linux/ccp.h:587 struct member 'u' not described in 'ccp_ecc_engine' Warning: include/linux/ccp.h:587 Excess struct member 'mm' description in 'ccp_ecc_engine' (did you mean one of: 'u.mm') Warning: include/linux/ccp.h:587 Excess struct member 'pm' description in 'ccp_ecc_engine' (did you mean one of: 'u.pm') Warning: include/linux/ccp.h:602 cannot understand function prototype: 'enum ccp_engine' Signed-off-by: Randy Dunlap Acked-by: Tom Lendacky Signed-off-by: Herbert Xu --- include/linux/ccp.h | 58 +++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/include/linux/ccp.h b/include/linux/ccp.h index 868924dec5a1..e6c599243f11 100644 --- a/include/linux/ccp.h +++ b/include/linux/ccp.h @@ -26,7 +26,7 @@ struct ccp_cmd; /** * ccp_present - check if a CCP device is present * - * Returns zero if a CCP device is present, -ENODEV otherwise. + * Returns: zero if a CCP device is present, -ENODEV otherwise. */ int ccp_present(void); @@ -38,7 +38,7 @@ int ccp_present(void); /** * ccp_version - get the version of the CCP * - * Returns a positive version number, or zero if no CCP + * Returns: a positive version number, or zero if no CCP */ unsigned int ccp_version(void); @@ -61,9 +61,9 @@ unsigned int ccp_version(void); * will be -EINPROGRESS. Any other "err" value during callback is * the result of the operation. * - * The cmd has been successfully queued if: - * the return code is -EINPROGRESS or - * the return code is -EBUSY and CCP_CMD_MAY_BACKLOG flag is set + * Returns: The cmd has been successfully queued if: + * * the return code is -EINPROGRESS or + * * the return code is -EBUSY and CCP_CMD_MAY_BACKLOG flag is set */ int ccp_enqueue_cmd(struct ccp_cmd *cmd); @@ -89,7 +89,7 @@ static inline int ccp_enqueue_cmd(struct ccp_cmd *cmd) /***** AES engine *****/ /** - * ccp_aes_type - AES key size + * enum ccp_aes_type - AES key size * * @CCP_AES_TYPE_128: 128-bit key * @CCP_AES_TYPE_192: 192-bit key @@ -99,11 +99,12 @@ enum ccp_aes_type { CCP_AES_TYPE_128 = 0, CCP_AES_TYPE_192, CCP_AES_TYPE_256, + /* private: */ CCP_AES_TYPE__LAST, }; /** - * ccp_aes_mode - AES operation mode + * enum ccp_aes_mode - AES operation mode * * @CCP_AES_MODE_ECB: ECB mode * @CCP_AES_MODE_CBC: CBC mode @@ -111,6 +112,10 @@ enum ccp_aes_type { * @CCP_AES_MODE_CFB: CFB mode * @CCP_AES_MODE_CTR: CTR mode * @CCP_AES_MODE_CMAC: CMAC mode + * @CCP_AES_MODE_GHASH: GHASH mode + * @CCP_AES_MODE_GCTR: GCTR mode + * @CCP_AES_MODE_GCM: GCM mode + * @CCP_AES_MODE_GMAC: GMAC mode */ enum ccp_aes_mode { CCP_AES_MODE_ECB = 0, @@ -123,11 +128,12 @@ enum ccp_aes_mode { CCP_AES_MODE_GCTR, CCP_AES_MODE_GCM, CCP_AES_MODE_GMAC, + /* private: */ CCP_AES_MODE__LAST, }; /** - * ccp_aes_mode - AES operation mode + * enum ccp_aes_action - AES operation mode * * @CCP_AES_ACTION_DECRYPT: AES decrypt operation * @CCP_AES_ACTION_ENCRYPT: AES encrypt operation @@ -135,6 +141,7 @@ enum ccp_aes_mode { enum ccp_aes_action { CCP_AES_ACTION_DECRYPT = 0, CCP_AES_ACTION_ENCRYPT, + /* private: */ CCP_AES_ACTION__LAST, }; /* Overloaded field */ @@ -146,6 +153,7 @@ enum ccp_aes_action { * @type: AES operation key size * @mode: AES operation mode * @action: AES operation (decrypt/encrypt) + * @authsize: AES block request size * @key: key to be used for this AES operation * @key_len: length in bytes of key * @iv: IV to be used for this AES operation @@ -156,6 +164,7 @@ enum ccp_aes_action { * @cmac_final: indicates final operation when running in CMAC mode * @cmac_key: K1/K2 key used in final CMAC operation * @cmac_key_len: length in bytes of cmac_key + * @aad_len: length in bytes of Additional Authenticated Data * * Variables required to be set when calling ccp_enqueue_cmd(): * - type, mode, action, key, key_len, src, dst, src_len @@ -192,7 +201,7 @@ struct ccp_aes_engine { /***** XTS-AES engine *****/ /** - * ccp_xts_aes_unit_size - XTS unit size + * enum ccp_xts_aes_unit_size - XTS unit size * * @CCP_XTS_AES_UNIT_SIZE_16: Unit size of 16 bytes * @CCP_XTS_AES_UNIT_SIZE_512: Unit size of 512 bytes @@ -206,11 +215,13 @@ enum ccp_xts_aes_unit_size { CCP_XTS_AES_UNIT_SIZE_1024, CCP_XTS_AES_UNIT_SIZE_2048, CCP_XTS_AES_UNIT_SIZE_4096, + /* private: */ CCP_XTS_AES_UNIT_SIZE__LAST, }; /** * struct ccp_xts_aes_engine - CCP XTS AES operation + * @type: ccp_aes_type - AES key size * @action: AES operation (decrypt/encrypt) * @unit_size: unit size of the XTS operation * @key: key to be used for this XTS AES operation @@ -247,11 +258,13 @@ struct ccp_xts_aes_engine { /***** SHA engine *****/ /** - * ccp_sha_type - type of SHA operation + * enum ccp_sha_type - type of SHA operation * * @CCP_SHA_TYPE_1: SHA-1 operation * @CCP_SHA_TYPE_224: SHA-224 operation * @CCP_SHA_TYPE_256: SHA-256 operation + * @CCP_SHA_TYPE_384: SHA-384 operation + * @CCP_SHA_TYPE_512: SHA-512 operation */ enum ccp_sha_type { CCP_SHA_TYPE_1 = 1, @@ -259,6 +272,7 @@ enum ccp_sha_type { CCP_SHA_TYPE_256, CCP_SHA_TYPE_384, CCP_SHA_TYPE_512, + /* private: */ CCP_SHA_TYPE__LAST, }; @@ -384,7 +398,7 @@ struct ccp_rsa_engine { /***** Passthru engine *****/ /** - * ccp_passthru_bitwise - type of bitwise passthru operation + * enum ccp_passthru_bitwise - type of bitwise passthru operation * * @CCP_PASSTHRU_BITWISE_NOOP: no bitwise operation performed * @CCP_PASSTHRU_BITWISE_AND: perform bitwise AND of src with mask @@ -398,11 +412,12 @@ enum ccp_passthru_bitwise { CCP_PASSTHRU_BITWISE_OR, CCP_PASSTHRU_BITWISE_XOR, CCP_PASSTHRU_BITWISE_MASK, + /* private: */ CCP_PASSTHRU_BITWISE__LAST, }; /** - * ccp_passthru_byteswap - type of byteswap passthru operation + * enum ccp_passthru_byteswap - type of byteswap passthru operation * * @CCP_PASSTHRU_BYTESWAP_NOOP: no byte swapping performed * @CCP_PASSTHRU_BYTESWAP_32BIT: swap bytes within 32-bit words @@ -412,6 +427,7 @@ enum ccp_passthru_byteswap { CCP_PASSTHRU_BYTESWAP_NOOP = 0, CCP_PASSTHRU_BYTESWAP_32BIT, CCP_PASSTHRU_BYTESWAP_256BIT, + /* private: */ CCP_PASSTHRU_BYTESWAP__LAST, }; @@ -450,8 +466,8 @@ struct ccp_passthru_engine { * @byte_swap: byteswap operation to perform * @mask: mask to be applied to data * @mask_len: length in bytes of mask - * @src: data to be used for this operation - * @dst: data produced by this operation + * @src_dma: data to be used for this operation + * @dst_dma: data produced by this operation * @src_len: length in bytes of data used for this operation * @final: indicate final pass-through operation * @@ -478,7 +494,7 @@ struct ccp_passthru_nomap_engine { #define CCP_ECC_MAX_OUTPUTS 3 /** - * ccp_ecc_function - type of ECC function + * enum ccp_ecc_function - type of ECC function * * @CCP_ECC_FUNCTION_MMUL_384BIT: 384-bit modular multiplication * @CCP_ECC_FUNCTION_MADD_384BIT: 384-bit modular addition @@ -564,8 +580,9 @@ struct ccp_ecc_point_math { * @function: ECC function to perform * @mod: ECC modulus * @mod_len: length in bytes of modulus - * @mm: module math parameters - * @pm: point math parameters + * @u: union for math parameters + * @u.mm: module math parameters + * @u.pm: point math parameters * @ecc_result: result of the ECC operation * * Variables required to be set when calling ccp_enqueue_cmd(): @@ -589,11 +606,11 @@ struct ccp_ecc_engine { /** - * ccp_engine - CCP operation identifiers + * enum ccp_engine - CCP operation identifiers * * @CCP_ENGINE_AES: AES operation - * @CCP_ENGINE_XTS_AES: 128-bit XTS AES operation - * @CCP_ENGINE_RSVD1: unused + * @CCP_ENGINE_XTS_AES_128: 128-bit XTS AES operation + * @CCP_ENGINE_DES3: 3DES operation * @CCP_ENGINE_SHA: SHA operation * @CCP_ENGINE_RSA: RSA operation * @CCP_ENGINE_PASSTHRU: pass-through operation @@ -609,6 +626,7 @@ enum ccp_engine { CCP_ENGINE_PASSTHRU, CCP_ENGINE_ZLIB_DECOMPRESS, CCP_ENGINE_ECC, + /* private: */ CCP_ENGINE__LAST, }; From a38fdcb9c944525ca71e6aaf35e708586d0ae87d Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Wed, 2 Sep 2026 21:23:23 +0200 Subject: [PATCH 052/146] crypto: atmel-tdes - sync output bounce buffer before DMA The slow path maps its output bounce buffer once at probe time with dma_map_single() and DMA_FROM_DEVICE, then reuses the mapping for every request. After the CPU copies a result from the buffer, dma_sync_single_for_device() must hand the buffer back to the device before the next DMA transfer. The driver omits this call, so cache lines from the previous result can remain valid while the device writes the next one. This bug was masked by the completion paths calling dma_sync_single_for_device() immediately before the CPU copied the output, where dma_sync_single_for_cpu() was required. For DMA_FROM_DEVICE on ARM926, dma_sync_single_for_device() invokes arm926_dma_map_area(), which invalidates the cache lines. The misplaced call therefore discarded the stale lines before every copy-out. Commit c8a9a647532f ("crypto: atmel-tdes - fix DMA sync direction") correctly changed the completion paths to call dma_sync_single_for_cpu(). On ARM926, that function invokes arm926_dma_unmap_area(), which is a no-op. The missing pre-DMA dma_sync_single_for_device() was therefore exposed on ARM926-based SAM9X60 and SAM9X7 SoCs. With CONFIG_CRYPTO_SELFTESTS=y all four DES/TDES algorithms fail on SAM9X75: alg: skcipher: atmel-ecb-tdes encryption test failed (wrong result) on test vector 2, cfg="unaligned buffer, offset=1" Call dma_sync_single_for_device() for the output buffer before starting DMA in both atmel_tdes_crypt_pdc() and atmel_tdes_crypt_dma(). Fixes: c8a9a647532f ("crypto: atmel-tdes - fix DMA sync direction") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Karl Mehltretter Reviewed-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 2756dab3f4c7..ed80423b4209 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -370,6 +370,8 @@ static int atmel_tdes_crypt_pdc(struct atmel_tdes_dev *dd, if (!(dd->flags & TDES_FLAGS_FAST)) { dma_sync_single_for_device(dd->dev, dma_addr_in, length, DMA_TO_DEVICE); + dma_sync_single_for_device(dd->dev, dma_addr_out, length, + DMA_FROM_DEVICE); } len32 = DIV_ROUND_UP(length, sizeof(u32)); @@ -402,6 +404,8 @@ static int atmel_tdes_crypt_dma(struct atmel_tdes_dev *dd, if (!(dd->flags & TDES_FLAGS_FAST)) { dma_sync_single_for_device(dd->dev, dma_addr_in, length, DMA_TO_DEVICE); + dma_sync_single_for_device(dd->dev, dma_addr_out, length, + DMA_FROM_DEVICE); } addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; From 8f808c8f32b67d42ba97457a7054bd5954d02856 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Wed, 2 Sep 2026 22:54:28 +0200 Subject: [PATCH 053/146] crypto: eip93 - fix ssl mac bit field definition Checked the register definitions with the documentation[1]. Turns out that the EIP93_SA_CMD_SSL_MAC bit field has a bad value. It's used in SSL offload mode. This driver doesn't support SSL offload yet, so this causes no problems. 1. MT7621 ProgrammingGuide DMA Fixes: 9739f5f93b78 ("crypto: eip93 - Add Inside Secure SafeXcel EIP-93 crypto engine support") Signed-off-by: Aleksander Jan Bajkowski Signed-off-by: Herbert Xu --- drivers/crypto/inside-secure/eip93/eip93-regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/inside-secure/eip93/eip93-regs.h b/drivers/crypto/inside-secure/eip93/eip93-regs.h index 96d28c6651bd..1d726bcdd77f 100644 --- a/drivers/crypto/inside-secure/eip93/eip93-regs.h +++ b/drivers/crypto/inside-secure/eip93/eip93-regs.h @@ -281,7 +281,7 @@ #define EIP93_SA_CMD_HASH_CRYPT_OFFSET GENMASK(23, 16) #define EIP93_SA_CMD_BYTE_OFFSET BIT(13) /* 0: CRYPT_OFFSET in 32bit word 1: CRYPT_OFFSET in 8bit bytes */ #define EIP93_SA_CMD_HMAC BIT(12) -#define EIP93_SA_CMD_SSL_MAC BIT(12) +#define EIP93_SA_CMD_SSL_MAC BIT(11) /* This mask can be either used for ARC4 or AES */ #define EIP93_SA_CMD_CHIPER_MODE GENMASK(9, 8) /* AES or DES operations */ From 356892abad7751501cbe4d0b9e1bd61647279f3c Mon Sep 17 00:00:00 2001 From: "Pawel Zalewski (The Capable Hub)" Date: Thu, 3 Sep 2026 16:42:16 +0100 Subject: [PATCH 054/146] crypto: ccp - 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. While we are at it - unify the list terminator to have a single space between the brackets and no trailing comma. Signed-off-by: Pawel Zalewski (The Capable Hub) Acked-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sp-platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/ccp/sp-platform.c b/drivers/crypto/ccp/sp-platform.c index 3f9843fa7782..c7ac840cbe13 100644 --- a/drivers/crypto/ccp/sp-platform.c +++ b/drivers/crypto/ccp/sp-platform.c @@ -40,8 +40,8 @@ static const struct sp_dev_vdata dev_vdata[] = { }; static const struct acpi_device_id sp_acpi_match[] = { - { "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] }, - { }, + { .id = "AMDI0C00", .driver_data = (kernel_ulong_t)&dev_vdata[0] }, + { } }; MODULE_DEVICE_TABLE(acpi, sp_acpi_match); From f69442515f5b7d976469d18190bb4eb27243e99d Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 3 Sep 2026 23:08:46 +0200 Subject: [PATCH 055/146] crypto: atmel-tdes - simplify DMA buffer initialization Calculate the buffer length in a single statement and simplify the error handling. Inline the dma_mapping_error() checks and return -ENOMEM from the common error path. If mapping the output buffer fails, unmap the previously mapped input buffer first. Also use dev_err() to log errors and %zu to format size_t, and clarify the error messages. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index ed80423b4209..53150f9b169b 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -308,45 +308,33 @@ static int atmel_tdes_crypt_pdc_stop(struct atmel_tdes_dev *dd) static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd) { - int err = -ENOMEM; - 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); + dd->buflen = PAGE_SIZE & ~(DES_BLOCK_SIZE - 1); if (!dd->buf_in || !dd->buf_out) { - dev_dbg(dd->dev, "unable to alloc pages.\n"); + dev_err(dd->dev, "failed to allocate DMA buffers\n"); goto err_alloc; } - /* MAP here */ - dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, - dd->buflen, DMA_TO_DEVICE); - err = dma_mapping_error(dd->dev, dd->dma_addr_in); - if (err) { - dev_dbg(dd->dev, "dma %zd bytes error\n", dd->buflen); - goto err_map_in; - } + dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, dd->buflen, DMA_TO_DEVICE); + if (dma_mapping_error(dd->dev, dd->dma_addr_in)) + goto err_map; - dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, - dd->buflen, DMA_FROM_DEVICE); - err = dma_mapping_error(dd->dev, dd->dma_addr_out); - if (err) { - dev_dbg(dd->dev, "dma %zd bytes error\n", dd->buflen); - goto err_map_out; + dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, dd->buflen, DMA_FROM_DEVICE); + if (dma_mapping_error(dd->dev, dd->dma_addr_out)) { + dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE); + goto err_map; } return 0; -err_map_out: - dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, - DMA_TO_DEVICE); -err_map_in: +err_map: + dev_err(dd->dev, "failed to map %zu bytes for DMA\n", dd->buflen); err_alloc: free_page((unsigned long)dd->buf_out); free_page((unsigned long)dd->buf_in); - return err; + return -ENOMEM; } static void atmel_tdes_buff_cleanup(struct atmel_tdes_dev *dd) From 45889add0c943d89fea38ffe9897bb80cd494e68 Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Fri, 4 Sep 2026 17:13:39 +0530 Subject: [PATCH 056/146] crypto: drivers - fix typos in comments Fix typos in comments, reported by scripts/checkpatch.pl using the misspelling list in scripts/spelling.txt. Only touches comments, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Reviewed-by: Thomas Huth Acked-by: Bartosz Golaszewski Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 4 ++-- drivers/crypto/cavium/cpt/cptpf_main.c | 12 ++++++------ drivers/crypto/cavium/cpt/cptvf_main.c | 4 ++-- drivers/crypto/cavium/cpt/cptvf_mbox.c | 4 ++-- drivers/crypto/cavium/nitrox/nitrox_main.c | 2 +- drivers/crypto/ccp/ccp-dev.c | 2 +- drivers/crypto/ccree/cc_buffer_mgr.c | 4 ++-- drivers/crypto/chelsio/chcr_algo.c | 2 +- drivers/crypto/marvell/octeontx/otx_cptvf_mbox.c | 4 ++-- drivers/crypto/omap-sham.c | 4 ++-- drivers/crypto/qce/aead.c | 2 +- drivers/crypto/s5p-sss.c | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 48f54b615504..89c0a3bdf4e0 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -1203,7 +1203,7 @@ static int atmel_sha_finup(struct ahash_request *req) /* * final() has to be always called to cleanup resources - * even if udpate() failed, except EINPROGRESS + * even if update() failed, except EINPROGRESS */ err2 = atmel_sha_final(req); @@ -1338,7 +1338,7 @@ static int atmel_sha_done(struct atmel_sha_dev *dd) return err; finish: - /* finish curent request */ + /* finish current request */ atmel_sha_finish_req(dd->req, err); return err; diff --git a/drivers/crypto/cavium/cpt/cptpf_main.c b/drivers/crypto/cavium/cpt/cptpf_main.c index 9358c1c041d4..4234f9f156a3 100644 --- a/drivers/crypto/cavium/cpt/cptpf_main.c +++ b/drivers/crypto/cavium/cpt/cptpf_main.c @@ -90,19 +90,19 @@ static void cpt_configure_group(struct cpt_device *cpt, u8 grp, static void cpt_disable_mbox_interrupts(struct cpt_device *cpt) { - /* Clear mbox(0) interupts for all vfs */ + /* Clear mbox(0) interrupts for all vfs */ cpt_write_csr64(cpt->reg_base, CPTX_PF_MBOX_ENA_W1CX(0, 0), ~0ull); } static void cpt_disable_ecc_interrupts(struct cpt_device *cpt) { - /* Clear ecc(0) interupts for all vfs */ + /* Clear ecc(0) interrupts for all vfs */ cpt_write_csr64(cpt->reg_base, CPTX_PF_ECC0_ENA_W1C(0), ~0ull); } static void cpt_disable_exec_interrupts(struct cpt_device *cpt) { - /* Clear exec interupts for all vfs */ + /* Clear exec interrupts for all vfs */ cpt_write_csr64(cpt->reg_base, CPTX_PF_EXEC_ENA_W1C(0), ~0ull); } @@ -115,7 +115,7 @@ static void cpt_disable_all_interrupts(struct cpt_device *cpt) static void cpt_enable_mbox_interrupts(struct cpt_device *cpt) { - /* Set mbox(0) interupts for all vfs */ + /* Set mbox(0) interrupts for all vfs */ cpt_write_csr64(cpt->reg_base, CPTX_PF_MBOX_ENA_W1SX(0, 0), ~0ull); } @@ -140,10 +140,10 @@ static int cpt_load_microcode(struct cpt_device *cpt, struct microcode *mcode) */ if (mcode->is_ae) { core = CPT_MAX_SE_CORES; /* start couting from 10 */ - total_cores = CPT_MAX_TOTAL_CORES; /* upto 15 */ + total_cores = CPT_MAX_TOTAL_CORES; /* up to 15 */ } else { core = 0; /* start couting from 0 */ - total_cores = CPT_MAX_SE_CORES; /* upto 9 */ + total_cores = CPT_MAX_SE_CORES; /* up to 9 */ } /* Point to microcode for each core of the group */ diff --git a/drivers/crypto/cavium/cpt/cptvf_main.c b/drivers/crypto/cavium/cpt/cptvf_main.c index db76df14c4a0..e07448098ac0 100644 --- a/drivers/crypto/cavium/cpt/cptvf_main.c +++ b/drivers/crypto/cavium/cpt/cptvf_main.c @@ -417,7 +417,7 @@ static void cptvf_enable_swerr_interrupts(struct cpt_vf *cptvf) vqx_misc_ena.u = cpt_read_csr64(cptvf->reg_base, CPTX_VQX_MISC_ENA_W1S(0, 0)); - /* Set mbox(0) interupts for the requested vf */ + /* Set mbox(0) interrupts for the requested vf */ vqx_misc_ena.s.swerr = 1; cpt_write_csr64(cptvf->reg_base, CPTX_VQX_MISC_ENA_W1S(0, 0), vqx_misc_ena.u); @@ -429,7 +429,7 @@ static void cptvf_enable_mbox_interrupts(struct cpt_vf *cptvf) vqx_misc_ena.u = cpt_read_csr64(cptvf->reg_base, CPTX_VQX_MISC_ENA_W1S(0, 0)); - /* Set mbox(0) interupts for the requested vf */ + /* Set mbox(0) interrupts for the requested vf */ vqx_misc_ena.s.mbox = 1; cpt_write_csr64(cptvf->reg_base, CPTX_VQX_MISC_ENA_W1S(0, 0), vqx_misc_ena.u); diff --git a/drivers/crypto/cavium/cpt/cptvf_mbox.c b/drivers/crypto/cavium/cpt/cptvf_mbox.c index 1267e1eba7e9..9f2ae10bbd60 100644 --- a/drivers/crypto/cavium/cpt/cptvf_mbox.c +++ b/drivers/crypto/cavium/cpt/cptvf_mbox.c @@ -120,7 +120,7 @@ int cptvf_send_vq_size_msg(struct cpt_vf *cptvf) } /* - * Communicate VF group required to PF and get the VQ binded to that group + * Communicate VF group required to PF and get the VQ bound to that group */ int cptvf_send_vf_to_grp_msg(struct cpt_vf *cptvf) { @@ -139,7 +139,7 @@ int cptvf_send_vf_to_grp_msg(struct cpt_vf *cptvf) } /* - * Communicate VF group required to PF and get the VQ binded to that group + * Communicate VF group required to PF and get the VQ bound to that group */ int cptvf_send_vf_priority_msg(struct cpt_vf *cptvf) { diff --git a/drivers/crypto/cavium/nitrox/nitrox_main.c b/drivers/crypto/cavium/nitrox/nitrox_main.c index e474c84d8d38..54b2db6bb5d0 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_main.c +++ b/drivers/crypto/cavium/nitrox/nitrox_main.c @@ -468,7 +468,7 @@ static int nitrox_probe(struct pci_dev *pdev, err = -EIO; goto ioremap_err; } - /* allocate command queus based on cpus, max queues are 64 */ + /* allocate command queues based on cpus, max queues are 64 */ ndev->nr_queues = min_t(u32, MAX_PF_QUEUES, num_online_cpus()); ndev->qlen = qlen; diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c index 246801912e1a..aff3348b8351 100644 --- a/drivers/crypto/ccp/ccp-dev.c +++ b/drivers/crypto/ccp/ccp-dev.c @@ -30,7 +30,7 @@ #define MAX_CCPS 32 -/* Limit CCP use to a specifed number of queues per device */ +/* Limit CCP use to a specified number of queues per device */ static unsigned int nqueues; module_param(nqueues, uint, 0444); MODULE_PARM_DESC(nqueues, "Number of queues per CCP (minimum 1; default: all available)"); diff --git a/drivers/crypto/ccree/cc_buffer_mgr.c b/drivers/crypto/ccree/cc_buffer_mgr.c index dc7e0cd51c25..a592f5ec1b6a 100644 --- a/drivers/crypto/ccree/cc_buffer_mgr.c +++ b/drivers/crypto/ccree/cc_buffer_mgr.c @@ -717,7 +717,7 @@ static void cc_prepare_aead_data_mlli(struct cc_drvdata *drvdata, } } else { /* Contig. ICV */ sg = &areq_ctx->src_sgl[areq_ctx->src.nents - 1]; - /*Should hanlde if the sg is not contig.*/ + /*Should handle if the sg is not contig.*/ areq_ctx->icv_dma_addr = sg_dma_address(sg) + (*src_last_bytes - authsize); areq_ctx->icv_virt_addr = sg_virt(sg) + @@ -749,7 +749,7 @@ static void cc_prepare_aead_data_mlli(struct cc_drvdata *drvdata, } else { /* Contig. ICV */ sg = &areq_ctx->src_sgl[areq_ctx->src.nents - 1]; - /*Should hanlde if the sg is not contig.*/ + /*Should handle if the sg is not contig.*/ areq_ctx->icv_dma_addr = sg_dma_address(sg) + (*src_last_bytes - authsize); areq_ctx->icv_virt_addr = sg_virt(sg) + diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c index 6dec42282768..e2f2b2a6200e 100644 --- a/drivers/crypto/chelsio/chcr_algo.c +++ b/drivers/crypto/chelsio/chcr_algo.c @@ -1605,7 +1605,7 @@ static struct sk_buff *create_hash_wr(struct ahash_request *req, req_ctx->hctx_wr.dma_addr = 0; } chcr_add_hash_src_ent(req, ulptx, param); - /* Request upto max wr size */ + /* Request up to max wr size */ temp = param->kctx_len + DUMMY_BYTES + (req_ctx->hctx_wr.imm ? (param->sg_len + param->bfr_len) : 0); atomic_inc(&adap->chcr_stats.digest_rqst); diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_mbox.c b/drivers/crypto/marvell/octeontx/otx_cptvf_mbox.c index 90fdafb7c468..38d1de24652b 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptvf_mbox.c +++ b/drivers/crypto/marvell/octeontx/otx_cptvf_mbox.c @@ -180,7 +180,7 @@ int otx_cptvf_send_vq_size_msg(struct otx_cptvf *cptvf) } /* - * Communicate VF group required to PF and get the VQ binded to that group + * Communicate VF group required to PF and get the VQ bound to that group */ int otx_cptvf_send_vf_to_grp_msg(struct otx_cptvf *cptvf, int group) { @@ -199,7 +199,7 @@ int otx_cptvf_send_vf_to_grp_msg(struct otx_cptvf *cptvf, int group) } /* - * Communicate VF group required to PF and get the VQ binded to that group + * Communicate VF group required to PF and get the VQ bound to that group */ int otx_cptvf_send_vf_priority_msg(struct otx_cptvf *cptvf) { diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index 6d2dd0b88f15..12d6dc68438a 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -1265,7 +1265,7 @@ static int omap_sham_finup(struct ahash_request *req) return err1; /* * final() has to be always called to cleanup resources - * even if udpate() failed, except EINPROGRESS + * even if update() failed, except EINPROGRESS */ err2 = omap_sham_final(req); @@ -1732,7 +1732,7 @@ static void omap_sham_done_task(struct work_struct *t) finish: dev_dbg(dd->dev, "update done: err: %d\n", err); - /* finish curent request */ + /* finish current request */ omap_sham_finish_req(dd->req, err); } diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 37eb6d556df5..e0061bfab216 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -379,7 +379,7 @@ static int qce_aead_create_ccm_nonce(struct qce_aead_reqctx *rctx, struct qce_ae /* * The crypto framework encodes cryptlen as unsigned int. Thus, even though - * spec allows for upto 8 bytes to encode msg_len only 4 bytes are needed. + * spec allows for up to 8 bytes to encode msg_len only 4 bytes are needed. */ if (msglen_size > 4) msglen_size = 4; diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index f20c02e9d646..a70102799223 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -1445,7 +1445,7 @@ static void s5p_hash_tasklet_cb(unsigned long data) return; finish: - /* finish curent request */ + /* finish current request */ s5p_hash_finish_req(dd->hash_req, 0); /* If we are not busy, process next req */ From b01c7923e73a24e1aeab56d74d8a9ae4aa3e7044 Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Fri, 4 Sep 2026 18:08:20 +0530 Subject: [PATCH 057/146] padata: fix typo "dependend" in comment Correct "dependend" to "dependent", reported by scripts/checkpatch.pl using the misspelling list in scripts/spelling.txt. Only touches comments, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Reviewed-by: Bradley Morgan Signed-off-by: Herbert Xu --- kernel/padata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/padata.c b/kernel/padata.c index 0d3ea1b68b1f..5a113c667d4c 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -534,7 +534,7 @@ static void padata_init_reorder_list(struct parallel_data *pd) } } -/* Allocate and initialize the internal cpumask dependend resources. */ +/* Allocate and initialize the internal cpumask dependent resources. */ static struct parallel_data *padata_alloc_pd(struct padata_shell *ps, int offlining_cpu) { From 13b481b15e82a2f3b1b7867d48a973bcf7dcedcb Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 4 Sep 2026 13:40:28 -0700 Subject: [PATCH 058/146] crypto: talitos - pass talitos_private to irq handlers The irq handlers only need priv, which they can get from the dev_get_drvdata() they currently perform on the struct device passed as data. Pass priv directly as the irq handler data and drop the dev_get_drvdata() call, while deriving dev from priv->dev where still needed. Assisted-by: opencode:deepseek-v4-flash-free Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index fa96b6bf17e3..41a87d7c30a0 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -751,8 +751,7 @@ static void talitos_error(struct device *dev, u32 isr, u32 isr_lo) #define DEF_TALITOS1_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \ { \ - struct device *dev = data; \ - struct talitos_private *priv = dev_get_drvdata(dev); \ + struct talitos_private *priv = data; \ u32 isr, isr_lo; \ unsigned long flags; \ \ @@ -765,7 +764,7 @@ static irqreturn_t talitos1_interrupt_##name(int irq, void *data) \ \ if (unlikely(isr & ch_err_mask || isr_lo & TALITOS1_IMR_LO_INIT)) { \ spin_unlock_irqrestore(&priv->reg_lock, flags); \ - talitos_error(dev, isr & ch_err_mask, isr_lo); \ + talitos_error(priv->dev, isr & ch_err_mask, isr_lo); \ } \ else { \ if (likely(isr & ch_done_mask)) { \ @@ -786,8 +785,7 @@ DEF_TALITOS1_INTERRUPT(4ch, TALITOS1_ISR_4CHDONE, TALITOS1_ISR_4CHERR, 0) #define DEF_TALITOS2_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \ { \ - struct device *dev = data; \ - struct talitos_private *priv = dev_get_drvdata(dev); \ + struct talitos_private *priv = data; \ u32 isr, isr_lo; \ unsigned long flags; \ \ @@ -800,7 +798,7 @@ static irqreturn_t talitos2_interrupt_##name(int irq, void *data) \ \ if (unlikely(isr & ch_err_mask || isr_lo)) { \ spin_unlock_irqrestore(&priv->reg_lock, flags); \ - talitos_error(dev, isr & ch_err_mask, isr_lo); \ + talitos_error(priv->dev, isr & ch_err_mask, isr_lo); \ } \ else { \ if (likely(isr & ch_done_mask)) { \ @@ -3242,7 +3240,7 @@ static void talitos_remove(struct platform_device *ofdev) for (i = 0; i < 2; i++) if (priv->irq[i] > 0) - free_irq(priv->irq[i], dev); + free_irq(priv->irq[i], priv); tasklet_kill(&priv->done_task[0]); if (priv->irq[1] > 0) @@ -3361,7 +3359,7 @@ static int talitos_probe_irq(struct platform_device *ofdev) if (is_sec1) { err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0, - dev_driver_string(dev), dev); + dev_driver_string(dev), priv); goto primary_out; } @@ -3372,18 +3370,18 @@ static int talitos_probe_irq(struct platform_device *ofdev) /* get the primary irq line */ if (priv->irq[1] < 0) { err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0, - dev_driver_string(dev), dev); + dev_driver_string(dev), priv); goto primary_out; } err = request_irq(priv->irq[0], talitos2_interrupt_ch0_2, 0, - dev_driver_string(dev), dev); + dev_driver_string(dev), priv); if (err) goto primary_out; /* get the secondary irq line */ err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0, - dev_driver_string(dev), dev); + dev_driver_string(dev), priv); if (err) { dev_err(dev, "failed to request secondary irq\n"); priv->irq[1] = 0; @@ -3422,6 +3420,7 @@ static int talitos_probe(struct platform_device *ofdev) dev_set_drvdata(dev, priv); + priv->dev = dev; priv->ofdev = ofdev; spin_lock_init(&priv->reg_lock); From f033e862a32ccc62513bbc3304cd5e3d34e2578b Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 4 Sep 2026 16:01:44 -0700 Subject: [PATCH 059/146] crypto: crypto4xx - use int for ppc4xx_trng_probe() Pass an error message to crypto4xx_probe() , which will allow handling failure. The inline function returns 0 as trng is optional functionality. Same with the of_node. Add an extra goto in crypto4xx_probe() to unregister algs as registering them happens before trng. Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/amcc/crypto4xx_core.c | 6 +++++- drivers/crypto/amcc/crypto4xx_trng.c | 15 ++++++++++----- drivers/crypto/amcc/crypto4xx_trng.h | 6 +++--- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index a044dce65cf4..acf18b71e54d 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -1315,9 +1315,13 @@ static int crypto4xx_probe(struct platform_device *ofdev) if (rc) goto err_irq; - ppc4xx_trng_probe(core_dev); + rc = ppc4xx_trng_probe(core_dev); + if (rc) + goto err_crypto; return 0; +err_crypto: + crypto4xx_unregister_alg(core_dev->dev); err_irq: free_irq(core_dev->irq, core_dev); err_tasklet: diff --git a/drivers/crypto/amcc/crypto4xx_trng.c b/drivers/crypto/amcc/crypto4xx_trng.c index cfd66b779ce1..83e9353529fc 100644 --- a/drivers/crypto/amcc/crypto4xx_trng.c +++ b/drivers/crypto/amcc/crypto4xx_trng.c @@ -68,7 +68,7 @@ static const struct of_device_id ppc4xx_trng_match[] = { {}, }; -void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev) +int ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev) { struct crypto4xx_device *dev = core_dev->dev; struct device_node *trng = NULL; @@ -79,17 +79,21 @@ void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev) trng = of_find_matching_node(NULL, ppc4xx_trng_match); if (!trng || !of_device_is_available(trng)) { of_node_put(trng); - return; + return 0; } dev->trng_base = of_iomap(trng, 0); of_node_put(trng); - if (!dev->trng_base) + if (!dev->trng_base) { + err = -EINVAL; goto err_out; + } rng = kzalloc_obj(*rng); - if (!rng) + if (!rng) { + err = -ENOMEM; goto err_out; + } rng->name = KBUILD_MODNAME; rng->data_present = ppc4xx_trng_data_present; @@ -105,13 +109,14 @@ void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev) err); goto err_out; } - return; + return 0; err_out: iounmap(dev->trng_base); kfree(rng); dev->trng_base = NULL; core_dev->trng = NULL; + return err; } void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev) diff --git a/drivers/crypto/amcc/crypto4xx_trng.h b/drivers/crypto/amcc/crypto4xx_trng.h index 7356716274cb..1030c3cfafd0 100644 --- a/drivers/crypto/amcc/crypto4xx_trng.h +++ b/drivers/crypto/amcc/crypto4xx_trng.h @@ -13,11 +13,11 @@ #define __CRYPTO4XX_TRNG_H__ #ifdef CONFIG_HW_RANDOM_PPC4XX -void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev); +int ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev); void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev); #else -static inline void ppc4xx_trng_probe( - struct crypto4xx_core_device *dev __maybe_unused) { } +static inline int ppc4xx_trng_probe( + struct crypto4xx_core_device *dev __maybe_unused) { return 0; } static inline void ppc4xx_trng_remove( struct crypto4xx_core_device *dev __maybe_unused) { } #endif From 9695df3b1db4ac4534274d38ee16e3b9b0bf910e Mon Sep 17 00:00:00 2001 From: Weiming Shi Date: Sun, 6 Sep 2026 19:01:53 +0800 Subject: [PATCH 060/146] asymmetric_keys: reject trust keys without IDs The PKCS#8 parser deliberately leaves the asym_key_ids payload slot empty. key_or_keyring_common() unconditionally dereferences that slot when a PKCS#8 key is supplied to a key_or_keyring restriction. Both the plain and :chain forms reach this branch, allowing an unprivileged caller to trigger a NULL pointer dereference through KEYCTL_RESTRICT_KEYRING followed by add_key(). Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000 KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] RIP: 0010:key_or_keyring_common (crypto/asymmetric_keys/restrict.c:205 crypto/asymmetric_keys/restrict.c:279) Call Trace: __key_create_or_update (security/keys/key.c:884) key_create_or_update (security/keys/key.c:1021) __do_sys_add_key (security/keys/keyctl.c:134) do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) Kernel panic - not syncing: Fatal exception Reject an asymmetric restriction key without key IDs. A PKCS#8 private key cannot identify the signer of a candidate certificate and is not a valid trust anchor. Fixes: 3c58b2362ba8 ("KEYS: Implement PKCS#8 RSA Private Key parser [ver #2]") Cc: stable@vger.kernel.org Reported-by: Xiang Mei Link: https://lore.kernel.org/r/20260429181629.110802-2-bestswngs@gmail.com Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Weiming Shi Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/restrict.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c index 86292965f493..0e4783ff7d22 100644 --- a/crypto/asymmetric_keys/restrict.c +++ b/crypto/asymmetric_keys/restrict.c @@ -243,10 +243,14 @@ static int key_or_keyring_common(struct key *dest_keyring, if (IS_ERR(key)) key = NULL; } else if (trusted->type == &key_type_asymmetric) { + const struct asymmetric_key_ids *kids; const struct asymmetric_key_id **signer_ids; - signer_ids = (const struct asymmetric_key_id **) - asymmetric_key_ids(trusted)->id; + kids = asymmetric_key_ids(trusted); + if (!kids) + return -ENOKEY; + + signer_ids = (const struct asymmetric_key_id **)kids->id; /* * The auth_ids come from the candidate key (the From 016f22d2268e02df705868110fe4e402b51bfffc Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 8 Sep 2026 09:53:40 +0200 Subject: [PATCH 061/146] crypto: zynqmp-sha - fix NULL pointer dereference in init_tfm zynqmp_sha_init_tfm() checks crypto_shash_statesize(tfm_ctx->fbk_tfm) before assigning the fallback transform to it, which dereferences a NULL pointer since the transform context is zero-initialized. Use the local fallback_tfm pointer for the size check instead. Fixes: c1dd353d18e5 ("crypto: zynqmp-sha - Make descsize an algorithm attribute") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/xilinx/zynqmp-sha.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/xilinx/zynqmp-sha.c b/drivers/crypto/xilinx/zynqmp-sha.c index 5813017b6b79..cd051e1f4275 100644 --- a/drivers/crypto/xilinx/zynqmp-sha.c +++ b/drivers/crypto/xilinx/zynqmp-sha.c @@ -59,7 +59,7 @@ static int zynqmp_sha_init_tfm(struct crypto_shash *hash) return PTR_ERR(fallback_tfm); if (crypto_shash_descsize(hash) < - crypto_shash_statesize(tfm_ctx->fbk_tfm)) { + crypto_shash_statesize(fallback_tfm)) { crypto_free_shash(fallback_tfm); return -EINVAL; } From 654358f71bc10e481c7ecf3b0975b34bee9cdf1a Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 8 Sep 2026 21:00:00 +0200 Subject: [PATCH 062/146] crypto: xilinx - use kfree_sensitive() in cleanup paths In zynqmp_aes_aead_cipher() and versal_aes_aead_cipher(), replace memzero_explicit() followed by kfree() with kfree_sensitive() to simplify the code. Signed-off-by: Thorsten Blum Reviewed-by: Harsh Jain Signed-off-by: Herbert Xu --- drivers/crypto/xilinx/zynqmp-aes-gcm.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/crypto/xilinx/zynqmp-aes-gcm.c b/drivers/crypto/xilinx/zynqmp-aes-gcm.c index d54c268dfe34..551726aac806 100644 --- a/drivers/crypto/xilinx/zynqmp-aes-gcm.c +++ b/drivers/crypto/xilinx/zynqmp-aes-gcm.c @@ -230,10 +230,8 @@ static int zynqmp_aes_aead_cipher(struct aead_request *req) } freemem: - memzero_explicit(kbuf, dma_size); - kfree(kbuf); - memzero_explicit(dmabuf, sizeof(struct zynqmp_aead_hw_req) + GCM_AES_IV_SIZE); - kfree(dmabuf); + kfree_sensitive(kbuf); + kfree_sensitive(dmabuf); return ret; } @@ -364,11 +362,9 @@ unmap: if (unlikely(dma_addr_hw_req)) dma_unmap_single(dev, dma_addr_hw_req, dmabuf_size, DMA_BIDIRECTIONAL); buf2_free: - memzero_explicit(dmabuf, dmabuf_size); - kfree(dmabuf); + kfree_sensitive(dmabuf); buf1_free: - memzero_explicit(kbuf, kbuf_size); - kfree(kbuf); + kfree_sensitive(kbuf); err: return ret; } From 1e4d31c4eb86982319245d8973473a621a256842 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 8 Sep 2026 21:16:06 +0200 Subject: [PATCH 063/146] crypto: xilinx - clear AES key buffer before freeing it In xilinx_aes_aead_exit(), the AES key buffer is freed without being cleared, which allows key material to remain in memory. Use kfree_sensitive() to clear the buffer before freeing it. Fixes: c315cb0005be ("crypto: xilinx - Change coherent DMA to streaming DMA API") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Reviewed-by: Thomas Huth Signed-off-by: Herbert Xu --- drivers/crypto/xilinx/zynqmp-aes-gcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/xilinx/zynqmp-aes-gcm.c b/drivers/crypto/xilinx/zynqmp-aes-gcm.c index 551726aac806..d9bd6dcd23a6 100644 --- a/drivers/crypto/xilinx/zynqmp-aes-gcm.c +++ b/drivers/crypto/xilinx/zynqmp-aes-gcm.c @@ -762,7 +762,7 @@ static void xilinx_aes_aead_exit(struct crypto_aead *aead) struct xilinx_aead_tfm_ctx *tfm_ctx = crypto_tfm_ctx(tfm); dma_unmap_single(tfm_ctx->dev, tfm_ctx->key_dma_addr, AES_KEYSIZE_256, DMA_TO_DEVICE); - kfree(tfm_ctx->key); + kfree_sensitive(tfm_ctx->key); if (tfm_ctx->fbk_cipher) { crypto_free_aead(tfm_ctx->fbk_cipher); tfm_ctx->fbk_cipher = NULL; From 178829f1b5b259938188a10f4103fdb901b6435e Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Wed, 9 Sep 2026 15:15:21 +0100 Subject: [PATCH 064/146] crypto: qat - fix active_devs leak on crypto alg registration failure adf_dev_start() registered both alg sets in a single condition. If qat_algs_register() succeeds but qat_asym_algs_register() fails, ADF_STATUS_CRYPTO_ALGS_REGISTERED is left clear, so adf_dev_stop() skips qat_algs_unregister(): the skciphers and aeads stay registered with active_devs stuck at 1, pinning the module. Both helpers leak active_devs internally as well - they increment it and return without decrementing when a crypto_register_*() call fails, and the asym path also leaves the already-registered akcipher behind. Split the registration in adf_dev_start() so that an asym failure unregisters qat_algs, and unwind active_devs (and the akcipher) on the error paths of both register helpers. While at it, propagate the error code returned by the register helpers instead of a blanket -EFAULT. Fixes: 9b2f33a1bfcd ("crypto: qat - fix unregistration of crypto algorithms") Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Reviewed-by: Thomas Huth Signed-off-by: Herbert Xu --- .../crypto/intel/qat/qat_common/adf_init.c | 24 ++++++++++++----- .../crypto/intel/qat/qat_common/qat_algs.c | 15 ++++++----- .../intel/qat/qat_common/qat_asym_algs.c | 26 ++++++++++++++----- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c index 3e39c53814de..81cb5e6c9f4a 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_init.c +++ b/drivers/crypto/intel/qat/qat_common/adf_init.c @@ -260,13 +260,23 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev) clear_bit(ADF_STATUS_STARTING, &accel_dev->status); set_bit(ADF_STATUS_STARTED, &accel_dev->status); - if (!list_empty(&accel_dev->crypto_list) && - (qat_algs_register() || qat_asym_algs_register())) { - dev_err(&GET_DEV(accel_dev), - "Failed to register crypto algs\n"); - set_bit(ADF_STATUS_STARTING, &accel_dev->status); - clear_bit(ADF_STATUS_STARTED, &accel_dev->status); - return -EFAULT; + if (!list_empty(&accel_dev->crypto_list)) { + ret = qat_algs_register(); + if (ret) { + dev_err(&GET_DEV(accel_dev), "Failed to register crypto algs\n"); + set_bit(ADF_STATUS_STARTING, &accel_dev->status); + clear_bit(ADF_STATUS_STARTED, &accel_dev->status); + return ret; + } + + ret = qat_asym_algs_register(); + if (ret) { + dev_err(&GET_DEV(accel_dev), "Failed to register crypto asym algs\n"); + qat_algs_unregister(); + set_bit(ADF_STATUS_STARTING, &accel_dev->status); + clear_bit(ADF_STATUS_STARTED, &accel_dev->status); + return ret; + } } set_bit(ADF_STATUS_CRYPTO_ALGS_REGISTERED, &accel_dev->status); diff --git a/drivers/crypto/intel/qat/qat_common/qat_algs.c b/drivers/crypto/intel/qat/qat_common/qat_algs.c index cb669fb66162..2ec19104787f 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_algs.c @@ -1319,19 +1319,22 @@ int qat_algs_register(void) ret = crypto_register_skciphers(qat_skciphers, ARRAY_SIZE(qat_skciphers)); if (ret) - goto unlock; + goto err_dec; ret = crypto_register_aeads(qat_aeads, ARRAY_SIZE(qat_aeads)); if (ret) - goto unreg_algs; + goto err_unreg_skciphers; + mutex_unlock(&algs_lock); + return 0; + +err_unreg_skciphers: + crypto_unregister_skciphers(qat_skciphers, ARRAY_SIZE(qat_skciphers)); +err_dec: + active_devs--; unlock: mutex_unlock(&algs_lock); return ret; - -unreg_algs: - crypto_unregister_skciphers(qat_skciphers, ARRAY_SIZE(qat_skciphers)); - goto unlock; } void qat_algs_unregister(void) diff --git a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c index 1049c583f84f..77d59e977472 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c @@ -1340,13 +1340,25 @@ int qat_asym_algs_register(void) int ret = 0; mutex_lock(&algs_lock); - if (++active_devs == 1) { - rsa.base.cra_flags = 0; - ret = crypto_register_akcipher(&rsa); - if (ret) - goto unlock; - ret = crypto_register_kpp(&dh); - } + if (++active_devs != 1) + goto unlock; + + rsa.base.cra_flags = 0; + ret = crypto_register_akcipher(&rsa); + if (ret) + goto err_dec; + + ret = crypto_register_kpp(&dh); + if (ret) + goto err_unreg_akcipher; + + mutex_unlock(&algs_lock); + return 0; + +err_unreg_akcipher: + crypto_unregister_akcipher(&rsa); +err_dec: + active_devs--; unlock: mutex_unlock(&algs_lock); return ret; From 5d69ed4cd4f9c68ff9a6ebb2e8a1079223a4ec6e Mon Sep 17 00:00:00 2001 From: Guangshuo Li Date: Sat, 12 Sep 2026 22:41:16 +0800 Subject: [PATCH 065/146] crypto: omap-des - fix crypto engine cleanup omap_des_probe() allocates and starts a crypto engine, but the remove path does not call the matching crypto_engine_exit(). The probe failure path already performs this cleanup. crypto_engine_alloc_init() creates a kthread worker for processing requests. Without crypto_engine_exit() during driver removal, the worker is left running after the device is removed. Call crypto_engine_exit() after unregistering the algorithms and before tearing down the remaining request handling resources. This stops the engine and destroys its worker. This issue was found by manual code inspection. Fixes: f1b77aaca85a ("crypto: omap-des - Integrate with the crypto engine framework") Cc: stable@vger.kernel.org Signed-off-by: Guangshuo Li Signed-off-by: Herbert Xu --- drivers/crypto/omap-des.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c index 3b7104cb4487..4b5a8d13f505 100644 --- a/drivers/crypto/omap-des.c +++ b/drivers/crypto/omap-des.c @@ -1082,6 +1082,8 @@ static void omap_des_remove(struct platform_device *pdev) omap_des_unregister_algs(dd->pdata); + crypto_engine_exit(dd->engine); + cancel_work_sync(&dd->done_task); omap_des_dma_cleanup(dd); pm_runtime_disable(dd->dev); From be51ea091c6563158531e8c74e040552fdb1e28c Mon Sep 17 00:00:00 2001 From: Guangshuo Li Date: Sat, 12 Sep 2026 22:46:08 +0800 Subject: [PATCH 066/146] crypto: omap-sham - fix crypto engine cleanup omap_sham_probe() allocates and starts a crypto engine, but the remove path does not call the matching crypto_engine_exit(). The probe failure path already performs this cleanup. crypto_engine_alloc_init() creates a kthread worker for processing requests. Without crypto_engine_exit() during driver removal, the worker is left running after the device is removed. Call crypto_engine_exit() after unregistering the algorithms and before tearing down the remaining request handling resources. This stops the engine and destroys its worker. This issue was found by manual code inspection. Fixes: 133c3d434d91 ("crypto: omap-sham - convert to use crypto engine") Cc: stable@vger.kernel.org Signed-off-by: Guangshuo Li Signed-off-by: Herbert Xu --- drivers/crypto/omap-sham.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index 12d6dc68438a..5e739415a010 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -2129,6 +2129,7 @@ static void omap_sham_remove(struct platform_device *pdev) list_del(&dd->list); spin_unlock_bh(&sham.lock); omap_sham_unregister_algs(dd->pdata); + crypto_engine_exit(dd->engine); cancel_work_sync(&dd->done_task); pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_disable(&pdev->dev); From a9a2152d292fd0bc73814eb4a127278ee7dd3f6a Mon Sep 17 00:00:00 2001 From: Slavin Liu Date: Sun, 13 Sep 2026 20:51:43 +0800 Subject: [PATCH 067/146] crypto: atmel-sha - reject initialization without a device A transform may be initialized for the first time after the last device has been removed from the driver list. Return -ENODEV when the lookup is empty, before the debug message reads dd->dev. Detected by static analysis and reviewed with AI-assisted source auditing. Fixes: ebc82efa1cd6 ("crypto: atmel - add Atmel SHA1/SHA256 driver") Assisted-by: LLM Signed-off-by: Slavin Liu Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 89c0a3bdf4e0..2d70a4107693 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -422,6 +422,9 @@ static int atmel_sha_init(struct ahash_request *req) struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); struct atmel_sha_dev *dd = atmel_sha_find_dev(tctx); + if (!dd) + return -ENODEV; + ctx->dd = dd; ctx->flags = 0; From 2618f76b277cef3df8ebdff403b05705f5f8a36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Jean?= Date: Fri, 21 Aug 2026 19:25:03 +0000 Subject: [PATCH 068/146] crypto: asymmetric_keys/x509 - copy X.509 TBS for data signature algorithms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For signature algorithms operating on a message rather than a digest, x509_get_sig_params() points sig->m directly into cert->tbs. cert->tbs is the preparsed add_key() payload. The syscall wipes and frees it on return, while the instantiated key retains public_key_signature. A later KEYCTL_LINK into an asymmetric restricted keyring therefore passes a dangling message pointer to ML-DSA. KASAN reports a slab-use-after-free in mldsa_verify(), with allocation and free provenance both leading to __do_sys_add_key(). Reuse is also an integrity issue: bytes occupying the freed object become the authenticated message instead of the certificate's own TBSCertificate. Give the signature object its own copy of the TBS, as is already done for a precomputed digest, and release it through the existing m_free contract. Fixes: f3eccecd782d ("pkcs7: Allow the signing algo to do whatever digestion it wants itself") Signed-off-by: Jérémy Jean Assisted-by: Codex:gpt-5 Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/x509_public_key.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 25cf8ac7f257..5c9165a83f91 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -53,9 +53,11 @@ int x509_get_sig_params(struct x509_certificate *cert) if (sig->algo_takes_data) { /* The signature algorithm does whatever passes for hashing. */ - sig->m = (u8 *)cert->tbs; + sig->m = kmemdup(cert->tbs, cert->tbs_size, GFP_KERNEL); + if (!sig->m) + return -ENOMEM; sig->m_size = cert->tbs_size; - sig->m_free = false; + sig->m_free = true; goto out; } From 553c623a12f4928a2889cf1bba0bd8885f0bdd4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Jean?= Date: Sat, 22 Aug 2026 21:27:04 +0000 Subject: [PATCH 069/146] crypto: asymmetric_keys/pkcs7 - Check all signers before waiving authattrs rejection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pkcs7_check_authattrs() only looks at the first SignerInfo when deciding whether rejection of authenticated attributes may be waived. For the remaining signers it checks only that authenticated attributes are either present on all signers or absent from all of them. This means an unmatched ML-DSA signer can be placed first, followed by a trusted RSA, ECDSA, or ECRDSA signer. Verification skips the unmatched signature and accepts the later trusted signer. The first signer still leaves the waiver enabled for the whole message, so the non-ML-DSA signer can use an exception intended only for ML-DSA. Check each SignerInfo's public-key algorithm before leaving the waiver enabled. Fixes: 91db696adea4 ("pkcs7: Allow authenticatedAttributes for ML-DSA") Assisted-by: Codex:gpt-5 Signed-off-by: Jérémy Jean Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/pkcs7_parser.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 6e3ffdac83ac..7f00e45a33cf 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -111,6 +111,12 @@ static int pkcs7_check_authattrs(struct pkcs7_message *msg) if (!!sinfo->authattrs != want) goto inconsistent; +#ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA + if (sinfo->authattrs && + strncmp(sinfo->sig->pkey_algo, "mldsa", 5) != 0) + msg->authattrs_rej_waivable = false; +#endif + if (!sinfo->authattrs && sinfo->sig->algo_takes_data) sinfo->sig->hash_algo = "none"; From ace145efdd80cd2eb95e84b1087d0f1fc55bdc0d Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Sun, 30 Aug 2026 21:17:53 +0800 Subject: [PATCH 070/146] hwrng: starfive - propagate clock and reset errors The StarFive TRNG probe and resume paths ignore failures from their clock and reset operations. That lets the driver register or resume while its hardware access prerequisites were not established. Check each transition, unwind only the previously enabled clock on failure, and propagate the error to the probe or PM core. Fixes: c388f458bc34 ("hwrng: starfive - Add TRNG driver for StarFive SoC") Signed-off-by: Pengpeng Hou Signed-off-by: Herbert Xu --- drivers/char/hw_random/jh7110-trng.c | 39 +++++++++++++++++++++------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/char/hw_random/jh7110-trng.c b/drivers/char/hw_random/jh7110-trng.c index aee12caab578..61eb4db7ac01 100644 --- a/drivers/char/hw_random/jh7110-trng.c +++ b/drivers/char/hw_random/jh7110-trng.c @@ -320,9 +320,17 @@ static int starfive_trng_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(trng->rst), "Error getting hardware reset line\n"); - clk_prepare_enable(trng->hclk); - clk_prepare_enable(trng->ahb); - reset_control_deassert(trng->rst); + ret = clk_prepare_enable(trng->hclk); + if (ret) + return ret; + + ret = clk_prepare_enable(trng->ahb); + if (ret) + goto disable_hclk; + + ret = reset_control_deassert(trng->rst); + if (ret) + goto disable_ahb; trng->rng.name = dev_driver_string(&pdev->dev); trng->rng.init = starfive_trng_init; @@ -342,13 +350,18 @@ static int starfive_trng_probe(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); reset_control_assert(trng->rst); - clk_disable_unprepare(trng->ahb); - clk_disable_unprepare(trng->hclk); - - return dev_err_probe(&pdev->dev, ret, "Failed to register hwrng\n"); + ret = dev_err_probe(&pdev->dev, ret, "Failed to register hwrng\n"); + goto disable_ahb; } return 0; + +disable_ahb: + clk_disable_unprepare(trng->ahb); +disable_hclk: + clk_disable_unprepare(trng->hclk); + + return ret; } static int __maybe_unused starfive_trng_suspend(struct device *dev) @@ -364,11 +377,17 @@ static int __maybe_unused starfive_trng_suspend(struct device *dev) static int __maybe_unused starfive_trng_resume(struct device *dev) { struct starfive_trng *trng = dev_get_drvdata(dev); + int ret; - clk_prepare_enable(trng->hclk); - clk_prepare_enable(trng->ahb); + ret = clk_prepare_enable(trng->hclk); + if (ret) + return ret; - return 0; + ret = clk_prepare_enable(trng->ahb); + if (ret) + clk_disable_unprepare(trng->hclk); + + return ret; } static const struct dev_pm_ops starfive_trng_pm_ops = { From c8acdd77a62374507ed8e70d59e124269d999b75 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Sun, 30 Aug 2026 21:48:35 +0800 Subject: [PATCH 071/146] crypto: starfive - propagate clock and reset errors starfive_cryp_probe() publishes the crypto device after enabling its clocks and deasserting its reset without checking whether those operations succeeded. Check each hardware activation step and unwind only the resources that were actually enabled before returning the error. Fixes: 42ef0e944b01 ("crypto: starfive - Add crypto engine support") Signed-off-by: Pengpeng Hou Signed-off-by: Herbert Xu --- drivers/crypto/starfive/jh7110-cryp.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/starfive/jh7110-cryp.c b/drivers/crypto/starfive/jh7110-cryp.c index c3830a7c1810..856290347b95 100644 --- a/drivers/crypto/starfive/jh7110-cryp.c +++ b/drivers/crypto/starfive/jh7110-cryp.c @@ -125,11 +125,12 @@ static int starfive_cryp_probe(struct platform_device *pdev) return ret; ret = clk_prepare_enable(cryp->ahb); - if (ret) { - clk_disable_unprepare(cryp->hclk); - return ret; - } - reset_control_deassert(cryp->rst); + if (ret) + goto disable_hclk; + + ret = reset_control_deassert(cryp->rst); + if (ret) + goto disable_ahb; spin_lock(&dev_list.lock); list_add(&cryp->list, &dev_list.dev_list); @@ -177,9 +178,11 @@ err_dma_init: list_del(&cryp->list); spin_unlock(&dev_list.lock); - clk_disable_unprepare(cryp->hclk); - clk_disable_unprepare(cryp->ahb); reset_control_assert(cryp->rst); +disable_ahb: + clk_disable_unprepare(cryp->ahb); +disable_hclk: + clk_disable_unprepare(cryp->hclk); return ret; } From 82c11f6b1241942c6e09deb85754a4e74a3ef4ec Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Mon, 14 Sep 2026 06:14:36 +0200 Subject: [PATCH 072/146] MAINTAINERS: update caam crypto driver maintainers list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding Sahil Malhotra as caam maintainer and removing Gaurav Jain. Signed-off-by: Sahil Malhotra Reviewed-by: Horia Geantă Signed-off-by: Herbert Xu --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index c3bcdcaa9b92..66cf3701ff19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10353,7 +10353,7 @@ F: include/video/ FREESCALE CAAM (Cryptographic Acceleration and Assurance Module) DRIVER M: Horia Geantă M: Pankaj Gupta -M: Gaurav Jain +M: Sahil Malhotra L: linux-crypto@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/crypto/fsl,sec-v4.0* From b7e0a9bd8086eb687b647a7c9a3635a3da40977d Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 14 Sep 2026 10:15:01 +0200 Subject: [PATCH 073/146] crypto: powerpc/vmx - clean up includes, metadata, and p8_init() In p8_init(), remove the goto statement and return ret directly. Remove any redundant includes, add a missing space in MODULE_AUTHOR(), and join the MODULE_DESCRIPTION() strings for better grepability. Also remove MODULE_VERSION(). It has never been updated and the kernel release better reflects the module version. Signed-off-by: Thorsten Blum Reviewed-by: Breno Leitao Tested-by: Srish Srinivasan Reviewed-by: Sudhakar Kuppusamy Signed-off-by: Herbert Xu --- arch/powerpc/crypto/vmx.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/crypto/vmx.c b/arch/powerpc/crypto/vmx.c index 08da5311dfdf..8abc4db8ee4e 100644 --- a/arch/powerpc/crypto/vmx.c +++ b/arch/powerpc/crypto/vmx.c @@ -8,12 +8,7 @@ */ #include -#include -#include -#include #include -#include -#include #include #include "aesp8-ppc.h" @@ -24,7 +19,7 @@ static int __init p8_init(void) ret = crypto_register_skcipher(&p8_aes_cbc_alg); if (ret) - goto err; + return ret; ret = crypto_register_skcipher(&p8_aes_ctr_alg); if (ret) @@ -40,7 +35,6 @@ err_unregister_aes_ctr: crypto_unregister_skcipher(&p8_aes_ctr_alg); err_unregister_aes_cbc: crypto_unregister_skcipher(&p8_aes_cbc_alg); -err: return ret; } @@ -54,8 +48,6 @@ static void __exit p8_exit(void) module_cpu_feature_match(PPC_MODULE_FEATURE_VEC_CRYPTO, p8_init); module_exit(p8_exit); -MODULE_AUTHOR("Marcelo Cerri"); -MODULE_DESCRIPTION("IBM VMX cryptographic acceleration instructions " - "support on Power 8"); +MODULE_AUTHOR("Marcelo Cerri "); +MODULE_DESCRIPTION("IBM VMX cryptographic acceleration instructions support on Power 8"); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.0.0"); From eeaf1ccd4c05d9c6ad67345862b36670e8e4dfc2 Mon Sep 17 00:00:00 2001 From: Suman Kumar Chakraborty Date: Wed, 16 Sep 2026 07:55:36 +0000 Subject: [PATCH 074/146] crypto: qat - fix error source for QAT GEN6 transmit interface faults TI_CD_PAR_STS faults were being decoded under ERRSOU1, which is incorrect for QAT GEN6 devices. They are actually raised on ERRSOU3. Move the handling of TI_CD_PAR_STS faults as part of the ERRSOU3 logic and split the status bits by their actual source: - Bits 0-18 (TI_INT_ERR_DEVHALT) handled when a DEVHALT is signalled and are counted once as ADF_RAS_FATAL. - Bit 19 (TIMISCSTS) handled separately and counted as ADF_RAS_UNCORR. Previously, a TI_INT_ERR_DEVHALT fault also incremented ADF_RAS_UNCORR in addition to ADF_RAS_FATAL. Since a DEVHALT is already fatal, remove the redundant increment. Bits 20-25 of TI_CD_PAR_STS are unused/reserved on QAT GEN6. Remove them from the mask. Cc: stable@vger.kernel.org Fixes: 7f3401d0a506 ("crypto: qat - enable RAS support for GEN6 devices") Signed-off-by: Suman Kumar Chakraborty Reviewed-by: Giovanni Cabiddu Reviewed-by: Ahsan Atta Signed-off-by: Herbert Xu --- .../intel/qat/qat_common/adf_gen6_ras.c | 20 +++++++++++++--- .../intel/qat/qat_common/adf_gen6_ras.h | 24 ++++++++++--------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen6_ras.c b/drivers/crypto/intel/qat/qat_common/adf_gen6_ras.c index 967253082a98..902c4b1a23e3 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen6_ras.c +++ b/drivers/crypto/intel/qat/qat_common/adf_gen6_ras.c @@ -323,14 +323,26 @@ static void adf_handle_ti_cd_par_sts(struct adf_accel_dev *accel_dev, void __iom u32 ti_cd_par_sts; ti_cd_par_sts = ADF_CSR_RD(csr, ADF_GEN6_TI_CD_PAR_STS); - ti_cd_par_sts &= ADF_GEN6_TI_CD_PAR_STS_MASK; + ti_cd_par_sts &= ADF_GEN6_TI_CD_PAR_STS_TI_INT_ERR_DEVHALT_MASK; if (ti_cd_par_sts) { dev_err(&GET_DEV(accel_dev), "TI CD parity error: %#x\n", ti_cd_par_sts); - ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR); ADF_CSR_WR(csr, ADF_GEN6_TI_CD_PAR_STS, ti_cd_par_sts); } } +static void adf_handle_ti_misc_cd_par_sts(struct adf_accel_dev *accel_dev, void __iomem *csr) +{ + u32 ti_misc_cd_par_sts; + + ti_misc_cd_par_sts = ADF_CSR_RD(csr, ADF_GEN6_TI_CD_PAR_STS); + ti_misc_cd_par_sts &= ADF_GEN6_TI_CD_PAR_STS_TI_MISC_MASK; + if (ti_misc_cd_par_sts) { + dev_err(&GET_DEV(accel_dev), "TI MISC CD parity error: %#x\n", ti_misc_cd_par_sts); + ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_UNCORR); + ADF_CSR_WR(csr, ADF_GEN6_TI_CD_PAR_STS, ti_misc_cd_par_sts); + } +} + static void adf_handle_ti_trnsb_par_sts(struct adf_accel_dev *accel_dev, void __iomem *csr) { u32 ti_trnsb_par_sts; @@ -367,7 +379,6 @@ static void adf_handle_ti_err(struct adf_accel_dev *accel_dev, void __iomem *csr adf_handle_ti_ci_par_sts(accel_dev, csr); adf_handle_ti_pullfub_par_sts(accel_dev, csr); adf_handle_ti_pushfub_par_sts(accel_dev, csr); - adf_handle_ti_cd_par_sts(accel_dev, csr); adf_handle_ti_trnsb_par_sts(accel_dev, csr); adf_handle_iosfp_cmd_parerr(accel_dev, csr); } @@ -591,6 +602,8 @@ static void adf_handle_timiscsts(struct adf_accel_dev *accel_dev, void __iomem * if (!(errsou & ADF_GEN6_ERRSOU3_TIMISCSTS_BIT)) return; + adf_handle_ti_misc_cd_par_sts(accel_dev, csr); + timiscsts = ADF_CSR_RD(csr, ADF_GEN6_TIMISCSTS); if (timiscsts) { dev_err(&GET_DEV(accel_dev), "Fatal error in transmit interface: %#x\n", @@ -730,6 +743,7 @@ static void adf_handle_ti_int_err_devhalt(struct adf_accel_dev *accel_dev, void if (!(errsou & ADF_GEN6_ERRSOU3_TI_INT_ERR_DEVHALT_BIT)) return; + adf_handle_ti_cd_par_sts(accel_dev, csr); dev_err(&GET_DEV(accel_dev), "DEVHALT due to a TI internal memory error\n"); ADF_RAS_ERR_CTR_INC(accel_dev->ras_errors, ADF_RAS_FATAL); } diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen6_ras.h b/drivers/crypto/intel/qat/qat_common/adf_gen6_ras.h index 66ced271d173..11f7b2986f56 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen6_ras.h +++ b/drivers/crypto/intel/qat/qat_common/adf_gen6_ras.h @@ -170,23 +170,25 @@ struct adf_ras_ops; #define ADF_GEN6_TI_CD_PAR_ERR_MASK 0x500638 /* - * TI CD parity status mask + * TI CD parity status mask - TI_INT_ERR_DEVHALT bits * BIT(0) - BIT(15) - CtxMdRam[0:15]_sts parity status * BIT(16) - Leaf2ClusterRam_sts parity status * BIT(17) - BIT(18) - Ring2LeafRam[0:1]_sts parity status - * BIT(19) - VirtualQ_sts parity status - * BIT(20) - DtRdQ_sts parity status - * BIT(21) - DtWrQ_sts parity status - * BIT(22) - RiCmdQ_sts parity status - * BIT(23) - BypassQ_sts parity status - * BIT(24) - DtRdQ_sc_sts parity status - * BIT(25) - DtWrQ_sc_sts parity status */ -#define ADF_GEN6_TI_CD_PAR_STS_MASK \ +#define ADF_GEN6_TI_CD_PAR_STS_TI_INT_ERR_DEVHALT_MASK \ (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | \ BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | \ - BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | \ - BIT(21) | BIT(22) | BIT(23) | BIT(24) | BIT(25)) + BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18)) + +/* + * TI CD parity status mask - TIMISCSTS bit + * BIT(19) - VirtualQ_sts parity status + */ +#define ADF_GEN6_TI_CD_PAR_STS_TI_MISC_MASK BIT(19) + +#define ADF_GEN6_TI_CD_PAR_STS_MASK \ + (ADF_GEN6_TI_CD_PAR_STS_TI_INT_ERR_DEVHALT_MASK | \ + ADF_GEN6_TI_CD_PAR_STS_TI_MISC_MASK) /* TI TRNSB parity status */ #define ADF_GEN6_TI_TRNSB_PAR_STS 0x500648 From 9fa551ef513777ffca5583d2f9ff8f7d9da3e7ed Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 16 Sep 2026 18:46:40 +1000 Subject: [PATCH 075/146] rhashtable: Use separate lockdep keys for each lock Use separate lockdep keys for the different types of locks in rhashtable (mutex, spin lock, and bucket locks). They are separate and not normally nested with respect to each other. Also move the rhashtable_init/rhltable_init kdoc to the header file as that's where the macros are defined. Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.") Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com Assisted-by: Gemini:gemini-3.6-flash Signed-off-by: Herbert Xu Reviewed-by: NeilBrown Tested-by: Shin'ichiro Kawasaki Signed-off-by: Herbert Xu --- include/linux/rhashtable-types.h | 71 +++++++++++++++++++++++++++++--- include/linux/rhashtable.h | 3 +- lib/rhashtable.c | 70 ++++--------------------------- lib/test_rhashtable.c | 2 +- 4 files changed, 75 insertions(+), 71 deletions(-) diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h index 0e1b172a4f6c..3576b8f08aff 100644 --- a/include/linux/rhashtable-types.h +++ b/include/linux/rhashtable-types.h @@ -70,6 +70,12 @@ struct rhashtable_params { rht_obj_cmpfn_t obj_cmpfn; }; +struct rhashtable_lockdep_keys { + struct lock_class_key lock_key; + struct lock_class_key mutex_key; + struct lock_class_key bucket_key; +}; + /** * struct rhashtable - Hash table handle * @tbl: Bucket table @@ -141,24 +147,77 @@ struct rhashtable_iter { int __rhashtable_init_noprof(struct rhashtable *ht, const struct rhashtable_params *params, - struct lock_class_key *key); + struct rhashtable_lockdep_keys *keys); #define rhashtable_init_noprof(ht, params) \ ({ \ - static struct lock_class_key __key; \ + static struct rhashtable_lockdep_keys __keys; \ \ - __rhashtable_init_noprof(ht, params, &__key); \ + __rhashtable_init_noprof(ht, params, &__keys); \ }) + +/** + * rhashtable_init - initialize a new hash table + * @ht: hash table to be initialized + * @params: configuration parameters + * + * Initializes a new hash table based on the provided configuration + * parameters. A table can be configured either with a variable or + * fixed length key: + * + * Configuration Example 1: Fixed length keys + * struct test_obj { + * int key; + * void * my_member; + * struct rhash_head node; + * }; + * + * struct rhashtable_params params = { + * .head_offset = offsetof(struct test_obj, node), + * .key_offset = offsetof(struct test_obj, key), + * .key_len = sizeof(int), + * .hashfn = jhash, + * }; + * + * Configuration Example 2: Variable length keys + * struct test_obj { + * [...] + * struct rhash_head node; + * }; + * + * u32 my_hash_fn(const void *data, u32 len, u32 seed) + * { + * struct test_obj *obj = data; + * + * return [... hash ...]; + * } + * + * struct rhashtable_params params = { + * .head_offset = offsetof(struct test_obj, node), + * .hashfn = jhash, + * .obj_hashfn = my_hash_fn, + * }; + */ #define rhashtable_init(...) alloc_hooks(rhashtable_init_noprof(__VA_ARGS__)) int __rhltable_init_noprof(struct rhltable *hlt, const struct rhashtable_params *params, - struct lock_class_key *key); + struct rhashtable_lockdep_keys *keys); #define rhltable_init_noprof(hlt, params) \ ({ \ - static struct lock_class_key __key; \ + static struct rhashtable_lockdep_keys __keys; \ \ - __rhltable_init_noprof(hlt, params, &__key); \ + __rhltable_init_noprof(hlt, params, &__keys); \ }) + +/** + * rhltable_init - initialize a new hash list table + * @hlt: hash list table to be initialized + * @params: configuration parameters + * + * Initializes a new hash list table. + * + * See documentation for rhashtable_init. + */ #define rhltable_init(...) alloc_hooks(rhltable_init_noprof(__VA_ARGS__)) #endif /* _LINUX_RHASHTABLE_TYPES_H */ diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index 6c5e6d9accba..ec853c1b9af3 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h @@ -328,8 +328,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl, local_irq_save(flags); bit_spin_lock(0, (unsigned long *)bucket); - /* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */ - lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_); + lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_); return flags; } diff --git a/lib/rhashtable.c b/lib/rhashtable.c index 5da0e53a8d42..a3a4a1f7751e 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -207,7 +207,6 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht, return NULL; #ifdef CONFIG_LOCKDEP - /* bitlocks must use nesting level 2 or more */ lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", ht->lockdep_key, 0); #endif @@ -432,7 +431,7 @@ static void rht_deferred_worker(struct work_struct *work) int err = 0; ht = container_of(work, struct rhashtable, run_work); - mutex_lock_nested(&ht->mutex, 1); + mutex_lock(&ht->mutex); tbl = rht_dereference(ht->tbl, ht); tbl = rhashtable_last_table(ht, tbl); @@ -1122,51 +1121,9 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed) return jhash2(key, length, seed); } -/** - * rhashtable_init - initialize a new hash table - * @ht: hash table to be initialized - * @params: configuration parameters - * - * Initializes a new hash table based on the provided configuration - * parameters. A table can be configured either with a variable or - * fixed length key: - * - * Configuration Example 1: Fixed length keys - * struct test_obj { - * int key; - * void * my_member; - * struct rhash_head node; - * }; - * - * struct rhashtable_params params = { - * .head_offset = offsetof(struct test_obj, node), - * .key_offset = offsetof(struct test_obj, key), - * .key_len = sizeof(int), - * .hashfn = jhash, - * }; - * - * Configuration Example 2: Variable length keys - * struct test_obj { - * [...] - * struct rhash_head node; - * }; - * - * u32 my_hash_fn(const void *data, u32 len, u32 seed) - * { - * struct test_obj *obj = data; - * - * return [... hash ...]; - * } - * - * struct rhashtable_params params = { - * .head_offset = offsetof(struct test_obj, node), - * .hashfn = jhash, - * .obj_hashfn = my_hash_fn, - * }; - */ int __rhashtable_init_noprof(struct rhashtable *ht, - const struct rhashtable_params *params, - struct lock_class_key *key) + const struct rhashtable_params *params, + struct rhashtable_lockdep_keys *keys) { struct bucket_table *tbl; size_t size; @@ -1176,13 +1133,11 @@ int __rhashtable_init_noprof(struct rhashtable *ht, return -EINVAL; memset(ht, 0, sizeof(*ht)); - /* mutex_lock must use nesting level 1 */ - mutex_init_with_key(&ht->mutex, key); + mutex_init_with_key(&ht->mutex, &keys->mutex_key); spin_lock_init(&ht->lock); - /* spin_lock can use nesting level 0 */ - lockdep_set_class(&ht->lock, key); + lockdep_set_class(&ht->lock, &keys->lock_key); #ifdef CONFIG_LOCKDEP - ht->lockdep_key = key; + ht->lockdep_key = &keys->bucket_key; #endif memcpy(&ht->p, params, sizeof(*params)); @@ -1236,22 +1191,13 @@ int __rhashtable_init_noprof(struct rhashtable *ht, } EXPORT_SYMBOL_GPL(__rhashtable_init_noprof); -/** - * rhltable_init - initialize a new hash list table - * @hlt: hash list table to be initialized - * @params: configuration parameters - * - * Initializes a new hash list table. - * - * See documentation for rhashtable_init. - */ int __rhltable_init_noprof(struct rhltable *hlt, const struct rhashtable_params *params, - struct lock_class_key *key) + struct rhashtable_lockdep_keys *keys) { int err; - err = __rhashtable_init_noprof(&hlt->ht, params, key); + err = __rhashtable_init_noprof(&hlt->ht, params, keys); hlt->ht.rhlist = true; return err; } diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c index 85a615e74591..b767a38a74f9 100644 --- a/lib/test_rhashtable.c +++ b/lib/test_rhashtable.c @@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt) ht = &rhlt->ht; /* Take the mutex to avoid RCU warning */ - mutex_lock_nested(&ht->mutex, 1); + mutex_lock(&ht->mutex); tbl = rht_dereference(ht->tbl, ht); for (i = 0; i < tbl->size; i++) { struct rhash_head *pos, *next; From bbdc0b7a8ea9571aba4331a2191e22914a11b620 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 16 Sep 2026 19:17:01 +0200 Subject: [PATCH 076/146] crypto: atmel-tdes - consolidate transfer setup atmel_tdes_crypt_pdc() and atmel_tdes_crypt_dma() store the transfer length in dd->dma_size and synchronize the bounce buffers before a slow transfer. Move the shared code to atmel_tdes_crypt_start() and use dd->dma_size in atmel_tdes_crypt_pdc() and atmel_tdes_crypt_dma() instead of passing the length separately. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 40 ++++++++++++------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 53150f9b169b..f084fda42423 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -349,20 +349,9 @@ static void atmel_tdes_buff_cleanup(struct atmel_tdes_dev *dd) static int atmel_tdes_crypt_pdc(struct atmel_tdes_dev *dd, dma_addr_t dma_addr_in, - dma_addr_t dma_addr_out, int length) + dma_addr_t dma_addr_out) { - int len32; - - dd->dma_size = length; - - if (!(dd->flags & TDES_FLAGS_FAST)) { - dma_sync_single_for_device(dd->dev, dma_addr_in, length, - DMA_TO_DEVICE); - dma_sync_single_for_device(dd->dev, dma_addr_out, length, - DMA_FROM_DEVICE); - } - - len32 = DIV_ROUND_UP(length, sizeof(u32)); + u32 len32 = DIV_ROUND_UP(dd->dma_size, sizeof(u32)); atmel_tdes_write(dd, TDES_PTCR, TDES_PTCR_TXTDIS|TDES_PTCR_RXTDIS); atmel_tdes_write(dd, TDES_TPR, dma_addr_in); @@ -381,21 +370,12 @@ static int atmel_tdes_crypt_pdc(struct atmel_tdes_dev *dd, static int atmel_tdes_crypt_dma(struct atmel_tdes_dev *dd, dma_addr_t dma_addr_in, - dma_addr_t dma_addr_out, int length) + dma_addr_t dma_addr_out) { struct scatterlist sg[2]; struct dma_async_tx_descriptor *in_desc, *out_desc; enum dma_slave_buswidth addr_width; - dd->dma_size = length; - - if (!(dd->flags & TDES_FLAGS_FAST)) { - dma_sync_single_for_device(dd->dev, dma_addr_in, length, - DMA_TO_DEVICE); - dma_sync_single_for_device(dd->dev, dma_addr_out, length, - DMA_FROM_DEVICE); - } - addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dd->dma_lch_in.dma_conf.dst_addr_width = addr_width; @@ -408,11 +388,11 @@ static int atmel_tdes_crypt_dma(struct atmel_tdes_dev *dd, sg_init_table(&sg[0], 1); sg_dma_address(&sg[0]) = dma_addr_in; - sg_dma_len(&sg[0]) = length; + sg_dma_len(&sg[0]) = dd->dma_size; sg_init_table(&sg[1], 1); sg_dma_address(&sg[1]) = dma_addr_out; - sg_dma_len(&sg[1]) = length; + sg_dma_len(&sg[1]) = dd->dma_size; in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, &sg[0], 1, DMA_MEM_TO_DEV, @@ -486,11 +466,17 @@ static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd) } dd->total -= count; + dd->dma_size = count; + + if (!fast) { + dma_sync_single_for_device(dd->dev, addr_in, dd->dma_size, DMA_TO_DEVICE); + dma_sync_single_for_device(dd->dev, addr_out, dd->dma_size, DMA_FROM_DEVICE); + } if (dd->caps.has_dma) - err = atmel_tdes_crypt_dma(dd, addr_in, addr_out, count); + err = atmel_tdes_crypt_dma(dd, addr_in, addr_out); else - err = atmel_tdes_crypt_pdc(dd, addr_in, addr_out, count); + err = atmel_tdes_crypt_pdc(dd, addr_in, addr_out); if (err && (dd->flags & TDES_FLAGS_FAST)) { dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); From e273759a0e29395a6e35e5f17ce03b2690476b2c Mon Sep 17 00:00:00 2001 From: Mohamad Raizudeen Date: Wed, 16 Sep 2026 23:12:27 +0530 Subject: [PATCH 077/146] crypto: amlogic - Use devm APIs for clock management The driver currently gets the core clock and manually enables it using clk_prepare_enable(). This requires matching calls to clk_disable_unprepare() in the error paths and remove function. Switch to devm_clk_get_enabled() instead. This lets the kernel handle enabling and disabling the clock automatically, which allow us to drop the manual cleanup code and keeps the probe function simple. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202608310329.QgxCCMs1-lkp@intel.com/ Signed-off-by: Mohamad Raizudeen Signed-off-by: Herbert Xu --- drivers/crypto/amlogic/amlogic-gxl-core.c | 41 ++++++++++------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/crypto/amlogic/amlogic-gxl-core.c b/drivers/crypto/amlogic/amlogic-gxl-core.c index 169c6eeb51e5..f292bb25674f 100644 --- a/drivers/crypto/amlogic/amlogic-gxl-core.c +++ b/drivers/crypto/amlogic/amlogic-gxl-core.c @@ -243,33 +243,29 @@ static int meson_crypto_probe(struct platform_device *pdev) if (IS_ERR(mc->base)) return PTR_ERR(mc->base); - mc->busclk = devm_clk_get(&pdev->dev, "blkmv"); + mc->busclk = devm_clk_get_enabled(&pdev->dev, "blkmv"); if (IS_ERR(mc->busclk)) { err = PTR_ERR(mc->busclk); - dev_err(&pdev->dev, "Cannot get core clock err=%d\n", err); - return err; - } - - for (i = 0; i < MAXFLOW; i++) { - mc->irqs[i] = platform_get_irq(pdev, i); - if (mc->irqs[i] < 0) - return mc->irqs[i]; - - err = devm_request_irq(&pdev->dev, mc->irqs[i], meson_irq_handler, 0, - "gxl-crypto", mc); - if (err < 0) - return err; - } - - err = clk_prepare_enable(mc->busclk); - if (err != 0) { - dev_err(&pdev->dev, "Cannot prepare_enable busclk\n"); + dev_err(&pdev->dev, "Cannot get/enable core clock err=%d\n", err); return err; } err = meson_allocate_chanlist(mc); if (err) - goto error_flow; + return err; + + for (i = 0; i < MAXFLOW; i++) { + mc->irqs[i] = platform_get_irq(pdev, i); + if (mc->irqs[i] < 0) { + err = mc->irqs[i]; + goto error_chanlist; + } + + err = devm_request_irq(&pdev->dev, mc->irqs[i], meson_irq_handler, 0, + "gxl-crypto", mc); + if (err < 0) + goto error_chanlist; + } err = meson_register_algs(mc); if (err) @@ -289,9 +285,8 @@ static int meson_crypto_probe(struct platform_device *pdev) return 0; error_alg: meson_unregister_algs(mc); +error_chanlist: meson_free_chanlist(mc, MAXFLOW - 1); -error_flow: - clk_disable_unprepare(mc->busclk); return err; } @@ -306,8 +301,6 @@ static void meson_crypto_remove(struct platform_device *pdev) meson_unregister_algs(mc); meson_free_chanlist(mc, MAXFLOW - 1); - - clk_disable_unprepare(mc->busclk); } static const struct of_device_id meson_crypto_of_match_table[] = { From 4e721fe9cb2a5cd899730f744c9cfb6bd39b37d0 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Thu, 17 Sep 2026 07:56:45 +0200 Subject: [PATCH 078/146] lib/842: depend on the decompressor for KUnit tests 842_DECOMPRESS_KUNIT_TEST selects the decompressor even when no other option needs it, including through KUNIT_ALL_TESTS. Depend on 842_DECOMPRESS as required by Documentation/dev-tools/kunit/style.rst. This also prevents the test from promoting a modular decompressor to built-in. Fixes: cca072cb1423 ("lib/842: add KUnit tests for the decompressor") Reported-by: Geert Uytterhoeven Closes: https://lore.kernel.org/r/CAMuHMdVcZ5cV4-HrjLYfFKh6UshiVxq5eXCNyp0Z1k_SMAvF5g@mail.gmail.com/ Assisted-by: LLM Signed-off-by: Karl Mehltretter Acked-by: David Gow Signed-off-by: Herbert Xu --- lib/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 48201092b3df..49f74005394b 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2228,7 +2228,7 @@ if RUNTIME_TESTING_MENU config 842_DECOMPRESS_KUNIT_TEST tristate "KUnit tests for the 842 decompressor" if !KUNIT_ALL_TESTS depends on KUNIT - select 842_DECOMPRESS + depends on 842_DECOMPRESS default KUNIT_ALL_TESTS help Enable stream-validation and boundary tests for the software 842 From 1dfb35de0800967c972eee35e19f3dfc8d50e512 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 18 Sep 2026 18:27:20 +1000 Subject: [PATCH 079/146] crypto: api - Fix DUP_FIRST crash on unregister The flag CRYPTO_ALG_DUP_FIRST is buggy because upon unregistration it tries to unregister the original algorithm rather than the duplicate which was allocated during registration. Fix this by locating the duplicated algorithm and unregistering that instead of the original. Also remove the duplicate crypto_destroy_alg call. Reported-by: Chenghai Huang Fixes: f1440a90465b ("crypto: api - Add support for duplicating algorithms before registration") Signed-off-by: Herbert Xu --- crypto/algapi.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/crypto/algapi.c b/crypto/algapi.c index 37de377719ae..a6839e2a20f3 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -424,7 +424,6 @@ static void crypto_free_alg(struct crypto_alg *alg) unsigned int algsize = alg->cra_type->algsize; u8 *p = (u8 *)alg - algsize; - crypto_destroy_alg(alg); kfree(p); } @@ -494,9 +493,31 @@ void crypto_unregister_alg(struct crypto_alg *alg) LIST_HEAD(list); down_write(&crypto_alg_sem); + if (alg->cra_flags & CRYPTO_ALG_DUP_FIRST) { + struct crypto_alg *q, *r = NULL; + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (crypto_is_larval(q)) + continue; + if (strcmp(q->cra_driver_name, alg->cra_driver_name)) + continue; + r = q; + break; + } + + if (!r) { + up_write(&crypto_alg_sem); + ret = -ENOENT; + goto not_found; + } + + alg = r; + } + ret = crypto_remove_alg(alg, &list); up_write(&crypto_alg_sem); +not_found: if (WARN(ret, "Algorithm %s is not registered", alg->cra_driver_name)) return; From 4b8ae2732070c5669adee2d5d3bb97b14af53a63 Mon Sep 17 00:00:00 2001 From: Mohamad Raizudeen Date: Fri, 18 Sep 2026 17:29:50 +0530 Subject: [PATCH 080/146] crypto: amlogic - Fix IRQ handler return value and fallthrough logic In meson_irq_handler(), when an interrupt matches a flow but the status register is empty, the driver prints an error but doesn't return. It falls through the loop and incorrectly prints an `unknown irq` message. Fix this by returning immediately. For empty status registers, return IRQ_NONE instead of IRQ_HANDLED to avoid masking spurious interrupts and allow the kernel to detect interrupt storms. Also use dev_err_ratelimited() to prevent console lockups during an interrupt storm. Additionally, the handler returned IRQ_HANDLED for genuinely unknown interrupts. Return IRQ_NONE instead for unhandled interrupts. Cc: stable@vger.kernel.org Fixes: 48fe583fe5417 ("crypto: amlogic - Add crypto accelerator for amlogic GXL") Signed-off-by: Mohamad Raizudeen Signed-off-by: Herbert Xu --- drivers/crypto/amlogic/amlogic-gxl-core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/amlogic/amlogic-gxl-core.c b/drivers/crypto/amlogic/amlogic-gxl-core.c index f292bb25674f..d5d84524c110 100644 --- a/drivers/crypto/amlogic/amlogic-gxl-core.c +++ b/drivers/crypto/amlogic/amlogic-gxl-core.c @@ -37,12 +37,13 @@ static irqreturn_t meson_irq_handler(int irq, void *data) complete(&mc->chanlist[flow].complete); return IRQ_HANDLED; } - dev_err(mc->dev, "%s %d Got irq for flow %d but ctrl is empty\n", __func__, irq, flow); + dev_err_ratelimited(mc->dev, "%s %d Got irq for flow %d but ctrl is empty\n", __func__, irq, flow); + return IRQ_NONE; } } - dev_err(mc->dev, "%s %d from unknown irq\n", __func__, irq); - return IRQ_HANDLED; + dev_err_ratelimited(mc->dev, "%s %d from unknown irq\n", __func__, irq); + return IRQ_NONE; } static struct meson_alg_template mc_algs[] = { From 9770bb7d335f8f8db01e99168bbdd9ce2cb6238c Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Fri, 18 Sep 2026 20:27:20 +0800 Subject: [PATCH 081/146] crypto: hisilicon/hpre - fix pointer dereference before length check In hpre_rsa_drop_leading_zeros(), the loop condition dereferences *ptr before checking *len, causing an out-of-bounds read when *len is zero. Swap to while (*len && !**ptr) to test length first. Fixes: c8b4b477079d ("crypto: hisilicon - add HiSilicon HPRE accelerator") Cc: stable@vger.kernel.org Signed-off-by: Weili Qian Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c index 09077abbf6ad..7894211b9972 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c +++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c @@ -720,7 +720,7 @@ static void hpre_dh_exit_tfm(struct crypto_kpp *tfm) static void hpre_rsa_drop_leading_zeros(const char **ptr, size_t *len) { - while (!**ptr && *len) { + while (*len && !**ptr) { (*ptr)++; (*len)--; } From 5b87f619cc5c0a55dcd85ce97974e3f5b9333b7b Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Fri, 18 Sep 2026 20:27:21 +0800 Subject: [PATCH 082/146] crypto: hisilicon/hpre - remove dma_free_coherent on NULL req->dst in ECDH In hpre_ecdh_hw_data_clr_all(), req->dst is always NULL because hpre_ecdh_dst_data_init() sets hpre_req->dst = NULL before mapping the user buffer with dma_map_single(). The dma_free_coherent() call on req->dst is therefore dead code. Remove it. Fixes: 05e7b906aa7c ("crypto: hisilicon/hpre - add 'ECDH' algorithm") Signed-off-by: Weili Qian Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre_crypto.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c index 7894211b9972..8551d6ccb78d 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c +++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c @@ -1407,8 +1407,6 @@ static void hpre_ecdh_hw_data_clr_all(struct hpre_ctx *ctx, if (unlikely(dma_mapping_error(dev, dma))) return; - if (req->dst) - dma_free_coherent(dev, ctx->key_sz << 1, req->dst, dma); if (dst) dma_unmap_single(dev, dma, ctx->key_sz << 1, DMA_FROM_DEVICE); } From 232804a5ed70a8ace32c46d341d438aeba54bc67 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Fri, 18 Sep 2026 20:27:22 +0800 Subject: [PATCH 083/146] crypto: hisilicon/hpre - return -EOVERFLOW for small ECDH output buffer hpre_ecdh_msg_request_set() returns -EINVAL when the output buffer is too small, after setting req->dst_len to the required size. -EINVAL is misleading because the caller can retry with a larger buffer. Return -EOVERFLOW as other kpp implementations do. Fixes: 05e7b906aa7c ("crypto: hisilicon/hpre - add 'ECDH' algorithm") Cc: stable@vger.kernel.org Signed-off-by: Weili Qian Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c index 8551d6ccb78d..6dea9ce5bae2 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c +++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c @@ -1450,7 +1450,7 @@ static int hpre_ecdh_msg_request_set(struct hpre_ctx *ctx, if (req->dst_len < ctx->key_sz << 1) { req->dst_len = ctx->key_sz << 1; - return -EINVAL; + return -EOVERFLOW; } tmp = kpp_request_ctx(req); From 12d8edda8cdb41d18c4891851e25bf58be6be995 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Fri, 18 Sep 2026 20:27:23 +0800 Subject: [PATCH 084/146] crypto: hisilicon/hpre - fix ECDH destination DMA mapping hpre_ecdh_dst_data_init() rejects valid requests whose output length does not equal ctx->key_sz << 1, and maps the user buffer using the user-provided len instead of the hardware transfer size. Drop the redundant length check and use ctx->key_sz << 1 for dma_map_single() so the whole hardware output is mapped. Fixes: 05e7b906aa7c ("crypto: hisilicon/hpre - add 'ECDH' algorithm") Cc: stable@vger.kernel.org Signed-off-by: Weili Qian Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre_crypto.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c index 6dea9ce5bae2..f77c318caa35 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c +++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c @@ -1510,13 +1510,13 @@ static int hpre_ecdh_dst_data_init(struct hpre_asym_request *hpre_req, struct device *dev = ctx->dev; dma_addr_t dma; - if (unlikely(!data || !sg_is_last(data) || len != ctx->key_sz << 1)) { - dev_err(dev, "data or data length is illegal!\n"); + if (unlikely(!data || !sg_is_last(data))) { + dev_err(dev, "data is illegal!\n"); return -EINVAL; } hpre_req->dst = NULL; - dma = dma_map_single(dev, sg_virt(data), len, DMA_FROM_DEVICE); + dma = dma_map_single(dev, sg_virt(data), ctx->key_sz << 1, DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(dev, dma))) { dev_err(dev, "dma map data err!\n"); return -ENOMEM; From 40ec9605cb195e065470f8f23ef94b1b541411a3 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Fri, 18 Sep 2026 20:27:24 +0800 Subject: [PATCH 085/146] crypto: hisilicon/hpre - fix GFP flags for dma_alloc_coherent The HPRE driver hard-codes GFP_ATOMIC for RSA/DH and GFP_KERNEL for ECDH. This may cause "scheduling while atomic" in atomic context or unnecessary allocation failures under memory pressure. Select GFP flags dynamically based on CRYPTO_TFM_REQ_MAY_SLEEP and store them in hpre_asym_request::flags. The areq field is a union of rsa/dh/ecdh request pointers; reading base.flags through any union member other than the one that was written would be type-punning, so a dedicated flags field avoids that. Fixes: 98dfa9343f37 ("crypto: hisilicon/hpre - don't use GFP_KERNEL to alloc mem during softirq") Cc: stable@vger.kernel.org Signed-off-by: Weili Qian Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre_crypto.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c index f77c318caa35..6ca34f3bf9ff 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c +++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c @@ -138,6 +138,7 @@ struct hpre_asym_request { int err; hpre_cb cb; struct timespec64 req_time; + u32 flags; }; static inline unsigned int hpre_align_sz(void) @@ -186,6 +187,7 @@ static int hpre_prepare_dma_buf(struct hpre_asym_request *hpre_req, struct scatterlist *data, unsigned int len, int is_src, dma_addr_t *tmp) { + gfp_t gfp = hpre_req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; struct hpre_ctx *ctx = hpre_req->ctx; struct device *dev = ctx->dev; void *ptr; @@ -195,7 +197,7 @@ static int hpre_prepare_dma_buf(struct hpre_asym_request *hpre_req, if (unlikely(shift < 0)) return -EINVAL; - ptr = dma_alloc_coherent(dev, ctx->key_sz, tmp, GFP_ATOMIC); + ptr = dma_alloc_coherent(dev, ctx->key_sz, tmp, gfp); if (unlikely(!ptr)) return -ENOMEM; @@ -419,6 +421,7 @@ static int hpre_msg_request_set(struct hpre_ctx *ctx, void *req, bool is_rsa) h_req = PTR_ALIGN(tmp, hpre_align_sz()); h_req->cb = hpre_rsa_cb; h_req->areq.rsa = akreq; + h_req->flags = akreq->base.flags; msg = &h_req->req; memset(msg, 0, sizeof(*msg)); } else { @@ -433,6 +436,7 @@ static int hpre_msg_request_set(struct hpre_ctx *ctx, void *req, bool is_rsa) h_req = PTR_ALIGN(tmp, hpre_align_sz()); h_req->cb = hpre_dh_cb; h_req->areq.dh = kreq; + h_req->flags = kreq->base.flags; msg = &h_req->req; memset(msg, 0, sizeof(*msg)); msg->key = cpu_to_le64(ctx->dh.dma_xa_p); @@ -1457,6 +1461,7 @@ static int hpre_ecdh_msg_request_set(struct hpre_ctx *ctx, h_req = PTR_ALIGN(tmp, hpre_align_sz()); h_req->cb = hpre_ecdh_cb; h_req->areq.ecdh = req; + h_req->flags = req->base.flags; msg = &h_req->req; memset(msg, 0, sizeof(*msg)); msg->in = cpu_to_le64(DMA_MAPPING_ERROR); @@ -1475,6 +1480,7 @@ static int hpre_ecdh_msg_request_set(struct hpre_ctx *ctx, static int hpre_ecdh_src_data_init(struct hpre_asym_request *hpre_req, struct scatterlist *data, unsigned int len) { + gfp_t gfp = hpre_req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; struct hpre_sqe *msg = &hpre_req->req; struct hpre_ctx *ctx = hpre_req->ctx; struct device *dev = ctx->dev; @@ -1488,7 +1494,7 @@ static int hpre_ecdh_src_data_init(struct hpre_asym_request *hpre_req, if (unlikely(shift < 0)) return -EINVAL; - ptr = dma_alloc_coherent(dev, ctx->key_sz << 2, &dma, GFP_KERNEL); + ptr = dma_alloc_coherent(dev, ctx->key_sz << 2, &dma, gfp); if (unlikely(!ptr)) return -ENOMEM; From 16cea0e5037b11bae2b1a8d2faf4de4a0af0e29b Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Fri, 18 Sep 2026 20:27:25 +0800 Subject: [PATCH 086/146] crypto: hisilicon/hpre - extract clusters num into inline function Seven functions in hpre_main.c open-code the same cluster number extraction from HPRE_CORE_INFO. Extract into hpre_get_clusters_num(). hpre_pre_store_cap_reg() uses a local hpre_cap[] array rather than qm->cap_tables.dev_cap_table[] and is therefore not converted. Signed-off-by: Weili Qian Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre_main.c | 43 ++++++++--------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index b6903fce6071..e1a567383de5 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -381,6 +381,14 @@ static const char *hpre_channel_name[HPRE_MAX_CHANNEL_NUM] = { static const struct hisi_qm_err_ini hpre_err_ini; +static inline u8 hpre_get_clusters_num(struct hisi_qm *qm) +{ + u32 cap = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val; + + return (cap >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) & + hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask; +} + bool hpre_check_alg_support(struct hisi_qm *qm, u32 alg) { u32 cap_val; @@ -557,15 +565,12 @@ static int hpre_set_cluster(struct hisi_qm *qm) struct device *dev = &qm->pdev->dev; u32 cluster_core_mask; unsigned long offset; - u32 hpre_core_info; u8 clusters_num; u32 val = 0; int ret, i; cluster_core_mask = qm->cap_tables.dev_cap_table[HPRE_CORE_EN].cap_val; - hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val; - clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) & - hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask; + clusters_num = hpre_get_clusters_num(qm); for (i = 0; i < clusters_num; i++) { offset = i * HPRE_CLSTR_ADDR_INTRVL; @@ -659,7 +664,6 @@ static void hpre_enable_clock_gate(struct hisi_qm *qm) { unsigned long offset; u8 clusters_num, i; - u32 hpre_core_info; u32 val; if (qm->ver < QM_HW_V3) @@ -673,9 +677,7 @@ static void hpre_enable_clock_gate(struct hisi_qm *qm) val |= HPRE_PEH_CFG_AUTO_GATE_EN; writel(val, qm->io_base + HPRE_PEH_CFG_AUTO_GATE); - hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val; - clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) & - hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask; + clusters_num = hpre_get_clusters_num(qm); for (i = 0; i < clusters_num; i++) { offset = (unsigned long)i * HPRE_CLSTR_ADDR_INTRVL; val = readl(qm->io_base + offset + HPRE_CLUSTER_DYN_CTL); @@ -692,7 +694,6 @@ static void hpre_disable_clock_gate(struct hisi_qm *qm) { unsigned long offset; u8 clusters_num, i; - u32 hpre_core_info; u32 val; if (qm->ver < QM_HW_V3) @@ -706,9 +707,7 @@ static void hpre_disable_clock_gate(struct hisi_qm *qm) val &= ~HPRE_PEH_CFG_AUTO_GATE_EN; writel(val, qm->io_base + HPRE_PEH_CFG_AUTO_GATE); - hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val; - clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) & - hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask; + clusters_num = hpre_get_clusters_num(qm); for (i = 0; i < clusters_num; i++) { offset = (unsigned long)i * HPRE_CLSTR_ADDR_INTRVL; val = readl(qm->io_base + offset + HPRE_CLUSTER_DYN_CTL); @@ -782,14 +781,11 @@ static int hpre_set_user_domain_and_cache(struct hisi_qm *qm) static void hpre_cnt_regs_clear(struct hisi_qm *qm) { unsigned long offset; - u32 hpre_core_info; u8 clusters_num; int i; /* clear clusterX/cluster_ctrl */ - hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val; - clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) & - hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask; + clusters_num = hpre_get_clusters_num(qm); for (i = 0; i < clusters_num; i++) { offset = HPRE_CLSTR_BASE + i * HPRE_CLSTR_ADDR_INTRVL; writel(0x0, qm->io_base + offset + HPRE_CLUSTER_INQURY); @@ -1072,13 +1068,10 @@ static int hpre_cluster_debugfs_init(struct hisi_qm *qm) char buf[HPRE_DBGFS_VAL_MAX_LEN]; struct debugfs_regset32 *regset; struct dentry *tmp_d; - u32 hpre_core_info; u8 clusters_num; int i, ret; - hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val; - clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) & - hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask; + clusters_num = hpre_get_clusters_num(qm); for (i = 0; i < clusters_num; i++) { ret = snprintf(buf, HPRE_DBGFS_VAL_MAX_LEN, "cluster%d", i); if (ret >= HPRE_DBGFS_VAL_MAX_LEN) @@ -1308,13 +1301,10 @@ static int hpre_show_last_regs_init(struct hisi_qm *qm) int com_dfx_regs_num = ARRAY_SIZE(hpre_com_dfx_regs); struct qm_debug *debug = &qm->debug; void __iomem *io_base; - u32 hpre_core_info; u8 clusters_num; int i, j, idx; - hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val; - clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) & - hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask; + clusters_num = hpre_get_clusters_num(qm); debug->last_words = kcalloc(cluster_dfx_regs_num * clusters_num + com_dfx_regs_num, sizeof(unsigned int), GFP_KERNEL); if (!debug->last_words) @@ -1354,7 +1344,6 @@ static void hpre_show_last_dfx_regs(struct hisi_qm *qm) struct qm_debug *debug = &qm->debug; struct pci_dev *pdev = qm->pdev; void __iomem *io_base; - u32 hpre_core_info; u8 clusters_num; int i, j, idx; u32 val; @@ -1370,9 +1359,7 @@ static void hpre_show_last_dfx_regs(struct hisi_qm *qm) hpre_com_dfx_regs[i].name, debug->last_words[i], val); } - hpre_core_info = qm->cap_tables.dev_cap_table[HPRE_CORE_INFO].cap_val; - clusters_num = (hpre_core_info >> hpre_basic_info[HPRE_CLUSTER_NUM_CAP].shift) & - hpre_basic_info[HPRE_CLUSTER_NUM_CAP].mask; + clusters_num = hpre_get_clusters_num(qm); for (i = 0; i < clusters_num; i++) { io_base = qm->io_base + hpre_cluster_offsets[i]; for (j = 0; j < cluster_dfx_regs_num; j++) { From 9be1b28a959bc953d36412b98560cb80f2716e25 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Fri, 18 Sep 2026 20:27:26 +0800 Subject: [PATCH 087/146] crypto: hisilicon/hpre - remove unused macros and struct fields Several macros, the hpre_asym_request::err field and the hpre::status field are defined but never referenced. Remove them. Signed-off-by: Weili Qian Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre.h | 1 - drivers/crypto/hisilicon/hpre/hpre_crypto.c | 6 ------ drivers/crypto/hisilicon/hpre/hpre_main.c | 4 ---- 3 files changed, 11 deletions(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre.h b/drivers/crypto/hisilicon/hpre/hpre.h index 021dbd9a1d48..f73d01f6da87 100644 --- a/drivers/crypto/hisilicon/hpre/hpre.h +++ b/drivers/crypto/hisilicon/hpre/hpre.h @@ -70,7 +70,6 @@ struct hpre_debug { struct hpre { struct hisi_qm qm; struct hpre_debug debug; - unsigned long status; }; enum hpre_alg_type { diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c index 6ca34f3bf9ff..66a276786a7d 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c +++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c @@ -21,19 +21,15 @@ struct hpre_ctx; #define HPRE_CRYPTO_ALG_PRI 1000 #define HPRE_ALIGN_SZ 64 #define HPRE_BITS_2_BYTES_SHIFT 3 -#define HPRE_RSA_512BITS_KSZ 64 -#define HPRE_RSA_1536BITS_KSZ 192 #define HPRE_CRT_PRMS 5 #define HPRE_CRT_Q 2 #define HPRE_CRT_P 3 #define HPRE_CRT_INV 4 #define HPRE_DH_G_FLAG 0x02 #define HPRE_TRY_SEND_TIMES 100 -#define HPRE_INVLD_REQ_ID (-1) #define HPRE_SQE_ALG_BITS 5 #define HPRE_SQE_DONE_SHIFT 30 -#define HPRE_DH_MAX_P_SZ 512 #define HPRE_DFX_SEC_TO_US 1000000 #define HPRE_DFX_US_TO_NS 1000 @@ -56,7 +52,6 @@ struct hpre_ctx; #define HPRE_DRV_RSA_MASK_CAP BIT(0) #define HPRE_DRV_DH_MASK_CAP BIT(1) #define HPRE_DRV_ECDH_MASK_CAP BIT(2) -#define HPRE_DRV_X25519_MASK_CAP BIT(5) static DEFINE_MUTEX(hpre_algs_lock); static unsigned int hpre_available_devs; @@ -135,7 +130,6 @@ struct hpre_asym_request { struct kpp_request *dh; struct kpp_request *ecdh; } areq; - int err; hpre_cb cb; struct timespec64 req_time; u32 flags; diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index e1a567383de5..03aa11a7a3b4 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -16,7 +16,6 @@ #define CAP_FILE_PERMISSION 0444 #define HPRE_CTRL_CNT_CLR_CE_BIT BIT(0) #define HPRE_CTRL_CNT_CLR_CE 0x301000 -#define HPRE_FSM_MAX_CNT 0x301008 #define HPRE_VFG_AXQOS 0x30100c #define HPRE_VFG_AXCACHE 0x301010 #define HPRE_RDCHN_INI_CFG 0x301014 @@ -41,7 +40,6 @@ #define HPRE_HAC_INT_SET 0x301500 #define HPRE_AXI_ERROR_MASK GENMASK(21, 10) #define HPRE_RNG_TIMEOUT_NUM 0x301A34 -#define HPRE_CORE_INT_ENABLE 0 #define HPRE_RDCHN_INI_ST 0x301a00 #define HPRE_CLSTR_BASE 0x302000 #define HPRE_CORE_EN_OFFSET 0x04 @@ -61,8 +59,6 @@ #define HPRE_CORE_ENB (HPRE_CLSTR_BASE + HPRE_CORE_EN_OFFSET) #define HPRE_CORE_INI_CFG (HPRE_CLSTR_BASE + HPRE_CORE_INI_CFG_OFFSET) #define HPRE_CORE_INI_STATUS (HPRE_CLSTR_BASE + HPRE_CORE_INI_STATUS_OFFSET) -#define HPRE_HAC_ECC1_CNT 0x301a04 -#define HPRE_HAC_ECC2_CNT 0x301a08 #define HPRE_HAC_SOURCE_INT 0x301600 #define HPRE_CLSTR_ADDR_INTRVL 0x1000 #define HPRE_CLUSTER_INQURY 0x100 From cb3a1364fed9ea7b063e3ae026177a145abb5940 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Fri, 18 Sep 2026 13:41:11 +0100 Subject: [PATCH 088/146] crypto: qat - hold cfg->lock when accessing config sections adf_cfg_sec_find() walks the per-device section list without holding cfg->lock, and the returned section pointer is used later under the lock. A concurrent section deletion under cfg->lock (adf_cfg_del_all_except() on device down, or adf_cfg_dev_remove() on removal) can free the section first, leading to a use-after-free. The debugfs dev_cfg reader has the same problem: qat_dev_cfg_show() walks both the section list and each section's param_head under the global qat_cfg_read_lock mutex, not the per-device cfg->lock used by the add and delete paths, so the two do not serialise. Updating an existing key frees the old key_val under cfg->lock, so even a config write concurrent with an open dev_cfg read can free an entry mid-walk, a wider window than section deletion alone. Take cfg->lock around the section lookup in adf_cfg_add_key_value_param() and around the lookup and insert in adf_cfg_section_add(), and use down_read()/up_read(&cfg->lock) in the debugfs start/stop callbacks. Remove the now-unused qat_cfg_read_lock. While here, return -ENOENT rather than -EFAULT when the section is not found; EFAULT (bad userspace address) is not meaningful for this case. Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework") Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_cfg.c | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.c b/drivers/crypto/intel/qat/qat_common/adf_cfg.c index b88febf53a19..e13db9ede0fa 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) /* Copyright(c) 2014 - 2020 Intel Corporation */ -#include #include #include #include @@ -9,13 +8,11 @@ #include "adf_cfg.h" #include "adf_common_drv.h" -static DEFINE_MUTEX(qat_cfg_read_lock); - static void *qat_dev_cfg_start(struct seq_file *sfile, loff_t *pos) { struct adf_cfg_device_data *dev_cfg = sfile->private; - mutex_lock(&qat_cfg_read_lock); + down_read(&dev_cfg->lock); return seq_list_start(&dev_cfg->sec_list, *pos); } @@ -43,7 +40,9 @@ static void *qat_dev_cfg_next(struct seq_file *sfile, void *v, loff_t *pos) static void qat_dev_cfg_stop(struct seq_file *sfile, void *v) { - mutex_unlock(&qat_cfg_read_lock); + struct adf_cfg_device_data *dev_cfg = sfile->private; + + up_read(&dev_cfg->lock); } static const struct seq_operations qat_dev_cfg_sops = { @@ -272,13 +271,10 @@ int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, enum adf_cfg_val_type type) { struct adf_cfg_device_data *cfg = accel_dev->cfg; + struct adf_cfg_section *section; struct adf_cfg_key_val *key_val; - struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev, - section_name); char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; - - if (!section) - return -EFAULT; + int ret = 0; key_val = kzalloc_obj(*key_val); if (!key_val) @@ -308,20 +304,28 @@ int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, * anything (the newly created key_val is freed). */ down_write(&cfg->lock); + + section = adf_cfg_sec_find(accel_dev, section_name); + if (!section) { + kfree(key_val); + ret = -ENOENT; + goto unlock; + } + if (!adf_cfg_key_val_get(accel_dev, section_name, key, temp_val)) { if (strncmp(temp_val, key_val->val, sizeof(temp_val))) { adf_cfg_keyval_remove(key, section); } else { kfree(key_val); - goto out; + goto unlock; } } adf_cfg_keyval_add(key_val, section); -out: +unlock: up_write(&cfg->lock); - return 0; + return ret; } EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param); @@ -339,21 +343,26 @@ EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param); int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name) { struct adf_cfg_device_data *cfg = accel_dev->cfg; - struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name); + struct adf_cfg_section *sec; + int ret = 0; - if (sec) - return 0; + down_write(&cfg->lock); + + if (adf_cfg_sec_find(accel_dev, name)) + goto unlock; sec = kzalloc_obj(*sec); - if (!sec) - return -ENOMEM; + if (!sec) { + ret = -ENOMEM; + goto unlock; + } strscpy(sec->name, name); INIT_LIST_HEAD(&sec->param_head); - down_write(&cfg->lock); list_add_tail(&sec->list, &cfg->sec_list); +unlock: up_write(&cfg->lock); - return 0; + return ret; } EXPORT_SYMBOL_GPL(adf_cfg_section_add); From a76c75cd6f8345b728e20e7bcddf0bac1fa6ba43 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Fri, 18 Sep 2026 13:41:12 +0100 Subject: [PATCH 089/146] crypto: qat - avoid redundant config list walks when adding a key adf_cfg_add_key_value_param() now resolves the target section under cfg->lock, but still calls adf_cfg_key_val_get(), which re-walks the section list to find that same section and then walks param_head to read the current value into a temporary buffer. If the value differs it calls adf_cfg_keyval_remove(), which walks param_head a third time to locate the entry that was already found. Look up the existing entry once with adf_cfg_key_value_find() and act on that pointer directly: free the new copy if the value is unchanged, or unlink and free the old entry before adding the new one. This drops two redundant list walks and the on-stack temp_val copy, and removes the now unused adf_cfg_keyval_remove() helper. No functional change. Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_cfg.c | 47 ++++++------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.c b/drivers/crypto/intel/qat/qat_common/adf_cfg.c index e13db9ede0fa..e2ef5284abef 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c @@ -145,24 +145,6 @@ static void adf_cfg_keyval_add(struct adf_cfg_key_val *new, list_add_tail(&new->list, &sec->param_head); } -static void adf_cfg_keyval_remove(const char *key, struct adf_cfg_section *sec) -{ - struct list_head *head = &sec->param_head; - struct list_head *list_ptr, *tmp; - - list_for_each_prev_safe(list_ptr, tmp, head) { - struct adf_cfg_key_val *ptr = - list_entry(list_ptr, struct adf_cfg_key_val, list); - - if (strncmp(ptr->key, key, sizeof(ptr->key))) - continue; - - list_del(list_ptr); - kfree(ptr); - break; - } -} - static void adf_cfg_keyval_del_all(struct list_head *head) { struct list_head *list_ptr, *tmp; @@ -271,9 +253,8 @@ int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, enum adf_cfg_val_type type) { struct adf_cfg_device_data *cfg = accel_dev->cfg; + struct adf_cfg_key_val *key_val, *existing; struct adf_cfg_section *section; - struct adf_cfg_key_val *key_val; - char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; int ret = 0; key_val = kzalloc_obj(*key_val); @@ -295,14 +276,6 @@ int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, } key_val->type = type; - /* Add the key-value pair as below policy: - * 1. if the key doesn't exist, add it; - * 2. if the key already exists with a different value then update it - * to the new value (the key is deleted and the newly created - * key_val containing the new value is added to the database); - * 3. if the key exists with the same value, then return without doing - * anything (the newly created key_val is freed). - */ down_write(&cfg->lock); section = adf_cfg_sec_find(accel_dev, section_name); @@ -312,13 +285,23 @@ int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, goto unlock; } - if (!adf_cfg_key_val_get(accel_dev, section_name, key, temp_val)) { - if (strncmp(temp_val, key_val->val, sizeof(temp_val))) { - adf_cfg_keyval_remove(key, section); - } else { + /* + * Add the key-value pair as below policy: + * 1. if the key doesn't exist, add it; + * 2. if the key already exists with a different value then update it + * to the new value (the key is deleted and the newly created + * key_val containing the new value is added to the database); + * 3. if the key exists with the same value, then return without doing + * anything (the newly created key_val is freed). + */ + existing = adf_cfg_key_value_find(section, key); + if (existing) { + if (!strncmp(existing->val, key_val->val, sizeof(existing->val))) { kfree(key_val); goto unlock; } + list_del(&existing->list); + kfree(existing); } adf_cfg_keyval_add(key_val, section); From 360094ceb2357ed65a9ed7868397ce490fc93ddd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 18 Sep 2026 16:27:36 -0700 Subject: [PATCH 090/146] crypto: ccp - Clean up kernel-doc warnings in psp-sev.h Clean up kernel-doc comments to prevent warnings in both and . include/linux/psp-sev.h: (62 lines; edited for brevity) Warning: include/linux/psp-sev.h:52 This comment starts with '/**', but isn't a kernel-doc comment. * SEV platform state Warning: include/linux/psp-sev.h:63 This comment starts with '/**', but isn't a kernel-doc comment. * SEV platform and guest management commands Warning: include/linux/psp-sev.h:167 struct member 'reserved' not described in 'sev_data_init' Warning: include/linux/psp-sev.h:187 struct member 'reserved' not described in 'sev_data_init_ex' Warning: include/linux/psp-sev.h:216 expecting prototype for struct sev_data_cert_import. Prototype was for struct sev_data_pek_cert_import instead Warning: include/linux/psp-sev.h:253 struct member 'pdh_cert_address' not described in 'sev_data_pdh_cert_export' Warning: include/linux/psp-sev.h:253 struct member 'pdh_cert_len' not described in 'sev_data_pdh_cert_export' Warning: include/linux/psp-sev.h:253 struct member 'reserved' not described in 'sev_data_pdh_cert_export' Warning: include/linux/psp-sev.h:253 Excess struct member 'pdh_address' description in 'sev_data_pdh_cert_export' (did you mean one of: 'pdh_cert_address', 'cert_chain_address') Warning: include/linux/psp-sev.h:253 Excess struct member 'pdh_len' description in 'sev_data_pdh_cert_export' (did you mean one of: 'pdh_cert_len') Warning: include/linux/psp-sev.h:446 expecting prototype for struct sev_data_send_update. Prototype was for struct sev_data_send_update_data instead Warning: include/linux/psp-sev.h:469 expecting prototype for struct sev_data_send_update. Prototype was for struct sev_data_send_update_vmsa instead Warning: include/linux/psp-sev.h:506 struct member 'policy' not described in 'sev_data_receive_start' Warning: include/linux/psp-sev.h:799 struct member 'rapl_dis' not described in 'sev_data_snp_init_ex' Warning: include/linux/psp-sev.h:799 struct member 'ciphertext_hiding_en' not described in 'sev_data_snp_init_ex' Warning: include/linux/psp-sev.h:799 struct member 'tio_en' not described in 'sev_data_snp_init_ex' Warning: include/linux/psp-sev.h:799 struct member 'max_snp_asid' not described in 'sev_data_snp_init_ex' Warning: include/linux/psp-sev.h:843 missing initial short description on line: * struct sev_platform_init_args Warning: include/linux/psp-sev.h:893 expecting prototype for struct feature_info. Prototype was for struct snp_feature_info instead Warning: include/linux/psp-sev.h:956 missing initial short description on line: * struct sev_snp_tcb_version_genoa_milan Warning: include/linux/psp-sev.h:973 missing initial short description on line: * struct sev_snp_tcb_version_turin Warning: include/linux/psp-sev.h:1053 function parameter 'filep' not described in 'sev_issue_cmd_external_user' Warning: include/linux/psp-sev.h:1053 function parameter 'id' not described in 'sev_issue_cmd_external_user' Warning: include/linux/psp-sev.h:1112 function parameter 'data' not described in 'sev_guest_decommission' Warning: include/linux/psp-sev.h:1112 function parameter 'error' not described in 'sev_guest_decommission' Warning: include/linux/psp-sev.h:1112 Excess function parameter 'decommission' description in 'sev_guest_decommission' Warning: include/linux/psp-sev.h:1112 Excess function parameter 'sev_ret' description in 'sev_guest_decommission' include/uapi/linux/psp-sev.h: Warning: include/uapi/linux/psp-sev.h:18 This comment starts with '/**', but isn't a kernel-doc comment. * SEV platform commands Warning: include/uapi/linux/psp-sev.h:39 This comment starts with '/**', but isn't a kernel-doc comment. * SEV Firmware status code Warning: include/uapi/linux/psp-sev.h:125 struct member 'api_major' not described in 'sev_user_data_status' Warning: include/uapi/linux/psp-sev.h:125 struct member 'api_minor' not described in 'sev_user_data_status' Warning: include/uapi/linux/psp-sev.h:125 Excess struct member 'major' description in 'sev_user_data_status' (did you mean one of: 'api_major') Warning: include/uapi/linux/psp-sev.h:125 Excess struct member 'minor' description in 'sev_user_data_status' (did you mean one of: 'api_minor') Warning: include/uapi/linux/psp-sev.h:153 expecting prototype for struct sev_user_data_cert_import. Prototype was for struct sev_user_data_pek_cert_import instead Warning: include/uapi/linux/psp-sev.h:168 struct member 'pdh_cert_address' not described in 'sev_user_data_pdh_cert_export' Warning: include/uapi/linux/psp-sev.h:168 struct member 'pdh_cert_len' not described in 'sev_user_data_pdh_cert_export' Warning: include/uapi/linux/psp-sev.h:168 Excess struct member 'pdh_address' description in 'sev_user_data_pdh_cert_export' (did you mean one of: 'pdh_cert_address', 'cert_chain_address') Warning: include/uapi/linux/psp-sev.h:168 Excess struct member 'pdh_len' description in 'sev_user_data_pdh_cert_export' (did you mean one of: 'pdh_cert_len') Warning: include/uapi/linux/psp-sev.h:263 expecting prototype for struct sev_data_snp_vlek_load. Prototype was for struct sev_user_data_snp_vlek_load instead Warning: include/uapi/linux/psp-sev.h:273 expecting prototype for struct sev_user_data_snp_vlek_wrapped_vlek_hashstick. Prototype was for struct sev_user_data_snp_wrapped_vlek_hashstick instead Signed-off-by: Randy Dunlap Acked-by: Tom Lendacky Signed-off-by: Herbert Xu --- include/linux/psp-sev.h | 86 +++++++++++++++++++++++++----------- include/uapi/linux/psp-sev.h | 26 +++++------ 2 files changed, 73 insertions(+), 39 deletions(-) diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index 03a79786df1d..fab62228f981 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -49,7 +49,7 @@ #define SEV_FW_BLOB_MAX_SIZE 0x4000 /* 16KB */ -/** +/* * SEV platform state */ enum sev_state { @@ -60,7 +60,7 @@ enum sev_state { SEV_STATE_MAX }; -/** +/* * SEV platform and guest management commands */ enum sev_cmd { @@ -157,6 +157,7 @@ enum sev_cmd { * struct sev_data_init - INIT command parameters * * @flags: processing flags + * @reserved: reserved * @tmr_address: system physical address used for SEV-ES * @tmr_len: len of tmr_address */ @@ -174,6 +175,7 @@ struct sev_data_init { * @flags: processing flags * @tmr_address: system physical address used for SEV-ES * @tmr_len: len of tmr_address + * @reserved: reserved * @nv_address: system physical address used for PSP NV storage * @nv_len: len of nv_address */ @@ -201,12 +203,13 @@ struct sev_data_pek_csr { } __packed; /** - * struct sev_data_cert_import - PEK_CERT_IMPORT command parameters + * struct sev_data_pek_cert_import - PEK_CERT_IMPORT command parameters * - * @pek_address: PEK certificate chain - * @pek_len: len of PEK certificate - * @oca_address: OCA certificate chain - * @oca_len: len of OCA certificate + * @pek_cert_address: PEK certificate chain + * @pek_cert_len: len of PEK certificate + * @reserved: reserved + * @oca_cert_address: OCA certificate chain + * @oca_cert_len: len of OCA certificate */ struct sev_data_pek_cert_import { u64 pek_cert_address; /* In */ @@ -240,8 +243,9 @@ struct sev_data_get_id { /** * struct sev_data_pdh_cert_export - PDH_CERT_EXPORT command parameters * - * @pdh_address: PDH certificate address - * @pdh_len: len of PDH certificate + * @pdh_cert_address: PDH certificate address + * @pdh_cert_len: len of PDH certificate + * @reserved: reserved * @cert_chain_address: PDH certificate chain * @cert_chain_len: len of PDH certificate chain */ @@ -304,6 +308,7 @@ struct sev_data_guest_status { * @policy: guest launch policy * @dh_cert_address: physical address of DH certificate blob * @dh_cert_len: len of DH certificate blob + * @reserved: reserved * @session_address: physical address of session parameters * @session_len: len of session parameters */ @@ -321,6 +326,7 @@ struct sev_data_launch_start { * struct sev_data_launch_update_data - LAUNCH_UPDATE_DATA command parameter * * @handle: handle of the VM to update + * @reserved: reserved * @len: len of memory to be encrypted * @address: physical address of memory region to encrypt */ @@ -335,6 +341,7 @@ struct sev_data_launch_update_data { * struct sev_data_launch_update_vmsa - LAUNCH_UPDATE_VMSA command * * @handle: handle of the VM + * @reserved: reserved * @address: physical address of memory region to encrypt * @len: len of memory region to encrypt */ @@ -349,6 +356,7 @@ struct sev_data_launch_update_vmsa { * struct sev_data_launch_measure - LAUNCH_MEASURE command parameters * * @handle: handle of the VM to process + * @reserved: reserved * @address: physical address containing the measurement blob * @len: len of measurement blob */ @@ -363,10 +371,13 @@ struct sev_data_launch_measure { * struct sev_data_launch_secret - LAUNCH_SECRET command parameters * * @handle: handle of the VM to process + * @reserved1: reserved * @hdr_address: physical address containing the packet header * @hdr_len: len of packet header + * @reserved2: reserved * @guest_address: system physical address of guest memory region * @guest_len: len of guest_paddr + * @reserved3: reserved * @trans_address: physical address of transport memory buffer * @trans_len: len of transport memory buffer */ @@ -399,10 +410,13 @@ struct sev_data_launch_finish { * @policy: policy information for the VM * @pdh_cert_address: physical address containing PDH certificate * @pdh_cert_len: len of PDH certificate + * @reserved1: reserved * @plat_certs_address: physical address containing platform certificate * @plat_certs_len: len of platform certificate + * @reserved2: reserved * @amd_certs_address: physical address containing AMD certificate * @amd_certs_len: len of AMD certificate + * @reserved3: reserved * @session_address: physical address containing Session data * @session_len: len of session data */ @@ -423,13 +437,16 @@ struct sev_data_send_start { } __packed; /** - * struct sev_data_send_update - SEND_UPDATE_DATA command + * struct sev_data_send_update_data - SEND_UPDATE_DATA command * * @handle: handle of the VM to process + * @reserved1: reserved * @hdr_address: physical address containing packet header * @hdr_len: len of packet header + * @reserved2: reserved * @guest_address: physical address of guest memory region to send * @guest_len: len of guest memory region to send + * @reserved3: reserved * @trans_address: physical address of host memory region * @trans_len: len of host memory region */ @@ -447,13 +464,15 @@ struct sev_data_send_update_data { } __packed; /** - * struct sev_data_send_update - SEND_UPDATE_VMSA command + * struct sev_data_send_update_vmsa - SEND_UPDATE_VMSA command * * @handle: handle of the VM to process * @hdr_address: physical address containing packet header * @hdr_len: len of packet header + * @reserved2: reserved * @guest_address: physical address of guest memory region to send * @guest_len: len of guest memory region to send + * @reserved3: reserved * @trans_address: physical address of host memory region * @trans_len: len of host memory region */ @@ -491,8 +510,10 @@ struct sev_data_send_cancel { * struct sev_data_receive_start - RECEIVE_START command parameters * * @handle: handle of the VM to perform receive operation + * @policy: policy information for the VM * @pdh_cert_address: system physical address containing PDH certificate blob * @pdh_cert_len: len of PDH certificate blob + * @reserved1: reserved * @session_address: system physical address containing session blob * @session_len: len of session blob */ @@ -510,10 +531,13 @@ struct sev_data_receive_start { * struct sev_data_receive_update_data - RECEIVE_UPDATE_DATA command parameters * * @handle: handle of the VM to update + * @reserved1: reserved * @hdr_address: physical address containing packet header blob * @hdr_len: len of packet header + * @reserved2: reserved * @guest_address: system physical address of guest memory region * @guest_len: len of guest memory region + * @reserved3: reserved * @trans_address: system physical address of transport buffer * @trans_len: len of transport buffer */ @@ -534,10 +558,13 @@ struct sev_data_receive_update_data { * struct sev_data_receive_update_vmsa - RECEIVE_UPDATE_VMSA command parameters * * @handle: handle of the VM to update + * @reserved1: reserved * @hdr_address: physical address containing packet header blob * @hdr_len: len of packet header + * @reserved2: reserved * @guest_address: system physical address of guest memory region * @guest_len: len of guest memory region + * @reserved3: reserved * @trans_address: system physical address of transport buffer * @trans_len: len of transport buffer */ @@ -567,6 +594,7 @@ struct sev_data_receive_finish { * struct sev_data_dbg - DBG_ENCRYPT/DBG_DECRYPT command parameters * * @handle: handle of the VM to perform debug operation + * @reserved: reserved * @src_addr: source address of data to operate on * @dst_addr: destination address of data to operate on * @len: len of data to operate on @@ -583,6 +611,7 @@ struct sev_data_dbg { * struct sev_data_attestation_report - SEV_ATTESTATION_REPORT command parameters * * @handle: handle of the VM + * @reserved: reserved * @mnonce: a random nonce that will be included in the report. * @address: physical address where the report will be copied. * @len: length of the physical buffer. @@ -781,9 +810,14 @@ struct sev_data_snp_guest_request { * * @init_rmp: indicate that the RMP should be initialized. * @list_paddr_en: indicate that list_paddr is valid + * @rapl_dis: whether RAPL is disabled + * @ciphertext_hiding_en: whether ciphertext hiding is enabled + * @tio_en: Indicates that SNP_INIT_EX initialized the RMP for SEV-TIO * @rsvd: reserved * @rsvd1: reserved * @list_paddr: system physical address of range list + * @max_snp_asid: When non-zero, enable ciphertext hiding and specify the + * maximum ASID that can be used for an SEV-SNP guest. * @rsvd2: reserved */ struct sev_data_snp_init_ex { @@ -841,7 +875,7 @@ struct sev_data_snp_shutdown_ex { } __packed; /** - * struct sev_platform_init_args + * struct sev_platform_init_args - parameters for sev_platform_init() * * @error: SEV firmware error code * @probe: True if this is being called as part of CCP module probe, which @@ -879,12 +913,12 @@ struct sev_data_snp_feature_info { } __packed; /** - * struct feature_info - FEATURE_INFO structure + * struct snp_feature_info - FEATURE_INFO structure * * @eax: output of SNP_FEATURE_INFO command * @ebx: output of SNP_FEATURE_INFO command * @ecx: output of SNP_FEATURE_INFO command - * #edx: output of SNP_FEATURE_INFO command + * @edx: output of SNP_FEATURE_INFO command */ struct snp_feature_info { u32 eax; @@ -954,7 +988,7 @@ struct sev_data_snp_verify_mitigation_dst { } __packed; /** - * struct sev_snp_tcb_version_genoa_milan + * struct sev_snp_tcb_version_genoa_milan - v1 SVN payload * * @boot_loader: SVN of PSP bootloader * @tee: SVN of PSP operating system @@ -971,7 +1005,7 @@ struct sev_snp_tcb_version_genoa_milan { }; /** - * struct sev_snp_tcb_version_turin + * struct sev_snp_tcb_version_turin - v2 SVN payload * * @fmc: SVN of FMC firmware * @boot_loader: SVN of PSP bootloader @@ -1037,9 +1071,9 @@ int sev_platform_status(struct sev_user_data_status *status, int *error); * behalf of userspace. The caller must pass a valid SEV file descriptor * so that we know that it has access to SEV device. * - * @filep - SEV device file pointer - * @cmd - command to issue - * @data - command buffer + * @filep: SEV device file pointer + * @id: command to issue + * @data: command buffer * @error: SEV command return code * * Returns: @@ -1056,8 +1090,8 @@ int sev_issue_cmd_external_user(struct file *filep, unsigned int id, /** * sev_guest_deactivate - perform SEV DEACTIVATE command * - * @deactivate: sev_data_deactivate structure to be processed - * @sev_ret: sev command return code + * @data: sev_data_deactivate structure to be processed + * @error: sev command return code * * Returns: * 0 if the sev successfully processed the command @@ -1071,8 +1105,8 @@ int sev_guest_deactivate(struct sev_data_deactivate *data, int *error); /** * sev_guest_activate - perform SEV ACTIVATE command * - * @activate: sev_data_activate structure to be processed - * @sev_ret: sev command return code + * @data: sev_data_activate structure to be processed + * @error: sev command return code * * Returns: * 0 if the sev successfully processed the command @@ -1086,7 +1120,7 @@ int sev_guest_activate(struct sev_data_activate *data, int *error); /** * sev_guest_df_flush - perform SEV DF_FLUSH command * - * @sev_ret: sev command return code + * @error: sev command return code * * Returns: * 0 if the sev successfully processed the command @@ -1100,8 +1134,8 @@ int sev_guest_df_flush(int *error); /** * sev_guest_decommission - perform SEV DECOMMISSION command * - * @decommission: sev_data_decommission structure to be processed - * @sev_ret: sev command return code + * @data: sev_data_decommission structure to be processed + * @error: sev command return code * * Returns: * 0 if the sev successfully processed the command diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h index 52dae70b058b..536626abe6db 100644 --- a/include/uapi/linux/psp-sev.h +++ b/include/uapi/linux/psp-sev.h @@ -15,7 +15,7 @@ #include -/** +/* * SEV platform commands */ enum { @@ -36,7 +36,7 @@ enum { SEV_MAX, }; -/** +/* * SEV Firmware status code */ typedef enum { @@ -109,8 +109,8 @@ typedef enum { /** * struct sev_user_data_status - PLATFORM_STATUS command parameters * - * @major: major API version - * @minor: minor API version + * @api_major: major API version + * @api_minor: minor API version * @state: platform state * @flags: platform config flags * @build: firmware build id for API version @@ -139,12 +139,12 @@ struct sev_user_data_pek_csr { } __packed; /** - * struct sev_user_data_cert_import - PEK_CERT_IMPORT command parameters + * struct sev_user_data_pek_cert_import - PEK_CERT_IMPORT command parameters * - * @pek_address: PEK certificate chain - * @pek_len: length of PEK certificate - * @oca_address: OCA certificate chain - * @oca_len: length of OCA certificate + * @pek_cert_address: PEK certificate chain + * @pek_cert_len: length of PEK certificate + * @oca_cert_address: OCA certificate chain + * @oca_cert_len: length of OCA certificate */ struct sev_user_data_pek_cert_import { __u64 pek_cert_address; /* In */ @@ -156,8 +156,8 @@ struct sev_user_data_pek_cert_import { /** * struct sev_user_data_pdh_cert_export - PDH_CERT_EXPORT command parameters * - * @pdh_address: PDH certificate address - * @pdh_len: length of PDH certificate + * @pdh_cert_address: PDH certificate address + * @pdh_cert_len: length of PDH certificate * @cert_chain_address: PDH certificate chain * @cert_chain_len: length of PDH certificate chain */ @@ -248,7 +248,7 @@ struct sev_user_data_snp_config { } __packed; /** - * struct sev_data_snp_vlek_load - SNP_VLEK_LOAD structure + * struct sev_user_data_snp_vlek_load - SNP_VLEK_LOAD structure * * @len: length of the command buffer read by the PSP * @vlek_wrapped_version: version of wrapped VLEK hashstick (Must be 0h) @@ -264,7 +264,7 @@ struct sev_user_data_snp_vlek_load { } __packed; /** - * struct sev_user_data_snp_vlek_wrapped_vlek_hashstick - Wrapped VLEK data + * struct sev_user_data_snp_wrapped_vlek_hashstick - Wrapped VLEK data * * @data: Opaque data provided by AMD KDS (as described in SEV-SNP Firmware ABI * 1.54, SNP_VLEK_LOAD) From 5d504e65516dde8c88117378292e9c78f3d2cf58 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 19 Sep 2026 07:49:34 +0200 Subject: [PATCH 091/146] crypto: qat - zero the VF migration state buffer on save The QAT VF migration state buffer is allocated with kmalloc(), while qat_vf_save_state() exposes all state_size bytes to userspace. The state manager writes only the serialized sections, leaving the unused tail unchanged. The first save can therefore disclose stale heap contents, and subsequent saves can disclose data left by an earlier migration. Zero the whole buffer before writing the setup data. Once the setup data is present, preserve it and zero the remaining state area before each state save. Fixes: f0bbfc391aa7 ("crypto: qat - implement interface for live migration") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-fable-5 Signed-off-by: Karl Mehltretter Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_gen4_vf_mig.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_vf_mig.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_vf_mig.c index bf2bae78a40d..d8b961b2f2f7 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen4_vf_mig.c +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_vf_mig.c @@ -837,6 +837,9 @@ static int adf_gen4_vfmig_save_state(struct qat_mig_dev *mdev) return ret; } + memset(mdev->state + mdev->setup_size, 0, + mdev->state_size - mdev->setup_size); + adf_mstate_mgr_init(vfmig->mstate_mgr, mdev->state + mdev->setup_size, mdev->state_size - mdev->setup_size); if (!adf_mstate_preamble_add(vfmig->mstate_mgr)) @@ -934,6 +937,8 @@ static int adf_gen4_vfmig_save_setup(struct qat_mig_dev *mdev) if (mdev->setup_size) return 0; + memset(mdev->state, 0, mdev->state_size); + adf_mstate_mgr_init(vfmig->mstate_mgr, mdev->state, mdev->state_size); if (!adf_mstate_preamble_add(vfmig->mstate_mgr)) return -EINVAL; From de4929b47683ed22d8c05f68d2d0f0cfd95b90a1 Mon Sep 17 00:00:00 2001 From: Muhammad Bilal Date: Sun, 20 Sep 2026 00:24:32 +0500 Subject: [PATCH 092/146] crypto: ccp - fix SFS ioctl race against device teardown sfs_ioctl() reads psp_master->sfs_data and caches it in sfs_dev before taking sfs_ioctl_mutex, while sfs_dev_destroy() frees sfs_dev->page and sfs_dev->command_buf with no locking at all and only clears psp->sfs_data afterwards. A call to sfs_ioctl() that reads sfs_data just before sfs_dev_destroy() runs will still acquire the mutex and go on to use the now-freed command buffer in send_sfs_cmd(). Have both functions take sfs_ioctl_mutex before touching psp->sfs_data, so a call that is already using sfs_dev completes before teardown can free it, and a call arriving after teardown sees sfs_data cleared and returns -ENODEV instead of racing it. Fixes: 648dbccc03a0 ("crypto: ccp - Add AMD Seamless Firmware Servicing (SFS) driver") Signed-off-by: Muhammad Bilal Reviewed-by: Ashish Kalra Reviewed-by: Thomas Huth Signed-off-by: Herbert Xu --- drivers/crypto/ccp/sfs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/ccp/sfs.c b/drivers/crypto/ccp/sfs.c index a4777839790b..530141f8bc74 100644 --- a/drivers/crypto/ccp/sfs.c +++ b/drivers/crypto/ccp/sfs.c @@ -111,13 +111,13 @@ static long sfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct sfs_device *sfs_dev; int ret = 0; + guard(mutex)(&sfs_ioctl_mutex); + if (!psp_master || !psp_master->sfs_data) return -ENODEV; sfs_dev = psp_master->sfs_data; - guard(mutex)(&sfs_ioctl_mutex); - switch (cmd) { case SFSIOCFWVERS: dev_dbg(sfs_dev->dev, "in SFSIOCFWVERS\n"); @@ -191,8 +191,11 @@ static void sfs_exit(struct kref *ref) void sfs_dev_destroy(struct psp_device *psp) { - struct sfs_device *sfs_dev = psp->sfs_data; + struct sfs_device *sfs_dev; + guard(mutex)(&sfs_ioctl_mutex); + + sfs_dev = psp->sfs_data; if (!sfs_dev) return; From b72a639bdee6e07d8091718ac3e451d9c5cba1b5 Mon Sep 17 00:00:00 2001 From: Jiale Yao Date: Mon, 21 Sep 2026 01:34:07 +0800 Subject: [PATCH 093/146] crypto: ccp - kill v3 IRQ tasklet during teardown On PCI devices using MSI-X, ccp_irq_handler() schedules irq_tasklet. The teardown paths release the IRQ but do not drain a tasklet that was already queued, so it can access ccp after the device-managed allocation has been released. Kill the tasklet after releasing the IRQ in both the initialization error path and ccp_destroy(). Fixes: 7b537b24e76a ("crypto: ccp - Change ISR handler method for a v3 CCP") Signed-off-by: Jiale Yao Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev-v3.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c index 60a133e23e5f..d92de4ad31ac 100644 --- a/drivers/crypto/ccp/ccp-dev-v3.c +++ b/drivers/crypto/ccp/ccp-dev-v3.c @@ -506,6 +506,8 @@ e_kthread: kthread_stop(ccp->cmd_q[i].kthread); sp_free_ccp_irq(ccp->sp, ccp); + if (ccp->use_tasklet) + tasklet_kill(&ccp->irq_tasklet); e_pool: for (i = 0; i < ccp->cmd_q_count; i++) @@ -545,6 +547,8 @@ static void ccp_destroy(struct ccp_device *ccp) kthread_stop(ccp->cmd_q[i].kthread); sp_free_ccp_irq(ccp->sp, ccp); + if (ccp->use_tasklet) + tasklet_kill(&ccp->irq_tasklet); for (i = 0; i < ccp->cmd_q_count; i++) dma_pool_destroy(ccp->cmd_q[i].dma_pool); From 67aefeccc4101a93627f36abbd049f191b54f903 Mon Sep 17 00:00:00 2001 From: Jiale Yao Date: Mon, 21 Sep 2026 01:34:17 +0800 Subject: [PATCH 094/146] crypto: ccp - kill v5 IRQ tasklet during teardown On PCI devices using MSI-X, ccp5_irq_handler() schedules irq_tasklet. The teardown paths release the IRQ but do not drain a tasklet that was already queued, so it can access ccp after the device-managed allocation has been released. Kill the tasklet after releasing the IRQ in both the initialization error path and ccp5_destroy(). Fixes: 6263b51eb319 ("crypto: ccp - Change ISR handler method for a v5 CCP") Signed-off-by: Jiale Yao Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-dev-v5.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index dcd6aab51e47..dacde9614e8a 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -995,6 +995,8 @@ e_kthread: e_irq: sp_free_ccp_irq(ccp->sp, ccp); + if (ccp->use_tasklet) + tasklet_kill(&ccp->irq_tasklet); e_pool: for (i = 0; i < ccp->cmd_q_count; i++) @@ -1046,6 +1048,8 @@ static void ccp5_destroy(struct ccp_device *ccp) kthread_stop(ccp->cmd_q[i].kthread); sp_free_ccp_irq(ccp->sp, ccp); + if (ccp->use_tasklet) + tasklet_kill(&ccp->irq_tasklet); /* Flush the cmd and backlog queue */ while (!list_empty(&ccp->cmd)) { From dfcaf2d961f236b3680c417802523375e14f204b Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 21 Sep 2026 08:11:20 +0200 Subject: [PATCH 095/146] crypto: cast5 - use memcpy_and_pad() in cast5_setkey() Use memcpy_and_pad() instead of separate memcpy() and memset() calls to simplify cast5_setkey(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- crypto/cast5_generic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crypto/cast5_generic.c b/crypto/cast5_generic.c index f68330793e0c..1de0dc966a03 100644 --- a/crypto/cast5_generic.c +++ b/crypto/cast5_generic.c @@ -483,9 +483,7 @@ int cast5_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len) c->rr = key_len <= 10 ? 1 : 0; - memset(p_key, 0, 16); - memcpy(p_key, key, key_len); - + memcpy_and_pad(p_key, sizeof(p_key), key, key_len, 0); x[0] = be32_to_cpu(p_key[0]); x[1] = be32_to_cpu(p_key[1]); From 1dfb15e6420b023b3ed479563c818d2e75203067 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 21 Sep 2026 08:11:21 +0200 Subject: [PATCH 096/146] crypto: cast6 - use memcpy_and_pad() in __cast6_setkey() Use memcpy_and_pad() instead of separate memcpy() and memset() calls to simplify __cast6_setkey(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- crypto/cast6_generic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crypto/cast6_generic.c b/crypto/cast6_generic.c index 4c08c42646f0..9b6bdd2aa511 100644 --- a/crypto/cast6_generic.c +++ b/crypto/cast6_generic.c @@ -112,8 +112,7 @@ int __cast6_setkey(struct cast6_ctx *c, const u8 *in_key, unsigned int key_len) if (key_len % 4 != 0) return -EINVAL; - memset(p_key, 0, 32); - memcpy(p_key, in_key, key_len); + memcpy_and_pad(p_key, sizeof(p_key), in_key, key_len, 0); key[0] = be32_to_cpu(p_key[0]); /* A */ key[1] = be32_to_cpu(p_key[1]); /* B */ From d76957328ade91af38ac88fb51f127cd78cbf62b Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 21 Sep 2026 08:11:22 +0200 Subject: [PATCH 097/146] crypto: ixp4xx - use memcpy_and_pad() in register_chain_var() Use memcpy_and_pad() instead of separate memcpy() and memset() calls to simplify register_chain_var(). Signed-off-by: Thorsten Blum Reviewed-by: Linus Walleij Signed-off-by: Herbert Xu --- drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c index fdda04672454..33e8e887a415 100644 --- a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c +++ b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c @@ -707,8 +707,7 @@ static int register_chain_var(struct crypto_tfm *tfm, u8 xpad, u32 target, return -EAGAIN; } - memcpy(pad, key, key_len); - memset(pad + key_len, 0, HMAC_PAD_BLOCKLEN - key_len); + memcpy_and_pad(pad, HMAC_PAD_BLOCKLEN, key, key_len, 0); for (i = 0; i < HMAC_PAD_BLOCKLEN; i++) pad[i] ^= xpad; From 377b26bedab11294aa4cc826dc8abaa5932d560f Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 21 Sep 2026 08:11:23 +0200 Subject: [PATCH 098/146] crypto: octeontx - use memcpy_and_pad() in aead_hmac_init() Use memcpy_and_pad() instead of separate memcpy() and memset() calls to simplify aead_hmac_init(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/marvell/octeontx/otx_cptvf_algs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c b/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c index 70befbdd442b..2f088afc536d 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c +++ b/drivers/crypto/marvell/octeontx/otx_cptvf_algs.c @@ -793,8 +793,7 @@ static int aead_hmac_init(struct crypto_aead *cipher, ipad = ctx->ipad; opad = ctx->opad; - memcpy(ipad, ctx->key, authkeylen); - memset(ipad + authkeylen, 0, bs - authkeylen); + memcpy_and_pad(ipad, bs, ctx->key, authkeylen, 0); memcpy(opad, ipad, bs); for (icount = 0; icount < bs; icount++) { From 404aac318dceb271c02577f3b5fc4f3788742ae5 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 21 Sep 2026 08:11:24 +0200 Subject: [PATCH 099/146] crypto: octeontx2 - use memcpy_and_pad() in aead_hmac_init() Use memcpy_and_pad() instead of separate memcpy() and memset() calls to simplify aead_hmac_init(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c index 3ccf17d031c6..9eb5dc0a4da6 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c @@ -883,8 +883,7 @@ static int aead_hmac_init(struct crypto_aead *cipher, ipad = ctx->ipad; opad = ctx->opad; - memcpy(ipad, ctx->key, authkeylen); - memset(ipad + authkeylen, 0, bs - authkeylen); + memcpy_and_pad(ipad, bs, ctx->key, authkeylen, 0); memcpy(opad, ipad, bs); for (icount = 0; icount < bs; icount++) { From e13aea2afbf6997f3b80df357d347e4089fb2e4c Mon Sep 17 00:00:00 2001 From: bui duc phuc Date: Tue, 22 Sep 2026 10:19:52 +0700 Subject: [PATCH 100/146] crypto: sun8i-ss - Use pm_runtime_resume_and_get() Replace the open-coded pm_runtime_get_sync() + pm_runtime_put_noidle() error handling pattern with pm_runtime_resume_and_get(), which already does this internally. No functional change. Found by manual code inspection. Signed-off-by: bui duc phuc Signed-off-by: Herbert Xu --- drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c index 36a1ebca2e70..56ba4ff6d5ff 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c @@ -120,12 +120,11 @@ int sun8i_ss_hash_init_tfm(struct crypto_ahash *tfm) memcpy(algt->fbname, crypto_ahash_driver_name(op->fallback_tfm), CRYPTO_MAX_ALG_NAME); - err = pm_runtime_get_sync(op->ss->dev); + err = pm_runtime_resume_and_get(op->ss->dev); if (err < 0) goto error_pm; return 0; error_pm: - pm_runtime_put_noidle(op->ss->dev); crypto_free_ahash(op->fallback_tfm); return err; } From 073e9ea3beb02411c1c492de31a4fbe5af47969b Mon Sep 17 00:00:00 2001 From: bui duc phuc Date: Tue, 22 Sep 2026 10:19:53 +0700 Subject: [PATCH 101/146] crypto: ccree - Use pm_runtime_resume_and_get() Replace the open-coded pm_runtime_get_sync() + pm_runtime_put_noidle() error handling pattern with pm_runtime_resume_and_get(), which already does this internally. No functional change. Found by manual code inspection. Signed-off-by: bui duc phuc Signed-off-by: Herbert Xu --- drivers/crypto/ccree/cc_pm.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/crypto/ccree/cc_pm.c b/drivers/crypto/ccree/cc_pm.c index bbd118f8de0e..666866119588 100644 --- a/drivers/crypto/ccree/cc_pm.c +++ b/drivers/crypto/ccree/cc_pm.c @@ -66,13 +66,7 @@ const struct dev_pm_ops ccree_pm = { int cc_pm_get(struct device *dev) { - int rc = pm_runtime_get_sync(dev); - if (rc < 0) { - pm_runtime_put_noidle(dev); - return rc; - } - - return 0; + return pm_runtime_resume_and_get(dev); } void cc_pm_put_suspend(struct device *dev) From 627934a5d280c84c51a9dc5ff602324fb63a773a Mon Sep 17 00:00:00 2001 From: bui duc phuc Date: Tue, 22 Sep 2026 10:19:54 +0700 Subject: [PATCH 102/146] crypto: sl3516 - Use pm_runtime_resume_and_get() Replace the open-coded pm_runtime_get_sync() + pm_runtime_put_noidle() error handling pattern with pm_runtime_resume_and_get(), which already does this internally. No functional change. Found by manual code inspection. Signed-off-by: bui duc phuc Reviewed-by: Linus Walleij Signed-off-by: Herbert Xu --- drivers/crypto/gemini/sl3516-ce-cipher.c | 3 +-- drivers/crypto/gemini/sl3516-ce-rng.c | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/gemini/sl3516-ce-cipher.c b/drivers/crypto/gemini/sl3516-ce-cipher.c index 02ec4282333b..eba46aebf176 100644 --- a/drivers/crypto/gemini/sl3516-ce-cipher.c +++ b/drivers/crypto/gemini/sl3516-ce-cipher.c @@ -331,13 +331,12 @@ int sl3516_ce_cipher_init(struct crypto_tfm *tfm) crypto_tfm_alg_driver_name(&sktfm->base), crypto_tfm_alg_driver_name(crypto_skcipher_tfm(op->fallback_tfm))); - err = pm_runtime_get_sync(op->ce->dev); + err = pm_runtime_resume_and_get(op->ce->dev); if (err < 0) goto error_pm; return 0; error_pm: - pm_runtime_put_noidle(op->ce->dev); crypto_free_skcipher(op->fallback_tfm); return err; } diff --git a/drivers/crypto/gemini/sl3516-ce-rng.c b/drivers/crypto/gemini/sl3516-ce-rng.c index 76931ec1cec5..19af03b03e42 100644 --- a/drivers/crypto/gemini/sl3516-ce-rng.c +++ b/drivers/crypto/gemini/sl3516-ce-rng.c @@ -24,11 +24,9 @@ static int sl3516_ce_rng_read(struct hwrng *rng, void *buf, size_t max, bool wai ce->hwrng_stat_bytes += max; #endif - err = pm_runtime_get_sync(ce->dev); - if (err < 0) { - pm_runtime_put_noidle(ce->dev); + err = pm_runtime_resume_and_get(ce->dev); + if (err < 0) return err; - } while (read < max) { *data = readl(ce->base + IPSEC_RAND_NUM_REG); From edf73c9922672ff94ca12162829ea178685430fd Mon Sep 17 00:00:00 2001 From: bui duc phuc Date: Tue, 22 Sep 2026 10:20:54 +0700 Subject: [PATCH 103/146] hwrng: omap3-rom - Use pm_runtime_resume_and_get() Replace the open-coded pm_runtime_get_sync() + pm_runtime_put_noidle() error handling pattern with pm_runtime_resume_and_get(), which already does this internally. No functional change. Found by manual code inspection. Signed-off-by: bui duc phuc Signed-off-by: Herbert Xu --- drivers/char/hw_random/omap3-rom-rng.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/char/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c index aa71f61c3dc9..0797add0d782 100644 --- a/drivers/char/hw_random/omap3-rom-rng.c +++ b/drivers/char/hw_random/omap3-rom-rng.c @@ -42,12 +42,9 @@ static int omap3_rom_rng_read(struct hwrng *rng, void *data, size_t max, bool w) ddata = (struct omap_rom_rng *)rng->priv; - r = pm_runtime_get_sync(ddata->dev); - if (r < 0) { - pm_runtime_put_noidle(ddata->dev); - + r = pm_runtime_resume_and_get(ddata->dev); + if (r < 0) return r; - } ptr = virt_to_phys(data); r = ddata->rom_rng_call(ptr, 4, RNG_GEN_HW); From ccbd95b3efbc0580b6abde2a905823417ca56022 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Tue, 22 Sep 2026 07:17:04 +0200 Subject: [PATCH 104/146] crypto: atmel - handle authenc requests without plaintext Authenc permits a nonempty associated-data string with no plaintext. The Atmel driver accepts such a request, has SHA process the associated data, and then unconditionally asks AES DMA to transfer zero bytes. The Atmel DMA engines reject the zero-length descriptor, so the valid request fails, normally with -ENOMEM. Skip the AES transfer when textlen is zero and proceed directly to SHA finalization. Once an HMAC transform has cached its inner and outer states, SHA can complete this path synchronously. The forced ahash completion callback then invokes the AES finalizer through a void function and discards its return value. This loses -EBADMSG for a mismatched tag and reports successful decryption. For synchronous SHA completion, release the SHA device without invoking the ahash callback and call the AES finalizer directly. Its result then propagates through the synchronous call chain. Keep the existing callback path for asynchronous completion. On a SAM9X75, the unpatched driver failed valid AAD-only requests and returned success for a bad tag after the transform had been used once. With this change, bad tags return -EBADMSG for both fresh and reused transforms. Fixes: 89a82ef87e01 ("crypto: atmel-authenc - add support to authenc(hmac(shaX), Y(aes)) modes") Assisted-by: LLM Signed-off-by: Karl Mehltretter Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes.c | 2 ++ drivers/crypto/atmel-sha.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 8e4de859cadc..84392411b98d 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -1826,6 +1826,8 @@ static int atmel_aes_authenc_transfer(struct atmel_aes_dev *dd, int err, dd->is_async = true; if (err) return atmel_aes_complete(dd, err); + if (!rctx->textlen) + return atmel_aes_authenc_digest(dd); /* Prepare src and dst scatter-lists to transfer cipher/plain texts. */ src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen); diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 2d70a4107693..4b883a8dcf30 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -2386,11 +2386,25 @@ static int atmel_sha_authenc_final_done(struct atmel_sha_dev *dd) { struct ahash_request *req = dd->req; struct atmel_sha_authenc_reqctx *authctx = ahash_request_ctx(req); + atmel_aes_authenc_fn_t cb; + struct atmel_aes_dev *aes_dev; size_t i, num_words = authctx->digestlen / sizeof(u32); for (i = 0; i < num_words; ++i) authctx->digest[i] = atmel_sha_read(dd, SHA_REG_DIGEST(i)); + if (!dd->is_async) { + /* + * Return the AES finalizer's status directly for synchronous requests. + * The ahash callback cannot propagate it. + */ + cb = authctx->cb; + aes_dev = authctx->aes_dev; + dd->force_complete = false; + (void)atmel_sha_complete(dd, 0); + return cb(aes_dev, 0, false); + } + return atmel_sha_complete(dd, 0); } From 3a31a4baad6726bf974bcc58a6398f6a36d10aa0 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 22 Sep 2026 19:49:18 +1000 Subject: [PATCH 105/146] crypto: tcrypt - Avoid reading req->base after submission Once a request has been submitted to the Crypto API, the value of req->base.data must not be read by the caller as it may change while the request is processed. Avoid reading it in tcrypt by combining the crypto_wait struct with the request object into a tcrypt request object and pass that around instead of the request object. Reported-by: T Pratham Fixes: beb63da739f7 ("crypto: tcrypt - Add speed tests for async hashing") Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 182 +++++++++++++++++++++++++++--------------------- 1 file changed, 101 insertions(+), 81 deletions(-) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 61a2501bfe9b..e6834bdde9b9 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -56,6 +56,21 @@ */ #define get_driver_name(tfm_type, tfm) crypto_tfm_alg_driver_name(tfm_type ## _tfm(tfm)) +struct tcrypt_aead_request { + struct aead_request *req; + struct crypto_wait wait; +}; + +struct tcrypt_ahash_request { + struct ahash_request *req; + struct crypto_wait wait; +}; + +struct tcrypt_skcipher_request { + struct skcipher_request *req; + struct crypto_wait wait; +}; + /* * Used by test_cipher_speed() */ @@ -129,18 +144,15 @@ static void sg_init_aead(struct scatterlist *sg, char *xbuf[XBUFSIZE], sg_set_buf(&sg[k + 1], xbuf[k], rem); } -static inline int do_one_aead_op(struct aead_request *req, int ret) +static inline int do_one_aead_op(struct tcrypt_aead_request *req, int ret) { - struct crypto_wait *wait = req->base.data; - - return crypto_wait_req(ret, wait); + return crypto_wait_req(ret, &req->wait); } struct test_mb_aead_data { struct scatterlist sg[XBUFSIZE]; struct scatterlist sgout[XBUFSIZE]; - struct aead_request *req; - struct crypto_wait wait; + struct tcrypt_aead_request req; char *xbuf[XBUFSIZE]; char *xoutbuf[XBUFSIZE]; char *axbuf[XBUFSIZE]; @@ -154,14 +166,14 @@ static int do_mult_aead_op(struct test_mb_aead_data *data, int enc, /* Fire up a bunch of concurrent requests */ for (i = 0; i < num_mb; i++) { if (enc == ENCRYPT) - rc[i] = crypto_aead_encrypt(data[i].req); + rc[i] = crypto_aead_encrypt(data[i].req.req); else - rc[i] = crypto_aead_decrypt(data[i].req); + rc[i] = crypto_aead_decrypt(data[i].req.req); } /* Wait for all requests to finish */ for (i = 0; i < num_mb; i++) { - rc[i] = crypto_wait_req(rc[i], &data[i].wait); + rc[i] = crypto_wait_req(rc[i], &data[i].req.wait); if (rc[i]) { pr_info("concurrent request %d error %d\n", i, rc[i]); @@ -310,21 +322,21 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs, } for (i = 0; i < num_mb; ++i) { - data[i].req = aead_request_alloc(tfm, GFP_KERNEL); - if (!data[i].req) { + data[i].req.req = aead_request_alloc(tfm, GFP_KERNEL); + if (!data[i].req.req) { pr_err("alg: aead: Failed to allocate request for %s\n", algo); while (i--) - aead_request_free(data[i].req); + aead_request_free(data[i].req.req); goto out_free_xoutbuf; } } for (i = 0; i < num_mb; ++i) { - crypto_init_wait(&data[i].wait); - aead_request_set_callback(data[i].req, + crypto_init_wait(&data[i].req.wait); + aead_request_set_callback(data[i].req.req, CRYPTO_TFM_REQ_MAY_BACKLOG, - crypto_req_done, &data[i].wait); + crypto_req_done, &data[i].req.wait); } pr_info("testing speed of multibuffer %s (%s) %s\n", algo, @@ -386,16 +398,16 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs, bs + (enc ? authsize : 0), assoc, aad_size); - aead_request_set_ad(cur->req, aad_size); + aead_request_set_ad(cur->req.req, aad_size); if (!enc) { - aead_request_set_crypt(cur->req, + aead_request_set_crypt(cur->req.req, cur->sgout, cur->sg, bs, iv); - ret = crypto_aead_encrypt(cur->req); - ret = do_one_aead_op(cur->req, ret); + ret = crypto_aead_encrypt(cur->req.req); + ret = do_one_aead_op(&cur->req, ret); if (ret) { pr_err("calculating auth failed (%d)\n", @@ -404,7 +416,7 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs, } } - aead_request_set_crypt(cur->req, cur->sg, + aead_request_set_crypt(cur->req.req, cur->sg, cur->sgout, bs + (enc ? 0 : authsize), iv); @@ -432,7 +444,7 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs, out: for (i = 0; i < num_mb; ++i) - aead_request_free(data[i].req); + aead_request_free(data[i].req.req); out_free_xoutbuf: for (i = 0; i < num_mb; ++i) testmgr_free_buf(data[i].xoutbuf); @@ -450,9 +462,10 @@ out_free_iv: kfree(iv); } -static int test_aead_jiffies(struct aead_request *req, int enc, +static int test_aead_jiffies(struct tcrypt_aead_request *treq, int enc, int blen, int secs) { + struct aead_request *req = treq->req; unsigned long start, end; int bcount; int ret; @@ -460,9 +473,9 @@ static int test_aead_jiffies(struct aead_request *req, int enc, for (start = jiffies, end = start + secs * HZ, bcount = 0; time_before(jiffies, end); bcount++) { if (enc) - ret = do_one_aead_op(req, crypto_aead_encrypt(req)); + ret = do_one_aead_op(treq, crypto_aead_encrypt(req)); else - ret = do_one_aead_op(req, crypto_aead_decrypt(req)); + ret = do_one_aead_op(treq, crypto_aead_decrypt(req)); if (ret) return ret; @@ -473,8 +486,9 @@ static int test_aead_jiffies(struct aead_request *req, int enc, return 0; } -static int test_aead_cycles(struct aead_request *req, int enc, int blen) +static int test_aead_cycles(struct tcrypt_aead_request *treq, int enc, int blen) { + struct aead_request *req = treq->req; unsigned long cycles = 0; int ret = 0; int i; @@ -482,9 +496,9 @@ static int test_aead_cycles(struct aead_request *req, int enc, int blen) /* Warm-up run. */ for (i = 0; i < 4; i++) { if (enc) - ret = do_one_aead_op(req, crypto_aead_encrypt(req)); + ret = do_one_aead_op(treq, crypto_aead_encrypt(req)); else - ret = do_one_aead_op(req, crypto_aead_decrypt(req)); + ret = do_one_aead_op(treq, crypto_aead_decrypt(req)); if (ret) goto out; @@ -496,9 +510,9 @@ static int test_aead_cycles(struct aead_request *req, int enc, int blen) start = get_cycles(); if (enc) - ret = do_one_aead_op(req, crypto_aead_encrypt(req)); + ret = do_one_aead_op(treq, crypto_aead_encrypt(req)); else - ret = do_one_aead_op(req, crypto_aead_decrypt(req)); + ret = do_one_aead_op(treq, crypto_aead_decrypt(req)); end = get_cycles(); if (ret) @@ -520,6 +534,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, unsigned int tcount, u8 authsize, unsigned int aad_size, u8 *keysize) { + struct tcrypt_aead_request treq; unsigned int i, j; struct crypto_aead *tfm; int ret = -ENOMEM; @@ -535,7 +550,6 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, char *axbuf[XBUFSIZE]; const int *b_size; unsigned int iv_len; - struct crypto_wait wait; iv = kzalloc(MAX_IVLEN, GFP_KERNEL); if (!iv) @@ -577,7 +591,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, goto out_noreq; } - crypto_init_wait(&wait); + crypto_init_wait(&treq.wait); pr_info("testing speed of %s (%s) %s\n", algo, get_driver_name(crypto_aead, tfm), e); @@ -587,9 +601,10 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, algo); goto out_noreq; } + treq.req = req; aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - crypto_req_done, &wait); + crypto_req_done, &treq.wait); i = 0; do { @@ -650,7 +665,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, */ aead_request_set_crypt(req, sgout, sg, bs, iv); - ret = do_one_aead_op(req, + ret = do_one_aead_op(&treq, crypto_aead_encrypt(req)); if (ret) { @@ -665,11 +680,11 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, iv); if (secs) { - ret = test_aead_jiffies(req, enc, bs, + ret = test_aead_jiffies(&treq, enc, bs, secs); cond_resched(); } else { - ret = test_aead_cycles(req, enc, bs); + ret = test_aead_cycles(&treq, enc, bs); } if (ret) { @@ -709,23 +724,22 @@ static void test_hash_sg_init(struct scatterlist *sg) } } -static inline int do_one_ahash_op(struct ahash_request *req, int ret) +static inline int do_one_ahash_op(struct tcrypt_ahash_request *treq, int ret) { - struct crypto_wait *wait = req->base.data; - - return crypto_wait_req(ret, wait); + return crypto_wait_req(ret, &treq->wait); } -static int test_ahash_jiffies_digest(struct ahash_request *req, int blen, - char *out, int secs) +static int test_ahash_jiffies_digest(struct tcrypt_ahash_request *treq, + int blen, char *out, int secs) { + struct ahash_request *req = treq->req; unsigned long start, end; int bcount; int ret; for (start = jiffies, end = start + secs * HZ, bcount = 0; time_before(jiffies, end); bcount++) { - ret = do_one_ahash_op(req, crypto_ahash_digest(req)); + ret = do_one_ahash_op(treq, crypto_ahash_digest(req)); if (ret) return ret; } @@ -736,28 +750,29 @@ static int test_ahash_jiffies_digest(struct ahash_request *req, int blen, return 0; } -static int test_ahash_jiffies(struct ahash_request *req, int blen, +static int test_ahash_jiffies(struct tcrypt_ahash_request *treq, int blen, int plen, char *out, int secs) { + struct ahash_request *req = treq->req; unsigned long start, end; int bcount, pcount; int ret; if (plen == blen) - return test_ahash_jiffies_digest(req, blen, out, secs); + return test_ahash_jiffies_digest(treq, blen, out, secs); for (start = jiffies, end = start + secs * HZ, bcount = 0; time_before(jiffies, end); bcount++) { - ret = do_one_ahash_op(req, crypto_ahash_init(req)); + ret = do_one_ahash_op(treq, crypto_ahash_init(req)); if (ret) return ret; for (pcount = 0; pcount < blen; pcount += plen) { - ret = do_one_ahash_op(req, crypto_ahash_update(req)); + ret = do_one_ahash_op(treq, crypto_ahash_update(req)); if (ret) return ret; } /* we assume there is enough space in 'out' for the result */ - ret = do_one_ahash_op(req, crypto_ahash_final(req)); + ret = do_one_ahash_op(treq, crypto_ahash_final(req)); if (ret) return ret; } @@ -768,15 +783,16 @@ static int test_ahash_jiffies(struct ahash_request *req, int blen, return 0; } -static int test_ahash_cycles_digest(struct ahash_request *req, int blen, - char *out) +static int test_ahash_cycles_digest(struct tcrypt_ahash_request *treq, + int blen, char *out) { + struct ahash_request *req = treq->req; unsigned long cycles = 0; int ret, i; /* Warm-up run. */ for (i = 0; i < 4; i++) { - ret = do_one_ahash_op(req, crypto_ahash_digest(req)); + ret = do_one_ahash_op(treq, crypto_ahash_digest(req)); if (ret) goto out; } @@ -787,7 +803,7 @@ static int test_ahash_cycles_digest(struct ahash_request *req, int blen, start = get_cycles(); - ret = do_one_ahash_op(req, crypto_ahash_digest(req)); + ret = do_one_ahash_op(treq, crypto_ahash_digest(req)); if (ret) goto out; @@ -806,26 +822,27 @@ out: return 0; } -static int test_ahash_cycles(struct ahash_request *req, int blen, +static int test_ahash_cycles(struct tcrypt_ahash_request *treq, int blen, int plen, char *out) { + struct ahash_request *req = treq->req; unsigned long cycles = 0; int i, pcount, ret; if (plen == blen) - return test_ahash_cycles_digest(req, blen, out); + return test_ahash_cycles_digest(treq, blen, out); /* Warm-up run. */ for (i = 0; i < 4; i++) { - ret = do_one_ahash_op(req, crypto_ahash_init(req)); + ret = do_one_ahash_op(treq, crypto_ahash_init(req)); if (ret) goto out; for (pcount = 0; pcount < blen; pcount += plen) { - ret = do_one_ahash_op(req, crypto_ahash_update(req)); + ret = do_one_ahash_op(treq, crypto_ahash_update(req)); if (ret) goto out; } - ret = do_one_ahash_op(req, crypto_ahash_final(req)); + ret = do_one_ahash_op(treq, crypto_ahash_final(req)); if (ret) goto out; } @@ -836,15 +853,15 @@ static int test_ahash_cycles(struct ahash_request *req, int blen, start = get_cycles(); - ret = do_one_ahash_op(req, crypto_ahash_init(req)); + ret = do_one_ahash_op(treq, crypto_ahash_init(req)); if (ret) goto out; for (pcount = 0; pcount < blen; pcount += plen) { - ret = do_one_ahash_op(req, crypto_ahash_update(req)); + ret = do_one_ahash_op(treq, crypto_ahash_update(req)); if (ret) goto out; } - ret = do_one_ahash_op(req, crypto_ahash_final(req)); + ret = do_one_ahash_op(treq, crypto_ahash_final(req)); if (ret) goto out; @@ -867,7 +884,7 @@ static void test_ahash_speed_common(const char *algo, unsigned int secs, struct hash_speed *speed, unsigned mask) { struct scatterlist sg[TVMEMSIZE]; - struct crypto_wait wait; + struct tcrypt_ahash_request treq; struct ahash_request *req; struct crypto_ahash *tfm; char *output; @@ -896,9 +913,10 @@ static void test_ahash_speed_common(const char *algo, unsigned int secs, goto out; } - crypto_init_wait(&wait); + treq.req = req; + crypto_init_wait(&treq.wait); ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - crypto_req_done, &wait); + crypto_req_done, &treq.wait); output = kmalloc(MAX_DIGEST_SIZE, GFP_KERNEL); if (!output) @@ -927,11 +945,11 @@ static void test_ahash_speed_common(const char *algo, unsigned int secs, ahash_request_set_crypt(req, sg, output, speed[i].plen); if (secs) { - ret = test_ahash_jiffies(req, speed[i].blen, + ret = test_ahash_jiffies(&treq, speed[i].blen, speed[i].plen, output, secs); cond_resched(); } else { - ret = test_ahash_cycles(req, speed[i].blen, + ret = test_ahash_cycles(&treq, speed[i].blen, speed[i].plen, output); } @@ -1217,16 +1235,16 @@ out_free_data: kfree(data); } -static inline int do_one_acipher_op(struct skcipher_request *req, int ret) +static inline int do_one_acipher_op(struct tcrypt_skcipher_request *req, + int ret) { - struct crypto_wait *wait = req->base.data; - - return crypto_wait_req(ret, wait); + return crypto_wait_req(ret, &req->wait); } -static int test_acipher_jiffies(struct skcipher_request *req, int enc, +static int test_acipher_jiffies(struct tcrypt_skcipher_request *treq, int enc, int blen, int secs) { + struct skcipher_request *req = treq->req; unsigned long start, end; int bcount; int ret; @@ -1234,10 +1252,10 @@ static int test_acipher_jiffies(struct skcipher_request *req, int enc, for (start = jiffies, end = start + secs * HZ, bcount = 0; time_before(jiffies, end); bcount++) { if (enc) - ret = do_one_acipher_op(req, + ret = do_one_acipher_op(treq, crypto_skcipher_encrypt(req)); else - ret = do_one_acipher_op(req, + ret = do_one_acipher_op(treq, crypto_skcipher_decrypt(req)); if (ret) @@ -1249,9 +1267,10 @@ static int test_acipher_jiffies(struct skcipher_request *req, int enc, return 0; } -static int test_acipher_cycles(struct skcipher_request *req, int enc, +static int test_acipher_cycles(struct tcrypt_skcipher_request *treq, int enc, int blen) { + struct skcipher_request *req = treq->req; unsigned long cycles = 0; int ret = 0; int i; @@ -1259,10 +1278,10 @@ static int test_acipher_cycles(struct skcipher_request *req, int enc, /* Warm-up run. */ for (i = 0; i < 4; i++) { if (enc) - ret = do_one_acipher_op(req, + ret = do_one_acipher_op(treq, crypto_skcipher_encrypt(req)); else - ret = do_one_acipher_op(req, + ret = do_one_acipher_op(treq, crypto_skcipher_decrypt(req)); if (ret) @@ -1275,10 +1294,10 @@ static int test_acipher_cycles(struct skcipher_request *req, int enc, start = get_cycles(); if (enc) - ret = do_one_acipher_op(req, + ret = do_one_acipher_op(treq, crypto_skcipher_encrypt(req)); else - ret = do_one_acipher_op(req, + ret = do_one_acipher_op(treq, crypto_skcipher_decrypt(req)); end = get_cycles(); @@ -1300,8 +1319,8 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs, struct cipher_speed_template *template, unsigned int tcount, u8 *keysize, bool async) { + struct tcrypt_skcipher_request treq; unsigned int ret, i, j, k, iv_len; - struct crypto_wait wait; const char *key; char iv[128]; struct skcipher_request *req; @@ -1314,7 +1333,7 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs, else e = "decryption"; - crypto_init_wait(&wait); + crypto_init_wait(&treq.wait); tfm = crypto_alloc_skcipher(algo, 0, async ? 0 : CRYPTO_ALG_ASYNC); @@ -1333,8 +1352,9 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs, goto out; } + treq.req = req; skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - crypto_req_done, &wait); + crypto_req_done, &treq.wait); i = 0; do { @@ -1401,11 +1421,11 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs, skcipher_request_set_crypt(req, sg, sg, bs, iv); if (secs) { - ret = test_acipher_jiffies(req, enc, + ret = test_acipher_jiffies(&treq, enc, bs, secs); cond_resched(); } else { - ret = test_acipher_cycles(req, enc, + ret = test_acipher_cycles(&treq, enc, bs); } From a0590c556cdbf88373d38494a23f1503d39b0ab2 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 22 Sep 2026 20:11:02 +0200 Subject: [PATCH 106/146] hwrng: intel - return -ENOMEM when kmalloc_obj() fails intel_rng_mod_init() incorrectly returns -ENODEV when kmalloc_obj() fails. Return -ENOMEM instead. Fixes: ee527cd3a20c ("Use stop_machine_run in the Intel RNG driver") Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/intel-rng.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index d24e747203c1..4aa91ee0e504 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -349,6 +349,7 @@ static int __init intel_rng_mod_init(void) intel_rng_hw = kmalloc_obj(*intel_rng_hw); if (!intel_rng_hw) { pci_dev_put(dev); + err = -ENOMEM; goto out; } From 780cd10c8e78f97ed768be229acff0ffd5483477 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 22 Sep 2026 22:11:16 -0700 Subject: [PATCH 107/146] crypto: sa2ul - Fix HMAC key preparation sa_prepare_iopads() has multiple bugs, as discussed at https://lore.kernel.org/linux-crypto/20260831055141.1632832-1-s-vadapalli@ti.com/T/#u - Commit 3bf533787910 ("crypto: sha256 - Use the partial block API") introduced a 1-byte buffer overflow in the SHA-256 case by making the crypto_shash_export() write 1 more than sizeof(struct sha256_state). - It never worked for HMAC keys longer than 64 bytes in the first place. Fix both of these bugs by just using the crypto library to prepare the key, like what the chelsio and qat drivers do. Also remove the pointless use of an indirect call. Fixes: 3bf533787910 ("crypto: sha256 - Use the partial block API") Fixes: d2c8ac187fc9 ("crypto: sa2ul - Add AEAD algorithm support") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/sa2ul.c | 119 +++++++++-------------------------------- 1 file changed, 26 insertions(+), 93 deletions(-) diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c index 0dce2b98886a..b014350a3da0 100644 --- a/drivers/crypto/sa2ul.c +++ b/drivers/crypto/sa2ul.c @@ -125,9 +125,7 @@ struct sa_cmdl_cfg { * @mci_enc: Mode Control Instruction for Encryption algorithm * @mci_dec: Mode Control Instruction for Decryption * @inv_key: Whether the encryption algorithm demands key inversion - * @ctx: Pointer to the algorithm context * @keyed_mac: Whether the authentication algorithm has key - * @prep_iopad: Function pointer to generate intermediate ipad/opad */ struct algo_data { struct sa_eng_info enc_eng; @@ -141,10 +139,7 @@ struct algo_data { u8 *mci_enc; u8 *mci_dec; bool inv_key; - struct sa_tfm_ctx *ctx; bool keyed_mac; - void (*prep_iopad)(struct algo_data *algo, const u8 *key, - u16 key_sz, __be32 *ipad, __be32 *opad); }; /** @@ -381,86 +376,36 @@ static void sa_swiz_128(u8 *in, u16 len) } } -/* Prepare the ipad and opad from key as per SHA algorithm step 1*/ -static void prepare_kipad(u8 *k_ipad, const u8 *key, u16 key_sz) +static void sa_prepare_iopads(struct algo_data *data, const u8 *key, u16 key_sz, + __be32 *ipad, __be32 *opad) { - int i; + union { + struct hmac_sha1_key sha1; + struct hmac_sha256_key sha256; + } k; - for (i = 0; i < key_sz; i++) - k_ipad[i] = key[i] ^ 0x36; - - /* Instead of XOR with 0 */ - for (; i < SHA1_BLOCK_SIZE; i++) - k_ipad[i] = 0x36; -} - -static void prepare_kopad(u8 *k_opad, const u8 *key, u16 key_sz) -{ - int i; - - for (i = 0; i < key_sz; i++) - k_opad[i] = key[i] ^ 0x5c; - - /* Instead of XOR with 0 */ - for (; i < SHA1_BLOCK_SIZE; i++) - k_opad[i] = 0x5c; -} - -static void sa_export_shash(void *state, struct shash_desc *hash, - int digest_size, __be32 *out) -{ - struct sha1_state *sha1; - struct sha256_state *sha256; - u32 *result; - - switch (digest_size) { - case SHA1_DIGEST_SIZE: - sha1 = state; - result = sha1->state; + switch (data->aalg_id) { + case SA_AALG_ID_HMAC_SHA1: + hmac_sha1_preparekey(&k.sha1, key, key_sz); + cpu_to_be32_array(ipad, k.sha1.istate.h, + ARRAY_SIZE(k.sha1.istate.h)); + cpu_to_be32_array(opad, k.sha1.ostate.h, + ARRAY_SIZE(k.sha1.ostate.h)); break; - case SHA256_DIGEST_SIZE: - sha256 = state; - result = sha256->state; + case SA_AALG_ID_HMAC_SHA2_256: + hmac_sha256_preparekey(&k.sha256, key, key_sz); + cpu_to_be32_array(ipad, k.sha256.key.istate.h, + ARRAY_SIZE(k.sha256.key.istate.h)); + cpu_to_be32_array(opad, k.sha256.key.ostate.h, + ARRAY_SIZE(k.sha256.key.ostate.h)); break; default: - dev_err(sa_k3_dev, "%s: bad digest_size=%d\n", __func__, - digest_size); + dev_err(sa_k3_dev, "%s: bad aalg_id=%d\n", __func__, + data->aalg_id); return; } - crypto_shash_export(hash, state); - - cpu_to_be32_array(out, result, digest_size / 4); -} - -static void sa_prepare_iopads(struct algo_data *data, const u8 *key, - u16 key_sz, __be32 *ipad, __be32 *opad) -{ - SHASH_DESC_ON_STACK(shash, data->ctx->shash); - int block_size = crypto_shash_blocksize(data->ctx->shash); - int digest_size = crypto_shash_digestsize(data->ctx->shash); - union { - struct sha1_state sha1; - struct sha256_state sha256; - u8 k_pad[SHA1_BLOCK_SIZE]; - } sha; - - shash->tfm = data->ctx->shash; - - prepare_kipad(sha.k_pad, key, key_sz); - - crypto_shash_init(shash); - crypto_shash_update(shash, sha.k_pad, block_size); - sa_export_shash(&sha, shash, digest_size, ipad); - - prepare_kopad(sha.k_pad, key, key_sz); - - crypto_shash_init(shash); - crypto_shash_update(shash, sha.k_pad, block_size); - - sa_export_shash(&sha, shash, digest_size, opad); - - memzero_explicit(&sha, sizeof(sha)); + memzero_explicit(&k, sizeof(k)); } /* Derive the inverse key used in AES-CBC decryption operation */ @@ -544,7 +489,7 @@ static void sa_set_sc_auth(struct algo_data *ad, const u8 *key, u16 key_sz, /* Copy the keys or ipad/opad */ if (ad->keyed_mac) - ad->prep_iopad(ad, key, key_sz, ipad, opad); + sa_prepare_iopads(ad, key, key_sz, ipad, opad); else { /* basic hash */ sc_buf[1] |= SA_BASIC_HASH; @@ -1697,8 +1642,7 @@ static void sa_aead_dma_in_callback(void *data) aead_request_complete(req, err); } -static int sa_cra_init_aead(struct crypto_aead *tfm, const char *hash, - const char *fallback) +static int sa_cra_init_aead(struct crypto_aead *tfm, const char *fallback) { struct sa_tfm_ctx *ctx = crypto_aead_ctx(tfm); struct sa_crypto_data *data = dev_get_drvdata(sa_k3_dev); @@ -1707,12 +1651,6 @@ static int sa_cra_init_aead(struct crypto_aead *tfm, const char *hash, memzero_explicit(ctx, sizeof(*ctx)); ctx->dev_data = data; - ctx->shash = crypto_alloc_shash(hash, 0, CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(ctx->shash)) { - dev_err(sa_k3_dev, "base driver %s couldn't be loaded\n", hash); - return PTR_ERR(ctx->shash); - } - ctx->fallback.aead = crypto_alloc_aead(fallback, 0, CRYPTO_ALG_NEED_FALLBACK); @@ -1744,14 +1682,12 @@ static int sa_cra_init_aead(struct crypto_aead *tfm, const char *hash, static int sa_cra_init_aead_sha1(struct crypto_aead *tfm) { - return sa_cra_init_aead(tfm, "sha1", - "authenc(hmac(sha1),cbc(aes))"); + return sa_cra_init_aead(tfm, "authenc(hmac(sha1),cbc(aes))"); } static int sa_cra_init_aead_sha256(struct crypto_aead *tfm) { - return sa_cra_init_aead(tfm, "sha256", - "authenc(hmac(sha256),cbc(aes))"); + return sa_cra_init_aead(tfm, "authenc(hmac(sha256),cbc(aes))"); } static void sa_exit_tfm_aead(struct crypto_aead *tfm) @@ -1759,7 +1695,6 @@ static void sa_exit_tfm_aead(struct crypto_aead *tfm) struct sa_tfm_ctx *ctx = crypto_aead_ctx(tfm); struct sa_crypto_data *data = dev_get_drvdata(sa_k3_dev); - crypto_free_shash(ctx->shash); crypto_free_aead(ctx->fallback.aead); sa_free_ctx_info(&ctx->enc, data); @@ -1785,7 +1720,6 @@ static int sa_aead_setkey(struct crypto_aead *authenc, if (key_idx >= 3) return -EINVAL; - ad->ctx = ctx; ad->enc_eng.eng_id = SA_ENG_ID_EM1; ad->enc_eng.sc_size = SA_CTX_ENC_TYPE1_SZ; ad->auth_eng.eng_id = SA_ENG_ID_AM1; @@ -1795,7 +1729,6 @@ static int sa_aead_setkey(struct crypto_aead *authenc, ad->inv_key = true; ad->keyed_mac = true; ad->ealg_id = SA_EALG_ID_AES_CBC; - ad->prep_iopad = sa_prepare_iopads; memset(&cfg, 0, sizeof(cfg)); cfg.enc = true; From 973eb89550d347aa4bc4e58452cf7a0d13fde29e Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 23 Sep 2026 06:01:14 +0000 Subject: [PATCH 108/146] crypto: hisilicon/qm - annotate cap_tables with __counted_by_ptr Annotate the 'qm_cap_table' and 'dev_cap_table' pointer fields in 'struct hisi_qm_cap_tables' with the '__counted_by_ptr' attribute. This improves bounds checking via CONFIG_UBSAN_BOUNDS and CONFIG_FORTIFY_SOURCE, allowing KASAN and compiler diagnostics to detect out-of-bounds accesses. The 'qm_cap_table' pointer is associated with 'qm_cap_size' which specifies its element count. Similarly, 'dev_cap_table' is associated with 'dev_cap_size'. To ensure safety under compiler instrumentation, the assignments in the initialization paths have been updated to set the 'size'/'count' fields prior to setting the pointer fields. This prevents any transient state where the pointer is valid but the count is 0 (or uninitialized), ensuring that subsequent accesses to these tables do not trigger false-positive bounds check panics. Cc: codemender-patching+linux@google.com Assisted-by: LLM Signed-off-by: Bill Wendling Reviewed-by: Gustavo A. R. Silva Reviewed-by: Longfang Liu Signed-off-by: Herbert Xu --- drivers/crypto/hisilicon/hpre/hpre_main.c | 2 +- drivers/crypto/hisilicon/qm.c | 2 +- drivers/crypto/hisilicon/sec2/sec_main.c | 2 +- drivers/crypto/hisilicon/zip/zip_main.c | 2 +- include/linux/hisi_acc_qm.h | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index 03aa11a7a3b4..fd3c34daceb7 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -1223,8 +1223,8 @@ static int hpre_pre_store_cap_reg(struct hisi_qm *qm) return -EINVAL; } - qm->cap_tables.dev_cap_table = hpre_cap; qm->cap_tables.dev_cap_size = size; + qm->cap_tables.dev_cap_table = hpre_cap; return 0; } diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index c01966a4a33f..7d13476451e3 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -5743,8 +5743,8 @@ static int qm_pre_store_caps(struct hisi_qm *qm) i, qm->cap_ver); } - qm->cap_tables.qm_cap_table = qm_cap; qm->cap_tables.qm_cap_size = size; + qm->cap_tables.qm_cap_table = qm_cap; return 0; } diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c index 752565200c16..ac423d016998 100644 --- a/drivers/crypto/hisilicon/sec2/sec_main.c +++ b/drivers/crypto/hisilicon/sec2/sec_main.c @@ -1285,8 +1285,8 @@ static int sec_pre_store_cap_reg(struct hisi_qm *qm) i, qm->cap_ver); } - qm->cap_tables.dev_cap_table = sec_cap; qm->cap_tables.dev_cap_size = size; + qm->cap_tables.dev_cap_table = sec_cap; return 0; } diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index 706a73656977..10091ad4a6a8 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -1400,8 +1400,8 @@ static int zip_pre_store_cap_reg(struct hisi_qm *qm) i, qm->cap_ver); } - qm->cap_tables.dev_cap_table = zip_cap; qm->cap_tables.dev_cap_size = size; + qm->cap_tables.dev_cap_table = zip_cap; return 0; } diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index f7570a409905..8dc49fa2123b 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -332,9 +332,9 @@ struct hisi_qm_cap_record { struct hisi_qm_cap_tables { u32 qm_cap_size; - struct hisi_qm_cap_record *qm_cap_table; + struct hisi_qm_cap_record *qm_cap_table __counted_by_ptr(qm_cap_size); u32 dev_cap_size; - struct hisi_qm_cap_record *dev_cap_table; + struct hisi_qm_cap_record *dev_cap_table __counted_by_ptr(dev_cap_size); }; struct hisi_qm_list { From e620245bff228aa8e482a19b72b8469366305d4c Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 23 Sep 2026 06:10:27 +0000 Subject: [PATCH 109/146] crypto: hisilicon/qm - add __counted_by_ptr to dfx_diff_registers Annotate the pointer field 'regs' in 'struct dfx_diff_registers' with the '__counted_by_ptr' attribute, referencing the 'reg_len' member which holds the element count of the allocated memory. In 'drivers/crypto/hisilicon/debugfs.c', the 'dfx_regs_init' function allocates the 'diff_regs' array and initializes each element's 'regs' pointer after setting its 'reg_len'. Since 'reg_len' is set before 'regs' is assigned, the compiler's bounds sanitizer can correctly associate the pointer with its allocated size. Cc: codemender-patching+linux@google.com Assisted-by: LLM Signed-off-by: Bill Wendling Reviewed-by: Gustavo A. R. Silva Signed-off-by: Herbert Xu --- include/linux/hisi_acc_qm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 8dc49fa2123b..f2885d60b468 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -196,7 +196,7 @@ struct qm_dev_dfx { }; struct dfx_diff_registers { - u32 *regs; + u32 *regs __counted_by_ptr(reg_len); u32 reg_offset; u32 reg_len; }; From a91d9346a70b68f77884cba9d9ec3b70f96bf9d2 Mon Sep 17 00:00:00 2001 From: ZhaoJinming Date: Wed, 23 Sep 2026 18:14:57 +0800 Subject: [PATCH 110/146] crypto: caam - fix double-free in caam_rsa_set_priv_key_form() caam_rsa_set_priv_key_form() frees the partially allocated key components (p, q, tmp1, tmp2, dp, dq) with kfree_sensitive() on its error path, but does not set those pointers to NULL afterward. When the function returns an error, caam_rsa_set_priv_key() jumps to its err label and calls caam_rsa_free_key(), which frees all of those same pointers again, resulting in a double-free. This is reachable when the allocation of q, tmp1, tmp2, dp, dq or qinv fails, e.g. under memory pressure, or for a malformed key whose CRT members decode to zero length and make caam_read_rsa_crt() return NULL. Set each pointer to NULL right after freeing it so that the subsequent caam_rsa_free_key() call becomes a no-op for the already-freed fields. Fixes: 52e26d77b8b3 ("crypto: caam - add support for RSA key form 2") Cc: stable@vger.kernel.org Signed-off-by: ZhaoJinming Reviewed-by: Sahil Malhotra Signed-off-by: Herbert Xu --- drivers/crypto/caam/caampkc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index cb001aa1de66..ac515ed8c575 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -1033,16 +1033,22 @@ static int caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx, free_dq: kfree_sensitive(rsa_key->dq); + rsa_key->dq = NULL; free_dp: kfree_sensitive(rsa_key->dp); + rsa_key->dp = NULL; free_tmp2: kfree_sensitive(rsa_key->tmp2); + rsa_key->tmp2 = NULL; free_tmp1: kfree_sensitive(rsa_key->tmp1); + rsa_key->tmp1 = NULL; free_q: kfree_sensitive(rsa_key->q); + rsa_key->q = NULL; free_p: kfree_sensitive(rsa_key->p); + rsa_key->p = NULL; return -ENOMEM; } From 10016246d5e572ed77c3eec2311c34b6d6b789a6 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 23 Sep 2026 12:42:35 +0200 Subject: [PATCH 111/146] hwrng: intel - declare warning string as const The warning string is not modified and only used during initialization. Declare it as const, replace __initdata with __initconst, and indent the string. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/intel-rng.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 4aa91ee0e504..5da06ed79e2d 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -305,11 +305,11 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, if ((intel_rng_hw->bios_cntl_val & (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) == BIOS_CNTL_LOCK_ENABLE_MASK) { - static __initdata /*const*/ char warning[] = -PFX "Firmware space is locked read-only. If you can't or\n" -PFX "don't want to disable this in firmware setup, and if\n" -PFX "you are certain that your system has a functional\n" -PFX "RNG, try using the 'no_fwh_detect' option.\n"; + static const char warning[] __initconst = + PFX "Firmware space is locked read-only. If you can't or\n" + PFX "don't want to disable this in firmware setup, and if\n" + PFX "you are certain that your system has a functional\n" + PFX "RNG, try using the 'no_fwh_detect' option.\n"; if (no_fwh_detect) return -ENODEV; From e7f5ce911efb2017381f28bbedb6243a74a9c285 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 23 Sep 2026 22:12:58 +0200 Subject: [PATCH 112/146] hwrng: amd - report partial reads in non-blocking mode amd_rng_read() returns 0 if no more data is available, even if some data was already copied to the output buffer. Return the number of copied bytes instead. Fixes: 85962d2248fa ("hwrng: amd - Convert to new hwrng read() API") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/amd-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c index dff80daae587..ac2d257793bf 100644 --- a/drivers/char/hw_random/amd-rng.c +++ b/drivers/char/hw_random/amd-rng.c @@ -80,7 +80,7 @@ static int amd_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) if (timeout-- == 0) return read; } else { - return 0; + return read; } } else { *data = ioread32(priv->iobase + RNGDATA); From 7e638679883ceff5b6e7b6dcad09c21a105e941f Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 24 Sep 2026 11:33:59 +0200 Subject: [PATCH 113/146] hwrng: ba431 - fix reported byte count Use the size of the buffer element instead of the pointer size to report the number of bytes read. Since data is a u32 pointer and sizeof(data) is 8 bytes on 64-bit systems, using the pointer size reports twice the number of bytes actually read. Fixes: 0289e9be5dc2 ("hwrng: ba431 - add support for BA431 hwrng") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/ba431-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/ba431-rng.c b/drivers/char/hw_random/ba431-rng.c index b0a39032c610..810c8cd5629a 100644 --- a/drivers/char/hw_random/ba431-rng.c +++ b/drivers/char/hw_random/ba431-rng.c @@ -147,7 +147,7 @@ static int ba431_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) } } - n *= sizeof(data); + n *= sizeof(*data); return (n || !wait) ? n : -EIO; } From 8c515ff87534a700823fbef194a10fc354a16654 Mon Sep 17 00:00:00 2001 From: Usama Arif Date: Thu, 24 Sep 2026 11:47:33 -0700 Subject: [PATCH 114/146] rhashtable: specialize default comparison for constant parameters The inline lookup and insert helpers receive the rhashtable parameters by value. With a static const parameter block, key_offset and key_len are compile-time constants at the call site. The default comparison throws that information away by reading both fields back from ht->p. Fixed-size keys consequently load the parameters and call bcmp() for every object in the bucket, even when the compiler could use scalar comparisons instead. The commit "sched_ext: Specialize the DSQ hashtable compare" [1] resulted in a 2.9x faster DSQ lookup after replacing this path for its u64 key with a scalar comparison. Doing that through obj_cmpfn requires every fixed-key user to provide its own callback. Pass the call-site parameters to rhashtable_compare(), as rht_key_get_hash() already does. Use them when key_len is a compile-time constant. Retain the ht->p path for dynamic parameter blocks. A constant zero key_len continues to take the runtime length from ht->p.key_len. This specializes the default comparison for all fixed-size users. With Clang 22 on x86-64, bcmp() disappears from sched_ext, mac80211, NFSd, TIPC, NFQUEUE, VFS superblock, pidfs, SysV IPC and hardware-breakpoint table paths. The affected build_policy.o, sta_info.o and nfsd filecache.o text shrinks by 512, 400 and 352 bytes respectively. Four- and eight-byte keys become direct scalar comparisons; six-byte MAC addresses become a four-byte and a two-byte comparison. Measure the VFS case with ustat() on a mounted ramfs. This exercises user_get_super() and its super_dev lookup. Across ten interleaved baseline and patched VM boot pairs, with five 3 million call samples per boot, the average per-boot median latency drops from 477.2 to 462.6 ns per call, or 3.0%. All ten pairs improved. No functional change intended. [1] https://lore.kernel.org/all/20260921171928.1639407-1-usama.arif@linux.dev/ Suggested-by: Mykola Lysenko Signed-off-by: Usama Arif Acked-by: Tejun Heo Signed-off-by: Herbert Xu --- include/linux/rhashtable.h | 20 +++++++++++++++----- lib/rhashtable.c | 5 +++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index ec853c1b9af3..70dac9214617 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h @@ -593,13 +593,23 @@ static inline void rht_assign_unlock(struct bucket_table *tbl, for (pos = list; pos && rht_entry(tpos, pos, member); \ pos = rcu_dereference_all(pos->next)) -static inline int rhashtable_compare(struct rhashtable_compare_arg *arg, - const void *obj) +/* + * Use constant params from inlined callers to specialize memcmp(). If params + * isn't constant, it must be equal to ht->p. + */ +static __always_inline int rhashtable_compare(struct rhashtable_compare_arg *arg, + const void *obj, + const struct rhashtable_params params) { struct rhashtable *ht = arg->ht; const char *ptr = obj; - return memcmp(ptr + ht->p.key_offset, arg->key, ht->p.key_len); + if (!__builtin_constant_p(params.key_len)) + return memcmp(ptr + ht->p.key_offset, arg->key, + ht->p.key_len); + + return memcmp(ptr + params.key_offset, arg->key, + params.key_len ? : ht->p.key_len); } /* Internal function, do not use. */ @@ -627,7 +637,7 @@ restart: rht_for_each_rcu_from(he, __rht_ptr_rcu(bkt, freq), tbl, hash) { if (params.obj_cmpfn ? params.obj_cmpfn(&arg, rht_obj(ht, he)) : - rhashtable_compare(&arg, rht_obj(ht, he))) + rhashtable_compare(&arg, rht_obj(ht, he), params)) continue; return he; } @@ -792,7 +802,7 @@ slow_path: if (!key || (params.obj_cmpfn ? params.obj_cmpfn(&arg, rht_obj(ht, head)) : - rhashtable_compare(&arg, rht_obj(ht, head)))) { + rhashtable_compare(&arg, rht_obj(ht, head), params))) { pprev = &head->next; continue; } diff --git a/lib/rhashtable.c b/lib/rhashtable.c index a3a4a1f7751e..500c45cd1304 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -549,7 +549,7 @@ static void *rhashtable_lookup_one(struct rhashtable *ht, if (!key || (ht->p.obj_cmpfn ? ht->p.obj_cmpfn(&arg, rht_obj(ht, head)) : - rhashtable_compare(&arg, rht_obj(ht, head)))) { + rhashtable_compare(&arg, rht_obj(ht, head), ht->p))) { pprev = &head->next; continue; } @@ -711,7 +711,8 @@ static struct rhash_head *__rhashtable_next_in_table( rht_for_each_rcu(he, tbl, b) { bool match = params.obj_cmpfn ? !params.obj_cmpfn(&arg, rht_obj(ht, he)) - : !rhashtable_compare(&arg, rht_obj(ht, he)); + : !rhashtable_compare(&arg, rht_obj(ht, he), + params); if (found) { if (match) continue; From 7e7be8815143751c20260f80cb4e7fe14dd24b74 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 24 Sep 2026 23:21:13 +0200 Subject: [PATCH 115/146] hwrng: core - reject unknown RNG names In rng_current_store(), err is 0 after successfully locking rng_mutex, and if the requested RNG name cannot be found, the function reports success even though the current RNG was not changed. Set err = -ENODEV before searching the RNG list to reject unknown names. Fixes: 142a27f0a731 ("hwrng: core - Reset user selected rng by writing "" to rng_current") Cc: stable@vger.kernel.org Signed-off-by: Thorsten Blum Reviewed-by: Andy Shevchenko Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 57eeefe90da9..1f9e31cdc7f0 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -376,6 +376,7 @@ static ssize_t rng_current_store(struct device *dev, cur_rng_set_by_user = 1; drop_current_rng(); } else { + err = -ENODEV; list_for_each_entry(rng, &rng_list, list) { if (sysfs_streq(rng->name, buf)) { err = set_current_rng(rng); From b5c2df42977390a71f1940def5be9bd5c69ac2e0 Mon Sep 17 00:00:00 2001 From: Aldo Ariel Panzardo Date: Fri, 25 Sep 2026 14:58:39 -0300 Subject: [PATCH 116/146] crypto: nx - validate 'ignore' before subtracting in decompress The decompress() function subtracts the header-supplied `ignore` value (a u16 from the compressed stream) from `dlen` (the number of bytes produced by the decompressor) without checking that ignore <= dlen. If a caller decompresses a crafted buffer where `hdr->ignore` exceeds the actual decompressed length, the subtraction wraps around to a near-UINT_MAX value. The subsequent memcpy() then copies gigabytes of data past the destination buffer, causing an out-of-bounds kernel write. Add a bounds check before the subtraction and return -EINVAL if the value is inconsistent. Cc: stable@vger.kernel.org Signed-off-by: Aldo Ariel Panzardo Signed-off-by: Herbert Xu --- drivers/crypto/nx/nx-842.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c index a61208cbcd27..b4404a138962 100644 --- a/drivers/crypto/nx/nx-842.c +++ b/drivers/crypto/nx/nx-842.c @@ -421,6 +421,8 @@ usesw: slen -= spadding; + if (ignore > dlen) + return -EINVAL; dlen -= ignore; if (ignore) pr_debug("ignoring last %x bytes\n", ignore); From 468dd85acf33f47949c212036d26d01e5e5437b7 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 26 Sep 2026 07:58:54 +0200 Subject: [PATCH 117/146] hwrng: virtio - use min() in copy_data() Use the simpler min() macro since all values are unsigned and compatible. The subtraction avail - vi->data_idx is also guaranteed to be positive by the preceding check. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/virtio-rng.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 5e83ffa105e4..5b1b23b5596a 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -81,13 +81,13 @@ static unsigned int copy_data(struct virtrng_info *vi, void *buf, * steered into adjacent slab memory, including under * speculation. */ - avail = min_t(unsigned int, vi->data_avail, sizeof(vi->data)); + avail = min(vi->data_avail, sizeof(vi->data)); if (vi->data_idx >= avail) { vi->data_avail = 0; request_entropy(vi); return 0; } - size = min_t(unsigned int, size, avail - vi->data_idx); + size = min(size, avail - vi->data_idx); idx = array_index_nospec(vi->data_idx, sizeof(vi->data)); memcpy(buf, vi->data + idx, size); vi->data_idx += size; From 98807de9ac11a11a352f148e66e32d781f22c114 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 26 Sep 2026 07:58:55 +0200 Subject: [PATCH 118/146] hwrng: virtio - use snprintf() in probe_common() While the current code works correctly, replace the unbounded sprintf() with the safer snprintf() to follow secure coding best practices. Signed-off-by: Thorsten Blum Reviewed-by: Thomas Huth Reviewed-by: Laurent Vivier Signed-off-by: Herbert Xu --- drivers/char/hw_random/virtio-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 5b1b23b5596a..f9982217247d 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -162,7 +162,7 @@ static int probe_common(struct virtio_device *vdev) err = index; goto err_ida; } - sprintf(vi->name, "virtio_rng.%d", index); + snprintf(vi->name, sizeof(vi->name), "virtio_rng.%d", vi->index); init_completion(&vi->have_data); vi->hwrng = (struct hwrng) { From 6fd70bc8bc01a578c7728b7bd1cb5689c62cc5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Jean?= Date: Sat, 26 Sep 2026 20:43:26 +0000 Subject: [PATCH 119/146] crypto: ecc - Handle exceptional points in Shamir multiplication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shamir multiplication mishandles equal points, opposite points and the point at infinity. This rejects valid ECDSA signatures and can accept invalid digest/signature tuples when the public key is G or -G. The kernel incorrectly rejects 16 valid signatures from Wycheproof. Handle doubling, cancellation and the point at infinity in precomputation and accumulation. Add regression tests for P-256 ECDSA and 256/512-bit EC-RDSA. The valid vectors are Wycheproof P1363 secp256r1/SHA-256 cases 60 and 210 converted to X9.62, two constructed ECDSA signatures for Q = +/-G with k = 2, and six constructed EC-RDSA signatures for Q = G, -G and -2G. Also add two invalid P-256 digest/signature tuples for Q = +/-G that must return -EKEYREJECTED. Fixes: 0d7a78643f69 ("crypto: ecrdsa - add EC-RDSA (GOST 34.10) algorithm") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Jérémy Jean Reviewed-by: Ignat Korchagin Reviewed-by: Stefan Berger Signed-off-by: Herbert Xu --- crypto/ecc.c | 33 ++++- crypto/testmgr.c | 11 +- crypto/testmgr.h | 327 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 363 insertions(+), 8 deletions(-) diff --git a/crypto/ecc.c b/crypto/ecc.c index 3250a464b852..c7366eb7ce1f 100644 --- a/crypto/ecc.c +++ b/crypto/ecc.c @@ -1423,9 +1423,22 @@ static void ecc_point_add(const struct ecc_point *result, vli_set(result->x, q->x, ndigits); vli_set(result->y, q->y, ndigits); vli_mod_sub(z, result->x, p->x, curve->p, ndigits); + if (vli_is_zero(z, ndigits)) { + if (vli_cmp(p->y, q->y, ndigits)) { + /* P + (-P) is the point at infinity. */ + vli_clear(result->x, ndigits); + vli_clear(result->y, ndigits); + return; + } + /* The co-Z addition formula does not handle P == Q. */ + z[0] = 1; + ecc_point_double_jacobian(result->x, result->y, z, curve); + goto out; + } vli_set(px, p->x, ndigits); vli_set(py, p->y, ndigits); xycz_add(px, py, result->x, result->y, curve); +out: vli_mod_inv(z, z, curve->p, ndigits); apply_z(result->x, result->y, z, curve); } @@ -1465,22 +1478,38 @@ void ecc_point_mult_shamir(const struct ecc_point *result, vli_set(rx, point->x, ndigits); vli_set(ry, point->y, ndigits); vli_clear(z + 1, ndigits - 1); - z[0] = 1; + z[0] = !ecc_point_is_zero(point); for (--i; i >= 0; i--) { ecc_point_double_jacobian(rx, ry, z, curve); idx = !!vli_test_bit(u1, i); idx |= (!!vli_test_bit(u2, i)) << 1; point = points[idx]; - if (point) { + if (point && !ecc_point_is_zero(point)) { u64 tx[ECC_MAX_DIGITS]; u64 ty[ECC_MAX_DIGITS]; u64 tz[ECC_MAX_DIGITS]; + if (vli_is_zero(z, ndigits)) { + /* Adding to infinity starts a new accumulator. */ + vli_set(rx, point->x, ndigits); + vli_set(ry, point->y, ndigits); + z[0] = 1; + continue; + } vli_set(tx, point->x, ndigits); vli_set(ty, point->y, ndigits); apply_z(tx, ty, z, curve); vli_mod_sub(tz, rx, tx, curve->p, ndigits); + if (vli_is_zero(tz, ndigits)) { + if (!vli_cmp(ry, ty, ndigits)) + ecc_point_double_jacobian(rx, ry, z, + curve); + else + /* Adding opposite points yields infinity. */ + vli_clear(z, ndigits); + continue; + } xycz_add(tx, ty, rx, ry, curve); vli_mod_mult_fast(z, z, tz, curve); } diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 4958211fbfa9..9419d61d0602 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -3958,16 +3958,17 @@ static int test_sig_one(struct crypto_sig *tfm, const struct sig_testvec *vecs) */ err = crypto_sig_verify(tfm, vecs->c, vecs->c_size, vecs->m, vecs->m_size); - if (err) { - pr_err("alg: sig: verify test failed: err %d\n", err); - return err; + if (err != vecs->verify_error) { + pr_err("alg: sig: verify test failed: expected %d, got %d\n", + vecs->verify_error, err); + return err ?: -EINVAL; } /* * Don't invoke sign test (which requires a private key) - * for vectors with only a public key. + * for vectors with only a public key or an invalid signature. */ - if (vecs->public_key_vec) + if (vecs->public_key_vec || vecs->verify_error) return 0; sig_size = crypto_sig_maxsize(tfm); diff --git a/crypto/testmgr.h b/crypto/testmgr.h index c4a15e714ecd..0ee15a8fae27 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -161,6 +161,7 @@ struct sig_testvec { unsigned int param_len; unsigned int m_size; unsigned int c_size; + int verify_error; bool public_key_vec; enum OID algo; }; @@ -1443,6 +1444,140 @@ static const struct sig_testvec x962_ecdsa_nist_p192_tv_template[] = { }; static const struct sig_testvec x962_ecdsa_nist_p256_tv_template[] = { + /* Invalid signature: Q = G, r = s, e = 3r mod n. */ + { + .key = + "\x04\x6b\x17\xd1\xf2\xe1\x2c\x42\x47\xf8\xbc\xe6\xe5\x63\xa4\x40" + "\xf2\x77\x03\x7d\x81\x2d\xeb\x33\xa0\xf4\xa1\x39\x45\xd8\x98\xc2" + "\x96\x4f\xe3\x42\xe2\xfe\x1a\x7f\x9b\x8e\xe7\xeb\x4a\x7c\x0f\x9e" + "\x16\x2b\xce\x33\x57\x6b\x31\x5e\xce\xcb\xb6\x40\x68\x37\xbf\x51" + "\xf5", + .key_len = 65, + .m = + "\xb2\xc3\x09\x72\x03\x17\x9d\xaa\x5c\x4a\xd8\xff\x02\xfe\xcb\x15" + "\x21\x53\x81\x77\x45\xec\x45\x24\x3d\x68\x10\xb9\xf2\xa5\x88\x3a", + .m_size = 32, + .c = + "\x30\x46\x02\x21\x00\x90\xeb\xad\xd0\x56\x5d\x34\x8e\x74\x18\xf2" + "\xff\xab\xaa\x43\xb1\x9f\x68\xd4\x0c\x4f\x01\x4b\xe3\x10\x60\x9e" + "\x7e\xfa\x58\x39\xd9\x02\x21\x00\x90\xeb\xad\xd0\x56\x5d\x34\x8e" + "\x74\x18\xf2\xff\xab\xaa\x43\xb1\x9f\x68\xd4\x0c\x4f\x01\x4b\xe3" + "\x10\x60\x9e\x7e\xfa\x58\x39\xd9", + .c_size = 72, + .verify_error = -EKEYREJECTED, + .public_key_vec = true, + }, + /* Invalid signature: Q = -G, r = s, e = 3r mod n. */ + { + .key = + "\x04\x6b\x17\xd1\xf2\xe1\x2c\x42\x47\xf8\xbc\xe6\xe5\x63\xa4\x40" + "\xf2\x77\x03\x7d\x81\x2d\xeb\x33\xa0\xf4\xa1\x39\x45\xd8\x98\xc2" + "\x96\xb0\x1c\xbd\x1c\x01\xe5\x80\x65\x71\x18\x14\xb5\x83\xf0\x61" + "\xe9\xd4\x31\xcc\xa9\x94\xce\xa1\x31\x34\x49\xbf\x97\xc8\x40\xae" + "\x0a", + .key_len = 65, + .m = + "\xb2\xc3\x09\x72\x03\x17\x9d\xaa\x5c\x4a\xd8\xff\x02\xfe\xcb\x15" + "\x21\x53\x81\x77\x45\xec\x45\x24\x3d\x68\x10\xb9\xf2\xa5\x88\x3a", + .m_size = 32, + .c = + "\x30\x46\x02\x21\x00\x90\xeb\xad\xd0\x56\x5d\x34\x8e\x74\x18\xf2" + "\xff\xab\xaa\x43\xb1\x9f\x68\xd4\x0c\x4f\x01\x4b\xe3\x10\x60\x9e" + "\x7e\xfa\x58\x39\xd9\x02\x21\x00\x90\xeb\xad\xd0\x56\x5d\x34\x8e" + "\x74\x18\xf2\xff\xab\xaa\x43\xb1\x9f\x68\xd4\x0c\x4f\x01\x4b\xe3" + "\x10\x60\x9e\x7e\xfa\x58\x39\xd9", + .c_size = 72, + .verify_error = -EKEYREJECTED, + .public_key_vec = true, + }, + /* Wycheproof secp256r1/SHA-256 tcId 60. */ + { + .key = + "\x04\x29\x27\xb1\x05\x12\xba\xe3\xed\xdc\xfe\x46\x78\x28\x12\x8b" + "\xad\x29\x03\x26\x99\x19\xf7\x08\x60\x69\xc8\xc4\xdf\x6c\x73\x28" + "\x38\xc7\x78\x79\x64\xea\xac\x00\xe5\x92\x1f\xb1\x49\x8a\x60\xf4" + "\x60\x67\x66\xb3\xd9\x68\x50\x01\x55\x8d\x1a\x97\x4e\x73\x41\x51" + "\x3e", + .key_len = 65, + .m = + "\x70\x23\x9d\xd8\x77\xf7\xc9\x44\xc4\x22\xf4\x4d\xea\x4e\xd1\xa5" + "\x2f\x26\x27\x41\x6f\xaf\x2f\x07\x2f\xa5\x0c\x77\x2e\xd6\xf8\x07", + .m_size = 32, + .c = + "\x30\x44\x02\x20\x64\xa1\xaa\xb5\x00\x0d\x0e\x80\x4f\x3e\x2f\xc0" + "\x2b\xde\xe9\xbe\x8f\xf3\x12\x33\x4e\x2b\xa1\x6d\x11\x54\x7c\x97" + "\x71\x1c\x89\x8e\x02\x20\x6a\xf0\x15\x97\x1c\xc3\x0b\xe6\xd1\xa2" + "\x06\xd4\xe0\x13\xe0\x99\x77\x72\xa2\xf9\x1d\x73\x28\x6f\xfd\x68" + "\x3b\x9b\xb2\xcf\x4f\x1b", + .c_size = 70, + .public_key_vec = true, + }, + /* Wycheproof secp256r1/SHA-256 tcId 210. */ + { + .key = + "\x04\xc6\xa7\x71\x52\x70\x24\x22\x77\x92\x17\x0a\x6f\x8e\xee\x73" + "\x5b\xf3\x2b\x7f\x98\xaf\x66\x9e\xad\x29\x98\x02\xe3\x2d\x7c\x31" + "\x07\xbc\x3b\x4b\x5e\x65\xab\x88\x7b\xbd\x34\x35\x72\xb3\xe5\x61" + "\x92\x61\xfe\x3a\x07\x3e\x2f\xfd\x78\x41\x2f\x72\x68\x67\xdb\x58" + "\x9e", + .key_len = 65, + .m = + "\xbb\x5a\x52\xf4\x2f\x9c\x92\x61\xed\x43\x61\xf5\x94\x22\xa1\xe3" + "\x00\x36\xe7\xc3\x2b\x27\x0c\x88\x07\xa4\x19\xfe\xca\x60\x50\x23", + .m_size = 32, + .c = + "\x30\x45\x02\x20\x7c\xf2\x7b\x18\x8d\x03\x4f\x7e\x8a\x52\x38\x03" + "\x04\xb5\x1a\xc3\xc0\x89\x69\xe2\x77\xf2\x1b\x35\xa6\x0b\x48\xfc" + "\x47\x66\x99\x78\x02\x21\x00\xb6\xdb\x6d\xb6\x24\x92\x49\x25\x49" + "\x24\x92\x49\x24\x92\x49\x24\x62\x5b\xd7\xa0\x9b\xec\x4c\xa8\x1b" + "\xcd\xd9\xf8\xfd\x6b\x63\xcc", + .c_size = 71, + .public_key_vec = true, + }, + /* Q = G, d = 1, k = 2. */ + { + .key = + "\x04\x6b\x17\xd1\xf2\xe1\x2c\x42\x47\xf8\xbc\xe6\xe5\x63\xa4\x40" + "\xf2\x77\x03\x7d\x81\x2d\xeb\x33\xa0\xf4\xa1\x39\x45\xd8\x98\xc2" + "\x96\x4f\xe3\x42\xe2\xfe\x1a\x7f\x9b\x8e\xe7\xeb\x4a\x7c\x0f\x9e" + "\x16\x2b\xce\x33\x57\x6b\x31\x5e\xce\xcb\xb6\x40\x68\x37\xbf\x51" + "\xf5", + .key_len = 65, + .m = + "\x35\x9d\x17\x29\xb9\x1a\x52\xe9\x8b\xb5\x95\xc3\x86\x28\x3c\x10" + "\x30\x44\x95\x1a\xa1\x08\x20\xf0\xa0\x22\xc4\x18\xc2\x71\xa0\xcc", + .m_size = 32, + .c = + "\x30\x44\x02\x20\x7c\xf2\x7b\x18\x8d\x03\x4f\x7e\x8a\x52\x38\x03" + "\x04\xb5\x1a\xc3\xc0\x89\x69\xe2\x77\xf2\x1b\x35\xa6\x0b\x48\xfc" + "\x47\x66\x99\x78\x02\x20\x59\x47\xc9\x21\x23\x0e\xd1\x34\x0b\x03" + "\xe6\xe3\x45\x6e\xab\x69\xf8\x66\xff\x7e\x8c\x7d\x1e\x13\x23\x17" + "\x06\x8a\x84\xec\x1d\x22", + .c_size = 70, + .public_key_vec = true, + }, + /* Q = -G, d = n - 1, k = 2. */ + { + .key = + "\x04\x6b\x17\xd1\xf2\xe1\x2c\x42\x47\xf8\xbc\xe6\xe5\x63\xa4\x40" + "\xf2\x77\x03\x7d\x81\x2d\xeb\x33\xa0\xf4\xa1\x39\x45\xd8\x98\xc2" + "\x96\xb0\x1c\xbd\x1c\x01\xe5\x80\x65\x71\x18\x14\xb5\x83\xf0\x61" + "\xe9\xd4\x31\xcc\xa9\x94\xce\xa1\x31\x34\x49\xbf\x97\xc8\x40\xae" + "\x0a", + .key_len = 65, + .m = + "\x35\x9d\x17\x29\xb9\x1a\x52\xe9\x8b\xb5\x95\xc3\x86\x28\x3c\x10" + "\x30\x44\x95\x1a\xa1\x08\x20\xf0\xa0\x22\xc4\x18\xc2\x71\xa0\xcc", + .m_size = 32, + .c = + "\x30\x45\x02\x20\x7c\xf2\x7b\x18\x8d\x03\x4f\x7e\x8a\x52\x38\x03" + "\x04\xb5\x1a\xc3\xc0\x89\x69\xe2\x77\xf2\x1b\x35\xa6\x0b\x48\xfc" + "\x47\x66\x99\x78\x02\x21\x00\xdc\x55\x4e\x07\x96\x0b\x81\xb6\x80" + "\xb1\xae\xe0\x40\xb9\x90\xa5\xf4\xc4\x90\x49\xbb\xa2\xa1\x62\x70" + "\xc5\x88\x51\x39\xe8\xa8\xfb", + .c_size = 71, + .public_key_vec = true, + }, { .key = /* secp256r1(sha1) */ "\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41" @@ -1827,7 +1962,8 @@ static const struct sig_testvec p1363_ecdsa_nist_p256_tv_template[] = { }; /* - * EC-RDSA test vectors are generated by gost-engine. + * EC-RDSA test vectors generated by gost-engine, followed by constructed + * exceptional-point regression vectors. */ static const struct sig_testvec ecrdsa_tv_template[] = { { @@ -1973,6 +2109,195 @@ static const struct sig_testvec ecrdsa_tv_template[] = { .m_size = 64, .public_key_vec = true, }, + /* + * Constructed EC-RDSA exceptional-point vectors. + * With Q = dG, choose k = z1 + d*z2 (mod n), r = x(kG) mod n, + * e = -r/z2 (mod n), and s = r*d + k*e (mod n). + * The input digest is e, encoded little-endian. + */ + /* cp256a: Q=G, z1 = 3, z2 = 1. */ + { + .key = + "\x04\x40\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x14\x1e\x9f\x9e\x9c\xc9\xac\x22\xb1\xe3\x23\xdf\x2d\x4f" + "\x29\x35\x76\x2b\x3f\x45\x5a\x50\xdf\x27\xda\x9c\x98\xe0\x71\xe4" + "\x91\x8d", + .key_len = 66, + .params = /* OID_gostCPSignA */ + "\x30\x13\x06\x07\x2a\x85\x03\x02\x02\x23\x01\x06\x08\x2a\x85\x03" + "\x07\x01\x01\x02\x02", + .param_len = 21, + .c = + "\x1a\xed\x44\xae\xd4\x4a\xed\x44\xae\xd4\x4a\xed\x44\xae\xd4\x49" + "\x32\x67\xe0\x26\x16\xfd\xb7\xaf\xa4\xd7\x3e\x61\xd4\xf9\x7b\x94" + "\xf7\x06\x3e\x70\x63\xe7\x06\x3e\x70\x63\xe7\x06\x3e\x70\x63\xe7" + "\x06\x3e\x70\x63\xe7\x06\x3e\x70\x63\xe7\x06\x3e\x70\x63\xe4\xb7", + .c_size = 64, + .m = + "\xdc\xd3\xfd\x46\xcb\x14\x9d\xe1\x8f\x92\x54\xb2\x0c\xa0\x22\x66" + "\x18\x9c\x8f\xc1\xf9\x18\x9c\x8f\xc1\xf9\x18\x9c\x8f\xc1\xf9\x08", + .m_size = 32, + .algo = OID_gost2012PKey256, + .public_key_vec = true, + }, + /* cp256a: Q=-G, z1 = 7, z2 = 6. */ + { + .key = + "\x04\x40\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x83\xdf\x60\x61\x63\x36\x53\xdd\x4e\x1c\xdc\x20\xd2\xb0" + "\xd6\xca\x89\xd4\xc0\xba\xa5\xaf\x20\xd8\x25\x63\x67\x1f\x8e\x1b" + "\x6e\x72", + .key_len = 66, + .params = /* OID_gostCPSignA */ + "\x30\x13\x06\x07\x2a\x85\x03\x02\x02\x23\x01\x06\x08\x2a\x85\x03" + "\x07\x01\x01\x02\x02", + .param_len = 21, + .c = + "\x2a\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\x92\x10\x2d\x68\x19\x8f\x22\xd5\x60\xeb\x59\xd6\xf3\xe5\x9e\xc2" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + .c_size = 64, + .m = + "\xc3\x9e\xe5\xf3\xd6\x59\xeb\x60\xd5\x22\x8f\x19\x68\x2d\x10\x92" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x2a", + .m_size = 32, + .algo = OID_gost2012PKey256, + .public_key_vec = true, + }, + /* cp256a: Q=-2G, z1 = 5, z2 = 2. */ + { + .key = + "\x04\x40\x95\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\x14\x1e\x9f\x9e\x9c\xc9\xac\x22\xb1\xe3\x23\xdf\x2d\x4f" + "\x29\x35\x76\x2b\x3f\x45\x5a\x50\xdf\x27\xda\x9c\x98\xe0\x71\xe4" + "\x91\x8d", + .key_len = 66, + .params = /* OID_gostCPSignA */ + "\x30\x13\x06\x07\x2a\x85\x03\x02\x02\x23\x01\x06\x08\x2a\x85\x03" + "\x07\x01\x01\x02\x02", + .param_len = 21, + .c = + "\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xb6\x30\x88\x38\x4c\xad\x68\x80\x22\xc2\x0d\x84\xdb\xb0\xdc\x47" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + .c_size = 64, + .m = + "\x49\xdc\xb0\xdb\x84\x0d\xc2\x22\x80\x68\xad\x4c\x38\x88\x30\xb6" + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f", + .m_size = 32, + .algo = OID_gost2012PKey256, + .public_key_vec = true, + }, + /* tc512a: Q=G, z1 = 3, z2 = 1. */ + { + .key = + "\x04\x81\x80\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\xa4\xf2\x15\x52\xcb\x89\xa5\x89\xb8\xf5\x35\xc2\x5f" + "\xfe\x28\x80\xe9\x41\x3a\x0e\xa5\xe6\x75\x3d\xe9\x36\xd0\x4f\xbe" + "\x26\x16\xdf\x21\xa9\xef\xcb\xfd\x64\x80\x77\xc1\xab\xf1\xac\x93" + "\x1c\x5e\xce\xe6\x50\x54\xe2\x16\x88\x1b\xa6\xe3\x6a\x83\x7a\xe8" + "\xcf\x03\x75", + .key_len = 131, + .params = /* OID_gostTC26Sign512A */ + "\x30\x0b\x06\x09\x2a\x85\x03\x07\x01\x02\x01\x02\x01", + .param_len = 13, + .c = + "\xd8\xc0\xd7\xe3\xfb\xa6\xca\xff\x6a\xd1\xb4\xb4\x82\x1d\x15\x6f" + "\xa7\xc7\xbd\x63\x95\xb8\x29\x0d\xd4\xfa\xb1\x1c\x36\xbd\x32\x8d" + "\x1a\xba\xf1\x2e\xbc\x7b\xf2\x02\x96\xf8\xef\x2a\x5e\x72\x64\x86" + "\x67\x62\xfb\x62\x8e\x83\x53\x63\xb7\xe6\x78\x3c\x42\xd7\x0d\x1d" + "\xb7\xbf\xb8\x09\x56\xc8\x67\x00\x31\xba\x19\x19\x29\xf6\x4e\x30" + "\x1d\x68\x16\x34\x23\x6d\x47\xa6\x0e\x57\x1a\x4b\xed\xc0\xef\x25" + "\x74\x52\xef\x78\xb5\xb9\x8d\xbb\x3d\x9f\x31\x29\xd9\x34\x94\x33" + "\xce\x2a\x3a\x35\xcb\x51\x9c\x91\xe2\xd6\x33\xd7\xb3\x73\xae\x16", + .c_size = 128, + .m = + "\x5f\x04\x9d\x6b\x69\x7d\xf7\xe7\xcb\x1b\x81\x2f\x76\xfe\x20\xcd" + "\x2c\xcc\xd0\x74\x63\xfa\x52\x32\x56\xfb\xd3\x3e\xba\xa5\x93\xb3" + "\xd9\x10\x3f\x12\xb4\xe5\xa8\xf1\x59\xb8\x92\xdc\xcb\xe9\x97\xe2" + "\xcf\xb1\x09\xd6\xe6\xe6\x45\xce\xff\x98\x37\xa9\xf6\x47\x40\x48", + .m_size = 64, + .algo = OID_gost2012PKey512, + .public_key_vec = true, + }, + /* tc512a: Q=-G, z1 = 7, z2 = 6. */ + { + .key = + "\x04\x81\x80\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x23\x0b\xea\xad\x34\x76\x5a\x76\x47\x0a\xca\x3d\xa0" + "\x01\xd7\x7f\x16\xbe\xc5\xf1\x5a\x19\x8a\xc2\x16\xc9\x2f\xb0\x41" + "\xd9\xe9\x20\xde\x56\x10\x34\x02\x9b\x7f\x88\x3e\x54\x0e\x53\x6c" + "\xe3\xa1\x31\x19\xaf\xab\x1d\xe9\x77\xe4\x59\x1c\x95\x7c\x85\x17" + "\x30\xfc\x8a", + .key_len = 131, + .params = /* OID_gostTC26Sign512A */ + "\x30\x0b\x06\x09\x2a\x85\x03\x07\x01\x02\x01\x02\x01", + .param_len = 13, + .c = + "\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\x93\xf3\x4a\x99\x7a\x46\xc4\x88\xb7\xf9\x15\xc6\xa7\x02\xb0\x30" + "\x4d\xa5\x9c\x55\xfd\x69\x5c\x2e\xe5\x66\xd8\xa0\x8f\x88\x59\x37" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + .c_size = 128, + .m = + "\x3a\x59\x88\x8f\xa0\xd8\x66\xe5\x2e\x5c\x69\xfd\x55\x9c\xa5\x4d" + "\x30\xb0\x02\xa7\xc6\x15\xf9\xb7\x88\xc4\x46\x7a\x99\x4a\xf3\x93" + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f", + .m_size = 64, + .algo = OID_gost2012PKey512, + .public_key_vec = true, + }, + /* tc512a: Q=-2G, z1 = 5, z2 = 2. */ + { + .key = + "\x04\x81\x80\x7c\x13\xea\xd2\xd9\xaf\x82\xb9\x1f\xb2\xfd\xe1\x8d" + "\xf4\x5b\x37\xe4\xf2\x04\x6a\x2a\x1d\x15\x16\x95\x2a\x5d\x40\xcd" + "\xbb\x34\x44\x2f\x2b\x13\x0a\x47\xb0\xf6\xe5\xa5\x58\x3a\xf4\x54" + "\x09\xb0\x1d\xf5\x5c\xf1\xbf\x9d\x86\xa5\x97\xab\x96\x29\x62\xfc" + "\xdc\x89\x3b\x76\x3d\x50\x6e\x8a\xcf\x02\x4c\x74\x0e\x6e\xe0\x1f" + "\x28\xab\x27\x9b\x20\x02\xc8\xc4\x12\xcb\x8a\xe3\xa4\x27\xce\x39" + "\x62\xdf\x35\x6d\xc1\x65\x7f\x7b\x48\x90\x11\x8f\x19\x7c\x1e\x67" + "\x91\x97\xeb\x90\x85\x25\xfc\x86\xb3\x88\x6e\x5c\x57\x1f\x1d\x1d" + "\x3b\xec\x37", + .key_len = 131, + .params = /* OID_gostTC26Sign512A */ + "\x30\x0b\x06\x09\x2a\x85\x03\x07\x01\x02\x01\x02\x01", + .param_len = 13, + .c = + "\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\x93\xf3\x4a\x99\x7a\x46\xc4\x88\xb7\xf9\x15\xc6\xa7\x02\xb0\x30" + "\x4d\xa5\x9c\x55\xfd\x69\x5c\x2e\xe5\x66\xd8\xa0\x8f\x88\x59\x33" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + .c_size = 128, + .m = + "\x39\x59\x88\x8f\xa0\xd8\x66\xe5\x2e\x5c\x69\xfd\x55\x9c\xa5\x4d" + "\x30\xb0\x02\xa7\xc6\x15\xf9\xb7\x88\xc4\x46\x7a\x99\x4a\xf3\x93" + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f", + .m_size = 64, + .algo = OID_gost2012PKey512, + .public_key_vec = true, + }, }; /* From 4c3ca7c8c152278332590bfd3df1b0f086364759 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 22 Sep 2026 20:11:01 +0200 Subject: [PATCH 120/146] hwrng: intel - return -ENOMEM when ioremap() fails intel_init_hw_struct() incorrectly returns -EBUSY when ioremap() fails. Return -ENOMEM instead. Fixes: c24c95a085c6 ("[PATCH] fix Intel RNG detection") Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/intel-rng.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 5da06ed79e2d..bc4aa9ea1195 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -318,8 +318,8 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, } intel_rng_hw->mem = ioremap(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); - if (intel_rng_hw->mem == NULL) - return -EBUSY; + if (!intel_rng_hw->mem) + return -ENOMEM; return 0; } From 87bb7ce07a212ce4f81bf7bb56b87cfafcd34071 Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Mon, 28 Sep 2026 16:06:56 +0200 Subject: [PATCH 121/146] crypto: caam/qi2 - reset the DPSECI at probe only when enabled Since the commit 060ce5037d5f ("crypto: caam/qi2 - add support for dpseci_reset()") probe resets every DPSECI. On a DPSECI the MC has just created from the DPL, never enabled, MC 10.40.x then logs for each of its queues: [E, qbman_rec_isr:396, QBMAN] QBMAN recoverable event 0x1000000 [E, dpmng_dump_rerr_fqid:1335, QBMAN] REL_FQ (FQ[0]) has 1 messages, dumping up to 16: [W, DPSECI] DPSECI ID[0]: Flush on queue 43 not confirmed That is 16 error lines for an 8-queue DPSECI, at every boot, although there is nothing to flush: a disabled DPSECI has no request in flight. The reset at remove is unchanged. Signed-off-by: Vincent Jardin Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg_qi2.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 6b47bcc16a50..6dccbd3b27a3 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -5041,11 +5041,22 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev) dev_info(dev, "dpseci v%d.%d\n", priv->major_ver, priv->minor_ver); if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) { - err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle); + int enabled; + + err = dpseci_is_enabled(priv->mc_io, 0, ls_dev->mc_handle, + &enabled); if (err) { - dev_err(dev, "dpseci_reset() failed\n"); + dev_err(dev, "dpseci_is_enabled() failed\n"); goto err_get_vers; } + + if (enabled) { + err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle); + if (err) { + dev_err(dev, "dpseci_reset() failed\n"); + goto err_get_vers; + } + } } err = dpseci_get_attributes(priv->mc_io, 0, ls_dev->mc_handle, From b566ebd52eeb661337ef5f52a000528af59479df Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Mon, 28 Sep 2026 16:09:16 +0200 Subject: [PATCH 122/146] crypto: caam/qi,qi2 - set plain_keylen for skcipher descriptors Since the commit 66b9a095f7f9 ("crypto: caam - Add support of paes algorithm") The shared descriptor then loads a zero-length key and the SEC decodes the inlined key bytes as commands. Test: with CONFIG_CRYPTO_SELFTESTS on LX2160A every skcipher but xts fails: dpaa2_caam dpseci.0: 40000307: DECO: desc idx 3: Invalid LOAD Command alg: skcipher: ctr-aes-caam-qi2 encryption failed on test vector 0; expected_error=0, actual_error=-22, cfg="in-place (one sglist)" caamalg_qi.c is compile-tested only. Fixes: 66b9a095f7f9 ("crypto: caam - Add support of paes algorithm") Signed-off-by: Vincent Jardin Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg_qi.c | 2 ++ drivers/crypto/caam/caamalg_qi2.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index aa779caacfe5..2f2682c8bcd8 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -637,6 +637,8 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, ctx->cdata.keylen = keylen; ctx->cdata.key_virt = key; ctx->cdata.key_inline = true; + ctx->cdata.plain_keylen = keylen; + ctx->cdata.key_cmd_opt = 0; /* skcipher encrypt, decrypt shared descriptors */ cnstr_shdsc_skcipher_encap(ctx->sh_desc_enc, &ctx->cdata, ivsize, diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 6dccbd3b27a3..959e7963f161 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -961,6 +961,8 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, ctx->cdata.keylen = keylen; ctx->cdata.key_virt = key; ctx->cdata.key_inline = true; + ctx->cdata.plain_keylen = keylen; + ctx->cdata.key_cmd_opt = 0; /* skcipher_encrypt shared descriptor */ flc = &ctx->flc[ENCRYPT]; From 2b91570f72670054ddae5b11b8c70a79c340014a Mon Sep 17 00:00:00 2001 From: George Abraham P Date: Tue, 29 Sep 2026 14:08:37 +0530 Subject: [PATCH 123/146] crypto: qat - force an edge when re-enabling all VF2PF interrupts VF2PF interrupts are edge-triggered: a source only fires on a masked -> unmasked transition of VM2PF_MSK, not by being unmasked. adf_enable_all_vf2pf_interrupts() does a plain read-modify-write unmask, assuming VM2PF_MSK still holds the all-masked value left by adf_disable_all_vf2pf_interrupts(). That breaks across a device reset: adf_dev_autoreset() (and AER recovery) FLR the PF while VFs stay alive, so a VF can latch a source in VM2PF_SOU with no vectors set up to deliver it. The FLR then resets VM2PF_MSK to its power-on default of 0 (unmasked) without a software write, so the following RMW unmask writes 0 over an already-0 register: no edge occurs and the latched VF2PF message is never delivered. Fix by having adf_enable_all_vf2pf_interrupts() mask all sources immediately before unmasking them, mirroring the idiom already used in adf_gen4_disable_pending_vf2pf_interrupts(), forcing the required edge regardless of the prior state of VM2PF_MSK. Fixes: 575185000539 ("crypto: qat - keep VFs enabled during reset") Signed-off-by: George Abraham P Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_isr.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_isr.c b/drivers/crypto/intel/qat/qat_common/adf_isr.c index 159e91a50106..0df4b398508e 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_isr.c +++ b/drivers/crypto/intel/qat/qat_common/adf_isr.c @@ -70,6 +70,7 @@ void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask) void adf_enable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 num_vfs) { void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev); + struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev); unsigned long flags; u32 vf_mask; @@ -79,7 +80,19 @@ void adf_enable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 num_vf spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags); WRITE_ONCE(accel_dev->pf.vf2pf_disabled, false); - GET_PFVF_OPS(accel_dev)->enable_vf2pf_interrupts(pmisc_addr, vf_mask); + /* + * A VF2PF interrupt is only generated when a source transitions from + * masked to unmasked. A VF may write to its VF2PF CSR while the source + * is masked or while the MSI-X vectors are torn down, for example + * during a device reset, leaving the source latched with no interrupt + * pending. The FLR performed as part of a device reset returns the mask + * register to its default value, which leaves all the sources unmasked, + * so simply unmasking is not guaranteed to be a transition. Mask all the + * sources first, so that unmasking always generates an interrupt for + * the sources latched in the meantime. + */ + pfvf_ops->disable_all_vf2pf_interrupts(pmisc_addr); + pfvf_ops->enable_vf2pf_interrupts(pmisc_addr, vf_mask); spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags); } From 611b15d344ff9c5e5be17e2f76df71feb9f8caa4 Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Tue, 29 Sep 2026 22:29:04 +0200 Subject: [PATCH 124/146] crypto: caam/qi2 - lower the algorithm priority Lower the priority to 100, as done for QAT in commit 8024774190a5 ("crypto: qat - lower priority for skcipher and aead algorithms"). The SEC stays reachable by driver name, and user space can raise its priority through the crypto_user interface. Suggested-by: Herbert Xu Link: https://lore.kernel.org/r/aruvJECCDNdguMdw@gondor.apana.org.au Signed-off-by: Vincent Jardin Reviewed-by: Sahil Malhotra Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg_qi2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 959e7963f161..c95afcb2c751 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -26,7 +26,7 @@ #include #include -#define CAAM_CRA_PRIORITY 2000 +#define CAAM_CRA_PRIORITY 100 /* max key is sum of AES_MAX_KEY_SIZE, max split key size */ #define CAAM_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE + \ From 7d91d0ae0cd94db834a6edafc1ab92e77f812154 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 29 Sep 2026 23:37:50 +0200 Subject: [PATCH 125/146] hwrng: atmel - use HZ_PER_MHZ in atmel_trng_init() Combine and inline the rate check to simplify the code. Drop the local rate variable and use HZ_PER_MHZ instead of the hard-coded frequency. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/atmel-rng.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index 06e79d516743..fe444196e6b3 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -17,6 +17,7 @@ #include #include #include +#include #define TRNG_CR 0x00 #define TRNG_MR 0x04 @@ -85,20 +86,14 @@ out: static int atmel_trng_init(struct atmel_trng *trng) { - unsigned long rate; int ret; ret = clk_prepare_enable(trng->clk); if (ret) return ret; - if (trng->has_half_rate) { - rate = clk_get_rate(trng->clk); - - /* if peripheral clk is above 100MHz, set HALFR */ - if (rate > 100000000) - writel(TRNG_HALFR, trng->base + TRNG_MR); - } + if (trng->has_half_rate && clk_get_rate(trng->clk) > 100 * HZ_PER_MHZ) + writel(TRNG_HALFR, trng->base + TRNG_MR); writel(TRNG_KEY | 1, trng->base + TRNG_CR); From c01d396a91e4ce0e8a5017dcc7207cdca0e756bd Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Thu, 1 Oct 2026 13:28:41 +0100 Subject: [PATCH 126/146] crypto: qat - remove unused get_num_accels() The get_num_accels() hook in struct adf_hw_device_data has had no callers since commit d237230728c5 ("crypto: qat - remove unused character device and IOCTLs"), which deleted its last user in adf_ctl_drv.c. Every device driver still populates it and two implementations are still exported, all of it dead code. Remove the hook, its generation-level implementations adf_gen2_get_num_accels() and adf_gen4_get_num_accels(), the per-device static implementations and all the assignments. The hw_data->num_accel field is left untouched as it is still used. Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c | 1 - drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c | 1 - drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c | 6 ------ drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c | 1 - .../crypto/intel/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c | 6 ------ drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c | 1 - drivers/crypto/intel/qat/qat_c62xvf/adf_c62xvf_hw_data.c | 6 ------ drivers/crypto/intel/qat/qat_common/adf_accel_devices.h | 1 - drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.c | 9 --------- drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.h | 1 - drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c | 6 ------ drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h | 1 - .../crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 1 - .../intel/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c | 6 ------ 14 files changed, 47 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c index 19f9f738630b..d6f1f626cf5a 100644 --- a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c +++ b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c @@ -443,7 +443,6 @@ void adf_init_hw_data_420xx(struct adf_hw_device_data *hw_data, u32 dev_id) hw_data->enable_error_correction = adf_gen4_enable_error_correction; hw_data->get_accel_mask = adf_gen4_get_accel_mask; hw_data->get_ae_mask = get_ae_mask; - hw_data->get_num_accels = adf_gen4_get_num_accels; hw_data->get_num_aes = adf_gen4_get_num_aes; hw_data->get_sram_bar_id = adf_gen4_get_sram_bar_id; hw_data->get_etr_bar_id = adf_gen4_get_etr_bar_id; diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c index 49b425be34c8..7d9dd44ca477 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c @@ -412,7 +412,6 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id) hw_data->enable_error_correction = adf_gen4_enable_error_correction; hw_data->get_accel_mask = adf_gen4_get_accel_mask; hw_data->get_ae_mask = get_ae_mask; - hw_data->get_num_accels = adf_gen4_get_num_accels; hw_data->get_num_aes = adf_gen4_get_num_aes; hw_data->get_sram_bar_id = adf_gen4_get_sram_bar_id; hw_data->get_etr_bar_id = adf_gen4_get_etr_bar_id; diff --git a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c index 388087e64540..ca9bc5dccf67 100644 --- a/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c +++ b/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c @@ -326,11 +326,6 @@ static u32 get_accel_mask(struct adf_hw_device_data *self) return ADF_GEN6_ACCELERATORS_MASK; } -static u32 get_num_accels(struct adf_hw_device_data *self) -{ - return ADF_GEN6_MAX_ACCELERATORS; -} - static u32 get_num_aes(struct adf_hw_device_data *self) { return self ? hweight32(self->ae_mask) : 0; @@ -1023,7 +1018,6 @@ void adf_init_hw_data_6xxx(struct adf_hw_device_data *hw_data) hw_data->enable_error_correction = enable_error_correction; hw_data->get_accel_mask = get_accel_mask; hw_data->get_ae_mask = get_ae_mask; - hw_data->get_num_accels = get_num_accels; hw_data->get_num_aes = get_num_aes; hw_data->get_sram_bar_id = get_sram_bar_id; hw_data->get_etr_bar_id = get_etr_bar_id; diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c index 07f2c42a68f5..b9cc6c97778a 100644 --- a/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c +++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c @@ -129,7 +129,6 @@ void adf_init_hw_data_c3xxx(struct adf_hw_device_data *hw_data) hw_data->get_accel_mask = get_accel_mask; hw_data->get_ae_mask = get_ae_mask; hw_data->get_accel_cap = adf_gen2_get_accel_cap; - hw_data->get_num_accels = adf_gen2_get_num_accels; hw_data->get_num_aes = adf_gen2_get_num_aes; hw_data->get_sram_bar_id = get_sram_bar_id; hw_data->get_etr_bar_id = get_etr_bar_id; diff --git a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c index db3c33fa1881..8a5cce516436 100644 --- a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c +++ b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c @@ -24,11 +24,6 @@ static u32 get_ae_mask(struct adf_hw_device_data *self) return ADF_C3XXXIOV_ACCELENGINES_MASK; } -static u32 get_num_accels(struct adf_hw_device_data *self) -{ - return ADF_C3XXXIOV_MAX_ACCELERATORS; -} - static u32 get_num_aes(struct adf_hw_device_data *self) { return ADF_C3XXXIOV_MAX_ACCELENGINES; @@ -80,7 +75,6 @@ void adf_init_hw_data_c3xxxiov(struct adf_hw_device_data *hw_data) hw_data->disable_iov = adf_vf2pf_notify_shutdown; hw_data->get_accel_mask = get_accel_mask; hw_data->get_ae_mask = get_ae_mask; - hw_data->get_num_accels = get_num_accels; hw_data->get_num_aes = get_num_aes; hw_data->get_etr_bar_id = get_etr_bar_id; hw_data->get_misc_bar_id = get_misc_bar_id; diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c b/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c index 0b410b41474d..aed1c951754a 100644 --- a/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c +++ b/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c @@ -131,7 +131,6 @@ void adf_init_hw_data_c62x(struct adf_hw_device_data *hw_data) hw_data->get_accel_mask = get_accel_mask; hw_data->get_ae_mask = get_ae_mask; hw_data->get_accel_cap = adf_gen2_get_accel_cap; - hw_data->get_num_accels = adf_gen2_get_num_accels; hw_data->get_num_aes = adf_gen2_get_num_aes; hw_data->get_sram_bar_id = get_sram_bar_id; hw_data->get_etr_bar_id = get_etr_bar_id; diff --git a/drivers/crypto/intel/qat/qat_c62xvf/adf_c62xvf_hw_data.c b/drivers/crypto/intel/qat/qat_c62xvf/adf_c62xvf_hw_data.c index 7f00035d3661..ded32eaae48d 100644 --- a/drivers/crypto/intel/qat/qat_c62xvf/adf_c62xvf_hw_data.c +++ b/drivers/crypto/intel/qat/qat_c62xvf/adf_c62xvf_hw_data.c @@ -24,11 +24,6 @@ static u32 get_ae_mask(struct adf_hw_device_data *self) return ADF_C62XIOV_ACCELENGINES_MASK; } -static u32 get_num_accels(struct adf_hw_device_data *self) -{ - return ADF_C62XIOV_MAX_ACCELERATORS; -} - static u32 get_num_aes(struct adf_hw_device_data *self) { return ADF_C62XIOV_MAX_ACCELENGINES; @@ -80,7 +75,6 @@ void adf_init_hw_data_c62xiov(struct adf_hw_device_data *hw_data) hw_data->disable_iov = adf_vf2pf_notify_shutdown; hw_data->get_accel_mask = get_accel_mask; hw_data->get_ae_mask = get_ae_mask; - hw_data->get_num_accels = get_num_accels; hw_data->get_num_aes = get_num_aes; hw_data->get_etr_bar_id = get_etr_bar_id; hw_data->get_misc_bar_id = get_misc_bar_id; diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h index a84380125fe5..b77f461e8583 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h +++ b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h @@ -279,7 +279,6 @@ struct adf_hw_device_data { u32 (*get_misc_bar_id)(struct adf_hw_device_data *self); u32 (*get_etr_bar_id)(struct adf_hw_device_data *self); u32 (*get_num_aes)(struct adf_hw_device_data *self); - u32 (*get_num_accels)(struct adf_hw_device_data *self); void (*get_arb_info)(struct arb_info *arb_csrs_info); void (*get_admin_info)(struct admin_info *admin_csrs_info); enum dev_sku_info (*get_sku)(struct adf_hw_device_data *self); diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.c b/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.c index 6a505e9a5cf9..bff89c8538f0 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.c +++ b/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.c @@ -7,15 +7,6 @@ #include "icp_qat_hw.h" #include -u32 adf_gen2_get_num_accels(struct adf_hw_device_data *self) -{ - if (!self || !self->accel_mask) - return 0; - - return hweight16(self->accel_mask); -} -EXPORT_SYMBOL_GPL(adf_gen2_get_num_accels); - u32 adf_gen2_get_num_aes(struct adf_hw_device_data *self) { if (!self || !self->ae_mask) diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.h b/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.h index 59bad368a921..3caeb1d178cf 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.h +++ b/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.h @@ -78,7 +78,6 @@ #define ADF_GEN2_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) #define ADF_GEN2_SMIA1_MASK 0x1 -u32 adf_gen2_get_num_accels(struct adf_hw_device_data *self); u32 adf_gen2_get_num_aes(struct adf_hw_device_data *self); void adf_gen2_enable_error_correction(struct adf_accel_dev *accel_dev); void adf_gen2_cfg_iov_thds(struct adf_accel_dev *accel_dev, bool enable, diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c index f4a58f04071a..d9a0ed7eee3d 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c @@ -21,12 +21,6 @@ u32 adf_gen4_get_accel_mask(struct adf_hw_device_data *self) } EXPORT_SYMBOL_GPL(adf_gen4_get_accel_mask); -u32 adf_gen4_get_num_accels(struct adf_hw_device_data *self) -{ - return ADF_GEN4_MAX_ACCELERATORS; -} -EXPORT_SYMBOL_GPL(adf_gen4_get_num_accels); - u32 adf_gen4_get_num_aes(struct adf_hw_device_data *self) { if (!self || !self->ae_mask) diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h index cd26b6724c43..46dfa23d825f 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h @@ -157,7 +157,6 @@ void adf_gen4_get_arb_info(struct arb_info *arb_info); u32 adf_gen4_get_etr_bar_id(struct adf_hw_device_data *self); u32 adf_gen4_get_heartbeat_clock(struct adf_hw_device_data *self); u32 adf_gen4_get_misc_bar_id(struct adf_hw_device_data *self); -u32 adf_gen4_get_num_accels(struct adf_hw_device_data *self); u32 adf_gen4_get_num_aes(struct adf_hw_device_data *self); enum dev_sku_info adf_gen4_get_sku(struct adf_hw_device_data *self); u32 adf_gen4_get_sram_bar_id(struct adf_hw_device_data *self); diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c index 5b4bd0ba1ccb..c318015fc2e2 100644 --- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c +++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c @@ -229,7 +229,6 @@ void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data) hw_data->get_accel_mask = get_accel_mask; hw_data->get_ae_mask = get_ae_mask; hw_data->get_accel_cap = get_accel_cap; - hw_data->get_num_accels = adf_gen2_get_num_accels; hw_data->get_num_aes = adf_gen2_get_num_aes; hw_data->get_etr_bar_id = get_etr_bar_id; hw_data->get_misc_bar_id = get_misc_bar_id; diff --git a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c index 828456c43b76..6fd5bb333859 100644 --- a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c +++ b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c @@ -24,11 +24,6 @@ static u32 get_ae_mask(struct adf_hw_device_data *self) return ADF_DH895XCCIOV_ACCELENGINES_MASK; } -static u32 get_num_accels(struct adf_hw_device_data *self) -{ - return ADF_DH895XCCIOV_MAX_ACCELERATORS; -} - static u32 get_num_aes(struct adf_hw_device_data *self) { return ADF_DH895XCCIOV_MAX_ACCELENGINES; @@ -80,7 +75,6 @@ void adf_init_hw_data_dh895xcciov(struct adf_hw_device_data *hw_data) hw_data->disable_iov = adf_vf2pf_notify_shutdown; hw_data->get_accel_mask = get_accel_mask; hw_data->get_ae_mask = get_ae_mask; - hw_data->get_num_accels = get_num_accels; hw_data->get_num_aes = get_num_aes; hw_data->get_etr_bar_id = get_etr_bar_id; hw_data->get_misc_bar_id = get_misc_bar_id; From 0d69de38873ee5eb39994244773cdba6b119e375 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 1 Oct 2026 17:06:04 +0200 Subject: [PATCH 127/146] hwrng: cctrng - drop redundant initializations The variables are reassigned before their initial values are read - drop the redundant initializations. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/cctrng.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c index 51290ea345c3..be35f058f37a 100644 --- a/drivers/char/hw_random/cctrng.c +++ b/drivers/char/hw_random/cctrng.c @@ -91,7 +91,7 @@ static int cc_trng_pm_get(struct device *dev) static void cc_trng_pm_put_suspend(struct device *dev) { - int rc = 0; + int rc; rc = pm_runtime_put_autosuspend(dev); if (rc) @@ -208,7 +208,7 @@ static int cctrng_read(struct hwrng *rng, void *data, size_t max, bool wait) struct cctrng_drvdata *drvdata = (struct cctrng_drvdata *)rng->priv; struct device *dev = &(drvdata->pdev->dev); u32 *buf = (u32 *)drvdata->circ.buf; - size_t copied = 0; + size_t copied; size_t cnt_w; size_t size; size_t left; @@ -268,7 +268,7 @@ static int cctrng_read(struct hwrng *rng, void *data, size_t max, bool wait) static void cc_trng_hw_trigger(struct cctrng_drvdata *drvdata) { - u32 tmp_smpl_cnt = 0; + u32 tmp_smpl_cnt; struct device *dev = &(drvdata->pdev->dev); dev_dbg(dev, "cctrng hw trigger.\n"); @@ -309,8 +309,8 @@ static void cc_trng_hw_trigger(struct cctrng_drvdata *drvdata) static void cc_trng_compwork_handler(struct work_struct *w) { - u32 isr = 0; - u32 ehr_valid = 0; + u32 isr; + u32 ehr_valid; struct cctrng_drvdata *drvdata = container_of(w, struct cctrng_drvdata, compwork); struct device *dev = &(drvdata->pdev->dev); @@ -453,7 +453,7 @@ static int cctrng_probe(struct platform_device *pdev) { struct cctrng_drvdata *drvdata; struct device *dev = &pdev->dev; - int rc = 0; + int rc; u32 val; int irq; From 3d68bdcf0d747dd5a2fad8e011dffbb1bd776f43 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 1 Oct 2026 23:04:48 +0200 Subject: [PATCH 128/146] hwrng: stm32 - use swap() in stm32_rng_probe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use swap() to simplify stm32_rng_probe(). Signed-off-by: Thorsten Blum Acked-by: Maxime Méré Signed-off-by: Herbert Xu --- drivers/char/hw_random/stm32-rng.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index f5bfe54c01dc..9114efc90d1c 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -569,18 +569,11 @@ static int stm32_rng_probe(struct platform_device *ofdev) return dev_err_probe(dev, -EINVAL, "Failed to get clocks: %d\n", ret); if (priv->data->nb_clock == 2) { - const char *id = priv->clk_bulk[1].id; - struct clk *clk = priv->clk_bulk[1].clk; - if (!priv->clk_bulk[0].id || !priv->clk_bulk[1].id) return dev_err_probe(dev, -EINVAL, "Missing clock name\n"); - if (strcmp(priv->clk_bulk[0].id, "core")) { - priv->clk_bulk[1].id = priv->clk_bulk[0].id; - priv->clk_bulk[1].clk = priv->clk_bulk[0].clk; - priv->clk_bulk[0].id = id; - priv->clk_bulk[0].clk = clk; - } + if (strcmp(priv->clk_bulk[0].id, "core")) + swap(priv->clk_bulk[0], priv->clk_bulk[1]); } pm_runtime_set_autosuspend_delay(dev, 100); From 70f49f55a15ea3028403c970d356f86d7fa9cff1 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 1 Oct 2026 23:16:10 +0200 Subject: [PATCH 129/146] hwrng: stm32 - reuse clock rate in stm32_rng_clock_freq_restrain() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reuse clock_rate and avoid calling clk_get_rate() again. Remove the extra space before the colon while at it. Signed-off-by: Thorsten Blum acked-by: Maxime Méré Signed-off-by: Herbert Xu --- drivers/char/hw_random/stm32-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index 9114efc90d1c..bcec6f0b9bb1 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -277,7 +277,7 @@ static uint stm32_rng_clock_freq_restrain(struct hwrng *rng) while ((clock_rate >> clock_div) > priv->data->max_clock_rate) clock_div++; - pr_debug("RNG clk rate : %lu\n", clk_get_rate(priv->clk_bulk[0].clk) >> clock_div); + pr_debug("RNG clk rate: %lu\n", clock_rate >> clock_div); return clock_div; } From aa2c03d3726c9e93554d7071d55d2f4a35e2481a Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 2 Oct 2026 16:19:51 +0200 Subject: [PATCH 130/146] hwrng: amd - simplify control flow in amd_rng_mod_init() Replace the goto found statement with a break and check pdev after the loop. Also consolidate the cleanup paths. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/amd-rng.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c index ac2d257793bf..fb5422612182 100644 --- a/drivers/char/hw_random/amd-rng.c +++ b/drivers/char/hw_random/amd-rng.c @@ -129,19 +129,15 @@ static int __init amd_rng_mod_init(void) { int err; struct pci_dev *pdev = NULL; - const struct pci_device_id *ent; u32 pmbase; struct amd768_priv *priv; - for_each_pci_dev(pdev) { - ent = pci_match_id(pci_tbl, pdev); - if (ent) - goto found; - } - /* Device not found. */ - return -ENODEV; + for_each_pci_dev(pdev) + if (pci_match_id(pci_tbl, pdev)) + break; + if (!pdev) + return -ENODEV; -found: err = pci_read_config_dword(pdev, 0x58, &pmbase); if (err) { err = pcibios_err_to_errno(err); @@ -171,7 +167,7 @@ found: if (!priv->iobase) { pr_err(DRV_NAME "Cannot map ioport\n"); err = -EINVAL; - goto err_iomap; + goto err; } amd_rng.priv = (unsigned long)priv; @@ -182,13 +178,12 @@ found: err = hwrng_register(&amd_rng); if (err) { pr_err(DRV_NAME " registering failed (%d)\n", err); - goto err_hwrng; + ioport_unmap(priv->iobase); + goto err; } return 0; -err_hwrng: - ioport_unmap(priv->iobase); -err_iomap: +err: release_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE); out: kfree(priv); From 378bbe625babd6860583f574d0697008170ab51f Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 2 Oct 2026 16:35:53 +0200 Subject: [PATCH 131/146] hwrng: stm32 - drop redundant initializations The variables are reassigned before their initial values are read - drop the redundant initializations. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/stm32-rng.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index bcec6f0b9bb1..e44e6e623808 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -156,7 +156,7 @@ end: */ static int stm32_rng_conceal_seed_error_sw_reset(struct stm32_rng_private *priv) { - unsigned int i = 0; + unsigned int i; u32 sr = readl_relaxed(priv->base + RNG_SR); writel_relaxed(sr & ~RNG_SR_SEIS, priv->base + RNG_SR); @@ -187,7 +187,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) { struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); unsigned int i = 0; - int retval = 0, err = 0; + int retval, err; u32 sr; retval = pm_runtime_resume_and_get(priv->dev); @@ -264,7 +264,7 @@ static uint stm32_rng_clock_freq_restrain(struct hwrng *rng) { struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); - unsigned long clock_rate = 0; + unsigned long clock_rate; uint clock_div = 0; clock_rate = clk_get_rate(priv->clk_bulk[0].clk); From 2fbde5f4981be8bf0db5b565a1c67515af65bc50 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 2 Oct 2026 16:48:38 +0200 Subject: [PATCH 132/146] hwrng: stm32 - use devm_platform_ioremap_resource() in stm32_rng_probe() The resource pointer is unused - use devm_platform_ioremap_resource() and remove the unnecessary local variable. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/stm32-rng.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index e44e6e623808..739263eb56ba 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -528,14 +528,13 @@ static int stm32_rng_probe(struct platform_device *ofdev) struct device *dev = &ofdev->dev; struct device_node *np = ofdev->dev.of_node; struct stm32_rng_private *priv; - struct resource *res; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - priv->base = devm_platform_get_and_ioremap_resource(ofdev, 0, &res); + priv->base = devm_platform_ioremap_resource(ofdev, 0); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); From 656cf38b96b659dcc937e6a82ce209d3ed0641f6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 2 Oct 2026 14:50:19 -0700 Subject: [PATCH 133/146] crypto: sa2ul - Remove unused fields Remove the shash, authkey, and auth fields from sa_tfm_ctx since they have no purpose and create confusion with fields that actually matter. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- drivers/crypto/sa2ul.c | 9 --------- drivers/crypto/sa2ul.h | 3 --- 2 files changed, 12 deletions(-) diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c index b014350a3da0..4557eae94164 100644 --- a/drivers/crypto/sa2ul.c +++ b/drivers/crypto/sa2ul.c @@ -1388,7 +1388,6 @@ static int sa_sha_run(struct ahash_request *req) static int sa_sha_setup(struct sa_tfm_ctx *ctx, struct algo_data *ad) { - int bs = crypto_shash_blocksize(ctx->shash); int cmdl_len; struct sa_cmdl_cfg cfg; @@ -1396,7 +1395,6 @@ static int sa_sha_setup(struct sa_tfm_ctx *ctx, struct algo_data *ad) ad->auth_eng.eng_id = SA_ENG_ID_AM1; ad->auth_eng.sc_size = SA_CTX_AUTH_TYPE2_SZ; - memset(ctx->authkey, 0, bs); memset(&cfg, 0, sizeof(cfg)); cfg.aalg = ad->aalg_id; cfg.enc_eng_id = ad->enc_eng.eng_id; @@ -1439,12 +1437,6 @@ static int sa_sha_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base) return ret; if (alg_base) { - ctx->shash = crypto_alloc_shash(alg_base, 0, 0); - if (IS_ERR(ctx->shash)) { - dev_err(sa_k3_dev, "base driver %s couldn't be loaded\n", - alg_base); - return PTR_ERR(ctx->shash); - } /* for fallback */ ctx->fallback.ahash = crypto_alloc_ahash(alg_base, 0, CRYPTO_ALG_ASYNC); @@ -1599,7 +1591,6 @@ static void sa_sha_cra_exit(struct crypto_tfm *tfm) if (crypto_tfm_alg_type(tfm) == CRYPTO_ALG_TYPE_AHASH) sa_free_ctx_info(&ctx->enc, data); - crypto_free_shash(ctx->shash); crypto_free_ahash(ctx->fallback.ahash); } diff --git a/drivers/crypto/sa2ul.h b/drivers/crypto/sa2ul.h index 12c17a68d350..211ef4e40f22 100644 --- a/drivers/crypto/sa2ul.h +++ b/drivers/crypto/sa2ul.h @@ -307,12 +307,9 @@ struct sa_tfm_ctx { struct sa_crypto_data *dev_data; struct sa_ctx_info enc; struct sa_ctx_info dec; - struct sa_ctx_info auth; int keylen; int iv_idx; u32 key[AES_KEYSIZE_256 / sizeof(u32)]; - u8 authkey[SHA512_BLOCK_SIZE]; - struct crypto_shash *shash; /* for fallback */ union { struct crypto_skcipher *skcipher; From 80fb9a85807177d3ca64746d59a68b1c6e8f20a6 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Sat, 3 Oct 2026 10:03:02 -0600 Subject: [PATCH 134/146] crypto: algif_hash - Allow hmac(sha512) for unpriviledged users By default users cannot run sha512hmac with the current set up. This is problematic because our kernel builds call this for FIPS compliance. Rather than have anyone turn off af_alg_restrict all together, let's allow a common use case. Signed-off-by: Justin M. Forbes Signed-off-by: Herbert Xu --- crypto/algif_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 6e8b5fb82a7f..0d3ec5760de6 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -23,7 +23,7 @@ static const struct af_alg_allowlist_entry hash_allowlist[] = { { "hmac(sha224)" }, /* iwd */ { "hmac(sha256)" }, /* iwd */ { "hmac(sha384)" }, /* iwd */ - { "hmac(sha512)" }, /* iwd, sha512hmac */ + { "hmac(sha512)", AF_ALG_UNPRIVILEGED }, /* iwd, sha512hmac */ { "md4" }, /* iwd */ { "md5" }, /* iwd */ { "sha1", AF_ALG_UNPRIVILEGED }, /* iwd, iproute2 < 7.0 */ From 2f90facc7b94934653eb7ebfadcc25d503b89196 Mon Sep 17 00:00:00 2001 From: Daehyeon Ko <4ncienth@gmail.com> Date: Sun, 4 Oct 2026 14:09:46 +0900 Subject: [PATCH 135/146] crypto: algif_skcipher - rewind rounded output bytes af_alg_get_rsgl() advances the receive iterator by the unrounded RX scatterlist length. For a continuing skcipher request, _skcipher_recvmsg() then rounds its local length down to a whole chunksize without restoring the iterator. A later chunk starts after bytes which the provider never wrote, while the syscall returns only the processed length. When copy_splice_read() supplies non-zeroed pages and publishes that return as a dense prefix, the gap exposes stale bytes from a previous page lifetime. With unprivileged xts(aes), a 31-byte MSG_MORE request followed by one final byte advances a 47-byte destination while returning 32 bytes. A hardened v7.2-rc5 image retained all 15 seeded stale bytes in 4,829 of 4,829 records. With init_on_alloc enabled, all 72,345 gap bytes observed were zero. Rewind the iterator by the tail excluded during rounding, before rejecting a zero processed length. The crypto request uses only the rounded length; af_alg_free_resources() releases the entire RX list before another receive iteration. The fixed target-like kernel returned byte-identical dense 48-byte output in 4,771 of 4,771 rounds. The unmodified kernel returned the vulnerable 32-byte short record in 2,409 of 2,409 rounds. Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Daehyeon Ko <4ncienth@gmail.com> Signed-off-by: Herbert Xu --- crypto/algif_skcipher.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 1e61fe6e24b9..291dbd698932 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -135,12 +135,16 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, * full block size buffers. */ if (ctx->more || len < ctx->used) { - if (len < bs) { + size_t excess = len % bs; + + len -= excess; + iov_iter_revert(&msg->msg_iter, excess); + + if (!len) { err = -EINVAL; goto free; } - len -= len % bs; cflags |= CRYPTO_SKCIPHER_REQ_NOTFINAL; } From 666d66df25253070cb297cb920b0bcfcfe5eb871 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 4 Oct 2026 14:50:42 -0700 Subject: [PATCH 136/146] crypto: talitos - init tasklets before requesting IRQs The talitos interrupt handlers schedule priv->done_task[] via tasklet_schedule(). Since the second IRQ support, probe has requested the IRQs before calling tasklet_init(), so an interrupt already pending when a line is requested, e.g. engine state left by the bootloader or a kexec'd kernel, would schedule a tasklet with a NULL callback. Look up the IRQ numbers and map the registers up front, so that -EPROBE_DEFER returns before anything is allocated and the done_task[] selection and reset_device() can see the secondary IRQ. Only request the IRQs once the channel fifos are allocated and init_device() has reset the engine. This matches remove(), which frees the IRQs before killing the tasklets. remove() frees every IRQ number that is > 0, so make sure that only requested lines are set when it runs from the probe error path: clear both numbers when probe fails before the request, and clear any line talitos_probe_irq() did not request. Previously a failed primary request in the two-IRQ case freed the never-requested secondary line. Fixes: c3e337f88a5b ("crypto: talitos - support for channel remap and 2nd IRQ") Assisted-by: LLM Signed-off-by: Rosen Penev Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 54 ++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 41a87d7c30a0..c7d9ce2905be 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -3353,21 +3353,13 @@ static int talitos_probe_irq(struct platform_device *ofdev) int err; bool is_sec1 = has_ftr_sec1(priv); - 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), priv); goto primary_out; } - priv->irq[1] = platform_get_irq_optional(ofdev, 1); - if (priv->irq[1] == -EPROBE_DEFER) - return priv->irq[1]; - - /* get the primary irq line */ + /* single (or primary) irq line */ if (priv->irq[1] < 0) { err = request_irq(priv->irq[0], talitos2_interrupt_4ch, 0, dev_driver_string(dev), priv); @@ -3379,7 +3371,7 @@ static int talitos_probe_irq(struct platform_device *ofdev) if (err) goto primary_out; - /* get the secondary irq line */ + /* secondary irq line */ err = request_irq(priv->irq[1], talitos2_interrupt_ch1_3, 0, dev_driver_string(dev), priv); if (err) { @@ -3392,7 +3384,9 @@ static int talitos_probe_irq(struct platform_device *ofdev) primary_out: if (err) { dev_err(dev, "failed to request primary irq\n"); + /* neither line is requested, keep remove() from freeing them */ priv->irq[0] = 0; + priv->irq[1] = 0; } return err; @@ -3404,12 +3398,27 @@ static int talitos_probe(struct platform_device *ofdev) struct device_node *np = ofdev->dev.of_node; struct talitos_private *priv; unsigned int num_channels; + void __iomem *reg; int i, err; int stride; + int irq0; + int irq1; if (of_property_read_u32(np, "fsl,num-channels", &num_channels)) return -EINVAL; + irq0 = platform_get_irq(ofdev, 0); + if (irq0 < 0) + return irq0; + + irq1 = platform_get_irq_optional(ofdev, 1); + if (irq1 == -EPROBE_DEFER) + return irq1; + + reg = devm_platform_ioremap_resource(ofdev, 0); + if (IS_ERR(reg)) + return PTR_ERR(reg); + priv = devm_kzalloc(dev, struct_size(priv, chan, num_channels), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -3425,12 +3434,7 @@ static int talitos_probe(struct platform_device *ofdev) spin_lock_init(&priv->reg_lock); - priv->reg = devm_platform_ioremap_resource(ofdev, 0); - if (IS_ERR(priv->reg)) { - dev_err(dev, "failed to of_iomap\n"); - err = PTR_ERR(priv->reg); - goto err_out; - } + priv->reg = reg; /* get SEC version capabilities from device tree */ of_property_read_u32(np, "fsl,channel-fifo-len", &priv->chfifo_len); @@ -3481,9 +3485,7 @@ static int talitos_probe(struct platform_device *ofdev) stride = TALITOS2_CH_STRIDE; } - err = talitos_probe_irq(ofdev); - if (err) - goto err_out; + priv->irq[0] = irq0; if (has_ftr_sec1(priv)) { if (priv->num_channels == 1) @@ -3493,6 +3495,7 @@ static int talitos_probe(struct platform_device *ofdev) tasklet_init(&priv->done_task[0], talitos1_done_4ch, (unsigned long)dev); } else { + priv->irq[1] = irq1; if (priv->irq[1] > 0) { tasklet_init(&priv->done_task[0], talitos2_done_ch0_2, (unsigned long)dev); @@ -3524,7 +3527,7 @@ static int talitos_probe(struct platform_device *ofdev) if (!priv->chan[i].fifo) { dev_err(dev, "failed to allocate request fifo %d\n", i); err = -ENOMEM; - goto err_out; + goto err_noirq; } atomic_set(&priv->chan[i].submit_count, @@ -3537,9 +3540,14 @@ static int talitos_probe(struct platform_device *ofdev) err = init_device(dev); if (err) { dev_err(dev, "failed to initialize device\n"); - goto err_out; + goto err_noirq; } + /* enable interrupts once the channel fifos and tasklets are set up */ + err = talitos_probe_irq(ofdev); + if (err) + goto err_out; + /* register the RNG, if available */ if (hw_supports(dev, DESC_HDR_SEL0_RNG)) { err = talitos_register_rng(dev); @@ -3597,6 +3605,10 @@ static int talitos_probe(struct platform_device *ofdev) return 0; +err_noirq: + /* the irq numbers are known, but the lines are not requested yet */ + priv->irq[0] = 0; + priv->irq[1] = 0; err_out: talitos_remove(ofdev); From 9260491bbfa6037067ca02002ff0f6195efaea4f Mon Sep 17 00:00:00 2001 From: Jean-Michel Hautbois Date: Wed, 26 Nov 2025 08:08:09 +0100 Subject: [PATCH 137/146] hwrng: imx-rngc - Use optional clock Change devm_clk_get() to devm_clk_get_optional() to support platforms where the RNG clock is always enabled and not exposed via the clock framework (such as ColdFire MCF54418). Reviewed-by: Frank Li Signed-off-by: Jean-Michel Hautbois Reviewed-by: Martin Kaiser Acked-by: Herbert Xu Signed-off-by: Herbert Xu --- drivers/char/hw_random/imx-rngc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index 0545a1870146..a09532384b9f 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -258,7 +258,7 @@ static int __init imx_rngc_probe(struct platform_device *pdev) if (IS_ERR(rngc->base)) return PTR_ERR(rngc->base); - rngc->clk = devm_clk_get(&pdev->dev, NULL); + rngc->clk = devm_clk_get_optional(&pdev->dev, NULL); if (IS_ERR(rngc->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(rngc->clk), "Cannot get rng_clk\n"); From 4ad7c1bd5f3dcd3fd6efbb068d6ee2a68dddfece Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Tue, 6 Oct 2026 16:06:47 +0100 Subject: [PATCH 138/146] crypto: qat - initialise state_lock on every path in adf_devmgr_add_dev() state_lock is initialised at the end of adf_devmgr_add_dev(), but the VF on host path whose id mapping already exists returns earlier via 'goto unlock'. That mapping outlives the VF, so this path is taken every time a VF is recreated on a BDF that already hosted one, e.g.: echo 0 > sriov_numvfs echo 32 > sriov_numvfs accel_dev is freshly allocated on each probe, so state_lock is left zeroed and adf_dev_up() takes an uninitialised mutex. With CONFIG_DEBUG_MUTEXES this is reported on a dh895xcc with 32 host-bound VFs: DEBUG_LOCKS_WARN_ON(lock->magic != lock) WARNING: kernel/locking/mutex.c:159 at mutex_lock+0x171/0x1c0 Call Trace: adf_dev_up+0x27/0xe0 [intel_qat] adf_probe+0x700/0xa80 [qat_dh895xccvf] local_pci_probe+0xd5/0x190 The same happens on teardown when adf_dev_down() locks it again. Initialise the lock next to the other per-device state, before the tables are updated, so it is done on every path. Fixes: 1bdc85550a2b ("crypto: qat - fix concurrency issue when device state changes") Cc: stable@vger.kernel.org Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c index 161863841a52..26b40dd59965 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c +++ b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c @@ -137,6 +137,7 @@ int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, mutex_lock(&table_lock); atomic_set(&accel_dev->ref_count, 0); + mutex_init(&accel_dev->state_lock); /* PF on host or VF on guest - optimized to remove redundant is_vf */ if (!accel_dev->is_vf || !pf) { @@ -210,7 +211,6 @@ int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, map->attached = true; list_add_tail(&map->list, &vfs_table); } - mutex_init(&accel_dev->state_lock); unlock: mutex_unlock(&table_lock); return ret; From 4921634ac0a9a65aaa5e41308aabda3d3f562ee3 Mon Sep 17 00:00:00 2001 From: Ahsan Atta Date: Tue, 6 Oct 2026 16:06:48 +0100 Subject: [PATCH 139/146] crypto: qat - fix use of destroyed vf2pf_lock on VF restart adf_dev_stop_async() sends the RESTARTING_COMPLETE message after adf_dev_down() has returned, but adf_dev_down() already destroyed the lock that message takes. Both run in sequence in the same worker, so every PF restart locks a destroyed mutex. With CONFIG_DEBUG_MUTEXES on a dh895xcc with 32 host-bound VFs this trips on the first PF reset: DEBUG_LOCKS_WARN_ON(lock->magic != lock) WARNING: kernel/locking/mutex.c:159 at mutex_lock+0x171/0x1c0 Workqueue: adf_vf_stop_wq adf_dev_stop_async [intel_qat] Call Trace: adf_gen2_pfvf_send+0x210/0x530 [intel_qat] adf_vf2pf_notify_restart_complete+0x55/0x80 [intel_qat] adf_dev_stop_async+0xdb/0x140 [intel_qat] The notification cannot move before adf_dev_down(): the PF waits for it before its own reset and the VF must tear down its rings first. vf2pf_lock protects the VF2PF CSR and is unrelated to the PF2VF bottom half it is initialised alongside. Tie its lifetime to the accel device, next to state_lock in adf_devmgr_add_dev()/adf_devmgr_rm_dev(), so it stays valid for messages sent outside the device up/down cycle. It is only touched for VFs, which set is_vf before adf_devmgr_add_dev() and keep it set until adf_devmgr_rm_dev(). Fixes: 6f1b5236348f ("crypto: qat - fix recovery flow for VFs") Cc: stable@vger.kernel.org Signed-off-by: Ahsan Atta Reviewed-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c | 8 ++++++++ drivers/crypto/intel/qat/qat_common/adf_vf_isr.c | 2 -- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c index 26b40dd59965..4e6d860c9a60 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c +++ b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c @@ -138,6 +138,12 @@ int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, mutex_lock(&table_lock); atomic_set(&accel_dev->ref_count, 0); mutex_init(&accel_dev->state_lock); + /* + * The VF2PF lock is used to send messages to the PF outside of the + * device up/down cycle, so it must live as long as the accel device. + */ + if (accel_dev->is_vf) + mutex_init(&accel_dev->vf.vf2pf_lock); /* PF on host or VF on guest - optimized to remove redundant is_vf */ if (!accel_dev->is_vf || !pf) { @@ -257,6 +263,8 @@ void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev, } } unlock: + if (accel_dev->is_vf) + mutex_destroy(&accel_dev->vf.vf2pf_lock); mutex_destroy(&accel_dev->state_lock); list_del(&accel_dev->list); mutex_unlock(&table_lock); diff --git a/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c b/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c index 9ffaa56def67..1f28655ec051 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c +++ b/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c @@ -118,7 +118,6 @@ static int adf_setup_pf2vf_bh(struct adf_accel_dev *accel_dev) tasklet_init(&accel_dev->vf.pf2vf_bh_tasklet, (void *)adf_pf2vf_bh_handler, (unsigned long)accel_dev); - mutex_init(&accel_dev->vf.vf2pf_lock); return 0; } @@ -126,7 +125,6 @@ static void adf_cleanup_pf2vf_bh(struct adf_accel_dev *accel_dev) { tasklet_disable(&accel_dev->vf.pf2vf_bh_tasklet); tasklet_kill(&accel_dev->vf.pf2vf_bh_tasklet); - mutex_destroy(&accel_dev->vf.vf2pf_lock); } static irqreturn_t adf_isr(int irq, void *privdata) From cc29ce88b1b5e7bda883037ba9f94cb857ec8531 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 6 Oct 2026 19:26:27 +0200 Subject: [PATCH 140/146] hwrng: intel - simplify intel_rng_mod_init() Return errors directly to simplify intel_rng_mod_init(). Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/intel-rng.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index bc4aa9ea1195..b6a50e3e7a6a 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -327,7 +327,7 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, static int __init intel_rng_mod_init(void) { - int err = -ENODEV; + int err; int i; struct pci_dev *dev = NULL; void __iomem *mem; @@ -339,7 +339,7 @@ static int __init intel_rng_mod_init(void) NULL); if (!dev) - goto out; /* Device not found. */ + return -ENODEV; if (no_fwh_detect < 0) { pci_dev_put(dev); @@ -349,8 +349,7 @@ static int __init intel_rng_mod_init(void) intel_rng_hw = kmalloc_obj(*intel_rng_hw); if (!intel_rng_hw) { pci_dev_put(dev); - err = -ENOMEM; - goto out; + return -ENOMEM; } err = intel_init_hw_struct(intel_rng_hw, dev); @@ -359,7 +358,7 @@ static int __init intel_rng_mod_init(void) kfree(intel_rng_hw); if (err == -ENODEV) goto fwh_done; - goto out; + return err; } /* @@ -375,21 +374,19 @@ static int __init intel_rng_mod_init(void) iounmap(intel_rng_hw->mem); kfree(intel_rng_hw); if (err) - goto out; + return err; fwh_done: - err = -ENOMEM; mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); if (!mem) - goto out; + return -ENOMEM; intel_rng.priv = (unsigned long)mem; /* Check for Random Number Generator */ - err = -ENODEV; hw_status = hwstatus_get(mem); if ((hw_status & INTEL_RNG_PRESENT) == 0) { iounmap(mem); - goto out; + return -ENODEV; } pr_info("Intel 82802 RNG detected\n"); @@ -398,10 +395,10 @@ fwh_done: pr_err(PFX "RNG registering failed (%d)\n", err); iounmap(mem); + return err; } -out: - return err; + return 0; } static void __exit intel_rng_mod_exit(void) From a7ea3d63e89712c6c167595370eb42674e56b5bc Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 6 Oct 2026 22:27:34 +0200 Subject: [PATCH 141/146] hwrng: cctrng - simplify cctrng_probe() Handle the error directly and drop the goto statement. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/cctrng.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c index be35f058f37a..03401ee59a8e 100644 --- a/drivers/char/hw_random/cctrng.c +++ b/drivers/char/hw_random/cctrng.c @@ -534,7 +534,8 @@ static int cctrng_probe(struct platform_device *pdev) rc = devm_hwrng_register(dev, &drvdata->rng); if (rc) { dev_err(dev, "Could not register hwrng device.\n"); - goto post_pm_err; + cc_trng_pm_fini(drvdata); + return rc; } /* trigger HW to start generate data */ @@ -547,11 +548,6 @@ static int cctrng_probe(struct platform_device *pdev) dev_info(dev, "ARM cctrng device initialized\n"); return 0; - -post_pm_err: - cc_trng_pm_fini(drvdata); - - return rc; } static void cctrng_remove(struct platform_device *pdev) From a29888556578e4695bca25a2807308e9050ee2ac Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 8 Oct 2026 11:37:37 +0200 Subject: [PATCH 142/146] hwrng: amd - use PMBASE_OFFSET consistently Use PMBASE_OFFSET instead of the hard-coded 0xF0 and add the missing space to the ioport_map() error message. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/char/hw_random/amd-rng.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c index fb5422612182..ef177c99515d 100644 --- a/drivers/char/hw_random/amd-rng.c +++ b/drivers/char/hw_random/amd-rng.c @@ -158,14 +158,14 @@ static int __init amd_rng_mod_init(void) if (!request_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE, DRV_NAME)) { dev_err(&pdev->dev, DRV_NAME " region 0x%x already in use!\n", - pmbase + 0xF0); + pmbase + PMBASE_OFFSET); err = -EBUSY; goto out; } priv->iobase = ioport_map(pmbase + PMBASE_OFFSET, PMBASE_SIZE); if (!priv->iobase) { - pr_err(DRV_NAME "Cannot map ioport\n"); + pr_err(DRV_NAME " cannot map ioport\n"); err = -EINVAL; goto err; } From fed9c1930e1dcec978ff323a6ea9dd783a63b8b3 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 10 Oct 2026 14:56:44 +0200 Subject: [PATCH 143/146] MAINTAINERS: delete entry for John Allen The email address bounced. I couldn't find a newer one in recent git history, so delete this email entry. Signed-off-by: Wolfram Sang Signed-off-by: Herbert Xu --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 66cf3701ff19..e02bb88411a0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1077,7 +1077,6 @@ F: include/linux/cdx/* AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER M: Tom Lendacky -M: John Allen L: linux-crypto@vger.kernel.org S: Supported F: drivers/crypto/ccp/ From c577e8d88783aa1c6e337dbc37fc739cfd40d93e Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 11 Oct 2026 15:15:56 +0200 Subject: [PATCH 144/146] crypto: atmel-tdes - use separate DMA scatterlists Use two separate input and output scatterlists instead of an array. Also use DMA_SLAVE_BUSWIDTH_4_BYTES directly and drop the now-unused addr_width variable. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index f084fda42423..b2fca4baee2f 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -372,37 +372,32 @@ static int atmel_tdes_crypt_dma(struct atmel_tdes_dev *dd, dma_addr_t dma_addr_in, dma_addr_t dma_addr_out) { - struct scatterlist sg[2]; - struct dma_async_tx_descriptor *in_desc, *out_desc; - enum dma_slave_buswidth addr_width; + struct scatterlist sg_in, sg_out; + struct dma_async_tx_descriptor *in_desc, *out_desc; - addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - - dd->dma_lch_in.dma_conf.dst_addr_width = addr_width; - dd->dma_lch_out.dma_conf.src_addr_width = addr_width; + dd->dma_lch_in.dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + dd->dma_lch_out.dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf); dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf); dd->flags |= TDES_FLAGS_DMA; - sg_init_table(&sg[0], 1); - sg_dma_address(&sg[0]) = dma_addr_in; - sg_dma_len(&sg[0]) = dd->dma_size; + sg_init_table(&sg_in, 1); + sg_dma_address(&sg_in) = dma_addr_in; + sg_dma_len(&sg_in) = dd->dma_size; - sg_init_table(&sg[1], 1); - sg_dma_address(&sg[1]) = dma_addr_out; - sg_dma_len(&sg[1]) = dd->dma_size; + sg_init_table(&sg_out, 1); + sg_dma_address(&sg_out) = dma_addr_out; + sg_dma_len(&sg_out) = dd->dma_size; - in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, &sg[0], - 1, DMA_MEM_TO_DEV, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, &sg_in, 1, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!in_desc) return -EINVAL; - out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, &sg[1], - 1, DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, &sg_out, 1, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!out_desc) return -EINVAL; From a9c624fa9ea0e27d044decfebb8befdef0e08299 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 11 Oct 2026 15:15:57 +0200 Subject: [PATCH 145/146] crypto: atmel-tdes - reuse fast in atmel_tdes_crypt_start() Use the existing fast variable instead of testing for TDES_FLAGS_FAST in dd->flags again. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index b2fca4baee2f..f92dc2fff50c 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -473,7 +473,7 @@ static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd) else err = atmel_tdes_crypt_pdc(dd, addr_in, addr_out); - if (err && (dd->flags & TDES_FLAGS_FAST)) { + if (err && fast) { dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE); } From 178aff4cf425b3fc51ff09c571fa1bfbc1eb8ea4 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 11 Oct 2026 15:15:58 +0200 Subject: [PATCH 146/146] crypto: atmel-tdes - consolidate error paths in atmel_tdes_dma_init() Release the DMA channel directly and consolidate the error paths. Signed-off-by: Thorsten Blum Signed-off-by: Herbert Xu --- drivers/crypto/atmel-tdes.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index f92dc2fff50c..6b561b333ac6 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -633,7 +633,7 @@ static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd) dd->dma_lch_in.chan = dma_request_chan(dd->dev, "tx"); if (IS_ERR(dd->dma_lch_in.chan)) { ret = PTR_ERR(dd->dma_lch_in.chan); - goto err_dma_in; + goto err_dma; } dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + @@ -649,7 +649,8 @@ static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd) dd->dma_lch_out.chan = dma_request_chan(dd->dev, "rx"); if (IS_ERR(dd->dma_lch_out.chan)) { ret = PTR_ERR(dd->dma_lch_out.chan); - goto err_dma_out; + dma_release_channel(dd->dma_lch_in.chan); + goto err_dma; } dd->dma_lch_out.dma_conf.src_addr = dd->phys_base + @@ -664,9 +665,7 @@ static int atmel_tdes_dma_init(struct atmel_tdes_dev *dd) return 0; -err_dma_out: - dma_release_channel(dd->dma_lch_in.chan); -err_dma_in: +err_dma: dev_err(dd->dev, "no DMA channel available\n"); return ret; }