/***************************************************************************
**                                                                        **
**  Keccak (http://keccak.noekeon.org/) implementation file               **
**                                                                        **
**  This file implements the Keccak hash algorithm as provided by the     **
**  inventors, and submitted to the third round of the NIST SHA-3         **
**  competition.                                                          **
**  For the QKeccakHash wrapper, the originally multiple files were       **
**  combined in this one. Slight modifications have been made to          **
**  allow use in C++ as an independently included .cpp file.              **
**  It is not meant to be compiled into an object, hence, there is no     **
**  header.                                                               **
**                                                                        **
**  The code here is not part of the actual QKeccakHash implementation    **
**  and thus not licensed under the GPLv3 but under its respecitve        **
**  license given by the inventors. Typically, this means it is in the    **
**  public domain, if not noted otherwise.                                **
**                                                                        **
***************************************************************************/

namespace MUtils {
namespace Hash {
namespace Internal {
namespace KeccakImpl {

typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
typedef unsigned long long int UINT64;

// ================================================================================
// =================== brg_endian.h
// ================================================================================


/*
 ---------------------------------------------------------------------------
 Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.

 LICENSE TERMS

 The redistribution and use of this software (with or without changes)
 is allowed without the payment of fees or royalties provided that:

  1. source code distributions include the above copyright notice, this
     list of conditions and the following disclaimer;

  2. binary distributions include the above copyright notice, this list
     of conditions and the following disclaimer in their documentation;

  3. the name of the copyright holder is not used to endorse products
     built using this software without specific written permission.

 DISCLAIMER

 This software is provided 'as is' with no explicit or implied warranties
 in respect of its properties, including, but not limited to, correctness
 and/or fitness for purpose.
 ---------------------------------------------------------------------------
 Issue Date: 20/12/2007
 Changes for ARM 9/9/2010
*/

#ifndef _BRG_ENDIAN_H
#define _BRG_ENDIAN_H

#define IS_BIG_ENDIAN      4321 /* byte 0 is most significant (mc68k) */
#define IS_LITTLE_ENDIAN   1234 /* byte 0 is least significant (i386) */

#if 0
/* Include files where endian defines and byteswap functions may reside */
#if defined( __sun )
#  include <sys/isa_defs.h>
#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
#  include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
      defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
#  include <machine/endian.h>
#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
#  if !defined( __MINGW32__ ) && !defined( _AIX )
#    include <endian.h>
#    if !defined( __BEOS__ )
#      include <byteswap.h>
#    endif
#  endif
#endif
#endif

/* Now attempt to set the define for platform byte order using any  */
/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which  */
/* seem to encompass most endian symbol definitions                 */

#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
#  if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
#    define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#  elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
#    define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#  endif
#elif defined( BIG_ENDIAN )
#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( LITTLE_ENDIAN )
#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif

#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
#  if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
#    define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#  elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
#    define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#  endif
#elif defined( _BIG_ENDIAN )
#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( _LITTLE_ENDIAN )
#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif

#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
#  if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
#    define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#  elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
#    define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#  endif
#elif defined( __BIG_ENDIAN )
#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN )
#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif

#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
#  if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
#    define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#  elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
#    define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#  endif
#elif defined( __BIG_ENDIAN__ )
#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN__ )
#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif

/*  if the platform byte order could not be determined, then try to */
/*  set this define using common machine defines                    */
#if !defined(PLATFORM_BYTE_ORDER)

#if   defined( __alpha__ ) || defined( __alpha ) || defined( i386 )       || \
      defined( __i386__ )  || defined( _M_I86 )  || defined( _M_IX86 )    || \
      defined( __OS2__ )   || defined( sun386 )  || defined( __TURBOC__ ) || \
      defined( vax )       || defined( vms )     || defined( VMS )        || \
      defined( __VMS )     || defined( _M_X64 )
#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN

#elif defined( AMIGA )   || defined( applec )    || defined( __AS400__ )  || \
      defined( _CRAY )   || defined( __hppa )    || defined( __hp9000 )   || \
      defined( ibm370 )  || defined( mc68000 )   || defined( m68k )       || \
      defined( __MRC__ ) || defined( __MVS__ )   || defined( __MWERKS__ ) || \
      defined( sparc )   || defined( __sparc)    || defined( SYMANTEC_C ) || \
      defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM )   || \
      defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN

#elif defined(__arm__)
# ifdef __BIG_ENDIAN
#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# else
#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif 1     /* **** EDIT HERE IF NECESSARY **** */
#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif 0     /* **** EDIT HERE IF NECESSARY **** */
#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#else
#  error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
#endif

#endif

#endif

// ================================================================================
// =================== KeccakSponge.h
// ================================================================================

/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/

Implementation by the designers,
hereby denoted as "the implementer".

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#ifndef _KeccakSponge_h_
#define _KeccakSponge_h_

/**
  * Function to initialize the state of the Keccak[r, c] sponge function.
  * The sponge function is set to the absorbing phase.
  * @param  state       Pointer to the state of the sponge function to be initialized.
  * @param  rate        The value of the rate r.
  * @param  capacity    The value of the capacity c.
  * @pre    One must have r+c=1600 and the rate a multiple of 64 bits in this implementation.
  * @return Zero if successful, 1 otherwise.
  */
int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity);
/**
  * Function to give input data for the sponge function to absorb.
  * @param  state       Pointer to the state of the sponge function initialized by InitSponge().
  * @param  data        Pointer to the input data. 
  *                     When @a databitLen is not a multiple of 8, the last bits of data must be
  *                     in the least significant bits of the last byte.
  * @param  databitLen  The number of input bits provided in the input data.
  * @pre    In the previous call to Absorb(), databitLen was a multiple of 8.
  * @pre    The sponge function must be in the absorbing phase,
  *         i.e., Squeeze() must not have been called before.
  * @return Zero if successful, 1 otherwise.
  */
int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen);
/**
  * Function to squeeze output data from the sponge function.
  * If the sponge function was in the absorbing phase, this function 
  * switches it to the squeezing phase.
  * @param  state       Pointer to the state of the sponge function initialized by InitSponge().
  * @param  output      Pointer to the buffer where to store the output data.
  * @param  outputLength    The number of output bits desired.
  *                     It must be a multiple of 8.
  * @return Zero if successful, 1 otherwise.
  */
int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength);

#endif

// ================================================================================
// =================== KeccakF-1600-int-set.h
// ================================================================================


#define ProvideFast576
#define ProvideFast832
#define ProvideFast1024
#define ProvideFast1088
#define ProvideFast1152
#define ProvideFast1344


// ================================================================================
// =================== KeccakF-1600-interface.h
// ================================================================================


/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/

Implementation by the designers,
hereby denoted as "the implementer".

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#ifndef _KeccakPermutationInterface_h_
#define _KeccakPermutationInterface_h_

//#include "KeccakF-1600-int-set.h"

void KeccakInitialize( void );
void KeccakInitializeState(unsigned char *state);
void KeccakPermutation(unsigned char *state);
#ifdef ProvideFast576
void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast832
void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast1024
void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast1088
void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast1152
void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast1344
void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data);
#endif
void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount);
#ifdef ProvideFast1024
void KeccakExtract1024bits(const unsigned char *state, unsigned char *data);
#endif
void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount);

#endif


// ================================================================================
// =================== KeccakF-1600-opt32-settings.h
// ================================================================================


#define Unrolling 2
//#define UseBebigokimisa
//#define UseInterleaveTables
#define UseSchedule 3


// ================================================================================
// =================== KeccakF-1600-unrolling.macros
// ================================================================================

/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/

Implementation by the designers,
hereby denoted as "the implementer".

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#if (Unrolling == 24)
#define rounds \
    prepareTheta \
    thetaRhoPiChiIotaPrepareTheta( 0, A, E) \
    thetaRhoPiChiIotaPrepareTheta( 1, E, A) \
    thetaRhoPiChiIotaPrepareTheta( 2, A, E) \
    thetaRhoPiChiIotaPrepareTheta( 3, E, A) \
    thetaRhoPiChiIotaPrepareTheta( 4, A, E) \
    thetaRhoPiChiIotaPrepareTheta( 5, E, A) \
    thetaRhoPiChiIotaPrepareTheta( 6, A, E) \
    thetaRhoPiChiIotaPrepareTheta( 7, E, A) \
    thetaRhoPiChiIotaPrepareTheta( 8, A, E) \
    thetaRhoPiChiIotaPrepareTheta( 9, E, A) \
    thetaRhoPiChiIotaPrepareTheta(10, A, E) \
    thetaRhoPiChiIotaPrepareTheta(11, E, A) \
    thetaRhoPiChiIotaPrepareTheta(12, A, E) \
    thetaRhoPiChiIotaPrepareTheta(13, E, A) \
    thetaRhoPiChiIotaPrepareTheta(14, A, E) \
    thetaRhoPiChiIotaPrepareTheta(15, E, A) \
    thetaRhoPiChiIotaPrepareTheta(16, A, E) \
    thetaRhoPiChiIotaPrepareTheta(17, E, A) \
    thetaRhoPiChiIotaPrepareTheta(18, A, E) \
    thetaRhoPiChiIotaPrepareTheta(19, E, A) \
    thetaRhoPiChiIotaPrepareTheta(20, A, E) \
    thetaRhoPiChiIotaPrepareTheta(21, E, A) \
    thetaRhoPiChiIotaPrepareTheta(22, A, E) \
    thetaRhoPiChiIota(23, E, A) \
    copyToState(state, A)
