@@@ test keccak and sha3
authorMark Wooding <mdw@distorted.org.uk>
Thu, 26 Sep 2019 03:46:03 +0000 (04:46 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Thu, 26 Sep 2019 03:46:03 +0000 (04:46 +0100)
Makefile.in
keccak1600-test.c [new file with mode: 0644]
sha3-test.c [new file with mode: 0644]

index 4ec557f..7df4bf6 100644 (file)
@@ -63,7 +63,8 @@ OBJECTS:=secnet.o util.o conffile.yy.o conffile.tab.o conffile.o modules.o \
        comm-common.o polypath.o \
        netlink.o rsa.o dh.o xdh.o serpent.o serpentbe.o \
        scaf.o f25519.o x25519.o ed25519.o fgoldi.o x448.o \
-       md5.o sha512.o tun.o slip.o sha1.o ipaddr.o log.o \
+       md5.o sha512.o keccak1600.o sha3.o \
+       tun.o slip.o sha1.o ipaddr.o log.o \
        process.o @LIBOBJS@ \
        hackypar.o
 # version.o is handled specially below and in the link rule for secnet.
@@ -147,6 +148,7 @@ endif
 check: eax-aes-test.confirm eax-serpent-test.confirm \
        eax-serpentbe-test.confirm check-ipaddrset \
        msgcode-test.confirm \
+       keccak1600-test.confirm sha3-test.confirm \
        f25519-test.confirm x25519-test.confirm ed25519-test.confirm \
        fgoldi-test.confirm x448-test.confirm
 
@@ -175,6 +177,20 @@ msgcode-test.confirm: msgcode-test
        ./msgcode-test
        touch $@
 
+keccak1600-test: keccak1600-test.o keccak1600.o crypto-test.o
+       $(CC) $(LDFLAGS) $(ALL_CFLAGS) -o $@ $^
+
+keccak1600-test.confirm: keccak1600-test keccak1600-tests.in
+       ./keccak1600-test <$(srcdir)/keccak1600-tests.in
+       touch $@
+
+sha3-test: sha3-test.o sha3.o keccak1600.o crypto-test.o
+       $(CC) $(LDFLAGS) $(ALL_CFLAGS) -o $@ $^
+
+sha3-test.confirm: sha3-test sha3-tests.in
+       ./sha3-test <$(srcdir)/sha3-tests.in
+       touch $@
+
 XDH_FUNCS = x25519 x448
 x25519_FIELD = f25519
 x448_FIELD = fgoldi
diff --git a/keccak1600-test.c b/keccak1600-test.c
new file mode 100644 (file)
index 0000000..e0102ac
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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, &regty_bytes, 0 }
+#define REG_N { "n", RN, &regty_uint, 0 }
+#define REG_Z { "z", RZ, &regty_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); }
diff --git a/sha3-test.c b/sha3-test.c
new file mode 100644 (file)
index 0000000..81d7610
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * 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, &regty_bytes, 0 }
+#define REG_N { "n", RN, &regty_uint, 0 }
+#define REG_FUNC { "func", RFUNC, &regty_string, 0 }
+#define REG_PERSO { "perso", RPERSO, &regty_string, 0 }
+#define REG_H { "h", RH, &regty_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); }