chiark / gitweb /
configure.ac: Replace with a new version.
[catacomb] / ec-test.c
1 /* -*-c-*-
2  *
3  * $Id$
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 /*----- Header files ------------------------------------------------------*/
31
32 #include <assert.h>
33 #include <ctype.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include <mLib/alloc.h>
39 #include <mLib/testrig.h>
40 #include <mLib/sub.h>
41
42 #include "ec.h"
43 #include "ec-test.h"
44
45 /*----- Cardboard cut-out elliptic curve ----------------------------------*/
46
47 typedef struct ecctx {
48   ec_curve c;
49   unsigned long magic;
50   char *name;
51   ec_curve *real;
52 } ecctx;
53
54 #define MAGIC 0x3a1f0b07
55
56 static void ecDESTROY(ec_curve *cc)
57 {
58   ecctx *c = (ecctx *)cc;
59   xfree(c->name);
60   ec_destroycurve(c->real);
61   DESTROY(c);
62 }
63
64 #define UNOP(OP)                                                        \
65   static ec *ec##OP(ec_curve *cc, ec *d, const ec *p) {                 \
66     ecctx *c = (ecctx *)cc;                                             \
67     return (EC_##OP(c->real, d, p));                                    \
68   }
69
70 #define BINOP(OP)                                                       \
71   static ec *ec##OP(ec_curve *cc, ec *d, const ec *p, const ec *q) {    \
72     ecctx *c = (ecctx *)cc;                                             \
73     return (EC_##OP(c->real, d, p, q));                                 \
74   }
75
76 UNOP(IN)
77 UNOP(OUT)
78 UNOP(FIX)
79 UNOP(NEG)
80 UNOP(DBL)
81 BINOP(ADD)
82 BINOP(SUB)
83
84 #undef UNOP
85 #undef BINOP
86
87 static ec *ecFIND(ec_curve *cc, ec *d, mp *x)
88 {
89   ecctx *c = (ecctx *)cc;
90   return (EC_FIND(c->real, d, x));
91 }
92
93 static int ecCHECK(ec_curve *cc, const ec *p)
94 {
95   ecctx *c = (ecctx *)cc;
96   return (EC_CHECK(c->real, p));
97 }
98
99 static int ecSAMEP(ec_curve *cc, ec_curve *dd)
100 {
101   ecctx *c = (ecctx *)cc, *d = (ecctx *)dd;
102   return (ec_samep(c->real, d->real));
103 }
104
105 static const ec_ops ecops = {
106   "cardboard",
107   ecDESTROY, ecSAMEP, ecIN, ecOUT, ecFIX,
108   ecFIND, ecNEG, ecADD, ecSUB, ecDBL, ecCHECK
109 };
110
111 static ec_curve *ec_cutout(ec_curve *real, const char *name)
112 {
113   ecctx *c = CREATE(ecctx);
114   c->c.f = real->f;
115   c->c.ops = &ecops;
116   c->c.a = real->a;
117   c->c.b = real->b;
118   c->magic = MAGIC;
119   c->name = xstrdup(name);
120   c->real = real;
121   return (&c->c);
122 }
123
124 static const char *ec_name(ec_curve *cc)
125 {
126   ecctx *c = (ecctx *)cc;
127   assert(c->magic == MAGIC);
128   return (c->name);
129 }
130
131 /*----- Test field types --------------------------------------------------*/
132
133 static void ecvcvt(const char *buf, dstr *d)
134 {
135   ec_curve *v;
136   qd_parse qd;
137
138   qd.p = buf;
139   qd.e = 0;
140   if ((v = ec_curveparse(&qd)) == 0) {
141     fprintf(stderr, "bad curve `%.*s|%s': %s\n",
142             qd.p - buf, buf, qd.p, qd.e);
143     exit(1);
144   }
145   dstr_ensure(d, sizeof(v));
146   *(ec_curve **)d->buf = ec_cutout(v, buf);
147   d->len += sizeof(v);
148 }
149
150 static void ecvdump(dstr *d, FILE *fp)
151 {
152   ec_curve *v = *(ec_curve **)d->buf;
153   fprintf(fp, "%s", ec_name(v));
154 }
155
156 const test_type type_ecurve = { ecvcvt, ecvdump };
157
158 static void eccvt(const char *p, dstr *d)
159 {
160   ec *a;
161   qd_parse qd;
162
163   qd.p = p;
164   qd.e = 0;
165   dstr_ensure(d, sizeof(ec));
166   a = (ec *)d->buf;
167   d->len += sizeof(ec);
168   ec_create(a);
169   if (!ec_ptparse(&qd, a)) {
170     fprintf(stderr, "bad point `%.*s|%s': %s\n", qd.p - p, p, qd.p, qd.e);
171     exit(1);
172   }
173 }
174
175 static void ecdodump(ec *a, FILE *fp)
176 {
177   if (EC_ATINF(a))
178     fputs("inf", fp);
179   else {
180     fputs("0x", fp);
181     mp_writefile(a->x, fp, 16);
182     fputs(", 0x", fp);
183     mp_writefile(a->y, fp, 16);
184   }
185 }
186
187 static void ecdump(dstr *d, FILE *fp)
188 {
189   ec *a = (ec *)d->buf;
190   ecdodump(a, fp);
191 }
192
193 const test_type type_ec = { eccvt, ecdump };
194
195 /*----- Testing elliptic curve functionality ------------------------------*/
196
197 #ifdef TEST_RIG
198
199 static void ecdestroy(ec_curve *c)
200 {
201   field *f = c->f;
202   ec_destroycurve(c);
203   F_DESTROY(f);
204 }
205
206 #define UNOP(op)                                                        \
207   static int v##op(dstr v[])                                            \
208   {                                                                     \
209     ec_curve *e = *(ec_curve **)v[0].buf;                               \
210     ec *a = (ec *)v[1].buf;                                             \
211     ec *r = (ec *)v[2].buf;                                             \
212     ec c = EC_INIT;                                                     \
213     int ok = 1;                                                         \
214     ec_##op(e, &c, a);                                                  \
215     if (!EC_EQ(r, &c)) {                                                \
216       fprintf(stderr, #op "failed");                                    \
217       fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);       \
218       fprintf(stderr, "\n    a = "); ecdodump(a, stderr);               \
219       fprintf(stderr, "\n    r = "); ecdodump(r, stderr);               \
220       fprintf(stderr, "\n    c = "); ecdodump(&c, stderr);              \
221       fprintf(stderr, "\n");                                            \
222       ok = 0;                                                           \
223     }                                                                   \
224     EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c);                       \
225     ecdestroy(e);                                                       \
226     return (ok);                                                        \
227   }
228
229 #define BINOP(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 *b = (ec *)v[2].buf;                                             \
235     ec *r = (ec *)v[3].buf;                                             \
236     ec c = EC_INIT;                                                     \
237     int ok = 1;                                                         \
238     ec_##op(e, &c, a, b);                                               \
239     if (!EC_EQ(r, &c)) {                                                \
240       fprintf(stderr, #op "failed");                                    \
241       fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);       \
242       fprintf(stderr, "\n    a = "); ecdodump(a, stderr);               \
243       fprintf(stderr, "\n    b = "); ecdodump(b, stderr);               \
244       fprintf(stderr, "\n    r = "); ecdodump(r, stderr);               \
245       fprintf(stderr, "\n    c = "); ecdodump(&c, stderr);              \
246       fprintf(stderr, "\n");                                            \
247       ok = 0;                                                           \
248     }                                                                   \
249     EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c);        \
250     ecdestroy(e);                                                       \
251     return (ok);                                                        \
252   }
253
254 UNOP(neg)
255 UNOP(dbl)
256 BINOP(add)
257 BINOP(sub)
258
259 static int vcheck(dstr v[])
260 {
261   ec_curve *e = *(ec_curve **)v[0].buf;
262   ec *a = (ec *)v[1].buf;
263   int r = *(int *)v[2].buf;
264   int c;
265   int ok = 1;
266   c = ec_check(e, a);
267   if (r != c) {
268     fprintf(stderr, "check failed");
269     fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
270     fprintf(stderr, "\n    a = "); ecdodump(a, stderr);
271     fprintf(stderr, "\n    r = %d", r);
272     fprintf(stderr, "\n    c = %d", c);
273     fprintf(stderr, "\n");
274     ok = 0;
275   }
276   EC_DESTROY(a);
277   ecdestroy(e);
278   return (ok);
279 }
280
281 static int vmul(dstr v[])
282 {
283   ec_curve *e = *(ec_curve **)v[0].buf;
284   ec *a = (ec *)v[1].buf;
285   mp *n = *(mp **)v[2].buf;
286   ec *r = (ec *)v[3].buf;
287   ec c = EC_INIT;
288   int ok = 1;
289   ec_mul(e, &c, a, n);
290   if (!EC_EQ(r, &c)) {
291     fprintf(stderr, "mul failed");
292     fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
293     fprintf(stderr, "\n    a = "); ecdodump(a, stderr);
294     fprintf(stderr, "\n    n = "); mp_writefile(n, stderr, 10);
295     fprintf(stderr, "\n    r = "); ecdodump(r, stderr);
296     fprintf(stderr, "\n    c = "); ecdodump(&c, stderr);
297     fprintf(stderr, "\n");
298     ok = 0;
299   }
300   EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); MP_DROP(n);
301   ecdestroy(e);
302   return (ok);
303 }
304
305 static int vfind(dstr v[])
306 {
307   ec_curve *e = *(ec_curve **)v[0].buf;
308   mp *x = *(mp **)v[1].buf;
309   ec *r = (ec *)v[2].buf;
310   ec c = EC_INIT;
311   int ok = 1;
312   if (!ec_find(e, &c, x)) EC_SETINF(&c);
313   if (!EC_EQ(r, &c)) {
314     fprintf(stderr, "find failed");
315     fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
316     fprintf(stderr, "\n    x = "); mp_writefile(x, stderr, 16);
317     fprintf(stderr, "\n    r = "); ecdodump(r, stderr);
318     fprintf(stderr, "\n    c = "); ecdodump(&c, stderr);
319     fprintf(stderr, "\n");
320     ok = 0;
321   }
322   MP_DROP(x); EC_DESTROY(r); EC_DESTROY(&c);
323   ecdestroy(e);
324   return (ok);
325 }
326
327 static test_chunk tests[] = {
328   { "neg", vneg, { &type_ecurve, &type_ec, &type_ec } },
329   { "dbl", vdbl, { &type_ecurve, &type_ec, &type_ec } },
330   { "add", vadd, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
331   { "sub", vsub, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
332   { "mul", vmul, { &type_ecurve, &type_ec, &type_mp, &type_ec } },
333   { "check", vcheck, { &type_ecurve, &type_ec, &type_int } },
334   { "find", vfind, { &type_ecurve, &type_mp, &type_ec } },
335   { 0, 0, { 0 } }
336 };
337
338 int main(int argc, char *argv[])
339 {
340   sub_init();
341   test_run(argc, argv, tests, SRCDIR "/tests/ec");
342   return (0);
343 }
344
345 #endif
346
347 /*----- That's all, folks -------------------------------------------------*/