#elif (Unrolling == 12)
#define rounds \
    prepareTheta \
    for(i=0; i<24; i+=12) { \
        thetaRhoPiChiIotaPrepareTheta(i   , A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \
    } \
    copyToState(state, A)
#elif (Unrolling == 8)
#define rounds \
    prepareTheta \
    for(i=0; i<24; i+=8) { \
        thetaRhoPiChiIotaPrepareTheta(i  , A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+6, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+7, E, A) \
    } \
    copyToState(state, A)
#elif (Unrolling == 6)
#define rounds \
    prepareTheta \
    for(i=0; i<24; i+=6) { \
        thetaRhoPiChiIotaPrepareTheta(i  , A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
    } \
    copyToState(state, A)
#elif (Unrolling == 4)
#define rounds \
    prepareTheta \
    for(i=0; i<24; i+=4) { \
        thetaRhoPiChiIotaPrepareTheta(i  , A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
    } \
    copyToState(state, A)
#elif (Unrolling == 3)
#define rounds \
    prepareTheta \
    for(i=0; i<24; i+=3) { \
        thetaRhoPiChiIotaPrepareTheta(i  , A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
        thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
        copyStateVariables(A, E) \
    } \
    copyToState(state, A)
#elif (Unrolling == 2)
#define rounds \
    prepareTheta \
    for(i=0; i<24; i+=2) { \
        thetaRhoPiChiIotaPrepareTheta(i  , A, E) \
        thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
    } \
    copyToState(state, A)
#elif (Unrolling == 1)
#define rounds \
    prepareTheta \
    for(i=0; i<24; i++) { \
        thetaRhoPiChiIotaPrepareTheta(i  , A, E) \
        copyStateVariables(A, E) \
    } \
    copyToState(state, A)
#else
#error "Unrolling is not correctly specified!"
#endif


// ================================================================================
// =================== KeccakF-1600-32-rvk.macros
// ================================================================================

/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/

Implementation by Ronny Van Keer,
hereby denoted as "the implementer".

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

static const UINT32 KeccakF1600RoundConstants_int2[2*24] =
{
    0x00000001UL,    0x00000000UL,
    0x00000000UL,    0x00000089UL,
    0x00000000UL,    0x8000008bUL,
    0x00000000UL,    0x80008080UL,
    0x00000001UL,    0x0000008bUL,
    0x00000001UL,    0x00008000UL,
    0x00000001UL,    0x80008088UL,
    0x00000001UL,    0x80000082UL,
    0x00000000UL,    0x0000000bUL,
    0x00000000UL,    0x0000000aUL,
    0x00000001UL,    0x00008082UL,
    0x00000000UL,    0x00008003UL,
    0x00000001UL,    0x0000808bUL,
    0x00000001UL,    0x8000000bUL,
    0x00000001UL,    0x8000008aUL,
    0x00000001UL,    0x80000081UL,
    0x00000000UL,    0x80000081UL,
    0x00000000UL,    0x80000008UL,
    0x00000000UL,    0x00000083UL,
    0x00000000UL,    0x80008003UL,
    0x00000001UL,    0x80008088UL,
    0x00000000UL,    0x80000088UL,
    0x00000001UL,    0x00008000UL,
    0x00000000UL,    0x80008082UL
};

#undef rounds

#define rounds \
{ \
    UINT32 Da0, De0, Di0, Do0, Du0; \
    UINT32 Da1, De1, Di1, Do1, Du1; \
    UINT32 Ba, Be, Bi, Bo, Bu; \
    UINT32 Aba0, Abe0, Abi0, Abo0, Abu0; \
    UINT32 Aba1, Abe1, Abi1, Abo1, Abu1; \
    UINT32 Aga0, Age0, Agi0, Ago0, Agu0; \
    UINT32 Aga1, Age1, Agi1, Ago1, Agu1; \
    UINT32 Aka0, Ake0, Aki0, Ako0, Aku0; \
    UINT32 Aka1, Ake1, Aki1, Ako1, Aku1; \
    UINT32 Ama0, Ame0, Ami0, Amo0, Amu0; \
    UINT32 Ama1, Ame1, Ami1, Amo1, Amu1; \
    UINT32 Asa0, Ase0, Asi0, Aso0, Asu0; \
    UINT32 Asa1, Ase1, Asi1, Aso1, Asu1; \
    UINT32 Cw, Cx, Cy, Cz; \
    UINT32 Eba0, Ebe0, Ebi0, Ebo0, Ebu0; \
    UINT32 Eba1, Ebe1, Ebi1, Ebo1, Ebu1; \
    UINT32 Ega0, Ege0, Egi0, Ego0, Egu0; \
    UINT32 Ega1, Ege1, Egi1, Ego1, Egu1; \
    UINT32 Eka0, Eke0, Eki0, Eko0, Eku0; \
    UINT32 Eka1, Eke1, Eki1, Eko1, Eku1; \
    UINT32 Ema0, Eme0, Emi0, Emo0, Emu0; \
    UINT32 Ema1, Eme1, Emi1, Emo1, Emu1; \
    UINT32 Esa0, Ese0, Esi0, Eso0, Esu0; \
    UINT32 Esa1, Ese1, Esi1, Eso1, Esu1; \
	const UINT32 * pRoundConstants = KeccakF1600RoundConstants_int2; \
    UINT32 i; \
\
    copyFromState(A, state) \
\
    for( i = 12; i != 0; --i ) { \
	    Cx = Abu0^Agu0^Aku0^Amu0^Asu0; \
	    Du1 = Abe1^Age1^Ake1^Ame1^Ase1; \
	    Da0 = Cx^ROL32(Du1, 1); \
	    Cz = Abu1^Agu1^Aku1^Amu1^Asu1; \
	    Du0 = Abe0^Age0^Ake0^Ame0^Ase0; \
	    Da1 = Cz^Du0; \
\
	    Cw = Abi0^Agi0^Aki0^Ami0^Asi0; \
	    Do0 = Cw^ROL32(Cz, 1); \
	    Cy = Abi1^Agi1^Aki1^Ami1^Asi1; \
	    Do1 = Cy^Cx; \
\
	    Cx = Aba0^Aga0^Aka0^Ama0^Asa0; \
	    De0 = Cx^ROL32(Cy, 1); \
	    Cz = Aba1^Aga1^Aka1^Ama1^Asa1; \
	    De1 = Cz^Cw; \
\
	    Cy = Abo1^Ago1^Ako1^Amo1^Aso1; \
	    Di0 = Du0^ROL32(Cy, 1); \
	    Cw = Abo0^Ago0^Ako0^Amo0^Aso0; \
	    Di1 = Du1^Cw; \
\
	    Du0 = Cw^ROL32(Cz, 1); \
	    Du1 = Cy^Cx; \
\
	    Aba0 ^= Da0; \
	    Ba = Aba0; \
	    Age0 ^= De0; \
	    Be = ROL32(Age0, 22); \
	    Aki1 ^= Di1; \
	    Bi = ROL32(Aki1, 22); \
	    Amo1 ^= Do1; \
	    Bo = ROL32(Amo1, 11); \
	    Asu0 ^= Du0; \
	    Bu = ROL32(Asu0, 7); \
	    Eba0 =   Ba ^((~Be)&  Bi ) ^ *(pRoundConstants++); \
	    Ebe0 =   Be ^((~Bi)&  Bo ); \
	    Ebi0 =   Bi ^((~Bo)&  Bu ); \
	    Ebo0 =   Bo ^((~Bu)&  Ba ); \
	    Ebu0 =   Bu ^((~Ba)&  Be ); \
\
	    Abo0 ^= Do0; \
	    Ba = ROL32(Abo0, 14); \
	    Agu0 ^= Du0; \
	    Be = ROL32(Agu0, 10); \
	    Aka1 ^= Da1; \
	    Bi = ROL32(Aka1, 2); \
	    Ame1 ^= De1; \
	    Bo = ROL32(Ame1, 23); \
	    Asi1 ^= Di1; \
	    Bu = ROL32(Asi1, 31); \
	    Ega0 =   Ba ^((~Be)&  Bi ); \
	    Ege0 =   Be ^((~Bi)&  Bo ); \
	    Egi0 =   Bi ^((~Bo)&  Bu ); \
	    Ego0 =   Bo ^((~Bu)&  Ba ); \
	    Egu0 =   Bu ^((~Ba)&  Be ); \
\
	    Abe1 ^= De1; \
	    Ba = ROL32(Abe1, 1); \
	    Agi0 ^= Di0; \
	    Be = ROL32(Agi0, 3); \
	    Ako1 ^= Do1; \
	    Bi = ROL32(Ako1, 13); \
	    Amu0 ^= Du0; \
	    Bo = ROL32(Amu0, 4); \
	    Asa0 ^= Da0; \
	    Bu = ROL32(Asa0, 9); \
	    Eka0 =   Ba ^((~Be)&  Bi ); \
	    Eke0 =   Be ^((~Bi)&  Bo ); \
	    Eki0 =   Bi ^((~Bo)&  Bu ); \
	    Eko0 =   Bo ^((~Bu)&  Ba ); \
	    Eku0 =   Bu ^((~Ba)&  Be ); \
\
	    Abu1 ^= Du1; \
	    Ba = ROL32(Abu1, 14); \
	    Aga0 ^= Da0; \
	    Be = ROL32(Aga0, 18); \
	    Ake0 ^= De0; \
	    Bi = ROL32(Ake0, 5); \
	    Ami1 ^= Di1; \
	    Bo = ROL32(Ami1, 8); \
	    Aso0 ^= Do0; \
	    Bu = ROL32(Aso0, 28); \
	    Ema0 =   Ba ^((~Be)&  Bi ); \
	    Eme0 =   Be ^((~Bi)&  Bo ); \
	    Emi0 =   Bi ^((~Bo)&  Bu ); \
	    Emo0 =   Bo ^((~Bu)&  Ba ); \
	    Emu0 =   Bu ^((~Ba)&  Be ); \
\
	    Abi0 ^= Di0; \
	    Ba = ROL32(Abi0, 31); \
	    Ago1 ^= Do1; \
	    Be = ROL32(Ago1, 28); \
	    Aku1 ^= Du1; \
	    Bi = ROL32(Aku1, 20); \
	    Ama1 ^= Da1; \
	    Bo = ROL32(Ama1, 21); \
	    Ase0 ^= De0; \
	    Bu = ROL32(Ase0, 1); \
	    Esa0 =   Ba ^((~Be)&  Bi ); \
	    Ese0 =   Be ^((~Bi)&  Bo ); \
	    Esi0 =   Bi ^((~Bo)&  Bu ); \
	    Eso0 =   Bo ^((~Bu)&  Ba ); \
	    Esu0 =   Bu ^((~Ba)&  Be ); \
\
	    Aba1 ^= Da1; \
	    Ba = Aba1; \
	    Age1 ^= De1; \
	    Be = ROL32(Age1, 22); \
	    Aki0 ^= Di0; \
	    Bi = ROL32(Aki0, 21); \
	    Amo0 ^= Do0; \
	    Bo = ROL32(Amo0, 10); \
	    Asu1 ^= Du1; \
	    Bu = ROL32(Asu1, 7); \
	    Eba1 =   Ba ^((~Be)&  Bi ); \
	    Eba1 ^= *(pRoundConstants++); \
	    Ebe1 =   Be ^((~Bi)&  Bo ); \
	    Ebi1 =   Bi ^((~Bo)&  Bu ); \
	    Ebo1 =   Bo ^((~Bu)&  Ba ); \
	    Ebu1 =   Bu ^((~Ba)&  Be ); \
\
	    Abo1 ^= Do1; \
	    Ba = ROL32(Abo1, 14); \
	    Agu1 ^= Du1; \
	    Be = ROL32(Agu1, 10); \
	    Aka0 ^= Da0; \
	    Bi = ROL32(Aka0, 1); \
	    Ame0 ^= De0; \
	    Bo = ROL32(Ame0, 22); \
	    Asi0 ^= Di0; \
	    Bu = ROL32(Asi0, 30); \
	    Ega1 =   Ba ^((~Be)&  Bi ); \
	    Ege1 =   Be ^((~Bi)&  Bo ); \
	    Egi1 =   Bi ^((~Bo)&  Bu ); \
	    Ego1 =   Bo ^((~Bu)&  Ba ); \
	    Egu1 =   Bu ^((~Ba)&  Be ); \
\
	    Abe0 ^= De0; \
	    Ba = Abe0; \
	    Agi1 ^= Di1; \
	    Be = ROL32(Agi1, 3); \
	    Ako0 ^= Do0; \
	    Bi = ROL32(Ako0, 12); \
	    Amu1 ^= Du1; \
	    Bo = ROL32(Amu1, 4); \
	    Asa1 ^= Da1; \
	    Bu = ROL32(Asa1, 9); \
	    Eka1 =   Ba ^((~Be)&  Bi ); \
	    Eke1 =   Be ^((~Bi)&  Bo ); \
	    Eki1 =   Bi ^((~Bo)&  Bu ); \
	    Eko1 =   Bo ^((~Bu)&  Ba ); \
	    Eku1 =   Bu ^((~Ba)&  Be ); \
\
	    Abu0 ^= Du0; \
	    Ba = ROL32(Abu0, 13); \
	    Aga1 ^= Da1; \
	    Be = ROL32(Aga1, 18); \
	    Ake1 ^= De1; \
	    Bi = ROL32(Ake1, 5); \
	    Ami0 ^= Di0; \
	    Bo = ROL32(Ami0, 7); \
	    Aso1 ^= Do1; \
	    Bu = ROL32(Aso1, 28); \
	    Ema1 =   Ba ^((~Be)&  Bi ); \
	    Eme1 =   Be ^((~Bi)&  Bo ); \
	    Emi1 =   Bi ^((~Bo)&  Bu ); \
	    Emo1 =   Bo ^((~Bu)&  Ba ); \
	    Emu1 =   Bu ^((~Ba)&  Be ); \
\
	    Abi1 ^= Di1; \
	    Ba = ROL32(Abi1, 31); \
	    Ago0 ^= Do0; \
	    Be = ROL32(Ago0, 27); \
	    Aku0 ^= Du0; \
	    Bi = ROL32(Aku0, 19); \
	    Ama0 ^= Da0; \
	    Bo = ROL32(Ama0, 20); \
	    Ase1 ^= De1; \
	    Bu = ROL32(Ase1, 1); \
	    Esa1 =   Ba ^((~Be)&  Bi ); \
	    Ese1 =   Be ^((~Bi)&  Bo ); \
	    Esi1 =   Bi ^((~Bo)&  Bu ); \
	    Eso1 =   Bo ^((~Bu)&  Ba ); \
	    Esu1 =   Bu ^((~Ba)&  Be ); \
\
	    Cx = Ebu0^Egu0^Eku0^Emu0^Esu0; \
	    Du1 = Ebe1^Ege1^Eke1^Eme1^Ese1; \
	    Da0 = Cx^ROL32(Du1, 1); \
	    Cz = Ebu1^Egu1^Eku1^Emu1^Esu1; \
	    Du0 = Ebe0^Ege0^Eke0^Eme0^Ese0; \
	    Da1 = Cz^Du0; \
\
	    Cw = Ebi0^Egi0^Eki0^Emi0^Esi0; \
	    Do0 = Cw^ROL32(Cz, 1); \
	    Cy = Ebi1^Egi1^Eki1^Emi1^Esi1; \
	    Do1 = Cy^Cx; \
\
	    Cx = Eba0^Ega0^Eka0^Ema0^Esa0; \
	    De0 = Cx^ROL32(Cy, 1); \
	    Cz = Eba1^Ega1^Eka1^Ema1^Esa1; \
	    De1 = Cz^Cw; \
\
	    Cy = Ebo1^Ego1^Eko1^Emo1^Eso1; \
	    Di0 = Du0^ROL32(Cy, 1); \
	    Cw = Ebo0^Ego0^Eko0^Emo0^Eso0; \
	    Di1 = Du1^Cw; \
\
	    Du0 = Cw^ROL32(Cz, 1); \
	    Du1 = Cy^Cx; \
\
	    Eba0 ^= Da0; \
	    Ba = Eba0; \
	    Ege0 ^= De0; \
	    Be = ROL32(Ege0, 22); \
	    Eki1 ^= Di1; \
	    Bi = ROL32(Eki1, 22); \
	    Emo1 ^= Do1; \
	    Bo = ROL32(Emo1, 11); \
	    Esu0 ^= Du0; \
	    Bu = ROL32(Esu0, 7); \
	    Aba0 =   Ba ^((~Be)&  Bi ); \
	    Aba0 ^= *(pRoundConstants++); \
	    Abe0 =   Be ^((~Bi)&  Bo ); \
	    Abi0 =   Bi ^((~Bo)&  Bu ); \
	    Abo0 =   Bo ^((~Bu)&  Ba ); \
	    Abu0 =   Bu ^((~Ba)&  Be ); \
\
	    Ebo0 ^= Do0; \
	    Ba = ROL32(Ebo0, 14); \
	    Egu0 ^= Du0; \
	    Be = ROL32(Egu0, 10); \
	    Eka1 ^= Da1; \
	    Bi = ROL32(Eka1, 2); \
	    Eme1 ^= De1; \
	    Bo = ROL32(Eme1, 23); \
	    Esi1 ^= Di1; \
	    Bu = ROL32(Esi1, 31); \
	    Aga0 =   Ba ^((~Be)&  Bi ); \
	    Age0 =   Be ^((~Bi)&  Bo ); \
	    Agi0 =   Bi ^((~Bo)&  Bu ); \
	    Ago0 =   Bo ^((~Bu)&  Ba ); \
	    Agu0 =   Bu ^((~Ba)&  Be ); \
\
	    Ebe1 ^= De1; \
	    Ba = ROL32(Ebe1, 1); \
	    Egi0 ^= Di0; \
	    Be = ROL32(Egi0, 3); \
	    Eko1 ^= Do1; \
	    Bi = ROL32(Eko1, 13); \
	    Emu0 ^= Du0; \
	    Bo = ROL32(Emu0, 4); \
	    Esa0 ^= Da0; \
	    Bu = ROL32(Esa0, 9); \
	    Aka0 =   Ba ^((~Be)&  Bi ); \
	    Ake0 =   Be ^((~Bi)&  Bo ); \
	    Aki0 =   Bi ^((~Bo)&  Bu ); \
	    Ako0 =   Bo ^((~Bu)&  Ba ); \
	    Aku0 =   Bu ^((~Ba)&  Be ); \
\
	    Ebu1 ^= Du1; \
	    Ba = ROL32(Ebu1, 14); \
	    Ega0 ^= Da0; \
	    Be = ROL32(Ega0, 18); \
	    Eke0 ^= De0; \
	    Bi = ROL32(Eke0, 5); \
	    Emi1 ^= Di1; \
	    Bo = ROL32(Emi1, 8); \
	    Eso0 ^= Do0; \
	    Bu = ROL32(Eso0, 28); \
	    Ama0 =   Ba ^((~Be)&  Bi ); \
	    Ame0 =   Be ^((~Bi)&  Bo ); \
	    Ami0 =   Bi ^((~Bo)&  Bu ); \
	    Amo0 =   Bo ^((~Bu)&  Ba ); \
	    Amu0 =   Bu ^((~Ba)&  Be ); \
\
	    Ebi0 ^= Di0; \
	    Ba = ROL32(Ebi0, 31); \
	    Ego1 ^= Do1; \
	    Be = ROL32(Ego1, 28); \
	    Eku1 ^= Du1; \
	    Bi = ROL32(Eku1, 20); \
	    Ema1 ^= Da1; \
	    Bo = ROL32(Ema1, 21); \
	    Ese0 ^= De0; \
	    Bu = ROL32(Ese0, 1); \
	    Asa0 =   Ba ^((~Be)&  Bi ); \
	    Ase0 =   Be ^((~Bi)&  Bo ); \
	    Asi0 =   Bi ^((~Bo)&  Bu ); \
	    Aso0 =   Bo ^((~Bu)&  Ba ); \
	    Asu0 =   Bu ^((~Ba)&  Be ); \
\
	    Eba1 ^= Da1; \
	    Ba = Eba1; \
	    Ege1 ^= De1; \
	    Be = ROL32(Ege1, 22); \
	    Eki0 ^= Di0; \
	    Bi = ROL32(Eki0, 21); \
	    Emo0 ^= Do0; \
	    Bo = ROL32(Emo0, 10); \
	    Esu1 ^= Du1; \
	    Bu = ROL32(Esu1, 7); \
	    Aba1 =   Ba ^((~Be)&  Bi ); \
	    Aba1 ^= *(pRoundConstants++); \
	    Abe1 =   Be ^((~Bi)&  Bo ); \
	    Abi1 =   Bi ^((~Bo)&  Bu ); \
	    Abo1 =   Bo ^((~Bu)&  Ba ); \
	    Abu1 =   Bu ^((~Ba)&  Be ); \
\
	    Ebo1 ^= Do1; \
	    Ba = ROL32(Ebo1, 14); \
	    Egu1 ^= Du1; \
	    Be = ROL32(Egu1, 10); \
	    Eka0 ^= Da0; \
	    Bi = ROL32(Eka0, 1); \
	    Eme0 ^= De0; \
	    Bo = ROL32(Eme0, 22); \
	    Esi0 ^= Di0; \
	    Bu = ROL32(Esi0, 30); \
	    Aga1 =   Ba ^((~Be)&  Bi ); \
	    Age1 =   Be ^((~Bi)&  Bo ); \
	    Agi1 =   Bi ^((~Bo)&  Bu ); \
	    Ago1 =   Bo ^((~Bu)&  Ba ); \
	    Agu1 =   Bu ^((~Ba)&  Be ); \
\
	    Ebe0 ^= De0; \
	    Ba = Ebe0; \
	    Egi1 ^= Di1; \
	    Be = ROL32(Egi1, 3); \
	    Eko0 ^= Do0; \
	    Bi = ROL32(Eko0, 12); \
	    Emu1 ^= Du1; \
	    Bo = ROL32(Emu1, 4); \
	    Esa1 ^= Da1; \
	    Bu = ROL32(Esa1, 9); \
	    Aka1 =   Ba ^((~Be)&  Bi ); \
	    Ake1 =   Be ^((~Bi)&  Bo ); \
	    Aki1 =   Bi ^((~Bo)&  Bu ); \
	    Ako1 =   Bo ^((~Bu)&  Ba ); \
	    Aku1 =   Bu ^((~Ba)&  Be ); \
\
	    Ebu0 ^= Du0; \
	    Ba = ROL32(Ebu0, 13); \
	    Ega1 ^= Da1; \
	    Be = ROL32(Ega1, 18); \
	    Eke1 ^= De1; \
	    Bi = ROL32(Eke1, 5); \
	    Emi0 ^= Di0; \
	    Bo = ROL32(Emi0, 7); \
	    Eso1 ^= Do1; \
	    Bu = ROL32(Eso1, 28); \
	    Ama1 =   Ba ^((~Be)&  Bi ); \
	    Ame1 =   Be ^((~Bi)&  Bo ); \
	    Ami1 =   Bi ^((~Bo)&  Bu ); \
	    Amo1 =   Bo ^((~Bu)&  Ba ); \
	    Amu1 =   Bu ^((~Ba)&  Be ); \
\
	    Ebi1 ^= Di1; \
	    Ba = ROL32(Ebi1, 31); \
	    Ego0 ^= Do0; \
	    Be = ROL32(Ego0, 27); \
	    Eku0 ^= Du0; \
	    Bi = ROL32(Eku0, 19); \
	    Ema0 ^= Da0; \
	    Bo = ROL32(Ema0, 20); \
	    Ese1 ^= De1; \
	    Bu = ROL32(Ese1, 1); \
	    Asa1 =   Ba ^((~Be)&  Bi ); \
	    Ase1 =   Be ^((~Bi)&  Bo ); \
	    Asi1 =   Bi ^((~Bo)&  Bu ); \
	    Aso1 =   Bo ^((~Bu)&  Ba ); \
	    Asu1 =   Bu ^((~Ba)&  Be ); \
    } \
    copyToState(state, A) \
}

#define copyFromState(X, state) \
    X##ba0 = state[ 0]; \
    X##ba1 = state[ 1]; \
    X##be0 = state[ 2]; \
    X##be1 = state[ 3]; \
    X##bi0 = state[ 4]; \
    X##bi1 = state[ 5]; \
    X##bo0 = state[ 6]; \
    X##bo1 = state[ 7]; \
    X##bu0 = state[ 8]; \
    X##bu1 = state[ 9]; \
    X##ga0 = state[10]; \
    X##ga1 = state[11]; \
    X##ge0 = state[12]; \
    X##ge1 = state[13]; \
    X##gi0 = state[14]; \
    X##gi1 = state[15]; \
    X##go0 = state[16]; \
    X##go1 = state[17]; \
    X##gu0 = state[18]; \
    X##gu1 = state[19]; \
    X##ka0 = state[20]; \
    X##ka1 = state[21]; \
    X##ke0 = state[22]; \
    X##ke1 = state[23]; \
    X##ki0 = state[24]; \
    X##ki1 = state[25]; \
    X##ko0 = state[26]; \
    X##ko1 = state[27]; \
    X##ku0 = state[28]; \
    X##ku1 = state[29]; \
    X##ma0 = state[30]; \
    X##ma1 = state[31]; \
    X##me0 = state[32]; \
    X##me1 = state[33]; \
    X##mi0 = state[34]; \
    X##mi1 = state[35]; \
    X##mo0 = state[36]; \
    X##mo1 = state[37]; \
    X##mu0 = state[38]; \
    X##mu1 = state[39]; \
    X##sa0 = state[40]; \
    X##sa1 = state[41]; \
    X##se0 = state[42]; \
    X##se1 = state[43]; \
    X##si0 = state[44]; \
    X##si1 = state[45]; \
    X##so0 = state[46]; \
    X##so1 = state[47]; \
    X##su0 = state[48]; \
    X##su1 = state[49]; \

#define copyToState(state, X) \
    state[ 0] = X##ba0; \
    state[ 1] = X##ba1; \
    state[ 2] = X##be0; \
    state[ 3] = X##be1; \
    state[ 4] = X##bi0; \
    state[ 5] = X##bi1; \
    state[ 6] = X##bo0; \
    state[ 7] = X##bo1; \
    state[ 8] = X##bu0; \
    state[ 9] = X##bu1; \
    state[10] = X##ga0; \
    state[11] = X##ga1; \
    state[12] = X##ge0; \
    state[13] = X##ge1; \
    state[14] = X##gi0; \
    state[15] = X##gi1; \
    state[16] = X##go0; \
    state[17] = X##go1; \
    state[18] = X##gu0; \
    state[19] = X##gu1; \
    state[20] = X##ka0; \
    state[21] = X##ka1; \
    state[22] = X##ke0; \
    state[23] = X##ke1; \
    state[24] = X##ki0; \
    state[25] = X##ki1; \
    state[26] = X##ko0; \
    state[27] = X##ko1; \
    state[28] = X##ku0; \
    state[29] = X##ku1; \
    state[30] = X##ma0; \
    state[31] = X##ma1; \
    state[32] = X##me0; \
    state[33] = X##me1; \
    state[34] = X##mi0; \
    state[35] = X##mi1; \
    state[36] = X##mo0; \
    state[37] = X##mo1; \
    state[38] = X##mu0; \
    state[39] = X##mu1; \
    state[40] = X##sa0; \
    state[41] = X##sa1; \
    state[42] = X##se0; \
    state[43] = X##se1; \
    state[44] = X##si0; \
    state[45] = X##si1; \
    state[46] = X##so0; \
    state[47] = X##so1; \
    state[48] = X##su0; \
    state[49] = X##su1; \


// ================================================================================
// =================== KeccakF-1600-32.macros
// ================================================================================

/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/

Implementation by the designers,
hereby denoted as "the implementer".

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#ifdef UseSchedule
    #if (UseSchedule == 1)
        #include "KeccakF-1600-32-s1.macros"
    #elif (UseSchedule == 2)
        #include "KeccakF-1600-32-s2.macros"
    #elif (UseSchedule == 3)
        //#include "KeccakF-1600-32-rvk.macros"
    #else
        #error "This schedule is not supported."
    #endif
#else
    #include "KeccakF-1600-32-s1.macros"
#endif

// ================================================================================
// =================== KeccakF-1600-opt32.c
// ================================================================================


/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/

Implementation by the designers,
hereby denoted as "the implementer".

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#include <string.h>
//#include "brg_endian.h"
//#include "KeccakF-1600-opt32-settings.h"
//#include "KeccakF-1600-interface.h"



#ifdef UseInterleaveTables
int interleaveTablesBuilt = 0;
UINT16 interleaveTable[65536];
UINT16 deinterleaveTable[65536];

void buildInterleaveTables()
{
    UINT32 i, j;
    UINT16 x;

    if (!interleaveTablesBuilt) {
        for(i=0; i<65536; i++) {
            x = 0;
            for(j=0; j<16; j++) {
                if (i & (1 << j))
                    x |= (1 << (j/2 + 8*(j%2)));
            }
            interleaveTable[i] = x;
            deinterleaveTable[x] = (UINT16)i;
        }
        interleaveTablesBuilt = 1;
    }
}

#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)

#define xor2bytesIntoInterleavedWords(even, odd, source, j) \
    i##j = interleaveTable[((const UINT16*)source)[j]]; \
    ((UINT8*)even)[j] ^= i##j & 0xFF; \
    ((UINT8*)odd)[j] ^= i##j >> 8;

#define setInterleavedWordsInto2bytes(dest, even, odd, j) \
    d##j = deinterleaveTable[((even >> (j*8)) & 0xFF) ^ (((odd >> (j*8)) & 0xFF) << 8)]; \
    ((UINT16*)dest)[j] = d##j;

#else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN)

#define xor2bytesIntoInterleavedWords(even, odd, source, j) \
    i##j = interleaveTable[source[2*j] ^ ((UINT16)source[2*j+1] << 8)]; \
    *even ^= (i##j & 0xFF) << (j*8); \
    *odd ^= ((i##j >> 8) & 0xFF) << (j*8);

#define setInterleavedWordsInto2bytes(dest, even, odd, j) \
    d##j = deinterleaveTable[((even >> (j*8)) & 0xFF) ^ (((odd >> (j*8)) & 0xFF) << 8)]; \
    dest[2*j] = d##j & 0xFF; \
    dest[2*j+1] = d##j >> 8;

#endif // Endianness

void xor8bytesIntoInterleavedWords(UINT32 *even, UINT32 *odd, const UINT8* source)
{
    UINT16 i0, i1, i2, i3;

    xor2bytesIntoInterleavedWords(even, odd, source, 0)
    xor2bytesIntoInterleavedWords(even, odd, source, 1)
    xor2bytesIntoInterleavedWords(even, odd, source, 2)
    xor2bytesIntoInterleavedWords(even, odd, source, 3)
}

#define xorLanesIntoState(laneCount, state, input) \
    { \
        int i; \
        for(i=0; i<(laneCount); i++) \
            xor8bytesIntoInterleavedWords(state+i*2, state+i*2+1, input+i*8); \
    }

void setInterleavedWordsInto8bytes(UINT8* dest, UINT32 even, UINT32 odd)
{
    UINT16 d0, d1, d2, d3;

    setInterleavedWordsInto2bytes(dest, even, odd, 0)
    setInterleavedWordsInto2bytes(dest, even, odd, 1)
    setInterleavedWordsInto2bytes(dest, even, odd, 2)
    setInterleavedWordsInto2bytes(dest, even, odd, 3)
}

#define extractLanes(laneCount, state, data) \
    { \
        int i; \
        for(i=0; i<(laneCount); i++) \
            setInterleavedWordsInto8bytes(data+i*8, ((UINT32*)state)[i*2], ((UINT32*)state)[i*2+1]); \
    }

#else // No interleaving tables

#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)

// Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
#define xorInterleavedLE(rateInLanes, state, input) \
	{ \
		const UINT32 * pI = (const UINT32 *)input; \
		UINT32 * pS = state; \
		UINT32 t, x0, x1; \
	    int i; \
	    for (i = (rateInLanes)-1; i >= 0; --i) \
		{ \
			x0 = *(pI++); \
			t = (x0 ^ (x0 >>  1)) & 0x22222222UL;  x0 = x0 ^ t ^ (t <<  1); \
			t = (x0 ^ (x0 >>  2)) & 0x0C0C0C0CUL;  x0 = x0 ^ t ^ (t <<  2); \
			t = (x0 ^ (x0 >>  4)) & 0x00F000F0UL;  x0 = x0 ^ t ^ (t <<  4); \
			t = (x0 ^ (x0 >>  8)) & 0x0000FF00UL;  x0 = x0 ^ t ^ (t <<  8); \
 			x1 = *(pI++); \
			t = (x1 ^ (x1 >>  1)) & 0x22222222UL;  x1 = x1 ^ t ^ (t <<  1); \
			t = (x1 ^ (x1 >>  2)) & 0x0C0C0C0CUL;  x1 = x1 ^ t ^ (t <<  2); \
			t = (x1 ^ (x1 >>  4)) & 0x00F000F0UL;  x1 = x1 ^ t ^ (t <<  4); \
			t = (x1 ^ (x1 >>  8)) & 0x0000FF00UL;  x1 = x1 ^ t ^ (t <<  8); \
			*(pS++) ^= (UINT16)x0 | (x1 << 16); \
			*(pS++) ^= (x0 >> 16) | (x1 & 0xFFFF0000); \
		} \
	}

#define xorLanesIntoState(laneCount, state, input) \
    xorInterleavedLE(laneCount, state, input)

#else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN)

// Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
UINT64 toInterleaving(UINT64 x) 
{
   UINT64 t;

   t = (x ^ (x >>  1)) & 0x2222222222222222ULL;  x = x ^ t ^ (t <<  1);
   t = (x ^ (x >>  2)) & 0x0C0C0C0C0C0C0C0CULL;  x = x ^ t ^ (t <<  2);
   t = (x ^ (x >>  4)) & 0x00F000F000F000F0ULL;  x = x ^ t ^ (t <<  4);
   t = (x ^ (x >>  8)) & 0x0000FF000000FF00ULL;  x = x ^ t ^ (t <<  8);
   t = (x ^ (x >> 16)) & 0x00000000FFFF0000ULL;  x = x ^ t ^ (t << 16);

   return x;
}

void xor8bytesIntoInterleavedWords(UINT32* evenAndOdd, const UINT8* source)
{
    // This can be optimized
    UINT64 sourceWord =
        (UINT64)source[0]
        ^ (((UINT64)source[1]) <<  8)
        ^ (((UINT64)source[2]) << 16)
        ^ (((UINT64)source[3]) << 24)
        ^ (((UINT64)source[4]) << 32)
        ^ (((UINT64)source[5]) << 40)
        ^ (((UINT64)source[6]) << 48)
        ^ (((UINT64)source[7]) << 56);
    UINT64 evenAndOddWord = toInterleaving(sourceWord);
    evenAndOdd[0] ^= (UINT32)evenAndOddWord;
    evenAndOdd[1] ^= (UINT32)(evenAndOddWord >> 32);
}

#define xorLanesIntoState(laneCount, state, input) \
    { \
        int i; \
        for(i=0; i<(laneCount); i++) \
            xor8bytesIntoInterleavedWords(state+i*2, input+i*8); \
    }

#endif // Endianness

// Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
UINT64 fromInterleaving(UINT64 x)
{
   UINT64 t;

   t = (x ^ (x >> 16)) & 0x00000000FFFF0000ULL;  x = x ^ t ^ (t << 16);
   t = (x ^ (x >>  8)) & 0x0000FF000000FF00ULL;  x = x ^ t ^ (t <<  8);
   t = (x ^ (x >>  4)) & 0x00F000F000F000F0ULL;  x = x ^ t ^ (t <<  4);
   t = (x ^ (x >>  2)) & 0x0C0C0C0C0C0C0C0CULL;  x = x ^ t ^ (t <<  2);
   t = (x ^ (x >>  1)) & 0x2222222222222222ULL;  x = x ^ t ^ (t <<  1);

   return x;
}

void setInterleavedWordsInto8bytes(UINT8* dest, UINT32* evenAndOdd)
{
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
    ((UINT64*)dest)[0] = fromInterleaving(*(UINT64*)evenAndOdd);
#else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN)
    // This can be optimized
    UINT64 evenAndOddWord = (UINT64)evenAndOdd[0] ^ ((UINT64)evenAndOdd[1] << 32);
    UINT64 destWord = fromInterleaving(evenAndOddWord);
    dest[0] = destWord & 0xFF;
    dest[1] = (destWord >> 8) & 0xFF;
    dest[2] = (destWord >> 16) & 0xFF;
    dest[3] = (destWord >> 24) & 0xFF;
    dest[4] = (destWord >> 32) & 0xFF;
    dest[5] = (destWord >> 40) & 0xFF;
    dest[6] = (destWord >> 48) & 0xFF;
    dest[7] = (destWord >> 56) & 0xFF;
#endif // Endianness
}

#define extractLanes(laneCount, state, data) \
    { \
        int i; \
        for(i=0; i<(laneCount); i++) \
            setInterleavedWordsInto8bytes(data+i*8, (UINT32*)state+i*2); \
    }

#endif // With or without interleaving tables

#if defined(_MSC_VER)
#define ROL32(a, offset) _rotl(a, offset)
#elif (defined (__arm__) && defined(__ARMCC_VERSION))
#define ROL32(a, offset) __ror(a, 32-(offset))
#else
#define ROL32(a, offset) ((((UINT32)a) << (offset)) ^ (((UINT32)a) >> (32-(offset))))
#endif

//#include "KeccakF-1600-unrolling.macros"
//#include "KeccakF-1600-32.macros"

#if (UseSchedule == 3)

#ifdef UseBebigokimisa
#error "No lane complementing with schedule 3."
#endif

#if (Unrolling != 2)
#error "Only unrolling 2 is supported by schedule 3."
#endif

void KeccakPermutationOnWords(UINT32 *state)
{
    rounds
}

void KeccakPermutationOnWordsAfterXoring(UINT32 *state, const UINT8 *input, unsigned int laneCount)
{
    xorLanesIntoState(laneCount, state, input)
    rounds
}

#ifdef ProvideFast576
void KeccakPermutationOnWordsAfterXoring576bits(UINT32 *state, const UINT8 *input)
{
    xorLanesIntoState(9, state, input)
    rounds
}
#endif

#ifdef ProvideFast832
void KeccakPermutationOnWordsAfterXoring832bits(UINT32 *state, const UINT8 *input)
{
    xorLanesIntoState(13, state, input)
    rounds
}
#endif

#ifdef ProvideFast1024
void KeccakPermutationOnWordsAfterXoring1024bits(UINT32 *state, const UINT8 *input)
{
    xorLanesIntoState(16, state, input)
    rounds
}
#endif

#ifdef ProvideFast1088
void KeccakPermutationOnWordsAfterXoring1088bits(UINT32 *state, const UINT8 *input)
{
    xorLanesIntoState(17, state, input)
    rounds
}
#endif

#ifdef ProvideFast1152
void KeccakPermutationOnWordsAfterXoring1152bits(UINT32 *state, const UINT8 *input)
{
    xorLanesIntoState(18, state, input)
    rounds
}
#endif

#ifdef ProvideFast1344
void KeccakPermutationOnWordsAfterXoring1344bits(UINT32 *state, const UINT8 *input)
{
    xorLanesIntoState(21, state, input)
    rounds
}
#endif

#else // (Schedule != 3)

void KeccakPermutationOnWords(UINT32 *state)
{
    declareABCDE
#if (Unrolling != 24)
    unsigned int i;
#endif

    copyFromState(A, state)
    rounds
}

void KeccakPermutationOnWordsAfterXoring(UINT32 *state, const UINT8 *input, unsigned int laneCount)
{
    declareABCDE
    unsigned int i;

    xorLanesIntoState(laneCount, state, input)
    copyFromState(A, state)
    rounds
}

#ifdef ProvideFast576
void KeccakPermutationOnWordsAfterXoring576bits(UINT32 *state, const UINT8 *input)
{
    declareABCDE
    unsigned int i;

    xorLanesIntoState(9, state, input)
    copyFromState(A, state)
    rounds
}
#endif

#ifdef ProvideFast832
void KeccakPermutationOnWordsAfterXoring832bits(UINT32 *state, const UINT8 *input)
{
    declareABCDE
    unsigned int i;

    xorLanesIntoState(13, state, input)
    copyFromState(A, state)
    rounds
}
#endif

#ifdef ProvideFast1024
void KeccakPermutationOnWordsAfterXoring1024bits(UINT32 *state, const UINT8 *input)
{
    declareABCDE
    unsigned int i;

    xorLanesIntoState(16, state, input)
    copyFromState(A, state)
    rounds
}
#endif

#ifdef ProvideFast1088
void KeccakPermutationOnWordsAfterXoring1088bits(UINT32 *state, const UINT8 *input)
{
    declareABCDE
    unsigned int i;

    xorLanesIntoState(17, state, input)
    copyFromState(A, state)
    rounds
}
#endif

#ifdef ProvideFast1152
void KeccakPermutationOnWordsAfterXoring1152bits(UINT32 *state, const UINT8 *input)
{
    declareABCDE
    unsigned int i;

    xorLanesIntoState(18, state, input)
    copyFromState(A, state)
    rounds
}
#endif

#ifdef ProvideFast1344
void KeccakPermutationOnWordsAfterXoring1344bits(UINT32 *state, const UINT8 *input)
{
    declareABCDE
    unsigned int i;

    xorLanesIntoState(21, state, input)
    copyFromState(A, state)
    rounds
}
#endif

#endif

void KeccakInitialize()
{
#ifdef UseInterleaveTables
    buildInterleaveTables();
#endif
}

void KeccakInitializeState(unsigned char *state)
{
    memset(state, 0, 200);
#ifdef UseBebigokimisa
    ((UINT32*)state)[ 2] = ~(UINT32)0;
    ((UINT32*)state)[ 3] = ~(UINT32)0;
    ((UINT32*)state)[ 4] = ~(UINT32)0;
    ((UINT32*)state)[ 5] = ~(UINT32)0;
    ((UINT32*)state)[16] = ~(UINT32)0;
    ((UINT32*)state)[17] = ~(UINT32)0;
    ((UINT32*)state)[24] = ~(UINT32)0;
    ((UINT32*)state)[25] = ~(UINT32)0;
    ((UINT32*)state)[34] = ~(UINT32)0;
    ((UINT32*)state)[35] = ~(UINT32)0;
    ((UINT32*)state)[40] = ~(UINT32)0;
    ((UINT32*)state)[41] = ~(UINT32)0;
#endif
}

void KeccakPermutation(unsigned char *state)
{
    // We assume the state is always stored as interleaved 32-bit words
    KeccakPermutationOnWords((UINT32*)state);
}

#ifdef ProvideFast576
void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data)
{
    KeccakPermutationOnWordsAfterXoring576bits((UINT32*)state, data);
}
#endif

#ifdef ProvideFast832
void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data)
{
    KeccakPermutationOnWordsAfterXoring832bits((UINT32*)state, data);
}
#endif

#ifdef ProvideFast1024
void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data)
{
    KeccakPermutationOnWordsAfterXoring1024bits((UINT32*)state, data);
}
#endif

#ifdef ProvideFast1088
void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data)
{
    KeccakPermutationOnWordsAfterXoring1088bits((UINT32*)state, data);
}
#endif

#ifdef ProvideFast1152
void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data)
{
    KeccakPermutationOnWordsAfterXoring1152bits((UINT32*)state, data);
}
#endif

#ifdef ProvideFast1344
void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data)
{
    KeccakPermutationOnWordsAfterXoring1344bits((UINT32*)state, data);
}
#endif

void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount)
{
    KeccakPermutationOnWordsAfterXoring((UINT32*)state, data, laneCount);
}

