xref: /linux/arch/x86/crypto/twofish_avx_glue.c (revision fb7399cf2d0b33825b8039f95c45395c7deba25c)
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/twofish.h>
17 
18 #include "twofish.h"
19 #include "ecb_cbc_helpers.h"
20 
21 #define TWOFISH_PARALLEL_BLOCKS 8
22 
23 /* 8-way parallel cipher functions */
24 asmlinkage void twofish_ecb_enc_8way(const void *ctx, u8 *dst, const u8 *src);
25 asmlinkage void twofish_ecb_dec_8way(const void *ctx, u8 *dst, const u8 *src);
26 
27 asmlinkage void twofish_cbc_dec_8way(const void *ctx, u8 *dst, const u8 *src);
28 
29 static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
30 				   const u8 *key, unsigned int keylen)
31 {
32 	return twofish_setkey(&tfm->base, key, keylen);
33 }
34 
35 static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
36 {
37 	__twofish_enc_blk_3way(ctx, dst, src, false);
38 }
39 
40 static int ecb_encrypt(struct skcipher_request *req)
41 {
42 	ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
43 	ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_enc_8way);
44 	ECB_BLOCK(3, twofish_enc_blk_3way);
45 	ECB_BLOCK(1, twofish_enc_blk);
46 	ECB_WALK_END();
47 }
48 
49 static int ecb_decrypt(struct skcipher_request *req)
50 {
51 	ECB_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
52 	ECB_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_ecb_dec_8way);
53 	ECB_BLOCK(3, twofish_dec_blk_3way);
54 	ECB_BLOCK(1, twofish_dec_blk);
55 	ECB_WALK_END();
56 }
57 
58 static int cbc_encrypt(struct skcipher_request *req)
59 {
60 	CBC_WALK_START(req, TF_BLOCK_SIZE, -1);
61 	CBC_ENC_BLOCK(twofish_enc_blk);
62 	CBC_WALK_END();
63 }
64 
65 static int cbc_decrypt(struct skcipher_request *req)
66 {
67 	CBC_WALK_START(req, TF_BLOCK_SIZE, TWOFISH_PARALLEL_BLOCKS);
68 	CBC_DEC_BLOCK(TWOFISH_PARALLEL_BLOCKS, twofish_cbc_dec_8way);
69 	CBC_DEC_BLOCK(3, twofish_dec_blk_cbc_3way);
70 	CBC_DEC_BLOCK(1, twofish_dec_blk);
71 	CBC_WALK_END();
72 }
73 
74 static struct skcipher_alg twofish_algs[] = {
75 	{
76 		.base.cra_name		= "ecb(twofish)",
77 		.base.cra_driver_name	= "ecb-twofish-avx",
78 		.base.cra_priority	= 400,
79 		.base.cra_blocksize	= TF_BLOCK_SIZE,
80 		.base.cra_ctxsize	= sizeof(struct twofish_ctx),
81 		.base.cra_module	= THIS_MODULE,
82 		.min_keysize		= TF_MIN_KEY_SIZE,
83 		.max_keysize		= TF_MAX_KEY_SIZE,
84 		.setkey			= twofish_setkey_skcipher,
85 		.encrypt		= ecb_encrypt,
86 		.decrypt		= ecb_decrypt,
87 	}, {
88 		.base.cra_name		= "cbc(twofish)",
89 		.base.cra_driver_name	= "cbc-twofish-avx",
90 		.base.cra_priority	= 400,
91 		.base.cra_blocksize	= TF_BLOCK_SIZE,
92 		.base.cra_ctxsize	= sizeof(struct twofish_ctx),
93 		.base.cra_module	= THIS_MODULE,
94 		.min_keysize		= TF_MIN_KEY_SIZE,
95 		.max_keysize		= TF_MAX_KEY_SIZE,
96 		.ivsize			= TF_BLOCK_SIZE,
97 		.setkey			= twofish_setkey_skcipher,
98 		.encrypt		= cbc_encrypt,
99 		.decrypt		= cbc_decrypt,
100 	},
101 };
102 
103 static int __init twofish_init(void)
104 {
105 	const char *feature_name;
106 
107 	if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, &feature_name)) {
108 		pr_info("CPU feature '%s' is not supported.\n", feature_name);
109 		return -ENODEV;
110 	}
111 
112 	return crypto_register_skciphers(twofish_algs,
113 					 ARRAY_SIZE(twofish_algs));
114 }
115 
116 static void __exit twofish_exit(void)
117 {
118 	crypto_unregister_skciphers(twofish_algs, ARRAY_SIZE(twofish_algs));
119 }
120 
121 module_init(twofish_init);
122 module_exit(twofish_exit);
123 
124 MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized");
125 MODULE_LICENSE("GPL");
126 MODULE_ALIAS_CRYPTO("twofish");
127