Re: [PATCH v6 7/8] crypto: qce - Use a fallback for CCM with a partial final block

From: Eric Biggers

Date: Thu Jul 23 2026 - 14:38:14 EST


On Fri, Jul 17, 2026 at 05:53:36PM +0200, Bartosz Golaszewski wrote:
> CCM builds on AES-CTR for encryption, and the crypto engine stalls on a
> partial final block just as it does for plain ctr(aes): a payload whose
> length is not a multiple of the AES block size leaves the operation
> incomplete and fails with a hardware operation error. This was caught by
> the ccm(aes) crypto self-tests.
>
> Force the software fallback for CCM requests whose message length is not
> block aligned, reusing the driver's existing need_fallback mechanism.
>
> Cc: stable@xxxxxxxxxxxxxxx
> Fixes: 9363efb4181c ("crypto: qce - Add support for AEAD algorithms")
> Tested-by: Kuldeep Singh <kuldeep.singh@xxxxxxxxxxxxxxxx>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
> ---
> drivers/crypto/qce/aead.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c
> index 336614a11377e0be246817da584296124f4de5d8..4fa018204cb628c112f64c45ff6c7407df73b945 100644
> --- a/drivers/crypto/qce/aead.c
> +++ b/drivers/crypto/qce/aead.c
> @@ -514,6 +514,14 @@ static int qce_aead_crypt(struct aead_request *req, int encrypt)
> ctx->need_fallback = true;
> }
>
> + /*
> + * CCM uses AES-CTR internally and the CE stalls on a partial final
> + * block, so a payload that is not a multiple of the block size has to
> + * be handled by the fallback.
> + */
> + if (IS_CCM(rctx->flags) && !IS_ALIGNED(rctx->cryptlen, AES_BLOCK_SIZE))
> + ctx->need_fallback = true;
> +
> /* If fallback is needed, schedule and exit */
> if (ctx->need_fallback) {

Here, the driver is storing per-request state ('need_fallback') in the
transformation context, which is a shared structure. This can cause the
driver to produce incorrect results if used for multiple concurrent
requests with the same algorithm.

On the topic of CCM, there's also a memory leak and buffer overread in
qce_aead_ccm_prepare_buf_assoclen(). It allocates a buffer of length
ALIGN(assoclen,16)+6, then treats it as a buffer of length
ALIGN(assoclen+6,16). That can be greater than the allocated length,
for example if assoclen = 15. Then it never frees the buffer.

The allocation is also being done using GFP_ATOMIC, which is
failure-prone. Users need crypto operations to be reliable.

This driver's CCM implementation also fails to validate that the message
length is allowed for the specified nonce length.

The error handling in qce_aead_async_req_handle() is also incorrect: it
calls dma_unmap_sg() on req->src instead of the actual mapped
scatterlist rctx->src_sg, which differ when assoclen > 0. It also uses
< 0 to check for failures from dma_map_sg(), when it actually returns an
unsigned int and returns 0 on failure.

Note that the ARMv8 CE implementation of AES-CCM is much faster and does
not have these issues.

- Eric