crypto: talitos - fix IPsec cipher in length
authorLEROY Christophe <christophe.leroy@c-s.fr>
Thu, 22 Mar 2018 09:57:01 +0000 (10:57 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 30 Mar 2018 17:33:10 +0000 (01:33 +0800)
For SEC 2.x+, cipher in length must contain only the ciphertext length.
In case of using hardware ICV checking, the ICV length is provided via
the "extent" field of the descriptor pointer.

Cc: <stable@vger.kernel.org> # 4.8+
Fixes: 549bd8bc5987 ("crypto: talitos - Implement AEAD for SEC1 using HMAC_SNOOP_NO_AFEU")
Reported-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Tested-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/talitos.c

index 9a9788d7d5a8e10a815bedcc07d22895f7e54e53..3cfd53a00dc18df3bcbcd0ae4e8fac8036da8490 100644 (file)
@@ -1146,10 +1146,10 @@ next:
        return count;
 }
 
-static int talitos_sg_map(struct device *dev, struct scatterlist *src,
-                  unsigned int len, struct talitos_edesc *edesc,
-                  struct talitos_ptr *ptr,
-                  int sg_count, unsigned int offset, int tbl_off)
+static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
+                             unsigned int len, struct talitos_edesc *edesc,
+                             struct talitos_ptr *ptr, int sg_count,
+                             unsigned int offset, int tbl_off, int elen)
 {
        struct talitos_private *priv = dev_get_drvdata(dev);
        bool is_sec1 = has_ftr_sec1(priv);
@@ -1158,6 +1158,7 @@ static int talitos_sg_map(struct device *dev, struct scatterlist *src,
                to_talitos_ptr(ptr, 0, 0, is_sec1);
                return 1;
        }
+       to_talitos_ptr_ext_set(ptr, elen, is_sec1);
        if (sg_count == 1) {
                to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1);
                return sg_count;
@@ -1166,7 +1167,7 @@ static int talitos_sg_map(struct device *dev, struct scatterlist *src,
                to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1);
                return sg_count;
        }
-       sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len,
+       sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len + elen,
                                         &edesc->link_tbl[tbl_off]);
        if (sg_count == 1) {
                /* Only one segment now, so no link tbl needed*/
@@ -1180,6 +1181,15 @@ static int talitos_sg_map(struct device *dev, struct scatterlist *src,
        return sg_count;
 }
 
+static int talitos_sg_map(struct device *dev, struct scatterlist *src,
+                         unsigned int len, struct talitos_edesc *edesc,
+                         struct talitos_ptr *ptr, int sg_count,
+                         unsigned int offset, int tbl_off)
+{
+       return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset,
+                                 tbl_off, 0);
+}
+
 /*
  * fill in and submit ipsec_esp descriptor
  */
@@ -1197,7 +1207,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
        unsigned int ivsize = crypto_aead_ivsize(aead);
        int tbl_off = 0;
        int sg_count, ret;
-       int sg_link_tbl_len;
+       int elen = 0;
        bool sync_needed = false;
        struct talitos_private *priv = dev_get_drvdata(dev);
        bool is_sec1 = has_ftr_sec1(priv);
@@ -1239,17 +1249,11 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
         * extent is bytes of HMAC postpended to ciphertext,
         * typically 12 for ipsec
         */
-       sg_link_tbl_len = cryptlen;
-
-       if (is_ipsec_esp) {
-               to_talitos_ptr_ext_set(&desc->ptr[4], authsize, is_sec1);
-
-               if (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)
-                       sg_link_tbl_len += authsize;
-       }
+       if (is_ipsec_esp && (desc->hdr & DESC_HDR_MODE1_MDEU_CICV))
+               elen = authsize;
 
-       ret = talitos_sg_map(dev, areq->src, sg_link_tbl_len, edesc,
-                            &desc->ptr[4], sg_count, areq->assoclen, tbl_off);
+       ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
+                                sg_count, areq->assoclen, tbl_off, elen);
 
        if (ret > 1) {
                tbl_off += ret;