diff options
author | Eric Biggers <ebiggers@google.com> | 2019-01-31 23:51:37 -0800 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2019-02-08 15:30:08 +0800 |
commit | d644f1c8746ed24f81075480f9e9cb3777ae8d65 (patch) | |
tree | 031ca8c64d91586823c8e8a4360a58abdfa00297 /crypto/morus640.c | |
parent | 0f533e67d26f228ea5dfdacc8a4bdeb487af5208 (diff) | |
download | linux-stable-d644f1c8746ed24f81075480f9e9cb3777ae8d65.tar.gz linux-stable-d644f1c8746ed24f81075480f9e9cb3777ae8d65.tar.bz2 linux-stable-d644f1c8746ed24f81075480f9e9cb3777ae8d65.zip |
crypto: morus - fix handling chunked inputs
The generic MORUS 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: 396be41f16fd ("crypto: morus - Add generic MORUS 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>
Diffstat (limited to 'crypto/morus640.c')
-rw-r--r-- | crypto/morus640.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/crypto/morus640.c b/crypto/morus640.c index 5cf530139b27..1617a1eb8be1 100644 --- a/crypto/morus640.c +++ b/crypto/morus640.c @@ -361,18 +361,19 @@ static void crypto_morus640_process_crypt(struct morus640_state *state, const struct morus640_ops *ops) { struct skcipher_walk walk; - u8 *dst; - const u8 *src; ops->skcipher_walk_init(&walk, req, false); while (walk.nbytes) { - src = walk.src.virt.addr; - dst = walk.dst.virt.addr; + unsigned int nbytes = walk.nbytes; - ops->crypt_chunk(state, dst, src, walk.nbytes); + 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); } } |