summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-01-31 23:51:36 -0800
committerHerbert Xu <herbert@gondor.apana.org.au>2019-02-08 15:30:08 +0800
commit0f533e67d26f228ea5dfdacc8a4bdeb487af5208 (patch)
tree2124e65bceaf4d859803284f4e98f99beceee967
parent42e95d1f10dcf8b18b1d7f52f7068985b3dc5b79 (diff)
downloadlinux-0f533e67d26f228ea5dfdacc8a4bdeb487af5208.tar.bz2
crypto: aegis - fix handling chunked inputs
The generic AEGIS implementations all fail the improved AEAD tests because they produce the wrong result with some data layouts. The issue is that they assume that if the skcipher_walk API gives 'nbytes' not aligned to the walksize (a.k.a. walk.stride), then it is the end of the data. In fact, this can happen before the end. Fix them. Fixes: f606a88e5823 ("crypto: aegis - Add generic AEGIS AEAD implementations") Cc: <stable@vger.kernel.org> # v4.18+ Cc: Ondrej Mosnacek <omosnace@redhat.com> Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/aegis128.c14
-rw-r--r--crypto/aegis128l.c14
-rw-r--r--crypto/aegis256.c14
3 files changed, 21 insertions, 21 deletions
diff --git a/crypto/aegis128.c b/crypto/aegis128.c
index 96e078a8a00a..3718a8341303 100644
--- a/crypto/aegis128.c
+++ b/crypto/aegis128.c
@@ -286,19 +286,19 @@ static void crypto_aegis128_process_crypt(struct aegis_state *state,
const struct aegis128_ops *ops)
{
struct skcipher_walk walk;
- u8 *src, *dst;
- unsigned int chunksize;
ops->skcipher_walk_init(&walk, req, false);
while (walk.nbytes) {
- src = walk.src.virt.addr;
- dst = walk.dst.virt.addr;
- chunksize = walk.nbytes;
+ unsigned int nbytes = walk.nbytes;
- ops->crypt_chunk(state, dst, src, chunksize);
+ if (nbytes < walk.total)
+ nbytes = round_down(nbytes, walk.stride);
- skcipher_walk_done(&walk, 0);
+ ops->crypt_chunk(state, walk.dst.virt.addr, walk.src.virt.addr,
+ nbytes);
+
+ skcipher_walk_done(&walk, walk.nbytes - nbytes);
}
}
diff --git a/crypto/aegis128l.c b/crypto/aegis128l.c
index a210e779b911..275a8616d71b 100644
--- a/crypto/aegis128l.c
+++ b/crypto/aegis128l.c
@@ -349,19 +349,19 @@ static void crypto_aegis128l_process_crypt(struct aegis_state *state,
const struct aegis128l_ops *ops)
{
struct skcipher_walk walk;
- u8 *src, *dst;
- unsigned int chunksize;
ops->skcipher_walk_init(&walk, req, false);
while (walk.nbytes) {
- src = walk.src.virt.addr;
- dst = walk.dst.virt.addr;
- chunksize = walk.nbytes;
+ unsigned int nbytes = walk.nbytes;
- ops->crypt_chunk(state, dst, src, chunksize);
+ if (nbytes < walk.total)
+ nbytes = round_down(nbytes, walk.stride);
- skcipher_walk_done(&walk, 0);
+ ops->crypt_chunk(state, walk.dst.virt.addr, walk.src.virt.addr,
+ nbytes);
+
+ skcipher_walk_done(&walk, walk.nbytes - nbytes);
}
}
diff --git a/crypto/aegis256.c b/crypto/aegis256.c
index 49882a28e93e..ecd6b7f34a2d 100644
--- a/crypto/aegis256.c
+++ b/crypto/aegis256.c
@@ -299,19 +299,19 @@ static void crypto_aegis256_process_crypt(struct aegis_state *state,
const struct aegis256_ops *ops)
{
struct skcipher_walk walk;
- u8 *src, *dst;
- unsigned int chunksize;
ops->skcipher_walk_init(&walk, req, false);
while (walk.nbytes) {
- src = walk.src.virt.addr;
- dst = walk.dst.virt.addr;
- chunksize = walk.nbytes;
+ unsigned int nbytes = walk.nbytes;
- ops->crypt_chunk(state, dst, src, chunksize);
+ if (nbytes < walk.total)
+ nbytes = round_down(nbytes, walk.stride);
- skcipher_walk_done(&walk, 0);
+ ops->crypt_chunk(state, walk.dst.virt.addr, walk.src.virt.addr,
+ nbytes);
+
+ skcipher_walk_done(&walk, walk.nbytes - nbytes);
}
}