xref: /openbmc/linux/arch/x86/crypto/twofish_avx_glue.c (revision d0034a7a4ac7fae708146ac0059b9c47a1543f0d)
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