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