catcrypt: Implement symmetric key-encapsulation and signature schemes.
[u/mdw/catacomb] / group-test.c
CommitLineData
34e4f738 1/* -*-c-*-
2 *
b817bfc6 3 * $Id: group-test.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
34e4f738 4 *
5 * Testing group operations
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
34e4f738 30/*----- Header files ------------------------------------------------------*/
31
32#include <stdarg.h>
33
34#include <mLib/testrig.h>
35
36#include "group.h"
37#include "fibrand.h"
38#include "ec.h"
39#include "ec-test.h"
40
41/*----- Main code ---------------------------------------------------------*/
42
43static group *getgroup(const char *p) {
44 group *g; qd_parse qd;
45 qd.p = p; qd.e = 0; g = group_parse(&qd);
46 if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; }
47 if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p,
48 p, qd.p, qd.e); exit(1); }
49 return (g);
50}
51
52static ge *getge(group *g, const char *p) {
53 ge *x = G_CREATE(g);
54 if (group_readstring(g, x, p, 0)) {
55 fprintf(stderr, "bad group element `%s'\n", p);
56 exit(1);
57 }
58 return (x);
59}
60
61static void show(group *g, const char *p, ge *x) {
62 fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr);
63 putc('\n', stderr);
64}
65
66static void showec(const char *p, ec *q) {
67 fprintf(stderr, "*** %s = ", p);
68 if (EC_ATINF(q)) fprintf(stderr, "inf\n");
69 else {
70 mp_writefile(q->x, stderr, 16); fputs(", ", stderr);
71 mp_writefile(q->x, stderr, 16); putchar('\n');
72 }
73}
74
75static void showmp(const char *p, mp *x, int r) {
76 fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r);
77 putc('\n', stderr);
78}
79
80static int check(const char *op, const char *gd, group *g,
81 ge *r, ge *c, ...) {
82 va_list ap;
83
84 if (G_EQ(g, r, c)) return (1);
85 fprintf(stderr, "\n*** %s failed\n", op);
86 fprintf(stderr, "*** group: %s\n", gd);
87 va_start(ap, c);
88 for (;;) {
89 const char *p; ge *x;
90 p = va_arg(ap, const char *); if (!p) break;
91 x = va_arg(ap, ge *); show(g, p, x);
92 }
93 show(g, "expected", r);
94 show(g, "computed", c);
95 return (0);
96}
97
98/*----- Actual tests ------------------------------------------------------*/
99
100static int vcheck(dstr *v)
101{
102 group *g = getgroup(v[0].buf);
103 grand *gr = fibrand_create(0);
104 const char *e = G_CHECK(g, gr);
105 int ok = 1;
106 gr->ops->destroy(gr);
107 if (!e) e = "ok";
108 G_DESTROYGROUP(g);
109 if (strcmp(e, v[1].buf)) {
110 ok = 0;
111 fprintf(stderr, "*** check failed\n");
112 fprintf(stderr, "*** group: %s\n", v[0].buf);
113 fprintf(stderr, "*** expected: %s\n", v[1].buf);
114 fprintf(stderr, "*** returned: %s\n", e);
115 }
116 assert(mparena_count(MPARENA_GLOBAL) == 0);
117 return (ok);
118}
119
120static int vcheckelt(dstr *v)
121{
122 group *g = getgroup(v[0].buf);
123 ge *x = getge(g, v[1].buf);
124 int ir = *(int *)v[2].buf;
125 int ic = group_check(g, x);
126 int ok = 1;
127 if (ir != ic) {
128 ok = 0;
129 fprintf(stderr, "*** check failed\n");
130 fprintf(stderr, "*** group: %s\n", v[0].buf);
131 show(g, "x", x);
132 fprintf(stderr, "*** expected %s\n", ir ? "failure" : "success");
133 }
134 G_DESTROY(g, x);
135 G_DESTROYGROUP(g);
136 assert(mparena_count(MPARENA_GLOBAL) == 0);
137 return (ok);
138}
139
140static int vmul(dstr *v)
141{
142 group *g = getgroup(v[0].buf);
143 ge *x = getge(g, v[1].buf);
144 ge *y = getge(g, v[2].buf);
145 ge *r = getge(g, v[3].buf);
146 ge *c = G_CREATE(g);
147 int ok = 1;
148 G_MUL(g, c, x, y);
149 ok &= check("mul", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
150 G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
151 G_DESTROYGROUP(g);
152 assert(mparena_count(MPARENA_GLOBAL) == 0);
153 return (ok);
154}
155
156static int vsqr(dstr *v)
157{
158 group *g = getgroup(v[0].buf);
159 ge *x = getge(g, v[1].buf);
160 ge *r = getge(g, v[2].buf);
161 ge *c = G_CREATE(g);
162 int ok = 1;
163 G_SQR(g, c, x);
164 ok &= check("sqr", v[0].buf, g, r, c, "x", x, (char *)0);
165 G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
166 G_DESTROYGROUP(g);
167 assert(mparena_count(MPARENA_GLOBAL) == 0);
168 return (ok);
169}
170
171static int vinv(dstr *v)
172{
173 group *g = getgroup(v[0].buf);
174 ge *x = getge(g, v[1].buf);
175 ge *r = getge(g, v[2].buf);
176 ge *c = G_CREATE(g);
177 int ok = 1;
178 G_INV(g, c, x);
179 ok &= check("inv", v[0].buf, g, r, c, "x", x, (char *)0);
180 G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
181 G_DESTROYGROUP(g);
182 assert(mparena_count(MPARENA_GLOBAL) == 0);
183 return (ok);
184}
185
186static int vdiv(dstr *v)
187{
188 group *g = getgroup(v[0].buf);
189 ge *x = getge(g, v[1].buf);
190 ge *y = getge(g, v[2].buf);
191 ge *r = getge(g, v[3].buf);
192 ge *c = G_CREATE(g);
193 int ok = 1;
194 G_DIV(g, c, x, y);
195 ok &= check("div", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
196 group_stddiv(g, c, x, y);
197 ok &= check("stddiv", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
198 G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
199 G_DESTROYGROUP(g);
200 assert(mparena_count(MPARENA_GLOBAL) == 0);
201 return (ok);
202}
203
204static int vexp(dstr *v)
205{
206 group *g = getgroup(v[0].buf);
207 ge *x = getge(g, v[1].buf);
208 mp *n = *(mp **)v[2].buf;
209 ge *r = getge(g, v[3].buf);
210 ge *c = G_CREATE(g);
211 int ok = 1;
212 G_EXP(g, c, x, n);
213 if (!G_EQ(g, r, c)) {
214 ok = 0;
215 fprintf(stderr, "\n*** exp failed\n");
216 fprintf(stderr, "*** group: %s\n", v[0].buf);
217 show(g, "x", x); showmp("n", n, 10);
218 show(g, "expected", r); show(g, "computed", c);
219 }
220 group_stdexp(g, c, x, n);
221 if (!G_EQ(g, r, c)) {
222 ok = 0;
223 fprintf(stderr, "\n*** stdexp failed\n");
224 fprintf(stderr, "*** group: %s\n", v[0].buf);
225 show(g, "x", x); showmp("n", n, 10);
226 show(g, "expected", r); show(g, "computed", c);
227 }
228 G_DESTROY(g, x); MP_DROP(n); G_DESTROY(g, r); G_DESTROY(g, c);
229 G_DESTROYGROUP(g);
230 assert(mparena_count(MPARENA_GLOBAL) == 0);
231 return (ok);
232}
233
234static int vmexp(size_t n, dstr *v)
235{
236 group *g = getgroup(v[0].buf);
237 ge *c, *r;
238 group_expfactor *f = xmalloc(n * sizeof(group_expfactor));
239 int ok = 1;
240 size_t i;
241 for (i = 0; i < n; i++) {
242 f[i].base = getge(g, v[1 + 2 * i].buf);
243 f[i].exp = *(mp **)v[2 + 2 * i].buf;
244 }
245 r = getge(g, v[1 + 2 * n].buf);
246 c = G_CREATE(g);
247 G_MEXP(g, c, f, n);
248 if (!G_EQ(g, r, c)) {
249 ok = 0;
250 fprintf(stderr, "\n*** mexp failed\n");
251 fprintf(stderr, "*** group: %s\n", v[0].buf);
252 for (i = 0; i < n; i++) {
253 show(g, "base", f[i].base);
254 showmp("exp", f[i].exp, 10);
255 }
256 show(g, "expected", r); show(g, "computed", c);
257 }
258 group_stdmexp(g, c, f, n);
259 if (!G_EQ(g, r, c)) {
260 ok = 0;
261 fprintf(stderr, "\n*** stdmexp failed\n");
262 fprintf(stderr, "*** group: %s\n", v[0].buf);
263 for (i = 0; i < n; i++) {
264 show(g, "base", f[i].base);
265 showmp("exp", f[i].exp, 10);
266 }
267 show(g, "expected", r); show(g, "computed", c);
268 }
269 for (i = 0; i < n; i++) { G_DESTROY(g, f[i].base); MP_DROP(f[i].exp); }
270 G_DESTROY(g, r); G_DESTROY(g, c);
271 G_DESTROYGROUP(g);
272 assert(mparena_count(MPARENA_GLOBAL) == 0);
273 return (ok);
274}
275
276static int vmexp1(dstr *v) { return vmexp(1, v); }
277static int vmexp2(dstr *v) { return vmexp(2, v); }
278static int vmexp3(dstr *v) { return vmexp(3, v); }
279static int vmexp4(dstr *v) { return vmexp(4, v); }
280
281static int vtoint(dstr *v)
282{
283 group *g = getgroup(v[0].buf);
284 ge *x = getge(g, v[1].buf);
285 int ir = *(int *)v[2].buf;
286 mp *r = *(mp **)v[3].buf;
287 mp *c;
288 int ic;
289 int ok = 1;
290 c = G_TOINT(g, MP_NEW, x);
291 ic = c ? 0 : -1;
292 if (ir != ic || (!ic && !MP_EQ(r, c))) {
293 ok = 0;
294 fprintf(stderr, "\n*** toint failed\n");
295 fprintf(stderr, "*** group: %s\n", v[0].buf);
296 if (ir) fprintf(stderr, "*** expected failure\n");
297 else { show(g, "x", x); showmp("expected", r, 16);
298 showmp("computed", c, 16); }
299 }
300 G_DESTROY(g, x); mp_drop(r); mp_drop(c);
301 G_DESTROYGROUP(g);
302 assert(mparena_count(MPARENA_GLOBAL) == 0);
303 return (ok);
304}
305
306static int vfromint(dstr *v)
307{
308 group *g = getgroup(v[0].buf);
309 mp *x = *(mp **)v[1].buf;
310 int ir = *(int *)v[2].buf;
311 ge *r = getge(g, v[3].buf);
312 int ic;
313 ge *c = G_CREATE(g);
314 int ok = 1;
315 ic = G_FROMINT(g, c, x);
316 if (ir != ic || (!ic && !G_EQ(g, r, c))) {
317 ok = 0;
318 fprintf(stderr, "\n*** fromint failed\n");
319 fprintf(stderr, "*** group: %s\n", v[0].buf);
320 showmp("x", x, 16); if (ir) fprintf(stderr, "*** should have failed\n");
321 else { show(g, "expected", r); show(g, "computed", c); }
322 }
323 MP_DROP(x); G_DESTROY(g, r); G_DESTROY(g, c);
324 G_DESTROYGROUP(g);
325 assert(mparena_count(MPARENA_GLOBAL) == 0);
326 return (ok);
327}
328
329static int vtoec(dstr *v)
330{
331 group *g = getgroup(v[0].buf);
332 ge *x = getge(g, v[1].buf);
333 int ir = *(int *)v[2].buf;
334 ec *r = (ec *)v[3].buf;
335 int ic;
336 ec c = EC_INIT;
337 int ok = 1;
338 ic = G_TOEC(g, &c, x);
339 if (ir != ic || (!ic && !EC_EQ(r, &c))) {
340 ok = 0;
341 fprintf(stderr, "\n*** toec failed\n");
342 fprintf(stderr, "*** group: %s\n", v[0].buf);
343 show(g, "x", x);
344 if (ir) fprintf(stderr, "*** should have failed\n");
345 else { showec("expected", r); showec("computed", &c); }
346 }
347 G_DESTROY(g, x); EC_DESTROY(&c); EC_DESTROY(r);
348 G_DESTROYGROUP(g);
349 assert(mparena_count(MPARENA_GLOBAL) == 0);
350 return (ok);
351}
352
353static int vfromec(dstr *v)
354{
355 group *g = getgroup(v[0].buf);
356 ec *p = (ec *)v[1].buf;
357 int ir = *(int *)v[2].buf;
358 ge *r = getge(g, v[3].buf);
359 int ic;
360 ge *c = G_CREATE(g);
361 int ok = 1;
362 ic = G_FROMEC(g, c, p);
363 if (ir != ic || (!ic && !G_EQ(g, r, c))) {
364 ok = 0;
365 fprintf(stderr, "\n*** fromec failed\n");
366 fprintf(stderr, "*** group: %s\n", v[0].buf);
367 showec("p", p); if (ir) fprintf(stderr, "*** should have failed\n");
368 else { show(g, "expected", r); show(g, "computed", c); }
369 }
370 EC_DESTROY(p); G_DESTROY(g, r); G_DESTROY(g, c);
371 G_DESTROYGROUP(g);
372 assert(mparena_count(MPARENA_GLOBAL) == 0);
373 return (ok);
374}
375
376static int vtobuf(dstr *v)
377{
378 group *g = getgroup(v[0].buf);
379 ge *x = getge(g, v[1].buf);
380 int ir = *(int *)v[2].buf;
381 dstr c = DSTR_INIT;
382 int ic;
383 buf b;
384 int ok = 1;
385
386 dstr_ensure(&c, v[3].len);
387 buf_init(&b, c.buf, v[3].len);
388 ic = G_TOBUF(g, &b, x);
389 c.len = BLEN(&b);
390 if (ic != ir || (!ic && (c.len != v[3].len ||
391 memcmp(c.buf, v[3].buf, c.len)))) {
392 ok = 0;
393 fprintf(stderr, "*** tobuf failed\n");
394 fprintf(stderr, "*** group: %s\n", v[0].buf);
395 show(g, "x", x);
396 if (ir) fprintf(stderr, "*** expected failure\n");
397 else {
398 fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
399 fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
400 fputc('\n', stderr);
401 }
402 }
403 G_DESTROY(g, x); dstr_destroy(&c);
404 G_DESTROYGROUP(g);
405 assert(mparena_count(MPARENA_GLOBAL) == 0);
406 return (ok);
407}
408
409static int vfrombuf(dstr *v)
410{
411 group *g = getgroup(v[0].buf);
412 int ir = *(int *)v[2].buf;
413 ge *r = getge(g, v[3].buf);
414 int ic;
415 ge *c = G_CREATE(g);
416 buf b;
417 int ok = 1;
418
419 buf_init(&b, v[1].buf, v[1].len);
420 ic = G_FROMBUF(g, &b, c);
421 if ((ic < 0) != (ir < 0) || (ir >= 0 &&
422 (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
423 ok = 0;
424 fprintf(stderr, "*** frombuf failed\n");
425 fprintf(stderr, "*** group: %s\n", v[0].buf);
426 fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
427 fputc('\n', stderr);
428 if (ir < 0) fprintf(stderr, "*** expected failure\n");
429 else {
430 show(g, "expected", r); show(g, "computed", c);
431 fprintf(stderr, "*** expected used = %d\n", ir);
432 fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
433 }
434 }
435 G_DESTROY(g, r); G_DESTROY(g, c);
436 G_DESTROYGROUP(g);
437 assert(mparena_count(MPARENA_GLOBAL) == 0);
438 return (ok);
439}
440
0f3faccd 441static int vtoraw(dstr *v)
442{
443 group *g = getgroup(v[0].buf);
444 ge *x = getge(g, v[1].buf);
445 int ir = *(int *)v[2].buf;
446 dstr c = DSTR_INIT;
447 int ic;
448 buf b;
449 int ok = 1;
450
451 dstr_ensure(&c, v[3].len);
452 buf_init(&b, c.buf, v[3].len);
453 ic = G_TORAW(g, &b, x);
454 c.len = BLEN(&b);
455 if (ic != ir || (!ic && (c.len != v[3].len ||
456 memcmp(c.buf, v[3].buf, c.len)))) {
457 ok = 0;
458 fprintf(stderr, "*** toraw failed\n");
459 fprintf(stderr, "*** group: %s\n", v[0].buf);
460 show(g, "x", x);
461 if (ir) fprintf(stderr, "*** expected failure\n");
462 else {
463 fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
464 fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
465 fputc('\n', stderr);
466 }
467 }
468 G_DESTROY(g, x); dstr_destroy(&c);
469 G_DESTROYGROUP(g);
470 assert(mparena_count(MPARENA_GLOBAL) == 0);
471 return (ok);
472}
473
474static int vfromraw(dstr *v)
475{
476 group *g = getgroup(v[0].buf);
477 int ir = *(int *)v[2].buf;
478 ge *r = getge(g, v[3].buf);
479 int ic;
480 ge *c = G_CREATE(g);
481 buf b;
482 int ok = 1;
483
484 buf_init(&b, v[1].buf, v[1].len);
485 ic = G_FROMRAW(g, &b, c);
486 if ((ic < 0) != (ir < 0) || (ir >= 0 &&
487 (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
488 ok = 0;
489 fprintf(stderr, "*** fromraw failed\n");
490 fprintf(stderr, "*** group: %s\n", v[0].buf);
491 fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
492 fputc('\n', stderr);
493 if (ir < 0) fprintf(stderr, "*** expected failure\n");
494 else {
495 show(g, "expected", r); show(g, "computed", c);
496 fprintf(stderr, "*** expected used = %d\n", ir);
497 fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
498 }
499 }
500 G_DESTROY(g, r); G_DESTROY(g, c);
501 G_DESTROYGROUP(g);
502 assert(mparena_count(MPARENA_GLOBAL) == 0);
503 return (ok);
504}
505
34e4f738 506static const test_chunk tests[] = {
507 { "check", vcheck, { &type_string, &type_string } },
508 { "checkelt", vcheckelt, { &type_string, &type_string, &type_int } },
509 { "mul", vmul, { &type_string, &type_string,
510 &type_string, &type_string } },
511 { "sqr", vsqr, { &type_string, &type_string,
512 &type_string } },
513 { "inv", vinv, { &type_string, &type_string,
514 &type_string } },
515 { "div", vdiv, { &type_string, &type_string,
516 &type_string, &type_string } },
517 { "exp", vexp, { &type_string, &type_string,
518 &type_mp, &type_string } },
519 { "mexp-1", vmexp1, { &type_string,
520 &type_string, &type_mp,
521 &type_string } },
522 { "mexp-2", vmexp2, { &type_string,
523 &type_string, &type_mp,
524 &type_string, &type_mp,
525 &type_string } },
526 { "mexp-3", vmexp3, { &type_string,
527 &type_string, &type_mp,
528 &type_string, &type_mp,
529 &type_string, &type_mp,
530 &type_string } },
531 { "mexp-4", vmexp4, { &type_string,
532 &type_string, &type_mp,
533 &type_string, &type_mp,
534 &type_string, &type_mp,
535 &type_string, &type_mp,
536 &type_string } },
537 { "toint", vtoint, { &type_string, &type_string,
538 &type_int, &type_mp } },
539 { "fromint", vfromint, { &type_string, &type_mp,
540 &type_int, &type_string } },
541 { "toec", vtoec, { &type_string, &type_string,
542 &type_int, &type_ec } },
543 { "fromec", vfromec, { &type_string, &type_ec,
544 &type_int, &type_string } },
545 { "tobuf", vtobuf, { &type_string, &type_string,
546 &type_int, &type_hex } },
547 { "frombuf", vfrombuf, { &type_string, &type_hex,
548 &type_int, &type_string } },
0f3faccd 549 { "toraw", vtoraw, { &type_string, &type_string,
550 &type_int, &type_hex } },
551 { "fromraw", vfromraw, { &type_string, &type_hex,
552 &type_int, &type_string } },
34e4f738 553 { 0 }
554};
555
556int main(int argc, char *argv[])
557{
558 sub_init();
559 test_run(argc, argv, tests, SRCDIR "/tests/group");
560 return (0);
561}
562
563/*----- That's all, folks -------------------------------------------------*/