Blame view

crypto/sha3_generic.c 8.03 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
2
3
4
5
  /*
   * Cryptographic API.
   *
   * SHA-3, as specified in
9332a9e73   Alexander A. Klimov   crypto: Replace H...
6
   * https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
7
8
   *
   * SHA-3 code by Jeff Garzik <jeff@garzik.org>
83dee2ce1   Ard Biesheuvel   crypto: sha3-gene...
9
   *               Ard Biesheuvel <ard.biesheuvel@linaro.org>
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
10
11
12
13
14
15
   */
  #include <crypto/internal/hash.h>
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/types.h>
  #include <crypto/sha3.h>
c013cee99   Ard Biesheuvel   crypto: sha3-gene...
16
  #include <asm/unaligned.h>
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
17

4767b9ad7   Ard Biesheuvel   crypto: sha3-gene...
18
  /*
739d875dd   David Howells   mn10300: Remove t...
19
   * On some 32-bit architectures (h8300), GCC ends up using
4767b9ad7   Ard Biesheuvel   crypto: sha3-gene...
20
21
22
23
24
25
26
27
28
29
30
   * over 1 KB of stack if we inline the round calculation into the loop
   * in keccakf(). On the other hand, on 64-bit architectures with plenty
   * of [64-bit wide] general purpose registers, not inlining it severely
   * hurts performance. So let's use 64-bitness as a heuristic to decide
   * whether to inline or not.
   */
  #ifdef CONFIG_64BIT
  #define SHA3_INLINE	inline
  #else
  #define SHA3_INLINE	noinline
  #endif
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
31
  #define KECCAK_ROUNDS 24
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
32
  static const u64 keccakf_rndc[24] = {
f743e70e8   Geert Uytterhoeven   crypto: sha3 - Ad...
33
34
35
36
37
38
39
40
  	0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
  	0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
  	0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
  	0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
  	0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
  	0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
  	0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
  	0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
41
  };
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
42
  /* update the state with given number of rounds */
4767b9ad7   Ard Biesheuvel   crypto: sha3-gene...
43
  static SHA3_INLINE void keccakf_round(u64 st[25])
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
44
  {
83dee2ce1   Ard Biesheuvel   crypto: sha3-gene...
45
  	u64 t[5], tt, bc[5];
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
46

4767b9ad7   Ard Biesheuvel   crypto: sha3-gene...
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  	/* Theta */
  	bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
  	bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
  	bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
  	bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
  	bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
  
  	t[0] = bc[4] ^ rol64(bc[1], 1);
  	t[1] = bc[0] ^ rol64(bc[2], 1);
  	t[2] = bc[1] ^ rol64(bc[3], 1);
  	t[3] = bc[2] ^ rol64(bc[4], 1);
  	t[4] = bc[3] ^ rol64(bc[0], 1);
  
  	st[0] ^= t[0];
  
  	/* Rho Pi */
  	tt = st[1];
  	st[ 1] = rol64(st[ 6] ^ t[1], 44);
  	st[ 6] = rol64(st[ 9] ^ t[4], 20);
  	st[ 9] = rol64(st[22] ^ t[2], 61);
  	st[22] = rol64(st[14] ^ t[4], 39);
  	st[14] = rol64(st[20] ^ t[0], 18);
  	st[20] = rol64(st[ 2] ^ t[2], 62);
  	st[ 2] = rol64(st[12] ^ t[2], 43);
  	st[12] = rol64(st[13] ^ t[3], 25);
  	st[13] = rol64(st[19] ^ t[4],  8);
  	st[19] = rol64(st[23] ^ t[3], 56);
  	st[23] = rol64(st[15] ^ t[0], 41);
  	st[15] = rol64(st[ 4] ^ t[4], 27);
  	st[ 4] = rol64(st[24] ^ t[4], 14);
  	st[24] = rol64(st[21] ^ t[1],  2);
  	st[21] = rol64(st[ 8] ^ t[3], 55);
  	st[ 8] = rol64(st[16] ^ t[1], 45);
  	st[16] = rol64(st[ 5] ^ t[0], 36);
  	st[ 5] = rol64(st[ 3] ^ t[3], 28);
  	st[ 3] = rol64(st[18] ^ t[3], 21);
  	st[18] = rol64(st[17] ^ t[2], 15);
  	st[17] = rol64(st[11] ^ t[1], 10);
  	st[11] = rol64(st[ 7] ^ t[2],  6);
  	st[ 7] = rol64(st[10] ^ t[0],  3);
  	st[10] = rol64(    tt ^ t[1],  1);
  
  	/* Chi */
  	bc[ 0] = ~st[ 1] & st[ 2];
  	bc[ 1] = ~st[ 2] & st[ 3];
  	bc[ 2] = ~st[ 3] & st[ 4];
  	bc[ 3] = ~st[ 4] & st[ 0];
  	bc[ 4] = ~st[ 0] & st[ 1];
  	st[ 0] ^= bc[ 0];
  	st[ 1] ^= bc[ 1];
  	st[ 2] ^= bc[ 2];
  	st[ 3] ^= bc[ 3];
  	st[ 4] ^= bc[ 4];
  
  	bc[ 0] = ~st[ 6] & st[ 7];
  	bc[ 1] = ~st[ 7] & st[ 8];
  	bc[ 2] = ~st[ 8] & st[ 9];
  	bc[ 3] = ~st[ 9] & st[ 5];
  	bc[ 4] = ~st[ 5] & st[ 6];
  	st[ 5] ^= bc[ 0];
  	st[ 6] ^= bc[ 1];
  	st[ 7] ^= bc[ 2];
  	st[ 8] ^= bc[ 3];
  	st[ 9] ^= bc[ 4];
  
  	bc[ 0] = ~st[11] & st[12];
  	bc[ 1] = ~st[12] & st[13];
  	bc[ 2] = ~st[13] & st[14];
  	bc[ 3] = ~st[14] & st[10];
  	bc[ 4] = ~st[10] & st[11];
  	st[10] ^= bc[ 0];
  	st[11] ^= bc[ 1];
  	st[12] ^= bc[ 2];
  	st[13] ^= bc[ 3];
  	st[14] ^= bc[ 4];
  
  	bc[ 0] = ~st[16] & st[17];
  	bc[ 1] = ~st[17] & st[18];
  	bc[ 2] = ~st[18] & st[19];
  	bc[ 3] = ~st[19] & st[15];
  	bc[ 4] = ~st[15] & st[16];
  	st[15] ^= bc[ 0];
  	st[16] ^= bc[ 1];
  	st[17] ^= bc[ 2];
  	st[18] ^= bc[ 3];
  	st[19] ^= bc[ 4];
  
  	bc[ 0] = ~st[21] & st[22];
  	bc[ 1] = ~st[22] & st[23];
  	bc[ 2] = ~st[23] & st[24];
  	bc[ 3] = ~st[24] & st[20];
  	bc[ 4] = ~st[20] & st[21];
  	st[20] ^= bc[ 0];
  	st[21] ^= bc[ 1];
  	st[22] ^= bc[ 2];
  	st[23] ^= bc[ 3];
  	st[24] ^= bc[ 4];
  }
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
145

