chiark / gitweb /
ec-field-test.c: Make the field-element type use internal format.
[secnet.git] / 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); }