keyutil.c: Remove stray tabs and trailing space from the list format.
[u/mdw/catacomb] / ec-test.c
CommitLineData
bc985cef 1/* -*-c-*-
2 *
5685a696 3 * $Id$
bc985cef 4 *
5 * Code for testing elliptic-curve stuff
6 *
7 * (c) 2004 Straylight/Edgeware
8 */
9
45c0fd36 10/*----- Licensing notice --------------------------------------------------*
bc985cef 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.
45c0fd36 18 *
bc985cef 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.
45c0fd36 23 *
bc985cef 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
bc985cef 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
47typedef 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
56static 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
76UNOP(IN)
77UNOP(OUT)
78UNOP(FIX)
79UNOP(NEG)
80UNOP(DBL)
81BINOP(ADD)
82BINOP(SUB)
83
84#undef UNOP
85#undef BINOP
86
87static 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
93static int ecCHECK(ec_curve *cc, const ec *p)
94{
95 ecctx *c = (ecctx *)cc;
96 return (EC_CHECK(c->real, p));
97}
98
34e4f738 99static 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
4e66da02 105static const ec_ops ecops = {
f94b972d 106 "cardboard",
34e4f738 107 ecDESTROY, ecSAMEP, ecIN, ecOUT, ecFIX,
bc985cef 108 ecFIND, ecNEG, ecADD, ecSUB, ecDBL, ecCHECK
109};
110
111static 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;
34e4f738 116 c->c.a = real->a;
117 c->c.b = real->b;
bc985cef 118 c->magic = MAGIC;
119 c->name = xstrdup(name);
120 c->real = real;
121 return (&c->c);
122}
123
124static const char *ec_name(ec_curve *cc)
125{
126 ecctx *c = (ecctx *)cc;
127 assert(c->magic == MAGIC);
128 return (c->name);
129}
130
432c4e18 131/*----- Test field types --------------------------------------------------*/
bc985cef 132
133static void ecvcvt(const char *buf, dstr *d)
134{
bc985cef 135 ec_curve *v;
432c4e18 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);
bc985cef 144 }
bc985cef 145 dstr_ensure(d, sizeof(v));
146 *(ec_curve **)d->buf = ec_cutout(v, buf);
147 d->len += sizeof(v);
148}
149
150static void ecvdump(dstr *d, FILE *fp)
151{
152 ec_curve *v = *(ec_curve **)d->buf;
153 fprintf(fp, "%s", ec_name(v));
154}
155
4e66da02 156const test_type type_ecurve = { ecvcvt, ecvdump };
bc985cef 157
158static void eccvt(const char *p, dstr *d)
159{
160 ec *a;
432c4e18 161 qd_parse qd;
bc985cef 162
432c4e18 163 qd.p = p;
164 qd.e = 0;
bc985cef 165 dstr_ensure(d, sizeof(ec));
166 a = (ec *)d->buf;
167 d->len += sizeof(ec);
168 ec_create(a);
432c4e18 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 }
bc985cef 173}
174
175static void ecdodump(ec *a, FILE *fp)
176{
177 if (EC_ATINF(a))
178 fputs("inf", fp);
179 else {
45c0fd36 180 fputs("0x", fp);
bc985cef 181 mp_writefile(a->x, fp, 16);
182 fputs(", 0x", fp);
183 mp_writefile(a->y, fp, 16);
184 }
185}
186
187static void ecdump(dstr *d, FILE *fp)
188{
189 ec *a = (ec *)d->buf;
190 ecdodump(a, fp);
191}
192
5685a696 193const test_type type_ec = { eccvt, ecdump };
bc985cef 194
195/*----- Testing elliptic curve functionality ------------------------------*/
196
197#ifdef TEST_RIG
198
199static 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
254UNOP(neg)
255UNOP(dbl)
256BINOP(add)
257BINOP(sub)
258
259static 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);
45c0fd36
MW
270 fprintf(stderr, "\n a = "); ecdodump(a, stderr);
271 fprintf(stderr, "\n r = %d", r);
272 fprintf(stderr, "\n c = %d", c);
bc985cef 273 fprintf(stderr, "\n");
274 ok = 0;
275 }
276 EC_DESTROY(a);
277 ecdestroy(e);
278 return (ok);
279}
280
281static 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);
45c0fd36
MW
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);
bc985cef 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
305static 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);
45c0fd36
MW
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);
bc985cef 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
327static 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
338int 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 -------------------------------------------------*/