xref: /linux/arch/mips/cavium-octeon/crypto/octeon-sha1.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
282be2dcfSAaro Koskinen /*
382be2dcfSAaro Koskinen  * Cryptographic API.
482be2dcfSAaro Koskinen  *
582be2dcfSAaro Koskinen  * SHA1 Secure Hash Algorithm.
682be2dcfSAaro Koskinen  *
782be2dcfSAaro Koskinen  * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>.
882be2dcfSAaro Koskinen  *
982be2dcfSAaro Koskinen  * Based on crypto/sha1_generic.c, which is:
1082be2dcfSAaro Koskinen  *
1182be2dcfSAaro Koskinen  * Copyright (c) Alan Smithee.
1282be2dcfSAaro Koskinen  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
1382be2dcfSAaro Koskinen  * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
1482be2dcfSAaro Koskinen  */
1582be2dcfSAaro Koskinen 
1682be2dcfSAaro Koskinen #include <linux/mm.h>
17a24d22b2SEric Biggers #include <crypto/sha1.h>
18*63bdbfc1STianjia Zhang #include <crypto/sha1_base.h>
1982be2dcfSAaro Koskinen #include <linux/init.h>
2082be2dcfSAaro Koskinen #include <linux/types.h>
2182be2dcfSAaro Koskinen #include <linux/module.h>
2282be2dcfSAaro Koskinen #include <asm/byteorder.h>
2382be2dcfSAaro Koskinen #include <asm/octeon/octeon.h>
2482be2dcfSAaro Koskinen #include <crypto/internal/hash.h>
2582be2dcfSAaro Koskinen 
2682be2dcfSAaro Koskinen #include "octeon-crypto.h"
2782be2dcfSAaro Koskinen 
2882be2dcfSAaro Koskinen /*
2982be2dcfSAaro Koskinen  * We pass everything as 64-bit. OCTEON can handle misaligned data.
3082be2dcfSAaro Koskinen  */
3182be2dcfSAaro Koskinen 
octeon_sha1_store_hash(struct sha1_state * sctx)3282be2dcfSAaro Koskinen static void octeon_sha1_store_hash(struct sha1_state *sctx)
3382be2dcfSAaro Koskinen {
3482be2dcfSAaro Koskinen 	u64 *hash = (u64 *)sctx->state;
3582be2dcfSAaro Koskinen 	union {
3682be2dcfSAaro Koskinen 		u32 word[2];
3782be2dcfSAaro Koskinen 		u64 dword;
3882be2dcfSAaro Koskinen 	} hash_tail = { { sctx->state[4], } };
3982be2dcfSAaro Koskinen 
4082be2dcfSAaro Koskinen 	write_octeon_64bit_hash_dword(hash[0], 0);
4182be2dcfSAaro Koskinen 	write_octeon_64bit_hash_dword(hash[1], 1);
4282be2dcfSAaro Koskinen 	write_octeon_64bit_hash_dword(hash_tail.dword, 2);
4382be2dcfSAaro Koskinen 	memzero_explicit(&hash_tail.word[0], sizeof(hash_tail.word[0]));
4482be2dcfSAaro Koskinen }
4582be2dcfSAaro Koskinen 
octeon_sha1_read_hash(struct sha1_state * sctx)4682be2dcfSAaro Koskinen static void octeon_sha1_read_hash(struct sha1_state *sctx)
4782be2dcfSAaro Koskinen {
4882be2dcfSAaro Koskinen 	u64 *hash = (u64 *)sctx->state;
4982be2dcfSAaro Koskinen 	union {
5082be2dcfSAaro Koskinen 		u32 word[2];
5182be2dcfSAaro Koskinen 		u64 dword;
5282be2dcfSAaro Koskinen 	} hash_tail;
5382be2dcfSAaro Koskinen 
5482be2dcfSAaro Koskinen 	hash[0]		= read_octeon_64bit_hash_dword(0);
5582be2dcfSAaro Koskinen 	hash[1]		= read_octeon_64bit_hash_dword(1);
5682be2dcfSAaro Koskinen 	hash_tail.dword	= read_octeon_64bit_hash_dword(2);
5782be2dcfSAaro Koskinen 	sctx->state[4]	= hash_tail.word[0];
5882be2dcfSAaro Koskinen 	memzero_explicit(&hash_tail.dword, sizeof(hash_tail.dword));
5982be2dcfSAaro Koskinen }
6082be2dcfSAaro Koskinen 
octeon_sha1_transform(const void * _block)6182be2dcfSAaro Koskinen static void octeon_sha1_transform(const void *_block)
6282be2dcfSAaro Koskinen {
6382be2dcfSAaro Koskinen 	const u64 *block = _block;
6482be2dcfSAaro Koskinen 
6582be2dcfSAaro Koskinen 	write_octeon_64bit_block_dword(block[0], 0);
6682be2dcfSAaro Koskinen 	write_octeon_64bit_block_dword(block[1], 1);
6782be2dcfSAaro Koskinen 	write_octeon_64bit_block_dword(block[2], 2);
6882be2dcfSAaro Koskinen 	write_octeon_64bit_block_dword(block[3], 3);
6982be2dcfSAaro Koskinen 	write_octeon_64bit_block_dword(block[4], 4);
7082be2dcfSAaro Koskinen 	write_octeon_64bit_block_dword(block[5], 5);
7182be2dcfSAaro Koskinen 	write_octeon_64bit_block_dword(block[6], 6);
7282be2dcfSAaro Koskinen 	octeon_sha1_start(block[7]);
7382be2dcfSAaro Koskinen }
7482be2dcfSAaro Koskinen 
__octeon_sha1_update(struct sha1_state * sctx,const u8 * data,unsigned int len)7582be2dcfSAaro Koskinen static void __octeon_sha1_update(struct sha1_state *sctx, const u8 *data,
7682be2dcfSAaro Koskinen 				 unsigned int len)
7782be2dcfSAaro Koskinen {
7882be2dcfSAaro Koskinen 	unsigned int partial;
7982be2dcfSAaro Koskinen 	unsigned int done;
8082be2dcfSAaro Koskinen 	const u8 *src;
8182be2dcfSAaro Koskinen 
8282be2dcfSAaro Koskinen 	partial = sctx->count % SHA1_BLOCK_SIZE;
8382be2dcfSAaro Koskinen 	sctx->count += len;
8482be2dcfSAaro Koskinen 	done = 0;
8582be2dcfSAaro Koskinen 	src = data;
8682be2dcfSAaro Koskinen 
8782be2dcfSAaro Koskinen 	if ((partial + len) >= SHA1_BLOCK_SIZE) {
8882be2dcfSAaro Koskinen 		if (partial) {
8982be2dcfSAaro Koskinen 			done = -partial;
9082be2dcfSAaro Koskinen 			memcpy(sctx->buffer + partial, data,
9182be2dcfSAaro Koskinen 			       done + SHA1_BLOCK_SIZE);
9282be2dcfSAaro Koskinen 			src = sctx->buffer;
9382be2dcfSAaro Koskinen 		}
9482be2dcfSAaro Koskinen 
9582be2dcfSAaro Koskinen 		do {
9682be2dcfSAaro Koskinen 			octeon_sha1_transform(src);
9782be2dcfSAaro Koskinen 			done += SHA1_BLOCK_SIZE;
9882be2dcfSAaro Koskinen 			src = data + done;
9982be2dcfSAaro Koskinen 		} while (done + SHA1_BLOCK_SIZE <= len);
10082be2dcfSAaro Koskinen 
10182be2dcfSAaro Koskinen 		partial = 0;
10282be2dcfSAaro Koskinen 	}
10382be2dcfSAaro Koskinen 	memcpy(sctx->buffer + partial, src, len - done);
10482be2dcfSAaro Koskinen }
10582be2dcfSAaro Koskinen 
octeon_sha1_update(struct shash_desc * desc,const u8 * data,unsigned int len)10682be2dcfSAaro Koskinen static int octeon_sha1_update(struct shash_desc *desc, const u8 *data,
10782be2dcfSAaro Koskinen 			unsigned int len)
10882be2dcfSAaro Koskinen {
10982be2dcfSAaro Koskinen 	struct sha1_state *sctx = shash_desc_ctx(desc);
11082be2dcfSAaro Koskinen 	struct octeon_cop2_state state;
11182be2dcfSAaro Koskinen 	unsigned long flags;
11282be2dcfSAaro Koskinen 
11382be2dcfSAaro Koskinen 	/*
11482be2dcfSAaro Koskinen 	 * Small updates never reach the crypto engine, so the generic sha1 is
11582be2dcfSAaro Koskinen 	 * faster because of the heavyweight octeon_crypto_enable() /
11682be2dcfSAaro Koskinen 	 * octeon_crypto_disable().
11782be2dcfSAaro Koskinen 	 */
11882be2dcfSAaro Koskinen 	if ((sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE)
11982be2dcfSAaro Koskinen 		return crypto_sha1_update(desc, data, len);
12082be2dcfSAaro Koskinen 
12182be2dcfSAaro Koskinen 	flags = octeon_crypto_enable(&state);
12282be2dcfSAaro Koskinen 	octeon_sha1_store_hash(sctx);
12382be2dcfSAaro Koskinen 
12482be2dcfSAaro Koskinen 	__octeon_sha1_update(sctx, data, len);
12582be2dcfSAaro Koskinen 
12682be2dcfSAaro Koskinen 	octeon_sha1_read_hash(sctx);
12782be2dcfSAaro Koskinen 	octeon_crypto_disable(&state, flags);
12882be2dcfSAaro Koskinen 
12982be2dcfSAaro Koskinen 	return 0;
13082be2dcfSAaro Koskinen }
13182be2dcfSAaro Koskinen 
octeon_sha1_final(struct shash_desc * desc,u8 * out)13282be2dcfSAaro Koskinen static int octeon_sha1_final(struct shash_desc *desc, u8 *out)
13382be2dcfSAaro Koskinen {
13482be2dcfSAaro Koskinen 	struct sha1_state *sctx = shash_desc_ctx(desc);
13582be2dcfSAaro Koskinen 	static const u8 padding[64] = { 0x80, };
13682be2dcfSAaro Koskinen 	struct octeon_cop2_state state;
13782be2dcfSAaro Koskinen 	__be32 *dst = (__be32 *)out;
13882be2dcfSAaro Koskinen 	unsigned int pad_len;
13982be2dcfSAaro Koskinen 	unsigned long flags;
14082be2dcfSAaro Koskinen 	unsigned int index;
14182be2dcfSAaro Koskinen 	__be64 bits;
14282be2dcfSAaro Koskinen 	int i;
14382be2dcfSAaro Koskinen 
14482be2dcfSAaro Koskinen 	/* Save number of bits. */
14582be2dcfSAaro Koskinen 	bits = cpu_to_be64(sctx->count << 3);
14682be2dcfSAaro Koskinen 
14782be2dcfSAaro Koskinen 	/* Pad out to 56 mod 64. */
14882be2dcfSAaro Koskinen 	index = sctx->count & 0x3f;
14982be2dcfSAaro Koskinen 	pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
15082be2dcfSAaro Koskinen 
15182be2dcfSAaro Koskinen 	flags = octeon_crypto_enable(&state);
15282be2dcfSAaro Koskinen 	octeon_sha1_store_hash(sctx);
15382be2dcfSAaro Koskinen 
15482be2dcfSAaro Koskinen 	__octeon_sha1_update(sctx, padding, pad_len);
15582be2dcfSAaro Koskinen 
15682be2dcfSAaro Koskinen 	/* Append length (before padding). */
15782be2dcfSAaro Koskinen 	__octeon_sha1_update(sctx, (const u8 *)&bits, sizeof(bits));
15882be2dcfSAaro Koskinen 
15982be2dcfSAaro Koskinen 	octeon_sha1_read_hash(sctx);
16082be2dcfSAaro Koskinen 	octeon_crypto_disable(&state, flags);
16182be2dcfSAaro Koskinen 
16282be2dcfSAaro Koskinen 	/* Store state in digest */
16382be2dcfSAaro Koskinen 	for (i = 0; i < 5; i++)
16482be2dcfSAaro Koskinen 		dst[i] = cpu_to_be32(sctx->state[i]);
16582be2dcfSAaro Koskinen 
16682be2dcfSAaro Koskinen 	/* Zeroize sensitive information. */
16782be2dcfSAaro Koskinen 	memset(sctx, 0, sizeof(*sctx));
16882be2dcfSAaro Koskinen 
16982be2dcfSAaro Koskinen 	return 0;
17082be2dcfSAaro Koskinen }
17182be2dcfSAaro Koskinen 
octeon_sha1_export(struct shash_desc * desc,void * out)17282be2dcfSAaro Koskinen static int octeon_sha1_export(struct shash_desc *desc, void *out)
17382be2dcfSAaro Koskinen {
17482be2dcfSAaro Koskinen 	struct sha1_state *sctx = shash_desc_ctx(desc);
17582be2dcfSAaro Koskinen 
17682be2dcfSAaro Koskinen 	memcpy(out, sctx, sizeof(*sctx));
17782be2dcfSAaro Koskinen 	return 0;
17882be2dcfSAaro Koskinen }
17982be2dcfSAaro Koskinen 
octeon_sha1_import(struct shash_desc * desc,const void * in)18082be2dcfSAaro Koskinen static int octeon_sha1_import(struct shash_desc *desc, const void *in)
18182be2dcfSAaro Koskinen {
18282be2dcfSAaro Koskinen 	struct sha1_state *sctx = shash_desc_ctx(desc);
18382be2dcfSAaro Koskinen 
18482be2dcfSAaro Koskinen 	memcpy(sctx, in, sizeof(*sctx));
18582be2dcfSAaro Koskinen 	return 0;
18682be2dcfSAaro Koskinen }
18782be2dcfSAaro Koskinen 
18882be2dcfSAaro Koskinen static struct shash_alg octeon_sha1_alg = {
18982be2dcfSAaro Koskinen 	.digestsize	=	SHA1_DIGEST_SIZE,
190*63bdbfc1STianjia Zhang 	.init		=	sha1_base_init,
19182be2dcfSAaro Koskinen 	.update		=	octeon_sha1_update,
19282be2dcfSAaro Koskinen 	.final		=	octeon_sha1_final,
19382be2dcfSAaro Koskinen 	.export		=	octeon_sha1_export,
19482be2dcfSAaro Koskinen 	.import		=	octeon_sha1_import,
19582be2dcfSAaro Koskinen 	.descsize	=	sizeof(struct sha1_state),
19682be2dcfSAaro Koskinen 	.statesize	=	sizeof(struct sha1_state),
19782be2dcfSAaro Koskinen 	.base		=	{
19882be2dcfSAaro Koskinen 		.cra_name	=	"sha1",
19982be2dcfSAaro Koskinen 		.cra_driver_name=	"octeon-sha1",
20082be2dcfSAaro Koskinen 		.cra_priority	=	OCTEON_CR_OPCODE_PRIORITY,
20182be2dcfSAaro Koskinen 		.cra_blocksize	=	SHA1_BLOCK_SIZE,
20282be2dcfSAaro Koskinen 		.cra_module	=	THIS_MODULE,
20382be2dcfSAaro Koskinen 	}
20482be2dcfSAaro Koskinen };
20582be2dcfSAaro Koskinen 
octeon_sha1_mod_init(void)20682be2dcfSAaro Koskinen static int __init octeon_sha1_mod_init(void)
20782be2dcfSAaro Koskinen {
20882be2dcfSAaro Koskinen 	if (!octeon_has_crypto())
20982be2dcfSAaro Koskinen 		return -ENOTSUPP;
21082be2dcfSAaro Koskinen 	return crypto_register_shash(&octeon_sha1_alg);
21182be2dcfSAaro Koskinen }
21282be2dcfSAaro Koskinen 
octeon_sha1_mod_fini(void)21382be2dcfSAaro Koskinen static void __exit octeon_sha1_mod_fini(void)
21482be2dcfSAaro Koskinen {
21582be2dcfSAaro Koskinen 	crypto_unregister_shash(&octeon_sha1_alg);
21682be2dcfSAaro Koskinen }
21782be2dcfSAaro Koskinen 
21882be2dcfSAaro Koskinen module_init(octeon_sha1_mod_init);
21982be2dcfSAaro Koskinen module_exit(octeon_sha1_mod_fini);
22082be2dcfSAaro Koskinen 
22182be2dcfSAaro Koskinen MODULE_LICENSE("GPL");
22282be2dcfSAaro Koskinen MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (OCTEON)");
22382be2dcfSAaro Koskinen MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
224