Skip to contentSkip to conversation

crypto: caam - reject overlong RSA CRT parameters

PATCH In review Jérémy Jean 3 participants 6 messages Oct 8 – Nov 4

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 crypto: caam - reject overlong RSA CRT parameters

caam_read_rsa_crt() right-aligns dP, dQ, and qInv in buffers sized from the corresponding prime. rsa_parse_priv_key() only bounds these integers against n, so a malformed key can provide, for example, a two-byte dP with a one-byte p. dstlen - nbytes then underflows and memcpy() writes outside the allocation during set_priv_key(). KASAN reports a slab-out-of-bounds write in caam_read_rsa_crt().

Reject empty or overlong CRT parameters after stripping leading zeros. qInv is consumed by CAAM as a p-sized value, so size it from p rather than q to match the DMA mapping in set_rsa_priv_f3_pdb(). Let the top-level key cleanup handle partial form-3 allocations and return the specific error to the caller.

Also test nbytes before dereferencing it while stripping zeros, so an all-zero integer does not read one byte beyond its input.

Fixes 4a651b122adb ("crypto: caam - add support for RSA key form 3")
Assisted-by LLM
---
 drivers/crypto/caam/caampkc.c | 69 +++++++++++++++--------------------
 1 file changed, 30 insertions(+), 39 deletions(-)
