Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Glue Code for 3-way parallel assembler optimized version of Twofish
  4 *
  5 * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  6 */
  7
  8#include <asm/cpu_device_id.h>
  9#include <crypto/algapi.h>
 10#include <crypto/twofish.h>
 11#include <linux/crypto.h>
 12#include <linux/init.h>
 13#include <linux/module.h>
 14#include <linux/types.h>
 15
 16#include "twofish.h"
 17#include "ecb_cbc_helpers.h"
 
 
 
 
 18
 19EXPORT_SYMBOL_GPL(__twofish_enc_blk_3way);
 20EXPORT_SYMBOL_GPL(twofish_dec_blk_3way);
 21
 22static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
 23				   const u8 *key, unsigned int keylen)
 24{
 25	return twofish_setkey(&tfm->base, key, keylen);
 26}
 27
 28static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
 
 29{
 30	__twofish_enc_blk_3way(ctx, dst, src, false);
 31}
 32
 33void twofish_dec_blk_cbc_3way(const void *ctx, u8 *dst, const u8 *src)
 34{
 35	u8 buf[2][TF_BLOCK_SIZE];
 36	const u8 *s = src;
 37
 38	if (dst == src)
 39		s = memcpy(buf, src, sizeof(buf));
 40	twofish_dec_blk_3way(ctx, dst, src);
 41	crypto_xor(dst + TF_BLOCK_SIZE, s, sizeof(buf));
 42
 
 
 
 
 43}
 44EXPORT_SYMBOL_GPL(twofish_dec_blk_cbc_3way);
 45
 46static int ecb_encrypt(struct skcipher_request *req)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 47{
 48	ECB_WALK_START(req, TF_BLOCK_SIZE, -1);
 49	ECB_BLOCK(3, twofish_enc_blk_3way);
 50	ECB_BLOCK(1, twofish_enc_blk);
 51	ECB_WALK_END();
 52}
 53
 54static int ecb_decrypt(struct skcipher_request *req)
 
 55{
 56	ECB_WALK_START(req, TF_BLOCK_SIZE, -1);
 57	ECB_BLOCK(3, twofish_dec_blk_3way);
 58	ECB_BLOCK(1, twofish_dec_blk);
 59	ECB_WALK_END();
 60}
 61
 62static int cbc_encrypt(struct skcipher_request *req)
 
 63{
 64	CBC_WALK_START(req, TF_BLOCK_SIZE, -1);
 65	CBC_ENC_BLOCK(twofish_enc_blk);
 66	CBC_WALK_END();
 67}
 68
 69static int cbc_decrypt(struct skcipher_request *req)
 
 70{
 71	CBC_WALK_START(req, TF_BLOCK_SIZE, -1);
 72	CBC_DEC_BLOCK(3, twofish_dec_blk_cbc_3way);
 73	CBC_DEC_BLOCK(1, twofish_dec_blk);
 74	CBC_WALK_END();
 75}
 76
 77static struct skcipher_alg tf_skciphers[] = {
 78	{
 79		.base.cra_name		= "ecb(twofish)",
 80		.base.cra_driver_name	= "ecb-twofish-3way",
 81		.base.cra_priority	= 300,
 82		.base.cra_blocksize	= TF_BLOCK_SIZE,
 83		.base.cra_ctxsize	= sizeof(struct twofish_ctx),
 84		.base.cra_module	= THIS_MODULE,
 85		.min_keysize		= TF_MIN_KEY_SIZE,
 86		.max_keysize		= TF_MAX_KEY_SIZE,
 87		.setkey			= twofish_setkey_skcipher,
 88		.encrypt		= ecb_encrypt,
 89		.decrypt		= ecb_decrypt,
 90	}, {
 91		.base.cra_name		= "cbc(twofish)",
 92		.base.cra_driver_name	= "cbc-twofish-3way",
 93		.base.cra_priority	= 300,
 94		.base.cra_blocksize	= TF_BLOCK_SIZE,
 95		.base.cra_ctxsize	= sizeof(struct twofish_ctx),
 96		.base.cra_module	= THIS_MODULE,
 97		.min_keysize		= TF_MIN_KEY_SIZE,
 98		.max_keysize		= TF_MAX_KEY_SIZE,
 99		.ivsize			= TF_BLOCK_SIZE,
100		.setkey			= twofish_setkey_skcipher,
101		.encrypt		= cbc_encrypt,
102		.decrypt		= cbc_decrypt,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103	},
104};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
106static bool is_blacklisted_cpu(void)
107{
108	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
109		return false;
110
111	switch (boot_cpu_data.x86_vfm) {
112	case INTEL_ATOM_BONNELL:
113	case INTEL_ATOM_BONNELL_MID:
114	case INTEL_ATOM_SALTWELL:
115		/*
116		 * On Atom, twofish-3way is slower than original assembler
117		 * implementation. Twofish-3way trades off some performance in
118		 * storing blocks in 64bit registers to allow three blocks to
119		 * be processed parallel. Parallel operation then allows gaining
120		 * more performance than was trade off, on out-of-order CPUs.
121		 * However Atom does not benefit from this parallelism and
122		 * should be blacklisted.
123		 */
124		return true;
125	}
126
127	if (boot_cpu_data.x86 == 0x0f) {
128		/*
129		 * On Pentium 4, twofish-3way is slower than original assembler
130		 * implementation because excessive uses of 64bit rotate and
131		 * left-shifts (which are really slow on P4) needed to store and
132		 * handle 128bit block in two 64bit registers.
133		 */
134		return true;
135	}
136
137	return false;
138}
139
140static int force;
141module_param(force, int, 0);
142MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
143
144static int __init twofish_3way_init(void)
145{
146	if (!force && is_blacklisted_cpu()) {
147		printk(KERN_INFO
148			"twofish-x86_64-3way: performance on this CPU "
149			"would be suboptimal: disabling "
150			"twofish-x86_64-3way.\n");
151		return -ENODEV;
152	}
153
154	return crypto_register_skciphers(tf_skciphers,
155					 ARRAY_SIZE(tf_skciphers));
156}
157
158static void __exit twofish_3way_fini(void)
159{
160	crypto_unregister_skciphers(tf_skciphers, ARRAY_SIZE(tf_skciphers));
161}
162
163module_init(twofish_3way_init);
164module_exit(twofish_3way_fini);
165
166MODULE_LICENSE("GPL");
167MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized");
168MODULE_ALIAS_CRYPTO("twofish");
169MODULE_ALIAS_CRYPTO("twofish-asm");
v4.10.11
 
  1/*
  2 * Glue Code for 3-way parallel assembler optimized version of Twofish
  3 *
  4 * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
  5 *
  6 * This program is free software; you can redistribute it and/or modify
  7 * it under the terms of the GNU General Public License as published by
  8 * the Free Software Foundation; either version 2 of the License, or
  9 * (at your option) any later version.
 10 *
 11 * This program is distributed in the hope that it will be useful,
 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14 * GNU General Public License for more details.
 15 *
 16 * You should have received a copy of the GNU General Public License
 17 * along with this program; if not, write to the Free Software
 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 19 * USA
 20 *
 21 */
 22
 23#include <asm/processor.h>
 
 
 24#include <linux/crypto.h>
 25#include <linux/init.h>
 26#include <linux/module.h>
 27#include <linux/types.h>
 28#include <crypto/algapi.h>
 29#include <crypto/twofish.h>
 30#include <crypto/b128ops.h>
 31#include <asm/crypto/twofish.h>
 32#include <asm/crypto/glue_helper.h>
 33#include <crypto/lrw.h>
 34#include <crypto/xts.h>
 35
 36EXPORT_SYMBOL_GPL(__twofish_enc_blk_3way);
 37EXPORT_SYMBOL_GPL(twofish_dec_blk_3way);
 38
 39static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
 40					const u8 *src)
 41{
 42	__twofish_enc_blk_3way(ctx, dst, src, false);
 43}
 44
 45static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst,
 46					    const u8 *src)
 47{
 48	__twofish_enc_blk_3way(ctx, dst, src, true);
 49}
 50
 51void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src)
 52{
 53	u128 ivs[2];
 
 54
 55	ivs[0] = src[0];
 56	ivs[1] = src[1];
 
 
 57
 58	twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
 59
 60	u128_xor(&dst[1], &dst[1], &ivs[0]);
 61	u128_xor(&dst[2], &dst[2], &ivs[1]);
 62}
 63EXPORT_SYMBOL_GPL(twofish_dec_blk_cbc_3way);
 64
 65void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 66{
 67	be128 ctrblk;
 68
 69	if (dst != src)
 70		*dst = *src;
 71
 72	le128_to_be128(&ctrblk, iv);
 73	le128_inc(iv);
 74
 75	twofish_enc_blk(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
 76	u128_xor(dst, dst, (u128 *)&ctrblk);
 77}
 78EXPORT_SYMBOL_GPL(twofish_enc_blk_ctr);
 79
 80void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
 81			      le128 *iv)
 82{
 83	be128 ctrblks[3];
 84
 85	if (dst != src) {
 86		dst[0] = src[0];
 87		dst[1] = src[1];
 88		dst[2] = src[2];
 89	}
 90
 91	le128_to_be128(&ctrblks[0], iv);
 92	le128_inc(iv);
 93	le128_to_be128(&ctrblks[1], iv);
 94	le128_inc(iv);
 95	le128_to_be128(&ctrblks[2], iv);
 96	le128_inc(iv);
 97
 98	twofish_enc_blk_xor_3way(ctx, (u8 *)dst, (u8 *)ctrblks);
 99}
