X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/0e29d9164d5cc4e3cafa509cda19de2e025446c1..e2568047e1f83f2ff6095c88d9be4a4d838cd62b:/ec.c diff --git a/ec.c b/ec.c index 9d4d6e7..c9707b7 100644 --- a/ec.c +++ b/ec.c @@ -48,13 +48,13 @@ ec_curve *eccurve_copy(ec_curve *c) return (0); a = F_OUT(f, MP_NEW, c->a); b = F_OUT(f, MP_NEW, c->b); - if (strcmp(EC_NAME(c), "prime") == 0) + if (STRCMP(EC_NAME(c), ==, "prime")) c = ec_prime(f, a, b); - else if (strcmp(EC_NAME(c), "primeproj") == 0) + else if (STRCMP(EC_NAME(c), ==, "primeproj")) c = ec_primeproj(f, a, b); - else if (strcmp(EC_NAME(c), "bin") == 0) + else if (STRCMP(EC_NAME(c), ==, "bin")) c = ec_bin(f, a, b); - else if (strcmp(EC_NAME(c), "binproj") == 0) + else if (STRCMP(EC_NAME(c), ==, "binproj")) c = ec_binproj(f, a, b); else c = 0; @@ -106,7 +106,7 @@ int getecpt(ec_curve *c, ec *d, PyObject *p) { if (toecpt(c, d, p)) { PyErr_Format(PyExc_TypeError, "can't convert %.100s to ecpt", - p->ob_type->tp_name); + Py_TYPE(p)->tp_name); return (-1); } return (0); @@ -188,38 +188,31 @@ static PyObject *ecpt_pymul(PyObject *x, PyObject *y) if (ECPT_PYCHECK(x)) { PyObject *t; t = x; x = y; y = t; } if (!ECPT_PYCHECK(y) || (xx = tomp(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; - buf b; ec p = EC_INIT; - size_t sz = 2*ECPT_C(me)->f->noctets + 1; - octet *q = xmalloc(sz); - h = 0xe0fdd039 + ECPT_C(me)->f->ops->ty; - buf_init(&b, q, sz); - EC_OUT(ECPT_C(me), &p, ECPT_P(me)); - ec_putraw(ECPT_C(me), &b, &p); + getecptout(&p, me); + if (EC_ATINF(&p)) h = 0x81d81a94; + else h = 0xe0fdd039 ^ (2*mphash(p.x)) ^ (3*mphash(p.y)); EC_DESTROY(&p); - xfree(q); - h = unihash_hash(&unihash_global, h, BBASE(&b), BLEN(&b)); - return (h % LONG_MAX); + return (h%LONG_MAX); } static PyObject *ecpt_pyrichcompare(PyObject *x, PyObject *y, int op) { - ec_curve *c; - PyObject *cobj; ec p = EC_INIT, q = EC_INIT; int b; PyObject *rc = 0; - if (ecbinop(x, y, &c, &cobj, &p, &q)) RETURN_NOTIMPL; - EC_OUT(c, &p, &p); - EC_OUT(c, &q, &q); + if (!ECPT_PYCHECK(y)) RETURN_NOTIMPL; + getecptout(&p, x); + getecptout(&q, y); switch (op) { case Py_EQ: b = EC_EQ(&p, &q); break; case Py_NE: b = !EC_EQ(&p, &q); break; @@ -232,44 +225,41 @@ end: return (rc); } -static PyObject *epmeth_oncurvep(PyObject *me, PyObject *arg) +static PyObject *epmeth_oncurvep(PyObject *me) { - if (!PyArg_ParseTuple(arg, ":oncurvep")) return (0); return (getbool(EC_ATINF(ECPT_P(me)) || !EC_CHECK(ECPT_C(me), ECPT_P(me)))); } -static PyObject *epmeth_dbl(PyObject *me, PyObject *arg) +static PyObject *epmeth_dbl(PyObject *me) { ec p = EC_INIT; - if (!PyArg_ParseTuple(arg, ":dbl")) return (0); EC_DBL(ECPT_C(me), &p, ECPT_P(me)); return (ecpt_pywrap(ECPT_COBJ(me), &p)); } -static PyObject *epmeth_tobuf(PyObject *me, PyObject *arg) +static PyObject *epmeth_tobuf(PyObject *me) { buf b; ec p = EC_INIT; PyObject *rc; size_t n; - if (!PyArg_ParseTuple(arg, ":tobuf")) return (0); getecptout(&p, me); if (EC_ATINF(&p)) n = 2; else - n = mp_octets(p.x) + mp_octets(p.y) + 4; + 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); } -static PyObject *epmeth_toraw(PyObject *me, PyObject *arg) +static PyObject *epmeth_toraw(PyObject *me) { buf b; PyObject *rc; @@ -278,15 +268,14 @@ static PyObject *epmeth_toraw(PyObject *me, PyObject *arg) ec pp = EC_INIT; int len; - if (!PyArg_ParseTuple(arg, ":toraw")) 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)); ec_putraw(c, &b, &pp); EC_DESTROY(&pp); - _PyString_Resize(&rc, BLEN(&b)); + BIN_SETLEN(rc, BLEN(&b)); return (rc); } @@ -297,15 +286,16 @@ static PyObject *epmeth_ec2osp(PyObject *me, PyObject *arg, PyObject *kw) char *p; ec_curve *c = ECPT_C(me); ec pp = EC_INIT; - int f = EC_EXPLY; + unsigned f = EC_EXPLY; int len; - char *kwlist[] = { "flags", 0 }; + static const char *const kwlist[] = { "flags", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|i:ectosp", kwlist, &f)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:ec2osp", KWLIST, + convuint, &f)) 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)) { @@ -313,13 +303,82 @@ 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 *epget_curve(PyObject *me, void *hunoz) - { RETURN_OBJ(ECPT_COBJ(me)); } +static PyObject *epmeth_frombuf(PyObject *me, PyObject *arg) +{ + struct bin in; + buf b; + PyObject *rc = 0; + ec pp = EC_INIT; + + 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)); +end: + return (rc); +} + +static PyObject *epmeth_parse(PyObject *me, PyObject *arg) +{ + char *p; + qd_parse qd; + PyObject *rc = 0; + ec pp = EC_INIT; + + if (!PyArg_ParseTuple(arg, "s:parse", &p)) goto end; + qd.p = p; qd.e = 0; + if (!ec_ptparse(&qd, &pp)) VALERR(qd.e); + rc = Py_BuildValue("(Ns)", ecpt_pywrapout(me, &pp), qd.p); +end: + return (rc); +} + +static PyObject *epmeth_fromraw(PyObject *me, PyObject *arg) +{ + struct bin in; + buf b; + PyObject *rc = 0; + ec_curve *cc; + ec pp = EC_INIT; + + 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"); + EC_IN(cc, &pp, &pp); + rc = Py_BuildValue("(NN)", ecpt_pywrap(me, &pp), bytestring_pywrapbuf(&b)); +end: + return (rc); +} + +static PyObject *epmeth_os2ecp(PyObject *me, PyObject *arg, PyObject *kw) +{ + struct bin in; + buf b; + PyObject *rc = 0; + ec_curve *cc; + unsigned f = EC_XONLY | EC_LSB | EC_SORT | EC_EXPLY; + ec pp = EC_INIT; + static const char *const kwlist[] = { "buf", "flags", 0 }; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:os2ecp", KWLIST, + convbin, &in, convuint, &f)) + return (0); + 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); + rc = Py_BuildValue("(NN)", ecpt_pywrap(me, &pp), bytestring_pywrapbuf(&b)); +end: + return (rc); +} static PyObject *epncget_ix(PyObject *me, void *hunoz) { @@ -419,9 +478,9 @@ static int ecptxl_3(ec_curve *c, ec *p, if (!x || !y || !z) TYERR("missing argument"); if (!c) VALERR("internal form with no curve!"); - if ((p->x == coord_in(c->f, x)) == 0 || - (p->y == coord_in(c->f, y)) == 0 || - (z != Py_None && (p->z = coord_in(c->f, z))) == 0) + if ((p->x = coord_in(c->f, x)) == 0 || + (p->y = coord_in(c->f, y)) == 0 || + (z != Py_None && (p->z = coord_in(c->f, z)) == 0)) goto end; if (!p->z) p->z = MP_COPY(c->f->one); /* just in case */ rc = 0; @@ -448,8 +507,7 @@ static int ecptxl_1(ec_curve *c, ec *p, PyObject *x) int rc = -1; PyObject *y = 0, *z = 0, *t = 0; mp *xx = 0; - const void *q; - int n; + Py_ssize_t n; qd_parse qd; Py_XINCREF(x); @@ -458,10 +516,8 @@ 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, 0)) - goto end; - qd.p = q; + } else if (TEXT_CHECK(x)) { + qd.p = TEXT_PTR(x); qd.e = 0; if (!ec_ptparse(&qd, p)) VALERR(qd.e); @@ -471,7 +527,7 @@ static int ecptxl_1(ec_curve *c, ec *p, PyObject *x) if (!EC_FIND(c, p, xx)) VALERR("not on the curve"); } else if (PySequence_Check(x)) { t = x; x = 0; - n = PySequence_Size(t); + 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 || @@ -479,6 +535,7 @@ static int ecptxl_1(ec_curve *c, ec *p, PyObject *x) (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); + goto end; } else TYERR("can't convert to curve point"); goto ok; @@ -507,14 +564,14 @@ static PyObject *ecptnc_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { PyObject *x = 0, *y = 0, *z = 0; ec p = EC_INIT; - char *kwlist[] = { "x", "y", 0 }; + static const char *const kwlist[] = { "x", "y", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|OO:new", kwlist, &x, &y) || + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|OO:new", KWLIST, &x, &y) || ecptxl(0, &p, x, y, z)) goto end; return (ecpt_pywrapout(ty, &p)); end: - EC_DESTROY(&p); + mp_drop(p.x); mp_drop(p.y); mp_drop(p.z); return (0); } @@ -525,8 +582,8 @@ static PyObject *ecpt_pyint(PyObject *me) PyObject *rc = 0; if (EC_ATINF(ECPT_P(me))) VALERR("point at infinity"); getecptout(&p, me); - if (mp_tolong_checked(p.x, &l)) goto end; - rc = PyInt_FromLong(l); + if (!mp_tolong_checked(p.x, &l, 0)) rc = PyInt_FromLong(l); + else rc = mp_topylong(p.x); end: EC_DESTROY(&p); return (rc); @@ -548,19 +605,19 @@ static PyObject *ecpt_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { PyObject *x = 0, *y = 0, *z = 0; ec p = EC_INIT; - char *kwlist[] = { "x", "y", "z", 0 }; + static const char *const kwlist[] = { "x", "y", "z", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|OOO:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|OOO:new", KWLIST, &x, &y, &z) || ecptxl(ECCURVE_C(ty), &p, x, y, z)) goto end; return (ecpt_pywrap((PyObject *)ty, &p)); end: - EC_DESTROY(&p); + mp_drop(p.x); mp_drop(p.y); mp_drop(p.z); return (0); } -static PyGetSetDef ecptnc_pygetset[] = { +static const PyGetSetDef ecptnc_pygetset[] = { #define GETSETNAME(op, name) epnc##op##_##name GET (ix, "P.ix -> integer x coordinate of P") GET (iy, "P.iy -> integer y coordinate of P") @@ -569,14 +626,16 @@ static PyGetSetDef ecptnc_pygetset[] = { { 0 } }; -static PyMethodDef ecptnc_pymethods[] = { +static const PyMethodDef ecptnc_pymethods[] = { #define METHNAME(func) epmeth_##func - METH (tobuf, "X.tobuf() -> BIN") + NAMETH(tobuf, "X.tobuf() -> BIN") + CMTH (frombuf, "frombuf(STR) -> (P, REST)") + CMTH (parse, "parse(STR) -> (P, REST)") #undef METHNAME { 0 } }; -static PyNumberMethods ecpt_pynumber = { +static const PyNumberMethods ecpt_pynumber = { 0, /* @nb_add@ */ 0, /* @nb_subtract@ */ 0, /* @nb_multiply@ */ @@ -619,8 +678,8 @@ static PyNumberMethods ecpt_pynumber = { 0, /* @nb_inplace_true_divide@ */ }; -static PyTypeObject ecpt_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ +static const PyTypeObject ecpt_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECPt", /* @tp_name@ */ sizeof(ecpt_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -631,7 +690,7 @@ static PyTypeObject ecpt_pytype_skel = { 0, /* @tp_setattr@ */ 0, /* @tp_compare@ */ 0, /* @tp_repr@ */ - &ecpt_pynumber, /* @tp_as_number@ */ + PYNUMBER(ecpt), /* @tp_as_number@ */ 0, /* @tp_as_sequence@ */ 0, /* @tp_as_mapping@ */ ecpt_pyhash, /* @tp_hash@ */ @@ -645,7 +704,9 @@ static PyTypeObject ecpt_pytype_skel = { Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Elliptic curve points, not associated with any curve.", + "ECPt([X, [Y]]): elliptic curve points, not associated with any curve.\n" + " X alone may be None, an existing point, a string 'X, Y', an\n" + " x-coordinate, or a pair (X, Y); X and Y should be a coordinate pair.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@ -653,9 +714,9 @@ static PyTypeObject ecpt_pytype_skel = { 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ - ecptnc_pymethods, /* @tp_methods@ */ + PYMETHODS(ecptnc), /* @tp_methods@ */ 0, /* @tp_members@ */ - ecptnc_pygetset, /* @tp_getset@ */ + PYGETSET(ecptnc), /* @tp_getset@ */ 0, /* @tp_base@ */ 0, /* @tp_dict@ */ 0, /* @tp_descr_get@ */ @@ -668,9 +729,16 @@ static PyTypeObject ecpt_pytype_skel = { 0 /* @tp_is_gc@ */ }; -static PyGetSetDef ecpt_pygetset[] = { +static const PyMemberDef ecpt_pymembers[] = { +#define MEMBERSTRUCT ecpt_pyobj + MEMRNM(curve, T_OBJECT, ob_type, READONLY, + "P.curve -> elliptic curve containing P") +#undef MEMBERSTRUCT + { 0 } +}; + +static const PyGetSetDef ecpt_pygetset[] = { #define GETSETNAME(op, name) ep##op##_##name - GET (curve, "P.curve -> elliptic curve containing P") GET (point, "P.point -> standalone curve point") GET (x, "P.x -> Cartesian x coordinate of P") GET (y, "P.y -> Cartesian y coordinate of P") @@ -681,17 +749,19 @@ static PyGetSetDef ecpt_pygetset[] = { { 0 } }; -static PyMethodDef ecpt_pymethods[] = { +static const PyMethodDef ecpt_pymethods[] = { #define METHNAME(func) epmeth_##func - METH (toraw, "X.toraw() -> BIN") + NAMETH(toraw, "X.toraw() -> BIN") KWMETH(ec2osp, "X.ec2osp([flags = EC_EXPLY]) -> BIN") - METH (dbl, "X.dbl() -> X + X") - METH (oncurvep, "X.oncurvep() -> BOOL") + NAMETH(dbl, "X.dbl() -> X + X") + NAMETH(oncurvep, "X.oncurvep() -> BOOL") + CMTH (fromraw, "fromraw(STR) -> (P, REST)") + KWCMTH(os2ecp, "os2ecp(STR, [flags = ...]) -> (P, REST)") #undef METHNAME { 0 } }; -static PyNumberMethods ecptcurve_pynumber = { +static const PyNumberMethods ecptcurve_pynumber = { ecpt_pyadd, /* @nb_add@ */ ecpt_pysub, /* @nb_subtract@ */ ecpt_pymul, /* @nb_multiply@ */ @@ -734,8 +804,8 @@ static PyNumberMethods ecptcurve_pynumber = { 0, /* @nb_inplace_true_divide@ */ }; -static PyTypeObject ecptcurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ +static const PyTypeObject ecptcurve_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECPtCurve", /* @tp_name@ */ sizeof(ecpt_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -746,7 +816,7 @@ static PyTypeObject ecptcurve_pytype_skel = { 0, /* @tp_setattr@ */ 0, /* @tp_compare@ */ 0, /* @tp_repr@ */ - &ecptcurve_pynumber, /* @tp_as_number@ */ + PYNUMBER(ecptcurve), /* @tp_as_number@ */ 0, /* @tp_as_sequence@ */ 0, /* @tp_as_mapping@ */ 0, /* @tp_hash@ */ @@ -760,7 +830,7 @@ static PyTypeObject ecptcurve_pytype_skel = { Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Elliptic curve points; abstract base class for points on given curves.", + "Elliptic curve points; abstract base class for points on given curves.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@ -768,9 +838,9 @@ static PyTypeObject ecptcurve_pytype_skel = { 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ - ecpt_pymethods, /* @tp_methods@ */ - 0, /* @tp_members@ */ - ecpt_pygetset, /* @tp_getset@ */ + PYMETHODS(ecpt), /* @tp_methods@ */ + PYMEMBERS(ecpt), /* @tp_members@ */ + PYGETSET(ecpt), /* @tp_getset@ */ 0, /* @tp_base@ */ 0, /* @tp_dict@ */ 0, /* @tp_descr_get@ */ @@ -787,10 +857,14 @@ static PyTypeObject ecptcurve_pytype_skel = { static PyObject *eccurve_pyrichcompare(PyObject *x, PyObject *y, int op) { - int b = ec_samep(ECCURVE_C(x), ECCURVE_C(y)); + int b; + + assert(ECCURVE_PYCHECK(x)); + if (!ECCURVE_PYCHECK(y)) RETURN_NOTIMPL; + b = ec_samep(ECCURVE_C(x), ECCURVE_C(y)); switch (op) { case Py_EQ: break; - case Py_NE: b = !b; + case Py_NE: b = !b; break; default: TYERR("can't order elliptic curves"); } return (getbool(b)); @@ -832,84 +906,6 @@ static PyObject *ecmeth_mmul(PyObject *me, PyObject *arg) ecmmul_id, ecmmul_fill, ecmmul_exp, ecmmul_drop)); } -static PyObject *meth__ECPtCurve_fromraw(PyObject *me, PyObject *arg) -{ - char *p; - int len; - buf b; - PyObject *rc = 0; - ec_curve *cc; - ec pp = EC_INIT; - - if (!PyArg_ParseTuple(arg, "Os#:fromraw", &me, &p, &len)) - return (0); - buf_init(&b, p, len); - cc = ECCURVE_C(me); - if (ec_getraw(cc, &b, &pp)) - VALERR("bad point"); - EC_IN(cc, &pp, &pp); - rc = Py_BuildValue("(NN)", ecpt_pywrap(me, &pp), bytestring_pywrapbuf(&b)); -end: - return (rc); -} - -static PyObject *meth__ECPtCurve_os2ecp(PyObject *me, - PyObject *arg, PyObject *kw) -{ - char *p; - int len; - buf b; - PyObject *rc = 0; - ec_curve *cc; - int f = EC_XONLY | EC_LSB | EC_SORT | EC_EXPLY; - ec pp = EC_INIT; - char *kwlist[] = { "buf", "flags", 0 }; - - if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|f:os2ecp", kwlist, - &me, &p, &len, &f)) - return (0); - buf_init(&b, p, len); - cc = ECCURVE_C(me); - if (ec_os2ecp(cc, f, &b, &pp)) VALERR("bad point"); - EC_IN(cc, &pp, &pp); - rc = Py_BuildValue("(NN)", ecpt_pywrap(me, &pp), bytestring_pywrapbuf(&b)); -end: - return (rc); -} - -static PyObject *meth__ECPt_frombuf(PyObject *me, PyObject *arg) -{ - buf b; - char *p; - int sz; - PyObject *rc = 0; - ec pp = EC_INIT; - - if (!PyArg_ParseTuple(arg, "Os#:frombuf", &me, &p, &sz)) goto end; - buf_init(&b, p, sz); - if (buf_getec(&b, &pp)) VALERR("malformed data"); - rc = Py_BuildValue("(NN)", ecpt_pywrapout(me, &pp), - bytestring_pywrapbuf(&b)); -end: - return (rc); -} - -static PyObject *meth__ECPt_parse(PyObject *me, PyObject *arg) -{ - char *p; - qd_parse qd; - PyObject *rc = 0; - ec pp = EC_INIT; - - if (!PyArg_ParseTuple(arg, "Os:parse", &me, &p)) goto end; - qd.p = p; - qd.e = 0; - if (!ec_ptparse(&qd, &pp)) VALERR(qd.e); - rc = Py_BuildValue("(Ns)", ecpt_pywrapout(me, &pp), qd.p); -end: - return (rc); -} - static void eccurve_pydealloc(PyObject *me) { ec_destroycurve(ECCURVE_C(me)); @@ -941,11 +937,11 @@ end: static PyObject *ecmeth_rand(PyObject *me, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "rng", 0 }; + static const char *const kwlist[] = { "rng", 0 }; grand *r = &rand_global; ec p = EC_INIT; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:rand", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:rand", KWLIST, convgrand, &r)) return (0); ec_rand(ECCURVE_C(me), &p, r); @@ -953,6 +949,21 @@ static PyObject *ecmeth_rand(PyObject *me, PyObject *arg, PyObject *kw) return (ecpt_pywrap(me, &p)); } +static PyObject *ecmeth_parse(PyObject *me, PyObject *arg) +{ + char *p; + qd_parse qd; + ec_curve *c; + PyObject *rc = 0; + + 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); +end: + return (rc); +} + static PyObject *eccurve_dopywrap(PyTypeObject *ty, PyObject *fobj, ec_curve *c) { @@ -982,13 +993,13 @@ PyObject *eccurve_pywrap(PyObject *fobj, ec_curve *c) else Py_INCREF(fobj); assert(FIELD_F(fobj) == c->f); - if (strcmp(EC_NAME(c), "prime") == 0) + if (STRCMP(EC_NAME(c), ==, "prime")) ty = ecprimecurve_pytype; - else if (strcmp(EC_NAME(c), "primeproj") == 0) + else if (STRCMP(EC_NAME(c), ==, "primeproj")) ty = ecprimeprojcurve_pytype; - else if (strcmp(EC_NAME(c), "bin") == 0) + else if (STRCMP(EC_NAME(c), ==, "bin")) ty = ecbincurve_pytype; - else if (strcmp(EC_NAME(c), "binproj") == 0) + else if (STRCMP(EC_NAME(c), ==, "binproj")) ty = ecbinprojcurve_pytype; else abort(); @@ -1001,10 +1012,10 @@ static PyObject *eccurve_pynew(PyTypeObject *ty, { PyObject *fobj; PyObject *cobj = 0; - char *kwlist[] = { "field", "a", "b", 0 }; + static const char *const kwlist[] = { "field", "a", "b", 0 }; mp *aa = 0, *bb = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O&O&", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O&O&", KWLIST, field_pytype, &fobj, convmp, &aa, convmp, &bb)) goto end; @@ -1016,26 +1027,8 @@ end: return (cobj); } -static PyObject *meth__ECCurve_parse(PyObject *me, PyObject *arg) -{ - char *p; - qd_parse qd; - ec_curve *c; - PyObject *rc = 0; - - if (!PyArg_ParseTuple(arg, "Os:parse", &me, &p)) - goto end; - qd.p = p; - qd.e = 0; - if ((c = ec_curveparse(&qd)) == 0) - VALERR(qd.e); - rc = eccurve_pywrap(0, c); -end: - return (rc); -} - 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))); } @@ -1049,7 +1042,7 @@ static PyObject *ecget_field(PyObject *me, void *hunoz) static PyObject *ecget_inf(PyObject *me, void *hunoz) { ec inf = EC_INIT; return (ecpt_pywrap(me, &inf)); } -static PyGetSetDef eccurve_pygetset[] = { +static const PyGetSetDef eccurve_pygetset[] = { #define GETSETNAME(op, name) ec##op##_##name GET (name, "E.name -> name of this kind of curve") GET (a, "E.a -> first parameter of curve") @@ -1060,18 +1053,18 @@ static PyGetSetDef eccurve_pygetset[] = { { 0 } }; -static PyMethodDef eccurve_pymethods[] = { +static const PyMethodDef eccurve_pymethods[] = { #define METHNAME(name) ecmeth_##name - METH (mmul, "\ -E.mmul([(P0, N0), (P1, N1), ...]) = N0 P0 + N1 P1 + ...") + METH (mmul, "E.mmul([(P0, N0), (P1, N1), ...]) = N0 P0 + N1 P1 + ...") METH (find, "E.find(X) -> P") - KWMETH(rand, "E.rand(rng = rand) ->P") + KWMETH(rand, "E.rand([rng = rand]) -> P") + SMTH (parse, "parse(STR) -> (E, REST)") #undef METHNAME { 0 } }; -static PyTypeObject eccurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ +static const PyTypeObject eccurve_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1103,9 +1096,9 @@ static PyTypeObject eccurve_pytype_skel = { 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ - eccurve_pymethods, /* @tp_methods@ */ + PYMETHODS(eccurve), /* @tp_methods@ */ 0, /* @tp_members@ */ - eccurve_pygetset, /* @tp_getset@ */ + PYGETSET(eccurve), /* @tp_getset@ */ 0, /* @tp_base@ */ 0, /* @tp_dict@ */ 0, /* @tp_descr_get@ */ @@ -1124,8 +1117,8 @@ static PyObject *ecprimecurve_pynew(PyTypeObject *ty, return (eccurve_pynew(ty, ec_prime, arg, kw)); } -static PyTypeObject ecprimecurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ +static const PyTypeObject ecprimecurve_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECPrimeCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1149,7 +1142,8 @@ static PyTypeObject ecprimecurve_pytype_skel = { Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "An elliptic curve over a prime field. Use ecprimeprojcurve.", + "ECPrimeCurve(FIELD, A, B): an elliptic curve over a prime field.\n" + " Use ECPrimeProjCurve instead.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@ -1178,8 +1172,8 @@ static PyObject *ecprimeprojcurve_pynew(PyTypeObject *ty, return (eccurve_pynew(ty, ec_primeproj, arg, kw)); } -static PyTypeObject ecprimeprojcurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ +static const PyTypeObject ecprimeprojcurve_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECPrimeProjCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1203,7 +1197,8 @@ static PyTypeObject ecprimeprojcurve_pytype_skel = { Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "An elliptic curve over a prime field, using projective coordinates.", + "ECPrimeProjCurve(FIELD, A, B): an elliptic curve over a prime field\n" + " using projective coordinates.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@ -1232,8 +1227,8 @@ static PyObject *ecbincurve_pynew(PyTypeObject *ty, return (eccurve_pynew(ty, ec_bin, arg, kw)); } -static PyTypeObject ecbincurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ +static const PyTypeObject ecbincurve_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECBinCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1257,7 +1252,8 @@ static PyTypeObject ecbincurve_pytype_skel = { Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "An elliptic curve over a binary field. Use ecbinprojcurve.", + "ECBinCurve(FIELD, A, B): an elliptic curve over a binary field.\n" + " Use ECBinProjCurve instead.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@ -1286,8 +1282,8 @@ static PyObject *ecbinprojcurve_pynew(PyTypeObject *ty, return (eccurve_pynew(ty, ec_binproj, arg, kw)); } -static PyTypeObject ecbinprojcurve_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ +static const PyTypeObject ecbinprojcurve_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECBinProjCurve", /* @tp_name@ */ sizeof(eccurve_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1311,7 +1307,8 @@ static PyTypeObject ecbinprojcurve_pytype_skel = { Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "An elliptic curve over a binary field, using projective coordinates.", + "ECBinProjCurve(FIELD, A, B): an elliptic curve over a binary field,\n" + " using projective coordinates.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@ -1336,8 +1333,6 @@ static 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); @@ -1372,10 +1367,10 @@ static PyObject *ecinfo_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { ec_info ei = { 0 }; PyObject *e, *g; - char *kwlist[] = { "curve", "G", "r", "h", 0 }; + static const char *const kwlist[] = { "curve", "G", "r", "h", 0 }; ecinfo_pyobj *rc = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!O&O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!O&O&:new", KWLIST, eccurve_pytype, &e, ecpt_pytype, &g, convmp, &ei.r, convmp, &ei.h)) goto end; @@ -1396,38 +1391,21 @@ end: return (0); } -static PyObject *meth__ECInfo_parse(PyObject *me, PyObject *arg) +static PyObject *eimeth_parse(PyObject *me, PyObject *arg) { char *p; qd_parse qd; ec_info ei; PyObject *rc = 0; - if (!PyArg_ParseTuple(arg, "Os:parse", &me, &p)) - goto end; - qd.p = p; - qd.e = 0; - if (ec_infoparse(&qd, &ei)) - VALERR(qd.e); + if (!PyArg_ParseTuple(arg, "s:parse", &p)) goto end; + qd.p = p; qd.e = 0; + if (ec_infoparse(&qd, &ei)) VALERR(qd.e); rc = Py_BuildValue("(Ns)", ecinfo_pywrap(&ei), qd.p); end: return (rc); } -static PyObject *meth__ECInfo__curven(PyObject *me, PyObject *arg) -{ - int i; - ec_info ei; - PyObject *rc = 0; - - if (!PyArg_ParseTuple(arg, "Oi:_curven", &me, &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)); @@ -1443,11 +1421,11 @@ end: static PyObject *eimeth_check(PyObject *me, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "rng", 0 }; + static const char *const kwlist[] = { "rng", 0 }; grand *r = &rand_global; const char *p; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:check", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:check", KWLIST, convgrand, &r)) goto end; if ((p = ec_checkinfo(ECINFO_EI(me), r)) != 0) @@ -1474,7 +1452,7 @@ static PyObject *eiget_r(PyObject *me, void *hunoz) static PyObject *eiget_h(PyObject *me, void *hunoz) { return (mp_pywrap(MP_COPY(ECINFO_EI(me)->h))); } -static PyGetSetDef ecinfo_pygetset[] = { +static const PyGetSetDef ecinfo_pygetset[] = { #define GETSETNAME(op, name) ei##op##_##name GET (curve, "I.curve -> the elliptic curve") GET (G, "I.G -> generator point for the group") @@ -1484,15 +1462,16 @@ static PyGetSetDef ecinfo_pygetset[] = { { 0 } }; -static PyMethodDef ecinfo_pymethods[] = { +static const PyMethodDef ecinfo_pymethods[] = { #define METHNAME(name) eimeth_##name - KWMETH(check, "I.check() -> None") + KWMETH(check, "I.check([rng = rand]) -> None") + SMTH (parse, "parse(STR) -> (I, REST)") #undef METHNAME { 0 } }; -static PyTypeObject ecinfo_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ +static const PyTypeObject ecinfo_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ "ECInfo", /* @tp_name@ */ sizeof(ecinfo_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1516,7 +1495,7 @@ static PyTypeObject ecinfo_pytype_skel = { Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Elliptic curve domain parameters.", + "ECInfo(CURVE, G, R, H): elliptic curve domain parameters.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@ -1524,9 +1503,9 @@ static PyTypeObject ecinfo_pytype_skel = { 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ - ecinfo_pymethods, /* @tp_methods@ */ + PYMETHODS(ecinfo), /* @tp_methods@ */ 0, /* @tp_members@ */ - ecinfo_pygetset, /* @tp_getset@ */ + PYGETSET(ecinfo), /* @tp_getset@ */ 0, /* @tp_base@ */ 0, /* @tp_dict@ */ 0, /* @tp_descr_get@ */ @@ -1541,16 +1520,9 @@ static PyTypeObject ecinfo_pytype_skel = { /*----- Setup -------------------------------------------------------------*/ -static PyMethodDef methods[] = { -#define METHNAME(func) meth_##func - METH (_ECPt_frombuf, "frombuf(E, STR) -> (P, REST)") - METH (_ECPtCurve_fromraw, "fromraw(E, STR) -> (P, REST)") - KWMETH(_ECPtCurve_os2ecp, "os2ecp(E, STR, [flags = ...]) -> (P, REST)") - METH (_ECPt_parse, "parse(E, STR) -> (P, REST)") - METH (_ECCurve_parse, "parse(STR) -> (E, REST)") - METH (_ECInfo_parse, "parse(STR) -> (I, REST)") - METH (_ECInfo__curven, "_curven(N) -> I") -#undef METHNAME +static const struct nameval consts[] = { + CONST(EC_XONLY), CONST(EC_YBIT), CONST(EC_LSB), + CONST(EC_CMPR), CONST(EC_EXPLY), CONST(EC_SORT), { 0 } }; @@ -1564,32 +1536,27 @@ void ec_pyinit(void) INITTYPE(ecbincurve, eccurve); INITTYPE(ecbinprojcurve, ecbincurve); INITTYPE(ecinfo, root); - addmethods(methods); } -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) @@ -1602,7 +1569,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 -------------------------------------------------*/