xref: /openbmc/linux/arch/x86/crypto/camellia_aesni_avx2_glue.c (revision 55a7e88f016873ef1717295d8460416b1ccd05a5)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Glue Code for x86_64/AVX2/AES-NI assembler optimized version of Camellia
4  *
5  * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
6  */
7 
8 #include <asm/crypto/camellia.h>
9 #include <asm/crypto/glue_helper.h>
10 #include <crypto/algapi.h>
11 #include <crypto/internal/simd.h>
12 #include <linux/crypto.h>
13 #include <linux/err.h>
14 #include <linux/module.h>
15 #include <linux/types.h>
16 
17 #define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
18 #define CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS 32
19 
20 /* 32-way AVX2/AES-NI parallel cipher functions */
21 asmlinkage void camellia_ecb_enc_32way(const void *ctx, u8 *dst, const u8 *src);
22 asmlinkage void camellia_ecb_dec_32way(const void *ctx, u8 *dst, const u8 *src);
23 
24 asmlinkage void camellia_cbc_dec_32way(const void *ctx, u8 *dst, const u8 *src);
25 asmlinkage void camellia_ctr_32way(const void *ctx, u8 *dst, const u8 *src,
26 				   le128 *iv);
27 
28 static const struct common_glue_ctx camellia_enc = {
29 	.num_funcs = 4,
30 	.fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
31 
32 	.funcs = { {
33 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
34 		.fn_u = { .ecb = camellia_ecb_enc_32way }
35 	}, {
36 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
37 		.fn_u = { .ecb = camellia_ecb_enc_16way }
38 	}, {
39 		.num_blocks = 2,
40 		.fn_u = { .ecb = camellia_enc_blk_2way }
41 	}, {
42 		.num_blocks = 1,
43 		.fn_u = { .ecb = camellia_enc_blk }
44 	} }
45 };
46 
47 static const struct common_glue_ctx camellia_ctr = {
48 	.num_funcs = 4,
49 	.fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
50 
51 	.funcs = { {
52 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
53 		.fn_u = { .ctr = camellia_ctr_32way }
54 	}, {
55 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
56 		.fn_u = { .ctr = camellia_ctr_16way }
57 	}, {
58 		.num_blocks = 2,
59 		.fn_u = { .ctr = camellia_crypt_ctr_2way }
60 	}, {
61 		.num_blocks = 1,
62 		.fn_u = { .ctr = camellia_crypt_ctr }
63 	} }
64 };
65 
66 static const struct common_glue_ctx camellia_dec = {
67 	.num_funcs = 4,
68 	.fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
69 
70 	.funcs = { {
71 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
72 		.fn_u = { .ecb = camellia_ecb_dec_32way }
73 	}, {
74 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
75 		.fn_u = { .ecb = camellia_ecb_dec_16way }
76 	}, {
77 		.num_blocks = 2,
78 		.fn_u = { .ecb = camellia_dec_blk_2way }
79 	}, {
80 		.num_blocks = 1,
81 		.fn_u = { .ecb = camellia_dec_blk }
82 	} }
83 };
84 
85 static const struct common_glue_ctx camellia_dec_cbc = {
86 	.num_funcs = 4,
87 	.fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
88 
89 	.funcs = { {
90 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
91 		.fn_u = { .cbc = camellia_cbc_dec_32way }
92 	}, {
93 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
94 		.fn_u = { .cbc = camellia_cbc_dec_16way }
95 	}, {
96 		.num_blocks = 2,
97 		.fn_u = { .cbc = camellia_decrypt_cbc_2way }
98 	}, {
99 		.num_blocks = 1,
100 		.fn_u = { .cbc = camellia_dec_blk }
101 	} }
102 };
103 
104 static int camellia_setkey(struct crypto_skcipher *tfm, const u8 *key,
105 			   unsigned int keylen)
106 {
107 	return __camellia_setkey(crypto_skcipher_ctx(tfm), key, keylen);
108 }
109 
110 static int ecb_encrypt(struct skcipher_request *req)
111 {
112 	return glue_ecb_req_128bit(&camellia_enc, req);
113 }
114 
115 static int ecb_decrypt(struct skcipher_request *req)
116 {
117 	return glue_ecb_req_128bit(&camellia_dec, req);
118 }
119 
120 static int cbc_encrypt(struct skcipher_request *req)
121 {
122 	return glue_cbc_encrypt_req_128bit(camellia_enc_blk, req);
123 }
124 
125 static int cbc_decrypt(struct skcipher_request *req)
126 {
127 	return glue_cbc_decrypt_req_128bit(&camellia_dec_cbc, req);
128 }
129 
130 static int ctr_crypt(struct skcipher_request *req)
131 {
132 	return glue_ctr_req_128bit(&camellia_ctr, req);
133 }
134 
135 static struct skcipher_alg camellia_algs[] = {
136 	{
137 		.base.cra_name		= "__ecb(camellia)",
138 		.base.cra_driver_name	= "__ecb-camellia-aesni-avx2",
139 		.base.cra_priority	= 500,
140 		.base.cra_flags		= CRYPTO_ALG_INTERNAL,
141 		.base.cra_blocksize	= CAMELLIA_BLOCK_SIZE,
142 		.base.cra_ctxsize	= sizeof(struct camellia_ctx),
143 		.base.cra_module	= THIS_MODULE,
144 		.min_keysize		= CAMELLIA_MIN_KEY_SIZE,
145 		.max_keysize		= CAMELLIA_MAX_KEY_SIZE,
146 		.setkey			= camellia_setkey,
147 		.encrypt		= ecb_encrypt,
148 		.decrypt		= ecb_decrypt,
149 	}, {
150 		.base.cra_name		= "__cbc(camellia)",
151 		.base.cra_driver_name	= "__cbc-camellia-aesni-avx2",
152 		.base.cra_priority	= 500,
153 		.base.cra_flags		= CRYPTO_ALG_INTERNAL,
154 		.base.cra_blocksize	= CAMELLIA_BLOCK_SIZE,
155 		.base.cra_ctxsize	= sizeof(struct camellia_ctx),
156 		.base.cra_module	= THIS_MODULE,
157 		.min_keysize		= CAMELLIA_MIN_KEY_SIZE,
158 		.max_keysize		= CAMELLIA_MAX_KEY_SIZE,
159 		.ivsize			= CAMELLIA_BLOCK_SIZE,
160 		.setkey			= camellia_setkey,
161 		.encrypt		= cbc_encrypt,
162 		.decrypt		= cbc_decrypt,
163 	}, {
164 		.base.cra_name		= "__ctr(camellia)",
165 		.base.cra_driver_name	= "__ctr-camellia-aesni-avx2",
166 		.base.cra_priority	= 500,
167 		.base.cra_flags		= CRYPTO_ALG_INTERNAL,
168 		.base.cra_blocksize	= 1,
169 		.base.cra_ctxsize	= sizeof(struct camellia_ctx),
170 		.base.cra_module	= THIS_MODULE,
171 		.min_keysize		= CAMELLIA_MIN_KEY_SIZE,
172 		.max_keysize		= CAMELLIA_MAX_KEY_SIZE,
173 		.ivsize			= CAMELLIA_BLOCK_SIZE,
174 		.chunksize		= CAMELLIA_BLOCK_SIZE,
175 		.setkey			= camellia_setkey,
176 		.encrypt		= ctr_crypt,
177 		.decrypt		= ctr_crypt,
178 	},
179 };
180 
181 static struct simd_skcipher_alg *camellia_simd_algs[ARRAY_SIZE(camellia_algs)];
182 
183 static int __init camellia_aesni_init(void)
184 {
185 	const char *feature_name;
186 
187 	if (!boot_cpu_has(X86_FEATURE_AVX) ||
188 	    !boot_cpu_has(X86_FEATURE_AVX2) ||
189 	    !boot_cpu_has(X86_FEATURE_AES) ||
190 	    !boot_cpu_has(X86_FEATURE_OSXSAVE)) {
191 		pr_info("AVX2 or AES-NI instructions are not detected.\n");
192 		return -ENODEV;
193 	}
194 
195 	if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,
196 				&feature_name)) {
197 		pr_info("CPU feature '%s' is not supported.\n", feature_name);
198 		return -ENODEV;
199 	}
200 
201 	return simd_register_skciphers_compat(camellia_algs,
202 					      ARRAY_SIZE(camellia_algs),
203 					      camellia_simd_algs);
204 }
205 
206 static void __exit camellia_aesni_fini(void)
207 {
208 	simd_unregister_skciphers(camellia_algs, ARRAY_SIZE(camellia_algs),
209 				  camellia_simd_algs);
210 }
211 
212 module_init(camellia_aesni_init);
213 module_exit(camellia_aesni_fini);
214 
215 MODULE_LICENSE("GPL");
216 MODULE_DESCRIPTION("Camellia Cipher Algorithm, AES-NI/AVX2 optimized");
217 MODULE_ALIAS_CRYPTO("camellia");
218 MODULE_ALIAS_CRYPTO("camellia-asm");
219