3 * $Id: ec-test.c,v 1.5 2004/04/02 01:03:49 mdw Exp $
5 * Code for testing elliptic-curve stuff
7 * (c) 2004 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
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.
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.
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,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.5 2004/04/02 01:03:49 mdw
34 * Miscellaneous constification.
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.)
43 * Revision 1.3 2004/03/27 17:54:11 mdw
44 * Standard curves and curve checking.
46 * Revision 1.2 2004/03/27 00:04:46 mdw
47 * Implement efficient reduction for pleasant-looking primes.
49 * Revision 1.1 2004/03/23 15:19:32 mdw
50 * Test elliptic curves more thoroughly.
54 /*----- Header files ------------------------------------------------------*/
62 #include <mLib/alloc.h>
63 #include <mLib/testrig.h>
69 /*----- Cardboard cut-out elliptic curve ----------------------------------*/
71 typedef struct ecctx
{
78 #define MAGIC 0x3a1f0b07
80 static void ecDESTROY(ec_curve
*cc
)
82 ecctx
*c
= (ecctx
*)cc
;
84 ec_destroycurve(c
->real
);
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)); \
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)); \
111 static ec
*ecFIND(ec_curve
*cc
, ec
*d
, mp
*x
)
113 ecctx
*c
= (ecctx
*)cc
;
114 return (EC_FIND(c
->real
, d
, x
));
117 static int ecCHECK(ec_curve
*cc
, const ec
*p
)
119 ecctx
*c
= (ecctx
*)cc
;
120 return (EC_CHECK(c
->real
, p
));
123 static int ecSAMEP(ec_curve
*cc
, ec_curve
*dd
)
125 ecctx
*c
= (ecctx
*)cc
, *d
= (ecctx
*)dd
;
126 return (ec_samep(c
->real
, d
->real
));
129 static const ec_ops ecops
= {
130 ecDESTROY
, ecSAMEP
, ecIN
, ecOUT
, ecFIX
,
131 ecFIND
, ecNEG
, ecADD
, ecSUB
, ecDBL
, ecCHECK
134 static ec_curve
*ec_cutout(ec_curve
*real
, const char *name
)
136 ecctx
*c
= CREATE(ecctx
);
142 c
->name
= xstrdup(name
);
147 static const char *ec_name(ec_curve
*cc
)
149 ecctx
*c
= (ecctx
*)cc
;
150 assert(c
->magic
== MAGIC
);
154 /*----- Test field types --------------------------------------------------*/
156 static void ecvcvt(const char *buf
, dstr
*d
)
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
);
168 dstr_ensure(d
, sizeof(v
));
169 *(ec_curve
**)d
->buf
= ec_cutout(v
, buf
);
173 static void ecvdump(dstr
*d
, FILE *fp
)
175 ec_curve
*v
= *(ec_curve
**)d
->buf
;
176 fprintf(fp
, "%s", ec_name(v
));
179 const test_type type_ecurve
= { ecvcvt
, ecvdump
};
181 static void eccvt(const char *p
, dstr
*d
)
188 dstr_ensure(d
, sizeof(ec
));
190 d
->len
+= sizeof(ec
);
192 if (!ec_ptparse(&qd
, a
)) {
193 fprintf(stderr
, "bad point `%.*s|%s': %s\n", qd
.p
- p
, p
, qd
.p
, qd
.e
);
198 static void ecdodump(ec
*a
, FILE *fp
)
204 mp_writefile(a
->x
, fp
, 16);
206 mp_writefile(a
->y
, fp
, 16);
210 static void ecdump(dstr
*d
, FILE *fp
)
212 ec
*a
= (ec
*)d
->buf
;
216 test_type type_ec
= { eccvt
, ecdump
};
218 /*----- Testing elliptic curve functionality ------------------------------*/
222 static void ecdestroy(ec_curve
*c
)
230 static int v##op(dstr v[]) \
232 ec_curve *e = *(ec_curve **)v[0].buf; \
233 ec *a = (ec *)v[1].buf; \
234 ec *r = (ec *)v[2].buf; \
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"); \
247 EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); \
253 static int v##op(dstr v[]) \
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; \
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"); \
272 EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c); \
282 static int vcheck(dstr v
[])
284 ec_curve
*e
= *(ec_curve
**)v
[0].buf
;
285 ec
*a
= (ec
*)v
[1].buf
;
286 int r
= *(int *)v
[2].buf
;
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");
304 static int vmul(dstr v
[])
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
;
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");
323 EC_DESTROY(a
); EC_DESTROY(r
); EC_DESTROY(&c
); MP_DROP(n
);
328 static int vfind(dstr v
[])
330 ec_curve
*e
= *(ec_curve
**)v
[0].buf
;
331 mp
*x
= *(mp
**)v
[1].buf
;
332 ec
*r
= (ec
*)v
[2].buf
;
335 if (!ec_find(e
, &c
, x
)) EC_SETINF(&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");
345 MP_DROP(x
); EC_DESTROY(r
); EC_DESTROY(&c
);
350 static 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
} },
361 int main(int argc
, char *argv
[])
364 test_run(argc
, argv
, tests
, SRCDIR
"/tests/ec");
370 /*----- That's all, folks -------------------------------------------------*/