12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
253964b9eSJeff Garzik /*
353964b9eSJeff Garzik * Cryptographic API.
453964b9eSJeff Garzik *
553964b9eSJeff Garzik * SHA-3, as specified in
69332a9e7SAlexander A. Klimov * https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
753964b9eSJeff Garzik *
853964b9eSJeff Garzik * SHA-3 code by Jeff Garzik <jeff@garzik.org>
983dee2ceSArd Biesheuvel * Ard Biesheuvel <ard.biesheuvel@linaro.org>
1053964b9eSJeff Garzik */
1153964b9eSJeff Garzik #include <crypto/internal/hash.h>
1253964b9eSJeff Garzik #include <linux/init.h>
1353964b9eSJeff Garzik #include <linux/module.h>
1453964b9eSJeff Garzik #include <linux/types.h>
1553964b9eSJeff Garzik #include <crypto/sha3.h>
16*5f60d5f6SAl Viro #include <linux/unaligned.h>
1753964b9eSJeff Garzik
184767b9adSArd Biesheuvel /*
19739d875dSDavid Howells * On some 32-bit architectures (h8300), GCC ends up using
204767b9adSArd Biesheuvel * over 1 KB of stack if we inline the round calculation into the loop
214767b9adSArd Biesheuvel * in keccakf(). On the other hand, on 64-bit architectures with plenty
224767b9adSArd Biesheuvel * of [64-bit wide] general purpose registers, not inlining it severely
234767b9adSArd Biesheuvel * hurts performance. So let's use 64-bitness as a heuristic to decide
244767b9adSArd Biesheuvel * whether to inline or not.
254767b9adSArd Biesheuvel */
264767b9adSArd Biesheuvel #ifdef CONFIG_64BIT
274767b9adSArd Biesheuvel #define SHA3_INLINE inline
284767b9adSArd Biesheuvel #else
294767b9adSArd Biesheuvel #define SHA3_INLINE noinline
304767b9adSArd Biesheuvel #endif
314767b9adSArd Biesheuvel
3253964b9eSJeff Garzik #define KECCAK_ROUNDS 24
3353964b9eSJeff Garzik
3453964b9eSJeff Garzik static const u64 keccakf_rndc[24] = {
35f743e70eSGeert Uytterhoeven 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
36f743e70eSGeert Uytterhoeven 0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
37f743e70eSGeert Uytterhoeven 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
38f743e70eSGeert Uytterhoeven 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
39f743e70eSGeert Uytterhoeven 0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
40f743e70eSGeert Uytterhoeven 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
41f743e70eSGeert Uytterhoeven 0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
42f743e70eSGeert Uytterhoeven 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
4353964b9eSJeff Garzik };
4453964b9eSJeff Garzik
4553964b9eSJeff Garzik /* update the state with given number of rounds */
4653964b9eSJeff Garzik
keccakf_round(u64 st[25])474767b9adSArd Biesheuvel static SHA3_INLINE void keccakf_round(u64 st[25])
4853964b9eSJeff Garzik {
4983dee2ceSArd Biesheuvel u64 t[5], tt, bc[5];
5053964b9eSJeff Garzik
5153964b9eSJeff Garzik /* Theta */
5283dee2ceSArd Biesheuvel bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
5383dee2ceSArd Biesheuvel bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
5483dee2ceSArd Biesheuvel bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
5583dee2ceSArd Biesheuvel bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
5683dee2ceSArd Biesheuvel bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
5753964b9eSJeff Garzik
5883dee2ceSArd Biesheuvel t[0] = bc[4] ^ rol64(bc[1], 1);
5983dee2ceSArd Biesheuvel t[1] = bc[0] ^ rol64(bc[2], 1);
6083dee2ceSArd Biesheuvel t[2] = bc[1] ^ rol64(bc[3], 1);
6183dee2ceSArd Biesheuvel t[3] = bc[2] ^ rol64(bc[4], 1);
6283dee2ceSArd Biesheuvel t[4] = bc[3] ^ rol64(bc[0], 1);
6383dee2ceSArd Biesheuvel
6483dee2ceSArd Biesheuvel st[0] ^= t[0];
6553964b9eSJeff Garzik
6653964b9eSJeff Garzik /* Rho Pi */
6783dee2ceSArd Biesheuvel tt = st[1];
6883dee2ceSArd Biesheuvel st[ 1] = rol64(st[ 6] ^ t[1], 44);
6983dee2ceSArd Biesheuvel st[ 6] = rol64(st[ 9] ^ t[4], 20);
7083dee2ceSArd Biesheuvel st[ 9] = rol64(st[22] ^ t[2], 61);
7183dee2ceSArd Biesheuvel st[22] = rol64(st[14] ^ t[4], 39);
7283dee2ceSArd Biesheuvel st[14] = rol64(st[20] ^ t[0], 18);
7383dee2ceSArd Biesheuvel st[20] = rol64(st[ 2] ^ t[2], 62);
7483dee2ceSArd Biesheuvel st[ 2] = rol64(st[12] ^ t[2], 43);
7583dee2ceSArd Biesheuvel st[12] = rol64(st[13] ^ t[3], 25);
7683dee2ceSArd Biesheuvel st[13] = rol64(st[19] ^ t[4], 8);
7783dee2ceSArd Biesheuvel st[19] = rol64(st[23] ^ t[3], 56);
7883dee2ceSArd Biesheuvel st[23] = rol64(st[15] ^ t[0], 41);
7983dee2ceSArd Biesheuvel st[15] = rol64(st[ 4] ^ t[4], 27);
8083dee2ceSArd Biesheuvel st[ 4] = rol64(st[24] ^ t[4], 14);
8183dee2ceSArd Biesheuvel st[24] = rol64(st[21] ^ t[1], 2);
8283dee2ceSArd Biesheuvel st[21] = rol64(st[ 8] ^ t[3], 55);
8383dee2ceSArd Biesheuvel st[ 8] = rol64(st[16] ^ t[1], 45);
8483dee2ceSArd Biesheuvel st[16] = rol64(st[ 5] ^ t[0], 36);
8583dee2ceSArd Biesheuvel st[ 5] = rol64(st[ 3] ^ t[3], 28);
8683dee2ceSArd Biesheuvel st[ 3] = rol64(st[18] ^ t[3], 21);
8783dee2ceSArd Biesheuvel st[18] = rol64(st[17] ^ t[2], 15);
8883dee2ceSArd Biesheuvel st[17] = rol64(st[11] ^ t[1], 10);
8983dee2ceSArd Biesheuvel st[11] = rol64(st[ 7] ^ t[2], 6);
9083dee2ceSArd Biesheuvel st[ 7] = rol64(st[10] ^ t[0], 3);
9183dee2ceSArd Biesheuvel st[10] = rol64( tt ^ t[1], 1);
9253964b9eSJeff Garzik
9353964b9eSJeff Garzik /* Chi */
9483dee2ceSArd Biesheuvel bc[ 0] = ~st[ 1] & st[ 2];
9583dee2ceSArd Biesheuvel bc[ 1] = ~st[ 2] & st[ 3];
9683dee2ceSArd Biesheuvel bc[ 2] = ~st[ 3] & st[ 4];
9783dee2ceSArd Biesheuvel bc[ 3] = ~st[ 4] & st[ 0];
9883dee2ceSArd Biesheuvel bc[ 4] = ~st[ 0] & st[ 1];
9983dee2ceSArd Biesheuvel st[ 0] ^= bc[ 0];
10083dee2ceSArd Biesheuvel st[ 1] ^= bc[ 1];
10183dee2ceSArd Biesheuvel st[ 2] ^= bc[ 2];
10283dee2ceSArd Biesheuvel st[ 3] ^= bc[ 3];
10383dee2ceSArd Biesheuvel st[ 4] ^= bc[ 4];
10483dee2ceSArd Biesheuvel
10583dee2ceSArd Biesheuvel bc[ 0] = ~st[ 6] & st[ 7];
10683dee2ceSArd Biesheuvel bc[ 1] = ~st[ 7] & st[ 8];
10783dee2ceSArd Biesheuvel bc[ 2] = ~st[ 8] & st[ 9];
10883dee2ceSArd Biesheuvel bc[ 3] = ~st[ 9] & st[ 5];
10983dee2ceSArd Biesheuvel bc[ 4] = ~st[ 5] & st[ 6];
11083dee2ceSArd Biesheuvel st[ 5] ^= bc[ 0];
11183dee2ceSArd Biesheuvel st[ 6] ^= bc[ 1];
11283dee2ceSArd Biesheuvel st[ 7] ^= bc[ 2];
11383dee2ceSArd Biesheuvel st[ 8] ^= bc[ 3];
11483dee2ceSArd Biesheuvel st[ 9] ^= bc[ 4];
11583dee2ceSArd Biesheuvel
11683dee2ceSArd Biesheuvel bc[ 0] = ~st[11] & st[12];
11783dee2ceSArd Biesheuvel bc[ 1] = ~st[12] & st[13];
11883dee2ceSArd Biesheuvel bc[ 2] = ~st[13] & st[14];
11983dee2ceSArd Biesheuvel bc[ 3] = ~st[14] & st[10];
12083dee2ceSArd Biesheuvel bc[ 4] = ~st[10] & st[11];
12183dee2ceSArd Biesheuvel st[10] ^= bc[ 0];
12283dee2ceSArd Biesheuvel st[11] ^= bc[ 1];
12383dee2ceSArd Biesheuvel st[12] ^= bc[ 2];
12483dee2ceSArd Biesheuvel st[13] ^= bc[ 3];
12583dee2ceSArd Biesheuvel st[14] ^= bc[ 4];
12683dee2ceSArd Biesheuvel
12783dee2ceSArd Biesheuvel bc[ 0] = ~st[16] & st[17];
12883dee2ceSArd Biesheuvel bc[ 1] = ~st[17] & st[18];
12983dee2ceSArd Biesheuvel bc[ 2] = ~st[18] & st[19];
13083dee2ceSArd Biesheuvel bc[ 3] = ~st[19] & st[15];
13183dee2ceSArd Biesheuvel bc[ 4] = ~st[15] & st[16];
13283dee2ceSArd Biesheuvel st[15] ^= bc[ 0];
13383dee2ceSArd Biesheuvel st[16] ^= bc[ 1];
13483dee2ceSArd Biesheuvel st[17] ^= bc[ 2];
13583dee2ceSArd Biesheuvel st[18] ^= bc[ 3];
13683dee2ceSArd Biesheuvel st[19] ^= bc[ 4];
13783dee2ceSArd Biesheuvel
13883dee2ceSArd Biesheuvel bc[ 0] = ~st[21] & st[22];
13983dee2ceSArd Biesheuvel bc[ 1] = ~st[22] & st[23];
14083dee2ceSArd Biesheuvel bc[ 2] = ~st[23] & st[24];
14183dee2ceSArd Biesheuvel bc[ 3] = ~st[24] & st[20];
14283dee2ceSArd Biesheuvel bc[ 4] = ~st[20] & st[21];
14383dee2ceSArd Biesheuvel st[20] ^= bc[ 0];
14483dee2ceSArd Biesheuvel st[21] ^= bc[ 1];
14583dee2ceSArd Biesheuvel st[22] ^= bc[ 2];
14683dee2ceSArd Biesheuvel st[23] ^= bc[ 3];
14783dee2ceSArd Biesheuvel st[24] ^= bc[ 4];
1484767b9adSArd Biesheuvel }
14953964b9eSJeff Garzik
keccakf(u64 st[25])150f044a84eSDmitry Vyukov static void keccakf(u64 st[25])
1514767b9adSArd Biesheuvel {
1524767b9adSArd Biesheuvel int round;
1534767b9adSArd Biesheuvel
1544767b9adSArd Biesheuvel for (round = 0; round < KECCAK_ROUNDS; round++) {
1554767b9adSArd Biesheuvel keccakf_round(st);
15653964b9eSJeff Garzik /* Iota */
15753964b9eSJeff Garzik st[0] ^= keccakf_rndc[round];
15853964b9eSJeff Garzik }
15953964b9eSJeff Garzik }
16053964b9eSJeff Garzik
crypto_sha3_init(struct shash_desc * desc)1616657674bSArd Biesheuvel int crypto_sha3_init(struct shash_desc *desc)
16253964b9eSJeff Garzik {
163beeb504aSArd Biesheuvel struct sha3_state *sctx = shash_desc_ctx(desc);
164beeb504aSArd Biesheuvel unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
165beeb504aSArd Biesheuvel
166beeb504aSArd Biesheuvel sctx->rsiz = 200 - 2 * digest_size;
16753964b9eSJeff Garzik sctx->rsizw = sctx->rsiz / 8;
168beeb504aSArd Biesheuvel sctx->partial = 0;
16953964b9eSJeff Garzik
170beeb504aSArd Biesheuvel memset(sctx->st, 0, sizeof(sctx->st));
17153964b9eSJeff Garzik return 0;
17253964b9eSJeff Garzik }
1736657674bSArd Biesheuvel EXPORT_SYMBOL(crypto_sha3_init);
17453964b9eSJeff Garzik
crypto_sha3_update(struct shash_desc * desc,const u8 * data,unsigned int len)1756657674bSArd Biesheuvel int crypto_sha3_update(struct shash_desc *desc, const u8 *data,
17653964b9eSJeff Garzik unsigned int len)
17753964b9eSJeff Garzik {
17853964b9eSJeff Garzik struct sha3_state *sctx = shash_desc_ctx(desc);
17953964b9eSJeff Garzik unsigned int done;
18053964b9eSJeff Garzik const u8 *src;
18153964b9eSJeff Garzik
18253964b9eSJeff Garzik done = 0;
18353964b9eSJeff Garzik src = data;
18453964b9eSJeff Garzik
18553964b9eSJeff Garzik if ((sctx->partial + len) > (sctx->rsiz - 1)) {
18653964b9eSJeff Garzik if (sctx->partial) {
18753964b9eSJeff Garzik done = -sctx->partial;
18853964b9eSJeff Garzik memcpy(sctx->buf + sctx->partial, data,
18953964b9eSJeff Garzik done + sctx->rsiz);
19053964b9eSJeff Garzik src = sctx->buf;
19153964b9eSJeff Garzik }
19253964b9eSJeff Garzik
19353964b9eSJeff Garzik do {
19453964b9eSJeff Garzik unsigned int i;
19553964b9eSJeff Garzik
19653964b9eSJeff Garzik for (i = 0; i < sctx->rsizw; i++)
197c013cee9SArd Biesheuvel sctx->st[i] ^= get_unaligned_le64(src + 8 * i);
19853964b9eSJeff Garzik keccakf(sctx->st);
19953964b9eSJeff Garzik
20053964b9eSJeff Garzik done += sctx->rsiz;
20153964b9eSJeff Garzik src = data + done;
20253964b9eSJeff Garzik } while (done + (sctx->rsiz - 1) < len);
20353964b9eSJeff Garzik
20453964b9eSJeff Garzik sctx->partial = 0;
20553964b9eSJeff Garzik }
20653964b9eSJeff Garzik memcpy(sctx->buf + sctx->partial, src, len - done);
20753964b9eSJeff Garzik sctx->partial += (len - done);
20853964b9eSJeff Garzik
20953964b9eSJeff Garzik return 0;
21053964b9eSJeff Garzik }
2116657674bSArd Biesheuvel EXPORT_SYMBOL(crypto_sha3_update);
21253964b9eSJeff Garzik
crypto_sha3_final(struct shash_desc * desc,u8 * out)2136657674bSArd Biesheuvel int crypto_sha3_final(struct shash_desc *desc, u8 *out)
21453964b9eSJeff Garzik {
21553964b9eSJeff Garzik struct sha3_state *sctx = shash_desc_ctx(desc);
21653964b9eSJeff Garzik unsigned int i, inlen = sctx->partial;
217beeb504aSArd Biesheuvel unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
218beeb504aSArd Biesheuvel __le64 *digest = (__le64 *)out;
21953964b9eSJeff Garzik
22053964b9eSJeff Garzik sctx->buf[inlen++] = 0x06;
22153964b9eSJeff Garzik memset(sctx->buf + inlen, 0, sctx->rsiz - inlen);
22253964b9eSJeff Garzik sctx->buf[sctx->rsiz - 1] |= 0x80;
22353964b9eSJeff Garzik
22453964b9eSJeff Garzik for (i = 0; i < sctx->rsizw; i++)
225c013cee9SArd Biesheuvel sctx->st[i] ^= get_unaligned_le64(sctx->buf + 8 * i);
22653964b9eSJeff Garzik
22753964b9eSJeff Garzik keccakf(sctx->st);
22853964b9eSJeff Garzik
229beeb504aSArd Biesheuvel for (i = 0; i < digest_size / 8; i++)
230beeb504aSArd Biesheuvel put_unaligned_le64(sctx->st[i], digest++);
23153964b9eSJeff Garzik
232beeb504aSArd Biesheuvel if (digest_size & 4)
233beeb504aSArd Biesheuvel put_unaligned_le32(sctx->st[i], (__le32 *)digest);
23453964b9eSJeff Garzik
23553964b9eSJeff Garzik memset(sctx, 0, sizeof(*sctx));
23653964b9eSJeff Garzik return 0;
23753964b9eSJeff Garzik }
2386657674bSArd Biesheuvel EXPORT_SYMBOL(crypto_sha3_final);
23953964b9eSJeff Garzik
240beeb504aSArd Biesheuvel static struct shash_alg algs[] = { {
24153964b9eSJeff Garzik .digestsize = SHA3_224_DIGEST_SIZE,
2426657674bSArd Biesheuvel .init = crypto_sha3_init,
2436657674bSArd Biesheuvel .update = crypto_sha3_update,
2446657674bSArd Biesheuvel .final = crypto_sha3_final,
24553964b9eSJeff Garzik .descsize = sizeof(struct sha3_state),
246beeb504aSArd Biesheuvel .base.cra_name = "sha3-224",
247beeb504aSArd Biesheuvel .base.cra_driver_name = "sha3-224-generic",
248beeb504aSArd Biesheuvel .base.cra_blocksize = SHA3_224_BLOCK_SIZE,
249beeb504aSArd Biesheuvel .base.cra_module = THIS_MODULE,
250beeb504aSArd Biesheuvel }, {
25153964b9eSJeff Garzik .digestsize = SHA3_256_DIGEST_SIZE,
2526657674bSArd Biesheuvel .init = crypto_sha3_init,
2536657674bSArd Biesheuvel .update = crypto_sha3_update,
2546657674bSArd Biesheuvel .final = crypto_sha3_final,
25553964b9eSJeff Garzik .descsize = sizeof(struct sha3_state),
256beeb504aSArd Biesheuvel .base.cra_name = "sha3-256",
257beeb504aSArd Biesheuvel .base.cra_driver_name = "sha3-256-generic",
258beeb504aSArd Biesheuvel .base.cra_blocksize = SHA3_256_BLOCK_SIZE,
259beeb504aSArd Biesheuvel .base.cra_module = THIS_MODULE,
260beeb504aSArd Biesheuvel }, {
26153964b9eSJeff Garzik .digestsize = SHA3_384_DIGEST_SIZE,
2626657674bSArd Biesheuvel .init = crypto_sha3_init,
2636657674bSArd Biesheuvel .update = crypto_sha3_update,
2646657674bSArd Biesheuvel .final = crypto_sha3_final,
26553964b9eSJeff Garzik .descsize = sizeof(struct sha3_state),
266beeb504aSArd Biesheuvel .base.cra_name = "sha3-384",
267beeb504aSArd Biesheuvel .base.cra_driver_name = "sha3-384-generic",
268beeb504aSArd Biesheuvel .base.cra_blocksize = SHA3_384_BLOCK_SIZE,
269beeb504aSArd Biesheuvel .base.cra_module = THIS_MODULE,
270beeb504aSArd Biesheuvel }, {
27153964b9eSJeff Garzik .digestsize = SHA3_512_DIGEST_SIZE,
2726657674bSArd Biesheuvel .init = crypto_sha3_init,
2736657674bSArd Biesheuvel .update = crypto_sha3_update,
2746657674bSArd Biesheuvel .final = crypto_sha3_final,
27553964b9eSJeff Garzik .descsize = sizeof(struct sha3_state),
276beeb504aSArd Biesheuvel .base.cra_name = "sha3-512",
277beeb504aSArd Biesheuvel .base.cra_driver_name = "sha3-512-generic",
278beeb504aSArd Biesheuvel .base.cra_blocksize = SHA3_512_BLOCK_SIZE,
279beeb504aSArd Biesheuvel .base.cra_module = THIS_MODULE,
280beeb504aSArd Biesheuvel } };
28153964b9eSJeff Garzik
sha3_generic_mod_init(void)28253964b9eSJeff Garzik static int __init sha3_generic_mod_init(void)
28353964b9eSJeff Garzik {
284beeb504aSArd Biesheuvel return crypto_register_shashes(algs, ARRAY_SIZE(algs));
28553964b9eSJeff Garzik }
28653964b9eSJeff Garzik
sha3_generic_mod_fini(void)28753964b9eSJeff Garzik static void __exit sha3_generic_mod_fini(void)
28853964b9eSJeff Garzik {
289beeb504aSArd Biesheuvel crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
29053964b9eSJeff Garzik }
29153964b9eSJeff Garzik
292c4741b23SEric Biggers subsys_initcall(sha3_generic_mod_init);
29353964b9eSJeff Garzik module_exit(sha3_generic_mod_fini);
29453964b9eSJeff Garzik
29553964b9eSJeff Garzik MODULE_LICENSE("GPL");
29653964b9eSJeff Garzik MODULE_DESCRIPTION("SHA-3 Secure Hash Algorithm");
29753964b9eSJeff Garzik
29853964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-224");
29953964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-224-generic");
30053964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-256");
30153964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-256-generic");
30253964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-384");
30353964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-384-generic");
30453964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-512");
30553964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-512-generic");
306