11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2107778b5SJohannes Goetzfried /*
3107778b5SJohannes Goetzfried * Glue Code for AVX assembler version of Twofish Cipher
4107778b5SJohannes Goetzfried *
5107778b5SJohannes Goetzfried * Copyright (C) 2012 Johannes Goetzfried
6107778b5SJohannes Goetzfried * <Johannes.Goetzfried@informatik.stud.uni-erlangen.de>
7107778b5SJohannes Goetzfried *
818be4527SJussi Kivilinna * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
9107778b5SJohannes Goetzfried */
10107778b5SJohannes Goetzfried
11107778b5SJohannes Goetzfried #include <linux/module.h>
12107778b5SJohannes Goetzfried #include <linux/types.h>
13107778b5SJohannes Goetzfried #include <linux/crypto.h>
14107778b5SJohannes Goetzfried #include <linux/err.h>
15107778b5SJohannes Goetzfried #include <crypto/algapi.h>
160e6ab46dSEric Biggers #include <crypto/internal/simd.h>
17107778b5SJohannes Goetzfried #include <crypto/twofish.h>
18107778b5SJohannes Goetzfried
19*a04ea6f7SArd Biesheuvel #include "twofish.h"
20165f3573SArd Biesheuvel #include "ecb_cbc_helpers.h"
21165f3573SArd Biesheuvel
22107778b5SJohannes Goetzfried #define TWOFISH_PARALLEL_BLOCKS 8
23107778b5SJohannes Goetzfried
248435a3c3SJussi Kivilinna /* 8-way parallel cipher functions */
259c1e8836SKees Cook asmlinkage void twofish_ecb_enc_8way(const void *ctx, u8 *dst, const u8 *src);
269c1e8836SKees Cook asmlinkage void twofish_ecb_dec_8way(const void *ctx, u8 *dst, const u8 *src);
278435a3c3SJussi Kivilinna
289c1e8836SKees Cook asmlinkage void twofish_cbc_dec_8way(const void *ctx, u8 *dst, const u8 *src);
298435a3c3SJussi Kivilinna
twofish_setkey_skcipher(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)300e6ab46dSEric Biggers static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
310e6ab46dSEric Biggers const u8 *key, unsigned int keylen)
320e6ab46dSEric Biggers {
330e6ab46dSEric Biggers return twofish_setkey(&tfm->base, key, keylen);
340e6ab46dSEric Biggers }
350e6ab46dSEric Biggers
twofish_enc_blk_3way(const void * ctx,u8 * dst,const u8 * src)369c1e8836SKees Cook static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
37107778b5SJohannes Goetzfried {
38107778b5SJohannes Goetzfried __twofish_enc_blk_3way(ctx, dst, src, false);
39107778b5SJohannes Goetzfried }
40107778b5SJohannes Goetzfried
ecb_encrypt(struct skcipher_request * req)410e6ab46dSEric Biggers static int ecb_encrypt(struct skcipher_request *req)
42107778b5SJohannes Goetzfried {
43165f3573SArd Biesheuvel ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
44165f3573SArd Biesheuvel ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_enc_8way);
45165f3573SArd Biesheuvel ECB_BLOCK(3, twofish_enc_blk_3way);
46165f3573SArd Biesheuvel ECB_BLOCK(1, twofish_enc_blk);
47165f3573SArd Biesheuvel ECB_WALK_END();
48107778b5SJohannes Goetzfried }
49107778b5SJohannes Goetzfried
ecb_decrypt(struct skcipher_request * req)500e6ab46dSEric Biggers static int ecb_decrypt(struct skcipher_request *req)
51107778b5SJohannes Goetzfried {
52165f3573SArd Biesheuvel ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
53165f3573SArd Biesheuvel ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_dec_8way);
54165f3573SArd Biesheuvel ECB_BLOCK(3, twofish_dec_blk_3way);
55165f3573SArd Biesheuvel ECB_BLOCK(1, twofish_dec_blk);
56165f3573SArd Biesheuvel ECB_WALK_END();
57107778b5SJohannes Goetzfried }
58107778b5SJohannes Goetzfried
cbc_encrypt(struct skcipher_request * req)590e6ab46dSEric Biggers static int cbc_encrypt(struct skcipher_request *req)
60107778b5SJohannes Goetzfried {
61165f3573SArd Biesheuvel CBC_WALK_START(req, TF_BLOCK_SIZE, -1);
62165f3573SArd Biesheuvel CBC_ENC_BLOCK(twofish_enc_blk);
63165f3573SArd Biesheuvel CBC_WALK_END();
64107778b5SJohannes Goetzfried }
65107778b5SJohannes Goetzfried
cbc_decrypt(struct skcipher_request * req)660e6ab46dSEric Biggers static int cbc_decrypt(struct skcipher_request *req)
67107778b5SJohannes Goetzfried {
68165f3573SArd Biesheuvel CBC_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
69165f3573SArd Biesheuvel CBC_DEC_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_cbc_dec_8way);
70165f3573SArd Biesheuvel CBC_DEC_BLOCK(3, twofish_dec_blk_cbc_3way);
71165f3573SArd Biesheuvel CBC_DEC_BLOCK(1, twofish_dec_blk);
72165f3573SArd Biesheuvel CBC_WALK_END();
73107778b5SJohannes Goetzfried }
74107778b5SJohannes Goetzfried
750e6ab46dSEric Biggers static struct skcipher_alg twofish_algs[] = {
760e6ab46dSEric Biggers {
770e6ab46dSEric Biggers .base.cra_name = "__ecb(twofish)",
780e6ab46dSEric Biggers .base.cra_driver_name = "__ecb-twofish-avx",
790e6ab46dSEric Biggers .base.cra_priority = 400,
800e6ab46dSEric Biggers .base.cra_flags = CRYPTO_ALG_INTERNAL,
810e6ab46dSEric Biggers .base.cra_blocksize = TF_BLOCK_SIZE,
820e6ab46dSEric Biggers .base.cra_ctxsize = sizeof(struct twofish_ctx),
830e6ab46dSEric Biggers .base.cra_module = THIS_MODULE,
84107778b5SJohannes Goetzfried .min_keysize = TF_MIN_KEY_SIZE,
85107778b5SJohannes Goetzfried .max_keysize = TF_MAX_KEY_SIZE,
860e6ab46dSEric Biggers .setkey = twofish_setkey_skcipher,
87107778b5SJohannes Goetzfried .encrypt = ecb_encrypt,
88107778b5SJohannes Goetzfried .decrypt = ecb_decrypt,
89107778b5SJohannes Goetzfried }, {
900e6ab46dSEric Biggers .base.cra_name = "__cbc(twofish)",
910e6ab46dSEric Biggers .base.cra_driver_name = "__cbc-twofish-avx",
920e6ab46dSEric Biggers .base.cra_priority = 400,
930e6ab46dSEric Biggers .base.cra_flags = CRYPTO_ALG_INTERNAL,
940e6ab46dSEric Biggers .base.cra_blocksize = TF_BLOCK_SIZE,
950e6ab46dSEric Biggers .base.cra_ctxsize = sizeof(struct twofish_ctx),
960e6ab46dSEric Biggers .base.cra_module = THIS_MODULE,
97107778b5SJohannes Goetzfried .min_keysize = TF_MIN_KEY_SIZE,
98107778b5SJohannes Goetzfried .max_keysize = TF_MAX_KEY_SIZE,
99107778b5SJohannes Goetzfried .ivsize = TF_BLOCK_SIZE,
1000e6ab46dSEric Biggers .setkey = twofish_setkey_skcipher,
1010e6ab46dSEric Biggers .encrypt = cbc_encrypt,
1020e6ab46dSEric Biggers .decrypt = cbc_decrypt,
103107778b5SJohannes Goetzfried },
1040e6ab46dSEric Biggers };
1050e6ab46dSEric Biggers
1060e6ab46dSEric Biggers static struct simd_skcipher_alg *twofish_simd_algs[ARRAY_SIZE(twofish_algs)];
107107778b5SJohannes Goetzfried
twofish_init(void)108107778b5SJohannes Goetzfried static int __init twofish_init(void)
109107778b5SJohannes Goetzfried {
1104eecd261SIngo Molnar const char *feature_name;
111107778b5SJohannes Goetzfried
112158ecc39SBorislav Petkov if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, &feature_name)) {
1134eecd261SIngo Molnar pr_info("CPU feature '%s' is not supported.\n", feature_name);
114107778b5SJohannes Goetzfried return -ENODEV;
115107778b5SJohannes Goetzfried }
116107778b5SJohannes Goetzfried
1170e6ab46dSEric Biggers return simd_register_skciphers_compat(twofish_algs,
1180e6ab46dSEric Biggers ARRAY_SIZE(twofish_algs),
1190e6ab46dSEric Biggers twofish_simd_algs);
120107778b5SJohannes Goetzfried }
121107778b5SJohannes Goetzfried
twofish_exit(void)122107778b5SJohannes Goetzfried static void __exit twofish_exit(void)
123107778b5SJohannes Goetzfried {
1240e6ab46dSEric Biggers simd_unregister_skciphers(twofish_algs, ARRAY_SIZE(twofish_algs),
1250e6ab46dSEric Biggers twofish_simd_algs);
126107778b5SJohannes Goetzfried }
127107778b5SJohannes Goetzfried
128107778b5SJohannes Goetzfried module_init(twofish_init);
129107778b5SJohannes Goetzfried module_exit(twofish_exit);
130107778b5SJohannes Goetzfried
131107778b5SJohannes Goetzfried MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized");
132107778b5SJohannes Goetzfried MODULE_LICENSE("GPL");
1335d26a105SKees Cook MODULE_ALIAS_CRYPTO("twofish");
134