f044a84e0   Dmitry Vyukov   crypto: don't opt...
146
  static void keccakf(u64 st[25])
4767b9ad7   Ard Biesheuvel   crypto: sha3-gene...
147
148
  {
  	int round;
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
149

4767b9ad7   Ard Biesheuvel   crypto: sha3-gene...
150
151
  	for (round = 0; round < KECCAK_ROUNDS; round++) {
  		keccakf_round(st);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
152
153
154
155
  		/* Iota */
  		st[0] ^= keccakf_rndc[round];
  	}
  }
6657674b2   Ard Biesheuvel   crypto: sha3-gene...
156
  int crypto_sha3_init(struct shash_desc *desc)
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
157
158
  {
  	struct sha3_state *sctx = shash_desc_ctx(desc);
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
159
  	unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
160

beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
161
162
163
  	sctx->rsiz = 200 - 2 * digest_size;
  	sctx->rsizw = sctx->rsiz / 8;
  	sctx->partial = 0;
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
164

beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
165
  	memset(sctx->st, 0, sizeof(sctx->st));
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
166
167
  	return 0;
  }
6657674b2   Ard Biesheuvel   crypto: sha3-gene...
168
  EXPORT_SYMBOL(crypto_sha3_init);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
169

6657674b2   Ard Biesheuvel   crypto: sha3-gene...
170
  int crypto_sha3_update(struct shash_desc *desc, const u8 *data,
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  		       unsigned int len)
  {
  	struct sha3_state *sctx = shash_desc_ctx(desc);
  	unsigned int done;
  	const u8 *src;
  
  	done = 0;
  	src = data;
  
  	if ((sctx->partial + len) > (sctx->rsiz - 1)) {
  		if (sctx->partial) {
  			done = -sctx->partial;
  			memcpy(sctx->buf + sctx->partial, data,
  			       done + sctx->rsiz);
  			src = sctx->buf;
  		}
  
  		do {
  			unsigned int i;
  
  			for (i = 0; i < sctx->rsizw; i++)
c013cee99   Ard Biesheuvel   crypto: sha3-gene...
192
  				sctx->st[i] ^= get_unaligned_le64(src + 8 * i);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
193
194
195
196
197
198
199
200
201
202
203
204
205
  			keccakf(sctx->st);
  
  			done += sctx->rsiz;
  			src = data + done;
  		} while (done + (sctx->rsiz - 1) < len);
  
  		sctx->partial = 0;
  	}
  	memcpy(sctx->buf + sctx->partial, src, len - done);
  	sctx->partial += (len - done);
  
  	return 0;
  }
6657674b2   Ard Biesheuvel   crypto: sha3-gene...
206
  EXPORT_SYMBOL(crypto_sha3_update);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
207

