twofish_glue_3way.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Glue Code for 3-way parallel assembler optimized version of Twofish
  4. *
  5. * Copyright (c) 2011 Jussi Kivilinna <[email protected]>
  6. */
  7. #include <crypto/algapi.h>
  8. #include <crypto/twofish.h>
  9. #include <linux/crypto.h>
  10. #include <linux/init.h>
  11. #include <linux/module.h>
  12. #include <linux/types.h>
  13. #include "twofish.h"
  14. #include "ecb_cbc_helpers.h"
  15. EXPORT_SYMBOL_GPL(__twofish_enc_blk_3way);
  16. EXPORT_SYMBOL_GPL(twofish_dec_blk_3way);
  17. static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
  18. const u8 *key, unsigned int keylen)
  19. {
  20. return twofish_setkey(&tfm->base, key, keylen);
  21. }
  22. static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
  23. {
  24. __twofish_enc_blk_3way(ctx, dst, src, false);
  25. }
  26. void twofish_dec_blk_cbc_3way(const void *ctx, u8 *dst, const u8 *src)
  27. {
  28. u8 buf[2][TF_BLOCK_SIZE];
  29. const u8 *s = src;
  30. if (dst == src)
  31. s = memcpy(buf, src, sizeof(buf));
  32. twofish_dec_blk_3way(ctx, dst, src);
  33. crypto_xor(dst + TF_BLOCK_SIZE, s, sizeof(buf));
  34. }
  35. EXPORT_SYMBOL_GPL(twofish_dec_blk_cbc_3way);
  36. static int ecb_encrypt(struct skcipher_request *req)
  37. {
  38. ECB_WALK_START(req, TF_BLOCK_SIZE, -1);
  39. ECB_BLOCK(3, twofish_enc_blk_3way);
  40. ECB_BLOCK(1, twofish_enc_blk);
  41. ECB_WALK_END();
  42. }
  43. static int ecb_decrypt(struct skcipher_request *req)
  44. {
  45. ECB_WALK_START(req, TF_BLOCK_SIZE, -1);
  46. ECB_BLOCK(3, twofish_dec_blk_3way);
  47. ECB_BLOCK(1, twofish_dec_blk);
  48. ECB_WALK_END();
  49. }
  50. static int cbc_encrypt(struct skcipher_request *req)
  51. {
  52. CBC_WALK_START(req, TF_BLOCK_SIZE, -1);
  53. CBC_ENC_BLOCK(twofish_enc_blk);
  54. CBC_WALK_END();
  55. }
  56. static int cbc_decrypt(struct skcipher_request *req)
  57. {
  58. CBC_WALK_START(req, TF_BLOCK_SIZE, -1);
  59. CBC_DEC_BLOCK(3, twofish_dec_blk_cbc_3way);
  60. CBC_DEC_BLOCK(1, twofish_dec_blk);
  61. CBC_WALK_END();
  62. }
  63. static struct skcipher_alg tf_skciphers[] = {
  64. {
  65. .base.cra_name = "ecb(twofish)",
  66. .base.cra_driver_name = "ecb-twofish-3way",
  67. .base.cra_priority = 300,
  68. .base.cra_blocksize = TF_BLOCK_SIZE,
  69. .base.cra_ctxsize = sizeof(struct twofish_ctx),
  70. .base.cra_module = THIS_MODULE,
  71. .min_keysize = TF_MIN_KEY_SIZE,
  72. .max_keysize = TF_MAX_KEY_SIZE,
  73. .setkey = twofish_setkey_skcipher,
  74. .encrypt = ecb_encrypt,
  75. .decrypt = ecb_decrypt,
  76. }, {
  77. .base.cra_name = "cbc(twofish)",
  78. .base.cra_driver_name = "cbc-twofish-3way",
  79. .base.cra_priority = 300,
  80. .base.cra_blocksize = TF_BLOCK_SIZE,
  81. .base.cra_ctxsize = sizeof(struct twofish_ctx),
  82. .base.cra_module = THIS_MODULE,
  83. .min_keysize = TF_MIN_KEY_SIZE,
  84. .max_keysize = TF_MAX_KEY_SIZE,
  85. .ivsize = TF_BLOCK_SIZE,
  86. .setkey = twofish_setkey_skcipher,
  87. .encrypt = cbc_encrypt,
  88. .decrypt = cbc_decrypt,
  89. },
  90. };
  91. static bool is_blacklisted_cpu(void)
  92. {
  93. if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
  94. return false;
  95. if (boot_cpu_data.x86 == 0x06 &&
  96. (boot_cpu_data.x86_model == 0x1c ||
  97. boot_cpu_data.x86_model == 0x26 ||
  98. boot_cpu_data.x86_model == 0x36)) {
  99. /*
  100. * On Atom, twofish-3way is slower than original assembler
  101. * implementation. Twofish-3way trades off some performance in
  102. * storing blocks in 64bit registers to allow three blocks to
  103. * be processed parallel. Parallel operation then allows gaining
  104. * more performance than was trade off, on out-of-order CPUs.
  105. * However Atom does not benefit from this parallelism and
  106. * should be blacklisted.
  107. */
  108. return true;
  109. }
  110. if (boot_cpu_data.x86 == 0x0f) {
  111. /*
  112. * On Pentium 4, twofish-3way is slower than original assembler
  113. * implementation because excessive uses of 64bit rotate and
  114. * left-shifts (which are really slow on P4) needed to store and
  115. * handle 128bit block in two 64bit registers.
  116. */
  117. return true;
  118. }
  119. return false;
  120. }
  121. static int force;
  122. module_param(force, int, 0);
  123. MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
  124. static int __init twofish_3way_init(void)
  125. {
  126. if (!force && is_blacklisted_cpu()) {
  127. printk(KERN_INFO
  128. "twofish-x86_64-3way: performance on this CPU "
  129. "would be suboptimal: disabling "
  130. "twofish-x86_64-3way.\n");
  131. return -ENODEV;
  132. }
  133. return crypto_register_skciphers(tf_skciphers,
  134. ARRAY_SIZE(tf_skciphers));
  135. }
  136. static void __exit twofish_3way_fini(void)
  137. {
  138. crypto_unregister_skciphers(tf_skciphers, ARRAY_SIZE(tf_skciphers));
  139. }
  140. module_init(twofish_3way_init);
  141. module_exit(twofish_3way_fini);
  142. MODULE_LICENSE("GPL");
  143. MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized");
  144. MODULE_ALIAS_CRYPTO("twofish");
  145. MODULE_ALIAS_CRYPTO("twofish-asm");