From 5bf585d21927a684ae9c16eb2a28cd786cec433c Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Thu, 26 Sep 2019 04:46:03 +0100 Subject: [PATCH] @@@ test keccak and sha3 --- Makefile.in | 18 +++++- keccak1600-test.c | 72 +++++++++++++++++++++ sha3-test.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 keccak1600-test.c create mode 100644 sha3-test.c diff --git a/Makefile.in b/Makefile.in index 4ec557f..7df4bf6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 index 0000000..e0102ac --- /dev/null +++ b/keccak1600-test.c @@ -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 + +#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); } diff --git a/sha3-test.c b/sha3-test.c new file mode 100644 index 0000000..81d7610 --- /dev/null +++ b/sha3-test.c @@ -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 + +#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); } -- 2.11.0