xref: /linux/crypto/sha3_generic.c (revision c013cee9)
153964b9eSJeff Garzik /*
253964b9eSJeff Garzik  * Cryptographic API.
353964b9eSJeff Garzik  *
453964b9eSJeff Garzik  * SHA-3, as specified in
553964b9eSJeff Garzik  * http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
653964b9eSJeff Garzik  *
753964b9eSJeff Garzik  * SHA-3 code by Jeff Garzik <jeff@garzik.org>
853964b9eSJeff Garzik  *
953964b9eSJeff Garzik  * This program is free software; you can redistribute it and/or modify it
1053964b9eSJeff Garzik  * under the terms of the GNU General Public License as published by the Free
1153964b9eSJeff Garzik  * Software Foundation; either version 2 of the License, or (at your option)•
1253964b9eSJeff Garzik  * any later version.
1353964b9eSJeff Garzik  *
1453964b9eSJeff Garzik  */
1553964b9eSJeff Garzik #include <crypto/internal/hash.h>
1653964b9eSJeff Garzik #include <linux/init.h>
1753964b9eSJeff Garzik #include <linux/module.h>
1853964b9eSJeff Garzik #include <linux/types.h>
1953964b9eSJeff Garzik #include <crypto/sha3.h>
2053964b9eSJeff Garzik #include <asm/byteorder.h>
21*c013cee9SArd Biesheuvel #include <asm/unaligned.h>
2253964b9eSJeff Garzik 
2353964b9eSJeff Garzik #define KECCAK_ROUNDS 24
2453964b9eSJeff Garzik 
2553964b9eSJeff Garzik #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
2653964b9eSJeff Garzik 
2753964b9eSJeff Garzik static const u64 keccakf_rndc[24] = {
28f743e70eSGeert Uytterhoeven 	0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
29f743e70eSGeert Uytterhoeven 	0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
30f743e70eSGeert Uytterhoeven 	0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
31f743e70eSGeert Uytterhoeven 	0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
32f743e70eSGeert Uytterhoeven 	0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
33f743e70eSGeert Uytterhoeven 	0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
34f743e70eSGeert Uytterhoeven 	0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
35f743e70eSGeert Uytterhoeven 	0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
3653964b9eSJeff Garzik };
3753964b9eSJeff Garzik 
3853964b9eSJeff Garzik static const int keccakf_rotc[24] = {
3953964b9eSJeff Garzik 	1,  3,  6,  10, 15, 21, 28, 36, 45, 55, 2,  14,
4053964b9eSJeff Garzik 	27, 41, 56, 8,  25, 43, 62, 18, 39, 61, 20, 44
4153964b9eSJeff Garzik };
4253964b9eSJeff Garzik 
4353964b9eSJeff Garzik static const int keccakf_piln[24] = {
4453964b9eSJeff Garzik 	10, 7,  11, 17, 18, 3, 5,  16, 8,  21, 24, 4,
4553964b9eSJeff Garzik 	15, 23, 19, 13, 12, 2, 20, 14, 22, 9,  6,  1
4653964b9eSJeff Garzik };
4753964b9eSJeff Garzik 
4853964b9eSJeff Garzik /* update the state with given number of rounds */
4953964b9eSJeff Garzik 
5053964b9eSJeff Garzik static void keccakf(u64 st[25])
5153964b9eSJeff Garzik {
5253964b9eSJeff Garzik 	int i, j, round;
5353964b9eSJeff Garzik 	u64 t, bc[5];
5453964b9eSJeff Garzik 
5553964b9eSJeff Garzik 	for (round = 0; round < KECCAK_ROUNDS; round++) {
5653964b9eSJeff Garzik 
5753964b9eSJeff Garzik 		/* Theta */
5853964b9eSJeff Garzik 		for (i = 0; i < 5; i++)
5953964b9eSJeff Garzik 			bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15]
6053964b9eSJeff Garzik 				^ st[i + 20];
6153964b9eSJeff Garzik 
6253964b9eSJeff Garzik 		for (i = 0; i < 5; i++) {
6353964b9eSJeff Garzik 			t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
6453964b9eSJeff Garzik 			for (j = 0; j < 25; j += 5)
6553964b9eSJeff Garzik 				st[j + i] ^= t;
6653964b9eSJeff Garzik 		}
6753964b9eSJeff Garzik 
6853964b9eSJeff Garzik 		/* Rho Pi */
6953964b9eSJeff Garzik 		t = st[1];
7053964b9eSJeff Garzik 		for (i = 0; i < 24; i++) {
7153964b9eSJeff Garzik 			j = keccakf_piln[i];
7253964b9eSJeff Garzik 			bc[0] = st[j];
7353964b9eSJeff Garzik 			st[j] = ROTL64(t, keccakf_rotc[i]);
7453964b9eSJeff Garzik 			t = bc[0];
7553964b9eSJeff Garzik 		}
7653964b9eSJeff Garzik 
7753964b9eSJeff Garzik 		/* Chi */
7853964b9eSJeff Garzik 		for (j = 0; j < 25; j += 5) {
7953964b9eSJeff Garzik 			for (i = 0; i < 5; i++)
8053964b9eSJeff Garzik 				bc[i] = st[j + i];
8153964b9eSJeff Garzik 			for (i = 0; i < 5; i++)
8253964b9eSJeff Garzik 				st[j + i] ^= (~bc[(i + 1) % 5]) &
8353964b9eSJeff Garzik 					     bc[(i + 2) % 5];
8453964b9eSJeff Garzik 		}
8553964b9eSJeff Garzik 
8653964b9eSJeff Garzik 		/* Iota */
8753964b9eSJeff Garzik 		st[0] ^= keccakf_rndc[round];
8853964b9eSJeff Garzik 	}
8953964b9eSJeff Garzik }
9053964b9eSJeff Garzik 
9153964b9eSJeff Garzik static void sha3_init(struct sha3_state *sctx, unsigned int digest_sz)
9253964b9eSJeff Garzik {
9353964b9eSJeff Garzik 	memset(sctx, 0, sizeof(*sctx));
9453964b9eSJeff Garzik 	sctx->md_len = digest_sz;
9553964b9eSJeff Garzik 	sctx->rsiz = 200 - 2 * digest_sz;
9653964b9eSJeff Garzik 	sctx->rsizw = sctx->rsiz / 8;
9753964b9eSJeff Garzik }
9853964b9eSJeff Garzik 
9953964b9eSJeff Garzik static int sha3_224_init(struct shash_desc *desc)
10053964b9eSJeff Garzik {
10153964b9eSJeff Garzik 	struct sha3_state *sctx = shash_desc_ctx(desc);
10253964b9eSJeff Garzik 
10353964b9eSJeff Garzik 	sha3_init(sctx, SHA3_224_DIGEST_SIZE);
10453964b9eSJeff Garzik 	return 0;
10553964b9eSJeff Garzik }
10653964b9eSJeff Garzik 
10753964b9eSJeff Garzik static int sha3_256_init(struct shash_desc *desc)
10853964b9eSJeff Garzik {
10953964b9eSJeff Garzik 	struct sha3_state *sctx = shash_desc_ctx(desc);
11053964b9eSJeff Garzik 
11153964b9eSJeff Garzik 	sha3_init(sctx, SHA3_256_DIGEST_SIZE);
11253964b9eSJeff Garzik 	return 0;
11353964b9eSJeff Garzik }
11453964b9eSJeff Garzik 
11553964b9eSJeff Garzik static int sha3_384_init(struct shash_desc *desc)
11653964b9eSJeff Garzik {
11753964b9eSJeff Garzik 	struct sha3_state *sctx = shash_desc_ctx(desc);
11853964b9eSJeff Garzik 
11953964b9eSJeff Garzik 	sha3_init(sctx, SHA3_384_DIGEST_SIZE);
12053964b9eSJeff Garzik 	return 0;
12153964b9eSJeff Garzik }
12253964b9eSJeff Garzik 
12353964b9eSJeff Garzik static int sha3_512_init(struct shash_desc *desc)
12453964b9eSJeff Garzik {
12553964b9eSJeff Garzik 	struct sha3_state *sctx = shash_desc_ctx(desc);
12653964b9eSJeff Garzik 
12753964b9eSJeff Garzik 	sha3_init(sctx, SHA3_512_DIGEST_SIZE);
12853964b9eSJeff Garzik 	return 0;
12953964b9eSJeff Garzik }
13053964b9eSJeff Garzik 
13153964b9eSJeff Garzik static int sha3_update(struct shash_desc *desc, const u8 *data,
13253964b9eSJeff Garzik 		       unsigned int len)
13353964b9eSJeff Garzik {
13453964b9eSJeff Garzik 	struct sha3_state *sctx = shash_desc_ctx(desc);
13553964b9eSJeff Garzik 	unsigned int done;
13653964b9eSJeff Garzik 	const u8 *src;
13753964b9eSJeff Garzik 
13853964b9eSJeff Garzik 	done = 0;
13953964b9eSJeff Garzik 	src = data;
14053964b9eSJeff Garzik 
14153964b9eSJeff Garzik 	if ((sctx->partial + len) > (sctx->rsiz - 1)) {
14253964b9eSJeff Garzik 		if (sctx->partial) {
14353964b9eSJeff Garzik 			done = -sctx->partial;
14453964b9eSJeff Garzik 			memcpy(sctx->buf + sctx->partial, data,
14553964b9eSJeff Garzik 			       done + sctx->rsiz);
14653964b9eSJeff Garzik 			src = sctx->buf;
14753964b9eSJeff Garzik 		}
14853964b9eSJeff Garzik 
14953964b9eSJeff Garzik 		do {
15053964b9eSJeff Garzik 			unsigned int i;
15153964b9eSJeff Garzik 
15253964b9eSJeff Garzik 			for (i = 0; i < sctx->rsizw; i++)
153*c013cee9SArd Biesheuvel 				sctx->st[i] ^= get_unaligned_le64(src + 8 * i);
15453964b9eSJeff Garzik 			keccakf(sctx->st);
15553964b9eSJeff Garzik 
15653964b9eSJeff Garzik 			done += sctx->rsiz;
15753964b9eSJeff Garzik 			src = data + done;
15853964b9eSJeff Garzik 		} while (done + (sctx->rsiz - 1) < len);
15953964b9eSJeff Garzik 
16053964b9eSJeff Garzik 		sctx->partial = 0;
16153964b9eSJeff Garzik 	}
16253964b9eSJeff Garzik 	memcpy(sctx->buf + sctx->partial, src, len - done);
16353964b9eSJeff Garzik 	sctx->partial += (len - done);
16453964b9eSJeff Garzik 
16553964b9eSJeff Garzik 	return 0;
16653964b9eSJeff Garzik }
16753964b9eSJeff Garzik 
16853964b9eSJeff Garzik static int sha3_final(struct shash_desc *desc, u8 *out)
16953964b9eSJeff Garzik {
17053964b9eSJeff Garzik 	struct sha3_state *sctx = shash_desc_ctx(desc);
17153964b9eSJeff Garzik 	unsigned int i, inlen = sctx->partial;
17253964b9eSJeff Garzik 
17353964b9eSJeff Garzik 	sctx->buf[inlen++] = 0x06;
17453964b9eSJeff Garzik 	memset(sctx->buf + inlen, 0, sctx->rsiz - inlen);
17553964b9eSJeff Garzik 	sctx->buf[sctx->rsiz - 1] |= 0x80;
17653964b9eSJeff Garzik 
17753964b9eSJeff Garzik 	for (i = 0; i < sctx->rsizw; i++)
178*c013cee9SArd Biesheuvel 		sctx->st[i] ^= get_unaligned_le64(sctx->buf + 8 * i);
17953964b9eSJeff Garzik 
18053964b9eSJeff Garzik 	keccakf(sctx->st);
18153964b9eSJeff Garzik 
18253964b9eSJeff Garzik 	for (i = 0; i < sctx->rsizw; i++)
18353964b9eSJeff Garzik 		sctx->st[i] = cpu_to_le64(sctx->st[i]);
18453964b9eSJeff Garzik 
18553964b9eSJeff Garzik 	memcpy(out, sctx->st, sctx->md_len);
18653964b9eSJeff Garzik 
18753964b9eSJeff Garzik 	memset(sctx, 0, sizeof(*sctx));
18853964b9eSJeff Garzik 	return 0;
18953964b9eSJeff Garzik }
19053964b9eSJeff Garzik 
19153964b9eSJeff Garzik static struct shash_alg sha3_224 = {
19253964b9eSJeff Garzik 	.digestsize	=	SHA3_224_DIGEST_SIZE,
19353964b9eSJeff Garzik 	.init		=	sha3_224_init,
19453964b9eSJeff Garzik 	.update		=	sha3_update,
19553964b9eSJeff Garzik 	.final		=	sha3_final,
19653964b9eSJeff Garzik 	.descsize	=	sizeof(struct sha3_state),
19753964b9eSJeff Garzik 	.base		=	{
19853964b9eSJeff Garzik 		.cra_name	=	"sha3-224",
19953964b9eSJeff Garzik 		.cra_driver_name =	"sha3-224-generic",
20053964b9eSJeff Garzik 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
20153964b9eSJeff Garzik 		.cra_blocksize	=	SHA3_224_BLOCK_SIZE,
20253964b9eSJeff Garzik 		.cra_module	=	THIS_MODULE,
20353964b9eSJeff Garzik 	}
20453964b9eSJeff Garzik };
20553964b9eSJeff Garzik 
20653964b9eSJeff Garzik static struct shash_alg sha3_256 = {
20753964b9eSJeff Garzik 	.digestsize	=	SHA3_256_DIGEST_SIZE,
20853964b9eSJeff Garzik 	.init		=	sha3_256_init,
20953964b9eSJeff Garzik 	.update		=	sha3_update,
21053964b9eSJeff Garzik 	.final		=	sha3_final,
21153964b9eSJeff Garzik 	.descsize	=	sizeof(struct sha3_state),
21253964b9eSJeff Garzik 	.base		=	{
21353964b9eSJeff Garzik 		.cra_name	=	"sha3-256",
21453964b9eSJeff Garzik 		.cra_driver_name =	"sha3-256-generic",
21553964b9eSJeff Garzik 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
21653964b9eSJeff Garzik 		.cra_blocksize	=	SHA3_256_BLOCK_SIZE,
21753964b9eSJeff Garzik 		.cra_module	=	THIS_MODULE,
21853964b9eSJeff Garzik 	}
21953964b9eSJeff Garzik };
22053964b9eSJeff Garzik 
22153964b9eSJeff Garzik static struct shash_alg sha3_384 = {
22253964b9eSJeff Garzik 	.digestsize	=	SHA3_384_DIGEST_SIZE,
22353964b9eSJeff Garzik 	.init		=	sha3_384_init,
22453964b9eSJeff Garzik 	.update		=	sha3_update,
22553964b9eSJeff Garzik 	.final		=	sha3_final,
22653964b9eSJeff Garzik 	.descsize	=	sizeof(struct sha3_state),
22753964b9eSJeff Garzik 	.base		=	{
22853964b9eSJeff Garzik 		.cra_name	=	"sha3-384",
22953964b9eSJeff Garzik 		.cra_driver_name =	"sha3-384-generic",
23053964b9eSJeff Garzik 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
23153964b9eSJeff Garzik 		.cra_blocksize	=	SHA3_384_BLOCK_SIZE,
23253964b9eSJeff Garzik 		.cra_module	=	THIS_MODULE,
23353964b9eSJeff Garzik 	}
23453964b9eSJeff Garzik };
23553964b9eSJeff Garzik 
23653964b9eSJeff Garzik static struct shash_alg sha3_512 = {
23753964b9eSJeff Garzik 	.digestsize	=	SHA3_512_DIGEST_SIZE,
23853964b9eSJeff Garzik 	.init		=	sha3_512_init,
23953964b9eSJeff Garzik 	.update		=	sha3_update,
24053964b9eSJeff Garzik 	.final		=	sha3_final,
24153964b9eSJeff Garzik 	.descsize	=	sizeof(struct sha3_state),
24253964b9eSJeff Garzik 	.base		=	{
24353964b9eSJeff Garzik 		.cra_name	=	"sha3-512",
24453964b9eSJeff Garzik 		.cra_driver_name =	"sha3-512-generic",
24553964b9eSJeff Garzik 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
24653964b9eSJeff Garzik 		.cra_blocksize	=	SHA3_512_BLOCK_SIZE,
24753964b9eSJeff Garzik 		.cra_module	=	THIS_MODULE,
24853964b9eSJeff Garzik 	}
24953964b9eSJeff Garzik };
25053964b9eSJeff Garzik 
25153964b9eSJeff Garzik static int __init sha3_generic_mod_init(void)
25253964b9eSJeff Garzik {
25353964b9eSJeff Garzik 	int ret;
25453964b9eSJeff Garzik 
25553964b9eSJeff Garzik 	ret = crypto_register_shash(&sha3_224);
25653964b9eSJeff Garzik 	if (ret < 0)
25753964b9eSJeff Garzik 		goto err_out;
25853964b9eSJeff Garzik 	ret = crypto_register_shash(&sha3_256);
25953964b9eSJeff Garzik 	if (ret < 0)
26053964b9eSJeff Garzik 		goto err_out_224;
26153964b9eSJeff Garzik 	ret = crypto_register_shash(&sha3_384);
26253964b9eSJeff Garzik 	if (ret < 0)
26353964b9eSJeff Garzik 		goto err_out_256;
26453964b9eSJeff Garzik 	ret = crypto_register_shash(&sha3_512);
26553964b9eSJeff Garzik 	if (ret < 0)
26653964b9eSJeff Garzik 		goto err_out_384;
26753964b9eSJeff Garzik 
26853964b9eSJeff Garzik 	return 0;
26953964b9eSJeff Garzik 
27053964b9eSJeff Garzik err_out_384:
27153964b9eSJeff Garzik 	crypto_unregister_shash(&sha3_384);
27253964b9eSJeff Garzik err_out_256:
27353964b9eSJeff Garzik 	crypto_unregister_shash(&sha3_256);
27453964b9eSJeff Garzik err_out_224:
27553964b9eSJeff Garzik 	crypto_unregister_shash(&sha3_224);
27653964b9eSJeff Garzik err_out:
27753964b9eSJeff Garzik 	return ret;
27853964b9eSJeff Garzik }
27953964b9eSJeff Garzik 
28053964b9eSJeff Garzik static void __exit sha3_generic_mod_fini(void)
28153964b9eSJeff Garzik {
28253964b9eSJeff Garzik 	crypto_unregister_shash(&sha3_224);
28353964b9eSJeff Garzik 	crypto_unregister_shash(&sha3_256);
28453964b9eSJeff Garzik 	crypto_unregister_shash(&sha3_384);
28553964b9eSJeff Garzik 	crypto_unregister_shash(&sha3_512);
28653964b9eSJeff Garzik }
28753964b9eSJeff Garzik 
28853964b9eSJeff Garzik module_init(sha3_generic_mod_init);
28953964b9eSJeff Garzik module_exit(sha3_generic_mod_fini);
29053964b9eSJeff Garzik 
29153964b9eSJeff Garzik MODULE_LICENSE("GPL");
29253964b9eSJeff Garzik MODULE_DESCRIPTION("SHA-3 Secure Hash Algorithm");
29353964b9eSJeff Garzik 
29453964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-224");
29553964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-224-generic");
29653964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-256");
29753964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-256-generic");
29853964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-384");
29953964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-384-generic");
30053964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-512");
30153964b9eSJeff Garzik MODULE_ALIAS_CRYPTO("sha3-512-generic");
302