Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: twofish-x86_64-3way - add lrw support

Patch adds LRW support for twofish-x86_64-3way by using lrw_crypt(). Patch has
been tested with tcrypt and automated filesystem tests.

Tcrypt benchmarks results (twofish-3way/twofish-asm speed ratios):

Intel Celeron T1600 (fam:6, model:15, step:13):

size lrw-enc lrw-dec
16B 0.99x 1.00x
64B 1.17x 1.17x
256B 1.26x 1.27x
1024B 1.30x 1.31x
8192B 1.31x 1.32x

AMD Phenom II 1055T (fam:16, model:10):

size lrw-enc lrw-dec
16B 1.06x 1.01x
64B 1.08x 1.14x
256B 1.19x 1.20x
1024B 1.21x 1.22x
8192B 1.23x 1.24x

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Jussi Kivilinna and committed by
Herbert Xu
81559f9a bee3a90e

+145 -5
+135
arch/x86/crypto/twofish_glue_3way.c
··· 32 32 #include <crypto/algapi.h> 33 33 #include <crypto/twofish.h> 34 34 #include <crypto/b128ops.h> 35 + #include <crypto/lrw.h> 36 + 37 + #if defined(CONFIG_CRYPTO_LRW) || defined(CONFIG_CRYPTO_LRW_MODULE) 38 + #define HAS_LRW 39 + #endif 35 40 36 41 /* regular block cipher functions from twofish_x86_64 module */ 37 42 asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst, ··· 437 432 }, 438 433 }; 439 434 435 + #ifdef HAS_LRW 436 + 437 + static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) 438 + { 439 + const unsigned int bsize = TF_BLOCK_SIZE; 440 + struct twofish_ctx *ctx = priv; 441 + int i; 442 + 443 + if (nbytes == 3 * bsize) { 444 + twofish_enc_blk_3way(ctx, srcdst, srcdst); 445 + return; 446 + } 447 + 448 + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) 449 + twofish_enc_blk(ctx, srcdst, srcdst); 450 + } 451 + 452 + static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) 453 + { 454 + const unsigned int bsize = TF_BLOCK_SIZE; 455 + struct twofish_ctx *ctx = priv; 456 + int i; 457 + 458 + if (nbytes == 3 * bsize) { 459 + twofish_dec_blk_3way(ctx, srcdst, srcdst); 460 + return; 461 + } 462 + 463 + for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) 464 + twofish_dec_blk(ctx, srcdst, srcdst); 465 + } 466 + 467 + struct twofish_lrw_ctx { 468 + struct lrw_table_ctx lrw_table; 469 + struct twofish_ctx twofish_ctx; 470 + }; 471 + 472 + static int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, 473 + unsigned int keylen) 474 + { 475 + struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); 476 + int err; 477 + 478 + err = __twofish_setkey(&ctx->twofish_ctx, key, keylen - TF_BLOCK_SIZE, 479 + &tfm->crt_flags); 480 + if (err) 481 + return err; 482 + 483 + return lrw_init_table(&ctx->lrw_table, key + keylen - TF_BLOCK_SIZE); 484 + } 485 + 486 + static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 487 + struct scatterlist *src, unsigned int nbytes) 488 + { 489 + struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 490 + be128 buf[3]; 491 + struct lrw_crypt_req req = { 492 + .tbuf = buf, 493 + .tbuflen = sizeof(buf), 494 + 495 + .table_ctx = &ctx->lrw_table, 496 + .crypt_ctx = &ctx->twofish_ctx, 497 + .crypt_fn = encrypt_callback, 498 + }; 499 + 500 + return lrw_crypt(desc, dst, src, nbytes, &req); 501 + } 502 + 503 + static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 504 + struct scatterlist *src, unsigned int nbytes) 505 + { 506 + struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 507 + be128 buf[3]; 508 + struct lrw_crypt_req req = { 509 + .tbuf = buf, 510 + .tbuflen = sizeof(buf), 511 + 512 + .table_ctx = &ctx->lrw_table, 513 + .crypt_ctx = &ctx->twofish_ctx, 514 + .crypt_fn = decrypt_callback, 515 + }; 516 + 517 + return lrw_crypt(desc, dst, src, nbytes, &req); 518 + } 519 + 520 + static void lrw_exit_tfm(struct crypto_tfm *tfm) 521 + { 522 + struct twofish_lrw_ctx *ctx = crypto_tfm_ctx(tfm); 523 + 524 + lrw_free_table(&ctx->lrw_table); 525 + } 526 + 527 + static struct crypto_alg blk_lrw_alg = { 528 + .cra_name = "lrw(twofish)", 529 + .cra_driver_name = "lrw-twofish-3way", 530 + .cra_priority = 300, 531 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 532 + .cra_blocksize = TF_BLOCK_SIZE, 533 + .cra_ctxsize = sizeof(struct twofish_lrw_ctx), 534 + .cra_alignmask = 0, 535 + .cra_type = &crypto_blkcipher_type, 536 + .cra_module = THIS_MODULE, 537 + .cra_list = LIST_HEAD_INIT(blk_lrw_alg.cra_list), 538 + .cra_exit = lrw_exit_tfm, 539 + .cra_u = { 540 + .blkcipher = { 541 + .min_keysize = TF_MIN_KEY_SIZE + TF_BLOCK_SIZE, 542 + .max_keysize = TF_MAX_KEY_SIZE + TF_BLOCK_SIZE, 543 + .ivsize = TF_BLOCK_SIZE, 544 + .setkey = lrw_twofish_setkey, 545 + .encrypt = lrw_encrypt, 546 + .decrypt = lrw_decrypt, 547 + }, 548 + }, 549 + }; 550 + 551 + #endif 552 + 440 553 int __init init(void) 441 554 { 442 555 int err; ··· 568 445 err = crypto_register_alg(&blk_ctr_alg); 569 446 if (err) 570 447 goto ctr_err; 448 + #ifdef HAS_LRW 449 + err = crypto_register_alg(&blk_lrw_alg); 450 + if (err) 451 + goto blk_lrw_err; 452 + #endif 571 453 572 454 return 0; 573 455 456 + #ifdef HAS_LRW 457 + blk_lrw_err: 458 + crypto_unregister_alg(&blk_ctr_alg); 459 + #endif 574 460 ctr_err: 575 461 crypto_unregister_alg(&blk_cbc_alg); 576 462 cbc_err: ··· 590 458 591 459 void __exit fini(void) 592 460 { 461 + #ifdef HAS_LRW 462 + crypto_unregister_alg(&blk_lrw_alg); 463 + #endif 593 464 crypto_unregister_alg(&blk_ctr_alg); 594 465 crypto_unregister_alg(&blk_cbc_alg); 595 466 crypto_unregister_alg(&blk_ecb_alg);
+8 -5
crypto/twofish_common.c
··· 580 580 ctx->a[(j) + 1] = rol32(y, 9) 581 581 582 582 /* Perform the key setup. */ 583 - int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len) 583 + int __twofish_setkey(struct twofish_ctx *ctx, const u8 *key, 584 + unsigned int key_len, u32 *flags) 584 585 { 585 - 586 - struct twofish_ctx *ctx = crypto_tfm_ctx(tfm); 587 - u32 *flags = &tfm->crt_flags; 588 - 589 586 int i, j, k; 590 587 591 588 /* Temporaries for CALC_K. */ ··· 698 701 699 702 return 0; 700 703 } 704 + EXPORT_SYMBOL_GPL(__twofish_setkey); 701 705 706 + int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len) 707 + { 708 + return __twofish_setkey(crypto_tfm_ctx(tfm), key, key_len, 709 + &tfm->crt_flags); 710 + } 702 711 EXPORT_SYMBOL_GPL(twofish_setkey); 703 712 704 713 MODULE_LICENSE("GPL");
+2
include/crypto/twofish.h
··· 17 17 u32 s[4][256], w[8], k[32]; 18 18 }; 19 19 20 + int __twofish_setkey(struct twofish_ctx *ctx, const u8 *key, 21 + unsigned int key_len, u32 *flags); 20 22 int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len); 21 23 22 24 #endif