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