Merge branch 'master' of git+ssh://metalzone.distorted.org.uk/~mdw/public-git/catacomb/
[u/mdw/catacomb] / utils / ecptdecompress.c
CommitLineData
38b90111 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"
389d8222 12#include "field-guts.h"
38b90111 13
14static 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
35int 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;
389d8222 46 mp *t = MP_NEW;
38b90111 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) {
389d8222 82 if (!ec_find(c, &pt, x)) {
38b90111 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:
389d8222 90 if (!MP_ODDP(yy) != !(p[0] & 1))
38b90111 91 yy = mp_sub(yy, c->f->m, yy);
92 break;
93 case FTY_BINARY:
389d8222 94 if (MP_ZEROP(x))
38b90111 95 yy = F_SQRT(c->f, MP_NEW, c->b);
96 else {
389d8222 97 mp *xin = F_IN(c->f, MP_NEW, x);
98 mp *xx = F_SQR(c->f, MP_NEW, xin);
38b90111 99 mp *b = F_MUL(c->f, MP_NEW, xx, c->a);
389d8222 100 mp *xxx = F_MUL(c->f, MP_NEW, xx, xin);
38b90111 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);
38b90111 106 yy = F_QUADSOLVE(c->f, MP_NEW, b);
389d8222 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);
38b90111 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
1d7857e7 129 if ((err = ec_checkinfo(&ei, &rand_global)) != 0)
38b90111 130 fprintf(stderr, "bad curve: %s\n", err);
38b90111 131 puthex("p", ei.c->f->m, 0);
389d8222 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);
38b90111 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);
389d8222 143 mp_drop(t);
38b90111 144 dstr_destroy(&d);
145 return (0);
146}