6657674b2   Ard Biesheuvel   crypto: sha3-gene...
208
  int crypto_sha3_final(struct shash_desc *desc, u8 *out)
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
209
210
211
  {
  	struct sha3_state *sctx = shash_desc_ctx(desc);
  	unsigned int i, inlen = sctx->partial;
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
212
213
  	unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
  	__le64 *digest = (__le64 *)out;
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
214
215
216
217
218
219
  
  	sctx->buf[inlen++] = 0x06;
  	memset(sctx->buf + inlen, 0, sctx->rsiz - inlen);
  	sctx->buf[sctx->rsiz - 1] |= 0x80;
  
  	for (i = 0; i < sctx->rsizw; i++)
c013cee99   Ard Biesheuvel   crypto: sha3-gene...
220
  		sctx->st[i] ^= get_unaligned_le64(sctx->buf + 8 * i);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
221
222
  
  	keccakf(sctx->st);
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
223
224
  	for (i = 0; i < digest_size / 8; i++)
  		put_unaligned_le64(sctx->st[i], digest++);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
225

beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
226
227
  	if (digest_size & 4)
  		put_unaligned_le32(sctx->st[i], (__le32 *)digest);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
228
229
230
231
  
  	memset(sctx, 0, sizeof(*sctx));
  	return 0;
  }
6657674b2   Ard Biesheuvel   crypto: sha3-gene...
232
  EXPORT_SYMBOL(crypto_sha3_final);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
233

beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
234
235
  static struct shash_alg algs[] = { {
  	.digestsize		= SHA3_224_DIGEST_SIZE,
6657674b2   Ard Biesheuvel   crypto: sha3-gene...
236
237
238
  	.init			= crypto_sha3_init,
  	.update			= crypto_sha3_update,
  	.final			= crypto_sha3_final,
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
239
240
241
  	.descsize		= sizeof(struct sha3_state),
  	.base.cra_name		= "sha3-224",
  	.base.cra_driver_name	= "sha3-224-generic",
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
242
243
244
245
  	.base.cra_blocksize	= SHA3_224_BLOCK_SIZE,
  	.base.cra_module	= THIS_MODULE,
  }, {
  	.digestsize		= SHA3_256_DIGEST_SIZE,
6657674b2   Ard Biesheuvel   crypto: sha3-gene...
246
247
248
  	.init			= crypto_sha3_init,
  	.update			= crypto_sha3_update,
  	.final			= crypto_sha3_final,
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
249
250
251
  	.descsize		= sizeof(struct sha3_state),
  	.base.cra_name		= "sha3-256",
  	.base.cra_driver_name	= "sha3-256-generic",
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
252
253
254
255
  	.base.cra_blocksize	= SHA3_256_BLOCK_SIZE,
  	.base.cra_module	= THIS_MODULE,
  }, {
  	.digestsize		= SHA3_384_DIGEST_SIZE,
6657674b2   Ard Biesheuvel   crypto: sha3-gene...
256
257
258
  	.init			= crypto_sha3_init,
  	.update			= crypto_sha3_update,
  	.final			= crypto_sha3_final,
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
259
260
261
  	.descsize		= sizeof(struct sha3_state),
  	.base.cra_name		= "sha3-384",
  	.base.cra_driver_name	= "sha3-384-generic",
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
262
263
264
265
  	.base.cra_blocksize	= SHA3_384_BLOCK_SIZE,
  	.base.cra_module	= THIS_MODULE,
  }, {
  	.digestsize		= SHA3_512_DIGEST_SIZE,
6657674b2   Ard Biesheuvel   crypto: sha3-gene...
266
267
268
  	.init			= crypto_sha3_init,
  	.update			= crypto_sha3_update,
  	.final			= crypto_sha3_final,
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
269
270
271
  	.descsize		= sizeof(struct sha3_state),
  	.base.cra_name		= "sha3-512",
  	.base.cra_driver_name	= "sha3-512-generic",
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
272
273
274
  	.base.cra_blocksize	= SHA3_512_BLOCK_SIZE,
  	.base.cra_module	= THIS_MODULE,
  } };
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
275
276
277
  
  static int __init sha3_generic_mod_init(void)
  {
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
278
  	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
279
280
281
282
  }
  
  static void __exit sha3_generic_mod_fini(void)
  {
beeb504ad   Ard Biesheuvel   crypto: sha3-gene...
283
  	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
284
  }
c4741b230   Eric Biggers   crypto: run initc...
285
  subsys_initcall(sha3_generic_mod_init);
53964b9ee   Jeff Garzik   crypto: sha3 - Ad...
286
287
288
289
290
291
292
293
294
295
296
297
298
  module_exit(sha3_generic_mod_fini);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("SHA-3 Secure Hash Algorithm");
  
  MODULE_ALIAS_CRYPTO("sha3-224");
  MODULE_ALIAS_CRYPTO("sha3-224-generic");
  MODULE_ALIAS_CRYPTO("sha3-256");
  MODULE_ALIAS_CRYPTO("sha3-256-generic");
  MODULE_ALIAS_CRYPTO("sha3-384");
  MODULE_ALIAS_CRYPTO("sha3-384-generic");
  MODULE_ALIAS_CRYPTO("sha3-512");
  MODULE_ALIAS_CRYPTO("sha3-512-generic");