]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
crypto: morus - fix handling chunked inputs
authorEric Biggers <ebiggers@google.com>
Fri, 1 Feb 2019 07:51:37 +0000 (23:51 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 Mar 2019 19:09:54 +0000 (20:09 +0100)
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: <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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
crypto/morus1280.c
crypto/morus640.c

index 3889c188f26653095835c4222a2c782584ca5aa6..b83576b4eb553d80019413a3f6885e705d68f2f1 100644 (file)
@@ -366,18 +366,19 @@ static void crypto_morus1280_process_crypt(struct morus1280_state *state,
                                           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);
        }
 }
 
index da06ec2f6a807ae6e1a8290d3178b726a38b9866..b6a477444f6de742355e3fedb8cc99f923bfc786 100644 (file)
@@ -365,18 +365,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);
        }
 }