100EXPORT_SYMBOL_GPL(twofish_enc_blk_ctr_3way);
101
102static const struct common_glue_ctx twofish_enc = {
103	.num_funcs = 2,
104	.fpu_blocks_limit = -1,
105
106	.funcs = { {
107		.num_blocks = 3,
108		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) }
109	}, {
110		.num_blocks = 1,
111		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk) }
112	} }
113};
114
115static const struct common_glue_ctx twofish_ctr = {
116	.num_funcs = 2,
117	.fpu_blocks_limit = -1,
118
119	.funcs = { {
120		.num_blocks = 3,
121		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_ctr_3way) }
122	}, {
123		.num_blocks = 1,
124		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_ctr) }
125	} }
126};
127
128static const struct common_glue_ctx twofish_dec = {
129	.num_funcs = 2,
130	.fpu_blocks_limit = -1,
131
132	.funcs = { {
133		.num_blocks = 3,
134		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) }
135	}, {
136		.num_blocks = 1,
137		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk) }
138	} }
139};
140
141static const struct common_glue_ctx twofish_dec_cbc = {
142	.num_funcs = 2,
143	.fpu_blocks_limit = -1,
144
145	.funcs = { {
146		.num_blocks = 3,
147		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) }
148	}, {
149		.num_blocks = 1,
150		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk) }
151	} }
152};
153
154static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
155		       struct scatterlist *src, unsigned int nbytes)
156{
157	return glue_ecb_crypt_128bit(&twofish_enc, desc, dst, src, nbytes);
 
 
 
158}
159
160static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
161		       struct scatterlist *src, unsigned int nbytes)
162{
163	return glue_ecb_crypt_128bit(&twofish_dec, desc, dst, src, nbytes);
 
 
 
164}
165
166static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
167		       struct scatterlist *src, unsigned int nbytes)
168{
169	return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(twofish_enc_blk), desc,
170				       dst, src, nbytes);
 
