Revision 0235e325b60dcbd41bc82cdee55b5e3940e70b3e authored by Matthias J. Kannwischer on 29 September 2021, 02:52:07 UTC, committed by rpls on 01 October 2021, 16:14:07 UTC
1 parent 9896316
Raw File
fips202.c
/* Based on the public domain implementation in
 * crypto_hash/keccakc512/simple/ from http://bench.cr.yp.to/supercop.html
 * by Ronny Van Keer
 * and the public domain "TweetFips202" implementation
 * from https://twitter.com/tweetfips202
 * by Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include "fips202.h"
#include "keccakf1600.h"

#define NROUNDS 24
#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64 - (offset))))

#ifdef PROFILE_HASHING
#include "hal.h"
extern unsigned long long hash_cycles;
#endif


/*************************************************
 * Name:        keccak_absorb
 *
 * Description: Absorb step of Keccak;
 *              non-incremental, starts by zeroeing the state.
 *
 * Arguments:   - uint64_t *s:       pointer to (uninitialized) output Keccak state
 *              - uint32_t r:        rate in bytes (e.g., 168 for SHAKE128)
 *              - const uint8_t *m:  pointer to input to be absorbed into s
 *              - size_t mlen:       length of input in bytes
 *              - uint8_t p:         domain-separation byte for different Keccak-derived functions
 **************************************************/
static void keccak_absorb(uint64_t *s,
    uint32_t r,
    const uint8_t *m, size_t mlen,
    uint8_t p)
{
  while (mlen >= r)
  {
    KeccakF1600_StateXORBytes(s, m, 0, r);
    KeccakF1600_StatePermute(s);
    mlen -= r;
    m += r;
  }

  if(mlen > 0){
    KeccakF1600_StateXORBytes(s, m, 0, mlen);
  }

  if(mlen == r-1){
    p |= 128;
    KeccakF1600_StateXORBytes(s, &p, mlen, 1);
  } else {
    KeccakF1600_StateXORBytes(s, &p, mlen, 1);
    p = 128;
    KeccakF1600_StateXORBytes(s, &p, r-1, 1);
  }
}


/*************************************************
 * Name:        keccak_squeezeblocks
 *
 * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each.
 *              Modifies the state. Can be called multiple times to keep squeezing,
 *              i.e., is incremental.
 *
 * Arguments:   - uint8_t *h:     pointer to output blocks
 *              - size_t nblocks: number of blocks to be squeezed (written to h)
 *              - uint64_t *s:    pointer to in/output Keccak state
 *              - uint32_t r:     rate in bytes (e.g., 168 for SHAKE128)
 **************************************************/
static void keccak_squeezeblocks(uint8_t *h, size_t nblocks,
    uint64_t *s,
    uint32_t r)
{
  while(nblocks > 0)
  {
    KeccakF1600_StatePermute(s);
    KeccakF1600_StateExtractBytes(s, h, 0, r);
    h += r;
    nblocks--;
  }
}

/*************************************************
 * Name:        keccak_inc_init
 *
 * Description: Initializes the incremental Keccak state to zero.
 *
 * Arguments:   - uint64_t *s_inc: pointer to input/output incremental state
 *                First 25 values represent Keccak state.
 *                26th value represents either the number of absorbed bytes
 *                that have not been permuted, or not-yet-squeezed bytes.
 **************************************************/
static void keccak_inc_init(uint64_t *s_inc) {
    size_t i;

    for (i = 0; i < 25; ++i) {
        s_inc[i] = 0;
    }
    s_inc[25] = 0;
}
/*************************************************
 * Name:        keccak_inc_absorb
 *
 * Description: Incremental keccak absorb
 *              Preceded by keccak_inc_init, succeeded by keccak_inc_finalize
 *
 * Arguments:   - uint64_t *s_inc: pointer to input/output incremental state
 *                First 25 values represent Keccak state.
 *                26th value represents either the number of absorbed bytes
 *                that have not been permuted, or not-yet-squeezed bytes.
 *              - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
 *              - const uint8_t *m: pointer to input to be absorbed into s_inc
 *              - size_t mlen: length of input in bytes
 **************************************************/