#ifdef ProvideFast1024
void KeccakExtract1024bits(const unsigned char *state, unsigned char *data)
{
    extractLanes(16, state, data)
#ifdef UseBebigokimisa
    ((UINT32*)data)[ 2] = ~((UINT32*)data)[ 2];
    ((UINT32*)data)[ 3] = ~((UINT32*)data)[ 3];
    ((UINT32*)data)[ 4] = ~((UINT32*)data)[ 4];
    ((UINT32*)data)[ 5] = ~((UINT32*)data)[ 5];
    ((UINT32*)data)[16] = ~((UINT32*)data)[16];
    ((UINT32*)data)[17] = ~((UINT32*)data)[17];
    ((UINT32*)data)[24] = ~((UINT32*)data)[24];
    ((UINT32*)data)[25] = ~((UINT32*)data)[25];
#endif
}
#endif

void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount)
{
    extractLanes((int)laneCount, state, data)
#ifdef UseBebigokimisa
    if (laneCount > 1) {
        ((UINT32*)data)[ 2] = ~((UINT32*)data)[ 2];
        ((UINT32*)data)[ 3] = ~((UINT32*)data)[ 3];
        if (laneCount > 2) {
            ((UINT32*)data)[ 4] = ~((UINT32*)data)[ 4];
            ((UINT32*)data)[ 5] = ~((UINT32*)data)[ 5];
            if (laneCount > 8) {
                ((UINT32*)data)[16] = ~((UINT32*)data)[16];
                ((UINT32*)data)[17] = ~((UINT32*)data)[17];
                if (laneCount > 12) {
                    ((UINT32*)data)[24] = ~((UINT32*)data)[24];
                    ((UINT32*)data)[25] = ~((UINT32*)data)[25];
                    if (laneCount > 17) {
                        ((UINT32*)data)[34] = ~((UINT32*)data)[34];
                        ((UINT32*)data)[35] = ~((UINT32*)data)[35];
                        if (laneCount > 20) {
                            ((UINT32*)data)[40] = ~((UINT32*)data)[40];
                            ((UINT32*)data)[41] = ~((UINT32*)data)[41];
                        }
                    }
                }
            }
        }
    }
#endif
}


