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