2 * Glue Code for x86_64/AVX/AES-NI assembler optimized version of Camellia
4 * Copyright © 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
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.
13 #include <linux/module.h>
14 #include <linux/types.h>
15 #include <linux/crypto.h>
16 #include <linux/err.h>
17 #include <crypto/algapi.h>
18 #include <crypto/ctr.h>
19 #include <crypto/lrw.h>
20 #include <crypto/xts.h>
22 #include <asm/xsave.h>
23 #include <asm/crypto/camellia.h>
24 #include <asm/crypto/ablk_helper.h>
25 #include <asm/crypto/glue_helper.h>
27 #define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
29 /* 16-way AES-NI parallel cipher functions */
30 asmlinkage
void camellia_ecb_enc_16way(struct camellia_ctx
*ctx
, u8
*dst
,
32 asmlinkage
void camellia_ecb_dec_16way(struct camellia_ctx
*ctx
, u8
*dst
,
35 asmlinkage
void camellia_cbc_dec_16way(struct camellia_ctx
*ctx
, u8
*dst
,
37 asmlinkage
void camellia_ctr_16way(struct camellia_ctx
*ctx
, u8
*dst
,
38 const u8
*src
, le128
*iv
);
40 static const struct common_glue_ctx camellia_enc
= {
42 .fpu_blocks_limit
= CAMELLIA_AESNI_PARALLEL_BLOCKS
,
45 .num_blocks
= CAMELLIA_AESNI_PARALLEL_BLOCKS
,
46 .fn_u
= { .ecb
= GLUE_FUNC_CAST(camellia_ecb_enc_16way
) }
49 .fn_u
= { .ecb
= GLUE_FUNC_CAST(camellia_enc_blk_2way
) }
52 .fn_u
= { .ecb
= GLUE_FUNC_CAST(camellia_enc_blk
) }
56 static const struct common_glue_ctx camellia_ctr
= {
58 .fpu_blocks_limit
= CAMELLIA_AESNI_PARALLEL_BLOCKS
,
61 .num_blocks
= CAMELLIA_AESNI_PARALLEL_BLOCKS
,
62 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(camellia_ctr_16way
) }
65 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(camellia_crypt_ctr_2way
) }
68 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(camellia_crypt_ctr
) }
72 static const struct common_glue_ctx camellia_dec
= {
74 .fpu_blocks_limit
= CAMELLIA_AESNI_PARALLEL_BLOCKS
,
77 .num_blocks
= CAMELLIA_AESNI_PARALLEL_BLOCKS
,
78 .fn_u
= { .ecb
= GLUE_FUNC_CAST(camellia_ecb_dec_16way
) }
81 .fn_u
= { .ecb
= GLUE_FUNC_CAST(camellia_dec_blk_2way
) }
84 .fn_u
= { .ecb
= GLUE_FUNC_CAST(camellia_dec_blk
) }
88 static const struct common_glue_ctx camellia_dec_cbc
= {
90 .fpu_blocks_limit
= CAMELLIA_AESNI_PARALLEL_BLOCKS
,
93 .num_blocks
= CAMELLIA_AESNI_PARALLEL_BLOCKS
,
94 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(camellia_cbc_dec_16way
) }
97 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(camellia_decrypt_cbc_2way
) }
100 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(camellia_dec_blk
) }
104 static int ecb_encrypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
105 struct scatterlist
*src
, unsigned int nbytes
)
107 return glue_ecb_crypt_128bit(&camellia_enc
, desc
, dst
, src
, nbytes
);
110 static int ecb_decrypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
111 struct scatterlist
*src
, unsigned int nbytes
)
113 return glue_ecb_crypt_128bit(&camellia_dec
, desc
, dst
, src
, nbytes
);
116 static int cbc_encrypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
117 struct scatterlist
*src
, unsigned int nbytes
)
119 return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(camellia_enc_blk
), desc
,
123 static int cbc_decrypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
124 struct scatterlist
*src
, unsigned int nbytes
)
126 return glue_cbc_decrypt_128bit(&camellia_dec_cbc
, desc
, dst
, src
,
130 static int ctr_crypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
131 struct scatterlist
*src
, unsigned int nbytes
)
133 return glue_ctr_crypt_128bit(&camellia_ctr
, desc
, dst
, src
, nbytes
);
136 static inline bool camellia_fpu_begin(bool fpu_enabled
, unsigned int nbytes
)
138 return glue_fpu_begin(CAMELLIA_BLOCK_SIZE
,
139 CAMELLIA_AESNI_PARALLEL_BLOCKS
, NULL
, fpu_enabled
,
143 static inline void camellia_fpu_end(bool fpu_enabled
)
145 glue_fpu_end(fpu_enabled
);
148 static int camellia_setkey(struct crypto_tfm
*tfm
, const u8
*in_key
,
149 unsigned int key_len
)
151 return __camellia_setkey(crypto_tfm_ctx(tfm
), in_key
, key_len
,
156 struct camellia_ctx
*ctx
;
160 static void encrypt_callback(void *priv
, u8
*srcdst
, unsigned int nbytes
)
162 const unsigned int bsize
= CAMELLIA_BLOCK_SIZE
;
163 struct crypt_priv
*ctx
= priv
;
166 ctx
->fpu_enabled
= camellia_fpu_begin(ctx
->fpu_enabled
, nbytes
);
168 if (nbytes
>= CAMELLIA_AESNI_PARALLEL_BLOCKS
* bsize
) {
169 camellia_ecb_enc_16way(ctx
->ctx
, srcdst
, srcdst
);
170 srcdst
+= bsize
* CAMELLIA_AESNI_PARALLEL_BLOCKS
;
171 nbytes
-= bsize
* CAMELLIA_AESNI_PARALLEL_BLOCKS
;
174 while (nbytes
>= CAMELLIA_PARALLEL_BLOCKS
* bsize
) {
175 camellia_enc_blk_2way(ctx
->ctx
, srcdst
, srcdst
);
176 srcdst
+= bsize
* CAMELLIA_PARALLEL_BLOCKS
;
177 nbytes
-= bsize
* CAMELLIA_PARALLEL_BLOCKS
;
180 for (i
= 0; i
< nbytes
/ bsize
; i
++, srcdst
+= bsize
)
181 camellia_enc_blk(ctx
->ctx
, srcdst
, srcdst
);
184 static void decrypt_callback(void *priv
, u8
*srcdst
, unsigned int nbytes
)
186 const unsigned int bsize
= CAMELLIA_BLOCK_SIZE
;
187 struct crypt_priv
*ctx
= priv
;
190 ctx
->fpu_enabled
= camellia_fpu_begin(ctx
->fpu_enabled
, nbytes
);
192 if (nbytes
>= CAMELLIA_AESNI_PARALLEL_BLOCKS
* bsize
) {
193 camellia_ecb_dec_16way(ctx
->ctx
, srcdst
, srcdst
);
194 srcdst
+= bsize
* CAMELLIA_AESNI_PARALLEL_BLOCKS
;
195 nbytes
-= bsize
* CAMELLIA_AESNI_PARALLEL_BLOCKS
;
198 while (nbytes
>= CAMELLIA_PARALLEL_BLOCKS
* bsize
) {
199 camellia_dec_blk_2way(ctx
->ctx
, srcdst
, srcdst
);
200 srcdst
+= bsize
* CAMELLIA_PARALLEL_BLOCKS
;
201 nbytes
-= bsize
* CAMELLIA_PARALLEL_BLOCKS
;
204 for (i
= 0; i
< nbytes
/ bsize
; i
++, srcdst
+= bsize
)
205 camellia_dec_blk(ctx
->ctx
, srcdst
, srcdst
);
208 static int lrw_encrypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
209 struct scatterlist
*src
, unsigned int nbytes
)
211 struct camellia_lrw_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
212 be128 buf
[CAMELLIA_AESNI_PARALLEL_BLOCKS
];
213 struct crypt_priv crypt_ctx
= {
214 .ctx
= &ctx
->camellia_ctx
,
215 .fpu_enabled
= false,
217 struct lrw_crypt_req req
= {
219 .tbuflen
= sizeof(buf
),
221 .table_ctx
= &ctx
->lrw_table
,
222 .crypt_ctx
= &crypt_ctx
,
223 .crypt_fn
= encrypt_callback
,
227 desc
->flags
&= ~CRYPTO_TFM_REQ_MAY_SLEEP
;
228 ret
= lrw_crypt(desc
, dst
, src
, nbytes
, &req
);
229 camellia_fpu_end(crypt_ctx
.fpu_enabled
);
234 static int lrw_decrypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
235 struct scatterlist
*src
, unsigned int nbytes
)
237 struct camellia_lrw_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
238 be128 buf
[CAMELLIA_AESNI_PARALLEL_BLOCKS
];
239 struct crypt_priv crypt_ctx
= {
240 .ctx
= &ctx
->camellia_ctx
,
241 .fpu_enabled
= false,
243 struct lrw_crypt_req req
= {
245 .tbuflen
= sizeof(buf
),
247 .table_ctx
= &ctx
->lrw_table
,
248 .crypt_ctx
= &crypt_ctx
,
249 .crypt_fn
= decrypt_callback
,
253 desc
->flags
&= ~CRYPTO_TFM_REQ_MAY_SLEEP
;
254 ret
= lrw_crypt(desc
, dst
, src
, nbytes
, &req
);
255 camellia_fpu_end(crypt_ctx
.fpu_enabled
);
260 static int xts_encrypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
261 struct scatterlist
*src
, unsigned int nbytes
)
263 struct camellia_xts_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
264 be128 buf
[CAMELLIA_AESNI_PARALLEL_BLOCKS
];
265 struct crypt_priv crypt_ctx
= {
266 .ctx
= &ctx
->crypt_ctx
,
267 .fpu_enabled
= false,
269 struct xts_crypt_req req
= {
271 .tbuflen
= sizeof(buf
),
273 .tweak_ctx
= &ctx
->tweak_ctx
,
274 .tweak_fn
= XTS_TWEAK_CAST(camellia_enc_blk
),
275 .crypt_ctx
= &crypt_ctx
,
276 .crypt_fn
= encrypt_callback
,
280 desc
->flags
&= ~CRYPTO_TFM_REQ_MAY_SLEEP
;
281 ret
= xts_crypt(desc
, dst
, src
, nbytes
, &req
);
282 camellia_fpu_end(crypt_ctx
.fpu_enabled
);
287 static int xts_decrypt(struct blkcipher_desc
*desc
, struct scatterlist
*dst
,
288 struct scatterlist
*src
, unsigned int nbytes
)
290 struct camellia_xts_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
291 be128 buf
[CAMELLIA_AESNI_PARALLEL_BLOCKS
];
292 struct crypt_priv crypt_ctx
= {
293 .ctx
= &ctx
->crypt_ctx
,
294 .fpu_enabled
= false,
296 struct xts_crypt_req req
= {
298 .tbuflen
= sizeof(buf
),
300 .tweak_ctx
= &ctx
->tweak_ctx
,
301 .tweak_fn
= XTS_TWEAK_CAST(camellia_enc_blk
),
302 .crypt_ctx
= &crypt_ctx
,
303 .crypt_fn
= decrypt_callback
,
307 desc
->flags
&= ~CRYPTO_TFM_REQ_MAY_SLEEP
;
308 ret
= xts_crypt(desc
, dst
, src
, nbytes
, &req
);
309 camellia_fpu_end(crypt_ctx
.fpu_enabled
);
314 static struct crypto_alg cmll_algs
[10] = { {
315 .cra_name
= "__ecb-camellia-aesni",
316 .cra_driver_name
= "__driver-ecb-camellia-aesni",
318 .cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
,
319 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
320 .cra_ctxsize
= sizeof(struct camellia_ctx
),
322 .cra_type
= &crypto_blkcipher_type
,
323 .cra_module
= THIS_MODULE
,
326 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
327 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
328 .setkey
= camellia_setkey
,
329 .encrypt
= ecb_encrypt
,
330 .decrypt
= ecb_decrypt
,
334 .cra_name
= "__cbc-camellia-aesni",
335 .cra_driver_name
= "__driver-cbc-camellia-aesni",
337 .cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
,
338 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
339 .cra_ctxsize
= sizeof(struct camellia_ctx
),
341 .cra_type
= &crypto_blkcipher_type
,
342 .cra_module
= THIS_MODULE
,
345 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
346 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
347 .setkey
= camellia_setkey
,
348 .encrypt
= cbc_encrypt
,
349 .decrypt
= cbc_decrypt
,
353 .cra_name
= "__ctr-camellia-aesni",
354 .cra_driver_name
= "__driver-ctr-camellia-aesni",
356 .cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
,
358 .cra_ctxsize
= sizeof(struct camellia_ctx
),
360 .cra_type
= &crypto_blkcipher_type
,
361 .cra_module
= THIS_MODULE
,
364 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
365 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
366 .ivsize
= CAMELLIA_BLOCK_SIZE
,
367 .setkey
= camellia_setkey
,
368 .encrypt
= ctr_crypt
,
369 .decrypt
= ctr_crypt
,
373 .cra_name
= "__lrw-camellia-aesni",
374 .cra_driver_name
= "__driver-lrw-camellia-aesni",
376 .cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
,
377 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
378 .cra_ctxsize
= sizeof(struct camellia_lrw_ctx
),
380 .cra_type
= &crypto_blkcipher_type
,
381 .cra_module
= THIS_MODULE
,
382 .cra_exit
= lrw_camellia_exit_tfm
,
385 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
+
387 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
+
389 .ivsize
= CAMELLIA_BLOCK_SIZE
,
390 .setkey
= lrw_camellia_setkey
,
391 .encrypt
= lrw_encrypt
,
392 .decrypt
= lrw_decrypt
,
396 .cra_name
= "__xts-camellia-aesni",
397 .cra_driver_name
= "__driver-xts-camellia-aesni",
399 .cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
,
400 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
401 .cra_ctxsize
= sizeof(struct camellia_xts_ctx
),
403 .cra_type
= &crypto_blkcipher_type
,
404 .cra_module
= THIS_MODULE
,
407 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
* 2,
408 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
* 2,
409 .ivsize
= CAMELLIA_BLOCK_SIZE
,
410 .setkey
= xts_camellia_setkey
,
411 .encrypt
= xts_encrypt
,
412 .decrypt
= xts_decrypt
,
416 .cra_name
= "ecb(camellia)",
417 .cra_driver_name
= "ecb-camellia-aesni",
419 .cra_flags
= CRYPTO_ALG_TYPE_ABLKCIPHER
| CRYPTO_ALG_ASYNC
,
420 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
421 .cra_ctxsize
= sizeof(struct async_helper_ctx
),
423 .cra_type
= &crypto_ablkcipher_type
,
424 .cra_module
= THIS_MODULE
,
425 .cra_init
= ablk_init
,
426 .cra_exit
= ablk_exit
,
429 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
430 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
431 .setkey
= ablk_set_key
,
432 .encrypt
= ablk_encrypt
,
433 .decrypt
= ablk_decrypt
,
437 .cra_name
= "cbc(camellia)",
438 .cra_driver_name
= "cbc-camellia-aesni",
440 .cra_flags
= CRYPTO_ALG_TYPE_ABLKCIPHER
| CRYPTO_ALG_ASYNC
,
441 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
442 .cra_ctxsize
= sizeof(struct async_helper_ctx
),
444 .cra_type
= &crypto_ablkcipher_type
,
445 .cra_module
= THIS_MODULE
,
446 .cra_init
= ablk_init
,
447 .cra_exit
= ablk_exit
,
450 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
451 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
452 .ivsize
= CAMELLIA_BLOCK_SIZE
,
453 .setkey
= ablk_set_key
,
454 .encrypt
= __ablk_encrypt
,
455 .decrypt
= ablk_decrypt
,
459 .cra_name
= "ctr(camellia)",
460 .cra_driver_name
= "ctr-camellia-aesni",
462 .cra_flags
= CRYPTO_ALG_TYPE_ABLKCIPHER
| CRYPTO_ALG_ASYNC
,
464 .cra_ctxsize
= sizeof(struct async_helper_ctx
),
466 .cra_type
= &crypto_ablkcipher_type
,
467 .cra_module
= THIS_MODULE
,
468 .cra_init
= ablk_init
,
469 .cra_exit
= ablk_exit
,
472 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
473 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
474 .ivsize
= CAMELLIA_BLOCK_SIZE
,
475 .setkey
= ablk_set_key
,
476 .encrypt
= ablk_encrypt
,
477 .decrypt
= ablk_encrypt
,
482 .cra_name
= "lrw(camellia)",
483 .cra_driver_name
= "lrw-camellia-aesni",
485 .cra_flags
= CRYPTO_ALG_TYPE_ABLKCIPHER
| CRYPTO_ALG_ASYNC
,
486 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
487 .cra_ctxsize
= sizeof(struct async_helper_ctx
),
489 .cra_type
= &crypto_ablkcipher_type
,
490 .cra_module
= THIS_MODULE
,
491 .cra_init
= ablk_init
,
492 .cra_exit
= ablk_exit
,
495 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
+
497 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
+
499 .ivsize
= CAMELLIA_BLOCK_SIZE
,
500 .setkey
= ablk_set_key
,
501 .encrypt
= ablk_encrypt
,
502 .decrypt
= ablk_decrypt
,
506 .cra_name
= "xts(camellia)",
507 .cra_driver_name
= "xts-camellia-aesni",
509 .cra_flags
= CRYPTO_ALG_TYPE_ABLKCIPHER
| CRYPTO_ALG_ASYNC
,
510 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
511 .cra_ctxsize
= sizeof(struct async_helper_ctx
),
513 .cra_type
= &crypto_ablkcipher_type
,
514 .cra_module
= THIS_MODULE
,
515 .cra_init
= ablk_init
,
516 .cra_exit
= ablk_exit
,
519 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
* 2,
520 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
* 2,
521 .ivsize
= CAMELLIA_BLOCK_SIZE
,
522 .setkey
= ablk_set_key
,
523 .encrypt
= ablk_encrypt
,
524 .decrypt
= ablk_decrypt
,
529 static int __init
camellia_aesni_init(void)
533 if (!cpu_has_avx
|| !cpu_has_aes
|| !cpu_has_osxsave
) {
534 pr_info("AVX or AES-NI instructions are not detected.\n");
538 xcr0
= xgetbv(XCR_XFEATURE_ENABLED_MASK
);
539 if ((xcr0
& (XSTATE_SSE
| XSTATE_YMM
)) != (XSTATE_SSE
| XSTATE_YMM
)) {
540 pr_info("AVX detected but unusable.\n");
544 return crypto_register_algs(cmll_algs
, ARRAY_SIZE(cmll_algs
));
547 static void __exit
camellia_aesni_fini(void)
549 crypto_unregister_algs(cmll_algs
, ARRAY_SIZE(cmll_algs
));
552 module_init(camellia_aesni_init
);
553 module_exit(camellia_aesni_fini
);
555 MODULE_LICENSE("GPL");
556 MODULE_DESCRIPTION("Camellia Cipher Algorithm, AES-NI/AVX optimized");
557 MODULE_ALIAS("camellia");
558 MODULE_ALIAS("camellia-asm");