--- /dev/null
+/*
+ * keccak1600-test.c: test harness for Keccak primitive
+ *
+ * (The implementations originally came with different test arrangements,
+ * with complicated external dependencies. This file replicates the original
+ * tests, but without the dependencies.)
+ */
+/*
+ * This file is Free Software. It was originally written for secnet.
+ *
+ * Copyright 2019 Mark Wooding
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+
+#include <stdio.h>
+
+#include "secnet.h"
+
+#include "keccak1600.h"
+#include "crypto-test.h"
+
+enum {
+ RZ, NROUT,
+ RX = NROUT, RN, NREG
+};
+
+static void test_p(struct reg *out, const struct reg *in, void *ctx)
+{
+ keccak1600_state u;
+ kludge64 t[25];
+ unsigned i;
+
+ allocate_bytes(&out[RZ].v, 200);
+ keccak1600_init(&u);
+ for (i = 0; i < 25; i++) LOAD64_L_(t[i], in[RX].v.bytes.p + 8*i);
+ keccak1600_mix(&u, t, 25);
+ keccak1600_p(&u, &u, in[RN].v.u);
+ keccak1600_extract(&u, t, 25);
+ for (i = 0; i < 25; i++) STORE64_L_(out[RZ].v.bytes.p + 8*i, t[i]);
+}
+
+#define REG_X { "x", RX, ®ty_bytes, 0 }
+#define REG_N { "n", RN, ®ty_uint, 0 }
+#define REG_Z { "z", RZ, ®ty_bytes, 0 }
+static const struct regdef
+ p_regs[] = { REG_X, REG_N, REG_Z, REGLIST_END };
+
+static const struct test tests[] = {
+ { "p", run_test, p_regs, test_p },
+ { 0 }
+};
+
+int main(void)
+ { return run_test_suite(NROUT, NREG, sizeof(struct reg), tests, stdin); }
--- /dev/null
+/*
+ * sha3-test.c: test harness for SHA3 and related functions
+ *
+ * (The implementations originally came with different test arrangements,
+ * with complicated external dependencies. This file replicates the original
+ * tests, but without the dependencies.)
+ */
+/*
+ * This file is Free Software. It was originally written for secnet.
+ *
+ * Copyright 2019 Mark Wooding
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+
+#include <stdio.h>
+
+#include "secnet.h"
+
+#include "keccak1600.h"
+#include "sha3.h"
+#include "crypto-test.h"
+
+enum {
+ RH, NROUT,
+ RM = NROUT, RN, RFUNC, RPERSO, NREG
+};
+
+struct test_context {
+ size_t step;
+ size_t outsz;
+};
+
+static void run_sha3_kat(struct test_state *state, const struct test *test)
+{
+ static const unsigned steps[] = { 1, 7, 192, -1 };
+ unsigned i = 0;
+ struct test_context ctx;
+
+ ctx.outsz = state->in[RH].v.bytes.sz;
+ do {
+ ctx.step = steps[i];
+ test->fn(state->out, state->in, &ctx);
+ check_test_output(state, test);
+ } while (steps[i++] != (unsigned)-1);
+}
+
+#define SHA3_VARIANTS(_) _(224) _(256) _(384) _(512)
+
+#define SHA3_TESTFUNCS(w) \
+ \
+static void test_sha3_##w##_kat(struct reg *out, \
+ const struct reg *in, void *vctx) \
+{ \
+ struct test_context *ctx = vctx; \
+ sha3_ctx hctx; \
+ const octet *p = in[RM].v.bytes.p; \
+ size_t sz = in[RM].v.bytes.sz, n; \
+ \
+ allocate_bytes(&out[RH].v, SHA3_##w##_HASHSZ); \
+ sha3_##w##_init(&hctx); \
+ while (sz) { \
+ n = ctx->step; if (n > sz) n = sz; \
+ sha3_hash(&hctx, p, n); p += n; sz -= n; \
+ } \
+ sha3_done(&hctx, out[RH].v.bytes.p); \
+} \
+ \
+static void test_sha3_##w##_mct(struct reg *out, \
+ const struct reg *in, void *vctx) \
+{ \
+ sha3_ctx hctx; \
+ octet *p; \
+ unsigned i, n = in[RN].v.u; \
+ \
+ allocate_bytes(&out[RH].v, SHA3_##w##_HASHSZ); \
+ p = out[RH].v.bytes.p; \
+ memcpy(p, in[RM].v.bytes.p, SHA3_##w##_HASHSZ); \
+ for (i = 0; i < n; i++) { \
+ sha3_##w##_init(&hctx); \
+ sha3_hash(&hctx, p, SHA3_##w##_HASHSZ); \
+ sha3_done(&hctx, p); \
+ } \
+}
+
+SHA3_VARIANTS(SHA3_TESTFUNCS)
+
+#define SHAKE_VARIANTS(_) _(128) _(256)
+
+#define SHAKE_TESTFUNCS(w) \
+ \
+static void test_shake##w##_kat(struct reg *out, \
+ const struct reg *in, void *vctx) \
+{ \
+ struct test_context *ctx = vctx; \
+ shake_ctx hctx; \
+ const octet *p = in[RM].v.bytes.p; octet *q; \
+ size_t sz = in[RM].v.bytes.sz, n; \
+ \
+ allocate_bytes(&out[RH].v, ctx->outsz); \
+ shake##w##_init(&hctx); \
+ while (sz) { \
+ n = ctx->step; if (n > sz) n = sz; \
+ shake_hash(&hctx, p, n); p += n; sz -= n; \
+ } \
+ shake_xof(&hctx); \
+ q = out[RH].v.bytes.p; sz = ctx->outsz; \
+ while (sz) { \
+ n = ctx->step; if (n > sz) n = sz; \
+ shake_get(&hctx, q, n); q += n; sz -= n; \
+ } \
+} \
+ \
+static void test_cshake##w##_kat(struct reg *out, \
+ const struct reg *in, void *vctx) \
+{ \
+ struct test_context *ctx = vctx; \
+ shake_ctx hctx; \
+ const octet *p = in[RM].v.bytes.p; octet *q; \
+ size_t sz = in[RM].v.bytes.sz, n; \
+ \
+ allocate_bytes(&out[RH].v, ctx->outsz); \
+ cshake##w##_init(&hctx, \
+ in[RFUNC].v.str.p, in[RFUNC].v.str.sz, \
+ in[RPERSO].v.str.p, in[RPERSO].v.str.sz); \
+ while (sz) { \
+ n = ctx->step; if (n > sz) n = sz; \
+ shake_hash(&hctx, p, n); p += n; sz -= n; \
+ } \
+ shake_xof(&hctx); \
+ q = out[RH].v.bytes.p; sz = ctx->outsz; \
+ while (sz) { \
+ n = ctx->step; if (n > sz) n = sz; \
+ shake_get(&hctx, q, n); q += n; sz -= n; \
+ } \
+}
+
+SHAKE_VARIANTS(SHAKE_TESTFUNCS)
+
+#define REG_M { "m", RM, ®ty_bytes, 0 }
+#define REG_N { "n", RN, ®ty_uint, 0 }
+#define REG_FUNC { "func", RFUNC, ®ty_string, 0 }
+#define REG_PERSO { "perso", RPERSO, ®ty_string, 0 }
+#define REG_H { "h", RH, ®ty_bytes, 0 }
+static const struct regdef
+ hash_kat_regs[] = { REG_M, REG_H, REGLIST_END },
+ hash_mct_regs[] = { REG_M, REG_N, REG_H, REGLIST_END },
+ cshake_regs[] = { REG_M, REG_FUNC, REG_PERSO, REG_H, REGLIST_END };
+
+#define SHA3_TESTDEFS(w) \
+ { "sha3-" #w "-hex", run_sha3_kat, \
+ hash_kat_regs, test_sha3_##w##_kat }, \
+ { "sha3-" #w "-mct", run_test, \
+ hash_mct_regs, test_sha3_##w##_mct },
+#define SHAKE_TESTDEFS(w) \
+ { "shake" #w, run_sha3_kat, \
+ hash_kat_regs, test_shake##w##_kat }, \
+ { "cshake" #w, run_sha3_kat, \
+ cshake_regs, test_cshake##w##_kat },
+static const struct test tests[] = {
+ SHA3_VARIANTS(SHA3_TESTDEFS)
+ SHAKE_VARIANTS(SHAKE_TESTDEFS)
+ { 0 }
+};
+
+int main(void)
+ { return run_test_suite(NROUT, NREG, sizeof(struct reg), tests, stdin); }