text: /*
  Implementation by Ronny Van Keer, hereby denoted as "the implementer".
  
  For more information, feedback or questions, please refer to our website:
  https://keccak.team/
  
  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 _SP800_185_h_
  #define _SP800_185_h_
  
  #include <stddef.h>
  #include "align.h"
  #include "KeccakSpongeWidth1600.h"
  #include "Phases.h"
  
  #ifndef KeccakP1600_excluded
  
  #ifndef _Keccak_BitTypes_
  #define _Keccak_BitTypes_
  typedef unsigned char BitSequence;
  
  typedef size_t BitLength;
  #endif
  
  typedef struct {
      KeccakWidth1600_SpongeInstance sponge;
      BitLength fixedOutputLength;
      unsigned int lastByteBitLen;
      BitSequence lastByteValue;
      KCP_Phases phase;
  } cSHAKE_Instance;
  
  /** cSHAKE128 function, as defined in NIST's Special Publication 800-185,
    * published December 2016.
    * @param  input           Pointer to the input message (X).
    * @param  inputBitLen     The length of the input message in bits.
    * @param  output          Pointer to the output buffer.
    * @param  outputBitLen    The desired number of output bits (L).
    * @param  name            Pointer to the function name string (N).
    * @param  nameBitLen      The length of the function name in bits.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE128( const BitSequence *input, BitLength inputBitLen, BitSequence *output, BitLength outputBitLen, const BitSequence *name, BitLength nameBitLen, const BitSequence *customization, BitLength customBitLen );
  
  /**
    * Function to initialize the cSHAKE128 instance used in sequential hashing mode.
    * @param  cskInstance     Pointer to the hash instance to be initialized.
    * @param  outputBitLen    The desired number of output bits (L).
    *                         or 0 for an arbitrarily-long output (XOF).
    * @param  name            Pointer to the function name string (N).
    * @param  nameBitLen      The length of the function name in bits.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE128_Initialize(cSHAKE_Instance *cskInstance, BitLength outputBitLen, const BitSequence *name, BitLength nameBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to give input data to be absorbed.
    * @param  cskInstance     Pointer to the hash instance initialized by cSHAKE128_Initialize().
    * @param  input           Pointer to the input data.
    * @param  inputBitLen     The number of input bits provided in the input data.
    *                         Only the last update call can input a partial byte, other calls must have a length multiple of 8.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE128_Update(cSHAKE_Instance *cskInstance, const BitSequence *input, BitLength inputBitLen);
  
  /**
    * Function to call after all input blocks have been input and to get
    * output bits if the length was specified when calling cSHAKE128_Initialize().
    * @param  cskInstance     Pointer to the hash instance initialized by cSHAKE128_Initialize().
    *                         If @a outputBitLen was not 0 in the call to cSHAKE128_Initialize(), the number of
    *                         output bits is equal to @a outputBitLen.
    *                         If @a outputBitLen was 0 in the call to cSHAKE128_Initialize(), the output bits
    *                         must be extracted using the cSHAKE128_Squeeze() function.
    * @param  output          Pointer to the buffer where to store the output data.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE128_Final(cSHAKE_Instance *cskInstance, BitSequence *output);
  
   /**
    * Function to squeeze output data.
    * @param  cskInstance     Pointer to the hash instance initialized by cSHAKE128_Initialize().
    * @param  output          Pointer to the buffer where to store the output data.
    * @param  outputBitLen    The number of output bits desired.
    *                         Only the last squeeze call can output a partial byte, 
    *                         other calls must have a length multiple of 8.
    * @pre    cSHAKE128_Final() must have been already called.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE128_Squeeze(cSHAKE_Instance *cskInstance, BitSequence *output, BitLength outputBitLen);
  
  /* ------------------------------------------------------------------------- */
  
  /** cSHAKE256 function, as defined in NIST's Special Publication 800-185,
    * published December 2016.
    * @param  input           Pointer to the input message (X).
    * @param  inputBitLen     The length of the input message in bits.
    * @param  output          Pointer to the output buffer.
    * @param  outputBitLen    The desired number of output bits (L).
    * @param  name            Pointer to the function name string (N).
    * @param  nameBitLen      The length of the function name in bits.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE256( const BitSequence *input, BitLength inputBitLen, BitSequence *output, BitLength outputBitLen, const BitSequence *name, BitLength nameBitLen, const BitSequence *customization, BitLength customBitLen );
  
  /**
    * Function to initialize the cSHAKE256 instance used in sequential hashing mode.
    * @param  cskInstance     Pointer to the hash instance to be initialized.
    * @param  outputBitLen    The desired number of output bits (L).
    *                         or 0 for an arbitrarily-long output (XOF).
    * @param  name            Pointer to the function name string (N).
    * @param  nameBitLen      The length of the function name in bits.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE256_Initialize(cSHAKE_Instance *cskInstance, BitLength outputBitLen, const BitSequence *name, BitLength nameBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to give input data to be absorbed.
    * @param  cskInstance     Pointer to the hash instance initialized by cSHAKE256_Initialize().
    * @param  input           Pointer to the input data.
    * @param  inputBitLen     The number of input bits provided in the input data.
    *                         Only the last update call can input a partial byte, other calls must have a length multiple of 8.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE256_Update(cSHAKE_Instance *cskInstance, const BitSequence *input, BitLength inputBitLen);
  
  /**
    * Function to call after all input blocks have been input and to get
    * output bits if the length was specified when calling cSHAKE256_Initialize().
    * @param  cskInstance     Pointer to the hash instance initialized by cSHAKE256_Initialize().
    *                         If @a outputBitLen was not 0 in the call to cSHAKE256_Initialize(), the number of
    *                         output bits is equal to @a outputBitLen.
    *                         If @a outputBitLen was 0 in the call to cSHAKE256_Initialize(), the output bits
    *                         must be extracted using the cSHAKE256_Squeeze() function.
    * @param  output          Pointer to the buffer where to store the output data.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE256_Final(cSHAKE_Instance *cskInstance, BitSequence *output);
  
   /**
    * Function to squeeze output data.
    * @param  cskInstance     Pointer to the hash instance initialized by cSHAKE256_Initialize().
    * @param  output          Pointer to the buffer where to store the output data.
    * @param  outputBitLen    The number of output bits desired.
    *                         Only the last squeeze call can output a partial byte, 
    *                         other calls must have a length multiple of 8.
    * @pre    cSHAKE256_Final() must have been already called.
    * @return 0 if successful, 1 otherwise.
    */
  int cSHAKE256_Squeeze(cSHAKE_Instance *cskInstance, BitSequence *output, BitLength outputBitLen);
  
  /* ------------------------------------------------------------------------- */
  
  typedef struct {
      cSHAKE_Instance csi;
      BitLength outputBitLen;
  } KMAC_Instance;
  
  /** KMAC128 function, as defined in NIST's Special Publication 800-185,
    * published December 2016.
    * @param  key             Pointer to the key (K).
    * @param  keyBitLen       The length of the key in bits.
    * @param  input           Pointer to the input message (X).
    * @param  inputBitLen     The length of the input message in bits.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @param  output          Pointer to the output buffer.
    * @param  outputBitLen    The desired number of output bits (L).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC128(const BitSequence *key, BitLength keyBitLen, const BitSequence *input, BitLength inputBitLen,
          BitSequence *output, BitLength outputBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to initialize the KMAC128 instance used in sequential MACing mode.
    * @param  kmInstance      Pointer to the instance to be initialized.
    * @param  key             Pointer to the key (K).
    * @param  keyBitLen       The length of the key in bits.
    * @param  outputBitLen    The desired number of output bits (L).
    *                         or 0 for an arbitrarily-long output (XOF).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC128_Initialize(KMAC_Instance *kmkInstance, const BitSequence *key, BitLength keyBitLen, BitLength outputBitLen,
          const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to give input data to be MACed.
    * @param  kmInstance      Pointer to the instance initialized by KMAC128_Initialize().
    * @param  input           Pointer to the input data.
    * @param  inputBitLen     The number of input bits provided in the input data.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC128_Update(KMAC_Instance *kmkInstance, const BitSequence *input, BitLength inputBitLen);
  
  /**
    * Function to call after all input data have been input and to get
    * output bits if the length was specified when calling KMAC128_Initialize().
    * @param  kmInstance      Pointer to the instance initialized by KMAC128_Initialize().
    *                         If @a outputBitLen was not 0 in the call to KMAC128_Initialize(), the number of
    *                         output bits is equal to @a outputBitLen.
    *                         If @a outputBitLen was 0 in the call to KMAC128_Initialize(), the output bits
    *                         must be extracted using the KMAC128_Squeeze() function.
    * @param  output          Pointer to the buffer where to store the output data.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC128_Final(KMAC_Instance *kmkInstance, BitSequence *output);
  
   /**
    * Function to squeeze output data.
    * @param  kmInstance      Pointer to the instance initialized by KMAC128_Initialize().
    * @param  output          Pointer to the buffer where to store the output data.
    * @param  outputBitLen    The number of output bits desired.
    *                         Only the last squeeze call can output a partial byte,
    *                         other calls must have a length multiple of 8.
    * @pre    KMAC128_Final() must have been already called.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC128_Squeeze(KMAC_Instance *kmkInstance, BitSequence *output, BitLength outputBitLen);
  
  /* ------------------------------------------------------------------------- */
  
  /** KMAC256 function, as defined in NIST's Special Publication 800-185,
    * published December 2016.
    * @param  key             Pointer to the key (K).
    * @param  keyBitLen       The length of the key in bits.
    * @param  input           Pointer to the input message (X).
    * @param  inputBitLen     The length of the input message in bits.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @param  output          Pointer to the output buffer.
    * @param  outputBitLen    The desired number of output bits (L).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC256(const BitSequence *key, BitLength keyBitLen, const BitSequence *input, BitLength inputBitLen,
          BitSequence *output, BitLength outputBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to initialize the KMAC256 instance used in sequential MACing mode.
    * @param  kmInstance      Pointer to the instance to be initialized.
    * @param  key             Pointer to the key (K).
    * @param  keyBitLen       The length of the key in bits.
    * @param  outputBitLen    The desired number of output bits (L).
    *                         or 0 for an arbitrarily-long output (XOF).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC256_Initialize(KMAC_Instance *kmkInstance, const BitSequence *key, BitLength keyBitLen, BitLength outputBitLen,
          const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to give input data to be MACed.
    * @param  kmInstance      Pointer to the instance initialized by KMAC256_Initialize().
    * @param  input           Pointer to the input data.
    * @param  inputBitLen     The number of input bits provided in the input data.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC256_Update(KMAC_Instance *kmkInstance, const BitSequence *input, BitLength inputBitLen);
  
  /**
    * Function to call after all input data have been input and to get
    * output bits if the length was specified when calling KMAC256_Initialize().
    * @param  kmInstance      Pointer to the instance initialized by KMAC256_Initialize().
    *                         If @a outputBitLen was not 0 in the call to KMAC256_Initialize(), the number of
    *                         output bits is equal to @a outputBitLen.
    *                         If @a outputBitLen was 0 in the call to KMAC256_Initialize(), the output bits
    *                         must be extracted using the KMAC256_Squeeze() function.
    * @param  output          Pointer to the buffer where to store the output data.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC256_Final(KMAC_Instance *kmkInstance, BitSequence *output);
  
   /**
    * Function to squeeze output data.
    * @param  kmInstance      Pointer to the instance initialized by KMAC256_Initialize().
    * @param  output          Pointer to the buffer where to store the output data.
    * @param  outputBitLen    The number of output bits desired.
    *                         Only the last squeeze call can output a partial byte,
    *                         other calls must have a length multiple of 8.
    * @pre    KMAC256_Final() must have been already called.
    * @return 0 if successful, 1 otherwise.
    */
  int KMAC256_Squeeze(KMAC_Instance *kmkInstance, BitSequence *output, BitLength outputBitLen);
  
  /* ------------------------------------------------------------------------- */
  
  typedef struct {
      KeccakWidth1600_SpongeInstance queueNode;
      KeccakWidth1600_SpongeInstance finalNode;
      unsigned int fixedOutputLength;
      unsigned int blockLen;
      unsigned int queueAbsorbedLen;
      size_t totalInputSize;
      KCP_Phases phase;
  } ParallelHash_Instance;
  
  /** Parallel hash function ParallelHash128, as defined in NIST's Special Publication 800-185,
    * published December 2016.
    * @param  input           Pointer to the input message (X).
    * @param  inputBitLen     The number of input bits provided in the input data.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @param  blockByteLen    Block size (B) in bytes, must be a power of 2.
    *                         The minimum value is 8 in this implementation.
    * @param  output          Pointer to the output buffer.
    * @param  outputBitLen    The desired number of output bits (L).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash128( const BitSequence *input, BitLength inputBitLen, unsigned int blockByteLen,
          BitSequence *output, BitLength outputBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to initialize the parallel hash function ParallelHash128 instance used in sequential hashing mode.
    * @param  ParallelHashInstance     Pointer to the hash instance to be initialized.
    * @param  blockByteLen    Block size (B) in bytes, must be a power of 2.
    *                         The minimum value is 8 in this implementation.
    * @param  outputBitLen    The desired number of output bits (L).
    *                         or 0 for an arbitrarily-long output (XOF).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash128_Initialize(ParallelHash_Instance *ParallelHashInstance, unsigned int blockByteLen,
          BitLength outputBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to give input data to be absorbed.
    * @param  ParallelHashInstance     Pointer to the hash instance initialized by ParallelHash128_Initialize().
    * @param  input           Pointer to the input data (X).
    * @param  inputBitLen     The number of input bits provided in the input data.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash128_Update(ParallelHash_Instance *ParallelHashInstance, const BitSequence *input, BitLength inputBitLen);
  
  /**
    * Function to call after all input blocks have been input and to get
    * output bits if the length was specified when calling ParallelHash128_Initialize().
    * @param  ParallelHashInstance     Pointer to the hash instance initialized by ParallelHash128_Initialize().
    * If @a outputBitLen was not 0 in the call to ParallelHash128_Initialize(), the number of
    *     output bits is equal to @a outputBitLen.
    * If @a outputBitLen was 0 in the call to ParallelHash128_Initialize(), the output bits
    *     must be extracted using the ParallelHash128_Squeeze() function.
    * @param  output          Pointer to the buffer where to store the output data.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash128_Final(ParallelHash_Instance *ParallelHashInstance, BitSequence * output);
  
   /**
    * Function to squeeze output data.
    * @param  ParallelHashInstance    Pointer to the hash instance initialized by ParallelHash128_Initialize().
    * @param  output          Pointer to the buffer where to store the output data.
    * @param  outputBitLen    The number of output bits desired.
    *                         Only the last squeeze call can output a partial byte,
    *                         other calls must have a length multiple of 8.
    * @pre    ParallelHash128_Final() must have been already called.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash128_Squeeze(ParallelHash_Instance *ParallelHashInstance, BitSequence *output, BitLength outputBitLen);
  
  /* ------------------------------------------------------------------------- */
  
  /** Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
    * published December 2016.
    * @param  input           Pointer to the input message (X).
    * @param  inputBitLen     The number of input bits provided in the input data.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @param  blockByteLen    Block size (B) in bytes, must be a power of 2.
    *                         The minimum value is 8 in this implementation.
    * @param  output          Pointer to the output buffer.
    * @param  outputBitLen    The desired number of output bits (L).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash256( const BitSequence *input, BitLength inputBitLen, unsigned int blockByteLen,
          BitSequence *output, BitLength outputBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to initialize the parallel hash function ParallelHash256 instance used in sequential hashing mode.
    * @param  ParallelHashInstance     Pointer to the hash instance to be initialized.
    * @param  blockByteLen    Block size (B) in bytes, must be a power of 2.
    *                         The minimum value is 8 in this implementation.
    * @param  outputBitLen    The desired number of output bits (L).
    *                         or 0 for an arbitrarily-long output (XOF).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash256_Initialize(ParallelHash_Instance *ParallelHashInstance, unsigned int blockByteLen,
          BitLength outputBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to give input data to be absorbed.
    * @param  ParallelHashInstance     Pointer to the hash instance initialized by ParallelHash256_Initialize().
    * @param  input           Pointer to the input data (X).
    * @param  inputBitLen     The number of input bits provided in the input data.
    *                         Only full bytes are supported, length must be a multiple of 8.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash256_Update(ParallelHash_Instance *ParallelHashInstance, const BitSequence *input, BitLength inputBitLen);
  
  /**
    * Function to call after all input blocks have been input and to get
    * output bits if the length was specified when calling ParallelHash256_Initialize().
    * @param  ParallelHashInstance     Pointer to the hash instance initialized by ParallelHash256_Initialize().
    * If @a outputBitLen was not 0 in the call to ParallelHash256_Initialize(), the number of
    *     output bits is equal to @a outputBitLen.
    * If @a outputBitLen was 0 in the call to ParallelHash256_Initialize(), the output bits
    *     must be extracted using the ParallelHash256_Squeeze() function.
    * @param  output          Pointer to the buffer where to store the output data.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash256_Final(ParallelHash_Instance *ParallelHashInstance, BitSequence * output);
  
   /**
    * Function to squeeze output data.
    * @param  ParallelHashInstance    Pointer to the hash instance initialized by ParallelHash256_Initialize().
    * @param  output          Pointer to the buffer where to store the output data.
    * @param  outputBitLen    The number of output bits desired.
    *                         Only the last squeeze call can output a partial byte,
    *                         other calls must have a length multiple of 8.
    * @pre    ParallelHash256_Final() must have been already called.
    * @return 0 if successful, 1 otherwise.
    */
  int ParallelHash256_Squeeze(ParallelHash_Instance *ParallelHashInstance, BitSequence *output, BitLength outputBitLen);
  
  /* ------------------------------------------------------------------------- */
  
  typedef struct {
      cSHAKE_Instance csi;
      BitLength outputBitLen;
  } TupleHash_Instance;
  
  typedef struct {
      /** Pointer to the tuple element data (Xn). */
      BitSequence *input;
  
      /** The number of input bits provided in this tuple element.
       *  Only full bytes are supported, length must be a multiple of 8.
       */
      BitLength inputBitLen;
  } TupleElement;
  
  /** Tuple hash function TupleHash128, as defined in NIST's Special Publication 800-185,
    * published December 2016.
    * @param  tuple            Pointer to an array of tuple elements (X).
    * @param  numberOfElements The number of tuple elements provided in the input data.
    * @param  output           Pointer to the output buffer.
    * @param  outputBitLen     The desired number of output bits (L).
    * @param  customization    Pointer to the customization string (S).
    * @param  customBitLen     The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash128( const TupleElement *tuple, size_t numberOfElements,
          BitSequence *output, BitLength outputBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to initialize the Tuple hash function TupleHash128 instance used in sequential hashing mode.
    * @param  TupleHashInstance     Pointer to the hash instance to be initialized.
    * @param  outputBitLen    The desired number of output bits (L).
    *                         or 0 for an arbitrarily-long output (XOF).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash128_Initialize(TupleHash_Instance *TupleHashInstance, BitLength outputBitLen,
          const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to give input data to be absorbed.
    * @param  TupleHashInstance     Pointer to the hash instance initialized by TupleHash128_Initialize().
    * @param  tuple            Pointer to an array of tuple elements (X).
    * @param  numberOfElements The number of tuple elements provided in the input data.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash128_Update(TupleHash_Instance *TupleHashInstance, const TupleElement *tuple, size_t numberOfElements);
  
  /**
    * Function to call after all input blocks have been input and to get
    * output bits if the length was specified when calling TupleHash128_Initialize().
    * @param  TupleHashInstance     Pointer to the hash instance initialized by TupleHash128_Initialize().
    * If @a outputBitLen was not 0 in the call to TupleHash128_Initialize(), the number of
    *     output bits is equal to @a outputBitLen.
    * If @a outputBitLen was 0 in the call to TupleHash128_Initialize(), the output bits
    *     must be extracted using the TupleHash128_Squeeze() function.
    * @param  output          Pointer to the buffer where to store the output data.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash128_Final(TupleHash_Instance *TupleHashInstance, BitSequence * output);
  
   /**
    * Function to squeeze output data.
    * @param  TupleHashInstance    Pointer to the hash instance initialized by TupleHash128_Initialize().
    * @param  output          Pointer to the buffer where to store the output data.
    * @param  outputBitLen    The number of output bits desired.
    *                         Only the last squeeze call can output a partial byte,
    *                         other calls must have a length multiple of 8.
    * @pre    TupleHash128_Final() must have been already called.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash128_Squeeze(TupleHash_Instance *TupleHashInstance, BitSequence *output, BitLength outputBitLen);
  
  /* ------------------------------------------------------------------------- */
  
  /** Tuple hash function TupleHash256, as defined in NIST's Special Publication 800-185,
    * published December 2016.
    * @param  tuple            Pointer to an array of tuple elements (X).
    * @param  numberOfElements The number of tuple elements provided in the input data.
    * @param  output           Pointer to the output buffer.
    * @param  outputBitLen     The desired number of output bits (L).
    * @param  customization    Pointer to the customization string (S).
    * @param  customBitLen     The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash256( const TupleElement *tuple, size_t numberOfElements,
          BitSequence *output, BitLength outputBitLen, const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to initialize the Tuple hash function TupleHash256 instance used in sequential hashing mode.
    * @param  TupleHashInstance     Pointer to the hash instance to be initialized.
    * @param  outputBitLen    The desired number of output bits (L).
    *                         or 0 for an arbitrarily-long output (XOF).
    * @param  customization   Pointer to the customization string (S).
    * @param  customBitLen    The length of the customization string in bits.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash256_Initialize(TupleHash_Instance *TupleHashInstance, BitLength outputBitLen,
          const BitSequence *customization, BitLength customBitLen);
  
  /**
    * Function to give input data to be absorbed.
    * @param  TupleHashInstance     Pointer to the hash instance initialized by TupleHash256_Initialize().
    * @param  tuple            Pointer to an array of tuple elements (X).
    * @param  numberOfElements The number of tuple elements provided in the input data.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash256_Update(TupleHash_Instance *TupleHashInstance, const TupleElement *tuple, size_t numberOfElements);
  
  /**
    * Function to call after all input blocks have been input and to get
    * output bits if the length was specified when calling TupleHash256_Initialize().
    * @param  TupleHashInstance     Pointer to the hash instance initialized by TupleHash256_Initialize().
    * If @a outputBitLen was not 0 in the call to TupleHash256_Initialize(), the number of
    *     output bits is equal to @a outputBitLen.
    * If @a outputBitLen was 0 in the call to TupleHash256_Initialize(), the output bits
    *     must be extracted using the TupleHash256_Squeeze() function.
    * @param  output          Pointer to the buffer where to store the output data.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash256_Final(TupleHash_Instance *TupleHashInstance, BitSequence * output);
  
   /**
    * Function to squeeze output data.
    * @param  TupleHashInstance    Pointer to the hash instance initialized by TupleHash256_Initialize().
    * @param  output          Pointer to the buffer where to store the output data.
    * @param  outputBitLen    The number of output bits desired.
    *                         Only the last squeeze call can output a partial byte,
    *                         other calls must have a length multiple of 8.
    * @pre    TupleHash256_Final() must have been already called.
    * @return 0 if successful, 1 otherwise.
    */
  int TupleHash256_Squeeze(TupleHash_Instance *TupleHashInstance, BitSequence *output, BitLength outputBitLen);
  
  #endif
  
  #endif
  