X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/c65df27983057ec76ed0e72bb370f9a5ae7dad28..38b901110909d19388502b487f0529514cf853ff:/utils/ecptdecompress.c diff --git a/utils/ecptdecompress.c b/utils/ecptdecompress.c new file mode 100644 index 00000000..dcfdcbde --- /dev/null +++ b/utils/ecptdecompress.c @@ -0,0 +1,137 @@ +#include +#include +#include + +#include +#include +#include + +#include "ec.h" +#include "mp.h" +#include "rand.h" + +static void puthex(const char *name, mp *x, size_t n) +{ + dstr d = DSTR_INIT; + hex_ctx hc; + char *p; + + if (!n) n = mp_octets(x); + p = xmalloc(n); + hex_init(&hc); + hc.indent = ""; + hc.maxline = 0; + mp_storeb(x, p, n); + hex_encode(&hc, p, n, &d); + hex_encode(&hc, 0, 0, &d); + printf(" %s 0x", name); + dstr_write(&d, stdout); + putchar('\n'); + dstr_destroy(&d); + xfree(p); +} + +int main(int argc, char *argv[]) +{ + ec_curve *c; + ec_info ei; + ec pt = EC_INIT; + qd_parse qd; + hex_ctx hc; + dstr d = DSTR_INIT; + size_t n; + octet *p; + mp *x, *y = 0, *yy = 0; + const char *err; + + qd.p = argv[1]; + qd.e = 0; + if ((c = ec_curveparse(&qd)) == 0 || !qd_eofp(&qd)) { + fprintf(stderr, "bad curve: %s\n", qd.e); + exit(1); + } + n = c->f->noctets; + + ei.c = c; + ei.r = mp_readstring(MP_NEW, argv[2], 0, 0); + ei.h = mp_readstring(MP_NEW, argv[3], 0, 0); + + EC_CREATE(&ei.g); + hex_init(&hc); + hex_decode(&hc, argv[4], strlen(argv[4]), &d); + hex_decode(&hc, 0, 0, &d); + p = (octet *)d.buf; + if (p[0] == 0) { + EC_SETINF(&ei.g); + } else { + if (d.len < n + 1) { + fprintf(stderr, "missing x\n"); + exit(1); + } + x = mp_loadb(MP_NEW, p + 1, n); + if (p[0] & 0x04) { + if (d.len < 2 * n + 1) { + fprintf(stderr, "missing y\n"); + exit(1); + } + y = mp_loadb(MP_NEW, p + n + 1, n); + } + if (p[0] & 0x02) { + if (!EC_FIND(c, &pt, x)) { + fprintf(stderr, "no matching y\n"); + exit(1); + } + yy = MP_COPY(pt.y); + ec_destroy(&pt); + switch (F_TYPE(c->f)) { + case FTY_PRIME: + if (!MP_ISODD(yy) != !(p[0] & 1)) + yy = mp_sub(yy, c->f->m, yy); + break; + case FTY_BINARY: + if (MP_ISZERO(x)) + yy = F_SQRT(c->f, MP_NEW, c->b); + else { + mp *xx = F_SQR(c->f, MP_NEW, x); + mp *b = F_MUL(c->f, MP_NEW, xx, c->a); + mp *xxx = F_MUL(c->f, MP_NEW, xx, x); + b = F_ADD(c->f, b, b, xxx); + b = F_ADD(c->f, b, b, c->b); + xx = F_INV(c->f, xx, xx); + b = F_MUL(c->f, b, b, xx); + mp_drop(xxx); + mp_drop(xx); + yy = F_QUADSOLVE(c->f, MP_NEW, b); + if (!MP_ISODD(yy) != !(p[0] & 1)) + yy = mp_add(yy, yy, MP_ONE); + yy = F_MUL(c->f, yy, yy, x); + } + break; + default: + abort(); + } + } + if (y && yy && !MP_EQ(y, yy)) { + fprintf(stderr, "inconsistent answers\n"); + exit(1); + } + ei.g.x = x; + ei.g.y = mp_copy(y ? y : yy); + mp_drop(y); mp_drop(yy); + } + + if ((err = ec_checkinfo(&ei, &rand_global)) != 0) { + fprintf(stderr, "bad curve: %s\n", err); + exit(0); + } + puthex("p", ei.c->f->m, 0); + puthex("a", ei.c->a, c->f->noctets); + puthex("b", ei.c->b, c->f->noctets); + puthex("r", ei.r, c->f->noctets); + printf(" h "); mp_writefile(ei.h, stdout, 10); putchar('\n'); + puthex("gx", ei.g.x, c->f->noctets); + puthex("gy", ei.g.y, c->f->noctets); + ec_freeinfo(&ei); + dstr_destroy(&d); + return (0); +}