From: Horia Geantă Date: Tue, 22 Jan 2019 14:47:01 +0000 (+0200) Subject: crypto: caam - handle zero-length AEAD output X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=763069ba49d3fa342fe35487d5de10fcf1589381;p=linux.git crypto: caam - handle zero-length AEAD output Recent AEAD changes in testmgr framework introduced by commit a0d608ee5ebf ("crypto: testmgr - unify the AEAD encryption and decryption test vectors") uncovered an error in the CAAM drivers, since they don't correctly handle the case when AEAD output length is zero. Add checks to avoid feeding zero-length req->dst to DMA API. Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu --- diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 80ae69f906fbd..0a4469fcd1922 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -846,7 +846,8 @@ static void caam_unmap(struct device *dev, struct scatterlist *src, if (dst != src) { if (src_nents) dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); - dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); + if (dst_nents) + dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); } else { dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); } @@ -1038,7 +1039,9 @@ static void init_aead_job(struct aead_request *req, out_options = in_options; if (unlikely(req->src != req->dst)) { - if (edesc->dst_nents == 1) { + if (!edesc->dst_nents) { + dst_dma = 0; + } else if (edesc->dst_nents == 1) { dst_dma = sg_dma_address(req->dst); } else { dst_dma = edesc->sec4_sg_dma + @@ -1289,12 +1292,19 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, mapped_src_nents = 0; } - mapped_dst_nents = dma_map_sg(jrdev, req->dst, dst_nents, - DMA_FROM_DEVICE); - if (unlikely(!mapped_dst_nents)) { - dev_err(jrdev, "unable to map destination\n"); - dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE); - return ERR_PTR(-ENOMEM); + /* Cover also the case of null (zero length) output data */ + if (dst_nents) { + mapped_dst_nents = dma_map_sg(jrdev, req->dst, + dst_nents, + DMA_FROM_DEVICE); + if (unlikely(!mapped_dst_nents)) { + dev_err(jrdev, "unable to map destination\n"); + dma_unmap_sg(jrdev, req->src, src_nents, + DMA_TO_DEVICE); + return ERR_PTR(-ENOMEM); + } + } else { + mapped_dst_nents = 0; } } diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index c0d55310aade1..7bce978846636 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -802,7 +802,8 @@ static void caam_unmap(struct device *dev, struct scatterlist *src, if (dst != src) { if (src_nents) dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); - dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); + if (dst_nents) + dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); } else { dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); } @@ -955,13 +956,19 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, mapped_src_nents = 0; } - mapped_dst_nents = dma_map_sg(qidev, req->dst, dst_nents, - DMA_FROM_DEVICE); - if (unlikely(!mapped_dst_nents)) { - dev_err(qidev, "unable to map destination\n"); - dma_unmap_sg(qidev, req->src, src_nents, DMA_TO_DEVICE); - qi_cache_free(edesc); - return ERR_PTR(-ENOMEM); + if (dst_nents) { + mapped_dst_nents = dma_map_sg(qidev, req->dst, + dst_nents, + DMA_FROM_DEVICE); + if (unlikely(!mapped_dst_nents)) { + dev_err(qidev, "unable to map destination\n"); + dma_unmap_sg(qidev, req->src, src_nents, + DMA_TO_DEVICE); + qi_cache_free(edesc); + return ERR_PTR(-ENOMEM); + } + } else { + mapped_dst_nents = 0; } } diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index cc59814afd29e..4bea4f1beac96 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -144,7 +144,8 @@ static void caam_unmap(struct device *dev, struct scatterlist *src, if (dst != src) { if (src_nents) dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); - dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); + if (dst_nents) + dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); } else { dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); } @@ -385,13 +386,18 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, mapped_src_nents = 0; } - mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents, - DMA_FROM_DEVICE); - if (unlikely(!mapped_dst_nents)) { - dev_err(dev, "unable to map destination\n"); - dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE); - qi_cache_free(edesc); - return ERR_PTR(-ENOMEM); + if (dst_nents) { + mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents, + DMA_FROM_DEVICE); + if (unlikely(!mapped_dst_nents)) { + dev_err(dev, "unable to map destination\n"); + dma_unmap_sg(dev, req->src, src_nents, + DMA_TO_DEVICE); + qi_cache_free(edesc); + return ERR_PTR(-ENOMEM); + } + } else { + mapped_dst_nents = 0; } } else { src_nents = sg_nents_for_len(req->src, req->assoclen +