Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eae55a58 authored by Christophe Leroy's avatar Christophe Leroy Committed by Herbert Xu
Browse files

crypto: talitos - properly handle split ICV.



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: 9c4a7965 ("crypto: talitos - Freescale integrated security engine (SEC) driver")
Signed-off-by: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 4bbfb839
Loading
Loading
Loading
Loading
+15 −11
Original line number Diff line number Diff line
@@ -1069,7 +1069,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);
@@ -1083,9 +1082,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);
@@ -1103,7 +1101,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);
@@ -1113,9 +1110,18 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev,
	ipsec_esp_unmap(dev, edesc, req, false);

	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)
@@ -1537,7 +1543,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;

	/* allocate extended descriptor */
@@ -1571,9 +1576,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, false, ipsec_esp_decrypt_swauth_done);
}