mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Changwei Zou <changwei.zou@canonical.com>
To: lukas@wunner.de
Cc: Martin.Kepplinger-Novakovic@ginzinger.com,
	changwei.zou@canonical.com, davem@davemloft.net,
	herbert@gondor.apana.org.au, ignat@linux.win,
	linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
	martink@posteo.de
Subject: [PATCH v5] crypto: rsassa-pkcs1 - Avoid cacheline sharing with underlying driver
Date: Fri, 31 Jul 2026 12:44:46 +1000	[thread overview]
Message-ID: <20260731024446.786329-1-changwei.zou@canonical.com> (raw)

out_buf is used as a DMA buffer for the RSA verification operation.
If it is not aligned to CRYPTO_DMA_ALIGN, cacheline sharing
problems (data corruption) would occur on CPUs with DMA-incoherent caches,
leading to -EKEYREJECTED.

Rename out_buf to buf, as it serves as both the input and output buffer.
Add a buf_ptr pointer to track its position.

Allocate the buffer separately via kmalloc(), which guarantees cacheline
alignment on architectures without fully coherent DMA.
This acts as a defensive measure, and avoids the need for an extra copy
in the underlying driver, which should check alignment before supplying
buffers to the hardware.

The intermittent error 'Key was rejected by service' on i.MX8 with CAAM
can be triggered when loading signed kernel modules.

    for i in $(seq 1 100); do
        sudo modprobe xfs 2>&1 && echo "SUCCESS on attempt $i" \
        && sudo rmmod xfs || echo "FAILED on attempt $i"
    done

Signed-off-by: Changwei Zou <changwei.zou@canonical.com>
---
 crypto/rsassa-pkcs1.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
index 94fa5e9600e7..b1fb5111b6af 100644
--- a/crypto/rsassa-pkcs1.c
+++ b/crypto/rsassa-pkcs1.c
@@ -223,11 +223,12 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
 	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
 	unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
 	struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
+	u8 *buf __free(kfree_sensitive) = NULL;
 	struct crypto_wait cwait;
 	struct scatterlist sg;
 	unsigned int dst_len;
 	unsigned int pos;
-	u8 *out_buf;
+	u8 *buf_ptr;
 	int err;
 
 	/* RFC 8017 sec 8.2.2 step 1 - length checking */
@@ -237,16 +238,16 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
 		return -EINVAL;
 
 	/* RFC 8017 sec 8.2.2 step 2 - RSA verification */
-	child_req = kmalloc(sizeof(*child_req) + child_reqsize + ctx->key_size,
-			    GFP_KERNEL);
-	if (!child_req)
+	child_req = kmalloc(sizeof(*child_req) + child_reqsize, GFP_KERNEL);
+	buf = kmalloc(ctx->key_size, GFP_KERNEL);
+	if (!child_req || !buf)
 		return -ENOMEM;
 
-	out_buf = (u8 *)(child_req + 1) + child_reqsize;
-	memcpy(out_buf, src, slen);
+	buf_ptr = buf;
+	memcpy(buf_ptr, src, slen);
 
 	crypto_init_wait(&cwait);
-	sg_init_one(&sg, out_buf, slen);
+	sg_init_one(&sg, buf_ptr, slen);
 	akcipher_request_set_tfm(child_req, ctx->child);
 	akcipher_request_set_crypt(child_req, &sg, &sg, slen, slen);
 	akcipher_request_set_callback(child_req, CRYPTO_TFM_REQ_MAY_SLEEP,
@@ -263,35 +264,35 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
 		return -EINVAL;
 
 	if (dst_len == ctx->key_size) {
-		if (out_buf[0] != 0x00)
+		if (buf_ptr[0] != 0x00)
 			/* Encrypted value had no leading 0 byte */
 			return -EINVAL;
 
 		dst_len--;
-		out_buf++;
+		buf_ptr++;
 	}
 
-	if (out_buf[0] != 0x01)
+	if (buf_ptr[0] != 0x01)
 		return -EBADMSG;
 
 	for (pos = 1; pos < dst_len; pos++)
-		if (out_buf[pos] != 0xff)
+		if (buf_ptr[pos] != 0xff)
 			break;
 
-	if (pos < 9 || pos == dst_len || out_buf[pos] != 0x00)
+	if (pos < 9 || pos == dst_len || buf_ptr[pos] != 0x00)
 		return -EBADMSG;
 	pos++;
 
 	if (hash_prefix->size > dst_len - pos)
 		return -EBADMSG;
-	if (crypto_memneq(out_buf + pos, hash_prefix->data, hash_prefix->size))
+	if (crypto_memneq(buf_ptr + pos, hash_prefix->data, hash_prefix->size))
 		return -EBADMSG;
 	pos += hash_prefix->size;
 
-	/* RFC 8017 sec 8.2.2 step 4 - comparison of digest with out_buf */
+	/* RFC 8017 sec 8.2.2 step 4 - comparison of digest with buf */
 	if (dlen != dst_len - pos)
 		return -EKEYREJECTED;
-	if (memcmp(digest, out_buf + pos, dlen) != 0)
+	if (memcmp(digest, buf_ptr + pos, dlen) != 0)
 		return -EKEYREJECTED;
 
 	return 0;
-- 
2.43.0


             reply	other threads:[~2026-07-31  2:44 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-31  2:44 Changwei Zou [this message]
2026-08-01  6:37 ` Herbert Xu
2026-08-01  8:44   ` Changwei Zou
2026-08-05  4:28   ` Changwei Zou
2026-09-29 13:53 ` Kepplinger-Novakovic Martin

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20260731024446.786329-1-changwei.zou@canonical.com \
    --to=changwei.zou@canonical.com \
    --cc=Martin.Kepplinger-Novakovic@ginzinger.com \
    --cc=davem@davemloft.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=ignat@linux.win \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=martink@posteo.de \
    /path/to/YOUR_REPLY

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

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

all inboxes | Powered by JetHome®