aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile20
-rw-r--r--main.c78
-rw-r--r--sha3.c1176
-rw-r--r--sha3.h22
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)
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..62fc21b
--- /dev/null
+++ b/main.c
@@ -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;
+}
diff --git a/sha3.c b/sha3.c
new file mode 100644
index 0000000..388bf24
--- /dev/null
+++ b/sha3.c
@@ -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 */
diff --git a/sha3.h b/sha3.h
new file mode 100644
index 0000000..6e49a40
--- /dev/null
+++ b/sha3.h
@@ -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 */