// ================================================================================
// =================== KeccakSponge.c
// ================================================================================


/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/

Implementation by the designers,
hereby denoted as "the implementer".

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#include <string.h>
//#include "KeccakSponge.h"
//#include "KeccakF-1600-interface.h"
#ifdef KeccakReference
//#include "displayIntermediateValues.h"
#endif

int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity)
{
    if (rate+capacity != 1600)
        return 1;
    if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0))
        return 1;
    KeccakInitialize();
    state->rate = rate;
    state->capacity = capacity;
    state->fixedOutputLength = 0;
    KeccakInitializeState(state->state);
    memset(state->dataQueue, 0, KeccakMaximumRateInBytes);
    state->bitsInQueue = 0;
    state->squeezing = 0;
    state->bitsAvailableForSqueezing = 0;

    return 0;
}

void AbsorbQueue(spongeState *state)
{
    // state->bitsInQueue is assumed to be equal to state->rate
    #ifdef KeccakReference
    displayBytes(1, "Block to be absorbed", state->dataQueue, state->rate/8);
    #endif
#ifdef ProvideFast576
    if (state->rate == 576)
        KeccakAbsorb576bits(state->state, state->dataQueue);
    else 
#endif
#ifdef ProvideFast832
    if (state->rate == 832)
        KeccakAbsorb832bits(state->state, state->dataQueue);
    else 
#endif
#ifdef ProvideFast1024
    if (state->rate == 1024)
        KeccakAbsorb1024bits(state->state, state->dataQueue);
    else 
#endif
#ifdef ProvideFast1088
    if (state->rate == 1088)
        KeccakAbsorb1088bits(state->state, state->dataQueue);
    else
#endif
#ifdef ProvideFast1152
    if (state->rate == 1152)
        KeccakAbsorb1152bits(state->state, state->dataQueue);
    else 
#endif
#ifdef ProvideFast1344
    if (state->rate == 1344)
        KeccakAbsorb1344bits(state->state, state->dataQueue);
    else 
#endif
        KeccakAbsorb(state->state, state->dataQueue, state->rate/64);
    state->bitsInQueue = 0;
}

