@@@ test keccak and sha3
[secnet] / sha3-test.c
1 /*
2 * sha3-test.c: test harness for SHA3 and related functions
3 *
4 * (The implementations originally came with different test arrangements,
5 * with complicated external dependencies. This file replicates the original
6 * tests, but without the dependencies.)
7 */
8 /*
9 * This file is Free Software. It was originally written for secnet.
10 *
11 * Copyright 2019 Mark Wooding
12 *
13 * You may redistribute secnet as a whole and/or modify it under the
14 * terms of the GNU General Public License as published by the Free
15 * Software Foundation; either version 3, or (at your option) any
16 * later version.
17 *
18 * You may redistribute this file and/or modify it under the terms of
19 * the GNU General Public License as published by the Free Software
20 * Foundation; either version 2, or (at your option) any later
21 * version.
22 *
23 * This software is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this software; if not, see
30 * https://www.gnu.org/licenses/gpl.html.
31 */
32
33 #include <stdio.h>
34
35 #include "secnet.h"
36
37 #include "keccak1600.h"
38 #include "sha3.h"
39 #include "crypto-test.h"
40
41 enum {
42 RH, NROUT,
43 RM = NROUT, RN, RFUNC, RPERSO, NREG
44 };
45
46 struct test_context {
47 size_t step;
48 size_t outsz;
49 };
50
51 static void run_sha3_kat(struct test_state *state, const struct test *test)
52 {
53 static const unsigned steps[] = { 1, 7, 192, -1 };
54 unsigned i = 0;
55 struct test_context ctx;
56
57 ctx.outsz = state->in[RH].v.bytes.sz;
58 do {
59 ctx.step = steps[i];
60 test->fn(state->out, state->in, &ctx);
61 check_test_output(state, test);
62 } while (steps[i++] != (unsigned)-1);
63 }
64
65 #define SHA3_VARIANTS(_) _(224) _(256) _(384) _(512)
66
67 #define SHA3_TESTFUNCS(w) \
68 \
69 static void test_sha3_##w##_kat(struct reg *out, \
70 const struct reg *in, void *vctx) \
71 { \
72 struct test_context *ctx = vctx; \
73 sha3_ctx hctx; \
74 const octet *p = in[RM].v.bytes.p; \
75 size_t sz = in[RM].v.bytes.sz, n; \
76 \
77 allocate_bytes(&out[RH].v, SHA3_##w##_HASHSZ); \
78 sha3_##w##_init(&hctx); \
79 while (sz) { \
80 n = ctx->step; if (n > sz) n = sz; \
81 sha3_hash(&hctx, p, n); p += n; sz -= n; \
82 } \
83 sha3_done(&hctx, out[RH].v.bytes.p); \
84 } \
85 \
86 static void test_sha3_##w##_mct(struct reg *out, \
87 const struct reg *in, void *vctx) \
88 { \
89 sha3_ctx hctx; \
90 octet *p; \
91 unsigned i, n = in[RN].v.u; \
92 \
93 allocate_bytes(&out[RH].v, SHA3_##w##_HASHSZ); \
94 p = out[RH].v.bytes.p; \
95 memcpy(p, in[RM].v.bytes.p, SHA3_##w##_HASHSZ); \
96 for (i = 0; i < n; i++) { \
97 sha3_##w##_init(&hctx); \
98 sha3_hash(&hctx, p, SHA3_##w##_HASHSZ); \
99 sha3_done(&hctx, p); \
100 } \
101 }
102
103 SHA3_VARIANTS(SHA3_TESTFUNCS)
104
105 #define SHAKE_VARIANTS(_) _(128) _(256)
106
107 #define SHAKE_TESTFUNCS(w) \
108 \
109 static void test_shake##w##_kat(struct reg *out, \
110 const struct reg *in, void *vctx) \
111 { \
112 struct test_context *ctx = vctx; \
113 shake_ctx hctx; \
114 const octet *p = in[RM].v.bytes.p; octet *q; \
115 size_t sz = in[RM].v.bytes.sz, n; \
116 \
117 allocate_bytes(&out[RH].v, ctx->outsz); \
118 shake##w##_init(&hctx); \
119 while (sz) { \
120 n = ctx->step; if (n > sz) n = sz; \
121 shake_hash(&hctx, p, n); p += n; sz -= n; \
122 } \
123 shake_xof(&hctx); \
124 q = out[RH].v.bytes.p; sz = ctx->outsz; \
125 while (sz) { \
126 n = ctx->step; if (n > sz) n = sz; \
127 shake_get(&hctx, q, n); q += n; sz -= n; \
128 } \
129 } \
130 \
131 static void test_cshake##w##_kat(struct reg *out, \
132 const struct reg *in, void *vctx) \
133 { \
134 struct test_context *ctx = vctx; \
135 shake_ctx hctx; \
136 const octet *p = in[RM].v.bytes.p; octet *q; \
137 size_t sz = in[RM].v.bytes.sz, n; \
138 \
139 allocate_bytes(&out[RH].v, ctx->outsz); \
140 cshake##w##_init(&hctx, \
141 in[RFUNC].v.str.p, in[RFUNC].v.str.sz, \
142 in[RPERSO].v.str.p, in[RPERSO].v.str.sz); \
143 while (sz) { \
144 n = ctx->step; if (n > sz) n = sz; \
145 shake_hash(&hctx, p, n); p += n; sz -= n; \
146 } \
147 shake_xof(&hctx); \
148 q = out[RH].v.bytes.p; sz = ctx->outsz; \
149 while (sz) { \
150 n = ctx->step; if (n > sz) n = sz; \
151 shake_get(&hctx, q, n); q += n; sz -= n; \
152 } \
153 }
154
155 SHAKE_VARIANTS(SHAKE_TESTFUNCS)
156
157 #define REG_M { "m", RM, &regty_bytes, 0 }
158 #define REG_N { "n", RN, &regty_uint, 0 }
159 #define REG_FUNC { "func", RFUNC, &regty_string, 0 }
160 #define REG_PERSO { "perso", RPERSO, &regty_string, 0 }
161 #define REG_H { "h", RH, &regty_bytes, 0 }
162 static const struct regdef
163 hash_kat_regs[] = { REG_M, REG_H, REGLIST_END },
164 hash_mct_regs[] = { REG_M, REG_N, REG_H, REGLIST_END },
165 cshake_regs[] = { REG_M, REG_FUNC, REG_PERSO, REG_H, REGLIST_END };
166
167 #define SHA3_TESTDEFS(w) \
168 { "sha3-" #w "-hex", run_sha3_kat, \
169 hash_kat_regs, test_sha3_##w##_kat }, \
170 { "sha3-" #w "-mct", run_test, \
171 hash_mct_regs, test_sha3_##w##_mct },
172 #define SHAKE_TESTDEFS(w) \
173 { "shake" #w, run_sha3_kat, \
174 hash_kat_regs, test_shake##w##_kat }, \
175 { "cshake" #w, run_sha3_kat, \
176 cshake_regs, test_cshake##w##_kat },
177 static const struct test tests[] = {
178 SHA3_VARIANTS(SHA3_TESTDEFS)
179 SHAKE_VARIANTS(SHAKE_TESTDEFS)
180 { 0 }
181 };
182
183 int main(void)
184 { return run_test_suite(NROUT, NREG, sizeof(struct reg), tests, stdin); }