Skip to content

Commit

Permalink
crypto: talitos - properly handle split ICV.
Browse files Browse the repository at this point in the history
[ Upstream commit eae55a5 ]

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: 9c4a796 ("crypto: talitos - Freescale integrated security engine (SEC) driver")
Signed-off-by: Christophe Leroy <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
chleroy authored and gregkh committed Jul 31, 2019
1 parent 846ed29 commit 8ebeb03
Showing 1 changed file with 15 additions and 11 deletions.
26 changes: 15 additions & 11 deletions drivers/crypto/talitos.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 8ebeb03

Please sign in to comment.