Commit | Line | Data |
---|---|---|
5bf585d2 MW |
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, ®ty_bytes, 0 } | |
158 | #define REG_N { "n", RN, ®ty_uint, 0 } | |
159 | #define REG_FUNC { "func", RFUNC, ®ty_string, 0 } | |
160 | #define REG_PERSO { "perso", RPERSO, ®ty_string, 0 } | |
161 | #define REG_H { "h", RH, ®ty_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); } |