1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Glue Code for AVX assembler version of Twofish Cipher
5 * Copyright (C) 2012 Johannes Goetzfried
6 * <Johannes.Goetzfried@informatik.stud.uni-erlangen.de>
8 * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
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>
22 #define TWOFISH_PARALLEL_BLOCKS 8
24 /* 8-way parallel cipher functions */
25 asmlinkage
void twofish_ecb_enc_8way(const void *ctx
, u8
*dst
, const u8
*src
);
26 asmlinkage
void twofish_ecb_dec_8way(const void *ctx
, u8
*dst
, const u8
*src
);
28 asmlinkage
void twofish_cbc_dec_8way(const void *ctx
, u8
*dst
, const u8
*src
);
29 asmlinkage
void twofish_ctr_8way(const void *ctx
, u8
*dst
, const u8
*src
,
32 asmlinkage
void twofish_xts_enc_8way(const void *ctx
, u8
*dst
, const u8
*src
,
34 asmlinkage
void twofish_xts_dec_8way(const void *ctx
, u8
*dst
, const u8
*src
,
37 static int twofish_setkey_skcipher(struct crypto_skcipher
*tfm
,
38 const u8
*key
, unsigned int keylen
)
40 return twofish_setkey(&tfm
->base
, key
, keylen
);
43 static inline void twofish_enc_blk_3way(const void *ctx
, u8
*dst
, const u8
*src
)
45 __twofish_enc_blk_3way(ctx
, dst
, src
, false);
48 static void twofish_xts_enc(const void *ctx
, u8
*dst
, const u8
*src
, le128
*iv
)
50 glue_xts_crypt_128bit_one(ctx
, dst
, src
, iv
, twofish_enc_blk
);
53 static void twofish_xts_dec(const void *ctx
, u8
*dst
, const u8
*src
, le128
*iv
)
55 glue_xts_crypt_128bit_one(ctx
, dst
, src
, iv
, twofish_dec_blk
);
58 struct twofish_xts_ctx
{
59 struct twofish_ctx tweak_ctx
;
60 struct twofish_ctx crypt_ctx
;
63 static int xts_twofish_setkey(struct crypto_skcipher
*tfm
, const u8
*key
,
66 struct twofish_xts_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
69 err
= xts_verify_key(tfm
, key
, keylen
);
73 /* first half of xts-key is for crypt */
74 err
= __twofish_setkey(&ctx
->crypt_ctx
, key
, keylen
/ 2);
78 /* second half of xts-key is for tweak */
79 return __twofish_setkey(&ctx
->tweak_ctx
, key
+ keylen
/ 2, keylen
/ 2);
82 static const struct common_glue_ctx twofish_enc
= {
84 .fpu_blocks_limit
= TWOFISH_PARALLEL_BLOCKS
,
87 .num_blocks
= TWOFISH_PARALLEL_BLOCKS
,
88 .fn_u
= { .ecb
= twofish_ecb_enc_8way
}
91 .fn_u
= { .ecb
= twofish_enc_blk_3way
}
94 .fn_u
= { .ecb
= twofish_enc_blk
}
98 static const struct common_glue_ctx twofish_ctr
= {
100 .fpu_blocks_limit
= TWOFISH_PARALLEL_BLOCKS
,
103 .num_blocks
= TWOFISH_PARALLEL_BLOCKS
,
104 .fn_u
= { .ctr
= twofish_ctr_8way
}
107 .fn_u
= { .ctr
= twofish_enc_blk_ctr_3way
}
110 .fn_u
= { .ctr
= twofish_enc_blk_ctr
}
114 static const struct common_glue_ctx twofish_enc_xts
= {
116 .fpu_blocks_limit
= TWOFISH_PARALLEL_BLOCKS
,
119 .num_blocks
= TWOFISH_PARALLEL_BLOCKS
,
120 .fn_u
= { .xts
= twofish_xts_enc_8way
}
123 .fn_u
= { .xts
= twofish_xts_enc
}
127 static const struct common_glue_ctx twofish_dec
= {
129 .fpu_blocks_limit
= TWOFISH_PARALLEL_BLOCKS
,
132 .num_blocks
= TWOFISH_PARALLEL_BLOCKS
,
133 .fn_u
= { .ecb
= twofish_ecb_dec_8way
}
136 .fn_u
= { .ecb
= twofish_dec_blk_3way
}
139 .fn_u
= { .ecb
= twofish_dec_blk
}
143 static const struct common_glue_ctx twofish_dec_cbc
= {
145 .fpu_blocks_limit
= TWOFISH_PARALLEL_BLOCKS
,
148 .num_blocks
= TWOFISH_PARALLEL_BLOCKS
,
149 .fn_u
= { .cbc
= twofish_cbc_dec_8way
}
152 .fn_u
= { .cbc
= twofish_dec_blk_cbc_3way
}
155 .fn_u
= { .cbc
= twofish_dec_blk
}
159 static const struct common_glue_ctx twofish_dec_xts
= {
161 .fpu_blocks_limit
= TWOFISH_PARALLEL_BLOCKS
,
164 .num_blocks
= TWOFISH_PARALLEL_BLOCKS
,
165 .fn_u
= { .xts
= twofish_xts_dec_8way
}
168 .fn_u
= { .xts
= twofish_xts_dec
}
172 static int ecb_encrypt(struct skcipher_request
*req
)
174 return glue_ecb_req_128bit(&twofish_enc
, req
);
177 static int ecb_decrypt(struct skcipher_request
*req
)
179 return glue_ecb_req_128bit(&twofish_dec
, req
);
182 static int cbc_encrypt(struct skcipher_request
*req
)
184 return glue_cbc_encrypt_req_128bit(twofish_enc_blk
, req
);
187 static int cbc_decrypt(struct skcipher_request
*req
)
189 return glue_cbc_decrypt_req_128bit(&twofish_dec_cbc
, req
);
192 static int ctr_crypt(struct skcipher_request
*req
)
194 return glue_ctr_req_128bit(&twofish_ctr
, req
);
197 static int xts_encrypt(struct skcipher_request
*req
)
199 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
200 struct twofish_xts_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
202 return glue_xts_req_128bit(&twofish_enc_xts
, req
, twofish_enc_blk
,
203 &ctx
->tweak_ctx
, &ctx
->crypt_ctx
, false);
206 static int xts_decrypt(struct skcipher_request
*req
)
208 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
209 struct twofish_xts_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
211 return glue_xts_req_128bit(&twofish_dec_xts
, req
, twofish_enc_blk
,
212 &ctx
->tweak_ctx
, &ctx
->crypt_ctx
, true);
215 static struct skcipher_alg twofish_algs
[] = {
217 .base
.cra_name
= "__ecb(twofish)",
218 .base
.cra_driver_name
= "__ecb-twofish-avx",
219 .base
.cra_priority
= 400,
220 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
221 .base
.cra_blocksize
= TF_BLOCK_SIZE
,
222 .base
.cra_ctxsize
= sizeof(struct twofish_ctx
),
223 .base
.cra_module
= THIS_MODULE
,
224 .min_keysize
= TF_MIN_KEY_SIZE
,
225 .max_keysize
= TF_MAX_KEY_SIZE
,
226 .setkey
= twofish_setkey_skcipher
,
227 .encrypt
= ecb_encrypt
,
228 .decrypt
= ecb_decrypt
,
230 .base
.cra_name
= "__cbc(twofish)",
231 .base
.cra_driver_name
= "__cbc-twofish-avx",
232 .base
.cra_priority
= 400,
233 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
234 .base
.cra_blocksize
= TF_BLOCK_SIZE
,
235 .base
.cra_ctxsize
= sizeof(struct twofish_ctx
),
236 .base
.cra_module
= THIS_MODULE
,
237 .min_keysize
= TF_MIN_KEY_SIZE
,
238 .max_keysize
= TF_MAX_KEY_SIZE
,
239 .ivsize
= TF_BLOCK_SIZE
,
240 .setkey
= twofish_setkey_skcipher
,
241 .encrypt
= cbc_encrypt
,
242 .decrypt
= cbc_decrypt
,
244 .base
.cra_name
= "__ctr(twofish)",
245 .base
.cra_driver_name
= "__ctr-twofish-avx",
246 .base
.cra_priority
= 400,
247 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
248 .base
.cra_blocksize
= 1,
249 .base
.cra_ctxsize
= sizeof(struct twofish_ctx
),
250 .base
.cra_module
= THIS_MODULE
,
251 .min_keysize
= TF_MIN_KEY_SIZE
,
252 .max_keysize
= TF_MAX_KEY_SIZE
,
253 .ivsize
= TF_BLOCK_SIZE
,
254 .chunksize
= TF_BLOCK_SIZE
,
255 .setkey
= twofish_setkey_skcipher
,
256 .encrypt
= ctr_crypt
,
257 .decrypt
= ctr_crypt
,
259 .base
.cra_name
= "__xts(twofish)",
260 .base
.cra_driver_name
= "__xts-twofish-avx",
261 .base
.cra_priority
= 400,
262 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
263 .base
.cra_blocksize
= TF_BLOCK_SIZE
,
264 .base
.cra_ctxsize
= sizeof(struct twofish_xts_ctx
),
265 .base
.cra_module
= THIS_MODULE
,
266 .min_keysize
= 2 * TF_MIN_KEY_SIZE
,
267 .max_keysize
= 2 * TF_MAX_KEY_SIZE
,
268 .ivsize
= TF_BLOCK_SIZE
,
269 .setkey
= xts_twofish_setkey
,
270 .encrypt
= xts_encrypt
,
271 .decrypt
= xts_decrypt
,
275 static struct simd_skcipher_alg
*twofish_simd_algs
[ARRAY_SIZE(twofish_algs
)];
277 static int __init
twofish_init(void)
279 const char *feature_name
;
281 if (!cpu_has_xfeatures(XFEATURE_MASK_SSE
| XFEATURE_MASK_YMM
, &feature_name
)) {
282 pr_info("CPU feature '%s' is not supported.\n", feature_name
);
286 return simd_register_skciphers_compat(twofish_algs
,
287 ARRAY_SIZE(twofish_algs
),
291 static void __exit
twofish_exit(void)
293 simd_unregister_skciphers(twofish_algs
, ARRAY_SIZE(twofish_algs
),
297 module_init(twofish_init
);
298 module_exit(twofish_exit
);
300 MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized");
301 MODULE_LICENSE("GPL");
302 MODULE_ALIAS_CRYPTO("twofish");