summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-02-01 02:51:37 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2019-02-08 02:30:08 -0500
commitd644f1c8746ed24f81075480f9e9cb3777ae8d65 (patch)
tree031ca8c64d91586823c8e8a4360a58abdfa00297
parent0f533e67d26f228ea5dfdacc8a4bdeb487af5208 (diff)
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>
-rw-r--r--crypto/morus1280.c13
-rw-r--r--crypto/morus640.c13
2 files changed, 14 insertions, 12 deletions
diff --git a/crypto/morus1280.c b/crypto/morus1280.c
index 78ba09db7328..0747732d5b78 100644
--- a/crypto/morus1280.c
+++ b/crypto/morus1280.c
@@ -362,18 +362,19 @@ static void crypto_morus1280_process_crypt(struct morus1280_state *state,
362 const struct morus1280_ops *ops) 362 const struct morus1280_ops *ops)
363{ 363{
364 struct skcipher_walk walk; 364 struct skcipher_walk walk;
365 u8 *dst;
366 const u8 *src;
367 365
368 ops->skcipher_walk_init(&walk, req, false); 366 ops->skcipher_walk_init(&walk, req, false);
369 367
370 while (walk.nbytes) { 368 while (walk.nbytes) {
371 src = walk.src.virt.addr; 369 unsigned int nbytes = walk.nbytes;
372 dst = walk.dst.virt.addr;
373 370
374 ops->crypt_chunk(state, dst, src, walk.nbytes); 371 if (nbytes < walk.total)
372 nbytes = round_down(nbytes, walk.stride);
375 373
376 skcipher_walk_done(&walk, 0); 374 ops->crypt_chunk(state, walk.dst.virt.addr, walk.src.virt.addr,
375 nbytes);
376
377 skcipher_walk_done(&walk, walk.nbytes - nbytes);
377 } 378 }
378} 379}
379 380
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,
361 const struct morus640_ops *ops) 361 const struct morus640_ops *ops)
362{ 362{
363 struct skcipher_walk walk; 363 struct skcipher_walk walk;
364 u8 *dst;
365 const u8 *src;
366 364
367 ops->skcipher_walk_init(&walk, req, false); 365 ops->skcipher_walk_init(&walk, req, false);
368 366
369 while (walk.nbytes) { 367 while (walk.nbytes) {
370 src = walk.src.virt.addr; 368 unsigned int nbytes = walk.nbytes;
371 dst = walk.dst.virt.addr;
372 369
373 ops->crypt_chunk(state, dst, src, walk.nbytes); 370 if (nbytes < walk.total)
371 nbytes = round_down(nbytes, walk.stride);
374 372
375 skcipher_walk_done(&walk, 0); 373 ops->crypt_chunk(state, walk.dst.virt.addr, walk.src.virt.addr,
374 nbytes);
375
376 skcipher_walk_done(&walk, walk.nbytes - nbytes);
376 } 377 }
377} 378}
378 379