1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Glue Code for x86_64/AVX/AES-NI assembler optimized version of Camellia
5 * Copyright © 2012-2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
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>
17 #define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
19 /* 16-way parallel cipher functions (avx/aes-ni) */
20 asmlinkage void camellia_ecb_enc_16way(const void *ctx, u8 *dst, const u8 *src);
21 EXPORT_SYMBOL_GPL(camellia_ecb_enc_16way);
23 asmlinkage void camellia_ecb_dec_16way(const void *ctx, u8 *dst, const u8 *src);
24 EXPORT_SYMBOL_GPL(camellia_ecb_dec_16way);
26 asmlinkage void camellia_cbc_dec_16way(const void *ctx, u8 *dst, const u8 *src);
27 EXPORT_SYMBOL_GPL(camellia_cbc_dec_16way);
29 asmlinkage void camellia_ctr_16way(const void *ctx, u8 *dst, const u8 *src,
31 EXPORT_SYMBOL_GPL(camellia_ctr_16way);
33 static const struct common_glue_ctx camellia_enc = {
35 .fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
38 .num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
39 .fn_u = { .ecb = camellia_ecb_enc_16way }
42 .fn_u = { .ecb = camellia_enc_blk_2way }
45 .fn_u = { .ecb = camellia_enc_blk }
49 static const struct common_glue_ctx camellia_ctr = {
51 .fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
54 .num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
55 .fn_u = { .ctr = camellia_ctr_16way }
58 .fn_u = { .ctr = camellia_crypt_ctr_2way }
61 .fn_u = { .ctr = camellia_crypt_ctr }
65 static const struct common_glue_ctx camellia_dec = {
67 .fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
70 .num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
71 .fn_u = { .ecb = camellia_ecb_dec_16way }
74 .fn_u = { .ecb = camellia_dec_blk_2way }
77 .fn_u = { .ecb = camellia_dec_blk }
81 static const struct common_glue_ctx camellia_dec_cbc = {
83 .fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
86 .num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
87 .fn_u = { .cbc = camellia_cbc_dec_16way }
90 .fn_u = { .cbc = camellia_decrypt_cbc_2way }
93 .fn_u = { .cbc = camellia_dec_blk }
97 static int camellia_setkey(struct crypto_skcipher *tfm, const u8 *key,
100 return __camellia_setkey(crypto_skcipher_ctx(tfm), key, keylen);
103 static int ecb_encrypt(struct skcipher_request *req)
105 return glue_ecb_req_128bit(&camellia_enc, req);
108 static int ecb_decrypt(struct skcipher_request *req)
110 return glue_ecb_req_128bit(&camellia_dec, req);
113 static int cbc_encrypt(struct skcipher_request *req)
115 return glue_cbc_encrypt_req_128bit(camellia_enc_blk, req);
118 static int cbc_decrypt(struct skcipher_request *req)
120 return glue_cbc_decrypt_req_128bit(&camellia_dec_cbc, req);
123 static int ctr_crypt(struct skcipher_request *req)
125 return glue_ctr_req_128bit(&camellia_ctr, req);
128 static struct skcipher_alg camellia_algs[] = {
130 .base.cra_name = "__ecb(camellia)",
131 .base.cra_driver_name = "__ecb-camellia-aesni",
132 .base.cra_priority = 400,
133 .base.cra_flags = CRYPTO_ALG_INTERNAL,
134 .base.cra_blocksize = CAMELLIA_BLOCK_SIZE,
135 .base.cra_ctxsize = sizeof(struct camellia_ctx),
136 .base.cra_module = THIS_MODULE,
137 .min_keysize = CAMELLIA_MIN_KEY_SIZE,
138 .max_keysize = CAMELLIA_MAX_KEY_SIZE,
139 .setkey = camellia_setkey,
140 .encrypt = ecb_encrypt,
141 .decrypt = ecb_decrypt,
143 .base.cra_name = "__cbc(camellia)",
144 .base.cra_driver_name = "__cbc-camellia-aesni",
145 .base.cra_priority = 400,
146 .base.cra_flags = CRYPTO_ALG_INTERNAL,
147 .base.cra_blocksize = CAMELLIA_BLOCK_SIZE,
148 .base.cra_ctxsize = sizeof(struct camellia_ctx),
149 .base.cra_module = THIS_MODULE,
150 .min_keysize = CAMELLIA_MIN_KEY_SIZE,
151 .max_keysize = CAMELLIA_MAX_KEY_SIZE,
152 .ivsize = CAMELLIA_BLOCK_SIZE,
153 .setkey = camellia_setkey,
154 .encrypt = cbc_encrypt,
155 .decrypt = cbc_decrypt,
157 .base.cra_name = "__ctr(camellia)",
158 .base.cra_driver_name = "__ctr-camellia-aesni",
159 .base.cra_priority = 400,
160 .base.cra_flags = CRYPTO_ALG_INTERNAL,
161 .base.cra_blocksize = 1,
162 .base.cra_ctxsize = sizeof(struct camellia_ctx),
163 .base.cra_module = THIS_MODULE,
164 .min_keysize = CAMELLIA_MIN_KEY_SIZE,
165 .max_keysize = CAMELLIA_MAX_KEY_SIZE,
166 .ivsize = CAMELLIA_BLOCK_SIZE,
167 .chunksize = CAMELLIA_BLOCK_SIZE,
168 .setkey = camellia_setkey,
169 .encrypt = ctr_crypt,
170 .decrypt = ctr_crypt,
174 static struct simd_skcipher_alg *camellia_simd_algs[ARRAY_SIZE(camellia_algs)];
176 static int __init camellia_aesni_init(void)
178 const char *feature_name;
180 if (!boot_cpu_has(X86_FEATURE_AVX) ||
181 !boot_cpu_has(X86_FEATURE_AES) ||
182 !boot_cpu_has(X86_FEATURE_OSXSAVE)) {
183 pr_info("AVX or AES-NI instructions are not detected.\n");
187 if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,
189 pr_info("CPU feature '%s' is not supported.\n", feature_name);
193 return simd_register_skciphers_compat(camellia_algs,
194 ARRAY_SIZE(camellia_algs),
198 static void __exit camellia_aesni_fini(void)
200 simd_unregister_skciphers(camellia_algs, ARRAY_SIZE(camellia_algs),
204 module_init(camellia_aesni_init);
205 module_exit(camellia_aesni_fini);
207 MODULE_LICENSE("GPL");
208 MODULE_DESCRIPTION("Camellia Cipher Algorithm, AES-NI/AVX optimized");
209 MODULE_ALIAS_CRYPTO("camellia");
210 MODULE_ALIAS_CRYPTO("camellia-asm");