aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2011-11-09 09:26:36 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2011-11-21 03:13:24 -0500
commit18482053f92b099663bd36a10e8f6bd2c8544669 (patch)
tree5747eb47b1b0ffa59d4ad5c2402021e3b4544a1f
parent251496dbfc1be38bc43b49651f3d33c02faccc47 (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.c211
-rw-r--r--crypto/serpent.c10
-rw-r--r--include/crypto/serpent.h2
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
48struct async_serpent_ctx { 53struct 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
470struct crypt_priv {
471 struct serpent_ctx *ctx;
472 bool fpu_enabled;
473};
474
475static 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
492static 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
509struct serpent_lrw_ctx {
510 struct lrw_table_ctx lrw_table;
511 struct serpent_ctx serpent_ctx;
512};
513
514static 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
529static 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
554static 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
579static 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
586static 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
463static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, 614static 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
814static 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
825static 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
661static int __init serpent_sse2_init(void) 854static 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
892ablk_lrw_err:
893 crypto_unregister_alg(&blk_lrw_alg);
894blk_lrw_err:
895 crypto_unregister_alg(&ablk_ctr_alg);
896#endif
690ablk_ctr_err: 897ablk_ctr_err:
691 crypto_unregister_alg(&ablk_cbc_alg); 898 crypto_unregister_alg(&ablk_cbc_alg);
692ablk_cbc_err: 899ablk_cbc_err:
@@ -703,6 +910,10 @@ blk_ecb_err:
703 910
704static void __exit serpent_sse2_exit(void) 911static 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
209int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) 209int __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}
352EXPORT_SYMBOL_GPL(__serpent_setkey);
353
354int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
355{
356 return __serpent_setkey(crypto_tfm_ctx(tfm), key, keylen);
357}
352EXPORT_SYMBOL_GPL(serpent_setkey); 358EXPORT_SYMBOL_GPL(serpent_setkey);
353 359
354void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src) 360void __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
20int __serpent_setkey(struct serpent_ctx *ctx, const u8 *key,
21 unsigned int keylen);
20int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen); 22int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen);
21 23
22void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src); 24void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src);