sha256-glue.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Linux/arm64 port of the OpenSSL SHA256 implementation for AArch64
  3. *
  4. * Copyright (c) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 2 of the License, or (at your option)
  9. * any later version.
  10. *
  11. */
  12. #include <asm/hwcap.h>
  13. #include <asm/neon.h>
  14. #include <asm/simd.h>
  15. #include <crypto/internal/hash.h>
  16. #include <crypto/sha.h>
  17. #include <crypto/sha256_base.h>
  18. #include <linux/cryptohash.h>
  19. #include <linux/types.h>
  20. #include <linux/string.h>
  21. MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash for arm64");
  22. MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
  23. MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
  24. MODULE_LICENSE("GPL v2");
  25. MODULE_ALIAS_CRYPTO("sha224");
  26. MODULE_ALIAS_CRYPTO("sha256");
  27. asmlinkage void sha256_block_data_order(u32 *digest, const void *data,
  28. unsigned int num_blks);
  29. asmlinkage void sha256_block_neon(u32 *digest, const void *data,
  30. unsigned int num_blks);
  31. static int sha256_update(struct shash_desc *desc, const u8 *data,
  32. unsigned int len)
  33. {
  34. return sha256_base_do_update(desc, data, len,
  35. (sha256_block_fn *)sha256_block_data_order);
  36. }
  37. static int sha256_finup(struct shash_desc *desc, const u8 *data,
  38. unsigned int len, u8 *out)
  39. {
  40. if (len)
  41. sha256_base_do_update(desc, data, len,
  42. (sha256_block_fn *)sha256_block_data_order);
  43. sha256_base_do_finalize(desc,
  44. (sha256_block_fn *)sha256_block_data_order);
  45. return sha256_base_finish(desc, out);
  46. }
  47. static int sha256_final(struct shash_desc *desc, u8 *out)
  48. {
  49. return sha256_finup(desc, NULL, 0, out);
  50. }
  51. static struct shash_alg algs[] = { {
  52. .digestsize = SHA256_DIGEST_SIZE,
  53. .init = sha256_base_init,
  54. .update = sha256_update,
  55. .final = sha256_final,
  56. .finup = sha256_finup,
  57. .descsize = sizeof(struct sha256_state),
  58. .base.cra_name = "sha256",
  59. .base.cra_driver_name = "sha256-arm64",
  60. .base.cra_priority = 100,
  61. .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
  62. .base.cra_blocksize = SHA256_BLOCK_SIZE,
  63. .base.cra_module = THIS_MODULE,
  64. }, {
  65. .digestsize = SHA224_DIGEST_SIZE,
  66. .init = sha224_base_init,
  67. .update = sha256_update,
  68. .final = sha256_final,
  69. .finup = sha256_finup,
  70. .descsize = sizeof(struct sha256_state),
  71. .base.cra_name = "sha224",
  72. .base.cra_driver_name = "sha224-arm64",
  73. .base.cra_priority = 100,
  74. .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
  75. .base.cra_blocksize = SHA224_BLOCK_SIZE,
  76. .base.cra_module = THIS_MODULE,
  77. } };
  78. static int sha256_update_neon(struct shash_desc *desc, const u8 *data,
  79. unsigned int len)
  80. {
  81. /*
  82. * Stacking and unstacking a substantial slice of the NEON register
  83. * file may significantly affect performance for small updates when
  84. * executing in interrupt context, so fall back to the scalar code
  85. * in that case.
  86. */
  87. if (!may_use_simd())
  88. return sha256_base_do_update(desc, data, len,
  89. (sha256_block_fn *)sha256_block_data_order);
  90. kernel_neon_begin();
  91. sha256_base_do_update(desc, data, len,
  92. (sha256_block_fn *)sha256_block_neon);
  93. kernel_neon_end();
  94. return 0;
  95. }
  96. static int sha256_finup_neon(struct shash_desc *desc, const u8 *data,
  97. unsigned int len, u8 *out)
  98. {
  99. if (!may_use_simd()) {
  100. if (len)
  101. sha256_base_do_update(desc, data, len,
  102. (sha256_block_fn *)sha256_block_data_order);
  103. sha256_base_do_finalize(desc,
  104. (sha256_block_fn *)sha256_block_data_order);
  105. } else {
  106. kernel_neon_begin();
  107. if (len)
  108. sha256_base_do_update(desc, data, len,
  109. (sha256_block_fn *)sha256_block_neon);
  110. sha256_base_do_finalize(desc,
  111. (sha256_block_fn *)sha256_block_neon);
  112. kernel_neon_end();
  113. }
  114. return sha256_base_finish(desc, out);
  115. }
  116. static int sha256_final_neon(struct shash_desc *desc, u8 *out)
  117. {
  118. return sha256_finup_neon(desc, NULL, 0, out);
  119. }
  120. static struct shash_alg neon_algs[] = { {
  121. .digestsize = SHA256_DIGEST_SIZE,
  122. .init = sha256_base_init,
  123. .update = sha256_update_neon,
  124. .final = sha256_final_neon,
  125. .finup = sha256_finup_neon,
  126. .descsize = sizeof(struct sha256_state),
  127. .base.cra_name = "sha256",
  128. .base.cra_driver_name = "sha256-arm64-neon",
  129. .base.cra_priority = 150,
  130. .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
  131. .base.cra_blocksize = SHA256_BLOCK_SIZE,
  132. .base.cra_module = THIS_MODULE,
  133. }, {
  134. .digestsize = SHA224_DIGEST_SIZE,
  135. .init = sha224_base_init,
  136. .update = sha256_update_neon,
  137. .final = sha256_final_neon,
  138. .finup = sha256_finup_neon,
  139. .descsize = sizeof(struct sha256_state),
  140. .base.cra_name = "sha224",
  141. .base.cra_driver_name = "sha224-arm64-neon",
  142. .base.cra_priority = 150,
  143. .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
  144. .base.cra_blocksize = SHA224_BLOCK_SIZE,
  145. .base.cra_module = THIS_MODULE,
  146. } };
  147. static int __init sha256_mod_init(void)
  148. {
  149. int ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
  150. if (ret)
  151. return ret;
  152. if (elf_hwcap & HWCAP_ASIMD) {
  153. ret = crypto_register_shashes(neon_algs, ARRAY_SIZE(neon_algs));
  154. if (ret)
  155. crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
  156. }
  157. return ret;
  158. }
  159. static void __exit sha256_mod_fini(void)
  160. {
  161. if (elf_hwcap & HWCAP_ASIMD)
  162. crypto_unregister_shashes(neon_algs, ARRAY_SIZE(neon_algs));
  163. crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
  164. }
  165. module_init(sha256_mod_init);
  166. module_exit(sha256_mod_fini);