int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen)
{
    unsigned long long i, j, wholeBlocks;
    unsigned int partialBlock, partialByte;
    const unsigned char *curData;

    if ((state->bitsInQueue % 8) != 0)
        return 1; // Only the last call may contain a partial byte
    if (state->squeezing)
        return 1; // Too late for additional input

    i = 0;
    while(i < databitlen) {
        if ((state->bitsInQueue == 0) && (databitlen >= state->rate) && (i <= (databitlen-state->rate))) {
            wholeBlocks = (databitlen-i)/state->rate;
            curData = data+i/8;
#ifdef ProvideFast576
            if (state->rate == 576) {
                for(j=0; j<wholeBlocks; j++, curData+=576/8) {
                    #ifdef KeccakReference
                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
                    #endif
                    KeccakAbsorb576bits(state->state, curData);
                }
            }
            else
#endif
#ifdef ProvideFast832
            if (state->rate == 832) {
                for(j=0; j<wholeBlocks; j++, curData+=832/8) {
                    #ifdef KeccakReference
                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
                    #endif
                    KeccakAbsorb832bits(state->state, curData);
                }
            }
            else
#endif
#ifdef ProvideFast1024
            if (state->rate == 1024) {
                for(j=0; j<wholeBlocks; j++, curData+=1024/8) {
                    #ifdef KeccakReference
                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
                    #endif
                    KeccakAbsorb1024bits(state->state, curData);
                }
            }
            else
#endif
#ifdef ProvideFast1088
            if (state->rate == 1088) {
                for(j=0; j<wholeBlocks; j++, curData+=1088/8) {
                    #ifdef KeccakReference
                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
                    #endif
                    KeccakAbsorb1088bits(state->state, curData);
                }
            }
            else
#endif
#ifdef ProvideFast1152
            if (state->rate == 1152) {
                for(j=0; j<wholeBlocks; j++, curData+=1152/8) {
                    #ifdef KeccakReference
                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
                    #endif
                    KeccakAbsorb1152bits(state->state, curData);
                }
            }
            else
#endif
#ifdef ProvideFast1344
            if (state->rate == 1344) {
                for(j=0; j<wholeBlocks; j++, curData+=1344/8) {
                    #ifdef KeccakReference
                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
                    #endif
                    KeccakAbsorb1344bits(state->state, curData);
                }
            }
            else
#endif
            {
                for(j=0; j<wholeBlocks; j++, curData+=state->rate/8) {
                    #ifdef KeccakReference
                    displayBytes(1, "Block to be absorbed", curData, state->rate/8);
                    #endif
                    KeccakAbsorb(state->state, curData, state->rate/64);
                }
            }
            i += wholeBlocks*state->rate;
        }
        else {
            partialBlock = (unsigned int)(databitlen - i);
            if (partialBlock+state->bitsInQueue > state->rate)
                partialBlock = state->rate-state->bitsInQueue;
            partialByte = partialBlock % 8;
            partialBlock -= partialByte;
            memcpy(state->dataQueue+state->bitsInQueue/8, data+i/8, partialBlock/8);
            state->bitsInQueue += partialBlock;
            i += partialBlock;
            if (state->bitsInQueue == state->rate)
                AbsorbQueue(state);
            if (partialByte > 0) {
                unsigned char mask = (1 << partialByte)-1;
                state->dataQueue[state->bitsInQueue/8] = data[i/8] & mask;
                state->bitsInQueue += partialByte;
                i += partialByte;
            }
        }
    }
    return 0;
}

