progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / utils / ecptdecompress.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4
5 #include <mLib/alloc.h>
6 #include <mLib/hex.h>
7 #include <mLib/dstr.h>
8 #include <mLib/macros.h>
9
10 #include "ec.h"
11 #include "mp.h"
12 #include "rand.h"
13 #include "field-guts.h"
14
15 static void puthex(const char *name, mp *x, size_t n)
16 {
17 dstr d = DSTR_INIT;
18 hex_ctx hc;
19 char *p;
20
21 if (!n) n = mp_octets(x);
22 p = xmalloc(n);
23 hex_init(&hc);
24 hc.indent = "";
25 hc.maxline = 0;
26 mp_storeb(x, p, n);
27 hex_encode(&hc, p, n, &d);
28 hex_encode(&hc, 0, 0, &d);
29 printf(" %s 0x", name);
30 dstr_write(&d, stdout);
31 putchar('\n');
32 dstr_destroy(&d);
33 xfree(p);
34 }
35
36 int main(int argc, char *argv[])
37 {
38 ec_curve *c;
39 ec_info ei;
40 ec pt = EC_INIT;
41 qd_parse qd;
42 hex_ctx hc;
43 dstr d = DSTR_INIT;
44 size_t n;
45 octet *p;
46 mp *x, *y = 0, *yy = 0;
47 mp *t = MP_NEW;
48 const char *err;
49
50 qd.p = argv[1];
51 qd.e = 0;
52 if ((c = ec_curveparse(&qd)) == 0 || !qd_eofp(&qd)) {
53 fprintf(stderr, "bad curve: %s\n", qd.e);
54 exit(1);
55 }
56 n = c->f->noctets;
57
58 ei.c = c;
59 ei.r = mp_readstring(MP_NEW, argv[2], 0, 0);
60 ei.h = mp_readstring(MP_NEW, argv[3], 0, 0);
61
62 EC_CREATE(&ei.g);
63 hex_init(&hc);
64 hex_decode(&hc, argv[4], strlen(argv[4]), &d);
65 hex_decode(&hc, 0, 0, &d);
66 p = (octet *)d.buf;
67 if (p[0] == 0) {
68 EC_SETINF(&ei.g);
69 } else {
70 if (d.len < n + 1) {
71 fprintf(stderr, "missing x\n");
72 exit(1);
73 }
74 x = mp_loadb(MP_NEW, p + 1, n);
75 if (p[0] & 0x04) {
76 if (d.len < 2 * n + 1) {
77 fprintf(stderr, "missing y\n");
78 exit(1);
79 }
80 y = mp_loadb(MP_NEW, p + n + 1, n);
81 }
82 if (p[0] & 0x02) {
83 if (!ec_find(c, &pt, x)) {
84 fprintf(stderr, "no matching y\n");
85 exit(1);
86 }
87 yy = MP_COPY(pt.y);
88 ec_destroy(&pt);
89 switch (F_TYPE(c->f)) {
90 case FTY_PRIME:
91 if (!MP_ODDP(yy) != !(p[0] & 1))
92 yy = mp_sub(yy, c->f->m, yy);
93 break;
94 case FTY_BINARY:
95 if (MP_ZEROP(x))
96 yy = F_SQRT(c->f, MP_NEW, c->b);
97 else {
98 mp *xin = F_IN(c->f, MP_NEW, x);
99 mp *xx = F_SQR(c->f, MP_NEW, xin);
100 mp *b = F_MUL(c->f, MP_NEW, xx, c->a);
101 mp *xxx = F_MUL(c->f, MP_NEW, xx, xin);
102 b = F_ADD(c->f, b, b, xxx);
103 b = F_ADD(c->f, b, b, c->b);
104 xx = F_INV(c->f, xx, xx);
105 b = F_MUL(c->f, b, b, xx);
106 mp_drop(xxx);
107 yy = F_QUADSOLVE(c->f, MP_NEW, b);
108 xx = F_OUT(c->f, xx, yy);
109 if (!MP_ODDP(xx) != !(p[0] & 1))
110 yy = gf_add(yy, yy, MP_ONE);
111 yy = F_MUL(c->f, yy, yy, xin);
112 yy = F_OUT(c->f, yy, yy);
113 mp_drop(xin);
114 mp_drop(xx);
115 }
116 break;
117 default:
118 abort();
119 }
120 }
121 if (y && yy && !MP_EQ(y, yy)) {
122 fprintf(stderr, "inconsistent answers\n");
123 exit(1);
124 }
125 ei.g.x = x;
126 ei.g.y = mp_copy(y ? y : yy);
127 mp_drop(y); mp_drop(yy);
128 }
129
130 if ((err = ec_checkinfo(&ei, &rand_global)) != 0)
131 fprintf(stderr, "bad curve: %s\n", err);
132 puthex("p", ei.c->f->m, 0);
133 if (STRCMP(F_NAME(ei.c->f), ==, "binnorm")) {
134 fctx_binnorm *fc = (fctx_binnorm *)ei.c->f;
135 puthex("beta", fc->ntop.r[fc->ntop.n - 1], c->f->noctets);
136 }
137 t = F_OUT(ei.c->f, t, ei.c->a); puthex("a", t, c->f->noctets);
138 t = F_OUT(ei.c->f, t, ei.c->b); puthex("b", t, c->f->noctets);
139 puthex("r", ei.r, c->f->noctets);
140 printf(" h "); mp_writefile(ei.h, stdout, 10); putchar('\n');
141 puthex("gx", ei.g.x, c->f->noctets);
142 puthex("gy", ei.g.y, c->f->noctets);
143 ec_freeinfo(&ei);
144 mp_drop(t);
145 dstr_destroy(&d);
146 return (0);
147 }