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>
45 /*----- Cardboard cut-out elliptic curve ----------------------------------*/
47 typedef struct ecctx
{
54 #define MAGIC 0x3a1f0b07
56 static void ecDESTROY(ec_curve
*cc
)
58 ecctx
*c
= (ecctx
*)cc
;
60 ec_destroycurve(c
->real
);
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)); \
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)); \
87 static ec
*ecFIND(ec_curve
*cc
, ec
*d
, mp
*x
)
89 ecctx
*c
= (ecctx
*)cc
;
90 return (EC_FIND(c
->real
, d
, x
));
93 static int ecCOMPR(ec_curve
*cc
, const ec
*p
)
95 ecctx
*c
= (ecctx
*)cc
;
96 return (EC_COMPR(c
->real
, p
));
99 static int ecCHECK(ec_curve
*cc
, const ec
*p
)
101 ecctx
*c
= (ecctx
*)cc
;
102 return (EC_CHECK(c
->real
, p
));
105 static int ecSAMEP(ec_curve
*cc
, ec_curve
*dd
)
107 ecctx
*c
= (ecctx
*)cc
, *d
= (ecctx
*)dd
;
108 return (ec_samep(c
->real
, d
->real
));
111 static const ec_ops ecops
= {
113 ecDESTROY
, ecSAMEP
, ecIN
, ecOUT
, ecFIX
,
114 ecFIND
, ecNEG
, ecADD
, ecSUB
, ecDBL
, ecCHECK
, ecCOMPR
117 static ec_curve
*ec_cutout(ec_curve
*real
, const char *name
)
119 ecctx
*c
= CREATE(ecctx
);
125 c
->name
= xstrdup(name
);
130 static const char *ec_name(ec_curve
*cc
)
132 ecctx
*c
= (ecctx
*)cc
;
133 assert(c
->magic
== MAGIC
);
137 /*----- Test field types --------------------------------------------------*/
139 static void ecvcvt(const char *buf
, dstr
*d
)
148 for (ee
= ectab
; ee
->name
; ee
++) {
149 if (qd_enum(&qd
, ee
->name
) >= 0) {
150 ec_infofromdata(&ei
, ee
->data
);
152 MP_DROP(ei
.r
); MP_DROP(ei
.h
);
157 if ((v
= ec_curveparse(&qd
)) == 0) {
158 fprintf(stderr
, "bad curve `%.*s|%s': %s\n",
159 (int)(qd
.p
- buf
), buf
, qd
.p
, qd
.e
);
163 dstr_ensure(d
, sizeof(v
));
164 *(ec_curve
**)d
->buf
= ec_cutout(v
, buf
);
168 static void ecvdump(dstr
*d
, FILE *fp
)
170 ec_curve
*v
= *(ec_curve
**)d
->buf
;
171 fprintf(fp
, "%s", ec_name(v
));
174 const test_type type_ecurve
= { ecvcvt
, ecvdump
};
176 static void eccvt(const char *p
, dstr
*d
)
183 dstr_ensure(d
, sizeof(ec
));
185 d
->len
+= sizeof(ec
);
187 if (!ec_ptparse(&qd
, a
)) {
188 fprintf(stderr
, "bad point `%.*s|%s': %s\n",
189 (int)(qd
.p
- p
), p
, qd
.p
, qd
.e
);
194 static void ecdodump(ec
*a
, FILE *fp
)
200 mp_writefile(a
->x
, fp
, 16);
202 mp_writefile(a
->y
, fp
, 16);
206 static void ecdump(dstr
*d
, FILE *fp
)
208 ec
*a
= (ec
*)d
->buf
;
212 const test_type type_ec
= { eccvt
, ecdump
};
214 /*----- Testing elliptic curve functionality ------------------------------*/
218 static void ecdestroy(ec_curve
*c
)
226 static int v##op(dstr v[]) \
228 ec_curve *e = *(ec_curve **)v[0].buf; \
229 ec *a = (ec *)v[1].buf; \
230 ec *r = (ec *)v[2].buf; \
234 if (!EC_EQ(r, &c)) { \
235 fprintf(stderr, #op " failed"); \
236 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \
237 fprintf(stderr, "\n a = "); ecdodump(a, stderr); \
238 fprintf(stderr, "\n r = "); ecdodump(r, stderr); \
239 fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \
240 fprintf(stderr, "\n"); \
243 EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); \
249 static int v##op(dstr v[]) \
251 ec_curve *e = *(ec_curve **)v[0].buf; \
252 ec *a = (ec *)v[1].buf; \
253 ec *b = (ec *)v[2].buf; \
254 ec *r = (ec *)v[3].buf; \
257 ec_##op(e, &c, a, b); \
258 if (!EC_EQ(r, &c)) { \
259 fprintf(stderr, #op " failed"); \
260 fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr); \
261 fprintf(stderr, "\n a = "); ecdodump(a, stderr); \
262 fprintf(stderr, "\n b = "); ecdodump(b, stderr); \
263 fprintf(stderr, "\n r = "); ecdodump(r, stderr); \
264 fprintf(stderr, "\n c = "); ecdodump(&c, stderr); \
265 fprintf(stderr, "\n"); \
268 EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c); \
278 static int vcheck(dstr v
[])
280 ec_curve
*e
= *(ec_curve
**)v
[0].buf
;
281 ec
*a
= (ec
*)v
[1].buf
;
282 int r
= *(int *)v
[2].buf
;
287 fprintf(stderr
, "check failed");
288 fprintf(stderr
, "\ncurve = "); type_ecurve
.dump(v
, stderr
);
289 fprintf(stderr
, "\n a = "); ecdodump(a
, stderr
);
290 fprintf(stderr
, "\n r = %d", r
);
291 fprintf(stderr
, "\n c = %d", c
);
292 fprintf(stderr
, "\n");
300 static int vmul(dstr v
[])
302 ec_curve
*e
= *(ec_curve
**)v
[0].buf
;
303 ec
*a
= (ec
*)v
[1].buf
;
304 mp
*n
= *(mp
**)v
[2].buf
;
305 ec
*r
= (ec
*)v
[3].buf
;
310 fprintf(stderr
, "mul failed");
311 fprintf(stderr
, "\ncurve = "); type_ecurve
.dump(v
, stderr
);
312 fprintf(stderr
, "\n a = "); ecdodump(a
, stderr
);
313 fprintf(stderr
, "\n n = "); mp_writefile(n
, stderr
, 10);
314 fprintf(stderr
, "\n r = "); ecdodump(r
, stderr
);
315 fprintf(stderr
, "\n c = "); ecdodump(&c
, stderr
);
316 fprintf(stderr
, "\n");
319 EC_DESTROY(a
); EC_DESTROY(r
); EC_DESTROY(&c
); MP_DROP(n
);
324 static int vfind(dstr v
[])
326 ec_curve
*e
= *(ec_curve
**)v
[0].buf
;
327 mp
*x
= *(mp
**)v
[1].buf
;
328 ec
*r
= (ec
*)v
[2].buf
;
331 if (!ec_find(e
, &c
, x
)) EC_SETINF(&c
);
333 fprintf(stderr
, "find failed");
334 fprintf(stderr
, "\ncurve = "); type_ecurve
.dump(v
, stderr
);
335 fprintf(stderr
, "\n x = "); mp_writefile(x
, stderr
, 16);
336 fprintf(stderr
, "\n r = "); ecdodump(r
, stderr
);
337 fprintf(stderr
, "\n c = "); ecdodump(&c
, stderr
);
338 fprintf(stderr
, "\n");
341 MP_DROP(x
); EC_DESTROY(r
); EC_DESTROY(&c
);
346 static int vec2osp(dstr v
[])
348 ec_curve
*e
= *(ec_curve
**)v
[0].buf
;
349 unsigned f
= *(int *)v
[1].buf
;
350 ec
*p
= (ec
*)v
[2].buf
;
351 size_t n
= 1 + 2*e
->f
->noctets
;
352 dstr d
= DSTR_INIT
, dd
= DSTR_INIT
;
357 if (strcmp(v
[3].buf
, "FAIL") == 0) wantwin
= 0;
358 else { wantwin
= 1; type_hex
.cvt(v
[3].buf
, &d
); }
360 dstr_ensure(&dd
, n
); buf_init(&b
, dd
.buf
, n
);
362 win
= !ec_ec2osp(e
, f
, &b
, p
);
363 if (!win
!= !wantwin
||
364 (win
&& (BLEN(&b
) != d
.len
||
365 memcmp(BBASE(&b
), d
.buf
, BLEN(&b
)) != 0))) {
367 fprintf(stderr
, "ec2osp failed");
368 fprintf(stderr
, "\ncurve = "); type_ecurve
.dump(v
, stderr
);
369 fprintf(stderr
, "\n fmt = 0x%02x", f
);
370 fprintf(stderr
, "\n p = "); ecdodump(p
, stderr
);
371 fprintf(stderr
, "\n want = ");
372 if (wantwin
) type_hex
.dump(&d
, stderr
);
373 else fprintf(stderr
, "FAIL");
374 fprintf(stderr
, "\nfound = ");
375 if (win
) { dd
.len
= BLEN(&b
); type_hex
.dump(&dd
, stderr
); }
376 else fprintf(stderr
, "FAIL");
377 fprintf(stderr
, "\n");
380 dstr_destroy(&d
); dstr_destroy(&dd
);
381 EC_DESTROY(p
); ecdestroy(e
);
385 static int vos2ecp(dstr v
[])
387 ec_curve
*e
= *(ec_curve
**)v
[0].buf
;
388 unsigned f
= *(int *)v
[1].buf
;
389 int remain
= *(int *)v
[4].buf
;
396 if (strcmp(v
[3].buf
, "FAIL") == 0) p
= 0;
397 else { type_ec
.cvt(v
[3].buf
, &d
); p
= (ec
*)d
.buf
; }
399 buf_init(&b
, v
[2].buf
, v
[2].len
);
400 win
= !ec_os2ecp(e
, f
, &b
, &q
);
402 if (!win
!= !p
|| (win
&& (!EC_EQ(p
, &q
) || BLEFT(&b
) != remain
))) {
404 fprintf(stderr
, "os2ecp failed");
405 fprintf(stderr
, "\ncurve = "); type_ecurve
.dump(v
, stderr
);
406 fprintf(stderr
, "\n fmt = 0x%02x", f
);
407 fprintf(stderr
, "\ninput = "); type_hex
.dump(&v
[2], stderr
);
408 fprintf(stderr
, "\n want = ");
409 if (p
) ecdodump(p
, stderr
); else fprintf(stderr
, "FAIL");
410 fprintf(stderr
, "\nfound = ");
411 if (win
) ecdodump(&q
, stderr
); else fprintf(stderr
, "FAIL");
412 fprintf(stderr
, "\nremain= %d", remain
);
413 fprintf(stderr
, "\nleft = %d", (int)BLEFT(&b
));
414 fprintf(stderr
, "\n");
417 if (p
) EC_DESTROY(p
); EC_DESTROY(&q
); ecdestroy(e
);
422 static test_chunk tests
[] = {
423 { "neg", vneg
, { &type_ecurve
, &type_ec
, &type_ec
} },
424 { "dbl", vdbl
, { &type_ecurve
, &type_ec
, &type_ec
} },
425 { "add", vadd
, { &type_ecurve
, &type_ec
, &type_ec
, &type_ec
} },
426 { "sub", vsub
, { &type_ecurve
, &type_ec
, &type_ec
, &type_ec
} },
427 { "mul", vmul
, { &type_ecurve
, &type_ec
, &type_mp
, &type_ec
} },
428 { "check", vcheck
, { &type_ecurve
, &type_ec
, &type_int
} },
429 { "find", vfind
, { &type_ecurve
, &type_mp
, &type_ec
} },
430 { "ec2osp", vec2osp
, { &type_ecurve
, &type_int
, &type_ec
, &type_string
} },
432 { &type_ecurve
, &type_int
, &type_hex
, &type_string
, &type_int
} },
436 int main(int argc
, char *argv
[])
439 test_run(argc
, argv
, tests
, SRCDIR
"/t/ec");
445 /*----- That's all, folks -------------------------------------------------*/