From c7f630ed23144939a540219787c7be3ffe14b24c Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Fri, 1 Sep 2023 16:45:37 -0400 Subject: initial commit --- .gitignore | 3 + Makefile | 20 ++ main.c | 78 ++++ sha3.c | 1176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sha3.h | 22 ++ 5 files changed, 1299 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 main.c create mode 100644 sha3.c create mode 100644 sha3.h 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 +#include +#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 \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 // uint64_t +#include // 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 // 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 + +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 */ -- cgit v1.2.3