static void keccak_inc_absorb(uint64_t *s_inc, uint32_t r, const uint8_t *m,
                              size_t mlen) {
    /* Recall that s_inc[25] is the non-absorbed bytes xored into the state */
    while (mlen + s_inc[25] >= r) {

        KeccakF1600_StateXORBytes(s_inc, m, s_inc[25], r-s_inc[25]);
        mlen -= (size_t)(r - s_inc[25]);
        m += r - s_inc[25];
        s_inc[25] = 0;

        KeccakF1600_StatePermute(s_inc);
    }

    KeccakF1600_StateXORBytes(s_inc, m, s_inc[25], mlen);
    s_inc[25] += mlen;
}

/*************************************************
 * Name:        keccak_inc_finalize
 *
 * Description: Finalizes Keccak absorb phase, prepares for squeezing
 *
 * Arguments:   - uint64_t *s_inc: pointer to input/output incremental state
 *                First 25 values represent Keccak state.
 *                26th value represents either the number of absorbed bytes
 *                that have not been permuted, or not-yet-squeezed bytes.
 *              - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
 *              - uint8_t p: domain-separation byte for different
 *                                 Keccak-derived functions
 **************************************************/
static void keccak_inc_finalize(uint64_t *s_inc, uint32_t r, uint8_t p) {
    /* After keccak_inc_absorb, we are guaranteed that s_inc[25] < r,
       so we can always use one more byte for p in the current state. */
    if(s_inc[25] == r-1){
      p |= 128;
      KeccakF1600_StateXORBytes(s_inc, &p, s_inc[25], 1);
    } else {
      KeccakF1600_StateXORBytes(s_inc, &p, s_inc[25], 1);
      p = 128;
      KeccakF1600_StateXORBytes(s_inc, &p, r-1, 1);
    }
    s_inc[25] = 0;
}

/*************************************************
 * Name:        keccak_inc_squeeze
 *
 * Description: Incremental Keccak squeeze; can be called on byte-level
 *
 * Arguments:   - uint8_t *h: pointer to output bytes
 *              - size_t outlen: number of bytes to be squeezed
 *              - uint64_t *s_inc: pointer to input/output incremental state
 *                First 25 values represent Keccak state.
 *                26th value represents either the number of absorbed bytes
 *                that have not been permuted, or not-yet-squeezed bytes.
 *              - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
 **************************************************/
static void keccak_inc_squeeze(uint8_t *h, size_t outlen,
                               uint64_t *s_inc, uint32_t r) {
    size_t len;
    if(outlen < s_inc[25])
    {
        len = outlen;
    }
    else
    {
        len = s_inc[25];
    }

    KeccakF1600_StateExtractBytes(s_inc, h, r-s_inc[25], len);
    h += len;
    outlen -= len;
    s_inc[25] -= len;

    /* Then squeeze the remaining necessary blocks */
    while (outlen > 0) {
        KeccakF1600_StatePermute(s_inc);

        if(outlen < r)
        {
            len = outlen;
        }
        else
        {
            len = r;
        }
        KeccakF1600_StateExtractBytes(s_inc, h, 0, len);
        h += len;
        outlen -= len;
        s_inc[25] = r - len;
    }
}

void shake128_inc_init(shake128incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_init(state->ctx);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_absorb(state->ctx, SHAKE128_RATE, input, inlen);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake128_inc_finalize(shake128incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_finalize(state->ctx, SHAKE128_RATE, 0x1F);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_squeeze(output, outlen, state->ctx, SHAKE128_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake128_inc_ctx_clone(shake128incctx* dest, const shake128incctx *src) {
    memcpy(dest, src, sizeof(shake128incctx));
}

void shake128_inc_ctx_release(shake128incctx *state) {
    (void) state;
}

void shake256_inc_init(shake256incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_init(state->ctx);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_absorb(state->ctx, SHAKE256_RATE, input, inlen);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake256_inc_finalize(shake256incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_finalize(state->ctx, SHAKE256_RATE, 0x1F);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_squeeze(output, outlen, state->ctx, SHAKE256_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake256_inc_ctx_clone(shake256incctx* dest, const shake256incctx *src) {
    memcpy(dest, src, sizeof(shake256incctx));
}

void shake256_inc_ctx_release(shake256incctx *state) {
    (void) state;
}

/********** cSHAKE128 ***********/

void cshake128_simple_absorb(shake128ctx *state, uint16_t cstm, const uint8_t *in, size_t inlen)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif


  uint8_t sep[8];
  size_t i;

  for (i = 0; i < 25; i++)
    state->ctx[i] = 0;

  /* Absorb customization (domain-separation) string */
  sep[0] = 0x01;
  sep[1] = 0xa8;
  sep[2] = 0x01;
  sep[3] = 0x00;
  sep[4] = 0x01;
  sep[5] = 16; // fixed bitlen of cstm
  sep[6] = cstm & 0xff;
  sep[7] = cstm >> 8;

  KeccakF1600_StateXORBytes(state->ctx, sep, 0, 8);
  KeccakF1600_StatePermute(state->ctx);

  /* Absorb input */
  keccak_absorb(state->ctx, SHAKE128_RATE, in, inlen, 0x04);

#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif

}


void cshake128_simple_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE128_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}


void cshake128_simple(uint8_t *output, size_t outlen, uint16_t cstm, const uint8_t *in, size_t inlen)
{
  shake128incctx state;
  uint8_t sep[8];
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif

  keccak_inc_init(state.ctx);

  /* Absorb customization (domain-separation) string */
  sep[0] = 0x01;
  sep[1] = 0xa8;
  sep[2] = 0x01;
  sep[3] = 0x00;
  sep[4] = 0x01;
  sep[5] = 16; // fixed bitlen of cstm
  sep[6] = cstm & 0xff;
  sep[7] = cstm >> 8;

  KeccakF1600_StateXORBytes(state.ctx, sep, 0, 8);
  KeccakF1600_StatePermute(state.ctx);

  /* Absorb input */
  keccak_inc_absorb(state.ctx, SHAKE128_RATE, in, inlen);
  keccak_inc_finalize(state.ctx, SHAKE128_RATE, 0x04);

  /* Squeeze output */
  keccak_inc_squeeze(output, outlen, state.ctx, SHAKE128_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}



/*************************************************
 * Name:        shake128_absorb
 *
 * Description: Absorb step of the SHAKE128 XOF.
 *              non-incremental, starts by zeroeing the state.
 *
 * Arguments:   - uint64_t *state:      pointer to (uninitialized) output Keccak state
 *              - const uint8_t *input: pointer to input to be absorbed into state
 *              - size_t inlen:         length of input in bytes
 **************************************************/
void shake128_absorb(shake128ctx *state, const uint8_t *input, size_t inlen)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  int i;
  for (i = 0; i < 25; i++)
    state->ctx[i] = 0;

  keccak_absorb(state->ctx, SHAKE128_RATE, input, inlen, 0x1F);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

/*************************************************
 * Name:        shake128_squeezeblocks
 *
 * Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of SHAKE128_RATE bytes each.
 *              Modifies the state. Can be called multiple times to keep squeezing,
 *              i.e., is incremental.
 *
 * Arguments:   - uint8_t *output:     pointer to output blocks
 *              - size_t nblocks:      number of blocks to be squeezed (written to output)
 *              - shake128ctx *state:  pointer to in/output Keccak state
 **************************************************/
void shake128_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE128_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  shake128incctx state;

  keccak_inc_init(state.ctx);

  /* Absorb input */
  keccak_inc_absorb(state.ctx, SHAKE128_RATE, input, inlen);
  keccak_inc_finalize(state.ctx, SHAKE128_RATE, 0x1F);

  /* Squeeze output */
  keccak_inc_squeeze(output, outlen, state.ctx, SHAKE128_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake128_ctx_release(shake128ctx *state) {
    (void) state;
}
void shake128_ctx_clone(shake128ctx *dest, const shake128ctx *src) {
    memcpy(dest, src, sizeof(shake128ctx));
}

void shake256_absorb(shake256ctx *state, const uint8_t *input, size_t inlen)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  int i;
  for (i = 0; i < 25; i++)
    state->ctx[i] = 0;

  keccak_absorb(state->ctx, SHAKE256_RATE, input, inlen, 0x1F);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}


void shake256_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE256_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

/*************************************************
 * Name:        shake256
 *
 * Description: SHAKE256 XOF with non-incremental API
 *
 * Arguments:   - uint8_t *output:      pointer to output
 *              - size_t outlen:        requested output length in bytes
 *              - const uint8_t *input: pointer to input
 *              - size_t inlen:         length of input in bytes
 **************************************************/
void shake256(uint8_t *output, size_t outlen,
    const uint8_t *input, size_t inlen)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  shake256incctx state;

  keccak_inc_init(state.ctx);

  /* Absorb input */
  keccak_inc_absorb(state.ctx, SHAKE256_RATE, input, inlen);
  keccak_inc_finalize(state.ctx, SHAKE256_RATE, 0x1F);

  /* Squeeze output */
  keccak_inc_squeeze(output, outlen, state.ctx, SHAKE256_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void shake256_ctx_release(shake256ctx *state) {
    (void) state;
}

void shake256_ctx_clone(shake256ctx *dest, const shake256ctx *src) {
    memcpy(dest, src, sizeof(shake256ctx));
}


/*************************************************
 * Name:        sha3_256
 *
 * Description: SHA3-256 with non-incremental API
 *
 * Arguments:   - uint8_t *output:      pointer to output
 *              - const uint8_t *input: pointer to input
 *              - size_t inlen:         length of input in bytes
 **************************************************/
void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  sha3_256incctx state;
  keccak_inc_init(state.ctx);

  /* Absorb input */
  keccak_inc_absorb(state.ctx, SHA3_256_RATE, input, inlen);
  keccak_inc_finalize(state.ctx, SHA3_256_RATE, 0x06);

  /* Squeeze output */
  keccak_inc_squeeze(output, 32, state.ctx, SHA3_256_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}
void sha3_256_inc_init(sha3_256incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_init(state->ctx);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void sha3_256_inc_absorb(sha3_256incctx *state, const uint8_t *input, size_t inlen) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_absorb(state->ctx, SHA3_256_RATE, input, inlen);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void sha3_256_inc_finalize(uint8_t *output, sha3_256incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    uint8_t t[SHA3_256_RATE];
    keccak_inc_finalize(state->ctx, SHA3_256_RATE, 0x06);

    keccak_squeezeblocks(t, 1, state->ctx, SHA3_256_RATE);

    for (size_t i = 0; i < 32; i++) {
        output[i] = t[i];
    }
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void sha3_256_inc_ctx_clone(sha3_256incctx *dest, const sha3_256incctx *src) {
    memcpy(dest, src, sizeof(sha3_256incctx));
}

void sha3_256_inc_ctx_release(sha3_256incctx *state) {
    (void) state;
}

void sha3_384_inc_init(sha3_384incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_init(state->ctx);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void sha3_384_inc_absorb(sha3_384incctx *state, const uint8_t *input, size_t inlen) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_absorb(state->ctx, SHA3_384_RATE, input, inlen);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void sha3_384_inc_finalize(uint8_t *output, sha3_384incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    uint8_t t[SHA3_384_RATE];
    keccak_inc_finalize(state->ctx, SHA3_384_RATE, 0x06);

    keccak_squeezeblocks(t, 1, state->ctx, SHA3_384_RATE);

    for (size_t i = 0; i < 48; i++) {
        output[i] = t[i];
    }
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void sha3_384_inc_ctx_clone(sha3_384incctx *dest, const sha3_384incctx *src) {
    memcpy(dest, src, sizeof(sha3_384incctx));
}

void sha3_384_inc_ctx_release(sha3_384incctx *state) {
    (void) state;
}

/*************************************************
 * Name:        sha3_384
 *
 * Description: SHA3-256 with non-incremental API
 *
 * Arguments:   - uint8_t *output:      pointer to output
 *              - const uint8_t *input: pointer to input
 *              - size_t inlen:   length of input in bytes
 **************************************************/
void sha3_384(uint8_t *output, const uint8_t *input, size_t inlen) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  sha3_384incctx state;
  keccak_inc_init(state.ctx);

  /* Absorb input */
  keccak_inc_absorb(state.ctx, SHA3_384_RATE, input, inlen);
  keccak_inc_finalize(state.ctx, SHA3_384_RATE, 0x06);

  /* Squeeze output */
  keccak_inc_squeeze(output, 48, state.ctx, SHA3_384_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}
/*************************************************
 * Name:        sha3_512
 *
 * Description: SHA3-512 with non-incremental API
 *
 * Arguments:   - uint8_t *output:      pointer to output
 *              - const uint8_t *input: pointer to input
 *              - size_t inlen:         length of input in bytes
 **************************************************/
void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  sha3_512incctx state;
  keccak_inc_init(state.ctx);

  /* Absorb input */
  keccak_inc_absorb(state.ctx, SHA3_512_RATE, input, inlen);
  keccak_inc_finalize(state.ctx, SHA3_512_RATE, 0x06);

  /* Squeeze output */
  keccak_inc_squeeze(output, 64, state.ctx, SHA3_512_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}
void sha3_512_inc_init(sha3_512incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_init(state->ctx);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void sha3_512_inc_absorb(sha3_512incctx *state, const uint8_t *input, size_t inlen) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    keccak_inc_absorb(state->ctx, SHA3_512_RATE, input, inlen);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void sha3_512_inc_finalize(uint8_t *output, sha3_512incctx *state) {
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
    uint8_t t[SHA3_512_RATE];
    keccak_inc_finalize(state->ctx, SHA3_512_RATE, 0x06);

    keccak_squeezeblocks(t, 1, state->ctx, SHA3_512_RATE);

    for (size_t i = 0; i < 64; i++) {
        output[i] = t[i];
    }
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}

void sha3_512_inc_ctx_clone(sha3_512incctx *dest, const sha3_512incctx *src) {
    memcpy(dest, src, sizeof(sha3_512incctx));
}

void sha3_512_inc_ctx_release(sha3_512incctx *state) {
    (void) state;
}

/********** cSHAKE256 ***********/

void cshake256_simple_absorb(shake256ctx *state, uint16_t cstm, const uint8_t *in, size_t inlen)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  uint8_t sep[8];
  size_t i;

  for (i = 0; i < 25; i++)
    state->ctx[i] = 0;

  /* Absorb customization (domain-separation) string */
  sep[0] = 0x01;
  sep[1] = 0x88;
  sep[2] = 0x01;
  sep[3] = 0x00;
  sep[4] = 0x01;
  sep[5] = 16; // fixed bitlen of cstm
  sep[6] = cstm & 0xff;
  sep[7] = cstm >> 8;

  KeccakF1600_StateXORBytes(state->ctx, sep, 0, 8);
  KeccakF1600_StatePermute(state->ctx);

  /* Absorb input */
  keccak_absorb(state->ctx, SHAKE256_RATE, in, inlen, 0x04);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}


void cshake256_simple_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state)
{
#ifdef PROFILE_HASHING
  uint64_t t0 = hal_get_time();
#endif
  keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE256_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}


void cshake256_simple(uint8_t *output, size_t outlen, uint16_t cstm, const uint8_t *in, size_t inlen)
{
  shake256incctx state;
  uint8_t sep[8];
  #ifdef PROFILE_HASHING
    uint64_t t0 = hal_get_time();
  #endif


  keccak_inc_init(state.ctx);

  /* Absorb customization (domain-separation) string */
  sep[0] = 0x01;
  sep[1] = 0x88;
  sep[2] = 0x01;
  sep[3] = 0x00;
  sep[4] = 0x01;
  sep[5] = 16; // fixed bitlen of cstm
  sep[6] = cstm & 0xff;
  sep[7] = cstm >> 8;

  KeccakF1600_StateXORBytes(state.ctx, sep, 0, 8);
  KeccakF1600_StatePermute(state.ctx);

  /* Absorb input */
  keccak_inc_absorb(state.ctx, SHAKE256_RATE, in, inlen);
  keccak_inc_finalize(state.ctx, SHAKE256_RATE, 0x04);

  /* Squeeze output */
  keccak_inc_squeeze(output, outlen, state.ctx, SHAKE256_RATE);
#ifdef PROFILE_HASHING
  uint64_t t1 = hal_get_time();
  hash_cycles += (t1-t0);
#endif
}
back to top