0001
0002
0003
0004
0005
0006
0007
0008 #include <crypto/internal/hash.h>
0009 #include <crypto/internal/simd.h>
0010 #include <crypto/sha1.h>
0011 #include <crypto/sha1_base.h>
0012 #include <linux/cpufeature.h>
0013 #include <linux/crypto.h>
0014 #include <linux/module.h>
0015
0016 #include <asm/hwcap.h>
0017 #include <asm/neon.h>
0018 #include <asm/simd.h>
0019
0020 #include "sha1.h"
0021
0022 MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
0023 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
0024 MODULE_LICENSE("GPL v2");
0025
0026 asmlinkage void sha1_ce_transform(struct sha1_state *sst, u8 const *src,
0027 int blocks);
0028
0029 static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
0030 unsigned int len)
0031 {
0032 struct sha1_state *sctx = shash_desc_ctx(desc);
0033
0034 if (!crypto_simd_usable() ||
0035 (sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE)
0036 return sha1_update_arm(desc, data, len);
0037
0038 kernel_neon_begin();
0039 sha1_base_do_update(desc, data, len, sha1_ce_transform);
0040 kernel_neon_end();
0041
0042 return 0;
0043 }
0044
0045 static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
0046 unsigned int len, u8 *out)
0047 {
0048 if (!crypto_simd_usable())
0049 return sha1_finup_arm(desc, data, len, out);
0050
0051 kernel_neon_begin();
0052 if (len)
0053 sha1_base_do_update(desc, data, len, sha1_ce_transform);
0054 sha1_base_do_finalize(desc, sha1_ce_transform);
0055 kernel_neon_end();
0056
0057 return sha1_base_finish(desc, out);
0058 }
0059
0060 static int sha1_ce_final(struct shash_desc *desc, u8 *out)
0061 {
0062 return sha1_ce_finup(desc, NULL, 0, out);
0063 }
0064
0065 static struct shash_alg alg = {
0066 .init = sha1_base_init,
0067 .update = sha1_ce_update,
0068 .final = sha1_ce_final,
0069 .finup = sha1_ce_finup,
0070 .descsize = sizeof(struct sha1_state),
0071 .digestsize = SHA1_DIGEST_SIZE,
0072 .base = {
0073 .cra_name = "sha1",
0074 .cra_driver_name = "sha1-ce",
0075 .cra_priority = 200,
0076 .cra_blocksize = SHA1_BLOCK_SIZE,
0077 .cra_module = THIS_MODULE,
0078 }
0079 };
0080
0081 static int __init sha1_ce_mod_init(void)
0082 {
0083 return crypto_register_shash(&alg);
0084 }
0085
0086 static void __exit sha1_ce_mod_fini(void)
0087 {
0088 crypto_unregister_shash(&alg);
0089 }
0090
0091 module_cpu_feature_match(SHA1, sha1_ce_mod_init);
0092 module_exit(sha1_ce_mod_fini);