X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/ddd4720bd8a7e04bb37ba6825b46f1bbdce9d3e7..ef5ac0d93e594e8fdff9cf446dad39f1e7c811e3:/ec.c diff --git a/ec.c b/ec.c index b958d53..04bd482 100644 --- a/ec.c +++ b/ec.c @@ -186,13 +186,17 @@ static PyObject *ecpt_pymul(PyObject *x, PyObject *y) ec zz = EC_INIT; if (ECPT_PYCHECK(x)) { PyObject *t; t = x; x = y; y = t; } - if (!ECPT_PYCHECK(y) || (xx = tomp(x)) == 0) RETURN_NOTIMPL; + if (!ECPT_PYCHECK(y)) RETURN_NOTIMPL; + if (FE_PYCHECK(x) && FE_F(x)->ops->ty == FTY_PRIME) + xx = F_OUT(FE_F(x), MP_NEW, FE_X(x)); + else if ((xx = implicitmp(x)) == 0) + RETURN_NOTIMPL; ec_imul(ECPT_C(y), &zz, ECPT_P(y), xx); MP_DROP(xx); return (ecpt_pywrap(ECPT_COBJ(y), &zz)); } -static long ecpt_pyhash(PyObject *me) +static Py_hash_t ecpt_pyhash(PyObject *me) { uint32 h; ec p = EC_INIT; @@ -251,10 +255,10 @@ static PyObject *epmeth_tobuf(PyObject *me) else n = mp_octets(p.x) + mp_octets(p.y) + 6; rc = bytestring_pywrap(0, n); - buf_init(&b, PyString_AS_STRING(rc), n); + buf_init(&b, BIN_PTR(rc), n); buf_putec(&b, &p); assert(BOK(&b)); - _PyString_Resize(&rc, BLEN(&b)); + BIN_SETLEN(rc, BLEN(&b)); EC_DESTROY(&p); return (rc); } @@ -270,12 +274,12 @@ static PyObject *epmeth_toraw(PyObject *me) len = c->f->noctets * 2 + 1; rc = bytestring_pywrap(0, len); - p = PyString_AS_STRING(rc); + p = BIN_PTR(rc); buf_init(&b, p, len); EC_OUT(c, &pp, ECPT_P(me)); ec_putraw(c, &b, &pp); EC_DESTROY(&pp); - _PyString_Resize(&rc, BLEN(&b)); + BIN_SETLEN(rc, BLEN(&b)); return (rc); } @@ -295,7 +299,7 @@ static PyObject *epmeth_ec2osp(PyObject *me, PyObject *arg, PyObject *kw) return (0); len = c->f->noctets * 2 + 1; rc = bytestring_pywrap(0, len); - p = PyString_AS_STRING(rc); + p = BIN_PTR(rc); buf_init(&b, p, len); EC_OUT(c, &pp, ECPT_P(me)); if (ec_ec2osp(c, f, &b, &pp)) { @@ -303,21 +307,20 @@ static PyObject *epmeth_ec2osp(PyObject *me, PyObject *arg, PyObject *kw) VALERR("invalid flags"); } EC_DESTROY(&pp); - _PyString_Resize(&rc, BLEN(&b)); + BIN_SETLEN(rc, BLEN(&b)); end: return (rc); } static PyObject *epmeth_frombuf(PyObject *me, PyObject *arg) { + struct bin in; buf b; - char *p; - Py_ssize_t sz; PyObject *rc = 0; ec pp = EC_INIT; - if (!PyArg_ParseTuple(arg, "s#:frombuf", &p, &sz)) goto end; - buf_init(&b, p, sz); + if (!PyArg_ParseTuple(arg, "O&:frombuf", convbin, &in)) goto end; + buf_init(&b, (/*unconst*/ void *)in.p, in.sz); if (buf_getec(&b, &pp)) VALERR("malformed data"); rc = Py_BuildValue("(NN)", ecpt_pywrapout(me, &pp), bytestring_pywrapbuf(&b)); @@ -330,11 +333,15 @@ static PyObject *epmeth_parse(PyObject *me, PyObject *arg) char *p; qd_parse qd; PyObject *rc = 0; + int paren; ec pp = EC_INIT; if (!PyArg_ParseTuple(arg, "s:parse", &p)) goto end; qd.p = p; qd.e = 0; + qd_skipspc(&qd); paren = qd_delim(&qd, '('); if (!ec_ptparse(&qd, &pp)) VALERR(qd.e); + qd_skipspc(&qd); if (paren && !qd_delim(&qd, ')')) + { EC_DESTROY(&pp); VALERR("missing `)'"); } rc = Py_BuildValue("(Ns)", ecpt_pywrapout(me, &pp), qd.p); end: return (rc); @@ -342,15 +349,14 @@ end: static PyObject *epmeth_fromraw(PyObject *me, PyObject *arg) { - char *p; - Py_ssize_t len; + struct bin in; buf b; PyObject *rc = 0; ec_curve *cc; ec pp = EC_INIT; - if (!PyArg_ParseTuple(arg, "s#:fromraw", &me, &p, &len)) return (0); - buf_init(&b, p, len); + if (!PyArg_ParseTuple(arg, "O&:fromraw", convbin, &in)) return (0); + buf_init(&b, (/*unconst*/ void *)in.p, in.sz); cc = ECCURVE_C(me); if (ec_getraw(cc, &b, &pp)) VALERR("bad point"); @@ -362,8 +368,7 @@ end: static PyObject *epmeth_os2ecp(PyObject *me, PyObject *arg, PyObject *kw) { - char *p; - Py_ssize_t len; + struct bin in; buf b; PyObject *rc = 0; ec_curve *cc; @@ -371,10 +376,10 @@ static PyObject *epmeth_os2ecp(PyObject *me, PyObject *arg, PyObject *kw) ec pp = EC_INIT; static const char *const kwlist[] = { "buf", "flags", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:os2ecp", KWLIST, - &p, &len, convuint, &f)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:os2ecp", KWLIST, + convbin, &in, convuint, &f)) return (0); - buf_init(&b, p, len); + buf_init(&b, (/*unconst*/ void *)in.p, in.sz); cc = ECCURVE_C(me); if (ec_os2ecp(cc, f, &b, &pp)) VALERR("bad point"); EC_IN(cc, &pp, &pp); @@ -466,7 +471,7 @@ static PyObject *epget__z(PyObject *me, void *hunoz) static mp *coord_in(field *f, PyObject *x) { mp *xx; - if (FE_PYCHECK(x) && FE_F(x) == f) + if (FE_PYCHECK(x) && (FE_F(x) == f || field_samep(FE_F(x), f))) return (MP_COPY(FE_X(x))); else if ((xx = getmp(x)) == 0) return (0); @@ -508,11 +513,10 @@ end: static int ecptxl_1(ec_curve *c, ec *p, PyObject *x) { int rc = -1; - PyObject *y = 0, *z = 0, *t = 0; + PyObject *y = 0, *z = 0, *t = 0, *u = 0; mp *xx = 0; - const void *q; - int n; qd_parse qd; + int paren; Py_XINCREF(x); if (!x || x == Py_None) @@ -520,38 +524,44 @@ static int ecptxl_1(ec_curve *c, ec *p, PyObject *x) else if (ECPT_PYCHECK(x)) { getecptout(p, x); goto fix; - } else if (PyString_Check(x)) { - if (PyObject_AsReadBuffer(x, &q, &n)) - goto end; - qd.p = q; - qd.e = 0; - if (!ec_ptparse(&qd, p)) - VALERR(qd.e); + } else if (TEXT_CHECK(x)) { + qd.p = TEXT_PTR(x); qd.e = 0; + qd_skipspc(&qd); paren = qd_delim(&qd, '('); + if (!ec_ptparse(&qd, p)) VALERR(qd.e); + qd_skipspc(&qd); if (paren && !qd_delim(&qd, ')')) + { EC_DESTROY(p); VALERR("missing `)'"); } + qd_skipspc(&qd); if (!qd_eofp(&qd)) VALERR("junk at eof"); goto fix; } else if (c && (xx = tomp(x)) != 0) { xx = F_IN(c->f, xx, xx); if (!EC_FIND(c, p, xx)) VALERR("not on the curve"); - } else if (PySequence_Check(x)) { - t = x; x = 0; - n = PySequence_Size(t); if (n < 0) goto end; - if (n != 2 && (n != 3 || !c)) - TYERR("want sequence of two or three items"); - if ((x = PySequence_GetItem(t, 0)) == 0 || - (y = PySequence_GetItem(t, 1)) == 0 || - (n == 3 && (z = PySequence_GetItem(t, 2)) == 0)) - goto end; - rc = (n == 2) ? ecptxl_2(c, p, x, y) : ecptxl_3(c, p, x, y, z); + } else if ((t = PyObject_GetIter(x)) != 0) { + Py_DECREF(x); + x = PyIter_Next(t); if (!x) goto enditer; + y = PyIter_Next(t); if (!y) goto enditer; + z = PyIter_Next(t); if (!z && PyErr_Occurred()) goto end; + if (z) { + u = PyIter_Next(t); + if (u) goto enditer; + else if (PyErr_Occurred()) goto end; + } + rc = !z ? ecptxl_2(c, p, x, y) : ecptxl_3(c, p, x, y, z); goto end; - } else + } else { + PyErr_Clear(); TYERR("can't convert to curve point"); + } goto ok; +enditer: + if (PyErr_Occurred()) goto end; + TYERR("expected sequence of 2 or 3 items"); fix: if (c) EC_IN(c, p, p); ok: rc = 0; end: - Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(z); Py_XDECREF(t); + Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(z); Py_XDECREF(t); Py_XDECREF(u); mp_drop(xx); return (rc); } @@ -595,6 +605,7 @@ end: return (rc); } +#ifdef PY2 static PyObject *ecpt_pylong(PyObject *me) { ec p = EC_INIT; @@ -606,6 +617,7 @@ end: EC_DESTROY(&p); return (rc); } +#endif static PyObject *ecpt_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { @@ -645,7 +657,9 @@ static const PyNumberMethods ecpt_pynumber = { 0, /* @nb_add@ */ 0, /* @nb_subtract@ */ 0, /* @nb_multiply@ */ +#ifdef PY2 0, /* @nb_divide@ */ +#endif 0, /* @nb_remainder@ */ 0, /* @nb_divmod@ */ 0, /* @nb_power@ */ @@ -659,17 +673,23 @@ static const PyNumberMethods ecpt_pynumber = { 0, /* @nb_and@ */ 0, /* @nb_xor@ */ 0, /* @nb_or@ */ +#ifdef PY2 0, /* @nb_coerce@ */ +#endif ecpt_pyint, /* @nb_int@ */ - ecpt_pylong, /* @nb_long@ */ + PY23(ecpt_pylong, 0), /* @nb_long@ */ 0, /* @nb_float@ */ +#ifdef PY2 0, /* @nb_oct@ */ 0, /* @nb_hex@ */ +#endif 0, /* @nb_inplace_add@ */ 0, /* @nb_inplace_subtract@ */ 0, /* @nb_inplace_multiply@ */ +#ifdef PY2 0, /* @nb_inplace_divide@ */ +#endif 0, /* @nb_inplace_remainder@ */ 0, /* @nb_inplace_power@ */ 0, /* @nb_inplace_lshift@ */ @@ -685,7 +705,7 @@ static const PyNumberMethods ecpt_pynumber = { }; static const PyTypeObject ecpt_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECPt", /* @tp_name@ */ sizeof(ecpt_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -737,7 +757,7 @@ static const PyTypeObject ecpt_pytype_skel = { static const PyMemberDef ecpt_pymembers[] = { #define MEMBERSTRUCT ecpt_pyobj - MEMRNM(curve, T_OBJECT, ob_type, READONLY, + MEMRNM(curve, T_OBJECT, PY23(ob_type, ob_base.ob_type), READONLY, "P.curve -> elliptic curve containing P") #undef MEMBERSTRUCT { 0 } @@ -771,7 +791,9 @@ static const PyNumberMethods ecptcurve_pynumber = { ecpt_pyadd, /* @nb_add@ */ ecpt_pysub, /* @nb_subtract@ */ ecpt_pymul, /* @nb_multiply@ */ +#ifdef PY2 0, /* @nb_divide@ */ +#endif 0, /* @nb_remainder@ */ 0, /* @nb_divmod@ */ 0, /* @nb_power@ */ @@ -785,12 +807,16 @@ static const PyNumberMethods ecptcurve_pynumber = { 0, /* @nb_and@ */ 0, /* @nb_xor@ */ 0, /* @nb_or@ */ +#ifdef PY2 0, /* @nb_coerce@ */ +#endif 0, /* @nb_int@ */ 0, /* @nb_long@ */ 0, /* @nb_float@ */ +#ifdef PY2 0, /* @nb_oct@ */ 0, /* @nb_hex@ */ +#endif 0, /* @nb_inplace_add@ */ 0, /* @nb_inplace_subtract@ */ @@ -811,7 +837,7 @@ static const PyNumberMethods ecptcurve_pynumber = { }; static const PyTypeObject ecptcurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECPtCurve", /* @tp_name@ */ sizeof(ecpt_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -892,7 +918,7 @@ static int ecmmul_fill(void *pp, PyObject *me, PyObject *x, PyObject *m) return (0); } -static PyObject *ecmmul_exp(PyObject *me, void *pp, int n) +static PyObject *ecmmul_exp(PyObject *me, void *pp, size_t n) { ec p = EC_INIT; ec_immul(ECCURVE_C(me), &p, pp, n); @@ -965,7 +991,7 @@ static PyObject *ecmeth_parse(PyObject *me, PyObject *arg) if (!PyArg_ParseTuple(arg, "s:parse", &p)) goto end; qd.p = p; qd.e = 0; if ((c = ec_curveparse(&qd)) == 0) VALERR(qd.e); - rc = eccurve_pywrap(0, c); + rc = Py_BuildValue("(Ns)", eccurve_pywrap(0, c), qd.p); end: return (rc); } @@ -1034,7 +1060,7 @@ end: } static PyObject *ecget_name(PyObject *me, void *hunoz) - { return (PyString_FromString(EC_NAME(ECCURVE_C(me)))); } + { return (TEXT_FROMSTR(EC_NAME(ECCURVE_C(me)))); } static PyObject *ecget_a(PyObject *me, void *hunoz) { return (fe_pywrap(ECCURVE_FOBJ(me), MP_COPY(ECCURVE_C(me)->a))); } @@ -1070,7 +1096,7 @@ static const PyMethodDef eccurve_pymethods[] = { }; static const PyTypeObject eccurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1124,7 +1150,7 @@ static PyObject *ecprimecurve_pynew(PyTypeObject *ty, } static const PyTypeObject ecprimecurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECPrimeCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1153,7 +1179,7 @@ static const PyTypeObject ecprimecurve_pytype_skel = { 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ - eccurve_pyrichcompare, /* @tp_richcompare@ */ + 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ @@ -1179,7 +1205,7 @@ static PyObject *ecprimeprojcurve_pynew(PyTypeObject *ty, } static const PyTypeObject ecprimeprojcurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECPrimeProjCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1208,7 +1234,7 @@ static const PyTypeObject ecprimeprojcurve_pytype_skel = { 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ - eccurve_pyrichcompare, /* @tp_richcompare@ */ + 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ @@ -1234,7 +1260,7 @@ static PyObject *ecbincurve_pynew(PyTypeObject *ty, } static const PyTypeObject ecbincurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECBinCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1263,7 +1289,7 @@ static const PyTypeObject ecbincurve_pytype_skel = { 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ - eccurve_pyrichcompare, /* @tp_richcompare@ */ + 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ @@ -1289,7 +1315,7 @@ static PyObject *ecbinprojcurve_pynew(PyTypeObject *ty, } static const PyTypeObject ecbinprojcurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECBinProjCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1318,7 +1344,7 @@ static const PyTypeObject ecbinprojcurve_pytype_skel = { 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ - eccurve_pyrichcompare, /* @tp_richcompare@ */ + 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ @@ -1339,8 +1365,6 @@ static const PyTypeObject ecbinprojcurve_pytype_skel = { /*----- Curve info --------------------------------------------------------*/ -static int ncurves = -1; - void ecinfo_copy(ec_info *eic, const ec_info *ei) { eic->c = eccurve_copy(ei->c); @@ -1414,20 +1438,6 @@ end: return (rc); } -static PyObject *eimeth__curven(PyObject *me, PyObject *arg) -{ - int i; - ec_info ei; - PyObject *rc = 0; - - if (!PyArg_ParseTuple(arg, "i:_curven", &i)) goto end; - if (i < 0 || i >= ncurves) VALERR("curve index out of range"); - ec_infofromdata(&ei, ectab[i].data); - rc = ecinfo_pywrap(&ei); -end: - return (rc); -} - static PyObject *ecinfo_pyrichcompare(PyObject *x, PyObject *y, int op) { int b = ec_sameinfop(ECINFO_EI(x), ECINFO_EI(y)); @@ -1488,13 +1498,12 @@ static const PyMethodDef ecinfo_pymethods[] = { #define METHNAME(name) eimeth_##name KWMETH(check, "I.check([rng = rand]) -> None") SMTH (parse, "parse(STR) -> (I, REST)") - SMTH (_curven, "_curven(N) -> I") #undef METHNAME { 0 } }; static const PyTypeObject ecinfo_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECInfo", /* @tp_name@ */ sizeof(ecinfo_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1543,6 +1552,12 @@ static const PyTypeObject ecinfo_pytype_skel = { /*----- Setup -------------------------------------------------------------*/ +static const struct nameval consts[] = { + CONST(EC_XONLY), CONST(EC_YBIT), CONST(EC_LSB), + CONST(EC_CMPR), CONST(EC_EXPLY), CONST(EC_SORT), + { 0 } +}; + void ec_pyinit(void) { INITTYPE(ecpt, root); @@ -1555,29 +1570,25 @@ void ec_pyinit(void) INITTYPE(ecinfo, root); } -static PyObject *namedcurves(void) +static const char *ec_namefn(const void *p) + { const ecentry *ec = p; return (ec->name); } + +static int ec_ixfn(const void *p) { - int i, j; - const char *p; - PyObject *d, *c; - - d = PyDict_New(); - for (i = 0; ectab[i].name; i++) { - p = ectab[i].name; - for (j = 0; j < i; j++) { - if (ectab[i].data == ectab[j].data) { - c = PyDict_GetItemString(d, (/*unconst*/ char *)ectab[j].name); - Py_INCREF(c); - goto found; - } - } - c = PyInt_FromLong(i); - found: - PyDict_SetItemString(d, (/*unconst*/ char *)p, c); - Py_DECREF(c); - } - ncurves = i; - return (d); + const ecentry *ec = p; + int i; + + for (i = 0; ectab[i].name; i++) + if (ectab[i].data == ec->data) return (i); + return (-1); +} + +static PyObject *ec_valfn(int i) +{ + ec_info ei; + + ec_infofromdata(&ei, ectab[i].data); + return (ecinfo_pywrap(&ei)); } void ec_pyinsert(PyObject *mod) @@ -1590,7 +1601,9 @@ void ec_pyinsert(PyObject *mod) INSERT("ECBinCurve", ecbincurve_pytype); INSERT("ECBinProjCurve", ecbinprojcurve_pytype); INSERT("ECInfo", ecinfo_pytype); - INSERT("_eccurves", namedcurves()); + INSERT("eccurves", make_grouptab(ectab, sizeof(*ectab), + ec_namefn, ec_ixfn, ec_valfn)); + setconstants(mod, consts); } /*----- That's all, folks -------------------------------------------------*/