@@ -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
134136static 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+
195235static 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
313405int 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+
364493int sha3_shake_memory (int num , const unsigned char * in , unsigned long inlen , unsigned char * out , const unsigned long * outlen )
365494{
366495 hash_state md ;
0 commit comments