Skip to content

Commit 02ad3e9

Browse files
committed
Add TurboSHAKE XOF functions.
TurboSHAKE128 and TurboSHAKE256 as described in https://keccak.team/files/TurboSHAKE.pdf. #691
1 parent b1fa61d commit 02ad3e9

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

src/hashes/sha3.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ const struct ltc_hash_descriptor keccak_512_desc =
130130

131131
#define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */
132132
#define SHA3_KECCAK_ROUNDS 24
133+
#define SHA3_KECCAK_TURBO_ROUNDS 12
134+
#define SHA3_KECCAK_TURBO_RC_OFFSET 12
133135

134136
static const ulong64 s_keccakf_rndc[24] = {
135137
CONST64(0x0000000000000001), CONST64(0x0000000000008082),
@@ -192,6 +194,44 @@ static void s_keccakf(ulong64 s[25])
192194
}
193195
}
194196

197+
static void s_keccak_turbo_f(ulong64 s[25])
198+
{
199+
int i, j, round;
200+
ulong64 t, bc[5];
201+
202+
for(round = 0; round < SHA3_KECCAK_TURBO_ROUNDS; round++) {
203+
/* Theta */
204+
for(i = 0; i < 5; i++) {
205+
bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
206+
}
207+
for(i = 0; i < 5; i++) {
208+
t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1);
209+
for(j = 0; j < 25; j += 5) {
210+
s[j + i] ^= t;
211+
}
212+
}
213+
/* Rho Pi */
214+
t = s[1];
215+
for(i = 0; i < 24; i++) {
216+
j = s_keccakf_piln[i];
217+
bc[0] = s[j];
218+
s[j] = ROL64(t, s_keccakf_rotc[i]);
219+
t = bc[0];
220+
}
221+
/* Chi */
222+
for(j = 0; j < 25; j += 5) {
223+
for(i = 0; i < 5; i++) {
224+
bc[i] = s[j + i];
225+
}
226+
for(i = 0; i < 5; i++) {
227+
s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
228+
}
229+
}
230+
/* Iota */
231+
s[0] ^= s_keccakf_rndc[SHA3_KECCAK_TURBO_RC_OFFSET + round];
232+
}
233+
}
234+
195235
static LTC_INLINE int ss_done(hash_state *md, unsigned char *hash, ulong64 pad)
196236
{
197237
unsigned i;
@@ -309,6 +349,58 @@ int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen)
309349
return CRYPT_OK;
310350
}
311351

352+
int sha3_turbo_process(hash_state *md, const unsigned char *in, unsigned long inlen)
353+
{
354+
/* 0...7 -- how much is needed to have a word */
355+
unsigned old_tail = (8 - md->sha3.byte_index) & 7;
356+
357+
unsigned long words;
358+
unsigned tail;
359+
unsigned long i;
360+
361+
if (inlen == 0) return CRYPT_OK; /* nothing to do */
362+
LTC_ARGCHK(md != NULL);
363+
LTC_ARGCHK(in != NULL);
364+
365+
if(inlen < old_tail) { /* have no complete word or haven't started the word yet */
366+
while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
367+
return CRYPT_OK;
368+
}
369+
370+
if(old_tail) { /* will have one word to process */
371+
inlen -= old_tail;
372+
while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
373+
/* now ready to add saved to the sponge */
374+
md->sha3.s[md->sha3.word_index] ^= md->sha3.saved;
375+
md->sha3.byte_index = 0;
376+
md->sha3.saved = 0;
377+
if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
378+
s_keccak_turbo_f(md->sha3.s);
379+
md->sha3.word_index = 0;
380+
}
381+
}
382+
383+
/* now work in full words directly from input */
384+
words = inlen / sizeof(ulong64);
385+
tail = inlen - words * sizeof(ulong64);
386+
387+
for(i = 0; i < words; i++, in += sizeof(ulong64)) {
388+
ulong64 t;
389+
LOAD64L(t, in);
390+
md->sha3.s[md->sha3.word_index] ^= t;
391+
if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
392+
s_keccak_turbo_f(md->sha3.s);
393+
md->sha3.word_index = 0;
394+
}
395+
}
396+
397+
/* finally, save the partial word */
398+
while (tail--) {
399+
md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
400+
}
401+
return CRYPT_OK;
402+
}
403+
312404
#ifdef LTC_SHA3
313405
int sha3_done(hash_state *md, unsigned char *out)
314406
{
@@ -361,6 +453,43 @@ int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen)
361453
return CRYPT_OK;
362454
}
363455

456+
int sha3_shake_turbo_done(hash_state *md, unsigned char *out, unsigned long outlen)
457+
{
458+
/* IMPORTANT NOTE: sha3_shake_turbo_done can be called many times */
459+
unsigned long idx;
460+
unsigned i;
461+
462+
if (outlen == 0) return CRYPT_OK; /* nothing to do */
463+
LTC_ARGCHK(md != NULL);
464+
LTC_ARGCHK(out != NULL);
465+
466+
if (!md->sha3.xof_flag) {
467+
/* shake_xof operation must be done only once */
468+
md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8)));
469+
md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
470+
s_keccak_turbo_f(md->sha3.s);
471+
/* store sha3.s[] as little-endian bytes into sha3.sb */
472+
for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
473+
STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
474+
}
475+
md->sha3.byte_index = 0;
476+
md->sha3.xof_flag = 1;
477+
}
478+
479+
for (idx = 0; idx < outlen; idx++) {
480+
if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) {
481+
s_keccak_turbo_f(md->sha3.s);
482+
/* store sha3.s[] as little-endian bytes into sha3.sb */
483+
for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
484+
STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
485+
}
486+
md->sha3.byte_index = 0;
487+
}
488+
out[idx] = md->sha3.sb[md->sha3.byte_index++];
489+
}
490+
return CRYPT_OK;
491+
}
492+
364493
int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen)
365494
{
366495
hash_state md;

src/headers/tomcrypt_hash.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ int sha3_256_init(hash_state * md);
265265
int sha3_224_init(hash_state * md);
266266
/* sha3_process is the same for all variants of SHA3 + KECCAK */
267267
int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen);
268+
int sha3_turbo_process(hash_state * md, const unsigned char *in, unsigned long inlen);
268269
#endif
269270

270271
#ifdef LTC_SHA3
@@ -280,7 +281,9 @@ int sha3_done(hash_state *md, unsigned char *out);
280281
/* SHAKE128 + SHAKE256 */
281282
int sha3_shake_init(hash_state *md, int num);
282283
#define sha3_shake_process(a,b,c) sha3_process(a,b,c)
284+
#define sha3_shake_turbo_process(a,b,c) sha3_turbo_process(a,b,c)
283285
int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen);
286+
int sha3_shake_turbo_done(hash_state *md, unsigned char *out, unsigned long outlen);
284287
int sha3_shake_test(void);
285288
int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen);
286289
#endif

0 commit comments

Comments
 (0)