pixie.c: Use `socklen_t' rather than `size_t'.
[u/mdw/catacomb] / math / ec-test.c
CommitLineData
bc985cef 1/* -*-c-*-
2 *
bc985cef 3 * Code for testing elliptic-curve stuff
4 *
5 * (c) 2004 Straylight/Edgeware
6 */
7
45c0fd36 8/*----- Licensing notice --------------------------------------------------*
bc985cef 9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
45c0fd36 16 *
bc985cef 17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
45c0fd36 21 *
bc985cef 22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
bc985cef 28/*----- Header files ------------------------------------------------------*/
29
30#include <assert.h>
31#include <ctype.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include <mLib/alloc.h>
37#include <mLib/testrig.h>
38#include <mLib/sub.h>
39
40#include "ec.h"
41#include "ec-test.h"
42
43/*----- Cardboard cut-out elliptic curve ----------------------------------*/
44
45typedef struct ecctx {
46 ec_curve c;
47 unsigned long magic;
48 char *name;
49 ec_curve *real;
50} ecctx;
51
52#define MAGIC 0x3a1f0b07
53
54static void ecDESTROY(ec_curve *cc)
55{
56 ecctx *c = (ecctx *)cc;
57 xfree(c->name);
58 ec_destroycurve(c->real);
59 DESTROY(c);
60}
61
62#define UNOP(OP) \
63 static ec *ec##OP(ec_curve *cc, ec *d, const ec *p) { \
64 ecctx *c = (ecctx *)cc; \
65 return (EC_##OP(c->real, d, p)); \
66 }
67
68#define BINOP(OP) \
69 static ec *ec##OP(ec_curve *cc, ec *d, const ec *p, const ec *q) { \
70 ecctx *c = (ecctx *)cc; \
71 return (EC_##OP(c->real, d, p, q)); \
72 }
73
74UNOP(IN)
75UNOP(OUT)
76UNOP(FIX)
77UNOP(NEG)
78UNOP(DBL)
79BINOP(ADD)
80BINOP(SUB)
81
82#undef UNOP
83#undef BINOP
84
85static ec *ecFIND(ec_curve *cc, ec *d, mp *x)
86{
87 ecctx *c = (ecctx *)cc;
88 return (EC_FIND(c->real, d, x));
89}
90
91static int ecCHECK(ec_curve *cc, const ec *p)
92{
93 ecctx *c = (ecctx *)cc;
94 return (EC_CHECK(c->real, p));
95}
96
34e4f738 97static int ecSAMEP(ec_curve *cc, ec_curve *dd)
98{
99 ecctx *c = (ecctx *)cc, *d = (ecctx *)dd;
100 return (ec_samep(c->real, d->real));
101}
102
4e66da02 103static const ec_ops ecops = {
f94b972d 104 "cardboard",
34e4f738 105 ecDESTROY, ecSAMEP, ecIN, ecOUT, ecFIX,
bc985cef 106 ecFIND, ecNEG, ecADD, ecSUB, ecDBL, ecCHECK
107};
108
109static ec_curve *ec_cutout(ec_curve *real, const char *name)
110{
111 ecctx *c = CREATE(ecctx);
112 c->c.f = real->f;
113 c->c.ops = &ecops;
34e4f738 114 c->c.a = real->a;
115 c->c.b = real->b;
bc985cef 116 c->magic = MAGIC;
117 c->name = xstrdup(name);
118 c->real = real;
119 return (&c->c);
120}
121
122static const char *ec_name(ec_curve *cc)
123{
124 ecctx *c = (ecctx *)cc;
125 assert(c->magic == MAGIC);
126 return (c->name);
127}
128
432c4e18 129/*----- Test field types --------------------------------------------------*/
bc985cef 130
131static void ecvcvt(const char *buf, dstr *d)
132{
bc985cef 133 ec_curve *v;
432c4e18 134 qd_parse qd;
135
136 qd.p = buf;
137 qd.e = 0;
138 if ((v = ec_curveparse(&qd)) == 0) {
139 fprintf(stderr, "bad curve `%.*s|%s': %s\n",
140 qd.p - buf, buf, qd.p, qd.e);
141 exit(1);
bc985cef 142 }
bc985cef 143 dstr_ensure(d, sizeof(v));
144 *(ec_curve **)d->buf = ec_cutout(v, buf);
145 d->len += sizeof(v);
146}
147
148static void ecvdump(dstr *d, FILE *fp)
149{
150 ec_curve *v = *(ec_curve **)d->buf;
151 fprintf(fp, "%s", ec_name(v));
152}
153
4e66da02 154const test_type type_ecurve = { ecvcvt, ecvdump };
bc985cef 155
156static void eccvt(const char *p, dstr *d)
157{
158 ec *a;
432c4e18 159 qd_parse qd;
bc985cef 160
432c4e18 161 qd.p = p;
162 qd.e = 0;
bc985cef 163 dstr_ensure(d, sizeof(ec));
164 a = (ec *)d->buf;
165 d->len += sizeof(ec);
166 ec_create(a);
432c4e18 167 if (!ec_ptparse(&qd, a)) {
168 fprintf(stderr, "bad point `%.*s|%s': %s\n", qd.p - p, p, qd.p, qd.e);
169 exit(1);
170 }
bc985cef 171}
172
173static void ecdodump(ec *a, FILE *fp)
174{
175 if (EC_ATINF(a))
176 fputs("inf", fp);
177 else {
45c0fd36 178 fputs("0x", fp);
bc985cef 179 mp_writefile(a->x, fp, 16);
180 fputs(", 0x", fp);
181 mp_writefile(a->y, fp, 16);
182 }
183}
184
185static void ecdump(dstr *d, FILE *fp)
186{
187 ec *a = (ec *)d->buf;
188 ecdodump(a, fp);
189}
190
5685a696 191const test_type type_ec = { eccvt, ecdump };
bc985cef 192
193/*----- Testing elliptic curve functionality ------------------------------*/
194
195#ifdef TEST_RIG
196
197static void ecdestroy(ec_curve *c)
198{
199 field *f = c->f;
200 ec_destroycurve(c);
201 F_DESTROY(f);
202}
203
204#define UNOP(op) \
205 static int v##op(dstr v[]) \
206 { \
207 ec_curve *e = *(ec_curve **)v[0].buf; \
208 ec *a = (ec *)v[1].buf; \
209 ec *r = (ec *)v[2].buf; \
210 ec c = EC_INIT; \
211 int ok = 1; \
212 ec_##op(e, &c, a); \
213 if (!EC_EQ(r, &c)) { \
214 fprintf(stderr, #op "failed"); \
215 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \
216 fprintf(stderr, "\n a = "); ecdodump(a, stderr); \
217 fprintf(stderr, "\n r = "); ecdodump(r, stderr); \
218 fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \
219 fprintf(stderr, "\n"); \
220 ok = 0; \
221 } \
222 EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); \
223 ecdestroy(e); \
224 return (ok); \
225 }
226
227#define BINOP(op) \
228 static int v##op(dstr v[]) \
229 { \
230 ec_curve *e = *(ec_curve **)v[0].buf; \
231 ec *a = (ec *)v[1].buf; \
232 ec *b = (ec *)v[2].buf; \
233 ec *r = (ec *)v[3].buf; \
234 ec c = EC_INIT; \
235 int ok = 1; \
236 ec_##op(e, &c, a, b); \
237 if (!EC_EQ(r, &c)) { \
238 fprintf(stderr, #op "failed"); \
239 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \
240 fprintf(stderr, "\n a = "); ecdodump(a, stderr); \
241 fprintf(stderr, "\n b = "); ecdodump(b, stderr); \
242 fprintf(stderr, "\n r = "); ecdodump(r, stderr); \
243 fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \
244 fprintf(stderr, "\n"); \
245 ok = 0; \
246 } \
247 EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c); \
248 ecdestroy(e); \
249 return (ok); \
250 }
251
252UNOP(neg)
253UNOP(dbl)
254BINOP(add)
255BINOP(sub)
256
257static int vcheck(dstr v[])
258{
259 ec_curve *e = *(ec_curve **)v[0].buf;
260 ec *a = (ec *)v[1].buf;
261 int r = *(int *)v[2].buf;
262 int c;
263 int ok = 1;
264 c = ec_check(e, a);
265 if (r != c) {
266 fprintf(stderr, "check failed");
267 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
45c0fd36
MW
268 fprintf(stderr, "\n a = "); ecdodump(a, stderr);
269 fprintf(stderr, "\n r = %d", r);
270 fprintf(stderr, "\n c = %d", c);
bc985cef 271 fprintf(stderr, "\n");
272 ok = 0;
273 }
274 EC_DESTROY(a);
275 ecdestroy(e);
276 return (ok);
277}
278
279static int vmul(dstr v[])
280{
281 ec_curve *e = *(ec_curve **)v[0].buf;
282 ec *a = (ec *)v[1].buf;
283 mp *n = *(mp **)v[2].buf;
284 ec *r = (ec *)v[3].buf;
285 ec c = EC_INIT;
286 int ok = 1;
287 ec_mul(e, &c, a, n);
288 if (!EC_EQ(r, &c)) {
289 fprintf(stderr, "mul failed");
290 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
45c0fd36
MW
291 fprintf(stderr, "\n a = "); ecdodump(a, stderr);
292 fprintf(stderr, "\n n = "); mp_writefile(n, stderr, 10);
293 fprintf(stderr, "\n r = "); ecdodump(r, stderr);
294 fprintf(stderr, "\n c = "); ecdodump(&c, stderr);
bc985cef 295 fprintf(stderr, "\n");
296 ok = 0;
297 }
298 EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); MP_DROP(n);
299 ecdestroy(e);
300 return (ok);
301}
302
303static int vfind(dstr v[])
304{
305 ec_curve *e = *(ec_curve **)v[0].buf;
306 mp *x = *(mp **)v[1].buf;
307 ec *r = (ec *)v[2].buf;
308 ec c = EC_INIT;
309 int ok = 1;
310 if (!ec_find(e, &c, x)) EC_SETINF(&c);
311 if (!EC_EQ(r, &c)) {
312 fprintf(stderr, "find failed");
313 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
45c0fd36
MW
314 fprintf(stderr, "\n x = "); mp_writefile(x, stderr, 16);
315 fprintf(stderr, "\n r = "); ecdodump(r, stderr);
316 fprintf(stderr, "\n c = "); ecdodump(&c, stderr);
bc985cef 317 fprintf(stderr, "\n");
318 ok = 0;
319 }
320 MP_DROP(x); EC_DESTROY(r); EC_DESTROY(&c);
321 ecdestroy(e);
322 return (ok);
323}
324
325static test_chunk tests[] = {
326 { "neg", vneg, { &type_ecurve, &type_ec, &type_ec } },
327 { "dbl", vdbl, { &type_ecurve, &type_ec, &type_ec } },
328 { "add", vadd, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
329 { "sub", vsub, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
330 { "mul", vmul, { &type_ecurve, &type_ec, &type_mp, &type_ec } },
331 { "check", vcheck, { &type_ecurve, &type_ec, &type_int } },
332 { "find", vfind, { &type_ecurve, &type_mp, &type_ec } },
333 { 0, 0, { 0 } }
334};
335
336int main(int argc, char *argv[])
337{
338 sub_init();
0f00dc4c 339 test_run(argc, argv, tests, SRCDIR "/t/ec");
bc985cef 340 return (0);
341}
342
343#endif
344
345/*----- That's all, folks -------------------------------------------------*/