@@ -353,19 +353,19 @@ int keccak_done(hash_state *md, unsigned char *out)
353353#endif
354354
355355#ifdef LTC_SHA3
356- static LTC_INLINE int s_sha3_shake_done (hash_state * md , unsigned char * out , unsigned long outlen , process_fn proc_f )
356+ static LTC_INLINE int s_sha3_shake_done (hash_state * md , unsigned char * out , unsigned long outlen , unsigned char domain , process_fn proc_f )
357357{
358358 /* IMPORTANT NOTE: sha3_shake_done can be called many times */
359359 unsigned long idx ;
360360 unsigned i ;
361361
362362 if (outlen == 0 ) return CRYPT_OK ; /* nothing to do */
363- LTC_ARGCHK (md != NULL );
363+ LTC_ARGCHK (md != NULL );
364364 LTC_ARGCHK (out != NULL );
365365
366366 if (!md -> sha3 .xof_flag ) {
367367 /* shake_xof operation must be done only once */
368- md -> sha3 .s [md -> sha3 .word_index ] ^= (md -> sha3 .saved ^ (CONST64 ( 0x1F ) << (md -> sha3 .byte_index * 8 )));
368+ md -> sha3 .s [md -> sha3 .word_index ] ^= (md -> sha3 .saved ^ ((( ulong64 )( domain ) ) << (md -> sha3 .byte_index * 8 )));
369369 md -> sha3 .s [SHA3_KECCAK_SPONGE_WORDS - md -> sha3 .capacity_words - 1 ] ^= CONST64 (0x8000000000000000 );
370370 proc_f (md -> sha3 .s );
371371 /* store sha3.s[] as little-endian bytes into sha3.sb */
@@ -392,13 +392,13 @@ static LTC_INLINE int s_sha3_shake_done(hash_state *md, unsigned char *out, unsi
392392
393393int sha3_shake_done (hash_state * md , unsigned char * out , unsigned long outlen )
394394{
395- return s_sha3_shake_done (md , out , outlen , s_keccakf );
395+ return s_sha3_shake_done (md , out , outlen , 0x1f , s_keccakf );
396396}
397397
398398#if defined LTC_TURBO_SHAKE
399399int turbo_shake_done (hash_state * md , unsigned char * out , unsigned long outlen )
400400{
401- return s_sha3_shake_done (md , out , outlen , s_keccak_turbo_f );
401+ return s_sha3_shake_done (md , out , outlen , 0x1f , s_keccak_turbo_f );
402402}
403403#endif
404404
@@ -416,4 +416,152 @@ int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, uns
416416}
417417#endif
418418
419+ #ifdef LTC_KANGAROO_TWELVE
420+
421+ static const unsigned char kangaroo_twelve_filler [] = { 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
422+
423+ int kangaroo_twelve_init (hash_state * md , int num )
424+ {
425+ int err ;
426+
427+ LTC_ARGCHK (md != NULL );
428+ LTC_ARGCHK (num == 128 || num == 256 );
429+
430+ if ((err = sha3_shake_init ((hash_state * )& md -> kt .outer , num )) != CRYPT_OK ) return err ;
431+ if ((err = sha3_shake_init ((hash_state * )& md -> kt .inner , num )) != CRYPT_OK ) return err ;
432+ md -> kt .blocks_count = 0 ;
433+ md -> kt .customization_len = 0 ;
434+ md -> kt .remaining = 8 * 1024 ;
435+ md -> kt .phase = 0 ;
436+ md -> kt .finished = 0 ;
437+ return CRYPT_OK ;
438+ }
439+
440+ static LTC_INLINE int s_kangaroo_twelve_process (hash_state * md , const unsigned char * in , unsigned long inlen )
441+ {
442+ unsigned long rem ;
443+ unsigned long amount ;
444+ int err ;
445+ int variant ;
446+ int digest_len ;
447+ unsigned char digest_buf [64 ];
448+
449+ LTC_ARGCHK (md != NULL );
450+ LTC_ARGCHK (in != NULL || inlen == 0 );
451+
452+ if (md -> kt .phase == 0 )
453+ {
454+ rem = md -> kt .remaining ;
455+ amount = rem < inlen ? rem : inlen ;
456+ md -> kt .remaining -= amount ;
457+ if ((err = turbo_shake_process ((hash_state * )& md -> kt .outer , in , amount )) != CRYPT_OK ) return err ;
458+ in += amount ;
459+ inlen -= amount ;
460+ if (md -> kt .remaining == 0 && inlen != 0 )
461+ {
462+ md -> kt .remaining = 8 * 1024 ;
463+ md -> kt .phase = 1 ;
464+ md -> kt .blocks_count += 1 ;
465+ if ((err = turbo_shake_process ((hash_state * )& md -> kt .outer , kangaroo_twelve_filler , sizeof (kangaroo_twelve_filler ))) != CRYPT_OK ) return err ;
466+ }
467+ }
468+ if (md -> kt .phase == 1 )
469+ {
470+ do
471+ {
472+ rem = md -> kt .remaining ;
473+ amount = rem < inlen ? rem : inlen ;
474+ md -> kt .remaining -= amount ;
475+ if ((err = turbo_shake_process ((hash_state * )& md -> kt .inner , in , amount )) != CRYPT_OK ) return err ;
476+ in += amount ;
477+ inlen -= amount ;
478+ if (md -> kt .remaining == 0 && inlen != 0 )
479+ {
480+ md -> kt .remaining = 8 * 1024 ;
481+ md -> kt .blocks_count += 1 ;
482+ assert (md -> kt .outer .capacity_words == 4 || md -> kt .outer .capacity_words == 8 );
483+ variant = md -> kt .outer .capacity_words == 4 ? 128 : 256 ;
484+ digest_len = variant == 128 ? 32 : 64 ;
485+ if ((err = s_sha3_shake_done ((hash_state * )& md -> kt .inner , digest_buf , digest_len , 0x0b , s_keccak_turbo_f )) != CRYPT_OK ) return err ;
486+ if ((err = turbo_shake_init ((hash_state * )& md -> kt .inner , variant )) != CRYPT_OK ) return err ;
487+ if ((err = turbo_shake_process ((hash_state * )& md -> kt .outer , digest_buf , digest_len )) != CRYPT_OK ) return err ;
488+ }
489+ } while (inlen != 0 );
490+ }
491+ return CRYPT_OK ;
492+ }
493+
494+ int kangaroo_twelve_process (hash_state * md , const unsigned char * in , unsigned long inlen )
495+ {
496+ LTC_ARGCHK (md != NULL );
497+ LTC_ARGCHK (in != NULL || inlen == 0 );
498+ LTC_ARGCHK (md -> kt .customization_len == 0 );
499+ LTC_ARGCHK (md -> kt .finished == 0 );
500+
501+ return s_kangaroo_twelve_process (md , in , inlen );
502+ }
503+
504+ int kangaroo_twelve_customization (hash_state * md , const unsigned char * in , unsigned long inlen )
505+ {
506+ LTC_ARGCHK (md != NULL );
507+ LTC_ARGCHK (in != NULL || inlen == 0 );
508+ LTC_ARGCHK (md -> kt .finished == 0 );
509+
510+ md -> kt .customization_len += inlen ;
511+ return s_kangaroo_twelve_process (md , in , inlen );
512+ }
513+
514+ int kangaroo_twelve_done (hash_state * md , unsigned char * out , unsigned long outlen )
515+ {
516+ int couner_len ;
517+ unsigned char couner_buf [sizeof (ulong64 ) + 1 ];
518+ int err ;
519+ int variant ;
520+ int digest_len ;
521+ unsigned char digest_buf [64 ];
522+ unsigned char ffff [2 ];
523+ unsigned char domain ;
524+
525+ LTC_ARGCHK (md != NULL );
526+ LTC_ARGCHK (out != NULL || outlen == 0 );
527+
528+ if (md -> kt .finished == 0 )
529+ {
530+ md -> kt .finished = 1 ;
531+ couner_len = 0 ;
532+ while (md -> kt .customization_len != 0 )
533+ {
534+ couner_buf [LTC_ARRAY_SIZE (couner_buf ) - 1 - 1 - couner_len ] = md -> kt .customization_len & 0xff ;
535+ md -> kt .customization_len >>= 8 ;
536+ ++ couner_len ;
537+ }
538+ couner_buf [LTC_ARRAY_SIZE (couner_buf ) - 1 ] = couner_len ;
539+ if ((err = s_kangaroo_twelve_process (md , & couner_buf [LTC_ARRAY_SIZE (couner_buf ) - 1 - couner_len ], couner_len + 1 )) != CRYPT_OK ) return err ;
540+ if (md -> kt .phase != 0 )
541+ {
542+ assert (md -> kt .outer .capacity_words == 4 || md -> kt .outer .capacity_words == 8 );
543+ variant = md -> kt .outer .capacity_words == 4 ? 128 : 256 ;
544+ digest_len = variant == 128 ? 32 : 64 ;
545+ if ((err = s_sha3_shake_done ((hash_state * )& md -> kt .inner , digest_buf , digest_len , 0x0b , s_keccak_turbo_f )) != CRYPT_OK ) return err ;
546+ if ((err = turbo_shake_process ((hash_state * )& md -> kt .outer , digest_buf , digest_len )) != CRYPT_OK ) return err ;
547+ couner_len = 0 ;
548+ while (md -> kt .blocks_count != 0 )
549+ {
550+ couner_buf [LTC_ARRAY_SIZE (couner_buf ) - 1 - 1 - couner_len ] = md -> kt .blocks_count & 0xff ;
551+ md -> kt .blocks_count >>= 8 ;
552+ ++ couner_len ;
553+ }
554+ couner_buf [LTC_ARRAY_SIZE (couner_buf ) - 1 ] = couner_len ;
555+ if ((err = turbo_shake_process ((hash_state * )& md -> kt .outer , & couner_buf [LTC_ARRAY_SIZE (couner_buf ) - 1 - couner_len ], couner_len + 1 )) != CRYPT_OK ) return err ;
556+ ffff [0 ] = 0xff ;
557+ ffff [1 ] = 0xff ;
558+ if ((err = turbo_shake_process ((hash_state * )& md -> kt .outer , ffff , LTC_ARRAY_SIZE (ffff ))) != CRYPT_OK ) return err ;
559+ }
560+ }
561+ domain = md -> kt .phase == 0 ? 0x07 : 0x06 ;
562+ return s_sha3_shake_done (md , out , outlen , domain , s_keccak_turbo_f );
563+ }
564+
565+ #endif
566+
419567#endif
0 commit comments