@@@ 64-bit kludging
[secnet] / crypto-test.h
1 /*
2 * crypto-test.h: common test vector processing
3 */
4 /*
5 * This file is Free Software. It was originally written for secnet.
6 *
7 * Copyright 2017, 2019 Mark Wooding
8 *
9 * You may redistribute secnet as a whole and/or modify it under the
10 * terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 3, or (at your option) any
12 * later version.
13 *
14 * You may redistribute this file and/or modify it under the terms of
15 * the GNU General Public License as published by the Free Software
16 * Foundation; either version 2, or (at your option) any later
17 * version.
18 *
19 * This software is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this software; if not, see
26 * https://www.gnu.org/licenses/gpl.html.
27 */
28
29 #ifndef crypto_test_h
30 #define crypto_test_h
31
32 /* Basic model.
33 *
34 * There is a collection of `registers', each of which can store a value.
35 * Some registers are designated as `input': their values are set while
36 * reading the test vector. Other registers are designated as `output': the
37 * test function is expected to calculate their values, which are then
38 * compared against final values supplied by the test vector. Any
39 * discrepancies are reported.
40 *
41 * While a test suite is running, there is a single vector of registers, and
42 * registers are identified by index, starting from zero. The number of
43 * registers, `nreg', and a threshold `nrout', are defined by the test suite:
44 * registers with index less than `nrout' are for output; other registers up
45 * to, but not including, `nreg' are for input. Finally, the test suite
46 * defines the size of a register. The common test machinery treats
47 * registers as entirely opaque, acting on them only through their defined
48 * types.
49 *
50 * Each kind of test defines a register mapping, which assigns types and
51 * (textual) names to some subset of the registers. A register can be marked
52 * optional; by default, the test vector parser will report an error if a
53 * defined register is not assigned a value.
54 *
55 * The register type is responsible for handling the register on behalf of
56 * the common code. (Test functions can have built-in knowledge of which
57 * registers have which types, and can manipulate registers directly, of
58 * course.)
59 *
60 * Finally, each test defines a test runner, which is responsible for
61 * invoking the test function and checking that the output registers are
62 * correct. There is a generic test runner, but some tests might benefit
63 * from special arrangements.
64 */
65
66 union regval {
67 long i; /* signed integer */
68 unsigned long u; /* unsigned integer */
69 struct { void *p; size_t sz; } bytes; /* buffer of bytes */
70 #ifdef REG_MEMBERS
71 REG_MEMBERS /* your members here */
72 #endif
73 };
74
75 struct reg {
76 unsigned f; /* flags */
77 #define REGF_LIVE 1u /* input register has a value */
78 union regval v; /* register value */
79 };
80
81 struct regty {
82 void (*init)(union regval *v); /* set up raw memory */
83 void (*parse)(union regval *v, char *p); /* parse text input as value */
84 void (*dump)(FILE *fp, const union regval *v); /* dump value as text */
85 int (*eq)(const union regval *v0, const union regval *v1); /* equal? */
86 void (*release)(union regval *v); /* release any resources */
87 };
88
89 struct regdef {
90 const char *name; /* register name (for input files) */
91 unsigned i; /* register index */
92 const struct regty *ty; /* register type descriptor */
93 unsigned f; /* flags */
94 #define REGF_OPT 1u /* (input) register is optional */
95 };
96 #define REGLIST_END { 0 }
97
98 struct test_state {
99 struct reg *in, *out; /* vectors of registers */
100 unsigned nrout; /* number of output registers */
101 unsigned nreg; /* total number of registers */
102 size_t regsz; /* size of an individual register */
103 int win, lose; /* number of tests passed/failed */
104 };
105
106 struct test {
107 const char *name; /* name of the test */
108 void (*run)(struct test_state *state, const struct test *test);
109 /* test runner (`run_test') */
110 const struct regdef *regs; /* register definitions */
111 void (*fn)(struct reg *out, const struct reg *in, void *ctx);
112 /* test function */
113 };
114
115 /* Utility functions. */
116 extern NORETURN(bail(const char *msg, ...))
117 FORMAT(printf, 1, 2);
118 extern void parse_hex(uint8_t *b, size_t sz, char *p);
119 extern void dump_hex(FILE *fp, const uint8_t *b, size_t sz);
120 extern void trivial_regty_init(union regval *v);
121 extern void trivial_regty_release(union regval *v);
122 extern void allocate_bytes(union regval *v, size_t sz);
123
124 /* Built-in register types. */
125 extern const struct regty
126 regty_int,
127 regty_uint,
128 regty_bytes;
129
130 /* Running tests. */
131 extern void check_test_output(struct test_state *state,
132 const struct test *test);
133 extern void run_test(struct test_state *state, const struct test *test);
134 extern int run_test_suite(unsigned nrout, unsigned nreg, size_t regsz,
135 const struct test *tests, FILE *fp);
136
137 #endif