diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2019-07-03 04:55:10 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2019-07-26 01:03:58 -0400 |
commit | 7cdc0ddbf74a19cecb2f0e9efa2cae9d3c665189 (patch) | |
tree | 5b44bcb399174e6d64d90ef96e0a80e42350b609 | |
parent | 521cdde758bf331d4e264ef3deef5a26d5ce0b4f (diff) |
crypto: aegis128 - add support for SIMD acceleration
Add some plumbing to allow the AEGIS128 code to be built with SIMD
routines for acceleration.
Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | crypto/Makefile | 1 | ||||
-rw-r--r-- | crypto/aegis.h | 14 | ||||
-rw-r--r-- | crypto/aegis128-core.c (renamed from crypto/aegis128.c) | 42 |
3 files changed, 46 insertions, 11 deletions
diff --git a/crypto/Makefile b/crypto/Makefile index 93375e124ff7..362a36f0bd2f 100644 --- a/crypto/Makefile +++ b/crypto/Makefile | |||
@@ -90,6 +90,7 @@ obj-$(CONFIG_CRYPTO_GCM) += gcm.o | |||
90 | obj-$(CONFIG_CRYPTO_CCM) += ccm.o | 90 | obj-$(CONFIG_CRYPTO_CCM) += ccm.o |
91 | obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o | 91 | obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o |
92 | obj-$(CONFIG_CRYPTO_AEGIS128) += aegis128.o | 92 | obj-$(CONFIG_CRYPTO_AEGIS128) += aegis128.o |
93 | aegis128-y := aegis128-core.o | ||
93 | obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o | 94 | obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o |
94 | obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o | 95 | obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o |
95 | obj-$(CONFIG_CRYPTO_DES) += des_generic.o | 96 | obj-$(CONFIG_CRYPTO_DES) += des_generic.o |
diff --git a/crypto/aegis.h b/crypto/aegis.h index 3308066ddde0..6cb65a497ba2 100644 --- a/crypto/aegis.h +++ b/crypto/aegis.h | |||
@@ -35,23 +35,23 @@ static const union aegis_block crypto_aegis_const[2] = { | |||
35 | } }, | 35 | } }, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static void crypto_aegis_block_xor(union aegis_block *dst, | 38 | static inline void crypto_aegis_block_xor(union aegis_block *dst, |
39 | const union aegis_block *src) | 39 | const union aegis_block *src) |
40 | { | 40 | { |
41 | dst->words64[0] ^= src->words64[0]; | 41 | dst->words64[0] ^= src->words64[0]; |
42 | dst->words64[1] ^= src->words64[1]; | 42 | dst->words64[1] ^= src->words64[1]; |
43 | } | 43 | } |
44 | 44 | ||
45 | static void crypto_aegis_block_and(union aegis_block *dst, | 45 | static inline void crypto_aegis_block_and(union aegis_block *dst, |
46 | const union aegis_block *src) | 46 | const union aegis_block *src) |
47 | { | 47 | { |
48 | dst->words64[0] &= src->words64[0]; | 48 | dst->words64[0] &= src->words64[0]; |
49 | dst->words64[1] &= src->words64[1]; | 49 | dst->words64[1] &= src->words64[1]; |
50 | } | 50 | } |
51 | 51 | ||
52 | static void crypto_aegis_aesenc(union aegis_block *dst, | 52 | static inline void crypto_aegis_aesenc(union aegis_block *dst, |
53 | const union aegis_block *src, | 53 | const union aegis_block *src, |
54 | const union aegis_block *key) | 54 | const union aegis_block *key) |
55 | { | 55 | { |
56 | const u8 *s = src->bytes; | 56 | const u8 *s = src->bytes; |
57 | const u32 *t = crypto_ft_tab[0]; | 57 | const u32 *t = crypto_ft_tab[0]; |
diff --git a/crypto/aegis128.c b/crypto/aegis128-core.c index 32840d5e7f65..f815b4685156 100644 --- a/crypto/aegis128.c +++ b/crypto/aegis128-core.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <crypto/algapi.h> | 9 | #include <crypto/algapi.h> |
10 | #include <crypto/internal/aead.h> | 10 | #include <crypto/internal/aead.h> |
11 | #include <crypto/internal/simd.h> | ||
11 | #include <crypto/internal/skcipher.h> | 12 | #include <crypto/internal/skcipher.h> |
12 | #include <crypto/scatterwalk.h> | 13 | #include <crypto/scatterwalk.h> |
13 | #include <linux/err.h> | 14 | #include <linux/err.h> |
@@ -15,6 +16,7 @@ | |||
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | #include <linux/scatterlist.h> | 18 | #include <linux/scatterlist.h> |
19 | #include <asm/simd.h> | ||
18 | 20 | ||
19 | #include "aegis.h" | 21 | #include "aegis.h" |
20 | 22 | ||
@@ -40,6 +42,15 @@ struct aegis128_ops { | |||
40 | const u8 *src, unsigned int size); | 42 | const u8 *src, unsigned int size); |
41 | }; | 43 | }; |
42 | 44 | ||
45 | static bool have_simd; | ||
46 | |||
47 | bool crypto_aegis128_have_simd(void); | ||
48 | void crypto_aegis128_update_simd(struct aegis_state *state, const void *msg); | ||
49 | void crypto_aegis128_encrypt_chunk_simd(struct aegis_state *state, u8 *dst, | ||
50 | const u8 *src, unsigned int size); | ||
51 | void crypto_aegis128_decrypt_chunk_simd(struct aegis_state *state, u8 *dst, | ||
52 | const u8 *src, unsigned int size); | ||
53 | |||
43 | static void crypto_aegis128_update(struct aegis_state *state) | 54 | static void crypto_aegis128_update(struct aegis_state *state) |
44 | { | 55 | { |
45 | union aegis_block tmp; | 56 | union aegis_block tmp; |
@@ -55,12 +66,22 @@ static void crypto_aegis128_update(struct aegis_state *state) | |||
55 | static void crypto_aegis128_update_a(struct aegis_state *state, | 66 | static void crypto_aegis128_update_a(struct aegis_state *state, |
56 | const union aegis_block *msg) | 67 | const union aegis_block *msg) |
57 | { | 68 | { |
69 | if (have_simd && crypto_simd_usable()) { | ||
70 | crypto_aegis128_update_simd(state, msg); | ||
71 | return; | ||
72 | } | ||
73 | |||
58 | crypto_aegis128_update(state); | 74 | crypto_aegis128_update(state); |
59 | crypto_aegis_block_xor(&state->blocks[0], msg); | 75 | crypto_aegis_block_xor(&state->blocks[0], msg); |
60 | } | 76 | } |
61 | 77 | ||
62 | static void crypto_aegis128_update_u(struct aegis_state *state, const void *msg) | 78 | static void crypto_aegis128_update_u(struct aegis_state *state, const void *msg) |
63 | { | 79 | { |
80 | if (have_simd && crypto_simd_usable()) { | ||
81 | crypto_aegis128_update_simd(state, msg); | ||
82 | return; | ||
83 | } | ||
84 | |||
64 | crypto_aegis128_update(state); | 85 | crypto_aegis128_update(state); |
65 | crypto_xor(state->blocks[0].bytes, msg, AEGIS_BLOCK_SIZE); | 86 | crypto_xor(state->blocks[0].bytes, msg, AEGIS_BLOCK_SIZE); |
66 | } | 87 | } |
@@ -365,7 +386,7 @@ static void crypto_aegis128_crypt(struct aead_request *req, | |||
365 | 386 | ||
366 | static int crypto_aegis128_encrypt(struct aead_request *req) | 387 | static int crypto_aegis128_encrypt(struct aead_request *req) |
367 | { | 388 | { |
368 | static const struct aegis128_ops ops = { | 389 | const struct aegis128_ops *ops = &(struct aegis128_ops){ |
369 | .skcipher_walk_init = skcipher_walk_aead_encrypt, | 390 | .skcipher_walk_init = skcipher_walk_aead_encrypt, |
370 | .crypt_chunk = crypto_aegis128_encrypt_chunk, | 391 | .crypt_chunk = crypto_aegis128_encrypt_chunk, |
371 | }; | 392 | }; |
@@ -375,7 +396,12 @@ static int crypto_aegis128_encrypt(struct aead_request *req) | |||
375 | unsigned int authsize = crypto_aead_authsize(tfm); | 396 | unsigned int authsize = crypto_aead_authsize(tfm); |
376 | unsigned int cryptlen = req->cryptlen; | 397 | unsigned int cryptlen = req->cryptlen; |
377 | 398 | ||
378 | crypto_aegis128_crypt(req, &tag, cryptlen, &ops); | 399 | if (have_simd && crypto_simd_usable()) |
400 | ops = &(struct aegis128_ops){ | ||
401 | .skcipher_walk_init = skcipher_walk_aead_encrypt, | ||
402 | .crypt_chunk = crypto_aegis128_encrypt_chunk_simd }; | ||
403 | |||
404 | crypto_aegis128_crypt(req, &tag, cryptlen, ops); | ||
379 | 405 | ||
380 | scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen, | 406 | scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen, |
381 | authsize, 1); | 407 | authsize, 1); |
@@ -384,7 +410,7 @@ static int crypto_aegis128_encrypt(struct aead_request *req) | |||
384 | 410 | ||
385 | static int crypto_aegis128_decrypt(struct aead_request *req) | 411 | static int crypto_aegis128_decrypt(struct aead_request *req) |
386 | { | 412 | { |
387 | static const struct aegis128_ops ops = { | 413 | const struct aegis128_ops *ops = &(struct aegis128_ops){ |
388 | .skcipher_walk_init = skcipher_walk_aead_decrypt, | 414 | .skcipher_walk_init = skcipher_walk_aead_decrypt, |
389 | .crypt_chunk = crypto_aegis128_decrypt_chunk, | 415 | .crypt_chunk = crypto_aegis128_decrypt_chunk, |
390 | }; | 416 | }; |
@@ -398,7 +424,12 @@ static int crypto_aegis128_decrypt(struct aead_request *req) | |||
398 | scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen, | 424 | scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen, |
399 | authsize, 0); | 425 | authsize, 0); |
400 | 426 | ||
401 | crypto_aegis128_crypt(req, &tag, cryptlen, &ops); | 427 | if (have_simd && crypto_simd_usable()) |
428 | ops = &(struct aegis128_ops){ | ||
429 | .skcipher_walk_init = skcipher_walk_aead_decrypt, | ||
430 | .crypt_chunk = crypto_aegis128_decrypt_chunk_simd }; | ||
431 | |||
432 | crypto_aegis128_crypt(req, &tag, cryptlen, ops); | ||
402 | 433 | ||
403 | return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0; | 434 | return crypto_memneq(tag.bytes, zeros, authsize) ? -EBADMSG : 0; |
404 | } | 435 | } |
@@ -429,6 +460,9 @@ static struct aead_alg crypto_aegis128_alg = { | |||
429 | 460 | ||
430 | static int __init crypto_aegis128_module_init(void) | 461 | static int __init crypto_aegis128_module_init(void) |
431 | { | 462 | { |
463 | if (IS_ENABLED(CONFIG_CRYPTO_AEGIS128_SIMD)) | ||
464 | have_simd = crypto_aegis128_have_simd(); | ||
465 | |||
432 | return crypto_register_aead(&crypto_aegis128_alg); | 466 | return crypto_register_aead(&crypto_aegis128_alg); |
433 | } | 467 | } |
434 | 468 | ||