diff options
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | Makefile | 20 | ||||
| -rw-r--r-- | main.c | 78 | ||||
| -rw-r--r-- | sha3.c | 1176 | ||||
| -rw-r--r-- | sha3.h | 22 | 
5 files changed, 1299 insertions, 0 deletions
| diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1be7108 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +test-sha3 +sha3 +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..11f844c --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +CFLAGS=-W -Wall -Wextra -Werror -pedantic -std=c11 -O3 -march=native -mtune=native +TEST_APP=./test-sha3 +EXAMPLE_APP=./sha3 +OBJS=sha3.o main.o + +.PHONY=test all + +all: $(EXAMPLE_APP) + +$(EXAMPLE_APP): $(OBJS) +	$(CC) -o $(EXAMPLE_APP) $(CFLAGS) $(OBJS) + +%.o: %.c +	$(CC) -c $(CFLAGS) $< + +test: +	$(CC) -o $(TEST_APP) -DSHA3_TEST sha3.c && $(TEST_APP) + +clean: +	$(RM) -f $(TEST_APP) $(EXAMPLE_APP) $(OBJS) @@ -0,0 +1,78 @@ +#include <stdio.h> +#include <string.h> +#include "sha3.h" + +// available functions +static const struct { +  const char *name; +  const size_t size; +  void (*func)(const uint8_t *, size_t, uint8_t *); +} fns[] = {{ +  .name = "sha3-224", +  .size = 28, +  .func = sha3_224, +}, { +  .name = "sha3-256", +  .size = 32, +  .func = sha3_256, +}, { +  .name = "sha3-384", +  .size = 48, +  .func = sha3_384, +}, { +  .name = "sha3-512", +  .size = 64, +  .func = sha3_512, +}, { +  .name = "shake128", +  .size = 16, +  .func = shake128, +}, { +  .name = "shake256", +  .size = 32, +  .func = shake256, +}}; + +#define USAGE "Usage: %s <algo> <data>\n" \ +              "\n" \ +              "Algorithms:\n" \ +              "- sha3-224\n" \ +              "- sha3-256\n" \ +              "- sha3-384\n" \ +              "- sha3-512\n" \ +              "- shake128\n" \ +              "- shake256\n" \ +              "\n" \ +              "Example:\n" \ +              "  %s sha3-256 \"asdf\"\n" \ +              "  dd2781f4c51bccdbe23e4d398b8a82261f585c278dbb4b84989fea70e76723a9\n" + +int main(int argc, char *argv[]) { +  if (argc < 3) { +    const char *app = (argc > 0) ? argv[0] : "sha3"; +    fprintf(stderr, USAGE, app, app); +    return -1; +  } + +  for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) { +    if (strncmp(argv[1], fns[i].name, strlen(fns[i].name) + 1)) { +      continue; +    } + +    // hash into buf +    uint8_t buf[64]; +    fns[i].func((uint8_t*) argv[2], strlen(argv[2]), buf); + +    // print result +    for (size_t j = 0; j < fns[i].size; j++) { +      printf("%02x", buf[j]); +    } +    fputs("\n", stdout); + +    // exit with success +    return 0; +  } + +  fprintf(stderr, "Unknown algorithm: %s", argv[1]); +  return -1; +} @@ -0,0 +1,1176 @@ +// +// Run self-tests: +//  +//     cc -W -Wall -Wextra -Werror -pedantic -std=c2x -O3 -march=native -mtune=native -mavx -mavx2 -msse2 -msse -mavx512f -std=c11 -DSHA3_TEST % && ./a.out + +#include <stdint.h> // uint64_t +#include <string.h> // memcpy() + +// 64-bit rotate left +#define ROL(v, n) (((v) << (n)) | ((v) >> (64-(n)))) + +static inline void theta(uint64_t a[static 25]) { +  const uint64_t c[5] = { +    a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20], +    a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21], +    a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22], +    a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23], +    a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24], +  }; + +  const uint64_t d[5] = { +    c[4] ^ ROL(c[1], 1), +    c[0] ^ ROL(c[2], 1), +    c[1] ^ ROL(c[3], 1), +    c[2] ^ ROL(c[4], 1), +    c[3] ^ ROL(c[0], 1), +  }; + +  a[ 0] ^= d[0]; a[ 1] ^= d[1]; a[ 2] ^= d[2]; a[ 3] ^= d[3]; a[ 4] ^= d[4]; +  a[ 5] ^= d[0]; a[ 6] ^= d[1]; a[ 7] ^= d[2]; a[ 8] ^= d[3]; a[ 9] ^= d[4]; +  a[10] ^= d[0]; a[11] ^= d[1]; a[12] ^= d[2]; a[13] ^= d[3]; a[14] ^= d[4]; +  a[15] ^= d[0]; a[16] ^= d[1]; a[17] ^= d[2]; a[18] ^= d[3]; a[19] ^= d[4]; +  a[20] ^= d[0]; a[21] ^= d[1]; a[22] ^= d[2]; a[23] ^= d[3]; a[24] ^= d[4]; +} + +static inline void rho(uint64_t a[static 25]) { +  a[1] = ROL(a[1], 1); // 1 % 64 = 1 +  a[2] = ROL(a[2], 62); // 190 % 64 = 62 +  a[3] = ROL(a[3], 28); // 28 % 64 = 28 +  a[4] = ROL(a[4], 27); // 91 % 64 = 27 +  a[5] = ROL(a[5], 36); // 36 % 64 = 36 +  a[6] = ROL(a[6], 44); // 300 % 64 = 44 +  a[7] = ROL(a[7], 6); // 6 % 64 = 6 +  a[8] = ROL(a[8], 55); // 55 % 64 = 55 +  a[9] = ROL(a[9], 20); // 276 % 64 = 20 +  a[10] = ROL(a[10], 3); // 3 % 64 = 3 +  a[11] = ROL(a[11], 10); // 10 % 64 = 10 +  a[12] = ROL(a[12], 43); // 171 % 64 = 43 +  a[13] = ROL(a[13], 25); // 153 % 64 = 25 +  a[14] = ROL(a[14], 39); // 231 % 64 = 39 +  a[15] = ROL(a[15], 41); // 105 % 64 = 41 +  a[16] = ROL(a[16], 45); // 45 % 64 = 45 +  a[17] = ROL(a[17], 15); // 15 % 64 = 15 +  a[18] = ROL(a[18], 21); // 21 % 64 = 21 +  a[19] = ROL(a[19], 8); // 136 % 64 = 8 +  a[20] = ROL(a[20], 18); // 210 % 64 = 18 +  a[21] = ROL(a[21], 2); // 66 % 64 = 2 +  a[22] = ROL(a[22], 61); // 253 % 64 = 61 +  a[23] = ROL(a[23], 56); // 120 % 64 = 56 +  a[24] = ROL(a[24], 14); // 78 % 64 = 14 +} + +static inline void pi(uint64_t a[static 25]) { +  uint64_t t[25] = { 0 }; +  memcpy(t, a, sizeof(t)); +  a[1] = t[6]; +  a[2] = t[12]; +  a[3] = t[18]; +  a[4] = t[24]; +  a[5] = t[3]; +  a[6] = t[9]; +  a[7] = t[10]; +  a[8] = t[16]; +  a[9] = t[22]; +  a[10] = t[1]; +  a[11] = t[7]; +  a[12] = t[13]; +  a[13] = t[19]; +  a[14] = t[20]; +  a[15] = t[4]; +  a[16] = t[5]; +  a[17] = t[11]; +  a[18] = t[17]; +  a[19] = t[23]; +  a[20] = t[2]; +  a[21] = t[8]; +  a[22] = t[14]; +  a[23] = t[15]; +  a[24] = t[21]; +} + +static inline void chi(uint64_t a[static 25]) { +  uint64_t t[25] = { 0 }; +  memcpy(t, a, sizeof(t)); +  a[0] = t[0] ^ (~t[1] & t[2]); +  a[1] = t[1] ^ (~t[2] & t[3]); +  a[2] = t[2] ^ (~t[3] & t[4]); +  a[3] = t[3] ^ (~t[4] & t[0]); +  a[4] = t[4] ^ (~t[0] & t[1]); +  a[5] = t[5] ^ (~t[6] & t[7]); +  a[6] = t[6] ^ (~t[7] & t[8]); +  a[7] = t[7] ^ (~t[8] & t[9]); +  a[8] = t[8] ^ (~t[9] & t[5]); +  a[9] = t[9] ^ (~t[5] & t[6]); +  a[10] = t[10] ^ (~t[11] & t[12]); +  a[11] = t[11] ^ (~t[12] & t[13]); +  a[12] = t[12] ^ (~t[13] & t[14]); +  a[13] = t[13] ^ (~t[14] & t[10]); +  a[14] = t[14] ^ (~t[10] & t[11]); +  a[15] = t[15] ^ (~t[16] & t[17]); +  a[16] = t[16] ^ (~t[17] & t[18]); +  a[17] = t[17] ^ (~t[18] & t[19]); +  a[18] = t[18] ^ (~t[19] & t[15]); +  a[19] = t[19] ^ (~t[15] & t[16]); +  a[20] = t[20] ^ (~t[21] & t[22]); +  a[21] = t[21] ^ (~t[22] & t[23]); +  a[22] = t[22] ^ (~t[23] & t[24]); +  a[23] = t[23] ^ (~t[24] & t[20]); +  a[24] = t[24] ^ (~t[20] & t[21]); +} + +static inline void iota(uint64_t a[static 25], const int i) { +  // round constants (ambiguous in spec) +  static const uint64_t RCS[] = { +    0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, +    0x000000000000808bULL, 0x0000000080000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, +    0x000000000000008aULL, 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL, +    0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, +    0x8000000000008002ULL, 0x8000000000000080ULL, 0x000000000000800aULL, 0x800000008000000aULL, +    0x8000000080008081ULL, 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL, +  }; + +  a[0] ^= RCS[i]; +} + +static inline void permute(uint64_t a[static 25]) { +  for (int i = 0; i < 24; i++) { +    theta(a); +    rho(a); +    pi(a); +    chi(a); +    iota(a, i); +  } +} + +typedef union { +  uint8_t u8[200]; +  uint64_t u64[25]; +} state_t; + +static inline size_t keccak(state_t * const a, const uint8_t *m, size_t m_len, const size_t rate) { +  while (m_len >= rate) { +    // absorb u64-sized chunks +    for (size_t i = 0; i < rate / sizeof(uint64_t); i++) { +      a->u64[i] ^= ((uint64_t*) m)[i]; +    } + +    // permute +    permute(a->u64); + +    m += rate; +    m_len -= rate; +  } + +  // absorb u64-sized chunks +  for (size_t i = 0; i < m_len / sizeof(uint64_t); i++) { +    a->u64[i] ^= ((uint64_t*) m)[i]; +  } + +  // absorb final bytes +  for (size_t i = m_len & ~(sizeof(uint64_t) - 1); i < m_len; i++) { +    a->u8[i] ^= m[i]; +  } + +  // return final chunk size +  return m_len; +} + +static inline void sha3(const uint8_t *m, size_t m_len, uint8_t * const dst, const size_t dst_len) { +  // in the sha3 hash functions, the capacity is always 2 times the +  // destination length, and the rate is the total state size minus the +  // capacity +  const size_t rate = 200 - 2 * dst_len; + +  state_t a = { .u64 = { 0 } }; + +  const size_t len = keccak(&a, m, m_len, rate); + +  // append suffix and padding +  // (note: suffix and padding are ambiguous in spec) +  a.u8[len] ^= 0x06; +  a.u8[rate-1] ^= 0x80; + +  // permute +  permute(a.u64); + +  // copy to destination +  memcpy(dst, a.u8, dst_len); +} + +void sha3_224(const uint8_t *m, size_t m_len, uint8_t dst[static 28]) { +  sha3(m, m_len, dst, 28); +} + +void sha3_256(const uint8_t *m, size_t m_len, uint8_t dst[static 32]) { +  sha3(m, m_len, dst, 32); +} + +void sha3_384(const uint8_t *m, size_t m_len, uint8_t dst[static 48]) { +  sha3(m, m_len, dst, 48); +} + +void sha3_512(const uint8_t *m, size_t m_len, uint8_t dst[static 64]) { +  sha3(m, m_len, dst, 64); +} + +static inline void shake(const uint8_t *m, size_t m_len, uint8_t * const dst, const size_t dst_len) { +  // in the sha3 xof functions, the capacity is always 2 times the +  // destination length, and the rate is the total state size minus the +  // capacity +  const size_t rate = 200 - 2 * dst_len; + +  state_t a = { .u64 = { 0 } }; + +  const size_t len = keccak(&a, m, m_len, rate); + +  // append suffix (s6.2) and padding +  // (note: suffix and padding are ambiguous in spec) +  a.u8[len] ^= 0x1f; +  a.u8[rate-1] ^= 0x80; + +  // permute +  permute(a.u64); + +  // copy to destination +  memcpy(dst, a.u8, dst_len); +} + +void shake128(const uint8_t *m, size_t m_len, uint8_t dst[static 16]) { +  shake(m, m_len, dst, 16); +} + +void shake256(const uint8_t *m, size_t m_len, uint8_t dst[static 32]) { +  shake(m, m_len, dst, 32); +} + + +#ifdef SHA3_TEST +#include <stdio.h> // printf() + +static void dump_hex(FILE *f, const uint8_t * const a, const size_t len) { +  fprintf(f, "  "); +  for (size_t i = 0; i < len; i++) { +    fprintf(f, "%02x ", a[i]); +    if ((i + 1) % 16 == 0) { +      fprintf(f, "\n  "); +    } +  } +  fprintf(f, "\n"); +} + +static void dump_state(FILE *f, const uint64_t a[static 25]) { +  dump_hex(f, (const uint8_t *) a, 25 * 8); +} + +static void test_theta(void) { +  // src: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-256_Msg30.pdf +  uint64_t a[25] = { [0] = 0x00000001997b5853ULL, [16] = 0x8000000000000000ULL }; +  const uint8_t exp[] = {  +    0x52, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00,  0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, +    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, +    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, +  }; + +  theta(a); +  if (memcmp(exp, a, sizeof(exp))) { +    fprintf(stderr, "test_theta() failed, got:\n"); +    dump_state(stderr, a); + +    fprintf(stderr, "exp:\n"); +    dump_state(stderr, (uint64_t*) exp); +  } +} + +static void test_rho(void) { +  uint8_t a[] = {  +    0x52, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00,  0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, +    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, +    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, +  }; + +  const uint8_t exp[] = { +    0x52, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, 0x97, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +    0x97, 0x19, 0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0A, 0x6B, 0x2F, 0x33, 0x00, +    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x99, 0x01, 0x00, 0x00, 0x00, 0x53, 0x58, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +    0x2F, 0x33, 0x00, 0x00, 0x00, 0x70, 0x0A, 0x6B, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x80, 0x29, 0xAC, 0xBD, 0xCC, 0x00, 0x00, +  }; + +  rho((uint64_t*) a); +  if (memcmp(exp, a, sizeof(exp))) { +    fprintf(stderr, "test_rho() failed, got:\n"); +    dump_state(stderr, (uint64_t*) a); + +    fprintf(stderr, "exp:\n"); +    dump_state(stderr, (uint64_t*) exp); +  } +} + +static void test_pi(void) { +  uint8_t a[] = { +    0x52, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, 0x97, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +    0x97, 0x19, 0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0A, 0x6B, 0x2F, 0x33, 0x00, +    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x99, 0x01, 0x00, 0x00, 0x00, 0x53, 0x58, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +    0x2F, 0x33, 0x00, 0x00, 0x00, 0x70, 0x0A, 0x6B, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x80, 0x29, 0xAC, 0xBD, 0xCC, 0x00, 0x00, +  }; + +  const uint8_t exp[] = { +    0x52, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, 0x97, 0x19, 0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x80, 0x29, 0xAC, 0xBD, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x60, 0x0A, 0x6B, 0x2F, 0x33, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x2F, 0x33, 0x00, 0x00, 0x00, 0x70, 0x0A, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, 0x97, 0x19, +    0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, +    0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x99, 0x01, 0x00, 0x00, 0x00, 0x53, 0x58, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +    0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, 0x00, +  }; + +  pi((uint64_t*) a); +  if (memcmp(exp, a, sizeof(exp))) { +    fprintf(stderr, "test_pi() failed, got:\n"); +    dump_state(stderr, (uint64_t*) a); + +    fprintf(stderr, "exp:\n"); +    dump_state(stderr, (uint64_t*) exp); +  } +} + +static void test_chi(void) { +  uint8_t a[] = { +    0x52, 0x58, 0x7B, 0x99, 0x01, 0x00, 0x00, 0x00, 0x97, 0x19, 0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x80, 0x29, 0xAC, 0xBD, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x60, 0x0A, 0x6B, 0x2F, 0x33, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x2F, 0x33, 0x00, 0x00, 0x00, 0x70, 0x0A, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, 0x97, 0x19, +    0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, +    0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x99, 0x01, 0x00, 0x00, 0x00, 0x53, 0x58, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +    0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, 0x00, +  }; + +  const uint8_t exp[] = { +    0x52, 0x58, 0x7B, 0x99, 0x01, 0x04, 0x00, 0x00, 0x97, 0x19, 0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, +    0x00, 0x80, 0x29, 0xAC, 0xBD, 0xC8, 0x00, 0x00, 0x52, 0x58, 0x52, 0x11, 0x00, 0x00, 0x00, 0x00, +    0x85, 0x81, 0x29, 0xAC, 0xBD, 0xFC, 0x85, 0xB5, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x27, 0x33, 0x60, 0x0A, 0x6B, 0x5F, 0x39, 0x6B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, +    0x2F, 0x33, 0x00, 0x00, 0x00, 0x70, 0x0A, 0x6B, 0x00, 0x00, 0x60, 0x0A, 0x6B, 0x2F, 0x33, 0x10, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, 0x20, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x16, 0x42, 0xC4, 0x31, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xDD, 0xE0, 0xB3, 0x97, 0x19, +    0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, +    0x00, 0x40, 0x00, 0x30, 0x85, 0xB5, 0x97, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +    0x99, 0x01, 0x00, 0x00, 0x00, 0x53, 0x58, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0xD5, 0x60, 0xED, 0x65, 0x06, 0x53, 0x58, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, +    0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, 0x00, +  }; + +  chi((uint64_t*) a); +  if (memcmp(exp, a, sizeof(exp))) { +    fprintf(stderr, "test_chi() failed, got:\n"); +    dump_state(stderr, (uint64_t*) a); + +    fprintf(stderr, "exp:\n"); +    dump_state(stderr, (uint64_t*) exp); +  } +} + +static void test_iota(void) { +  uint8_t a[] = { +    0x52, 0x58, 0x7B, 0x99, 0x01, 0x04, 0x00, 0x00, 0x97, 0x19, 0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, +    0x00, 0x80, 0x29, 0xAC, 0xBD, 0xC8, 0x00, 0x00, 0x52, 0x58, 0x52, 0x11, 0x00, 0x00, 0x00, 0x00, +    0x85, 0x81, 0x29, 0xAC, 0xBD, 0xFC, 0x85, 0xB5, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x27, 0x33, 0x60, 0x0A, 0x6B, 0x5F, 0x39, 0x6B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, +    0x2F, 0x33, 0x00, 0x00, 0x00, 0x70, 0x0A, 0x6B, 0x00, 0x00, 0x60, 0x0A, 0x6B, 0x2F, 0x33, 0x10, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, 0x20, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x16, 0x42, 0xC4, 0x31, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xDD, 0xE0, 0xB3, 0x97, 0x19, +    0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, +    0x00, 0x40, 0x00, 0x30, 0x85, 0xB5, 0x97, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +    0x99, 0x01, 0x00, 0x00, 0x00, 0x53, 0x58, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0xD5, 0x60, 0xED, 0x65, 0x06, 0x53, 0x58, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, +    0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, 0x00, +  }; + +  const uint8_t exp[] = { +    0x53, 0x58, 0x7B, 0x99, 0x01, 0x04, 0x00, 0x00, 0x97, 0x19, 0x00, 0x00, 0x00, 0x30, 0x85, 0xB5, +    0x00, 0x80, 0x29, 0xAC, 0xBD, 0xC8, 0x00, 0x00, 0x52, 0x58, 0x52, 0x11, 0x00, 0x00, 0x00, 0x00, +    0x85, 0x81, 0x29, 0xAC, 0xBD, 0xFC, 0x85, 0xB5, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0x27, 0x33, 0x60, 0x0A, 0x6B, 0x5F, 0x39, 0x6B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, +    0x2F, 0x33, 0x00, 0x00, 0x00, 0x70, 0x0A, 0x6B, 0x00, 0x00, 0x60, 0x0A, 0x6B, 0x2F, 0x33, 0x10, +    0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, 0x00, 0x20, 0xA6, 0xB0, 0xF6, 0x32, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x16, 0x42, 0xC4, 0x31, 0x03, 0x00, 0x00, +    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xDD, 0xE0, 0xB3, 0x97, 0x19, +    0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, +    0x00, 0x40, 0x00, 0x30, 0x85, 0xB5, 0x97, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +    0x99, 0x01, 0x00, 0x00, 0x00, 0x53, 0x58, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +    0xD5, 0x60, 0xED, 0x65, 0x06, 0x53, 0x58, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, +    0x4C, 0x61, 0xED, 0x65, 0x06, 0x00, 0x00, 0x00, +  }; + +  iota((uint64_t*) a, 0); +  if (memcmp(exp, a, sizeof(exp))) { +    fprintf(stderr, "test_iota() failed, got:\n"); +    dump_state(stderr, (uint64_t*) a); + +    fprintf(stderr, "exp:\n"); +    dump_state(stderr, (uint64_t*) exp); +  } +} + +static void test_permute(void) { +  uint64_t a[25] = { [0] = 0x00000001997b5853ULL, [16] = 0x8000000000000000ULL }; +  const uint64_t exp[] = { +    0xE95A9E40EF2F24C8ULL, 0x24C64DAE57C8F1D1ULL, +    0x8CAA629F80192BB9ULL, 0xD0B178A0541C4107ULL, +  }; + +  permute(a); +  if (memcmp(exp, a, sizeof(exp))) { +    fprintf(stderr, "test_permute() failed, got:\n"); +    dump_hex(stderr, (uint8_t*) a, 32); + +    fprintf(stderr, "exp:\n"); +    dump_hex(stderr, (uint8_t*) exp, 32); +  } +} + +static void test_sha3_224(void) { +  static const struct { +    const char *name; // test name +    const uint8_t msg[256]; // test message +    const size_t len; // test message length +    const uint8_t exp[28]; // expected hash +  } tests[] = {{ +    .name = "empty", +    .msg = "", +    .len = 0, +    .exp = { +      0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, +      0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab, +      0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, +      0x5b, 0x5a, 0x6b, 0xc7,  +    }, +  }, { +    .name = "asdf", +    .msg = "asdf", +    .len = 4, +    .exp = { +      0x47, 0xcc, 0xa2, 0x03, 0xee, 0xfc, 0xa3, 0x49, +      0xde, 0xaa, 0x41, 0x8d, 0xa7, 0xfe, 0x05, 0x38, +      0x9e, 0xf6, 0x49, 0x98, 0x5c, 0x87, 0xa9, 0xb6, +      0x55, 0xad, 0x12, 0x8c, +    }, +  }, { +    .name = "a-134", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 134, +    .exp = { +      0x5d, 0x1d, 0xb4, 0xe4, 0x7c, 0x0c, 0x4a, 0x42, +      0x45, 0xb9, 0x0d, 0x18, 0x55, 0xb0, 0x7c, 0xb1, +      0x6f, 0xb9, 0x40, 0xc5, 0x00, 0x76, 0xc1, 0xfd, +      0x2a, 0xc2, 0x17, 0xfe,  +    }, +  }, { +    .name = "a-135", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 135, +    .exp = { +      0xf9, 0xf2, 0x8c, 0x21, 0xa2, 0xb0, 0x88, 0x4b, +      0xbd, 0x35, 0x94, 0xca, 0xe8, 0x2b, 0xf8, 0x11, +      0xc0, 0xc1, 0xed, 0xe4, 0x27, 0xe0, 0x83, 0xd5, +      0x57, 0x6e, 0x90, 0x9d,  +    }, +  }, { +    .name = "a-136", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 136, +    .exp = { +      0x96, 0x13, 0x6a, 0x6a, 0x09, 0x44, 0x33, 0xb4, +      0xaa, 0x85, 0x5f, 0x16, 0x38, 0x29, 0xa2, 0xce, +      0x6b, 0xca, 0x7d, 0x56, 0xcf, 0xd2, 0x16, 0x3b, +      0x47, 0xf1, 0xf1, 0xc4,  +    }, +  }, { +    .name = "ff-256", +    .msg = { +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +    }, +    .len = 256, +    .exp = { +      0xb6, 0x53, 0x4d, 0x8b, 0xee, 0xdf, 0xb5, 0xed, +      0x3f, 0x95, 0x3b, 0x09, 0xd1, 0x2f, 0xc3, 0x8f, +      0x3d, 0x8b, 0x0b, 0xea, 0x9d, 0x80, 0xbd, 0x1e, +      0x25, 0xc9, 0xfc, 0x35,  +    }, +  }, { +    .name = "a-210", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 210, +    .exp = { +      0x03, 0x05, 0x4a, 0xb0, 0xa3, 0x37, 0x99, 0xbe, +      0x2b, 0x17, 0xc8, 0x2b, 0x3a, 0x13, 0x90, 0x05, +      0x2e, 0x49, 0xdf, 0x31, 0x6d, 0x85, 0x15, 0x2d, +      0x74, 0x66, 0xab, 0x57,  +    }, +  }}; + +  for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { +    uint8_t got[28] = { 0 }; +    sha3_224(tests[i].msg, tests[i].len, got); +    if (memcmp(got, tests[i].exp, sizeof(got))) { +      fprintf(stderr, "test_sha3_224(\"%s\") failed, got:\n", tests[i].name); +      dump_hex(stderr, got, 28); + +      fprintf(stderr, "exp:\n"); +      dump_hex(stderr, tests[i].exp, 28); +    } +  } +} + +static void test_sha3_256(void) { +  static const struct { +    const char *name; // test name +    const uint8_t msg[256]; // test message +    const size_t len; // test message length +    const uint8_t exp[32]; // expected hash +  } tests[] = {{ +    .name = "empty", +    .msg = "", +    .len = 0, +    .exp = { +      0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, +      0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, +      0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, +      0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a,  +    }, +  }, { +    .name = "asdf", +    .msg = "asdf", +    .len = 4, +    .exp = { +      0xdd, 0x27, 0x81, 0xf4, 0xc5, 0x1b, 0xcc, 0xdb, +      0xe2, 0x3e, 0x4d, 0x39, 0x8b, 0x8a, 0x82, 0x26, +      0x1f, 0x58, 0x5c, 0x27, 0x8d, 0xbb, 0x4b, 0x84, +      0x98, 0x9f, 0xea, 0x70, 0xe7, 0x67, 0x23, 0xa9,  +    }, +  }, { +    .name = "a-134", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 134, +    .exp = { +      0x58, 0xb9, 0x70, 0xc3, 0x7a, 0xc2, 0xd6, 0x5b, +      0x59, 0x9b, 0x69, 0x18, 0x68, 0xa6, 0x14, 0x01, +      0xa5, 0x01, 0xc4, 0x0f, 0x23, 0x5d, 0x55, 0xf0, +      0x59, 0xd3, 0x9a, 0x94, 0x2f, 0x41, 0xdc, 0xee, +    }, +  }, { +    .name = "a-135", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 135, +    .exp = { +      0x80, 0x94, 0xbb, 0x53, 0xc4, 0x4c, 0xfb, 0x1e, +      0x67, 0xb7, 0xc3, 0x04, 0x47, 0xf9, 0xa1, 0xc3, +      0x36, 0x96, 0xd2, 0x46, 0x3e, 0xcc, 0x1d, 0x9c, +      0x92, 0x53, 0x89, 0x13, 0x39, 0x28, 0x43, 0xc9, +    }, +  }, { +    .name = "a-136", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 136, +    .exp = { +      0x3f, 0xc5, 0x55, 0x9f, 0x14, 0xdb, 0x8e, 0x45, +      0x3a, 0x0a, 0x30, 0x91, 0xed, 0xbd, 0x2b, 0xc2, +      0x5e, 0x11, 0x52, 0x8d, 0x81, 0xc6, 0x6f, 0xa5, +      0x70, 0xa4, 0xef, 0xdc, 0xc2, 0x69, 0x5e, 0xe1, +    }, +  }, { +    .name = "ff-256", +    .msg = { +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +    }, +    .len = 256, +    .exp = { +      0xea, 0xa5, 0x7c, 0x69, 0x9a, 0x7a, 0x61, 0x4f, +      0x9d, 0x96, 0x1e, 0x42, 0xd8, 0xb1, 0x2a, 0x93, +      0x54, 0x6e, 0x8e, 0x80, 0xd3, 0x1f, 0x5c, 0xfc, +      0xc4, 0x3f, 0x95, 0x39, 0xed, 0x06, 0x30, 0x7a,  +    }, +  }, { +    .name = "a-210", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 210, +    .exp = { +      0xb4, 0x12, 0xbd, 0x70, 0xce, 0x67, 0xeb, 0x59, +      0x0b, 0xb2, 0x25, 0x09, 0xef, 0x4e, 0x68, 0x7e, +      0x02, 0xb4, 0x8e, 0x07, 0xd2, 0xbb, 0xd7, 0xbb, +      0x9a, 0xfb, 0x58, 0x70, 0xfd, 0x14, 0xc1, 0x13,  +    }, +  }}; + +  for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { +    uint8_t got[32] = { 0 }; +    sha3_256(tests[i].msg, tests[i].len, got); +    if (memcmp(got, tests[i].exp, sizeof(got))) { +      fprintf(stderr, "test_sha3_256(\"%s\") failed, got:\n", tests[i].name); +      dump_hex(stderr, got, 32); + +      fprintf(stderr, "exp:\n"); +      dump_hex(stderr, tests[i].exp, 32); +    } +  } +} + +static void test_sha3_384(void) { +  static const struct { +    const char *name; // test name +    const uint8_t msg[256]; // test message +    const size_t len; // test message length +    const uint8_t exp[48]; // expected hash +  } tests[] = {{ +    .name = "empty", +    .msg = "", +    .len = 0, +    .exp = { +      0x0c, 0x63, 0xa7, 0x5b, 0x84, 0x5e, 0x4f, 0x7d, +      0x01, 0x10, 0x7d, 0x85, 0x2e, 0x4c, 0x24, 0x85, +      0xc5, 0x1a, 0x50, 0xaa, 0xaa, 0x94, 0xfc, 0x61, +      0x99, 0x5e, 0x71, 0xbb, 0xee, 0x98, 0x3a, 0x2a, +      0xc3, 0x71, 0x38, 0x31, 0x26, 0x4a, 0xdb, 0x47, +      0xfb, 0x6b, 0xd1, 0xe0, 0x58, 0xd5, 0xf0, 0x04,  +    }, +  }, { +    .name = "asdf", +    .msg = "asdf", +    .len = 4, +    .exp = { +      0xcc, 0x8c, 0x24, 0x61, 0xa8, 0xac, 0xb5, 0x8c, +      0x9e, 0x7b, 0x78, 0x95, 0x8e, 0xa3, 0x6d, 0x5f, +      0xd3, 0x20, 0x38, 0xf9, 0x58, 0xcd, 0xbb, 0x59, +      0xf2, 0x6b, 0x0f, 0xfd, 0x1c, 0x36, 0x57, 0x61, +      0x83, 0xe1, 0xc2, 0xca, 0x33, 0x57, 0xca, 0x1e, +      0x33, 0x3a, 0x11, 0xaf, 0xac, 0x8a, 0xed, 0xe6,  +    }, +  }, { +    .name = "a-134", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 134, +    .exp = { +      0xac, 0x8b, 0xca, 0x5d, 0x14, 0xed, 0xb5, 0xfc, +      0x82, 0xe2, 0x2e, 0x45, 0x33, 0x34, 0xcb, 0x39, +      0xef, 0x43, 0x14, 0xa5, 0x9a, 0xd7, 0xba, 0x6f, +      0xb1, 0x0f, 0x0b, 0x11, 0xbe, 0x7b, 0x4a, 0xf3, +      0xfd, 0xe3, 0xe9, 0x54, 0x07, 0x81, 0xc2, 0x39, +      0xfa, 0x4c, 0x1f, 0x60, 0x44, 0xf3, 0x1d, 0xa9,  +    }, +  }, { +    .name = "a-135", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 135, +    .exp = { +      0xa2, 0xd5, 0x19, 0x07, 0xc0, 0x61, 0x1e, 0x25, +      0xc0, 0x58, 0xf0, 0x67, 0x50, 0x42, 0xe8, 0xf5, +      0x3c, 0xc4, 0x73, 0xdc, 0x34, 0x7c, 0x5e, 0xa8, +      0xa8, 0x13, 0xd8, 0x86, 0xb3, 0xaa, 0x8f, 0x8d, +      0xca, 0xb6, 0x1a, 0x23, 0x62, 0x37, 0xd9, 0x4d, +      0xe4, 0x04, 0xcd, 0x66, 0x60, 0x62, 0x43, 0xf9,  +    }, +  }, { +    .name = "a-136", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 136, +    .exp = { +      0xcb, 0xbc, 0xb4, 0x66, 0x41, 0x7a, 0x2f, 0x6d, +      0x46, 0x64, 0x79, 0xbb, 0x6d, 0xc6, 0x59, 0x43, +      0x4d, 0x95, 0x89, 0xde, 0x3a, 0x53, 0xac, 0xc9, +      0xb4, 0x27, 0x58, 0x04, 0x82, 0xe3, 0x05, 0x94, +      0x88, 0x88, 0xc8, 0xfa, 0x6d, 0x06, 0x9c, 0x5e, +      0x6a, 0x89, 0x9a, 0xa3, 0x4a, 0x9a, 0xf1, 0x5a,  +    }, +  }, { +    .name = "ff-256", +    .msg = { +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +    }, +    .len = 256, +    .exp = { +      0x91, 0xb2, 0xc0, 0xab, 0x2c, 0xe3, 0x31, 0xcd, +      0x59, 0xab, 0x98, 0x3b, 0x87, 0xaf, 0xc9, 0xe5, +      0x45, 0x66, 0x33, 0xb1, 0x30, 0x49, 0xac, 0x84, +      0x36, 0x04, 0xc9, 0xb6, 0xc3, 0xab, 0x09, 0xc3, +      0x5c, 0xf8, 0x8c, 0xcb, 0xf7, 0x61, 0xc5, 0x64, +      0x7c, 0x92, 0x2b, 0xcc, 0x9b, 0x37, 0x5a, 0x6b,  +    }, +  }, { +    .name = "a-210", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 210, +    .exp = { +      0x23, 0x2f, 0xba, 0x5c, 0x81, 0x59, 0x36, 0xc7, +      0x7b, 0x37, 0x3a, 0x5e, 0x5d, 0xa0, 0xd2, 0xca, +      0x3b, 0x15, 0xcd, 0x28, 0x58, 0x92, 0x66, 0x14, +      0x5a, 0x92, 0xd6, 0x50, 0xfa, 0x58, 0xef, 0x4f, +      0xdf, 0xa3, 0x4e, 0x9e, 0x2f, 0x0e, 0xa8, 0x7a, +      0x67, 0x32, 0x8f, 0x68, 0x9a, 0x6b, 0x8f, 0x04,  +    }, +  }}; + +  for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { +    uint8_t got[48] = { 0 }; +    sha3_384(tests[i].msg, tests[i].len, got); +    if (memcmp(got, tests[i].exp, sizeof(got))) { +      fprintf(stderr, "test_sha3_384(\"%s\") failed, got:\n", tests[i].name); +      dump_hex(stderr, got, 48); + +      fprintf(stderr, "exp:\n"); +      dump_hex(stderr, tests[i].exp, 48); +    } +  } +} + +static void test_sha3_512(void) { +  static const struct { +    const char *name; // test name +    const uint8_t msg[256]; // test message +    const size_t len; // test message length +    const uint8_t exp[64]; // expected hash +  } tests[] = {{ +    .name = "empty", +    .msg = "", +    .len = 0, +    .exp = { +      0xa6, 0x9f, 0x73, 0xcc, 0xa2, 0x3a, 0x9a, 0xc5, +      0xc8, 0xb5, 0x67, 0xdc, 0x18, 0x5a, 0x75, 0x6e, +      0x97, 0xc9, 0x82, 0x16, 0x4f, 0xe2, 0x58, 0x59, +      0xe0, 0xd1, 0xdc, 0xc1, 0x47, 0x5c, 0x80, 0xa6, +      0x15, 0xb2, 0x12, 0x3a, 0xf1, 0xf5, 0xf9, 0x4c, +      0x11, 0xe3, 0xe9, 0x40, 0x2c, 0x3a, 0xc5, 0x58, +      0xf5, 0x00, 0x19, 0x9d, 0x95, 0xb6, 0xd3, 0xe3, +      0x01, 0x75, 0x85, 0x86, 0x28, 0x1d, 0xcd, 0x26,  +    }, +  }, { +    .name = "asdf", +    .msg = "asdf", +    .len = 4, +    .exp = { +      0x8d, 0x88, 0xcf, 0x5b, 0x20, 0xf5, 0x3a, 0xcd, +      0x7a, 0xe1, 0x47, 0x9b, 0x5b, 0x36, 0xdc, 0x20, +      0x21, 0x75, 0x3b, 0x04, 0x99, 0x02, 0xc7, 0x72, +      0x47, 0xbb, 0x27, 0xb1, 0x31, 0xb3, 0x00, 0xbd, +      0x3c, 0xa8, 0xbe, 0xef, 0x28, 0x75, 0x6d, 0xce, +      0x27, 0xb8, 0x99, 0x08, 0x67, 0xc4, 0x57, 0x7a, +      0x25, 0x35, 0xe7, 0xe3, 0xb7, 0x51, 0x41, 0x39, +      0x9c, 0xa1, 0xa9, 0x4c, 0xc8, 0x4b, 0x0e, 0xb9,  +    }, +  }, { +    .name = "a-134", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 134, +    .exp = { +      0x4e, 0x72, 0xa4, 0xf6, 0x55, 0x99, 0xa2, 0x47, +      0x2a, 0x66, 0xf8, 0xa8, 0xd6, 0xcf, 0xb3, 0x84, +      0xb7, 0xd3, 0x4f, 0x52, 0xec, 0xaa, 0x00, 0xe9, +      0xf0, 0x66, 0x82, 0x0b, 0x0e, 0xdc, 0x1f, 0xcc, +      0x9c, 0xf3, 0x12, 0x0b, 0x81, 0x46, 0x89, 0xbc, +      0x62, 0xb7, 0x72, 0x0f, 0x4e, 0x4c, 0x99, 0x3d, +      0xa0, 0x84, 0x08, 0x27, 0xf6, 0x95, 0x03, 0x8a, +      0x82, 0x18, 0x69, 0xe8, 0xa6, 0x27, 0x60, 0xe8,  +    }, +  }, { +    .name = "a-135", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 135, +    .exp = { +      0x4b, 0xe1, 0xe7, 0x02, 0x76, 0xf9, 0x12, 0x2f, +      0x47, 0x0a, 0x54, 0xc2, 0x72, 0x40, 0xc7, 0xd0, +      0x70, 0x9d, 0xab, 0x74, 0x69, 0x95, 0x8b, 0x48, +      0xa9, 0x50, 0xd6, 0x9d, 0xa6, 0xdd, 0x07, 0xca, +      0x13, 0x58, 0x26, 0xd9, 0xd2, 0x3e, 0x97, 0x5c, +      0xb9, 0x28, 0x3e, 0x7d, 0x23, 0x6e, 0xf9, 0x8a, +      0x80, 0x45, 0x1d, 0xca, 0x8e, 0x31, 0x1f, 0x52, +      0x09, 0x63, 0x08, 0xb2, 0xc8, 0xd7, 0x0c, 0xc7,  +    }, +  }, { +    .name = "a-136", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 136, +    .exp = { +      0xe5, 0x03, 0x92, 0xc9, 0x1e, 0xd9, 0x57, 0x68, +      0xc8, 0xdc, 0xf5, 0x2a, 0x12, 0xe5, 0xdb, 0x1e, +      0xcd, 0x03, 0x47, 0xfb, 0x99, 0x5f, 0x7f, 0xf4, +      0xea, 0x06, 0x99, 0x46, 0x49, 0xbb, 0xd1, 0xa0, +      0xde, 0x7a, 0xe3, 0x6a, 0x62, 0xaa, 0xdc, 0x00, +      0xa7, 0x04, 0xd7, 0x30, 0xb5, 0x2b, 0xda, 0x19, +      0x1b, 0x72, 0x95, 0x1e, 0x2a, 0xfc, 0x9b, 0x6f, +      0xb6, 0x82, 0x47, 0x87, 0xb2, 0x08, 0x62, 0x57,  +    }, +  }, { +    .name = "ff-256", +    .msg = { +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +    }, +    .len = 256, +    .exp = { +      0x02, 0x3a, 0x91, 0x27, 0xcf, 0x29, 0x6d, 0x01, +      0x12, 0x0e, 0x3d, 0xaa, 0x92, 0x76, 0x15, 0x23, +      0x8e, 0x97, 0xdd, 0xb6, 0x33, 0x26, 0xe2, 0x89, +      0xb3, 0x31, 0xe2, 0x25, 0xbe, 0x41, 0xea, 0xd5, +      0x90, 0xf1, 0xdd, 0x5c, 0x80, 0x1d, 0x91, 0x03, +      0xfe, 0x65, 0x7d, 0x23, 0x63, 0xbd, 0xb2, 0x66, +      0xe7, 0x90, 0xb1, 0x89, 0x0b, 0x3d, 0xd5, 0x79, +      0xdc, 0xa7, 0xf9, 0x1f, 0x5f, 0x4d, 0x98, 0x49,  +    }, +  }, { +    .name = "a-210", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 210, +    .exp = { +      0x47, 0xfa, 0xd7, 0x8d, 0x72, 0x35, 0xe5, 0xcd, +      0xb9, 0xd7, 0x23, 0x6c, 0xfc, 0xf2, 0x79, 0xdb, +      0x0f, 0x8a, 0xcd, 0x5b, 0xf1, 0x7b, 0xdc, 0x74, +      0x18, 0xe4, 0x29, 0xb7, 0x1a, 0x0a, 0x21, 0xb7, +      0xed, 0xe8, 0x54, 0x64, 0xcf, 0x69, 0x44, 0x63, +      0xff, 0x0e, 0x56, 0xf2, 0x8f, 0x04, 0xbf, 0x85, +      0xc0, 0x85, 0xe1, 0x17, 0x6a, 0x47, 0xd7, 0x3b, +      0xf2, 0x8b, 0xdb, 0xa0, 0x4f, 0x4a, 0xe7, 0x61,  +    }, +  }}; + +  for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { +    uint8_t got[64] = { 0 }; +    sha3_512(tests[i].msg, tests[i].len, got); +    if (memcmp(got, tests[i].exp, sizeof(got))) { +      fprintf(stderr, "test_sha3_512(\"%s\") failed, got:\n", tests[i].name); +      dump_hex(stderr, got, 64); + +      fprintf(stderr, "exp:\n"); +      dump_hex(stderr, tests[i].exp, 64); +    } +  } +} + +static void test_shake128(void) { +  static const struct { +    const char *name; // test name +    const uint8_t msg[256]; // test message +    const size_t len; // test message length +    const uint8_t exp[16]; // expected hash +  } tests[] = {{ +    .name = "empty", +    .msg = "", +    .len = 0, +    .exp = { +      0x7f, 0x9c, 0x2b, 0xa4, 0xe8, 0x8f, 0x82, 0x7d, +      0x61, 0x60, 0x45, 0x50, 0x76, 0x05, 0x85, 0x3e,  +    }, +  }, { +    .name = "asdf", +    .msg = "asdf", +    .len = 4, +    .exp = { +      0xef, 0x02, 0x2c, 0xc5, 0x3c, 0x74, 0xb3, 0x28, +      0x43, 0xf9, 0xc1, 0xf1, 0x14, 0x13, 0xd5, 0x9c,  +    }, +  }, { +    .name = "a-134", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 134, +    .exp = { +      0xc8, 0x73, 0x5e, 0x5f, 0x6f, 0x15, 0xaf, 0xe5, +      0x1a, 0x8c, 0x3b, 0x07, 0xc4, 0xc6, 0x8d, 0x86,  +    }, +  }, { +    .name = "a-135", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 135, +    .exp = { +      0xa5, 0xe2, 0xb2, 0x27, 0x8d, 0x1b, 0x75, 0x86, +      0x6c, 0x78, 0x77, 0xa0, 0xff, 0xa2, 0x47, 0x37,  +    }, +  }, { +    .name = "a-136", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 136, +    .exp = { +      0x0d, 0x01, 0x58, 0xd4, 0x46, 0x78, 0x3a, 0x9b, +      0x18, 0xa6, 0x90, 0x8c, 0x08, 0xbb, 0x5d, 0xe6,  +    }, +  }, { +    .name = "ff-256", +    .msg = { +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +    }, +    .len = 256, +    .exp = { +      0xf3, 0x06, 0x93, 0x04, 0x16, 0x5c, 0x0e, 0xad, +      0x13, 0x25, 0xb5, 0x26, 0x76, 0x05, 0x95, 0xed,  +    }, +  }, { +    .name = "a-210", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 210, +    .exp = { +      0xb1, 0xb4, 0xf3, 0xad, 0x3a, 0x1f, 0x67, 0x60, +      0xe3, 0x08, 0x67, 0xdd, 0x71, 0xb3, 0x49, 0xfa,  +    }, +  }}; + +  for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { +    uint8_t got[16] = { 0 }; +    shake128(tests[i].msg, tests[i].len, got); +    if (memcmp(got, tests[i].exp, sizeof(got))) { +      fprintf(stderr, "test_shake128(\"%s\") failed, got:\n", tests[i].name); +      dump_hex(stderr, got, 16); + +      fprintf(stderr, "exp:\n"); +      dump_hex(stderr, tests[i].exp, 16); +    } +  } +} + +static void test_shake256(void) { +  static const struct { +    const char *name; // test name +    const uint8_t msg[256]; // test message +    const size_t len; // test message length +    const uint8_t exp[32]; // expected hash +  } tests[] = {{ +    .name = "empty", +    .msg = "", +    .len = 0, +    .exp = { +      0x46, 0xb9, 0xdd, 0x2b, 0x0b, 0xa8, 0x8d, 0x13, +      0x23, 0x3b, 0x3f, 0xeb, 0x74, 0x3e, 0xeb, 0x24, +      0x3f, 0xcd, 0x52, 0xea, 0x62, 0xb8, 0x1b, 0x82, +      0xb5, 0x0c, 0x27, 0x64, 0x6e, 0xd5, 0x76, 0x2f,  +    }, +  }, { +    .name = "asdf", +    .msg = "asdf", +    .len = 4, +    .exp = { +      0xf0, 0x0c, 0x15, 0x64, 0x33, 0x96, 0x61, 0x6a, +      0x89, 0xa0, 0xcb, 0x79, 0x03, 0x9f, 0x74, 0x05, +      0x75, 0xde, 0xfe, 0x9d, 0xbe, 0x30, 0x7c, 0xcc, +      0xda, 0xf8, 0xae, 0x21, 0x0e, 0x1c, 0x9c, 0xc6,  +    }, +  }, { +    .name = "a-134", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 134, +    .exp = { +      0xf1, 0xe0, 0x3f, 0x37, 0x8e, 0xb7, 0x79, 0x04, +      0xba, 0x15, 0xbb, 0x64, 0x2a, 0x84, 0xb9, 0x0d, +      0xe5, 0x2e, 0x29, 0x3e, 0xaf, 0xc2, 0x7c, 0xef, +      0x05, 0x88, 0x3b, 0x16, 0x56, 0xae, 0xc3, 0x41,  +    }, +  }, { +    .name = "a-135", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 135, +    .exp = { +      0x55, 0xb9, 0x91, 0xec, 0xe1, 0xe5, 0x67, 0xb6, +      0xe7, 0xc2, 0xc7, 0x14, 0x44, 0x4d, 0xd2, 0x01, +      0xcd, 0x51, 0xf4, 0xf3, 0x83, 0x2d, 0x08, 0xe1, +      0xd2, 0x6b, 0xeb, 0xc6, 0x3e, 0x07, 0xa3, 0xd7,  +    }, +  }, { +    .name = "a-136", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 136, +    .exp = { +      0x8f, 0xcc, 0x5a, 0x08, 0xf0, 0xa1, 0xf6, 0x82, +      0x7c, 0x9c, 0xf6, 0x4e, 0xe8, 0xd1, 0x6e, 0x04, +      0x43, 0x10, 0x63, 0x59, 0xca, 0x6c, 0x8e, 0xfd, +      0x23, 0x07, 0x59, 0x25, 0x6f, 0x44, 0x99, 0x6a,  +    }, +  }, { +    .name = "ff-256", +    .msg = { +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +    }, +    .len = 256, +    .exp = { +      0x3f, 0x25, 0xdf, 0x0e, 0x37, 0x17, 0x14, 0xdf, +      0xb0, 0xcc, 0x3d, 0x96, 0x17, 0xe1, 0xa0, 0x71, +      0x75, 0xa0, 0xf0, 0x84, 0xc7, 0x00, 0x29, 0x23, +      0x5c, 0x72, 0x7c, 0x5a, 0x68, 0x5e, 0xf0, 0x14,  +    }, +  }, { +    .name = "a-210", +    .msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +    .len = 210, +    .exp = { +      0xc9, 0xe2, 0xd9, 0x58, 0xf2, 0xdd, 0x3d, 0x97, +      0x53, 0x8a, 0x1b, 0xac, 0x1b, 0x4e, 0xb3, 0x2e, +      0x28, 0x23, 0x6b, 0x5d, 0xfc, 0xe0, 0x29, 0xfc, +      0xc8, 0x73, 0xc0, 0xf2, 0x70, 0xe1, 0x3e, 0x9f,  +    }, +  }}; + +  for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { +    uint8_t got[32] = { 0 }; +    shake256(tests[i].msg, tests[i].len, got); +    if (memcmp(got, tests[i].exp, sizeof(got))) { +      fprintf(stderr, "test_shake256(\"%s\") failed, got:\n", tests[i].name); +      dump_hex(stderr, got, 32); + +      fprintf(stderr, "exp:\n"); +      dump_hex(stderr, tests[i].exp, 32); +    } +  } +} + +int main(void) { +  test_theta(); +  test_rho(); +  test_pi(); +  test_chi(); +  test_iota(); +  test_permute(); +  test_sha3_224(); +  test_sha3_256(); +  test_sha3_384(); +  test_sha3_512(); +  test_shake128(); +  test_shake256(); +  printf("ok\n"); +} + +#endif /* SHA3_TEST */ @@ -0,0 +1,22 @@ +#ifndef SHA3_H +#define SHA3_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <stdint.h> + +void sha3_224(const uint8_t *m, size_t m_len, uint8_t dst[static 28]); +void sha3_256(const uint8_t *m, size_t m_len, uint8_t dst[static 32]); +void sha3_384(const uint8_t *m, size_t m_len, uint8_t dst[static 48]); +void sha3_512(const uint8_t *m, size_t m_len, uint8_t dst[static 64]); + +void shake128(const uint8_t *m, size_t m_len, uint8_t dst[static 16]); +void shake256(const uint8_t *m, size_t m_len, uint8_t dst[static 32]); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SHA3_H */ | 
