3 * Code for testing elliptic-curve stuff
5 * (c) 2004 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
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.
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.
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,
28 /*----- Header files ------------------------------------------------------*/
36 #include <mLib/alloc.h>
37 #include <mLib/testrig.h>
43 /*----- Cardboard cut-out elliptic curve ----------------------------------*/
45 typedef struct ecctx {
52 #define MAGIC 0x3a1f0b07
54 static void ecDESTROY(ec_curve *cc)
56 ecctx *c = (ecctx *)cc;
58 ec_destroycurve(c->real);
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)); \
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)); \
85 static ec *ecFIND(ec_curve *cc, ec *d, mp *x)
87 ecctx *c = (ecctx *)cc;
88 return (EC_FIND(c->real, d, x));
91 static int ecCHECK(ec_curve *cc, const ec *p)
93 ecctx *c = (ecctx *)cc;
94 return (EC_CHECK(c->real, p));
97 static int ecSAMEP(ec_curve *cc, ec_curve *dd)
99 ecctx *c = (ecctx *)cc, *d = (ecctx *)dd;
100 return (ec_samep(c->real, d->real));
103 static const ec_ops ecops = {
105 ecDESTROY, ecSAMEP, ecIN, ecOUT, ecFIX,
106 ecFIND, ecNEG, ecADD, ecSUB, ecDBL, ecCHECK
109 static ec_curve *ec_cutout(ec_curve *real, const char *name)
111 ecctx *c = CREATE(ecctx);
117 c->name = xstrdup(name);
122 static const char *ec_name(ec_curve *cc)
124 ecctx *c = (ecctx *)cc;
125 assert(c->magic == MAGIC);
129 /*----- Test field types --------------------------------------------------*/
131 static void ecvcvt(const char *buf, dstr *d)
138 if ((v = ec_curveparse(&qd)) == 0) {
139 fprintf(stderr, "bad curve `%.*s|%s': %s\n",
140 (int)(qd.p - buf), buf, qd.p, qd.e);
143 dstr_ensure(d, sizeof(v));
144 *(ec_curve **)d->buf = ec_cutout(v, buf);
148 static void ecvdump(dstr *d, FILE *fp)
150 ec_curve *v = *(ec_curve **)d->buf;
151 fprintf(fp, "%s", ec_name(v));
154 const test_type type_ecurve = { ecvcvt, ecvdump };
156 static void eccvt(const char *p, dstr *d)
163 dstr_ensure(d, sizeof(ec));
165 d->len += sizeof(ec);
167 if (!ec_ptparse(&qd, a)) {
168 fprintf(stderr, "bad point `%.*s|%s': %s\n",
169 (int)(qd.p - p), p, qd.p, qd.e);
174 static void ecdodump(ec *a, FILE *fp)
180 mp_writefile(a->x, fp, 16);
182 mp_writefile(a->y, fp, 16);
186 static void ecdump(dstr *d, FILE *fp)
188 ec *a = (ec *)d->buf;
192 const test_type type_ec = { eccvt, ecdump };
194 /*----- Testing elliptic curve functionality ------------------------------*/
198 static void ecdestroy(ec_curve *c)
206 static int v##op(dstr v[]) \
208 ec_curve *e = *(ec_curve **)v[0].buf; \
209 ec *a = (ec *)v[1].buf; \
210 ec *r = (ec *)v[2].buf; \
214 if (!EC_EQ(r, &c)) { \
215 fprintf(stderr, #op "failed"); \
216 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \
217 fprintf(stderr, "\n a = "); ecdodump(a, stderr); \
218 fprintf(stderr, "\n r = "); ecdodump(r, stderr); \
219 fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \
220 fprintf(stderr, "\n"); \
223 EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); \
229 static int v##op(dstr v[]) \
231 ec_curve *e = *(ec_curve **)v[0].buf; \
232 ec *a = (ec *)v[1].buf; \
233 ec *b = (ec *)v[2].buf; \
234 ec *r = (ec *)v[3].buf; \
237 ec_##op(e, &c, a, b); \
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 b = "); ecdodump(b, stderr); \
243 fprintf(stderr, "\n r = "); ecdodump(r, stderr); \
244 fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \
245 fprintf(stderr, "\n"); \
248 EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c); \
258 static int vcheck(dstr v[])
260 ec_curve *e = *(ec_curve **)v[0].buf;
261 ec *a = (ec *)v[1].buf;
262 int r = *(int *)v[2].buf;
267 fprintf(stderr, "check failed");
268 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
269 fprintf(stderr, "\n a = "); ecdodump(a, stderr);
270 fprintf(stderr, "\n r = %d", r);
271 fprintf(stderr, "\n c = %d", c);
272 fprintf(stderr, "\n");
280 static int vmul(dstr v[])
282 ec_curve *e = *(ec_curve **)v[0].buf;
283 ec *a = (ec *)v[1].buf;
284 mp *n = *(mp **)v[2].buf;
285 ec *r = (ec *)v[3].buf;
290 fprintf(stderr, "mul failed");
291 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
292 fprintf(stderr, "\n a = "); ecdodump(a, stderr);
293 fprintf(stderr, "\n n = "); mp_writefile(n, stderr, 10);
294 fprintf(stderr, "\n r = "); ecdodump(r, stderr);
295 fprintf(stderr, "\n c = "); ecdodump(&c, stderr);
296 fprintf(stderr, "\n");
299 EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); MP_DROP(n);
304 static int vfind(dstr v[])
306 ec_curve *e = *(ec_curve **)v[0].buf;
307 mp *x = *(mp **)v[1].buf;
308 ec *r = (ec *)v[2].buf;
311 if (!ec_find(e, &c, x)) EC_SETINF(&c);
313 fprintf(stderr, "find failed");
314 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
315 fprintf(stderr, "\n x = "); mp_writefile(x, stderr, 16);
316 fprintf(stderr, "\n r = "); ecdodump(r, stderr);
317 fprintf(stderr, "\n c = "); ecdodump(&c, stderr);
318 fprintf(stderr, "\n");
321 MP_DROP(x); EC_DESTROY(r); EC_DESTROY(&c);
326 static test_chunk tests[] = {
327 { "neg", vneg, { &type_ecurve, &type_ec, &type_ec } },
328 { "dbl", vdbl, { &type_ecurve, &type_ec, &type_ec } },
329 { "add", vadd, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
330 { "sub", vsub, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
331 { "mul", vmul, { &type_ecurve, &type_ec, &type_mp, &type_ec } },
332 { "check", vcheck, { &type_ecurve, &type_ec, &type_int } },
333 { "find", vfind, { &type_ecurve, &type_mp, &type_ec } },
337 int main(int argc, char *argv[])
340 test_run(argc, argv, tests, SRCDIR "/t/ec");
346 /*----- That's all, folks -------------------------------------------------*/