]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
crypto: talitos - properly handle split ICV.
authorChristophe Leroy <christophe.leroy@c-s.fr>
Tue, 21 May 2019 13:34:17 +0000 (13:34 +0000)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Wed, 14 Aug 2019 09:18:49 +0000 (11:18 +0200)
BugLink: https://bugs.launchpad.net/bugs/1839036
[ Upstream commit eae55a586c3c8b50982bad3c3426e9c9dd7a0075 ]

The driver assumes that the ICV is as a single piece in the last
element of the scatterlist. This assumption is wrong.

This patch ensures that the ICV is properly handled regardless of
the scatterlist layout.

Fixes: 9c4a79653b35 ("crypto: talitos - Freescale integrated security engine (SEC) driver")
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/crypto/talitos.c

index 529801c2bcbfe90c51f3770039f6577c6a15c046..982a38eea4c6dd17c13a6dfd0cfee847a54f4fb0 100644 (file)
@@ -981,7 +981,6 @@ static void ipsec_esp_encrypt_done(struct device *dev,
        unsigned int authsize = crypto_aead_authsize(authenc);
        unsigned int ivsize = crypto_aead_ivsize(authenc);
        struct talitos_edesc *edesc;
-       struct scatterlist *sg;
        void *icvdata;
 
        edesc = container_of(desc, struct talitos_edesc, desc);
@@ -995,9 +994,8 @@ static void ipsec_esp_encrypt_done(struct device *dev,
                else
                        icvdata = &edesc->link_tbl[edesc->src_nents +
                                                   edesc->dst_nents + 2];
-               sg = sg_last(areq->dst, edesc->dst_nents);
-               memcpy((char *)sg_virt(sg) + sg->length - authsize,
-                      icvdata, authsize);
+               sg_pcopy_from_buffer(areq->dst, edesc->dst_nents ? : 1, icvdata,
+                                    authsize, areq->assoclen + areq->cryptlen);
        }
 
        dma_unmap_single(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
@@ -1015,7 +1013,6 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev,
        struct crypto_aead *authenc = crypto_aead_reqtfm(req);
        unsigned int authsize = crypto_aead_authsize(authenc);
        struct talitos_edesc *edesc;
-       struct scatterlist *sg;
        char *oicv, *icv;
        struct talitos_private *priv = dev_get_drvdata(dev);
        bool is_sec1 = has_ftr_sec1(priv);
@@ -1025,9 +1022,18 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev,
        ipsec_esp_unmap(dev, edesc, req);
 
        if (!err) {
+               char icvdata[SHA512_DIGEST_SIZE];
+               int nents = edesc->dst_nents ? : 1;
+               unsigned int len = req->assoclen + req->cryptlen;
+
                /* auth check */
-               sg = sg_last(req->dst, edesc->dst_nents ? : 1);
-               icv = (char *)sg_virt(sg) + sg->length - authsize;
+               if (nents > 1) {
+                       sg_pcopy_to_buffer(req->dst, nents, icvdata, authsize,
+                                          len - authsize);
+                       icv = icvdata;
+               } else {
+                       icv = (char *)sg_virt(req->dst) + len - authsize;
+               }
 
                if (edesc->dma_len) {
                        if (is_sec1)
@@ -1443,7 +1449,6 @@ static int aead_decrypt(struct aead_request *req)
        struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
        struct talitos_private *priv = dev_get_drvdata(ctx->dev);
        struct talitos_edesc *edesc;
-       struct scatterlist *sg;
        void *icvdata;
 
        req->cryptlen -= authsize;
@@ -1477,9 +1482,8 @@ static int aead_decrypt(struct aead_request *req)
        else
                icvdata = &edesc->link_tbl[0];
 
-       sg = sg_last(req->src, edesc->src_nents ? : 1);
-
-       memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
+       sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize,
+                          req->assoclen + req->cryptlen - authsize);
 
        return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
 }