1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10
11 /* based on https://github.com/brainhub/SHA3IUF (public domain) */
12
13 #include "tomcrypt_private.h"
14
15 #ifdef LTC_SHA3
16
17 const struct ltc_hash_descriptor sha3_224_desc =
18 {
19 "sha3-224", /* name of hash */
20 17, /* internal ID */
21 28, /* Size of digest in octets */
22 144, /* Input block size in octets */
23 { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */
24 9, /* Length OID */
25 &sha3_224_init,
26 &sha3_process,
27 &sha3_done,
28 &sha3_224_test,
29 NULL
30 };
31
32 const struct ltc_hash_descriptor sha3_256_desc =
33 {
34 "sha3-256", /* name of hash */
35 18, /* internal ID */
36 32, /* Size of digest in octets */
37 136, /* Input block size in octets */
38 { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */
39 9, /* Length OID */
40 &sha3_256_init,
41 &sha3_process,
42 &sha3_done,
43 &sha3_256_test,
44 NULL
45 };
46
47 const struct ltc_hash_descriptor sha3_384_desc =
48 {
49 "sha3-384", /* name of hash */
50 19, /* internal ID */
51 48, /* Size of digest in octets */
52 104, /* Input block size in octets */
53 { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */
54 9, /* Length OID */
55 &sha3_384_init,
56 &sha3_process,
57 &sha3_done,
58 &sha3_384_test,
59 NULL
60 };
61
62 const struct ltc_hash_descriptor sha3_512_desc =
63 {
64 "sha3-512", /* name of hash */
65 20, /* internal ID */
66 64, /* Size of digest in octets */
67 72, /* Input block size in octets */
68 { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */
69 9, /* Length OID */
70 &sha3_512_init,
71 &sha3_process,
72 &sha3_done,
73 &sha3_512_test,
74 NULL
75 };
76 #endif
77
78 #ifdef LTC_KECCAK
79 const struct ltc_hash_descriptor keccak_224_desc =
80 {
81 "keccak224", /* name of hash */
82 29, /* internal ID */
83 28, /* Size of digest in octets */
84 144, /* Input block size in octets */
85 { 0 }, 0, /* no ASN.1 OID */
86 &sha3_224_init,
87 &sha3_process,
88 &keccak_done,
89 &keccak_224_test,
90 NULL
91 };
92
93 const struct ltc_hash_descriptor keccak_256_desc =
94 {
95 "keccak256", /* name of hash */
96 30, /* internal ID */
97 32, /* Size of digest in octets */
98 136, /* Input block size in octets */
99 { 0 }, 0, /* no ASN.1 OID */
100 &sha3_256_init,
101 &sha3_process,
102 &keccak_done,
103 &keccak_256_test,
104 NULL
105 };
106
107 const struct ltc_hash_descriptor keccak_384_desc =
108 {
109 "keccak384", /* name of hash */
110 31, /* internal ID */
111 48, /* Size of digest in octets */
112 104, /* Input block size in octets */
113 { 0 }, 0, /* no ASN.1 OID */
114 &sha3_384_init,
115 &sha3_process,
116 &keccak_done,
117 &keccak_384_test,
118 NULL
119 };
120
121 const struct ltc_hash_descriptor keccak_512_desc =
122 {
123 "keccak512", /* name of hash */
124 32, /* internal ID */
125 64, /* Size of digest in octets */
126 72, /* Input block size in octets */
127 { 0 }, 0, /* no ASN.1 OID */
128 &sha3_512_init,
129 &sha3_process,
130 &keccak_done,
131 &keccak_512_test,
132 NULL
133 };
134 #endif
135
136 #if defined(LTC_SHA3) || defined(LTC_KECCAK)
137
138 #define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */
139 #define SHA3_KECCAK_ROUNDS 24
140
141 static const ulong64 keccakf_rndc[24] = {
142 CONST64(0x0000000000000001), CONST64(0x0000000000008082),
143 CONST64(0x800000000000808a), CONST64(0x8000000080008000),
144 CONST64(0x000000000000808b), CONST64(0x0000000080000001),
145 CONST64(0x8000000080008081), CONST64(0x8000000000008009),
146 CONST64(0x000000000000008a), CONST64(0x0000000000000088),
147 CONST64(0x0000000080008009), CONST64(0x000000008000000a),
148 CONST64(0x000000008000808b), CONST64(0x800000000000008b),
149 CONST64(0x8000000000008089), CONST64(0x8000000000008003),
150 CONST64(0x8000000000008002), CONST64(0x8000000000000080),
151 CONST64(0x000000000000800a), CONST64(0x800000008000000a),
152 CONST64(0x8000000080008081), CONST64(0x8000000000008080),
153 CONST64(0x0000000080000001), CONST64(0x8000000080008008)
154 };
155
156 static const unsigned keccakf_rotc[24] = {
157 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
158 };
159
160 static const unsigned keccakf_piln[24] = {
161 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
162 };
163
keccakf(ulong64 s[25])164 static void keccakf(ulong64 s[25])
165 {
166 int i, j, round;
167 ulong64 t, bc[5];
168
169 for(round = 0; round < SHA3_KECCAK_ROUNDS; round++) {
170 /* Theta */
171 for(i = 0; i < 5; i++) {
172 bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
173 }
174 for(i = 0; i < 5; i++) {
175 t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1);
176 for(j = 0; j < 25; j += 5) {
177 s[j + i] ^= t;
178 }
179 }
180 /* Rho Pi */
181 t = s[1];
182 for(i = 0; i < 24; i++) {
183 j = keccakf_piln[i];
184 bc[0] = s[j];
185 s[j] = ROL64(t, keccakf_rotc[i]);
186 t = bc[0];
187 }
188 /* Chi */
189 for(j = 0; j < 25; j += 5) {
190 for(i = 0; i < 5; i++) {
191 bc[i] = s[j + i];
192 }
193 for(i = 0; i < 5; i++) {
194 s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
195 }
196 }
197 /* Iota */
198 s[0] ^= keccakf_rndc[round];
199 }
200 }
201
_done(hash_state * md,unsigned char * hash,ulong64 pad)202 static LTC_INLINE int _done(hash_state *md, unsigned char *hash, ulong64 pad)
203 {
204 unsigned i;
205
206 LTC_ARGCHK(md != NULL);
207 LTC_ARGCHK(hash != NULL);
208
209 md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (pad << (md->sha3.byte_index * 8)));
210 md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
211 keccakf(md->sha3.s);
212
213 /* store sha3.s[] as little-endian bytes into sha3.sb */
214 for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
215 STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
216 }
217
218 XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4);
219 return CRYPT_OK;
220 }
221
222 /* Public Inteface */
223
sha3_224_init(hash_state * md)224 int sha3_224_init(hash_state *md)
225 {
226 LTC_ARGCHK(md != NULL);
227 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
228 md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64));
229 return CRYPT_OK;
230 }
231
sha3_256_init(hash_state * md)232 int sha3_256_init(hash_state *md)
233 {
234 LTC_ARGCHK(md != NULL);
235 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
236 md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64));
237 return CRYPT_OK;
238 }
239
sha3_384_init(hash_state * md)240 int sha3_384_init(hash_state *md)
241 {
242 LTC_ARGCHK(md != NULL);
243 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
244 md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64));
245 return CRYPT_OK;
246 }
247
sha3_512_init(hash_state * md)248 int sha3_512_init(hash_state *md)
249 {
250 LTC_ARGCHK(md != NULL);
251 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
252 md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64));
253 return CRYPT_OK;
254 }
255
256 #ifdef LTC_SHA3
sha3_shake_init(hash_state * md,int num)257 int sha3_shake_init(hash_state *md, int num)
258 {
259 LTC_ARGCHK(md != NULL);
260 if (num != 128 && num != 256) return CRYPT_INVALID_ARG;
261 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
262 md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64)));
263 return CRYPT_OK;
264 }
265 #endif
266
sha3_process(hash_state * md,const unsigned char * in,unsigned long inlen)267 int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen)
268 {
269 /* 0...7 -- how much is needed to have a word */
270 unsigned old_tail = (8 - md->sha3.byte_index) & 7;
271
272 unsigned long words;
273 unsigned tail;
274 unsigned long i;
275
276 if (inlen == 0) return CRYPT_OK; /* nothing to do */
277 LTC_ARGCHK(md != NULL);
278 LTC_ARGCHK(in != NULL);
279
280 if(inlen < old_tail) { /* have no complete word or haven't started the word yet */
281 while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
282 return CRYPT_OK;
283 }
284
285 if(old_tail) { /* will have one word to process */
286 inlen -= old_tail;
287 while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
288 /* now ready to add saved to the sponge */
289 md->sha3.s[md->sha3.word_index] ^= md->sha3.saved;
290 md->sha3.byte_index = 0;
291 md->sha3.saved = 0;
292 if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
293 keccakf(md->sha3.s);
294 md->sha3.word_index = 0;
295 }
296 }
297
298 /* now work in full words directly from input */
299 words = inlen / sizeof(ulong64);
300 tail = inlen - words * sizeof(ulong64);
301
302 for(i = 0; i < words; i++, in += sizeof(ulong64)) {
303 ulong64 t;
304 LOAD64L(t, in);
305 md->sha3.s[md->sha3.word_index] ^= t;
306 if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
307 keccakf(md->sha3.s);
308 md->sha3.word_index = 0;
309 }
310 }
311
312 /* finally, save the partial word */
313 while (tail--) {
314 md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
315 }
316 return CRYPT_OK;
317 }
318
319 #ifdef LTC_SHA3
sha3_done(hash_state * md,unsigned char * out)320 int sha3_done(hash_state *md, unsigned char *out)
321 {
322 return _done(md, out, CONST64(0x06));
323 }
324 #endif
325
326 #ifdef LTC_KECCAK
keccak_done(hash_state * md,unsigned char * out)327 int keccak_done(hash_state *md, unsigned char *out)
328 {
329 return _done(md, out, CONST64(0x01));
330 }
331 #endif
332
333 #ifdef LTC_SHA3
sha3_shake_done(hash_state * md,unsigned char * out,unsigned long outlen)334 int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen)
335 {
336 /* IMPORTANT NOTE: sha3_shake_done can be called many times */
337 unsigned long idx;
338 unsigned i;
339
340 if (outlen == 0) return CRYPT_OK; /* nothing to do */
341 LTC_ARGCHK(md != NULL);
342 LTC_ARGCHK(out != NULL);
343
344 if (!md->sha3.xof_flag) {
345 /* shake_xof operation must be done only once */
346 md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8)));
347 md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
348 keccakf(md->sha3.s);
349 /* store sha3.s[] as little-endian bytes into sha3.sb */
350 for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
351 STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
352 }
353 md->sha3.byte_index = 0;
354 md->sha3.xof_flag = 1;
355 }
356
357 for (idx = 0; idx < outlen; idx++) {
358 if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) {
359 keccakf(md->sha3.s);
360 /* store sha3.s[] as little-endian bytes into sha3.sb */
361 for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
362 STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
363 }
364 md->sha3.byte_index = 0;
365 }
366 out[idx] = md->sha3.sb[md->sha3.byte_index++];
367 }
368 return CRYPT_OK;
369 }
370
sha3_shake_memory(int num,const unsigned char * in,unsigned long inlen,unsigned char * out,const unsigned long * outlen)371 int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen)
372 {
373 hash_state md;
374 int err;
375 LTC_ARGCHK(in != NULL);
376 LTC_ARGCHK(out != NULL);
377 LTC_ARGCHK(outlen != NULL);
378 if ((err = sha3_shake_init(&md, num)) != CRYPT_OK) return err;
379 if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err;
380 if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err;
381 return CRYPT_OK;
382 }
383 #endif
384
385 #endif
386
387 /* ref: $Format:%D$ */
388 /* git commit: $Format:%H$ */
389 /* commit time: $Format:%ai$ */
390