crypto: caam - handle zero-length AEAD output

Recent AEAD changes in testmgr framework introduced by commit
a0d608ee5e ("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ă <horia.geanta@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Horia Geantă 2019-01-22 16:47:01 +02:00 committed by Herbert Xu
parent 87870cfb4b
commit 763069ba49
3 changed files with 47 additions and 24 deletions

View File

@ -846,7 +846,8 @@ static void caam_unmap(struct device *dev, struct scatterlist *src,
if (dst != src) { if (dst != src) {
if (src_nents) if (src_nents)
dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); 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 { } else {
dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); 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; out_options = in_options;
if (unlikely(req->src != req->dst)) { 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); dst_dma = sg_dma_address(req->dst);
} else { } else {
dst_dma = edesc->sec4_sg_dma + 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_src_nents = 0;
} }
mapped_dst_nents = dma_map_sg(jrdev, req->dst, dst_nents, /* Cover also the case of null (zero length) output data */
DMA_FROM_DEVICE); if (dst_nents) {
if (unlikely(!mapped_dst_nents)) { mapped_dst_nents = dma_map_sg(jrdev, req->dst,
dev_err(jrdev, "unable to map destination\n"); dst_nents,
dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE); DMA_FROM_DEVICE);
return ERR_PTR(-ENOMEM); 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;
} }
} }

View File

@ -802,7 +802,8 @@ static void caam_unmap(struct device *dev, struct scatterlist *src,
if (dst != src) { if (dst != src) {
if (src_nents) if (src_nents)
dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); 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 { } else {
dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); 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_src_nents = 0;
} }
mapped_dst_nents = dma_map_sg(qidev, req->dst, dst_nents, if (dst_nents) {
DMA_FROM_DEVICE); mapped_dst_nents = dma_map_sg(qidev, req->dst,
if (unlikely(!mapped_dst_nents)) { dst_nents,
dev_err(qidev, "unable to map destination\n"); DMA_FROM_DEVICE);
dma_unmap_sg(qidev, req->src, src_nents, DMA_TO_DEVICE); if (unlikely(!mapped_dst_nents)) {
qi_cache_free(edesc); dev_err(qidev, "unable to map destination\n");
return ERR_PTR(-ENOMEM); dma_unmap_sg(qidev, req->src, src_nents,
DMA_TO_DEVICE);
qi_cache_free(edesc);
return ERR_PTR(-ENOMEM);
}
} else {
mapped_dst_nents = 0;
} }
} }

View File

@ -144,7 +144,8 @@ static void caam_unmap(struct device *dev, struct scatterlist *src,
if (dst != src) { if (dst != src) {
if (src_nents) if (src_nents)
dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); 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 { } else {
dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); 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_src_nents = 0;
} }
mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents, if (dst_nents) {
DMA_FROM_DEVICE); mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents,
if (unlikely(!mapped_dst_nents)) { DMA_FROM_DEVICE);
dev_err(dev, "unable to map destination\n"); if (unlikely(!mapped_dst_nents)) {
dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE); dev_err(dev, "unable to map destination\n");
qi_cache_free(edesc); dma_unmap_sg(dev, req->src, src_nents,
return ERR_PTR(-ENOMEM); DMA_TO_DEVICE);
qi_cache_free(edesc);
return ERR_PTR(-ENOMEM);
}
} else {
mapped_dst_nents = 0;
} }
} else { } else {
src_nents = sg_nents_for_len(req->src, req->assoclen + src_nents = sg_nents_for_len(req->src, req->assoclen +