Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d644f1c8 authored by Eric Biggers's avatar Eric Biggers Committed by Herbert Xu
Browse files

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: 396be41f ("crypto: morus - Add generic MORUS AEAD implementations")
Cc: <stable@vger.kernel.org> # v4.18+
Cc: Ondrej Mosnacek <omosnace@redhat.com>
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Reviewed-by: default avatarOndrej Mosnacek <omosnace@redhat.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 0f533e67
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -362,18 +362,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);
	}
}

+7 −6
Original line number Diff line number Diff line
@@ -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);
	}
}