| From e108b2898a88ac654e978f0ec40f426e6aefe2f5 Mon Sep 17 00:00:00 2001 |
| From: Christophe Leroy <christophe.leroy@c-s.fr> |
| Date: Tue, 21 May 2019 13:34:17 +0000 |
| Subject: crypto: talitos - properly handle split ICV. |
| |
| [ 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> |
| --- |
| drivers/crypto/talitos.c | 26 +++++++++++++++----------- |
| 1 file changed, 15 insertions(+), 11 deletions(-) |
| |
| diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c |
| index 0b12772c7919..e7864aa494a1 100644 |
| --- a/drivers/crypto/talitos.c |
| +++ b/drivers/crypto/talitos.c |
| @@ -984,7 +984,6 @@ static void ipsec_esp_encrypt_done(struct device *dev, |
| struct crypto_aead *authenc = crypto_aead_reqtfm(areq); |
| unsigned int authsize = crypto_aead_authsize(authenc); |
| struct talitos_edesc *edesc; |
| - struct scatterlist *sg; |
| void *icvdata; |
| |
| edesc = container_of(desc, struct talitos_edesc, desc); |
| @@ -998,9 +997,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); |
| } |
| |
| kfree(edesc); |
| @@ -1016,7 +1014,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); |
| @@ -1026,9 +1023,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) |
| @@ -1458,7 +1464,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; |
| @@ -1493,9 +1498,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); |
| } |
| -- |
| 2.20.1 |
| |