diff options
author | Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 2011-11-09 09:26:36 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2011-11-21 03:13:24 -0500 |
commit | 18482053f92b099663bd36a10e8f6bd2c8544669 (patch) | |
tree | 5747eb47b1b0ffa59d4ad5c2402021e3b4544a1f | |
parent | 251496dbfc1be38bc43b49651f3d33c02faccc47 (diff) |
crypto: serpent-sse2 - add lrw support
Patch adds LRW support for serpent-sse2 by using lrw_crypt(). Patch has been
tested with tcrypt and automated filesystem tests.
Tcrypt benchmarks results (serpent-sse2/serpent_generic speed ratios):
Benchmark results with tcrypt:
Intel Celeron T1600 (x86_64) (fam:6, model:15, step:13):
size lrw-enc lrw-dec
16B 1.00x 0.96x
64B 1.01x 1.01x
256B 3.01x 2.97x
1024B 3.39x 3.33x
8192B 3.35x 3.33x
AMD Phenom II 1055T (x86_64) (fam:16, model:10):
size lrw-enc lrw-dec
16B 0.98x 1.03x
64B 1.01x 1.04x
256B 2.10x 2.14x
1024B 2.28x 2.33x
8192B 2.30x 2.33x
Intel Atom N270 (i586):
size lrw-enc lrw-dec
16B 0.97x 0.97x
64B 1.47x 1.50x
256B 1.72x 1.69x
1024B 1.88x 1.81x
8192B 1.84x 1.79x
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | arch/x86/crypto/serpent_sse2_glue.c | 211 | ||||
-rw-r--r-- | crypto/serpent.c | 10 | ||||
-rw-r--r-- | include/crypto/serpent.h | 2 |
3 files changed, 221 insertions, 2 deletions
diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index 947cf570f6a7..db318e5cb240 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c | |||
@@ -39,12 +39,17 @@ | |||
39 | #include <crypto/cryptd.h> | 39 | #include <crypto/cryptd.h> |
40 | #include <crypto/b128ops.h> | 40 | #include <crypto/b128ops.h> |
41 | #include <crypto/ctr.h> | 41 | #include <crypto/ctr.h> |
42 | #include <crypto/lrw.h> | ||
42 | #include <asm/i387.h> | 43 | #include <asm/i387.h> |
43 | #include <asm/serpent.h> | 44 | #include <asm/serpent.h> |
44 | #include <crypto/scatterwalk.h> | 45 | #include <crypto/scatterwalk.h> |
45 | #include <linux/workqueue.h> | 46 | #include <linux/workqueue.h> |
46 | #include <linux/spinlock.h> | 47 | #include <linux/spinlock.h> |
47 | 48 | ||
49 | #if defined(CONFIG_CRYPTO_LRW) || defined(CONFIG_CRYPTO_LRW_MODULE) | ||
50 | #define HAS_LRW | ||
51 | #endif | ||
52 | |||
48 | struct async_serpent_ctx { | 53 | struct async_serpent_ctx { |
49 | struct cryptd_ablkcipher *cryptd_tfm; | 54 | struct cryptd_ablkcipher *cryptd_tfm; |
50 | }; | 55 | }; |
@@ -460,6 +465,152 @@ static struct crypto_alg blk_ctr_alg = { | |||
460 | }, | 465 | }, |
461 | }; | 466 | }; |
462 | 467 | ||
468 | #ifdef HAS_LRW | ||
469 | |||
470 | struct crypt_priv { | ||
471 | struct serpent_ctx *ctx; | ||
472 | bool fpu_enabled; | ||
473 | }; | ||
474 | |||
475 | static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) | ||
476 | { | ||
477 | const unsigned int bsize = SERPENT_BLOCK_SIZE; | ||
478 | struct crypt_priv *ctx = priv; | ||
479 | int i; | ||
480 | |||
481 | ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes); | ||
482 | |||
483 | if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) { | ||
484 | serpent_enc_blk_xway(ctx->ctx, srcdst, srcdst); | ||
485 | return; | ||
486 | } | ||
487 | |||
488 | for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) | ||
489 | __serpent_encrypt(ctx->ctx, srcdst, srcdst); | ||
490 | } | ||
491 | |||
492 | static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) | ||
493 | { | ||
494 | const unsigned int bsize = SERPENT_BLOCK_SIZE; | ||
495 | struct crypt_priv *ctx = priv; | ||
496 | int i; | ||
497 | |||
498 | ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes); | ||
499 | |||
500 | if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) { | ||
501 | serpent_dec_blk_xway(ctx->ctx, srcdst, srcdst); | ||
502 | return; | ||
503 | } | ||
504 | |||
505 | for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) | ||
506 | __serpent_decrypt(ctx->ctx, srcdst, srcdst); | ||
507 | } | ||
508 | |||
509 | struct serpent_lrw_ctx { | ||
510 | struct lrw_table_ctx lrw_table; | ||
511 | struct serpent_ctx serpent_ctx; | ||
512 | }; | ||
513 | |||
514 | static int lrw_serpent_setkey(struct crypto_tfm *tfm, const u8 *key, | ||
515 | unsigned int keylen) | ||
516 | { | ||
517 | struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm); | ||
518 | int err; | ||
519 | |||
520 | err = __serpent_setkey(&ctx->serpent_ctx, key, keylen - | ||
521 | SERPENT_BLOCK_SIZE); | ||
522 | if (err) | ||
523 | return err; | ||
524 | |||
525 | return lrw_init_table(&ctx->lrw_table, key + keylen - | ||
526 | SERPENT_BLOCK_SIZE); | ||
527 | } | ||
528 | |||
529 | static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
530 | struct scatterlist *src, unsigned int nbytes) | ||
531 | { | ||
532 | struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
533 | be128 buf[SERPENT_PARALLEL_BLOCKS]; | ||
534 | struct crypt_priv crypt_ctx = { | ||
535 | .ctx = &ctx->serpent_ctx, | ||
536 | .fpu_enabled = false, | ||
537 | }; | ||
538 | struct lrw_crypt_req req = { | ||
539 | .tbuf = buf, | ||
540 | .tbuflen = sizeof(buf), | ||
541 | |||
542 | .table_ctx = &ctx->lrw_table, | ||
543 | .crypt_ctx = &crypt_ctx, | ||
544 | .crypt_fn = encrypt_callback, | ||
545 | }; | ||
546 | int ret; | ||
547 | |||
548 | ret = lrw_crypt(desc, dst, src, nbytes, &req); | ||
549 | serpent_fpu_end(crypt_ctx.fpu_enabled); | ||
550 | |||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
555 | struct scatterlist *src, unsigned int nbytes) | ||
556 | { | ||
557 | struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
558 | be128 buf[SERPENT_PARALLEL_BLOCKS]; | ||
559 | struct crypt_priv crypt_ctx = { | ||
560 | .ctx = &ctx->serpent_ctx, | ||
561 | .fpu_enabled = false, | ||
562 | }; | ||
563 | struct lrw_crypt_req req = { | ||
564 | .tbuf = buf, | ||
565 | .tbuflen = sizeof(buf), | ||
566 | |||
567 | .table_ctx = &ctx->lrw_table, | ||
568 | .crypt_ctx = &crypt_ctx, | ||
569 | .crypt_fn = decrypt_callback, | ||
570 | }; | ||
571 | int ret; | ||
572 | |||
573 | ret = lrw_crypt(desc, dst, src, nbytes, &req); | ||
574 | serpent_fpu_end(crypt_ctx.fpu_enabled); | ||
575 | |||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | static void lrw_exit_tfm(struct crypto_tfm *tfm) | ||
580 | { | ||
581 | struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm); | ||
582 | |||
583 | lrw_free_table(&ctx->lrw_table); | ||
584 | } | ||
585 | |||
586 | static struct crypto_alg blk_lrw_alg = { | ||
587 | .cra_name = "__lrw-serpent-sse2", | ||
588 | .cra_driver_name = "__driver-lrw-serpent-sse2", | ||
589 | .cra_priority = 0, | ||
590 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
591 | .cra_blocksize = SERPENT_BLOCK_SIZE, | ||
592 | .cra_ctxsize = sizeof(struct serpent_lrw_ctx), | ||
593 | .cra_alignmask = 0, | ||
594 | .cra_type = &crypto_blkcipher_type, | ||
595 | .cra_module = THIS_MODULE, | ||
596 | .cra_list = LIST_HEAD_INIT(blk_lrw_alg.cra_list), | ||
597 | .cra_exit = lrw_exit_tfm, | ||
598 | .cra_u = { | ||
599 | .blkcipher = { | ||
600 | .min_keysize = SERPENT_MIN_KEY_SIZE + | ||
601 | SERPENT_BLOCK_SIZE, | ||
602 | .max_keysize = SERPENT_MAX_KEY_SIZE + | ||
603 | SERPENT_BLOCK_SIZE, | ||
604 | .ivsize = SERPENT_BLOCK_SIZE, | ||
605 | .setkey = lrw_serpent_setkey, | ||
606 | .encrypt = lrw_encrypt, | ||
607 | .decrypt = lrw_decrypt, | ||
608 | }, | ||
609 | }, | ||
610 | }; | ||
611 | |||
612 | #endif | ||
613 | |||
463 | static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, | 614 | static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, |
464 | unsigned int key_len) | 615 | unsigned int key_len) |
465 | { | 616 | { |
@@ -658,6 +809,48 @@ static struct crypto_alg ablk_ctr_alg = { | |||
658 | }, | 809 | }, |
659 | }; | 810 | }; |
660 | 811 | ||
812 | #ifdef HAS_LRW | ||
813 | |||
814 | static int ablk_lrw_init(struct crypto_tfm *tfm) | ||
815 | { | ||
816 | struct cryptd_ablkcipher *cryptd_tfm; | ||
817 | |||
818 | cryptd_tfm = cryptd_alloc_ablkcipher("__driver-lrw-serpent-sse2", 0, 0); | ||
819 | if (IS_ERR(cryptd_tfm)) | ||
820 | return PTR_ERR(cryptd_tfm); | ||
821 | ablk_init_common(tfm, cryptd_tfm); | ||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | static struct crypto_alg ablk_lrw_alg = { | ||
826 | .cra_name = "lrw(serpent)", | ||
827 | .cra_driver_name = "lrw-serpent-sse2", | ||
828 | .cra_priority = 400, | ||
829 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
830 | .cra_blocksize = SERPENT_BLOCK_SIZE, | ||
831 | .cra_ctxsize = sizeof(struct async_serpent_ctx), | ||
832 | .cra_alignmask = 0, | ||
833 | .cra_type = &crypto_ablkcipher_type, | ||
834 | .cra_module = THIS_MODULE, | ||
835 | .cra_list = LIST_HEAD_INIT(ablk_lrw_alg.cra_list), | ||
836 | .cra_init = ablk_lrw_init, | ||
837 | .cra_exit = ablk_exit, | ||
838 | .cra_u = { | ||
839 | .ablkcipher = { | ||
840 | .min_keysize = SERPENT_MIN_KEY_SIZE + | ||
841 | SERPENT_BLOCK_SIZE, | ||
842 | .max_keysize = SERPENT_MAX_KEY_SIZE + | ||
843 | SERPENT_BLOCK_SIZE, | ||
844 | .ivsize = SERPENT_BLOCK_SIZE, | ||
845 | .setkey = ablk_set_key, | ||
846 | .encrypt = ablk_encrypt, | ||
847 | .decrypt = ablk_decrypt, | ||
848 | }, | ||
849 | }, | ||
850 | }; | ||
851 | |||
852 | #endif | ||
853 | |||
661 | static int __init serpent_sse2_init(void) | 854 | static int __init serpent_sse2_init(void) |
662 | { | 855 | { |
663 | int err; | 856 | int err; |
@@ -685,8 +878,22 @@ static int __init serpent_sse2_init(void) | |||
685 | err = crypto_register_alg(&ablk_ctr_alg); | 878 | err = crypto_register_alg(&ablk_ctr_alg); |
686 | if (err) | 879 | if (err) |
687 | goto ablk_ctr_err; | 880 | goto ablk_ctr_err; |
881 | #ifdef HAS_LRW | ||
882 | err = crypto_register_alg(&blk_lrw_alg); | ||
883 | if (err) | ||
884 | goto blk_lrw_err; | ||
885 | err = crypto_register_alg(&ablk_lrw_alg); | ||
886 | if (err) | ||
887 | goto ablk_lrw_err; | ||
888 | #endif | ||
688 | return err; | 889 | return err; |
689 | 890 | ||
891 | #ifdef HAS_LRW | ||
892 | ablk_lrw_err: | ||
893 | crypto_unregister_alg(&blk_lrw_alg); | ||
894 | blk_lrw_err: | ||
895 | crypto_unregister_alg(&ablk_ctr_alg); | ||
896 | #endif | ||
690 | ablk_ctr_err: | 897 | ablk_ctr_err: |
691 | crypto_unregister_alg(&ablk_cbc_alg); | 898 | crypto_unregister_alg(&ablk_cbc_alg); |
692 | ablk_cbc_err: | 899 | ablk_cbc_err: |
@@ -703,6 +910,10 @@ blk_ecb_err: | |||
703 | 910 | ||
704 | static void __exit serpent_sse2_exit(void) | 911 | static void __exit serpent_sse2_exit(void) |
705 | { | 912 | { |
913 | #ifdef HAS_LRW | ||
914 | crypto_unregister_alg(&ablk_lrw_alg); | ||
915 | crypto_unregister_alg(&blk_lrw_alg); | ||
916 | #endif | ||
706 | crypto_unregister_alg(&ablk_ctr_alg); | 917 | crypto_unregister_alg(&ablk_ctr_alg); |
707 | crypto_unregister_alg(&ablk_cbc_alg); | 918 | crypto_unregister_alg(&ablk_cbc_alg); |
708 | crypto_unregister_alg(&ablk_ecb_alg); | 919 | crypto_unregister_alg(&ablk_ecb_alg); |
diff --git a/crypto/serpent.c b/crypto/serpent.c index eb6163041b08..7cc2caeb88a5 100644 --- a/crypto/serpent.c +++ b/crypto/serpent.c | |||
@@ -206,9 +206,9 @@ | |||
206 | x1 ^= x4; x3 ^= x4; x4 &= x0; \ | 206 | x1 ^= x4; x3 ^= x4; x4 &= x0; \ |
207 | x4 ^= x2; | 207 | x4 ^= x2; |
208 | 208 | ||
209 | int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | 209 | int __serpent_setkey(struct serpent_ctx *ctx, const u8 *key, |
210 | unsigned int keylen) | ||
210 | { | 211 | { |
211 | struct serpent_ctx *ctx = crypto_tfm_ctx(tfm); | ||
212 | u32 *k = ctx->expkey; | 212 | u32 *k = ctx->expkey; |
213 | u8 *k8 = (u8 *)k; | 213 | u8 *k8 = (u8 *)k; |
214 | u32 r0,r1,r2,r3,r4; | 214 | u32 r0,r1,r2,r3,r4; |
@@ -349,6 +349,12 @@ int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | |||
349 | 349 | ||
350 | return 0; | 350 | return 0; |
351 | } | 351 | } |
352 | EXPORT_SYMBOL_GPL(__serpent_setkey); | ||
353 | |||
354 | int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | ||
355 | { | ||
356 | return __serpent_setkey(crypto_tfm_ctx(tfm), key, keylen); | ||
357 | } | ||
352 | EXPORT_SYMBOL_GPL(serpent_setkey); | 358 | EXPORT_SYMBOL_GPL(serpent_setkey); |
353 | 359 | ||
354 | void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src) | 360 | void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src) |
diff --git a/include/crypto/serpent.h b/include/crypto/serpent.h index 40df885f9d1f..b7e0941eb6fc 100644 --- a/include/crypto/serpent.h +++ b/include/crypto/serpent.h | |||
@@ -17,6 +17,8 @@ struct serpent_ctx { | |||
17 | u32 expkey[SERPENT_EXPKEY_WORDS]; | 17 | u32 expkey[SERPENT_EXPKEY_WORDS]; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | int __serpent_setkey(struct serpent_ctx *ctx, const u8 *key, | ||
21 | unsigned int keylen); | ||
20 | int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen); | 22 | int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen); |
21 | 23 | ||
22 | void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src); | 24 | void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src); |