0001
0002
0003
0004
0005
0006
0007
0008 #include <asm/neon.h>
0009 #include <asm/simd.h>
0010 #include <asm/unaligned.h>
0011 #include <crypto/internal/hash.h>
0012 #include <crypto/internal/simd.h>
0013 #include <crypto/sha1.h>
0014 #include <crypto/sha1_base.h>
0015 #include <linux/cpufeature.h>
0016 #include <linux/crypto.h>
0017 #include <linux/module.h>
0018
0019 MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
0020 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
0021 MODULE_LICENSE("GPL v2");
0022 MODULE_ALIAS_CRYPTO("sha1");
0023
0024 struct sha1_ce_state {
0025 struct sha1_state sst;
0026 u32 finalize;
0027 };
0028
0029 extern const u32 sha1_ce_offsetof_count;
0030 extern const u32 sha1_ce_offsetof_finalize;
0031
0032 asmlinkage int sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src,
0033 int blocks);
0034
0035 static void __sha1_ce_transform(struct sha1_state *sst, u8 const *src,
0036 int blocks)
0037 {
0038 while (blocks) {
0039 int rem;
0040
0041 kernel_neon_begin();
0042 rem = sha1_ce_transform(container_of(sst, struct sha1_ce_state,
0043 sst), src, blocks);
0044 kernel_neon_end();
0045 src += (blocks - rem) * SHA1_BLOCK_SIZE;
0046 blocks = rem;
0047 }
0048 }
0049
0050 const u32 sha1_ce_offsetof_count = offsetof(struct sha1_ce_state, sst.count);
0051 const u32 sha1_ce_offsetof_finalize = offsetof(struct sha1_ce_state, finalize);
0052
0053 static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
0054 unsigned int len)
0055 {
0056 struct sha1_ce_state *sctx = shash_desc_ctx(desc);
0057
0058 if (!crypto_simd_usable())
0059 return crypto_sha1_update(desc, data, len);
0060
0061 sctx->finalize = 0;
0062 sha1_base_do_update(desc, data, len, __sha1_ce_transform);
0063
0064 return 0;
0065 }
0066
0067 static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
0068 unsigned int len, u8 *out)
0069 {
0070 struct sha1_ce_state *sctx = shash_desc_ctx(desc);
0071 bool finalize = !sctx->sst.count && !(len % SHA1_BLOCK_SIZE) && len;
0072
0073 if (!crypto_simd_usable())
0074 return crypto_sha1_finup(desc, data, len, out);
0075
0076
0077
0078
0079
0080 sctx->finalize = finalize;
0081
0082 sha1_base_do_update(desc, data, len, __sha1_ce_transform);
0083 if (!finalize)
0084 sha1_base_do_finalize(desc, __sha1_ce_transform);
0085 return sha1_base_finish(desc, out);
0086 }
0087
0088 static int sha1_ce_final(struct shash_desc *desc, u8 *out)
0089 {
0090 struct sha1_ce_state *sctx = shash_desc_ctx(desc);
0091
0092 if (!crypto_simd_usable())
0093 return crypto_sha1_finup(desc, NULL, 0, out);
0094
0095 sctx->finalize = 0;
0096 sha1_base_do_finalize(desc, __sha1_ce_transform);
0097 return sha1_base_finish(desc, out);
0098 }
0099
0100 static int sha1_ce_export(struct shash_desc *desc, void *out)
0101 {
0102 struct sha1_ce_state *sctx = shash_desc_ctx(desc);
0103
0104 memcpy(out, &sctx->sst, sizeof(struct sha1_state));
0105 return 0;
0106 }
0107
0108 static int sha1_ce_import(struct shash_desc *desc, const void *in)
0109 {
0110 struct sha1_ce_state *sctx = shash_desc_ctx(desc);
0111
0112 memcpy(&sctx->sst, in, sizeof(struct sha1_state));
0113 sctx->finalize = 0;
0114 return 0;
0115 }
0116
0117 static struct shash_alg alg = {
0118 .init = sha1_base_init,
0119 .update = sha1_ce_update,
0120 .final = sha1_ce_final,
0121 .finup = sha1_ce_finup,
0122 .import = sha1_ce_import,
0123 .export = sha1_ce_export,
0124 .descsize = sizeof(struct sha1_ce_state),
0125 .statesize = sizeof(struct sha1_state),
0126 .digestsize = SHA1_DIGEST_SIZE,
0127 .base = {
0128 .cra_name = "sha1",
0129 .cra_driver_name = "sha1-ce",
0130 .cra_priority = 200,
0131 .cra_blocksize = SHA1_BLOCK_SIZE,
0132 .cra_module = THIS_MODULE,
0133 }
0134 };
0135
0136 static int __init sha1_ce_mod_init(void)
0137 {
0138 return crypto_register_shash(&alg);
0139 }
0140
0141 static void __exit sha1_ce_mod_fini(void)
0142 {
0143 crypto_unregister_shash(&alg);
0144 }
0145
0146 module_cpu_feature_match(SHA1, sha1_ce_mod_init);
0147 module_exit(sha1_ce_mod_fini);