0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <asm/hwcap.h>
0013 #include <asm/neon.h>
0014 #include <asm/simd.h>
0015 #include <asm/unaligned.h>
0016 #include <crypto/internal/hash.h>
0017 #include <crypto/internal/simd.h>
0018 #include <crypto/sha3.h>
0019 #include <linux/cpufeature.h>
0020 #include <linux/crypto.h>
0021 #include <linux/module.h>
0022
0023 MODULE_DESCRIPTION("SHA3 secure hash using ARMv8 Crypto Extensions");
0024 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
0025 MODULE_LICENSE("GPL v2");
0026 MODULE_ALIAS_CRYPTO("sha3-224");
0027 MODULE_ALIAS_CRYPTO("sha3-256");
0028 MODULE_ALIAS_CRYPTO("sha3-384");
0029 MODULE_ALIAS_CRYPTO("sha3-512");
0030
0031 asmlinkage int sha3_ce_transform(u64 *st, const u8 *data, int blocks,
0032 int md_len);
0033
0034 static int sha3_update(struct shash_desc *desc, const u8 *data,
0035 unsigned int len)
0036 {
0037 struct sha3_state *sctx = shash_desc_ctx(desc);
0038 unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
0039
0040 if (!crypto_simd_usable())
0041 return crypto_sha3_update(desc, data, len);
0042
0043 if ((sctx->partial + len) >= sctx->rsiz) {
0044 int blocks;
0045
0046 if (sctx->partial) {
0047 int p = sctx->rsiz - sctx->partial;
0048
0049 memcpy(sctx->buf + sctx->partial, data, p);
0050 kernel_neon_begin();
0051 sha3_ce_transform(sctx->st, sctx->buf, 1, digest_size);
0052 kernel_neon_end();
0053
0054 data += p;
0055 len -= p;
0056 sctx->partial = 0;
0057 }
0058
0059 blocks = len / sctx->rsiz;
0060 len %= sctx->rsiz;
0061
0062 while (blocks) {
0063 int rem;
0064
0065 kernel_neon_begin();
0066 rem = sha3_ce_transform(sctx->st, data, blocks,
0067 digest_size);
0068 kernel_neon_end();
0069 data += (blocks - rem) * sctx->rsiz;
0070 blocks = rem;
0071 }
0072 }
0073
0074 if (len) {
0075 memcpy(sctx->buf + sctx->partial, data, len);
0076 sctx->partial += len;
0077 }
0078 return 0;
0079 }
0080
0081 static int sha3_final(struct shash_desc *desc, u8 *out)
0082 {
0083 struct sha3_state *sctx = shash_desc_ctx(desc);
0084 unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
0085 __le64 *digest = (__le64 *)out;
0086 int i;
0087
0088 if (!crypto_simd_usable())
0089 return crypto_sha3_final(desc, out);
0090
0091 sctx->buf[sctx->partial++] = 0x06;
0092 memset(sctx->buf + sctx->partial, 0, sctx->rsiz - sctx->partial);
0093 sctx->buf[sctx->rsiz - 1] |= 0x80;
0094
0095 kernel_neon_begin();
0096 sha3_ce_transform(sctx->st, sctx->buf, 1, digest_size);
0097 kernel_neon_end();
0098
0099 for (i = 0; i < digest_size / 8; i++)
0100 put_unaligned_le64(sctx->st[i], digest++);
0101
0102 if (digest_size & 4)
0103 put_unaligned_le32(sctx->st[i], (__le32 *)digest);
0104
0105 memzero_explicit(sctx, sizeof(*sctx));
0106 return 0;
0107 }
0108
0109 static struct shash_alg algs[] = { {
0110 .digestsize = SHA3_224_DIGEST_SIZE,
0111 .init = crypto_sha3_init,
0112 .update = sha3_update,
0113 .final = sha3_final,
0114 .descsize = sizeof(struct sha3_state),
0115 .base.cra_name = "sha3-224",
0116 .base.cra_driver_name = "sha3-224-ce",
0117 .base.cra_blocksize = SHA3_224_BLOCK_SIZE,
0118 .base.cra_module = THIS_MODULE,
0119 .base.cra_priority = 200,
0120 }, {
0121 .digestsize = SHA3_256_DIGEST_SIZE,
0122 .init = crypto_sha3_init,
0123 .update = sha3_update,
0124 .final = sha3_final,
0125 .descsize = sizeof(struct sha3_state),
0126 .base.cra_name = "sha3-256",
0127 .base.cra_driver_name = "sha3-256-ce",
0128 .base.cra_blocksize = SHA3_256_BLOCK_SIZE,
0129 .base.cra_module = THIS_MODULE,
0130 .base.cra_priority = 200,
0131 }, {
0132 .digestsize = SHA3_384_DIGEST_SIZE,
0133 .init = crypto_sha3_init,
0134 .update = sha3_update,
0135 .final = sha3_final,
0136 .descsize = sizeof(struct sha3_state),
0137 .base.cra_name = "sha3-384",
0138 .base.cra_driver_name = "sha3-384-ce",
0139 .base.cra_blocksize = SHA3_384_BLOCK_SIZE,
0140 .base.cra_module = THIS_MODULE,
0141 .base.cra_priority = 200,
0142 }, {
0143 .digestsize = SHA3_512_DIGEST_SIZE,
0144 .init = crypto_sha3_init,
0145 .update = sha3_update,
0146 .final = sha3_final,
0147 .descsize = sizeof(struct sha3_state),
0148 .base.cra_name = "sha3-512",
0149 .base.cra_driver_name = "sha3-512-ce",
0150 .base.cra_blocksize = SHA3_512_BLOCK_SIZE,
0151 .base.cra_module = THIS_MODULE,
0152 .base.cra_priority = 200,
0153 } };
0154
0155 static int __init sha3_neon_mod_init(void)
0156 {
0157 return crypto_register_shashes(algs, ARRAY_SIZE(algs));
0158 }
0159
0160 static void __exit sha3_neon_mod_fini(void)
0161 {
0162 crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
0163 }
0164
0165 module_cpu_feature_match(SHA3, sha3_neon_mod_init);
0166 module_exit(sha3_neon_mod_fini);