chiark / gitweb /
ec-field-test.c: Make the field-element type use internal format.
[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 { unsigned char *p; size_t sz; } bytes; /* buffer of bytes */
70     struct { char *p; size_t sz; } str; /* text string */
71 #ifdef REG_MEMBERS
72     REG_MEMBERS                         /* your members here */
73 #endif
74 };
75
76 struct reg {
77     unsigned f;                         /* flags */
78 #define REGF_LIVE 1u                    /*   input register has a value */
79     union regval v;                     /* register value */
80 };
81
82 struct regty {
83     void (*init)(union regval *v);      /* set up raw memory */
84     void (*parse)(union regval *v, char *p); /* parse text input as value */
85     void (*dump)(FILE *fp, const union regval *v); /* dump value as text */
86     int (*eq)(const union regval *v0, const union regval *v1); /* equal? */
87     void (*release)(union regval *v);   /* release any resources */
88 };
89
90 struct regdef {
91     const char *name;                   /* register name (for input files) */
92     unsigned i;                         /* register index */
93     const struct regty *ty;             /* register type descriptor */
94     unsigned f;                         /* flags */
95 #define REGF_OPT 1u                     /*   (input) register is optional */
96 };
97 #define REGLIST_END { 0 }
98
99 struct test_state {
100     struct reg *in, *out;               /* vectors of registers */
101     unsigned nrout;                     /* number of output registers */
102     unsigned nreg;                      /* total number of registers */
103     size_t regsz;                       /* size of an individual register */
104     int win, lose;                      /* number of tests passed/failed */
105 };
106
107 struct test {
108     const char *name;                   /* name of the test */
109     void (*run)(struct test_state *state, const struct test *test);
110                                         /* test runner (`run_test') */
111     const struct regdef *regs;          /* register definitions */
112     void (*fn)(struct reg *out, const struct reg *in, void *ctx);
113                                         /* test function */
114 };
115
116 /* Utility functions. */
117 extern NORETURN(bail(const char *msg, ...))
118     FORMAT(printf, 1, 2);
119 extern void parse_hex(uint8_t *b, size_t sz, char *p);
120 extern void dump_hex(FILE *fp, const uint8_t *b, size_t sz);
121 extern void trivial_regty_init(union regval *v);
122 extern void trivial_regty_release(union regval *v);
123 extern void allocate_bytes(union regval *v, size_t sz);
124 extern void allocate_string(union regval *v, size_t sz);
125
126 /* Built-in register types. */
127 extern const struct regty
128     regty_int,
129     regty_uint,
130     regty_bytes,
131     regty_string;
132
133 /* Running tests. */
134 extern void check_test_output(struct test_state *state,
135                               const struct test *test);
136 extern void run_test(struct test_state *state, const struct test *test);
137 extern int run_test_suite(unsigned nrout, unsigned nreg, size_t regsz,
138                           const struct test *tests, FILE *fp);
139
140 #endif