1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Glue Code for AVX assembler version of Twofish Cipher
4  *
5  * Copyright (C) 2012 Johannes Goetzfried
6  *     <Johannes.Goetzfried@informatik.stud.uni-erlangen.de>
7  *
8  * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
9  */
10 
11 #include <linux/module.h>
12 #include <linux/types.h>
13 #include <linux/crypto.h>
14 #include <linux/err.h>
15 #include <crypto/algapi.h>
16 #include <crypto/internal/simd.h>
17 #include <crypto/twofish.h>
18 #include <crypto/xts.h>
19 #include <asm/crypto/glue_helper.h>
20 #include <asm/crypto/twofish.h>
21 
22 #define TWOFISH_PARALLEL_BLOCKS 8
23 
24 /* 8-way parallel cipher functions */
25 asmlinkage void twofish_ecb_enc_8way(struct twofish_ctx *ctx, u8 *dst,
26 				     const u8 *src);
27 asmlinkage void twofish_ecb_dec_8way(struct twofish_ctx *ctx, u8 *dst,
28 				     const u8 *src);
29 
30 asmlinkage void twofish_cbc_dec_8way(struct twofish_ctx *ctx, u8 *dst,
31 				     const u8 *src);
32 asmlinkage void twofish_ctr_8way(struct twofish_ctx *ctx, u8 *dst,
33 				 const u8 *src, le128 *iv);
34 
35 asmlinkage void twofish_xts_enc_8way(struct twofish_ctx *ctx, u8 *dst,
36 				     const u8 *src, le128 *iv);
37 asmlinkage void twofish_xts_dec_8way(struct twofish_ctx *ctx, u8 *dst,
38 				     const u8 *src, le128 *iv);
39 
twofish_setkey_skcipher(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)40 static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
41 				   const u8 *key, unsigned int keylen)
42 {
43 	return twofish_setkey(&tfm->base, key, keylen);
44 }
45 
twofish_enc_blk_3way(struct twofish_ctx * ctx,u8 * dst,const u8 * src)46 static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
47 					const u8 *src)
48 {
49 	__twofish_enc_blk_3way(ctx, dst, src, false);
50 }
51 
twofish_xts_enc(void * ctx,u128 * dst,const u128 * src,le128 * iv)52 static void twofish_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv)
53 {
54 	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
55 				  GLUE_FUNC_CAST(twofish_enc_blk));
56 }
57 
twofish_xts_dec(void * ctx,u128 * dst,const u128 * src,le128 * iv)58 static void twofish_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv)
59 {
60 	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
61 				  GLUE_FUNC_CAST(twofish_dec_blk));
62 }
63 
64 struct twofish_xts_ctx {
65 	struct twofish_ctx tweak_ctx;
66 	struct twofish_ctx crypt_ctx;
67 };
68 
xts_twofish_setkey(struct crypto_skcipher * tfm,const u8 * key,unsigned int keylen)69 static int xts_twofish_setkey(struct crypto_skcipher *tfm, const u8 *key,
70 			      unsigned int keylen)
71 {
72 	struct twofish_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
73 	u32 *flags = &tfm->base.crt_flags;
74 	int err;
75 
76 	err = xts_verify_key(tfm, key, keylen);
77 	if (err)
78 		return err;
79 
80 	/* first half of xts-key is for crypt */
81 	err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
82 	if (err)
83 		return err;
84 
85 	/* second half of xts-key is for tweak */
86 	return __twofish_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2,
87 				flags);
88 }
89 
90 static const struct common_glue_ctx twofish_enc = {
91 	.num_funcs = 3,
92 	.fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
93 
94 	.funcs = { {
95 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
96 		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_enc_8way) }
97 	}, {
98 		.num_blocks = 3,
99 		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) }
100 	}, {
101 		.num_blocks = 1,
102 		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk) }
103 	} }
104 };
105 
106 static const struct common_glue_ctx twofish_ctr = {
107 	.num_funcs = 3,
108 	.fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
109 
110 	.funcs = { {
111 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
112 		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_ctr_8way) }
113 	}, {
114 		.num_blocks = 3,
115 		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_3way) }
116 	}, {
117 		.num_blocks = 1,
118 		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr) }
119 	} }
120 };
121 
122 static const struct common_glue_ctx twofish_enc_xts = {
123 	.num_funcs = 2,
124 	.fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
125 
126 	.funcs = { {
127 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
128 		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_enc_8way) }
129 	}, {
130 		.num_blocks = 1,
131 		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_enc) }
132 	} }
133 };
134 
135 static const struct common_glue_ctx twofish_dec = {
136 	.num_funcs = 3,
137 	.fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
138 
139 	.funcs = { {
140 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
141 		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_dec_8way) }
142 	}, {
143 		.num_blocks = 3,
144 		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) }
145 	}, {
146 		.num_blocks = 1,
147 		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk) }
148 	} }
149 };
150 
151 static const struct common_glue_ctx twofish_dec_cbc = {
152 	.num_funcs = 3,
153 	.fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
154 
155 	.funcs = { {
156 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
157 		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_cbc_dec_8way) }
158 	}, {
159 		.num_blocks = 3,
160 		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) }
161 	}, {
162 		.num_blocks = 1,
163 		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk) }
164 	} }
165 };
166 
167 static const struct common_glue_ctx twofish_dec_xts = {
168 	.num_funcs = 2,
169 	.fpu_blocks_limit = TWOFISH_PARALLEL_BLOCKS,
170 
171 	.funcs = { {
172 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
173 		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_dec_8way) }
174 	}, {
175 		.num_blocks = 1,
176 		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_dec) }
177 	} }
178 };
179 
ecb_encrypt(struct skcipher_request * req)180 static int ecb_encrypt(struct skcipher_request *req)
181 {
182 	return glue_ecb_req_128bit(&twofish_enc, req);
183 }
184 
ecb_decrypt(struct skcipher_request * req)185 static int ecb_decrypt(struct skcipher_request *req)
186 {
187 	return glue_ecb_req_128bit(&twofish_dec, req);
188 }
189 
cbc_encrypt(struct skcipher_request * req)190 static int cbc_encrypt(struct skcipher_request *req)
191 {
192 	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(twofish_enc_blk),
193 					   req);
194 }
195 
cbc_decrypt(struct skcipher_request * req)196 static int cbc_decrypt(struct skcipher_request *req)
197 {
198 	return glue_cbc_decrypt_req_128bit(&twofish_dec_cbc, req);
199 }
200 
ctr_crypt(struct skcipher_request * req)201 static int ctr_crypt(struct skcipher_request *req)
202 {
203 	return glue_ctr_req_128bit(&twofish_ctr, req);
204 }
205 
xts_encrypt(struct skcipher_request * req)206 static int xts_encrypt(struct skcipher_request *req)
207 {
208 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
209 	struct twofish_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
210 
211 	return glue_xts_req_128bit(&twofish_enc_xts, req,
212 				   XTS_TWEAK_CAST(twofish_enc_blk),
213 				   &ctx->tweak_ctx, &ctx->crypt_ctx, false);
214 }
215 
xts_decrypt(struct skcipher_request * req)216 static int xts_decrypt(struct skcipher_request *req)
217 {
218 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
219 	struct twofish_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
220 
221 	return glue_xts_req_128bit(&twofish_dec_xts, req,
222 				   XTS_TWEAK_CAST(twofish_enc_blk),
223 				   &ctx->tweak_ctx, &ctx->crypt_ctx, true);
224 }
225 
226 static struct skcipher_alg twofish_algs[] = {
227 	{
228 		.base.cra_name		= "__ecb(twofish)",
229 		.base.cra_driver_name	= "__ecb-twofish-avx",
230 		.base.cra_priority	= 400,
231 		.base.cra_flags		= CRYPTO_ALG_INTERNAL,
232 		.base.cra_blocksize	= TF_BLOCK_SIZE,
233 		.base.cra_ctxsize	= sizeof(struct twofish_ctx),
234 		.base.cra_module	= THIS_MODULE,
235 		.min_keysize		= TF_MIN_KEY_SIZE,
236 		.max_keysize		= TF_MAX_KEY_SIZE,
237 		.setkey			= twofish_setkey_skcipher,
238 		.encrypt		= ecb_encrypt,
239 		.decrypt		= ecb_decrypt,
240 	}, {
241 		.base.cra_name		= "__cbc(twofish)",
242 		.base.cra_driver_name	= "__cbc-twofish-avx",
243 		.base.cra_priority	= 400,
244 		.base.cra_flags		= CRYPTO_ALG_INTERNAL,
245 		.base.cra_blocksize	= TF_BLOCK_SIZE,
246 		.base.cra_ctxsize	= sizeof(struct twofish_ctx),
247 		.base.cra_module	= THIS_MODULE,
248 		.min_keysize		= TF_MIN_KEY_SIZE,
249 		.max_keysize		= TF_MAX_KEY_SIZE,
250 		.ivsize			= TF_BLOCK_SIZE,
251 		.setkey			= twofish_setkey_skcipher,
252 		.encrypt		= cbc_encrypt,
253 		.decrypt		= cbc_decrypt,
254 	}, {
255 		.base.cra_name		= "__ctr(twofish)",
256 		.base.cra_driver_name	= "__ctr-twofish-avx",
257 		.base.cra_priority	= 400,
258 		.base.cra_flags		= CRYPTO_ALG_INTERNAL,
259 		.base.cra_blocksize	= 1,
260 		.base.cra_ctxsize	= sizeof(struct twofish_ctx),
261 		.base.cra_module	= THIS_MODULE,
262 		.min_keysize		= TF_MIN_KEY_SIZE,
263 		.max_keysize		= TF_MAX_KEY_SIZE,
264 		.ivsize			= TF_BLOCK_SIZE,
265 		.chunksize		= TF_BLOCK_SIZE,
266 		.setkey			= twofish_setkey_skcipher,
267 		.encrypt		= ctr_crypt,
268 		.decrypt		= ctr_crypt,
269 	}, {
270 		.base.cra_name		= "__xts(twofish)",
271 		.base.cra_driver_name	= "__xts-twofish-avx",
272 		.base.cra_priority	= 400,
273 		.base.cra_flags		= CRYPTO_ALG_INTERNAL,
274 		.base.cra_blocksize	= TF_BLOCK_SIZE,
275 		.base.cra_ctxsize	= sizeof(struct twofish_xts_ctx),
276 		.base.cra_module	= THIS_MODULE,
277 		.min_keysize		= 2 * TF_MIN_KEY_SIZE,
278 		.max_keysize		= 2 * TF_MAX_KEY_SIZE,
279 		.ivsize			= TF_BLOCK_SIZE,
280 		.setkey			= xts_twofish_setkey,
281 		.encrypt		= xts_encrypt,
282 		.decrypt		= xts_decrypt,
283 	},
284 };
285 
286 static struct simd_skcipher_alg *twofish_simd_algs[ARRAY_SIZE(twofish_algs)];
287 
twofish_init(void)288 static int __init twofish_init(void)
289 {
290 	const char *feature_name;
291 
292 	if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, &feature_name)) {
293 		pr_info("CPU feature '%s' is not supported.\n", feature_name);
294 		return -ENODEV;
295 	}
296 
297 	return simd_register_skciphers_compat(twofish_algs,
298 					      ARRAY_SIZE(twofish_algs),
299 					      twofish_simd_algs);
300 }
301 
twofish_exit(void)302 static void __exit twofish_exit(void)
303 {
304 	simd_unregister_skciphers(twofish_algs, ARRAY_SIZE(twofish_algs),
305 				  twofish_simd_algs);
306 }
307 
308 module_init(twofish_init);
309 module_exit(twofish_exit);
310 
311 MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized");
312 MODULE_LICENSE("GPL");
313 MODULE_ALIAS_CRYPTO("twofish");
314