]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
crypto: qat - validate RSA CRT component lengths
authorGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Thu, 28 May 2026 15:57:44 +0000 (16:57 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 11 Jun 2026 05:53:58 +0000 (13:53 +0800)
The generic RSA key parser (rsa_helper.c) bounds each CRT component (p,
q, dp, dq, qinv) by the modulus size n_sz, but qat_rsa_setkey_crt()
allocates half-size DMA buffers (key_sz / 2) and right-aligns each
component with:

    memcpy(dst + half_key_sz - len, src, len)

When a CRT component is larger than half_key_sz the subtraction
underflows and memcpy writes past the DMA buffer, causing memory
corruption.

Add a len > half_key_sz check next to the existing !len check for each
of the five CRT components so the driver falls back to the non-CRT path
instead of writing out of bounds.

Fixes: 879f77e9071f ("crypto: qat - Add RSA CRT mode")
Cc: stable@vger.kernel.org
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Reviewed-by: Ahsan Atta <ahsan.atta@intel.com>
Reviewed-by: Laurent M Coquerel <laurent.m.coquerel@intel.com>
Tested-by: Laurent M Coquerel <laurent.m.coquerel@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/intel/qat/qat_common/qat_asym_algs.c

index e09b9edfce423db119e3debf9edf8ef48b3756db..75c15c8e41dba7122f9fd297bb8c025ce53e8022 100644 (file)
@@ -1085,7 +1085,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        ptr = rsa_key->p;
        len = rsa_key->p_sz;
        qat_rsa_drop_leading_zeros(&ptr, &len);
-       if (!len)
+       if (!len || len > half_key_sz)
                goto err;
        ctx->p = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL);
        if (!ctx->p)
@@ -1096,7 +1096,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        ptr = rsa_key->q;
        len = rsa_key->q_sz;
        qat_rsa_drop_leading_zeros(&ptr, &len);
-       if (!len)
+       if (!len || len > half_key_sz)
                goto free_p;
        ctx->q = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL);
        if (!ctx->q)
@@ -1107,7 +1107,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        ptr = rsa_key->dp;
        len = rsa_key->dp_sz;
        qat_rsa_drop_leading_zeros(&ptr, &len);
-       if (!len)
+       if (!len || len > half_key_sz)
                goto free_q;
        ctx->dp = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dp,
                                     GFP_KERNEL);
@@ -1119,7 +1119,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        ptr = rsa_key->dq;
        len = rsa_key->dq_sz;
        qat_rsa_drop_leading_zeros(&ptr, &len);
-       if (!len)
+       if (!len || len > half_key_sz)
                goto free_dp;
        ctx->dq = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dq,
                                     GFP_KERNEL);
@@ -1131,7 +1131,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        ptr = rsa_key->qinv;
        len = rsa_key->qinv_sz;
        qat_rsa_drop_leading_zeros(&ptr, &len);
-       if (!len)
+       if (!len || len > half_key_sz)
                goto free_dq;
        ctx->qinv = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_qinv,
                                       GFP_KERNEL);