162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Cryptographic API.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * SHA-3, as specified in
662306a36Sopenharmony_ci * https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * SHA-3 code by Jeff Garzik <jeff@garzik.org>
962306a36Sopenharmony_ci *               Ard Biesheuvel <ard.biesheuvel@linaro.org>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#include <crypto/internal/hash.h>
1262306a36Sopenharmony_ci#include <linux/init.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/types.h>
1562306a36Sopenharmony_ci#include <crypto/sha3.h>
1662306a36Sopenharmony_ci#include <asm/unaligned.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/*
1962306a36Sopenharmony_ci * On some 32-bit architectures (h8300), GCC ends up using
2062306a36Sopenharmony_ci * over 1 KB of stack if we inline the round calculation into the loop
2162306a36Sopenharmony_ci * in keccakf(). On the other hand, on 64-bit architectures with plenty
2262306a36Sopenharmony_ci * of [64-bit wide] general purpose registers, not inlining it severely
2362306a36Sopenharmony_ci * hurts performance. So let's use 64-bitness as a heuristic to decide
2462306a36Sopenharmony_ci * whether to inline or not.
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci#ifdef CONFIG_64BIT
2762306a36Sopenharmony_ci#define SHA3_INLINE	inline
2862306a36Sopenharmony_ci#else
2962306a36Sopenharmony_ci#define SHA3_INLINE	noinline
3062306a36Sopenharmony_ci#endif
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define KECCAK_ROUNDS 24
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic const u64 keccakf_rndc[24] = {
3562306a36Sopenharmony_ci	0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
3662306a36Sopenharmony_ci	0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
3762306a36Sopenharmony_ci	0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
3862306a36Sopenharmony_ci	0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
3962306a36Sopenharmony_ci	0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
4062306a36Sopenharmony_ci	0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
4162306a36Sopenharmony_ci	0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
4262306a36Sopenharmony_ci	0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
4362306a36Sopenharmony_ci};
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/* update the state with given number of rounds */
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic SHA3_INLINE void keccakf_round(u64 st[25])
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	u64 t[5], tt, bc[5];
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	/* Theta */
5262306a36Sopenharmony_ci	bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
5362306a36Sopenharmony_ci	bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
5462306a36Sopenharmony_ci	bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
5562306a36Sopenharmony_ci	bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
5662306a36Sopenharmony_ci	bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	t[0] = bc[4] ^ rol64(bc[1], 1);
5962306a36Sopenharmony_ci	t[1] = bc[0] ^ rol64(bc[2], 1);
6062306a36Sopenharmony_ci	t[2] = bc[1] ^ rol64(bc[3], 1);
6162306a36Sopenharmony_ci	t[3] = bc[2] ^ rol64(bc[4], 1);
6262306a36Sopenharmony_ci	t[4] = bc[3] ^ rol64(bc[0], 1);
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	st[0] ^= t[0];
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	/* Rho Pi */
6762306a36Sopenharmony_ci	tt = st[1];
6862306a36Sopenharmony_ci	st[ 1] = rol64(st[ 6] ^ t[1], 44);
6962306a36Sopenharmony_ci	st[ 6] = rol64(st[ 9] ^ t[4], 20);
7062306a36Sopenharmony_ci	st[ 9] = rol64(st[22] ^ t[2], 61);
7162306a36Sopenharmony_ci	st[22] = rol64(st[14] ^ t[4], 39);
7262306a36Sopenharmony_ci	st[14] = rol64(st[20] ^ t[0], 18);
7362306a36Sopenharmony_ci	st[20] = rol64(st[ 2] ^ t[2], 62);
7462306a36Sopenharmony_ci	st[ 2] = rol64(st[12] ^ t[2], 43);
7562306a36Sopenharmony_ci	st[12] = rol64(st[13] ^ t[3], 25);
7662306a36Sopenharmony_ci	st[13] = rol64(st[19] ^ t[4],  8);
7762306a36Sopenharmony_ci	st[19] = rol64(st[23] ^ t[3], 56);
7862306a36Sopenharmony_ci	st[23] = rol64(st[15] ^ t[0], 41);
7962306a36Sopenharmony_ci	st[15] = rol64(st[ 4] ^ t[4], 27);
8062306a36Sopenharmony_ci	st[ 4] = rol64(st[24] ^ t[4], 14);
8162306a36Sopenharmony_ci	st[24] = rol64(st[21] ^ t[1],  2);
8262306a36Sopenharmony_ci	st[21] = rol64(st[ 8] ^ t[3], 55);
8362306a36Sopenharmony_ci	st[ 8] = rol64(st[16] ^ t[1], 45);
8462306a36Sopenharmony_ci	st[16] = rol64(st[ 5] ^ t[0], 36);
8562306a36Sopenharmony_ci	st[ 5] = rol64(st[ 3] ^ t[3], 28);
8662306a36Sopenharmony_ci	st[ 3] = rol64(st[18] ^ t[3], 21);
8762306a36Sopenharmony_ci	st[18] = rol64(st[17] ^ t[2], 15);
8862306a36Sopenharmony_ci	st[17] = rol64(st[11] ^ t[1], 10);
8962306a36Sopenharmony_ci	st[11] = rol64(st[ 7] ^ t[2],  6);
9062306a36Sopenharmony_ci	st[ 7] = rol64(st[10] ^ t[0],  3);
9162306a36Sopenharmony_ci	st[10] = rol64(    tt ^ t[1],  1);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	/* Chi */
9462306a36Sopenharmony_ci	bc[ 0] = ~st[ 1] & st[ 2];
9562306a36Sopenharmony_ci	bc[ 1] = ~st[ 2] & st[ 3];
9662306a36Sopenharmony_ci	bc[ 2] = ~st[ 3] & st[ 4];
9762306a36Sopenharmony_ci	bc[ 3] = ~st[ 4] & st[ 0];
9862306a36Sopenharmony_ci	bc[ 4] = ~st[ 0] & st[ 1];
9962306a36Sopenharmony_ci	st[ 0] ^= bc[ 0];
10062306a36Sopenharmony_ci	st[ 1] ^= bc[ 1];
10162306a36Sopenharmony_ci	st[ 2] ^= bc[ 2];
10262306a36Sopenharmony_ci	st[ 3] ^= bc[ 3];
10362306a36Sopenharmony_ci	st[ 4] ^= bc[ 4];
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	bc[ 0] = ~st[ 6] & st[ 7];
10662306a36Sopenharmony_ci	bc[ 1] = ~st[ 7] & st[ 8];
10762306a36Sopenharmony_ci	bc[ 2] = ~st[ 8] & st[ 9];
10862306a36Sopenharmony_ci	bc[ 3] = ~st[ 9] & st[ 5];
10962306a36Sopenharmony_ci	bc[ 4] = ~st[ 5] & st[ 6];
11062306a36Sopenharmony_ci	st[ 5] ^= bc[ 0];
11162306a36Sopenharmony_ci	st[ 6] ^= bc[ 1];
11262306a36Sopenharmony_ci	st[ 7] ^= bc[ 2];
11362306a36Sopenharmony_ci	st[ 8] ^= bc[ 3];
11462306a36Sopenharmony_ci	st[ 9] ^= bc[ 4];
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	bc[ 0] = ~st[11] & st[12];
11762306a36Sopenharmony_ci	bc[ 1] = ~st[12] & st[13];
11862306a36Sopenharmony_ci	bc[ 2] = ~st[13] & st[14];
11962306a36Sopenharmony_ci	bc[ 3] = ~st[14] & st[10];
12062306a36Sopenharmony_ci	bc[ 4] = ~st[10] & st[11];
12162306a36Sopenharmony_ci	st[10] ^= bc[ 0];
12262306a36Sopenharmony_ci	st[11] ^= bc[ 1];
12362306a36Sopenharmony_ci	st[12] ^= bc[ 2];
12462306a36Sopenharmony_ci	st[13] ^= bc[ 3];
12562306a36Sopenharmony_ci	st[14] ^= bc[ 4];
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	bc[ 0] = ~st[16] & st[17];
12862306a36Sopenharmony_ci	bc[ 1] = ~st[17] & st[18];
12962306a36Sopenharmony_ci	bc[ 2] = ~st[18] & st[19];
13062306a36Sopenharmony_ci	bc[ 3] = ~st[19] & st[15];
13162306a36Sopenharmony_ci	bc[ 4] = ~st[15] & st[16];
13262306a36Sopenharmony_ci	st[15] ^= bc[ 0];
13362306a36Sopenharmony_ci	st[16] ^= bc[ 1];
13462306a36Sopenharmony_ci	st[17] ^= bc[ 2];
13562306a36Sopenharmony_ci	st[18] ^= bc[ 3];
13662306a36Sopenharmony_ci	st[19] ^= bc[ 4];
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	bc[ 0] = ~st[21] & st[22];
13962306a36Sopenharmony_ci	bc[ 1] = ~st[22] & st[23];
14062306a36Sopenharmony_ci	bc[ 2] = ~st[23] & st[24];
14162306a36Sopenharmony_ci	bc[ 3] = ~st[24] & st[20];
14262306a36Sopenharmony_ci	bc[ 4] = ~st[20] & st[21];
14362306a36Sopenharmony_ci	st[20] ^= bc[ 0];
14462306a36Sopenharmony_ci	st[21] ^= bc[ 1];
14562306a36Sopenharmony_ci	st[22] ^= bc[ 2];
14662306a36Sopenharmony_ci	st[23] ^= bc[ 3];
14762306a36Sopenharmony_ci	st[24] ^= bc[ 4];
14862306a36Sopenharmony_ci}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistatic void keccakf(u64 st[25])
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	int round;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	for (round = 0; round < KECCAK_ROUNDS; round++) {
15562306a36Sopenharmony_ci		keccakf_round(st);
15662306a36Sopenharmony_ci		/* Iota */
15762306a36Sopenharmony_ci		st[0] ^= keccakf_rndc[round];
15862306a36Sopenharmony_ci	}
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ciint crypto_sha3_init(struct shash_desc *desc)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	struct sha3_state *sctx = shash_desc_ctx(desc);
16462306a36Sopenharmony_ci	unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	sctx->rsiz = 200 - 2 * digest_size;
16762306a36Sopenharmony_ci	sctx->rsizw = sctx->rsiz / 8;
16862306a36Sopenharmony_ci	sctx->partial = 0;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	memset(sctx->st, 0, sizeof(sctx->st));
17162306a36Sopenharmony_ci	return 0;
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ciEXPORT_SYMBOL(crypto_sha3_init);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciint crypto_sha3_update(struct shash_desc *desc, const u8 *data,
17662306a36Sopenharmony_ci		       unsigned int len)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	struct sha3_state *sctx = shash_desc_ctx(desc);
17962306a36Sopenharmony_ci	unsigned int done;
18062306a36Sopenharmony_ci	const u8 *src;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	done = 0;
18362306a36Sopenharmony_ci	src = data;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	if ((sctx->partial + len) > (sctx->rsiz - 1)) {
18662306a36Sopenharmony_ci		if (sctx->partial) {
18762306a36Sopenharmony_ci			done = -sctx->partial;
18862306a36Sopenharmony_ci			memcpy(sctx->buf + sctx->partial, data,
18962306a36Sopenharmony_ci			       done + sctx->rsiz);
19062306a36Sopenharmony_ci			src = sctx->buf;
19162306a36Sopenharmony_ci		}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci		do {
19462306a36Sopenharmony_ci			unsigned int i;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci			for (i = 0; i < sctx->rsizw; i++)
19762306a36Sopenharmony_ci				sctx->st[i] ^= get_unaligned_le64(src + 8 * i);
19862306a36Sopenharmony_ci			keccakf(sctx->st);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci			done += sctx->rsiz;
20162306a36Sopenharmony_ci			src = data + done;
20262306a36Sopenharmony_ci		} while (done + (sctx->rsiz - 1) < len);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci		sctx->partial = 0;
20562306a36Sopenharmony_ci	}
20662306a36Sopenharmony_ci	memcpy(sctx->buf + sctx->partial, src, len - done);
20762306a36Sopenharmony_ci	sctx->partial += (len - done);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	return 0;
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ciEXPORT_SYMBOL(crypto_sha3_update);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ciint crypto_sha3_final(struct shash_desc *desc, u8 *out)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	struct sha3_state *sctx = shash_desc_ctx(desc);
21662306a36Sopenharmony_ci	unsigned int i, inlen = sctx->partial;
21762306a36Sopenharmony_ci	unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
21862306a36Sopenharmony_ci	__le64 *digest = (__le64 *)out;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	sctx->buf[inlen++] = 0x06;
22162306a36Sopenharmony_ci	memset(sctx->buf + inlen, 0, sctx->rsiz - inlen);
22262306a36Sopenharmony_ci	sctx->buf[sctx->rsiz - 1] |= 0x80;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	for (i = 0; i < sctx->rsizw; i++)
22562306a36Sopenharmony_ci		sctx->st[i] ^= get_unaligned_le64(sctx->buf + 8 * i);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	keccakf(sctx->st);
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	for (i = 0; i < digest_size / 8; i++)
23062306a36Sopenharmony_ci		put_unaligned_le64(sctx->st[i], digest++);
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	if (digest_size & 4)
23362306a36Sopenharmony_ci		put_unaligned_le32(sctx->st[i], (__le32 *)digest);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	memset(sctx, 0, sizeof(*sctx));
23662306a36Sopenharmony_ci	return 0;
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ciEXPORT_SYMBOL(crypto_sha3_final);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic struct shash_alg algs[] = { {
24162306a36Sopenharmony_ci	.digestsize		= SHA3_224_DIGEST_SIZE,
24262306a36Sopenharmony_ci	.init			= crypto_sha3_init,
24362306a36Sopenharmony_ci	.update			= crypto_sha3_update,
24462306a36Sopenharmony_ci	.final			= crypto_sha3_final,
24562306a36Sopenharmony_ci	.descsize		= sizeof(struct sha3_state),
24662306a36Sopenharmony_ci	.base.cra_name		= "sha3-224",
24762306a36Sopenharmony_ci	.base.cra_driver_name	= "sha3-224-generic",
24862306a36Sopenharmony_ci	.base.cra_blocksize	= SHA3_224_BLOCK_SIZE,
24962306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
25062306a36Sopenharmony_ci}, {
25162306a36Sopenharmony_ci	.digestsize		= SHA3_256_DIGEST_SIZE,
25262306a36Sopenharmony_ci	.init			= crypto_sha3_init,
25362306a36Sopenharmony_ci	.update			= crypto_sha3_update,
25462306a36Sopenharmony_ci	.final			= crypto_sha3_final,
25562306a36Sopenharmony_ci	.descsize		= sizeof(struct sha3_state),
25662306a36Sopenharmony_ci	.base.cra_name		= "sha3-256",
25762306a36Sopenharmony_ci	.base.cra_driver_name	= "sha3-256-generic",
25862306a36Sopenharmony_ci	.base.cra_blocksize	= SHA3_256_BLOCK_SIZE,
25962306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
26062306a36Sopenharmony_ci}, {
26162306a36Sopenharmony_ci	.digestsize		= SHA3_384_DIGEST_SIZE,
26262306a36Sopenharmony_ci	.init			= crypto_sha3_init,
26362306a36Sopenharmony_ci	.update			= crypto_sha3_update,
26462306a36Sopenharmony_ci	.final			= crypto_sha3_final,
26562306a36Sopenharmony_ci	.descsize		= sizeof(struct sha3_state),
26662306a36Sopenharmony_ci	.base.cra_name		= "sha3-384",
26762306a36Sopenharmony_ci	.base.cra_driver_name	= "sha3-384-generic",
26862306a36Sopenharmony_ci	.base.cra_blocksize	= SHA3_384_BLOCK_SIZE,
26962306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
27062306a36Sopenharmony_ci}, {
27162306a36Sopenharmony_ci	.digestsize		= SHA3_512_DIGEST_SIZE,
27262306a36Sopenharmony_ci	.init			= crypto_sha3_init,
27362306a36Sopenharmony_ci	.update			= crypto_sha3_update,
27462306a36Sopenharmony_ci	.final			= crypto_sha3_final,
27562306a36Sopenharmony_ci	.descsize		= sizeof(struct sha3_state),
27662306a36Sopenharmony_ci	.base.cra_name		= "sha3-512",
27762306a36Sopenharmony_ci	.base.cra_driver_name	= "sha3-512-generic",
27862306a36Sopenharmony_ci	.base.cra_blocksize	= SHA3_512_BLOCK_SIZE,
27962306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
28062306a36Sopenharmony_ci} };
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_cistatic int __init sha3_generic_mod_init(void)
28362306a36Sopenharmony_ci{
28462306a36Sopenharmony_ci	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_cistatic void __exit sha3_generic_mod_fini(void)
28862306a36Sopenharmony_ci{
28962306a36Sopenharmony_ci	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
29062306a36Sopenharmony_ci}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cisubsys_initcall(sha3_generic_mod_init);
29362306a36Sopenharmony_cimodule_exit(sha3_generic_mod_fini);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ciMODULE_LICENSE("GPL");
29662306a36Sopenharmony_ciMODULE_DESCRIPTION("SHA-3 Secure Hash Algorithm");
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha3-224");
29962306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha3-224-generic");
30062306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha3-256");
30162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha3-256-generic");
30262306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha3-384");
30362306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha3-384-generic");
30462306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha3-512");
30562306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha3-512-generic");
306