crypto: caam - handle zero-length AEAD output
authorHoria Geantă <horia.geanta@nxp.com>
Tue, 22 Jan 2019 14:47:01 +0000 (16:47 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 1 Feb 2019 06:42:03 +0000 (14:42 +0800)
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ă <horia.geanta@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/caamalg_qi.c
drivers/crypto/caam/caamalg_qi2.c

index 80ae69f906fbd360a8ca8f714aea9dfe990584e2..0a4469fcd19228548c1208b0a3a4cb1a5e236ba9 100644 (file)
@@ -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;
                }
        }
 
index c0d55310aade17387ad2e58c284df0d152b21b5d..7bce97884663608cc2c490456970324bc7f4b0d8 100644 (file)
@@ -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;
                }
        }
 
index cc59814afd29e536f6727e87e59ecb9ffae728ea..4bea4f1beac96156c5ed36ccdd5f04e2a43750b8 100644 (file)
@@ -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 +