aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2011-11-09 09:26:41 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2011-11-21 03:13:24 -0500
commit5962f8b66dd040ad89d55b58967ea2dec607f4d3 (patch)
treecad506028aa0a54facdb68cc500d4ab4eb62305a /arch/x86
parent18482053f92b099663bd36a10e8f6bd2c8544669 (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')
-rw-r--r--arch/x86/crypto/serpent_sse2_glue.c180
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
53struct async_serpent_ctx { 58struct 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
470struct crypt_priv { 475struct 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
509struct serpent_lrw_ctx { 518struct 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
625struct serpent_xts_ctx {
626 struct serpent_ctx tweak_ctx;
627 struct serpent_ctx crypt_ctx;
628};
629
630static 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
654static 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
680static 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
706static 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
614static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, 731static 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
973static 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
984static 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
854static int __init serpent_sse2_init(void) 1011static 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);
1058ablk_xts_err:
1059 crypto_unregister_alg(&blk_xts_alg);
1060blk_xts_err:
1061#endif
891#ifdef HAS_LRW 1062#ifdef HAS_LRW
1063 crypto_unregister_alg(&ablk_lrw_alg);
892ablk_lrw_err: 1064ablk_lrw_err:
893 crypto_unregister_alg(&blk_lrw_alg); 1065 crypto_unregister_alg(&blk_lrw_alg);
894blk_lrw_err: 1066blk_lrw_err:
895 crypto_unregister_alg(&ablk_ctr_alg);
896#endif 1067#endif
1068 crypto_unregister_alg(&ablk_ctr_alg);
897ablk_ctr_err: 1069ablk_ctr_err:
898 crypto_unregister_alg(&ablk_cbc_alg); 1070 crypto_unregister_alg(&ablk_cbc_alg);
899ablk_cbc_err: 1071ablk_cbc_err:
@@ -910,6 +1082,10 @@ blk_ecb_err:
910 1082
911static void __exit serpent_sse2_exit(void) 1083static 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);