171}
172
173static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
174		       struct scatterlist *src, unsigned int nbytes)
175{
176	return glue_cbc_decrypt_128bit(&twofish_dec_cbc, desc, dst, src,
177				       nbytes);
 
 
178}
179
180static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
181		     struct scatterlist *src, unsigned int nbytes)
182{
183	return glue_ctr_crypt_128bit(&twofish_ctr, desc, dst, src, nbytes);
184}
185
186static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
187{
188	const unsigned int bsize = TF_BLOCK_SIZE;
189	struct twofish_ctx *ctx = priv;
190	int i;
191
192	if (nbytes == 3 * bsize) {
193		twofish_enc_blk_3way(ctx, srcdst, srcdst);
194		return;
195	}
196
197	for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
198		twofish_enc_blk(ctx, srcdst, srcdst);
199}
200
201static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
202{
203	const unsigned int bsize = TF_BLOCK_SIZE;
204	struct twofish_ctx *ctx = priv;
205	int i;
206
207	if (nbytes == 3 * bsize) {
208		twofish_dec_blk_3way(ctx, srcdst, srcdst);
209		return;
210	}
211
212	for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
213		twofish_dec_blk(ctx, srcdst, srcdst);
214}
215
216int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key,
217		       unsigned int keylen)
218{
219	struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
220	int err;
221
222	err = __twofish_setkey(&ctx->twofish_ctx, key, keylen - TF_BLOCK_SIZE,
223			       &tfm->crt_flags);
224	if (err)
225		return err;
226
227	return lrw_init_table(&ctx->lrw_table, key + keylen - TF_BLOCK_SIZE);
228}
229EXPORT_SYMBOL_GPL(lrw_twofish_setkey);
230
231static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
232		       struct scatterlist *src, unsigned int nbytes)
233{
234	struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
235	be128 buf[3];
236	struct lrw_crypt_req req = {
237		.tbuf = buf,
238		.tbuflen = sizeof(buf),
239
240		.table_ctx = &ctx->lrw_table,
241		.crypt_ctx = &ctx->twofish_ctx,
242		.crypt_fn = encrypt_callback,
243	};
244
245	return lrw_crypt(desc, dst, src, nbytes, &req);
246}
247
248static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
249		       struct scatterlist *src, unsigned int nbytes)
250{
251	struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
252	be128 buf[3];
253	struct lrw_crypt_req req = {
254		.tbuf = buf,
255		.tbuflen = sizeof(buf),
256
257		.table_ctx = &ctx->lrw_table,
258		.crypt_ctx = &ctx->twofish_ctx,
259		.crypt_fn = decrypt_callback,
260	};
261
262	return lrw_crypt(desc, dst, src, nbytes, &req);
263}
264
265void lrw_twofish_exit_tfm(struct crypto_tfm *tfm)
266{
267	struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
268
269	lrw_free_table(&ctx->lrw_table);
270}
271EXPORT_SYMBOL_GPL(lrw_twofish_exit_tfm);
272
273int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key,
274		       unsigned int keylen)
275{
276	struct twofish_xts_ctx *ctx = crypto_tfm_ctx(tfm);
277	u32 *flags = &tfm->crt_flags;
278	int err;
279
280	err = xts_check_key(tfm, key, keylen);
281	if (err)
282		return err;
283
284	/* first half of xts-key is for crypt */
285	err = __twofish_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
286	if (err)
287		return err;
288
289	/* second half of xts-key is for tweak */
290	return __twofish_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2,
291				flags);
292}
293EXPORT_SYMBOL_GPL(xts_twofish_setkey);
294
295static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
296		       struct scatterlist *src, unsigned int nbytes)
297{
298	struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
299	be128 buf[3];
300	struct xts_crypt_req req = {
301		.tbuf = buf,
302		.tbuflen = sizeof(buf),
303
304		.tweak_ctx = &ctx->tweak_ctx,
305		.tweak_fn = XTS_TWEAK_CAST(twofish_enc_blk),
306		.crypt_ctx = &ctx->crypt_ctx,
307		.crypt_fn = encrypt_callback,
308	};
309
310	return xts_crypt(desc, dst, src, nbytes, &req);
311}
312
313static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
314		       struct scatterlist *src, unsigned int nbytes)
315{
316	struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
317	be128 buf[3];
318	struct xts_crypt_req req = {
319		.tbuf = buf,
320		.tbuflen = sizeof(buf),
321
322		.tweak_ctx = &ctx->tweak_ctx,
323		.tweak_fn = XTS_TWEAK_CAST(twofish_enc_blk),
324		.crypt_ctx = &ctx->crypt_ctx,
325		.crypt_fn = decrypt_callback,
326	};
327
328	return xts_crypt(desc, dst, src, nbytes, &req);
329}
330
331static struct crypto_alg tf_algs[5] = { {
332	.cra_name		= "ecb(twofish)",
333	.cra_driver_name	= "ecb-twofish-3way",
334	.cra_priority		= 300,
335	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
336	.cra_blocksize		= TF_BLOCK_SIZE,
337	.cra_ctxsize		= sizeof(struct twofish_ctx),
338	.cra_alignmask		= 0,
339	.cra_type		= &crypto_blkcipher_type,
340	.cra_module		= THIS_MODULE,
341	.cra_u = {
342		.blkcipher = {
343			.min_keysize	= TF_MIN_KEY_SIZE,
344			.max_keysize	= TF_MAX_KEY_SIZE,
345			.setkey		= twofish_setkey,
346			.encrypt	= ecb_encrypt,
347			.decrypt	= ecb_decrypt,
348		},
349	},
350}, {
351	.cra_name		= "cbc(twofish)",
352	.cra_driver_name	= "cbc-twofish-3way",
353	.cra_priority		= 300,
354	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
355	.cra_blocksize		= TF_BLOCK_SIZE,
356	.cra_ctxsize		= sizeof(struct twofish_ctx),
357	.cra_alignmask		= 0,
358	.cra_type		= &crypto_blkcipher_type,
359	.cra_module		= THIS_MODULE,
360	.cra_u = {
361		.blkcipher = {
362			.min_keysize	= TF_MIN_KEY_SIZE,
363			.max_keysize	= TF_MAX_KEY_SIZE,
364			.ivsize		= TF_BLOCK_SIZE,
365			.setkey		= twofish_setkey,
366			.encrypt	= cbc_encrypt,
367			.decrypt	= cbc_decrypt,
368		},
369	},
370}, {
371	.cra_name		= "ctr(twofish)",
372	.cra_driver_name	= "ctr-twofish-3way",
373	.cra_priority		= 300,
374	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
375	.cra_blocksize		= 1,
376	.cra_ctxsize		= sizeof(struct twofish_ctx),
377	.cra_alignmask		= 0,
378	.cra_type		= &crypto_blkcipher_type,
379	.cra_module		= THIS_MODULE,
380	.cra_u = {
381		.blkcipher = {
382			.min_keysize	= TF_MIN_KEY_SIZE,
383			.max_keysize	= TF_MAX_KEY_SIZE,
384			.ivsize		= TF_BLOCK_SIZE,
385			.setkey		= twofish_setkey,
386			.encrypt	= ctr_crypt,
387			.decrypt	= ctr_crypt,
388		},
389	},
390}, {
391	.cra_name		= "lrw(twofish)",
392	.cra_driver_name	= "lrw-twofish-3way",
393	.cra_priority		= 300,
394	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
395	.cra_blocksize		= TF_BLOCK_SIZE,
396	.cra_ctxsize		= sizeof(struct twofish_lrw_ctx),
397	.cra_alignmask		= 0,
398	.cra_type		= &crypto_blkcipher_type,
399	.cra_module		= THIS_MODULE,
400	.cra_exit		= lrw_twofish_exit_tfm,
401	.cra_u = {
402		.blkcipher = {
403			.min_keysize	= TF_MIN_KEY_SIZE + TF_BLOCK_SIZE,
404			.max_keysize	= TF_MAX_KEY_SIZE + TF_BLOCK_SIZE,
405			.ivsize		= TF_BLOCK_SIZE,
406			.setkey		= lrw_twofish_setkey,
407			.encrypt	= lrw_encrypt,
408			.decrypt	= lrw_decrypt,
409		},
410	},
411}, {
412	.cra_name		= "xts(twofish)",
413	.cra_driver_name	= "xts-twofish-3way",
414	.cra_priority		= 300,
415	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
416	.cra_blocksize		= TF_BLOCK_SIZE,
417	.cra_ctxsize		= sizeof(struct twofish_xts_ctx),
418	.cra_alignmask		= 0,
419	.cra_type		= &crypto_blkcipher_type,
420	.cra_module		= THIS_MODULE,
421	.cra_u = {
422		.blkcipher = {
423			.min_keysize	= TF_MIN_KEY_SIZE * 2,
424			.max_keysize	= TF_MAX_KEY_SIZE * 2,
425			.ivsize		= TF_BLOCK_SIZE,
426			.setkey		= xts_twofish_setkey,
427			.encrypt	= xts_encrypt,
428			.decrypt	= xts_decrypt,
429		},
430	},
431} };
432
433static bool is_blacklisted_cpu(void)
434{
435	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
436		return false;
437
438	if (boot_cpu_data.x86 == 0x06 &&
439		(boot_cpu_data.x86_model == 0x1c ||
440		 boot_cpu_data.x86_model == 0x26 ||
441		 boot_cpu_data.x86_model == 0x36)) {
442		/*
443		 * On Atom, twofish-3way is slower than original assembler
444		 * implementation. Twofish-3way trades off some performance in
445		 * storing blocks in 64bit registers to allow three blocks to
446		 * be processed parallel. Parallel operation then allows gaining
447		 * more performance than was trade off, on out-of-order CPUs.
448		 * However Atom does not benefit from this parallellism and
449		 * should be blacklisted.
450		 */
451		return true;
452	}
453
454	if (boot_cpu_data.x86 == 0x0f) {
455		/*
456		 * On Pentium 4, twofish-3way is slower than original assembler
457		 * implementation because excessive uses of 64bit rotate and
458		 * left-shifts (which are really slow on P4) needed to store and
459		 * handle 128bit block in two 64bit registers.
460		 */
461		return true;
462	}
463
464	return false;
465}
466
467static int force;
468module_param(force, int, 0);
469MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
470
471static int __init init(void)
472{
473	if (!force && is_blacklisted_cpu()) {
474		printk(KERN_INFO
475			"twofish-x86_64-3way: performance on this CPU "
476			"would be suboptimal: disabling "
477			"twofish-x86_64-3way.\n");
478		return -ENODEV;
479	}
480
481	return crypto_register_algs(tf_algs, ARRAY_SIZE(tf_algs));
 
482}
483
484static void __exit fini(void)
485{
486	crypto_unregister_algs(tf_algs, ARRAY_SIZE(tf_algs));
487}
488
489module_init(init);
490module_exit(fini);
491
492MODULE_LICENSE("GPL");
493MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized");
494MODULE_ALIAS_CRYPTO("twofish");
495MODULE_ALIAS_CRYPTO("twofish-asm");