Commit e89d4cb6 authored by Christophe Leroy's avatar Christophe Leroy Committed by Greg Kroah-Hartman

crypto: talitos - Do not modify req->cryptlen on decryption.

commit 7ede4c36 upstream.

For decrypt, req->cryptlen includes the size of the authentication
part while all functions of the driver expect cryptlen to be
the size of the encrypted data.

As it is not expected to change req->cryptlen, this patch
implements local calculation of cryptlen.
Signed-off-by: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
Fixes: 9c4a7965 ("crypto: talitos - Freescale integrated security engine (SEC) driver")
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9aff4077
...@@ -959,11 +959,13 @@ static void talitos_sg_unmap(struct device *dev, ...@@ -959,11 +959,13 @@ static void talitos_sg_unmap(struct device *dev,
static void ipsec_esp_unmap(struct device *dev, static void ipsec_esp_unmap(struct device *dev,
struct talitos_edesc *edesc, struct talitos_edesc *edesc,
struct aead_request *areq) struct aead_request *areq, bool encrypt)
{ {
struct crypto_aead *aead = crypto_aead_reqtfm(areq); struct crypto_aead *aead = crypto_aead_reqtfm(areq);
struct talitos_ctx *ctx = crypto_aead_ctx(aead); struct talitos_ctx *ctx = crypto_aead_ctx(aead);
unsigned int ivsize = crypto_aead_ivsize(aead); unsigned int ivsize = crypto_aead_ivsize(aead);
unsigned int authsize = crypto_aead_authsize(aead);
unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP; bool is_ipsec_esp = edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP;
struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3]; struct talitos_ptr *civ_ptr = &edesc->desc.ptr[is_ipsec_esp ? 2 : 3];
...@@ -972,7 +974,7 @@ static void ipsec_esp_unmap(struct device *dev, ...@@ -972,7 +974,7 @@ static void ipsec_esp_unmap(struct device *dev,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE); unmap_single_talitos_ptr(dev, civ_ptr, DMA_TO_DEVICE);
talitos_sg_unmap(dev, edesc, areq->src, areq->dst, areq->cryptlen, talitos_sg_unmap(dev, edesc, areq->src, areq->dst, cryptlen,
areq->assoclen); areq->assoclen);
if (edesc->dma_len) if (edesc->dma_len)
...@@ -983,7 +985,7 @@ static void ipsec_esp_unmap(struct device *dev, ...@@ -983,7 +985,7 @@ static void ipsec_esp_unmap(struct device *dev,
unsigned int dst_nents = edesc->dst_nents ? : 1; unsigned int dst_nents = edesc->dst_nents ? : 1;
sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize, sg_pcopy_to_buffer(areq->dst, dst_nents, ctx->iv, ivsize,
areq->assoclen + areq->cryptlen - ivsize); areq->assoclen + cryptlen - ivsize);
} }
} }
...@@ -1005,7 +1007,7 @@ static void ipsec_esp_encrypt_done(struct device *dev, ...@@ -1005,7 +1007,7 @@ static void ipsec_esp_encrypt_done(struct device *dev,
edesc = container_of(desc, struct talitos_edesc, desc); edesc = container_of(desc, struct talitos_edesc, desc);
ipsec_esp_unmap(dev, edesc, areq); ipsec_esp_unmap(dev, edesc, areq, true);
/* copy the generated ICV to dst */ /* copy the generated ICV to dst */
if (edesc->icv_ool) { if (edesc->icv_ool) {
...@@ -1039,7 +1041,7 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev, ...@@ -1039,7 +1041,7 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev,
edesc = container_of(desc, struct talitos_edesc, desc); edesc = container_of(desc, struct talitos_edesc, desc);
ipsec_esp_unmap(dev, edesc, req); ipsec_esp_unmap(dev, edesc, req, false);
if (!err) { if (!err) {
char icvdata[SHA512_DIGEST_SIZE]; char icvdata[SHA512_DIGEST_SIZE];
...@@ -1085,7 +1087,7 @@ static void ipsec_esp_decrypt_hwauth_done(struct device *dev, ...@@ -1085,7 +1087,7 @@ static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
edesc = container_of(desc, struct talitos_edesc, desc); edesc = container_of(desc, struct talitos_edesc, desc);
ipsec_esp_unmap(dev, edesc, req); ipsec_esp_unmap(dev, edesc, req, false);
/* check ICV auth status */ /* check ICV auth status */
if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) != if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
...@@ -1188,6 +1190,7 @@ static int talitos_sg_map(struct device *dev, struct scatterlist *src, ...@@ -1188,6 +1190,7 @@ static int talitos_sg_map(struct device *dev, struct scatterlist *src,
* fill in and submit ipsec_esp descriptor * fill in and submit ipsec_esp descriptor
*/ */
static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
bool encrypt,
void (*callback)(struct device *dev, void (*callback)(struct device *dev,
struct talitos_desc *desc, struct talitos_desc *desc,
void *context, int error)) void *context, int error))
...@@ -1197,7 +1200,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, ...@@ -1197,7 +1200,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
struct talitos_ctx *ctx = crypto_aead_ctx(aead); struct talitos_ctx *ctx = crypto_aead_ctx(aead);
struct device *dev = ctx->dev; struct device *dev = ctx->dev;
struct talitos_desc *desc = &edesc->desc; struct talitos_desc *desc = &edesc->desc;
unsigned int cryptlen = areq->cryptlen; unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
unsigned int ivsize = crypto_aead_ivsize(aead); unsigned int ivsize = crypto_aead_ivsize(aead);
int tbl_off = 0; int tbl_off = 0;
int sg_count, ret; int sg_count, ret;
...@@ -1324,7 +1327,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, ...@@ -1324,7 +1327,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
ret = talitos_submit(dev, ctx->ch, desc, callback, areq); ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
if (ret != -EINPROGRESS) { if (ret != -EINPROGRESS) {
ipsec_esp_unmap(dev, edesc, areq); ipsec_esp_unmap(dev, edesc, areq, encrypt);
kfree(edesc); kfree(edesc);
} }
return ret; return ret;
...@@ -1438,9 +1441,10 @@ static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv, ...@@ -1438,9 +1441,10 @@ static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
unsigned int authsize = crypto_aead_authsize(authenc); unsigned int authsize = crypto_aead_authsize(authenc);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc); struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
unsigned int ivsize = crypto_aead_ivsize(authenc); unsigned int ivsize = crypto_aead_ivsize(authenc);
unsigned int cryptlen = areq->cryptlen - (encrypt ? 0 : authsize);
return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
iv, areq->assoclen, areq->cryptlen, iv, areq->assoclen, cryptlen,
authsize, ivsize, icv_stashing, authsize, ivsize, icv_stashing,
areq->base.flags, encrypt); areq->base.flags, encrypt);
} }
...@@ -1459,7 +1463,7 @@ static int aead_encrypt(struct aead_request *req) ...@@ -1459,7 +1463,7 @@ static int aead_encrypt(struct aead_request *req)
/* set encrypt */ /* set encrypt */
edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
return ipsec_esp(edesc, req, ipsec_esp_encrypt_done); return ipsec_esp(edesc, req, true, ipsec_esp_encrypt_done);
} }
static int aead_decrypt(struct aead_request *req) static int aead_decrypt(struct aead_request *req)
...@@ -1471,8 +1475,6 @@ static int aead_decrypt(struct aead_request *req) ...@@ -1471,8 +1475,6 @@ static int aead_decrypt(struct aead_request *req)
struct talitos_edesc *edesc; struct talitos_edesc *edesc;
void *icvdata; void *icvdata;
req->cryptlen -= authsize;
/* allocate extended descriptor */ /* allocate extended descriptor */
edesc = aead_edesc_alloc(req, req->iv, 1, false); edesc = aead_edesc_alloc(req, req->iv, 1, false);
if (IS_ERR(edesc)) if (IS_ERR(edesc))
...@@ -1489,7 +1491,8 @@ static int aead_decrypt(struct aead_request *req) ...@@ -1489,7 +1491,8 @@ static int aead_decrypt(struct aead_request *req)
/* reset integrity check result bits */ /* reset integrity check result bits */
return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done); return ipsec_esp(edesc, req, false,
ipsec_esp_decrypt_hwauth_done);
} }
/* Have to check the ICV with software */ /* Have to check the ICV with software */
...@@ -1505,7 +1508,7 @@ static int aead_decrypt(struct aead_request *req) ...@@ -1505,7 +1508,7 @@ static int aead_decrypt(struct aead_request *req)
sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize, sg_pcopy_to_buffer(req->src, edesc->src_nents ? : 1, icvdata, authsize,
req->assoclen + req->cryptlen - authsize); req->assoclen + req->cryptlen - authsize);
return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done); return ipsec_esp(edesc, req, false, ipsec_esp_decrypt_swauth_done);
} }
static int ablkcipher_setkey(struct crypto_ablkcipher *cipher, static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment