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