void PadAndSwitchToSqueezingPhase(spongeState *state)
{
    // Note: the bits are numbered from 0=LSB to 7=MSB
    if (state->bitsInQueue + 1 == state->rate) {
        state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8);
        AbsorbQueue(state);
        memset(state->dataQueue, 0, state->rate/8);
    }
    else {
        memset(state->dataQueue + (state->bitsInQueue+7)/8, 0, state->rate/8 - (state->bitsInQueue+7)/8);
        state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8);
    }
    state->dataQueue[(state->rate-1)/8] |= 1 << ((state->rate-1) % 8);
    AbsorbQueue(state);

    #ifdef KeccakReference
    displayText(1, "--- Switching to squeezing phase ---");
    #endif
#ifdef ProvideFast1024
    if (state->rate == 1024) {
        KeccakExtract1024bits(state->state, state->dataQueue);
        state->bitsAvailableForSqueezing = 1024;
    }
    else
#endif
    {
        KeccakExtract(state->state, state->dataQueue, state->rate/64);
        state->bitsAvailableForSqueezing = state->rate;
    }
    #ifdef KeccakReference
    displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8);
    #endif
    state->squeezing = 1;
}

int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength)
{
    unsigned long long i;
    unsigned int partialBlock;

    if (!state->squeezing)
        PadAndSwitchToSqueezingPhase(state);
    if ((outputLength % 8) != 0)
        return 1; // Only multiple of 8 bits are allowed, truncation can be done at user level

    i = 0;
    while(i < outputLength) {
        if (state->bitsAvailableForSqueezing == 0) {
            KeccakPermutation(state->state);
#ifdef ProvideFast1024
            if (state->rate == 1024) {
                KeccakExtract1024bits(state->state, state->dataQueue);
                state->bitsAvailableForSqueezing = 1024;
            }
            else
#endif
            {
                KeccakExtract(state->state, state->dataQueue, state->rate/64);
                state->bitsAvailableForSqueezing = state->rate;
            }
            #ifdef KeccakReference
            displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8);
            #endif
        }
        partialBlock = state->bitsAvailableForSqueezing;
        if ((unsigned long long)partialBlock > outputLength - i)
            partialBlock = (unsigned int)(outputLength - i);
        memcpy(output+i/8, state->dataQueue+(state->rate-state->bitsAvailableForSqueezing)/8, partialBlock/8);
        state->bitsAvailableForSqueezing -= partialBlock;
        i += partialBlock;
    }
    return 0;
}



