xref: /openbmc/linux/arch/arm64/crypto/sha3-ce-glue.c (revision cd6714f9)
1*cd6714f9STom Rix // SPDX-License-Identifier: GPL-2.0
215d5910eSArd Biesheuvel /*
315d5910eSArd Biesheuvel  * sha3-ce-glue.c - core SHA-3 transform using v8.2 Crypto Extensions
415d5910eSArd Biesheuvel  *
515d5910eSArd Biesheuvel  * Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
615d5910eSArd Biesheuvel  *
715d5910eSArd Biesheuvel  * This program is free software; you can redistribute it and/or modify
815d5910eSArd Biesheuvel  * it under the terms of the GNU General Public License version 2 as
915d5910eSArd Biesheuvel  * published by the Free Software Foundation.
1015d5910eSArd Biesheuvel  */
1115d5910eSArd Biesheuvel 
1215d5910eSArd Biesheuvel #include <asm/hwcap.h>
1315d5910eSArd Biesheuvel #include <asm/neon.h>
1415d5910eSArd Biesheuvel #include <asm/simd.h>
1515d5910eSArd Biesheuvel #include <asm/unaligned.h>
1615d5910eSArd Biesheuvel #include <crypto/internal/hash.h>
17e52b7023SEric Biggers #include <crypto/internal/simd.h>
1815d5910eSArd Biesheuvel #include <crypto/sha3.h>
1915d5910eSArd Biesheuvel #include <linux/cpufeature.h>
2015d5910eSArd Biesheuvel #include <linux/crypto.h>
2115d5910eSArd Biesheuvel #include <linux/module.h>
2215d5910eSArd Biesheuvel 
2315d5910eSArd Biesheuvel MODULE_DESCRIPTION("SHA3 secure hash using ARMv8 Crypto Extensions");
2415d5910eSArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
2515d5910eSArd Biesheuvel MODULE_LICENSE("GPL v2");
260df07d81SArd Biesheuvel MODULE_ALIAS_CRYPTO("sha3-224");
270df07d81SArd Biesheuvel MODULE_ALIAS_CRYPTO("sha3-256");
280df07d81SArd Biesheuvel MODULE_ALIAS_CRYPTO("sha3-384");
290df07d81SArd Biesheuvel MODULE_ALIAS_CRYPTO("sha3-512");
3015d5910eSArd Biesheuvel 
319ecc9f31SArd Biesheuvel asmlinkage int sha3_ce_transform(u64 *st, const u8 *data, int blocks,
3215d5910eSArd Biesheuvel 				 int md_len);
3315d5910eSArd Biesheuvel 
sha3_update(struct shash_desc * desc,const u8 * data,unsigned int len)3415d5910eSArd Biesheuvel static int sha3_update(struct shash_desc *desc, const u8 *data,
3515d5910eSArd Biesheuvel 		       unsigned int len)
3615d5910eSArd Biesheuvel {
3715d5910eSArd Biesheuvel 	struct sha3_state *sctx = shash_desc_ctx(desc);
3815d5910eSArd Biesheuvel 	unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
3915d5910eSArd Biesheuvel 
40e52b7023SEric Biggers 	if (!crypto_simd_usable())
4115d5910eSArd Biesheuvel 		return crypto_sha3_update(desc, data, len);
4215d5910eSArd Biesheuvel 
4315d5910eSArd Biesheuvel 	if ((sctx->partial + len) >= sctx->rsiz) {
4415d5910eSArd Biesheuvel 		int blocks;
4515d5910eSArd Biesheuvel 
4615d5910eSArd Biesheuvel 		if (sctx->partial) {
4715d5910eSArd Biesheuvel 			int p = sctx->rsiz - sctx->partial;
4815d5910eSArd Biesheuvel 
4915d5910eSArd Biesheuvel 			memcpy(sctx->buf + sctx->partial, data, p);
5015d5910eSArd Biesheuvel 			kernel_neon_begin();
5115d5910eSArd Biesheuvel 			sha3_ce_transform(sctx->st, sctx->buf, 1, digest_size);
5215d5910eSArd Biesheuvel 			kernel_neon_end();
5315d5910eSArd Biesheuvel 
5415d5910eSArd Biesheuvel 			data += p;
5515d5910eSArd Biesheuvel 			len -= p;
5615d5910eSArd Biesheuvel 			sctx->partial = 0;
5715d5910eSArd Biesheuvel 		}
5815d5910eSArd Biesheuvel 
5915d5910eSArd Biesheuvel 		blocks = len / sctx->rsiz;
6015d5910eSArd Biesheuvel 		len %= sctx->rsiz;
6115d5910eSArd Biesheuvel 
629ecc9f31SArd Biesheuvel 		while (blocks) {
639ecc9f31SArd Biesheuvel 			int rem;
649ecc9f31SArd Biesheuvel 
6515d5910eSArd Biesheuvel 			kernel_neon_begin();
669ecc9f31SArd Biesheuvel 			rem = sha3_ce_transform(sctx->st, data, blocks,
679ecc9f31SArd Biesheuvel 						digest_size);
6815d5910eSArd Biesheuvel 			kernel_neon_end();
699ecc9f31SArd Biesheuvel 			data += (blocks - rem) * sctx->rsiz;
709ecc9f31SArd Biesheuvel 			blocks = rem;
7115d5910eSArd Biesheuvel 		}
7215d5910eSArd Biesheuvel 	}
7315d5910eSArd Biesheuvel 
7415d5910eSArd Biesheuvel 	if (len) {
7515d5910eSArd Biesheuvel 		memcpy(sctx->buf + sctx->partial, data, len);
7615d5910eSArd Biesheuvel 		sctx->partial += len;
7715d5910eSArd Biesheuvel 	}
7815d5910eSArd Biesheuvel 	return 0;
7915d5910eSArd Biesheuvel }
8015d5910eSArd Biesheuvel 
sha3_final(struct shash_desc * desc,u8 * out)8115d5910eSArd Biesheuvel static int sha3_final(struct shash_desc *desc, u8 *out)
8215d5910eSArd Biesheuvel {
8315d5910eSArd Biesheuvel 	struct sha3_state *sctx = shash_desc_ctx(desc);
8415d5910eSArd Biesheuvel 	unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
8515d5910eSArd Biesheuvel 	__le64 *digest = (__le64 *)out;
8615d5910eSArd Biesheuvel 	int i;
8715d5910eSArd Biesheuvel 
88e52b7023SEric Biggers 	if (!crypto_simd_usable())
8915d5910eSArd Biesheuvel 		return crypto_sha3_final(desc, out);
9015d5910eSArd Biesheuvel 
9115d5910eSArd Biesheuvel 	sctx->buf[sctx->partial++] = 0x06;
9215d5910eSArd Biesheuvel 	memset(sctx->buf + sctx->partial, 0, sctx->rsiz - sctx->partial);
9315d5910eSArd Biesheuvel 	sctx->buf[sctx->rsiz - 1] |= 0x80;
9415d5910eSArd Biesheuvel 
9515d5910eSArd Biesheuvel 	kernel_neon_begin();
9615d5910eSArd Biesheuvel 	sha3_ce_transform(sctx->st, sctx->buf, 1, digest_size);
9715d5910eSArd Biesheuvel 	kernel_neon_end();
9815d5910eSArd Biesheuvel 
9915d5910eSArd Biesheuvel 	for (i = 0; i < digest_size / 8; i++)
10015d5910eSArd Biesheuvel 		put_unaligned_le64(sctx->st[i], digest++);
10115d5910eSArd Biesheuvel 
10215d5910eSArd Biesheuvel 	if (digest_size & 4)
10315d5910eSArd Biesheuvel 		put_unaligned_le32(sctx->st[i], (__le32 *)digest);
10415d5910eSArd Biesheuvel 
105458c0480SArvind Sankar 	memzero_explicit(sctx, sizeof(*sctx));
10615d5910eSArd Biesheuvel 	return 0;
10715d5910eSArd Biesheuvel }
10815d5910eSArd Biesheuvel 
10915d5910eSArd Biesheuvel static struct shash_alg algs[] = { {
11015d5910eSArd Biesheuvel 	.digestsize		= SHA3_224_DIGEST_SIZE,
11115d5910eSArd Biesheuvel 	.init			= crypto_sha3_init,
11215d5910eSArd Biesheuvel 	.update			= sha3_update,
11315d5910eSArd Biesheuvel 	.final			= sha3_final,
11415d5910eSArd Biesheuvel 	.descsize		= sizeof(struct sha3_state),
11515d5910eSArd Biesheuvel 	.base.cra_name		= "sha3-224",
11615d5910eSArd Biesheuvel 	.base.cra_driver_name	= "sha3-224-ce",
11715d5910eSArd Biesheuvel 	.base.cra_blocksize	= SHA3_224_BLOCK_SIZE,
11815d5910eSArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
11915d5910eSArd Biesheuvel 	.base.cra_priority	= 200,
12015d5910eSArd Biesheuvel }, {
12115d5910eSArd Biesheuvel 	.digestsize		= SHA3_256_DIGEST_SIZE,
12215d5910eSArd Biesheuvel 	.init			= crypto_sha3_init,
12315d5910eSArd Biesheuvel 	.update			= sha3_update,
12415d5910eSArd Biesheuvel 	.final			= sha3_final,
12515d5910eSArd Biesheuvel 	.descsize		= sizeof(struct sha3_state),
12615d5910eSArd Biesheuvel 	.base.cra_name		= "sha3-256",
12715d5910eSArd Biesheuvel 	.base.cra_driver_name	= "sha3-256-ce",
12815d5910eSArd Biesheuvel 	.base.cra_blocksize	= SHA3_256_BLOCK_SIZE,
12915d5910eSArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
13015d5910eSArd Biesheuvel 	.base.cra_priority	= 200,
13115d5910eSArd Biesheuvel }, {
13215d5910eSArd Biesheuvel 	.digestsize		= SHA3_384_DIGEST_SIZE,
13315d5910eSArd Biesheuvel 	.init			= crypto_sha3_init,
13415d5910eSArd Biesheuvel 	.update			= sha3_update,
13515d5910eSArd Biesheuvel 	.final			= sha3_final,
13615d5910eSArd Biesheuvel 	.descsize		= sizeof(struct sha3_state),
13715d5910eSArd Biesheuvel 	.base.cra_name		= "sha3-384",
13815d5910eSArd Biesheuvel 	.base.cra_driver_name	= "sha3-384-ce",
13915d5910eSArd Biesheuvel 	.base.cra_blocksize	= SHA3_384_BLOCK_SIZE,
14015d5910eSArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
14115d5910eSArd Biesheuvel 	.base.cra_priority	= 200,
14215d5910eSArd Biesheuvel }, {
14315d5910eSArd Biesheuvel 	.digestsize		= SHA3_512_DIGEST_SIZE,
14415d5910eSArd Biesheuvel 	.init			= crypto_sha3_init,
14515d5910eSArd Biesheuvel 	.update			= sha3_update,
14615d5910eSArd Biesheuvel 	.final			= sha3_final,
14715d5910eSArd Biesheuvel 	.descsize		= sizeof(struct sha3_state),
14815d5910eSArd Biesheuvel 	.base.cra_name		= "sha3-512",
14915d5910eSArd Biesheuvel 	.base.cra_driver_name	= "sha3-512-ce",
15015d5910eSArd Biesheuvel 	.base.cra_blocksize	= SHA3_512_BLOCK_SIZE,
15115d5910eSArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
15215d5910eSArd Biesheuvel 	.base.cra_priority	= 200,
15315d5910eSArd Biesheuvel } };
15415d5910eSArd Biesheuvel 
sha3_neon_mod_init(void)15515d5910eSArd Biesheuvel static int __init sha3_neon_mod_init(void)
15615d5910eSArd Biesheuvel {
15715d5910eSArd Biesheuvel 	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
15815d5910eSArd Biesheuvel }
15915d5910eSArd Biesheuvel 
sha3_neon_mod_fini(void)16015d5910eSArd Biesheuvel static void __exit sha3_neon_mod_fini(void)
16115d5910eSArd Biesheuvel {
16215d5910eSArd Biesheuvel 	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
16315d5910eSArd Biesheuvel }
16415d5910eSArd Biesheuvel 
16515d5910eSArd Biesheuvel module_cpu_feature_match(SHA3, sha3_neon_mod_init);
16615d5910eSArd Biesheuvel module_exit(sha3_neon_mod_fini);
167