--- /dev/null
+/* -*-c-*-
+ *
+ * Code for testing elliptic-curve stuff
+ *
+ * (c) 2004 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/testrig.h>
+#include <mLib/sub.h>
+
+#include "ec.h"
+#include "ec-test.h"
+
+/*----- Cardboard cut-out elliptic curve ----------------------------------*/
+
+typedef struct ecctx {
+ ec_curve c;
+ unsigned long magic;
+ char *name;
+ ec_curve *real;
+} ecctx;
+
+#define MAGIC 0x3a1f0b07
+
+static void ecDESTROY(ec_curve *cc)
+{
+ ecctx *c = (ecctx *)cc;
+ xfree(c->name);
+ ec_destroycurve(c->real);
+ DESTROY(c);
+}
+
+#define UNOP(OP) \
+ static ec *ec##OP(ec_curve *cc, ec *d, const ec *p) { \
+ ecctx *c = (ecctx *)cc; \
+ return (EC_##OP(c->real, d, p)); \
+ }
+
+#define BINOP(OP) \
+ static ec *ec##OP(ec_curve *cc, ec *d, const ec *p, const ec *q) { \
+ ecctx *c = (ecctx *)cc; \
+ return (EC_##OP(c->real, d, p, q)); \
+ }
+
+UNOP(IN)
+UNOP(OUT)
+UNOP(FIX)
+UNOP(NEG)
+UNOP(DBL)
+BINOP(ADD)
+BINOP(SUB)
+
+#undef UNOP
+#undef BINOP
+
+static ec *ecFIND(ec_curve *cc, ec *d, mp *x)
+{
+ ecctx *c = (ecctx *)cc;
+ return (EC_FIND(c->real, d, x));
+}
+
+static int ecCHECK(ec_curve *cc, const ec *p)
+{
+ ecctx *c = (ecctx *)cc;
+ return (EC_CHECK(c->real, p));
+}
+
+static int ecSAMEP(ec_curve *cc, ec_curve *dd)
+{
+ ecctx *c = (ecctx *)cc, *d = (ecctx *)dd;
+ return (ec_samep(c->real, d->real));
+}
+
+static const ec_ops ecops = {
+ "cardboard",
+ ecDESTROY, ecSAMEP, ecIN, ecOUT, ecFIX,
+ ecFIND, ecNEG, ecADD, ecSUB, ecDBL, ecCHECK
+};
+
+static ec_curve *ec_cutout(ec_curve *real, const char *name)
+{
+ ecctx *c = CREATE(ecctx);
+ c->c.f = real->f;
+ c->c.ops = &ecops;
+ c->c.a = real->a;
+ c->c.b = real->b;
+ c->magic = MAGIC;
+ c->name = xstrdup(name);
+ c->real = real;
+ return (&c->c);
+}
+
+static const char *ec_name(ec_curve *cc)
+{
+ ecctx *c = (ecctx *)cc;
+ assert(c->magic == MAGIC);
+ return (c->name);
+}
+
+/*----- Test field types --------------------------------------------------*/
+
+static void ecvcvt(const char *buf, dstr *d)
+{
+ ec_curve *v;
+ qd_parse qd;
+
+ qd.p = buf;
+ qd.e = 0;
+ if ((v = ec_curveparse(&qd)) == 0) {
+ fprintf(stderr, "bad curve `%.*s|%s': %s\n",
+ qd.p - buf, buf, qd.p, qd.e);
+ exit(1);
+ }
+ dstr_ensure(d, sizeof(v));
+ *(ec_curve **)d->buf = ec_cutout(v, buf);
+ d->len += sizeof(v);
+}
+
+static void ecvdump(dstr *d, FILE *fp)
+{
+ ec_curve *v = *(ec_curve **)d->buf;
+ fprintf(fp, "%s", ec_name(v));
+}
+
+const test_type type_ecurve = { ecvcvt, ecvdump };
+
+static void eccvt(const char *p, dstr *d)
+{
+ ec *a;
+ qd_parse qd;
+
+ qd.p = p;
+ qd.e = 0;
+ dstr_ensure(d, sizeof(ec));
+ a = (ec *)d->buf;
+ d->len += sizeof(ec);
+ ec_create(a);
+ if (!ec_ptparse(&qd, a)) {
+ fprintf(stderr, "bad point `%.*s|%s': %s\n", qd.p - p, p, qd.p, qd.e);
+ exit(1);
+ }
+}
+
+static void ecdodump(ec *a, FILE *fp)
+{
+ if (EC_ATINF(a))
+ fputs("inf", fp);
+ else {
+ fputs("0x", fp);
+ mp_writefile(a->x, fp, 16);
+ fputs(", 0x", fp);
+ mp_writefile(a->y, fp, 16);
+ }
+}
+
+static void ecdump(dstr *d, FILE *fp)
+{
+ ec *a = (ec *)d->buf;
+ ecdodump(a, fp);
+}
+
+const test_type type_ec = { eccvt, ecdump };
+
+/*----- Testing elliptic curve functionality ------------------------------*/
+
+#ifdef TEST_RIG
+
+static void ecdestroy(ec_curve *c)
+{
+ field *f = c->f;
+ ec_destroycurve(c);
+ F_DESTROY(f);
+}
+
+#define UNOP(op) \
+ static int v##op(dstr v[]) \
+ { \
+ ec_curve *e = *(ec_curve **)v[0].buf; \
+ ec *a = (ec *)v[1].buf; \
+ ec *r = (ec *)v[2].buf; \
+ ec c = EC_INIT; \
+ int ok = 1; \
+ ec_##op(e, &c, a); \
+ if (!EC_EQ(r, &c)) { \
+ fprintf(stderr, #op "failed"); \
+ fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \
+ fprintf(stderr, "\n a = "); ecdodump(a, stderr); \
+ fprintf(stderr, "\n r = "); ecdodump(r, stderr); \
+ fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \
+ fprintf(stderr, "\n"); \
+ ok = 0; \
+ } \
+ EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); \
+ ecdestroy(e); \
+ return (ok); \
+ }
+
+#define BINOP(op) \
+ static int v##op(dstr v[]) \
+ { \
+ ec_curve *e = *(ec_curve **)v[0].buf; \
+ ec *a = (ec *)v[1].buf; \
+ ec *b = (ec *)v[2].buf; \
+ ec *r = (ec *)v[3].buf; \
+ ec c = EC_INIT; \
+ int ok = 1; \
+ ec_##op(e, &c, a, b); \
+ if (!EC_EQ(r, &c)) { \
+ fprintf(stderr, #op "failed"); \
+ fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \
+ fprintf(stderr, "\n a = "); ecdodump(a, stderr); \
+ fprintf(stderr, "\n b = "); ecdodump(b, stderr); \
+ fprintf(stderr, "\n r = "); ecdodump(r, stderr); \
+ fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \
+ fprintf(stderr, "\n"); \
+ ok = 0; \
+ } \
+ EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c); \
+ ecdestroy(e); \
+ return (ok); \
+ }
+
+UNOP(neg)
+UNOP(dbl)
+BINOP(add)
+BINOP(sub)
+
+static int vcheck(dstr v[])
+{
+ ec_curve *e = *(ec_curve **)v[0].buf;
+ ec *a = (ec *)v[1].buf;
+ int r = *(int *)v[2].buf;
+ int c;
+ int ok = 1;
+ c = ec_check(e, a);
+ if (r != c) {
+ fprintf(stderr, "check failed");
+ fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
+ fprintf(stderr, "\n a = "); ecdodump(a, stderr);
+ fprintf(stderr, "\n r = %d", r);
+ fprintf(stderr, "\n c = %d", c);
+ fprintf(stderr, "\n");
+ ok = 0;
+ }
+ EC_DESTROY(a);
+ ecdestroy(e);
+ return (ok);
+}
+
+static int vmul(dstr v[])
+{
+ ec_curve *e = *(ec_curve **)v[0].buf;
+ ec *a = (ec *)v[1].buf;
+ mp *n = *(mp **)v[2].buf;
+ ec *r = (ec *)v[3].buf;
+ ec c = EC_INIT;
+ int ok = 1;
+ ec_mul(e, &c, a, n);
+ if (!EC_EQ(r, &c)) {
+ fprintf(stderr, "mul failed");
+ fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
+ fprintf(stderr, "\n a = "); ecdodump(a, stderr);
+ fprintf(stderr, "\n n = "); mp_writefile(n, stderr, 10);
+ fprintf(stderr, "\n r = "); ecdodump(r, stderr);
+ fprintf(stderr, "\n c = "); ecdodump(&c, stderr);
+ fprintf(stderr, "\n");
+ ok = 0;
+ }
+ EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); MP_DROP(n);
+ ecdestroy(e);
+ return (ok);
+}
+
+static int vfind(dstr v[])
+{
+ ec_curve *e = *(ec_curve **)v[0].buf;
+ mp *x = *(mp **)v[1].buf;
+ ec *r = (ec *)v[2].buf;
+ ec c = EC_INIT;
+ int ok = 1;
+ if (!ec_find(e, &c, x)) EC_SETINF(&c);
+ if (!EC_EQ(r, &c)) {
+ fprintf(stderr, "find failed");
+ fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
+ fprintf(stderr, "\n x = "); mp_writefile(x, stderr, 16);
+ fprintf(stderr, "\n r = "); ecdodump(r, stderr);
+ fprintf(stderr, "\n c = "); ecdodump(&c, stderr);
+ fprintf(stderr, "\n");
+ ok = 0;
+ }
+ MP_DROP(x); EC_DESTROY(r); EC_DESTROY(&c);
+ ecdestroy(e);
+ return (ok);
+}
+
+static test_chunk tests[] = {
+ { "neg", vneg, { &type_ecurve, &type_ec, &type_ec } },
+ { "dbl", vdbl, { &type_ecurve, &type_ec, &type_ec } },
+ { "add", vadd, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
+ { "sub", vsub, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
+ { "mul", vmul, { &type_ecurve, &type_ec, &type_mp, &type_ec } },
+ { "check", vcheck, { &type_ecurve, &type_ec, &type_int } },
+ { "find", vfind, { &type_ecurve, &type_mp, &type_ec } },
+ { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+ sub_init();
+ test_run(argc, argv, tests, SRCDIR "/t/ec");
+ return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/