// ================================================================================
// =================== KeccakNISTInterface.h
// ================================================================================


/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/

Implementation by the designers,
hereby denoted as "the implementer".

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#ifndef _KeccakNISTInterface_h_
#define _KeccakNISTInterface_h_

//#include "KeccakSponge.h"

typedef unsigned char BitSequence;
typedef unsigned long long DataLength;
typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn;

typedef spongeState hashState;

/**
  * Function to initialize the state of the Keccak[r, c] sponge function.
  * The rate r and capacity c values are determined from @a hashbitlen.
  * @param  state       Pointer to the state of the sponge function to be initialized.
  * @param  hashbitlen  The desired number of output bits, 
  *                     or 0 for Keccak[] with default parameters
  *                     and arbitrarily-long output.
  * @pre    The value of hashbitlen must be one of 0, 224, 256, 384 and 512.
  * @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect.
  */
HashReturn Init(hashState *state, int hashbitlen);
/**
  * Function to give input data for the sponge function to absorb.
  * @param  state       Pointer to the state of the sponge function initialized by Init().
  * @param  data        Pointer to the input data. 
  *                     When @a databitLen is not a multiple of 8, the last bits of data must be
  *                     in the most significant bits of the last byte.
  * @param  databitLen  The number of input bits provided in the input data.
  * @pre    In the previous call to Absorb(), databitLen was a multiple of 8.
  * @return SUCCESS if successful, FAIL otherwise.
  */
HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen);
/**
  * Function to squeeze output data from the sponge function.
  * If @a hashbitlen was not 0 in the call to Init(), the number of output bits is equal to @a hashbitlen.
  * If @a hashbitlen was 0 in the call to Init(), the output bits must be extracted using the Squeeze() function.
  * @param  state       Pointer to the state of the sponge function initialized by Init().
  * @param  hashval     Pointer to the buffer where to store the output data.
  * @return SUCCESS if successful, FAIL otherwise.
  */
HashReturn Final(hashState *state, BitSequence *hashval);
/**
  * Function to compute a hash using the Keccak[r, c] sponge function.
  * The rate r and capacity c values are determined from @a hashbitlen.
  * @param  hashbitlen  The desired number of output bits.
  * @param  data        Pointer to the input data. 
  *                     When @a databitLen is not a multiple of 8, the last bits of data must be
  *                     in the most significant bits of the last byte.
  * @param  databitLen  The number of input bits provided in the input data.
  * @param  hashval     Pointer to the buffer where to store the output data.
  * @pre    The value of hashbitlen must be one of 224, 256, 384 and 512.
  * @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect.
  */
HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval);

#endif


// ================================================================================
// =================== KeccakNISTInterface.c
// ================================================================================



/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/

Implementation by the designers,
hereby denoted as "the implementer".

To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/

#include <string.h>
//#include "KeccakNISTInterface.h"
//#include "KeccakF-1600-interface.h"

HashReturn Init(hashState *state, int hashbitlen)
{
    switch(hashbitlen) {
        case 0: // Default parameters, arbitrary length output
            InitSponge((spongeState*)state, 1024, 576);
            break;
        case 224:
            InitSponge((spongeState*)state, 1152, 448);
            break;
        case 256:
            InitSponge((spongeState*)state, 1088, 512);
            break;
        case 384:
            InitSponge((spongeState*)state, 832, 768);
            break;
        case 512:
            InitSponge((spongeState*)state, 576, 1024);
            break;
        default:
            return BAD_HASHLEN;
    }
    state->fixedOutputLength = hashbitlen;
    return SUCCESS;
}

HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen)
{
    if ((databitlen % 8) == 0)
        return (HashReturn)Absorb((spongeState*)state, data, databitlen);
    else {
        HashReturn ret = (HashReturn)Absorb((spongeState*)state, data, databitlen - (databitlen % 8));
        if (ret == SUCCESS) {
            unsigned char lastByte; 
            // Align the last partial byte to the least significant bits
            lastByte = data[databitlen/8] >> (8 - (databitlen % 8));
            return (HashReturn)Absorb((spongeState*)state, &lastByte, databitlen % 8);
        }
        else
            return ret;
    }
}

HashReturn Final(hashState *state, BitSequence *hashval)
{
    return (HashReturn)Squeeze(state, hashval, state->fixedOutputLength);
}

HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval)
{
    hashState state;
    HashReturn result;

    if ((hashbitlen != 224) && (hashbitlen != 256) && (hashbitlen != 384) && (hashbitlen != 512))
        return BAD_HASHLEN; // Only the four fixed output lengths available through this API
    result = Init(&state, hashbitlen);
    if (result != SUCCESS)
        return result;
    result = Update(&state, data, databitlen);
    if (result != SUCCESS)
        return result;
    result = Final(&state, hashval);
    return result;
}


} // end of namespace KeccakImpl
} // end of namespace Internal
} // end of namespace Hash
} // end of namespace MUtils

