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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 May 2018 07:51:49 +0000 (09:51 +0200)
commit 2b1227301a8e4729409694e323b72c064c47cb6b upstream.

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>
[backported to 4.9.y, 4.14.y]
Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/crypto/talitos.c

index ceae251..57e1b20 100644 (file)
@@ -1116,10 +1116,10 @@ next:
        return count;
 }
 
-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);
@@ -1130,7 +1130,7 @@ int talitos_sg_map(struct device *dev, struct scatterlist *src,
        }
 
        to_talitos_ptr_len(ptr, len, is_sec1);
-       to_talitos_ptr_ext_set(ptr, 0, is_sec1);
+       to_talitos_ptr_ext_set(ptr, elen, is_sec1);
 
        if (sg_count == 1) {
                to_talitos_ptr(ptr, sg_dma_address(src) + offset, is_sec1);
@@ -1140,7 +1140,7 @@ int talitos_sg_map(struct device *dev, struct scatterlist *src,
                to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, 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*/
@@ -1154,6 +1154,15 @@ 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
  */
@@ -1171,7 +1180,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);
@@ -1225,20 +1234,12 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
         * extent is bytes of HMAC postpended to ciphertext,
         * typically 12 for ipsec
         */
-       to_talitos_ptr_len(&desc->ptr[4], cryptlen, is_sec1);
-       to_talitos_ptr_ext_set(&desc->ptr[4], 0, is_sec1);
-
-       sg_link_tbl_len = cryptlen;
-
-       if (desc->hdr & DESC_HDR_TYPE_IPSEC_ESP) {
-               to_talitos_ptr_ext_set(&desc->ptr[4], authsize, is_sec1);
-
-               if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
-                       sg_link_tbl_len += authsize;
-       }
+       if ((desc->hdr & DESC_HDR_TYPE_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;