1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Cryptographic API.
4 *
5 * SHA1 Secure Hash Algorithm.
6 *
7 * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>.
8 *
9 * Based on crypto/sha1_generic.c, which is:
10 *
11 * Copyright (c) Alan Smithee.
12 * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
13 * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
14 */
15
16#include <linux/mm.h>
17#include <crypto/sha1.h>
18#include <crypto/sha1_base.h>
19#include <linux/init.h>
20#include <linux/types.h>
21#include <linux/module.h>
22#include <asm/byteorder.h>
23#include <asm/octeon/octeon.h>
24#include <crypto/internal/hash.h>
25
26#include "octeon-crypto.h"
27
28/*
29 * We pass everything as 64-bit. OCTEON can handle misaligned data.
30 */
31
32static void octeon_sha1_store_hash(struct sha1_state *sctx)
33{
34	u64 *hash = (u64 *)sctx->state;
35	union {
36		u32 word[2];
37		u64 dword;
38	} hash_tail = { { sctx->state[4], } };
39
40	write_octeon_64bit_hash_dword(hash[0], 0);
41	write_octeon_64bit_hash_dword(hash[1], 1);
42	write_octeon_64bit_hash_dword(hash_tail.dword, 2);
43	memzero_explicit(&hash_tail.word[0], sizeof(hash_tail.word[0]));
44}
45
46static void octeon_sha1_read_hash(struct sha1_state *sctx)
47{
48	u64 *hash = (u64 *)sctx->state;
49	union {
50		u32 word[2];
51		u64 dword;
52	} hash_tail;
53
54	hash[0]		= read_octeon_64bit_hash_dword(0);
55	hash[1]		= read_octeon_64bit_hash_dword(1);
56	hash_tail.dword	= read_octeon_64bit_hash_dword(2);
57	sctx->state[4]	= hash_tail.word[0];
58	memzero_explicit(&hash_tail.dword, sizeof(hash_tail.dword));
59}
60
61static void octeon_sha1_transform(const void *_block)
62{
63	const u64 *block = _block;
64
65	write_octeon_64bit_block_dword(block[0], 0);
66	write_octeon_64bit_block_dword(block[1], 1);
67	write_octeon_64bit_block_dword(block[2], 2);
68	write_octeon_64bit_block_dword(block[3], 3);
69	write_octeon_64bit_block_dword(block[4], 4);
70	write_octeon_64bit_block_dword(block[5], 5);
71	write_octeon_64bit_block_dword(block[6], 6);
72	octeon_sha1_start(block[7]);
73}
74
75static void __octeon_sha1_update(struct sha1_state *sctx, const u8 *data,
76				 unsigned int len)
77{
78	unsigned int partial;
79	unsigned int done;
80	const u8 *src;
81
82	partial = sctx->count % SHA1_BLOCK_SIZE;
83	sctx->count += len;
84	done = 0;
85	src = data;
86
87	if ((partial + len) >= SHA1_BLOCK_SIZE) {
88		if (partial) {
89			done = -partial;
90			memcpy(sctx->buffer + partial, data,
91			       done + SHA1_BLOCK_SIZE);
92			src = sctx->buffer;
93		}
94
95		do {
96			octeon_sha1_transform(src);
97			done += SHA1_BLOCK_SIZE;
98			src = data + done;
99		} while (done + SHA1_BLOCK_SIZE <= len);
100
101		partial = 0;
102	}
103	memcpy(sctx->buffer + partial, src, len - done);
104}
105
106static int octeon_sha1_update(struct shash_desc *desc, const u8 *data,
107			unsigned int len)
108{
109	struct sha1_state *sctx = shash_desc_ctx(desc);
110	struct octeon_cop2_state state;
111	unsigned long flags;
112
113	/*
114	 * Small updates never reach the crypto engine, so the generic sha1 is
115	 * faster because of the heavyweight octeon_crypto_enable() /
116	 * octeon_crypto_disable().
117	 */
118	if ((sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE)
119		return crypto_sha1_update(desc, data, len);
120
121	flags = octeon_crypto_enable(&state);
122	octeon_sha1_store_hash(sctx);
123
124	__octeon_sha1_update(sctx, data, len);
125
126	octeon_sha1_read_hash(sctx);
127	octeon_crypto_disable(&state, flags);
128
129	return 0;
130}
131
132static int octeon_sha1_final(struct shash_desc *desc, u8 *out)
133{
134	struct sha1_state *sctx = shash_desc_ctx(desc);
135	static const u8 padding[64] = { 0x80, };
136	struct octeon_cop2_state state;
137	__be32 *dst = (__be32 *)out;
138	unsigned int pad_len;
139	unsigned long flags;
140	unsigned int index;
141	__be64 bits;
142	int i;
143
144	/* Save number of bits. */
145	bits = cpu_to_be64(sctx->count << 3);
146
147	/* Pad out to 56 mod 64. */
148	index = sctx->count & 0x3f;
149	pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
150
151	flags = octeon_crypto_enable(&state);
152	octeon_sha1_store_hash(sctx);
153
154	__octeon_sha1_update(sctx, padding, pad_len);
155
156	/* Append length (before padding). */
157	__octeon_sha1_update(sctx, (const u8 *)&bits, sizeof(bits));
158
159	octeon_sha1_read_hash(sctx);
160	octeon_crypto_disable(&state, flags);
161
162	/* Store state in digest */
163	for (i = 0; i < 5; i++)
164		dst[i] = cpu_to_be32(sctx->state[i]);
165
166	/* Zeroize sensitive information. */
167	memset(sctx, 0, sizeof(*sctx));
168
169	return 0;
170}
171
172static int octeon_sha1_export(struct shash_desc *desc, void *out)
173{
174	struct sha1_state *sctx = shash_desc_ctx(desc);
175
176	memcpy(out, sctx, sizeof(*sctx));
177	return 0;
178}
179
180static int octeon_sha1_import(struct shash_desc *desc, const void *in)
181{
182	struct sha1_state *sctx = shash_desc_ctx(desc);
183
184	memcpy(sctx, in, sizeof(*sctx));
185	return 0;
186}
187
188static struct shash_alg octeon_sha1_alg = {
189	.digestsize	=	SHA1_DIGEST_SIZE,
190	.init		=	sha1_base_init,
191	.update		=	octeon_sha1_update,
192	.final		=	octeon_sha1_final,
193	.export		=	octeon_sha1_export,
194	.import		=	octeon_sha1_import,
195	.descsize	=	sizeof(struct sha1_state),
196	.statesize	=	sizeof(struct sha1_state),
197	.base		=	{
198		.cra_name	=	"sha1",
199		.cra_driver_name=	"octeon-sha1",
200		.cra_priority	=	OCTEON_CR_OPCODE_PRIORITY,
201		.cra_blocksize	=	SHA1_BLOCK_SIZE,
202		.cra_module	=	THIS_MODULE,
203	}
204};
205
206static int __init octeon_sha1_mod_init(void)
207{
208	if (!octeon_has_crypto())
209		return -ENOTSUPP;
210	return crypto_register_shash(&octeon_sha1_alg);
211}
212
213static void __exit octeon_sha1_mod_fini(void)
214{
215	crypto_unregister_shash(&octeon_sha1_alg);
216}
217
218module_init(octeon_sha1_mod_init);
219module_exit(octeon_sha1_mod_fini);
220
221MODULE_LICENSE("GPL");
222MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (OCTEON)");
223MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
224