Commit 62293a37 authored by Horia Geanta's avatar Horia Geanta Committed by Herbert Xu

crypto: talitos - fix aead sglen for case 'dst != src'

For aead case when source and destination buffers are different,
there is an incorrect assumption that the source length includes the ICV
length. Fix this, since it leads to an oops when using sg_count() to
find the number of nents in the scatterlist:

Unable to handle kernel paging request for data at address 0x00000004
Faulting instruction address: 0xf2265a28
Oops: Kernel access of bad area, sig: 11 [#1]
SMP NR_CPUS=8 P2020 RDB
Modules linked in: talitos(+)
CPU: 1 PID: 2187 Comm: cryptomgr_test Not tainted 3.11.0 #12
task: c4e72e20 ti: ef634000 task.ti: ef634000
NIP: f2265a28 LR: f2266ad8 CTR: c000c900
REGS: ef635bb0 TRAP: 0300   Not tainted  (3.11.0)
MSR: 00029000 <CE,EE,ME>  CR: 42042084  XER: 00000000
DEAR: 00000004, ESR: 00000000

GPR00: f2266e10 ef635c60 c4e72e20 00000001 00000014 ef635c69 00000001 c11f3082
GPR08: 00000010 00000000 00000002 2f635d58 22044084 00000000 00000000 c0755c80
GPR16: c4bf1000 ef784000 00000000 00000000 00000020 00000014 00000010 ef2f6100
GPR24: ef2f6200 00000024 ef143210 ef2f6000 00000000 ef635d58 00000000 2f635d58
NIP [f2265a28] sg_count+0x1c/0xb4 [talitos]
LR [f2266ad8] talitos_edesc_alloc+0x12c/0x410 [talitos]
Call Trace:
[ef635c60] [c0552068] schedule_timeout+0x148/0x1ac (unreliable)
[ef635cc0] [f2266e10] aead_edesc_alloc+0x54/0x64 [talitos]
[ef635ce0] [f22680f0] aead_encrypt+0x24/0x70 [talitos]
[ef635cf0] [c024b948] __test_aead+0x494/0xf68
[ef635e20] [c024d54c] test_aead+0x64/0xcc
[ef635e40] [c024d604] alg_test_aead+0x50/0xc4
[ef635e60] [c024c838] alg_test+0x10c/0x2e4
[ef635ee0] [c0249d1c] cryptomgr_test+0x4c/0x54
[ef635ef0] [c005d598] kthread+0xa8/0xac
[ef635f40] [c000e3bc] ret_from_kernel_thread+0x5c/0x64
Instruction dump:
81230024 552807fe 0f080000 5523003a 4bffff24 39000000 2c040000 99050000
408100a0 7c691b78 38c00001 38600000 <80e90004> 38630001 8109000c 70ea0002
---[ end trace 4498123cd8478591 ]---
Signed-off-by: default avatarHoria Geanta <horia.geanta@freescale.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent bbf9c893
...@@ -1112,7 +1112,8 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, ...@@ -1112,7 +1112,8 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
unsigned int authsize, unsigned int authsize,
unsigned int ivsize, unsigned int ivsize,
int icv_stashing, int icv_stashing,
u32 cryptoflags) u32 cryptoflags,
bool encrypt)
{ {
struct talitos_edesc *edesc; struct talitos_edesc *edesc;
int assoc_nents = 0, src_nents, dst_nents, alloc_len, dma_len; int assoc_nents = 0, src_nents, dst_nents, alloc_len, dma_len;
...@@ -1145,19 +1146,17 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, ...@@ -1145,19 +1146,17 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
assoc_nents = assoc_nents ? assoc_nents + 1 : 2; assoc_nents = assoc_nents ? assoc_nents + 1 : 2;
} }
src_nents = sg_count(src, cryptlen + authsize, &src_chained); if (!dst || dst == src) {
src_nents = (src_nents == 1) ? 0 : src_nents; src_nents = sg_count(src, cryptlen + authsize, &src_chained);
src_nents = (src_nents == 1) ? 0 : src_nents;
if (!dst) { dst_nents = dst ? src_nents : 0;
dst_nents = 0; } else { /* dst && dst != src*/
} else { src_nents = sg_count(src, cryptlen + (encrypt ? 0 : authsize),
if (dst == src) { &src_chained);
dst_nents = src_nents; src_nents = (src_nents == 1) ? 0 : src_nents;
} else { dst_nents = sg_count(dst, cryptlen + (encrypt ? authsize : 0),
dst_nents = sg_count(dst, cryptlen + authsize, &dst_chained);
&dst_chained); dst_nents = (dst_nents == 1) ? 0 : dst_nents;
dst_nents = (dst_nents == 1) ? 0 : dst_nents;
}
} }
/* /*
...@@ -1208,7 +1207,7 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev, ...@@ -1208,7 +1207,7 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
} }
static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv, static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
int icv_stashing) int icv_stashing, bool encrypt)
{ {
struct crypto_aead *authenc = crypto_aead_reqtfm(areq); struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc); struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
...@@ -1217,7 +1216,7 @@ static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv, ...@@ -1217,7 +1216,7 @@ static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
return talitos_edesc_alloc(ctx->dev, areq->assoc, areq->src, areq->dst, return talitos_edesc_alloc(ctx->dev, areq->assoc, areq->src, areq->dst,
iv, areq->assoclen, areq->cryptlen, iv, areq->assoclen, areq->cryptlen,
ctx->authsize, ivsize, icv_stashing, ctx->authsize, ivsize, icv_stashing,
areq->base.flags); areq->base.flags, encrypt);
} }
static int aead_encrypt(struct aead_request *req) static int aead_encrypt(struct aead_request *req)
...@@ -1227,7 +1226,7 @@ static int aead_encrypt(struct aead_request *req) ...@@ -1227,7 +1226,7 @@ static int aead_encrypt(struct aead_request *req)
struct talitos_edesc *edesc; struct talitos_edesc *edesc;
/* allocate extended descriptor */ /* allocate extended descriptor */
edesc = aead_edesc_alloc(req, req->iv, 0); edesc = aead_edesc_alloc(req, req->iv, 0, true);
if (IS_ERR(edesc)) if (IS_ERR(edesc))
return PTR_ERR(edesc); return PTR_ERR(edesc);
...@@ -1250,7 +1249,7 @@ static int aead_decrypt(struct aead_request *req) ...@@ -1250,7 +1249,7 @@ static int aead_decrypt(struct aead_request *req)
req->cryptlen -= authsize; req->cryptlen -= authsize;
/* allocate extended descriptor */ /* allocate extended descriptor */
edesc = aead_edesc_alloc(req, req->iv, 1); edesc = aead_edesc_alloc(req, req->iv, 1, false);
if (IS_ERR(edesc)) if (IS_ERR(edesc))
return PTR_ERR(edesc); return PTR_ERR(edesc);
...@@ -1296,7 +1295,7 @@ static int aead_givencrypt(struct aead_givcrypt_request *req) ...@@ -1296,7 +1295,7 @@ static int aead_givencrypt(struct aead_givcrypt_request *req)
struct talitos_edesc *edesc; struct talitos_edesc *edesc;
/* allocate extended descriptor */ /* allocate extended descriptor */
edesc = aead_edesc_alloc(areq, req->giv, 0); edesc = aead_edesc_alloc(areq, req->giv, 0, true);
if (IS_ERR(edesc)) if (IS_ERR(edesc))
return PTR_ERR(edesc); return PTR_ERR(edesc);
...@@ -1452,7 +1451,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc, ...@@ -1452,7 +1451,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
} }
static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request * static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
areq) areq, bool encrypt)
{ {
struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
...@@ -1460,7 +1459,7 @@ static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request * ...@@ -1460,7 +1459,7 @@ static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
return talitos_edesc_alloc(ctx->dev, NULL, areq->src, areq->dst, return talitos_edesc_alloc(ctx->dev, NULL, areq->src, areq->dst,
areq->info, 0, areq->nbytes, 0, ivsize, 0, areq->info, 0, areq->nbytes, 0, ivsize, 0,
areq->base.flags); areq->base.flags, encrypt);
} }
static int ablkcipher_encrypt(struct ablkcipher_request *areq) static int ablkcipher_encrypt(struct ablkcipher_request *areq)
...@@ -1470,7 +1469,7 @@ static int ablkcipher_encrypt(struct ablkcipher_request *areq) ...@@ -1470,7 +1469,7 @@ static int ablkcipher_encrypt(struct ablkcipher_request *areq)
struct talitos_edesc *edesc; struct talitos_edesc *edesc;
/* allocate extended descriptor */ /* allocate extended descriptor */
edesc = ablkcipher_edesc_alloc(areq); edesc = ablkcipher_edesc_alloc(areq, true);
if (IS_ERR(edesc)) if (IS_ERR(edesc))
return PTR_ERR(edesc); return PTR_ERR(edesc);
...@@ -1487,7 +1486,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *areq) ...@@ -1487,7 +1486,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *areq)
struct talitos_edesc *edesc; struct talitos_edesc *edesc;
/* allocate extended descriptor */ /* allocate extended descriptor */
edesc = ablkcipher_edesc_alloc(areq); edesc = ablkcipher_edesc_alloc(areq, false);
if (IS_ERR(edesc)) if (IS_ERR(edesc))
return PTR_ERR(edesc); return PTR_ERR(edesc);
...@@ -1639,7 +1638,7 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq, ...@@ -1639,7 +1638,7 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq); struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
return talitos_edesc_alloc(ctx->dev, NULL, req_ctx->psrc, NULL, NULL, 0, return talitos_edesc_alloc(ctx->dev, NULL, req_ctx->psrc, NULL, NULL, 0,
nbytes, 0, 0, 0, areq->base.flags); nbytes, 0, 0, 0, areq->base.flags, false);
} }
static int ahash_init(struct ahash_request *areq) static int ahash_init(struct ahash_request *areq)
......
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