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 /arch/x86/crypto/serpent_sse2_glue.c | |
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>
Diffstat (limited to 'arch/x86/crypto/serpent_sse2_glue.c')
-rw-r--r-- | arch/x86/crypto/serpent_sse2_glue.c | 211 |
1 files changed, 211 insertions, 0 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); |