drivers/crypto/caam/caampkc.c +30 -39
index cb001aa1de66..2082adaae585 100644
@@ -880,7 +880,7 @@ static void caam_rsa_free_key(struct caam_rsa_key *key)
 
 static void caam_rsa_drop_leading_zeros(const u8 **ptr, size_t *nbytes)
 {
-	while (!**ptr && *nbytes) {
+	while (*nbytes && !**ptr) {
 		(*ptr)++;
 		(*nbytes)--;
 	}
@@ -896,22 +896,22 @@ static void caam_rsa_drop_leading_zeros(const u8 **ptr, size_t *nbytes)
  * @ptr   : pointer to {dP, dQ, qInv} CRT member
  * @nbytes: length in bytes of {dP, dQ, qInv} CRT member
  * @dstlen: length in bytes of corresponding p or q prime factor
+ * @dst   : pointer to the zero-padded output buffer
  */
-static u8 *caam_read_rsa_crt(const u8 *ptr, size_t nbytes, size_t dstlen)
+static int caam_read_rsa_crt(const u8 *ptr, size_t nbytes, size_t dstlen,
+			     u8 **dst)
 {
-	u8 *dst;
-
 	caam_rsa_drop_leading_zeros(&ptr, &nbytes);
-	if (!nbytes)
-		return NULL;
+	if (!nbytes || nbytes > dstlen)
+		return -EINVAL;
 
-	dst = kzalloc(dstlen, GFP_KERNEL);
-	if (!dst)
-		return NULL;
+	*dst = kzalloc(dstlen, GFP_KERNEL);
+	if (!*dst)
+		return -ENOMEM;
 
-	memcpy(dst + (dstlen - nbytes), ptr, nbytes);
+	memcpy(*dst + (dstlen - nbytes), ptr, nbytes);
 
-	return dst;
+	return 0;
 }
 
 /**
@@ -991,6 +991,7 @@ static int caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
 	size_t p_sz = raw_key->p_sz;
 	size_t q_sz = raw_key->q_sz;
 	unsigned aligned_size;
+	int ret;
 
 	rsa_key->p = caam_read_raw_data(raw_key->p, &p_sz);
 	if (!rsa_key->p)
@@ -999,51 +1000,39 @@ static int caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
 
 	rsa_key->q = caam_read_raw_data(raw_key->q, &q_sz);
 	if (!rsa_key->q)
-		goto free_p;
+		return -ENOMEM;
 	rsa_key->q_sz = q_sz;
 
 	aligned_size = ALIGN(raw_key->p_sz, dma_get_cache_alignment());
 	rsa_key->tmp1 = kzalloc(aligned_size, GFP_KERNEL);
 	if (!rsa_key->tmp1)
-		goto free_q;
+		return -ENOMEM;
 
 	aligned_size = ALIGN(raw_key->q_sz, dma_get_cache_alignment());
 	rsa_key->tmp2 = kzalloc(aligned_size, GFP_KERNEL);
 	if (!rsa_key->tmp2)
-		goto free_tmp1;
+		return -ENOMEM;
 
 	rsa_key->priv_form = FORM2;
 
-	rsa_key->dp = caam_read_rsa_crt(raw_key->dp, raw_key->dp_sz, p_sz);
-	if (!rsa_key->dp)
-		goto free_tmp2;
+	ret = caam_read_rsa_crt(raw_key->dp, raw_key->dp_sz, p_sz,
+				&rsa_key->dp);
+	if (ret)
+		return ret;
 
-	rsa_key->dq = caam_read_rsa_crt(raw_key->dq, raw_key->dq_sz, q_sz);
-	if (!rsa_key->dq)
-		goto free_dp;
+	ret = caam_read_rsa_crt(raw_key->dq, raw_key->dq_sz, q_sz,
+				&rsa_key->dq);
+	if (ret)
+		return ret;
 
-	rsa_key->qinv = caam_read_rsa_crt(raw_key->qinv, raw_key->qinv_sz,
-					  q_sz);
-	if (!rsa_key->qinv)
-		goto free_dq;
+	ret = caam_read_rsa_crt(raw_key->qinv, raw_key->qinv_sz, p_sz,
+				&rsa_key->qinv);
+	if (ret)
+		return ret;
 
 	rsa_key->priv_form = FORM3;
 
 	return 0;
-
-free_dq:
-	kfree_sensitive(rsa_key->dq);
-free_dp:
-	kfree_sensitive(rsa_key->dp);
-free_tmp2:
-	kfree_sensitive(rsa_key->tmp2);
-free_tmp1:
-	kfree_sensitive(rsa_key->tmp1);
-free_q:
-	kfree_sensitive(rsa_key->q);
-free_p:
-	kfree_sensitive(rsa_key->p);
-	return -ENOMEM;
 }
 
 static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
@@ -1061,6 +1050,8 @@ static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
 	if (ret)
 		return ret;
 
+	ret = -ENOMEM;
+
 	/* Copy key in DMA zone */
 	rsa_key->d = kmemdup(raw_key.d, raw_key.d_sz, GFP_KERNEL);
 	if (!rsa_key->d)
@@ -1097,7 +1088,7 @@ static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
 
 err:
 	caam_rsa_free_key(rsa_key);
-	return -ENOMEM;
+	return ret;
 }
 
 static unsigned int caam_rsa_max_size(struct crypto_akcipher *tfm)
Signature · 1 line
2.47.3
maintainer
#1 lore raw
Quoted 16 lines · Jérémy Jean

caam_read_rsa_crt() right-aligns dP, dQ, and qInv in buffers sized from the corresponding prime. rsa_parse_priv_key() only bounds these integers against n, so a malformed key can provide, for example, a two-byte dP with a one-byte p. dstlen - nbytes then underflows and memcpy() writes outside the allocation during set_priv_key(). KASAN reports a slab-out-of-bounds write in caam_read_rsa_crt().

Reject empty or overlong CRT parameters after stripping leading zeros. qInv is consumed by CAAM as a p-sized value, so size it from p rather than q to match the DMA mapping in set_rsa_priv_f3_pdb(). Let the top-level key cleanup handle partial form-3 allocations and return the specific error to the caller.

Also test nbytes before dereferencing it while stripping zeros, so an all-zero integer does not read one byte beyond its input.

Quoted 7 lines
Fixes 4a651b122adb ("crypto: caam - add support for RSA key form 3")
Assisted-by LLM
---
 drivers/crypto/caam/caampkc.c | 69 +++++++++++++++--------------------
 1 file changed, 30 insertions(+), 39 deletions(-)

Sahil, could you please review this patch?

Thanks,

Signature · 3 lines
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
maintainer
#2 lore raw
Quoted 25 lines · Herbert Xu
Quoted 16 lines · Jérémy Jean

caam_read_rsa_crt() right-aligns dP, dQ, and qInv in buffers sized from the corresponding prime. rsa_parse_priv_key() only bounds these integers against n, so a malformed key can provide, for example, a two-byte dP with a one-byte p. dstlen - nbytes then underflows and memcpy() writes outside the allocation during set_priv_key(). KASAN reports a slab-out-of-bounds write in caam_read_rsa_crt().

Reject empty or overlong CRT parameters after stripping leading zeros. qInv is consumed by CAAM as a p-sized value, so size it from p rather than q to match the DMA mapping in set_rsa_priv_f3_pdb(). Let the top-level key cleanup handle partial form-3 allocations and return the specific error to the caller.

Also test nbytes before dereferencing it while stripping zeros, so an all-zero integer does not read one byte beyond its input.

Quoted 7 lines
Fixes 4a651b122adb ("crypto: caam - add support for RSA key form 3")
Assisted-by LLM
---
 drivers/crypto/caam/caampkc.c | 69 +++++++++++++++--------------------
 1 file changed, 30 insertions(+), 39 deletions(-)
Quoted 1 line

Sahil, could you please review this patch?

Hi Sahil:

It's been two weeks and you've provided no feedback.

If there isn't going to be timely feedback to patches on this driver then it will be removed.

Thanks,

Signature · 3 lines
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
#3 lore raw

Hi Herbert,

Sorry for the delay.
I just reviewed the patch and in process of reviewing other pending patches also.

Regards,
Sahil Malhotra

NXP Confidential

Quoted 11 lines

-----Original Message-----
From: Herbert Xu <[email protected]>
Sent: 26 October 2026 10:13
To: Jérémy Jean <[email protected]>
Cc: Horia Geanta <[email protected]>; Pankaj Gupta <[email protected]>; Sahil Malhotra <[email protected]>; David S. Miller <[email protected]>; [email protected]; linux- [email protected]; [email protected]
Subject: [EXT] Re: [REPOST PATCH] crypto: caam - reject overlong RSA CRT parameters

Quoted 1 line

Caution: This is an external email. Please take care when clicking links

or

Quoted 32 lines

opening attachments. When in doubt, report the message using the 'Report this email' button

Quoted 27 lines · Herbert Xu
Quoted 25 lines · Jérémy Jean

caam_read_rsa_crt() right-aligns dP, dQ, and qInv in buffers sized from the corresponding prime. rsa_parse_priv_key() only bounds these integers against n, so a malformed key can provide, for example, a two-byte dP with a one-byte p. dstlen - nbytes then underflows and memcpy() writes outside the allocation during set_priv_key(). KASAN reports a slab-out-of-bounds write in caam_read_rsa_crt().

Reject empty or overlong CRT parameters after stripping leading zeros. qInv is consumed by CAAM as a p-sized value, so size it from p rather than q to match the DMA mapping in set_rsa_priv_f3_pdb(). Let the top-level key cleanup handle partial form-3 allocations and return the specific error to the caller.

Also test nbytes before dereferencing it while stripping zeros, so an all-zero integer does not read one byte beyond its input.

Fixes 4a651b122adb ("crypto: caam - add support for RSA key form

3")

---
 drivers/crypto/caam/caampkc.c | 69
+++++++++++++++--------------------
 1 file changed, 30 insertions(+), 39 deletions(-)
Quoted 7 lines
Quoted 1 line

Sahil, could you please review this patch?

Hi Sahil:

It's been two weeks and you've provided no feedback.

If there isn't going to be timely feedback to patches on this driver then

it will be

Quoted 21 lines

removed.

Thanks,
--
Email: Herbert Xu <[email protected]> Home Page:
https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fgondo
r.apana.org.au%2F~herbert%2F&data=05%7C02%7Csahil.malhotra%40nxp.c om%7C8ae2201e6d304d4bca0708df331b9897%7C686ea1d3bc2b4c6fa92c d99c5c301635%7C0%7C0%7C639285865952622472%7CUnknown%7CTW FpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXa W4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=YP2 HDGxtmPHRqtU3%2F6lFqhjJwOUa8Czp6IV3QJI%2FaYc%3D&reserved=0 PGP Key:
https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fgondo
r.apana.org.au%2F~herbert%2Fpubkey.txt&data=05%7C02%7Csahil.malhotr a%40nxp.com%7C8ae2201e6d304d4bca0708df331b9897%7C686ea1d3bc 2b4c6fa92cd99c5c301635%7C0%7C0%7C639285865952656160%7CUnkn own%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwM CIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C &sdata=9N5IuUc0ReEfh37OUvvVqfWMs1NJRxS6yDd32NmUu84%3D&reser ved=0

Reviewed-by Sahil Malhotra on v1 1/1
#4 lore raw
In reply to Jérémy Jean

Hi Jeremy,

Sorry for the delayed response.

I am ok with this patch.

Regards,
Sahil Malhotra

NXP Confidential

Quoted 187 lines

-----Original Message-----
From: Jérémy Jean <[email protected]>
Sent: 08 October 2026 15:06
To: Horia Geanta <[email protected]>; Pankaj Gupta <[email protected]>; Sahil Malhotra <[email protected]>; Herbert Xu <[email protected]>; David S. Miller <[email protected]>; [email protected]; linux- [email protected]
Cc: Jérémy Jean <[email protected]>; [email protected]
Subject: [EXT] [REPOST PATCH] crypto: caam - reject overlong RSA CRT parameters

Caution: This is an external email. Please take care when clicking links or opening attachments. When in doubt, report the message using the 'Report this email' button

caam_read_rsa_crt() right-aligns dP, dQ, and qInv in buffers sized from the corresponding prime. rsa_parse_priv_key() only bounds these integers against n, so a malformed key can provide, for example, a two-byte dP with a one- byte p. dstlen - nbytes then underflows and
memcpy() writes outside the allocation during set_priv_key(). KASAN reports a slab-out-of-bounds write in caam_read_rsa_crt().

Reject empty or overlong CRT parameters after stripping leading zeros. qInv is consumed by CAAM as a p-sized value, so size it from p rather than q to match the DMA mapping in set_rsa_priv_f3_pdb(). Let the top-level key cleanup handle partial form-3 allocations and return the specific error to the caller.

Also test nbytes before dereferencing it while stripping zeros, so an all-zero integer does not read one byte beyond its input.

Fixes 4a651b122adb ("crypto: caam - add support for RSA key form 3")
Assisted-by LLM
---
 drivers/crypto/caam/caampkc.c | 69 +++++++++++++++--------------------
 1 file changed, 30 insertions(+), 39 deletions(-)
drivers/crypto/caam/caampkc.c +11 -11
index cb001aa1de66..2082adaae585 100644
@@ -880,7 +880,7 @@ static void caam_rsa_free_key(struct caam_rsa_key
 *key)
 
 static void caam_rsa_drop_leading_zeros(const u8 **ptr, size_t *nbytes)  {
-       while (!**ptr && *nbytes) {
+       while (*nbytes && !**ptr) {
                (*ptr)++;
                (*nbytes)--;
        }
@@ -896,22 +896,22 @@ static void caam_rsa_drop_leading_zeros(const u8
 **ptr, size_t *nbytes)
  * @ptr   : pointer to {dP, dQ, qInv} CRT member
  * @nbytes: length in bytes of {dP, dQ, qInv} CRT member
  * @dstlen: length in bytes of corresponding p or q prime factor
+ * @dst   : pointer to the zero-padded output buffer
  */
-static u8 *caam_read_rsa_crt(const u8 *ptr, size_t nbytes, size_t dstlen)
+static int caam_read_rsa_crt(const u8 *ptr, size_t nbytes, size_t dstlen,
+                            u8 **dst)
 {
-       u8 *dst;
-
        caam_rsa_drop_leading_zeros(&ptr, &nbytes);
-       if (!nbytes)
-               return NULL;
+       if (!nbytes || nbytes > dstlen)
+               return -EINVAL;
 
-       dst = kzalloc(dstlen, GFP_KERNEL);
-       if (!dst)
-               return NULL;
+       *dst = kzalloc(dstlen, GFP_KERNEL);
+       if (!*dst)
+               return -ENOMEM;
 
-       memcpy(dst + (dstlen - nbytes), ptr, nbytes);
+       memcpy(*dst + (dstlen - nbytes), ptr, nbytes);
 
-       return dst;
+       return 0;
 }
 

/**

drivers/crypto/caam/caampkc.c +1 -0
@@ -991,6 +991,7 @@ static int caam_rsa_set_priv_key_form(struct
 caam_rsa_ctx *ctx,
        size_t p_sz = raw_key->p_sz;
        size_t q_sz = raw_key->q_sz;
        unsigned aligned_size;
+       int ret;
 
        rsa_key->p = caam_read_raw_data(raw_key->p, &p_sz);
        if (!rsa_key->p)
drivers/crypto/caam/caampkc.c +15 -27
@@ -999,51 +1000,39 @@ static int caam_rsa_set_priv_key_form(struct
 caam_rsa_ctx *ctx,
 
        rsa_key->q = caam_read_raw_data(raw_key->q, &q_sz);
        if (!rsa_key->q)
-               goto free_p;
+               return -ENOMEM;
        rsa_key->q_sz = q_sz;
 
        aligned_size = ALIGN(raw_key->p_sz, dma_get_cache_alignment());
        rsa_key->tmp1 = kzalloc(aligned_size, GFP_KERNEL);
        if (!rsa_key->tmp1)
-               goto free_q;
+               return -ENOMEM;
 
        aligned_size = ALIGN(raw_key->q_sz, dma_get_cache_alignment());
        rsa_key->tmp2 = kzalloc(aligned_size, GFP_KERNEL);
        if (!rsa_key->tmp2)
-               goto free_tmp1;
+               return -ENOMEM;
 
        rsa_key->priv_form = FORM2;
 
-       rsa_key->dp = caam_read_rsa_crt(raw_key->dp, raw_key->dp_sz, p_sz);
-       if (!rsa_key->dp)
-               goto free_tmp2;
+       ret = caam_read_rsa_crt(raw_key->dp, raw_key->dp_sz, p_sz,
+                               &rsa_key->dp);
+       if (ret)
+               return ret;
 
-       rsa_key->dq = caam_read_rsa_crt(raw_key->dq, raw_key->dq_sz, q_sz);
-       if (!rsa_key->dq)
-               goto free_dp;
+       ret = caam_read_rsa_crt(raw_key->dq, raw_key->dq_sz, q_sz,
+                               &rsa_key->dq);
+       if (ret)
+               return ret;
 
-       rsa_key->qinv = caam_read_rsa_crt(raw_key->qinv, raw_key->qinv_sz,
-                                         q_sz);
-       if (!rsa_key->qinv)
-               goto free_dq;
+       ret = caam_read_rsa_crt(raw_key->qinv, raw_key->qinv_sz, p_sz,
+                               &rsa_key->qinv);
+       if (ret)
+               return ret;
 
        rsa_key->priv_form = FORM3;
 
        return 0;
-
-free_dq:
-       kfree_sensitive(rsa_key->dq);
-free_dp:
-       kfree_sensitive(rsa_key->dp);
-free_tmp2:
-       kfree_sensitive(rsa_key->tmp2);
-free_tmp1:
-       kfree_sensitive(rsa_key->tmp1);
-free_q:
-       kfree_sensitive(rsa_key->q);
-free_p:
-       kfree_sensitive(rsa_key->p);
-       return -ENOMEM;
 }
 

static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,

drivers/crypto/caam/caampkc.c +2 -0
@@ -1061,6 +1050,8 @@ static int caam_rsa_set_priv_key(struct
 crypto_akcipher *tfm, const void *key,
        if (ret)
                return ret;
 
+       ret = -ENOMEM;
+
        /* Copy key in DMA zone */
        rsa_key->d = kmemdup(raw_key.d, raw_key.d_sz, GFP_KERNEL);
        if (!rsa_key->d)
drivers/crypto/caam/caampkc.c +1 -1
@@ -1097,7 +1088,7 @@ static int caam_rsa_set_priv_key(struct
 crypto_akcipher *tfm, const void *key,
 
 err:
        caam_rsa_free_key(rsa_key);
-       return -ENOMEM;
+       return ret;
 }
 

static unsigned int caam_rsa_max_size(struct crypto_akcipher *tfm)
--
2.47.3

maintainer
#5 lore raw
In reply to Jérémy Jean
Quoted 16 lines · Jérémy Jean

caam_read_rsa_crt() right-aligns dP, dQ, and qInv in buffers sized from the corresponding prime. rsa_parse_priv_key() only bounds these integers against n, so a malformed key can provide, for example, a two-byte dP with a one-byte p. dstlen - nbytes then underflows and memcpy() writes outside the allocation during set_priv_key(). KASAN reports a slab-out-of-bounds write in caam_read_rsa_crt().

Reject empty or overlong CRT parameters after stripping leading zeros. qInv is consumed by CAAM as a p-sized value, so size it from p rather than q to match the DMA mapping in set_rsa_priv_f3_pdb(). Let the top-level key cleanup handle partial form-3 allocations and return the specific error to the caller.

Also test nbytes before dereferencing it while stripping zeros, so an all-zero integer does not read one byte beyond its input.

Quoted 7 lines
Fixes 4a651b122adb ("crypto: caam - add support for RSA key form 3")
Assisted-by LLM
---
 drivers/crypto/caam/caampkc.c | 69 +++++++++++++++--------------------
 1 file changed, 30 insertions(+), 39 deletions(-)

Patch applied. Thanks.

Signature · 3 lines
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt