Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

  • 766ff36
  • /
  • common
  • /
  • fips202.c
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
content badge
swh:1:cnt:d57c5132f26f2a43bbf2900abdac652960661c06
directory badge
swh:1:dir:7a1df14e56288daf1f465cf54513d4488403b3df

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
fips202.c
// SPDX-License-Identifier: Apache-2.0 or CC0-1.0
/* 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

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API