summaryrefslogtreecommitdiff
path: root/crypto/aegis128-core.c
diff options
context:
space:
mode:
authorArd Biesheuvel <ardb@kernel.org>2020-11-17 14:32:13 +0100
committerHerbert Xu <herbert@gondor.apana.org.au>2020-11-27 17:13:40 +1100
commit2664e3ee1b5cedc5d4acd2c1e4c9b2f2e3a865a0 (patch)
tree1270dc913e404bf990e6faf33be8828831676f1c /crypto/aegis128-core.c
parent71bbed437c533f08c19535abe2c1fe92cbdabc1c (diff)
downloadlinux-crypto-2664e3ee1b5cedc5d4acd2c1e4c9b2f2e3a865a0.tar.gz
linux-crypto-2664e3ee1b5cedc5d4acd2c1e4c9b2f2e3a865a0.zip
crypto: aegis128/neon - move final tag check to SIMD domain
Instead of calculating the tag and returning it to the caller on decryption, use a SIMD compare and min across vector to perform the comparison. This is slightly more efficient, and removes the need on the caller's part to wipe the tag from memory if the decryption failed. While at it, switch to unsigned int when passing cryptlen and assoclen - we don't support input sizes where it matters anyway. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Ondrej Mosnacek <omosnacek@gmail.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/aegis128-core.c')
-rw-r--r--crypto/aegis128-core.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/crypto/aegis128-core.c b/crypto/aegis128-core.c
index 3a712358..859c7b90 100644
--- a/crypto/aegis128-core.c
+++ b/crypto/aegis128-core.c
@@ -67,9 +67,11 @@ void crypto_aegis128_encrypt_chunk_simd(struct aegis_state *state, u8 *dst,
const u8 *src, unsigned int size);
void crypto_aegis128_decrypt_chunk_simd(struct aegis_state *state, u8 *dst,
const u8 *src, unsigned int size);
-void crypto_aegis128_final_simd(struct aegis_state *state,
- union aegis_block *tag_xor,
- u64 assoclen, u64 cryptlen);
+int crypto_aegis128_final_simd(struct aegis_state *state,
+ union aegis_block *tag_xor,
+ unsigned int assoclen,
+ unsigned int cryptlen,
+ unsigned int authsize);
static void crypto_aegis128_update(struct aegis_state *state)
{
@@ -411,7 +413,7 @@ static int crypto_aegis128_encrypt(struct aead_request *req)
crypto_aegis128_process_crypt(&state, &walk,
crypto_aegis128_encrypt_chunk_simd);
crypto_aegis128_final_simd(&state, &tag, req->assoclen,
- cryptlen);
+ cryptlen, 0);
} else {
crypto_aegis128_init(&state, &ctx->key, req->iv);
crypto_aegis128_process_ad(&state, req->src, req->assoclen);
@@ -445,8 +447,15 @@ static int crypto_aegis128_decrypt(struct aead_request *req)
crypto_aegis128_process_ad(&state, req->src, req->assoclen);
crypto_aegis128_process_crypt(&state, &walk,
crypto_aegis128_decrypt_chunk_simd);
- crypto_aegis128_final_simd(&state, &tag, req->assoclen,
- cryptlen);
+ if (unlikely(crypto_aegis128_final_simd(&state, &tag,
+ req->assoclen,
+ cryptlen, authsize))) {
+ skcipher_walk_aead_decrypt(&walk, req, false);
+ crypto_aegis128_process_crypt(NULL, req, &walk,
+ crypto_aegis128_wipe_chunk);
+ return -EBADMSG;
+ }
+ return 0;
} else {
crypto_aegis128_init(&state, &ctx->key, req->iv);
crypto_aegis128_process_ad(&state, req->src, req->assoclen);