Skip to content

Commit 580e295

Browse files
ebiggersherbertx
authored andcommitted
crypto: arm64/gcm-aes-ce - fix no-NEON fallback code
The arm64 gcm-aes-ce algorithm is failing the extra crypto self-tests following my patches to test the !may_use_simd() code paths, which previously were untested. The problem is that in the !may_use_simd() case, an odd number of AES blocks can be processed within each step of the skcipher_walk. However, the skcipher_walk is being done with a "stride" of 2 blocks and is advanced by an even number of blocks after each step. This causes the encryption to produce the wrong ciphertext and authentication tag, and causes the decryption to incorrectly fail. Fix it by only processing an even number of blocks per step. Fixes: c2b24c3 ("crypto: arm64/aes-gcm-ce - fix scatterwalk API violation") Fixes: 71e52c2 ("crypto: arm64/aes-ce-gcm - operate on two input blocks at a time") Cc: <[email protected]> # v4.19+ Signed-off-by: Eric Biggers <[email protected]> Reviewed-by: Ard Biesheuvel <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 7aceaae commit 580e295

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

arch/arm64/crypto/ghash-ce-glue.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,9 +473,11 @@ static int gcm_encrypt(struct aead_request *req)
473473
put_unaligned_be32(2, iv + GCM_IV_SIZE);
474474

475475
while (walk.nbytes >= (2 * AES_BLOCK_SIZE)) {
476-
int blocks = walk.nbytes / AES_BLOCK_SIZE;
476+
const int blocks =
477+
walk.nbytes / (2 * AES_BLOCK_SIZE) * 2;
477478
u8 *dst = walk.dst.virt.addr;
478479
u8 *src = walk.src.virt.addr;
480+
int remaining = blocks;
479481

480482
do {
481483
__aes_arm64_encrypt(ctx->aes_key.key_enc,
@@ -485,9 +487,9 @@ static int gcm_encrypt(struct aead_request *req)
485487

486488
dst += AES_BLOCK_SIZE;
487489
src += AES_BLOCK_SIZE;
488-
} while (--blocks > 0);
490+
} while (--remaining > 0);
489491

490-
ghash_do_update(walk.nbytes / AES_BLOCK_SIZE, dg,
492+
ghash_do_update(blocks, dg,
491493
walk.dst.virt.addr, &ctx->ghash_key,
492494
NULL, pmull_ghash_update_p64);
493495

@@ -609,7 +611,7 @@ static int gcm_decrypt(struct aead_request *req)
609611
put_unaligned_be32(2, iv + GCM_IV_SIZE);
610612

611613
while (walk.nbytes >= (2 * AES_BLOCK_SIZE)) {
612-
int blocks = walk.nbytes / AES_BLOCK_SIZE;
614+
int blocks = walk.nbytes / (2 * AES_BLOCK_SIZE) * 2;
613615
u8 *dst = walk.dst.virt.addr;
614616
u8 *src = walk.src.virt.addr;
615617

0 commit comments

Comments
 (0)