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