4.19-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Biggers <[email protected]>

commit d644f1c8746ed24f81075480f9e9cb3777ae8d65 upstream.

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: <[email protected]> # v4.18+
Cc: Ondrej Mosnacek <[email protected]>
Signed-off-by: Eric Biggers <[email protected]>
Reviewed-by: Ondrej Mosnacek <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
 crypto/morus1280.c |   13 +++++++------
 crypto/morus640.c  |   13 +++++++------
 2 files changed, 14 insertions(+), 12 deletions(-)

--- a/crypto/morus1280.c
+++ b/crypto/morus1280.c
@@ -366,18 +366,19 @@ static void crypto_morus1280_process_cry
                                           const struct morus1280_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);
        }
 }
 
--- a/crypto/morus640.c
+++ b/crypto/morus640.c
@@ -365,18 +365,19 @@ static void crypto_morus640_process_cryp
                                          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);
        }
 }
 


Reply via email to