diff options
author | Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 2011-11-09 09:26:41 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2011-11-21 03:13:24 -0500 |
commit | 5962f8b66dd040ad89d55b58967ea2dec607f4d3 (patch) | |
tree | cad506028aa0a54facdb68cc500d4ab4eb62305a /arch/x86/crypto | |
parent | 18482053f92b099663bd36a10e8f6bd2c8544669 (diff) |
crypto: serpent-sse2 - add xts support
Patch adds XTS support for serpent-sse2 by using xts_crypt(). Patch has been
tested with tcrypt and automated filesystem tests.
Tcrypt benchmarks results (serpent-sse2/serpent_generic speed ratios):
Intel Celeron T1600 (x86_64) (fam:6, model:15, step:13):
size xts-enc xts-dec
16B 0.98x 1.00x
64B 1.00x 1.01x
256B 2.78x 2.75x
1024B 3.30x 3.26x
8192B 3.39x 3.30x
AMD Phenom II 1055T (x86_64) (fam:16, model:10):
size xts-enc xts-dec
16B 1.05x 1.02x
64B 1.04x 1.03x
256B 2.10x 2.05x
1024B 2.34x 2.35x
8192B 2.34x 2.40x
Intel Atom N270 (i586):
size xts-enc xts-dec
16B 0.95x 0.96x
64B 1.53x 1.50x
256B 1.72x 1.75x
1024B 1.88x 1.87x
8192B 1.86x 1.83x
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')
-rw-r--r-- | arch/x86/crypto/serpent_sse2_glue.c | 180 |
1 files changed, 178 insertions, 2 deletions
diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c index db318e5cb240..2dffc5ab883e 100644 --- a/arch/x86/crypto/serpent_sse2_glue.c +++ b/arch/x86/crypto/serpent_sse2_glue.c | |||
@@ -40,6 +40,7 @@ | |||
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 <crypto/lrw.h> |
43 | #include <crypto/xts.h> | ||
43 | #include <asm/i387.h> | 44 | #include <asm/i387.h> |
44 | #include <asm/serpent.h> | 45 | #include <asm/serpent.h> |
45 | #include <crypto/scatterwalk.h> | 46 | #include <crypto/scatterwalk.h> |
@@ -50,6 +51,10 @@ | |||
50 | #define HAS_LRW | 51 | #define HAS_LRW |
51 | #endif | 52 | #endif |
52 | 53 | ||
54 | #if defined(CONFIG_CRYPTO_XTS) || defined(CONFIG_CRYPTO_XTS_MODULE) | ||
55 | #define HAS_XTS | ||
56 | #endif | ||
57 | |||
53 | struct async_serpent_ctx { | 58 | struct async_serpent_ctx { |
54 | struct cryptd_ablkcipher *cryptd_tfm; | 59 | struct cryptd_ablkcipher *cryptd_tfm; |
55 | }; | 60 | }; |
@@ -465,7 +470,7 @@ static struct crypto_alg blk_ctr_alg = { | |||
465 | }, | 470 | }, |
466 | }; | 471 | }; |
467 | 472 | ||
468 | #ifdef HAS_LRW | 473 | #if defined(HAS_LRW) || defined(HAS_XTS) |
469 | 474 | ||
470 | struct crypt_priv { | 475 | struct crypt_priv { |
471 | struct serpent_ctx *ctx; | 476 | struct serpent_ctx *ctx; |
@@ -506,6 +511,10 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) | |||
506 | __serpent_decrypt(ctx->ctx, srcdst, srcdst); | 511 | __serpent_decrypt(ctx->ctx, srcdst, srcdst); |
507 | } | 512 | } |
508 | 513 | ||
514 | #endif | ||
515 | |||
516 | #ifdef HAS_LRW | ||
517 | |||
509 | struct serpent_lrw_ctx { | 518 | struct serpent_lrw_ctx { |
510 | struct lrw_table_ctx lrw_table; | 519 | struct lrw_table_ctx lrw_table; |
511 | struct serpent_ctx serpent_ctx; | 520 | struct serpent_ctx serpent_ctx; |
@@ -611,6 +620,114 @@ static struct crypto_alg blk_lrw_alg = { | |||
611 | 620 | ||
612 | #endif | 621 | #endif |
613 | 622 | ||
623 | #ifdef HAS_XTS | ||
624 | |||
625 | struct serpent_xts_ctx { | ||
626 | struct serpent_ctx tweak_ctx; | ||
627 | struct serpent_ctx crypt_ctx; | ||
628 | }; | ||
629 | |||
630 | static int xts_serpent_setkey(struct crypto_tfm *tfm, const u8 *key, | ||
631 | unsigned int keylen) | ||
632 | { | ||
633 | struct serpent_xts_ctx *ctx = crypto_tfm_ctx(tfm); | ||
634 | u32 *flags = &tfm->crt_flags; | ||
635 | int err; | ||
636 | |||
637 | /* key consists of keys of equal size concatenated, therefore | ||
638 | * the length must be even | ||
639 | */ | ||
640 | if (keylen % 2) { | ||
641 | *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | ||
642 | return -EINVAL; | ||
643 | } | ||
644 | |||
645 | /* first half of xts-key is for crypt */ | ||
646 | err = __serpent_setkey(&ctx->crypt_ctx, key, keylen / 2); | ||
647 | if (err) | ||
648 | return err; | ||
649 | |||
650 | /* second half of xts-key is for tweak */ | ||
651 | return __serpent_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2); | ||
652 | } | ||
653 | |||
654 | static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
655 | struct scatterlist *src, unsigned int nbytes) | ||
656 | { | ||
657 | struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
658 | be128 buf[SERPENT_PARALLEL_BLOCKS]; | ||
659 | struct crypt_priv crypt_ctx = { | ||
660 | .ctx = &ctx->crypt_ctx, | ||
661 | .fpu_enabled = false, | ||
662 | }; | ||
663 | struct xts_crypt_req req = { | ||
664 | .tbuf = buf, | ||
665 | .tbuflen = sizeof(buf), | ||
666 | |||
667 | .tweak_ctx = &ctx->tweak_ctx, | ||
668 | .tweak_fn = XTS_TWEAK_CAST(__serpent_encrypt), | ||
669 | .crypt_ctx = &crypt_ctx, | ||
670 | .crypt_fn = encrypt_callback, | ||
671 | }; | ||
672 | int ret; | ||
673 | |||
674 | ret = xts_crypt(desc, dst, src, nbytes, &req); | ||
675 | serpent_fpu_end(crypt_ctx.fpu_enabled); | ||
676 | |||
677 | return ret; | ||
678 | } | ||
679 | |||
680 | static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
681 | struct scatterlist *src, unsigned int nbytes) | ||
682 | { | ||
683 | struct serpent_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
684 | be128 buf[SERPENT_PARALLEL_BLOCKS]; | ||
685 | struct crypt_priv crypt_ctx = { | ||
686 | .ctx = &ctx->crypt_ctx, | ||
687 | .fpu_enabled = false, | ||
688 | }; | ||
689 | struct xts_crypt_req req = { | ||
690 | .tbuf = buf, | ||
691 | .tbuflen = sizeof(buf), | ||
692 | |||
693 | .tweak_ctx = &ctx->tweak_ctx, | ||
694 | .tweak_fn = XTS_TWEAK_CAST(__serpent_encrypt), | ||
695 | .crypt_ctx = &crypt_ctx, | ||
696 | .crypt_fn = decrypt_callback, | ||
697 | }; | ||
698 | int ret; | ||
699 | |||
700 | ret = xts_crypt(desc, dst, src, nbytes, &req); | ||
701 | serpent_fpu_end(crypt_ctx.fpu_enabled); | ||
702 | |||
703 | return ret; | ||
704 | } | ||
705 | |||
706 | static struct crypto_alg blk_xts_alg = { | ||
707 | .cra_name = "__xts-serpent-sse2", | ||
708 | .cra_driver_name = "__driver-xts-serpent-sse2", | ||
709 | .cra_priority = 0, | ||
710 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
711 | .cra_blocksize = SERPENT_BLOCK_SIZE, | ||
712 | .cra_ctxsize = sizeof(struct serpent_xts_ctx), | ||
713 | .cra_alignmask = 0, | ||
714 | .cra_type = &crypto_blkcipher_type, | ||
715 | .cra_module = THIS_MODULE, | ||
716 | .cra_list = LIST_HEAD_INIT(blk_xts_alg.cra_list), | ||
717 | .cra_u = { | ||
718 | .blkcipher = { | ||
719 | .min_keysize = SERPENT_MIN_KEY_SIZE * 2, | ||
720 | .max_keysize = SERPENT_MAX_KEY_SIZE * 2, | ||
721 | .ivsize = SERPENT_BLOCK_SIZE, | ||
722 | .setkey = xts_serpent_setkey, | ||
723 | .encrypt = xts_encrypt, | ||
724 | .decrypt = xts_decrypt, | ||
725 | }, | ||
726 | }, | ||
727 | }; | ||
728 | |||
729 | #endif | ||
730 | |||
614 | static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, | 731 | static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, |
615 | unsigned int key_len) | 732 | unsigned int key_len) |
616 | { | 733 | { |
@@ -851,6 +968,46 @@ static struct crypto_alg ablk_lrw_alg = { | |||
851 | 968 | ||
852 | #endif | 969 | #endif |
853 | 970 | ||
971 | #ifdef HAS_XTS | ||
972 | |||
973 | static int ablk_xts_init(struct crypto_tfm *tfm) | ||
974 | { | ||
975 | struct cryptd_ablkcipher *cryptd_tfm; | ||
976 | |||
977 | cryptd_tfm = cryptd_alloc_ablkcipher("__driver-xts-serpent-sse2", 0, 0); | ||
978 | if (IS_ERR(cryptd_tfm)) | ||
979 | return PTR_ERR(cryptd_tfm); | ||
980 | ablk_init_common(tfm, cryptd_tfm); | ||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | static struct crypto_alg ablk_xts_alg = { | ||
985 | .cra_name = "xts(serpent)", | ||
986 | .cra_driver_name = "xts-serpent-sse2", | ||
987 | .cra_priority = 400, | ||
988 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
989 | .cra_blocksize = SERPENT_BLOCK_SIZE, | ||
990 | .cra_ctxsize = sizeof(struct async_serpent_ctx), | ||
991 | .cra_alignmask = 0, | ||
992 | .cra_type = &crypto_ablkcipher_type, | ||
993 | .cra_module = THIS_MODULE, | ||
994 | .cra_list = LIST_HEAD_INIT(ablk_xts_alg.cra_list), | ||
995 | .cra_init = ablk_xts_init, | ||
996 | .cra_exit = ablk_exit, | ||
997 | .cra_u = { | ||
998 | .ablkcipher = { | ||
999 | .min_keysize = SERPENT_MIN_KEY_SIZE * 2, | ||
1000 | .max_keysize = SERPENT_MAX_KEY_SIZE * 2, | ||
1001 | .ivsize = SERPENT_BLOCK_SIZE, | ||
1002 | .setkey = ablk_set_key, | ||
1003 | .encrypt = ablk_encrypt, | ||
1004 | .decrypt = ablk_decrypt, | ||
1005 | }, | ||
1006 | }, | ||
1007 | }; | ||
1008 | |||
1009 | #endif | ||
1010 | |||
854 | static int __init serpent_sse2_init(void) | 1011 | static int __init serpent_sse2_init(void) |
855 | { | 1012 | { |
856 | int err; | 1013 | int err; |
@@ -886,14 +1043,29 @@ static int __init serpent_sse2_init(void) | |||
886 | if (err) | 1043 | if (err) |
887 | goto ablk_lrw_err; | 1044 | goto ablk_lrw_err; |
888 | #endif | 1045 | #endif |
1046 | #ifdef HAS_XTS | ||
1047 | err = crypto_register_alg(&blk_xts_alg); | ||
1048 | if (err) | ||
1049 | goto blk_xts_err; | ||
1050 | err = crypto_register_alg(&ablk_xts_alg); | ||
1051 | if (err) | ||
1052 | goto ablk_xts_err; | ||
1053 | #endif | ||
889 | return err; | 1054 | return err; |
890 | 1055 | ||
1056 | #ifdef HAS_XTS | ||
1057 | crypto_unregister_alg(&ablk_xts_alg); | ||
1058 | ablk_xts_err: | ||
1059 | crypto_unregister_alg(&blk_xts_alg); | ||
1060 | blk_xts_err: | ||
1061 | #endif | ||
891 | #ifdef HAS_LRW | 1062 | #ifdef HAS_LRW |
1063 | crypto_unregister_alg(&ablk_lrw_alg); | ||
892 | ablk_lrw_err: | 1064 | ablk_lrw_err: |
893 | crypto_unregister_alg(&blk_lrw_alg); | 1065 | crypto_unregister_alg(&blk_lrw_alg); |
894 | blk_lrw_err: | 1066 | blk_lrw_err: |
895 | crypto_unregister_alg(&ablk_ctr_alg); | ||
896 | #endif | 1067 | #endif |
1068 | crypto_unregister_alg(&ablk_ctr_alg); | ||
897 | ablk_ctr_err: | 1069 | ablk_ctr_err: |
898 | crypto_unregister_alg(&ablk_cbc_alg); | 1070 | crypto_unregister_alg(&ablk_cbc_alg); |
899 | ablk_cbc_err: | 1071 | ablk_cbc_err: |
@@ -910,6 +1082,10 @@ blk_ecb_err: | |||
910 | 1082 | ||
911 | static void __exit serpent_sse2_exit(void) | 1083 | static void __exit serpent_sse2_exit(void) |
912 | { | 1084 | { |
1085 | #ifdef HAS_XTS | ||
1086 | crypto_unregister_alg(&ablk_xts_alg); | ||
1087 | crypto_unregister_alg(&blk_xts_alg); | ||
1088 | #endif | ||
913 | #ifdef HAS_LRW | 1089 | #ifdef HAS_LRW |
914 | crypto_unregister_alg(&ablk_lrw_alg); | 1090 | crypto_unregister_alg(&ablk_lrw_alg); |
915 | crypto_unregister_alg(&blk_lrw_alg); | 1091 | crypto_unregister_alg(&blk_lrw_alg); |