From: Mark Wooding Date: Wed, 27 Nov 2019 15:11:08 +0000 (+0000) Subject: Merge branch '1.2.x' into 1.3.x X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/catacomb-python/commitdiff_plain/7f38dc76ee0809207e67be7b2a2ddc600aba54d5?ds=sidebyside;hp=-c Merge branch '1.2.x' into 1.3.x * 1.2.x: (89 commits) t/: Add a test suite. ec.c: Don't lose error status when constructing points from a sequence. ec.c: Free partially constructed points coordinatewise. *.c: Be more careful about `PySequence_Size'. key.c: Reformat the rest of the `KeyError' constructor. key.c: Parse `KeyError' constructor arguments by hand. catacomb-python.h: Add a macro for raising `OverflowError'. key.c: Collect `KeyError' argument count as a separate step. key.c: Use tuple functions on `KeyError' argument tuple. key.c: Rename sad-path label to `end'. key.c: Delete duplicate setting of `errstring'. util.c (mkexc): Populate dictionary before constructing exception class. key.c: Only set the error code. catacomb.c, util.c: Publish negative constants correctly. field.c: Delete the completely unused `getfe' function. key.c (convfilter): Fix sense of error tests. buffer.c, ec.c: Fix required size for EC `buffer' encoding. algorithms.c: Fix `max' property name in docstrings. catacomb/__init__.py (_HashBase): Check that integers are within bounds. debian/rules: Build using the provided Makefile. ... --- 7f38dc76ee0809207e67be7b2a2ddc600aba54d5 diff --combined MANIFEST.in index 36bf4c2,c09417b..33ce54a --- a/MANIFEST.in +++ b/MANIFEST.in @@@ -1,4 -1,4 +1,4 @@@ -### Manifest template for Catacomb/Python. +### Manifest template for Catacomb/Python. -*-conf-*- ## Generated build machinery. include COPYING auto-version mdwsetup.py pysetup.mk @@@ -8,16 -8,11 +8,17 @@@ include MANIFEST.in setup.py Makefil ## C extension code. include *.c *.h + include t/*.py t/keyring include algorithms.py exclude algorithms.h + +## Scripts. +include pock include pwsafe +## Manual pages. +include *.[13] + ## Python wrapping. recursive-include catacomb *.py diff --combined algorithms.c index d73981e,edd73fd..37d52cd --- a/algorithms.c +++ b/algorithms.c @@@ -83,11 -83,11 +83,11 @@@ PyObject *keysz_pywrap(const octet *k static PyObject *keyszany_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "default", 0 }; + static const char *const kwlist[] = { "default", 0 }; int dfl; keysz_pyobj *o; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "i:new", kwlist, &dfl)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "i:new", KWLIST, &dfl)) goto end; if (dfl < 0) VALERR("key size cannot be negative"); o = (keysz_pyobj *)ty->tp_alloc(ty, 0); @@@ -100,16 -100,18 +100,16 @@@ end static PyObject *keyszrange_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "default", "min", "max", "mod", 0 }; + static const char *const kwlist[] = { "default", "min", "max", "mod", 0 }; int dfl, min = 0, max = 0, mod = 1; keyszrange_pyobj *o; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "i|iii:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "i|iii:new", KWLIST, &dfl, &min, &max, &mod)) goto end; - if (dfl < 0 || min < 0 || max < 0) - VALERR("key size cannot be negative"); - if (min > dfl || (max && dfl > max)) - VALERR("bad key size bounds"); - if (mod <= 0 || dfl % mod || min % mod || max % mod) + if (dfl < 0 || min < 0) VALERR("key size cannot be negative"); + if (min > dfl || (max && dfl > max)) VALERR("bad key size bounds"); + if (mod <= 0 || dfl%mod || min%mod || max%mod) VALERR("bad key size modulus"); o = (keyszrange_pyobj *)ty->tp_alloc(ty, 0); o->dfl = dfl; @@@ -124,20 -126,20 +124,19 @@@ end static PyObject *keyszset_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "default", "set", 0 }; + static const char *const kwlist[] = { "default", "set", 0 }; int dfl, i, n, xx; PyObject *set = 0; PyObject *x = 0, *l = 0; keyszset_pyobj *o = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "i|O:new", kwlist, - &dfl, &set)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "i|O:new", KWLIST, &dfl, &set)) goto end; if (!set) set = PyTuple_New(0); else Py_INCREF(set); if (!PySequence_Check(set)) TYERR("want a sequence"); - n = PySequence_Size(set); - l = PyList_New(0); - if (PyErr_Occurred()) goto end; + n = PySequence_Size(set); if (n < 0) goto end; + l = PyList_New(0); if (!l) goto end; if (dfl < 0) VALERR("key size cannot be negative"); x = PyInt_FromLong(dfl); PyList_Append(l, x); @@@ -206,7 -208,7 +205,7 @@@ static PyMemberDef keysz_pymembers[] = static PyGetSetDef keyszany_pygetset[] = { #define GETSETNAME(op, name) ka##op##_##name GET (min, "KSZ.min -> smallest allowed key size") - GET (max, "KSZ.min -> largest allowed key size") + GET (max, "KSZ.max -> largest allowed key size") #undef GETSETNAME { 0 } }; @@@ -214,7 -216,7 +213,7 @@@ static PyMemberDef keyszrange_pymembers[] = { #define MEMBERSTRUCT keyszrange_pyobj MEMBER(min, T_INT, READONLY, "KSZ.min -> smallest allowed key size") - MEMBER(max, T_INT, READONLY, "KSZ.min -> largest allowed key size") + MEMBER(max, T_INT, READONLY, "KSZ.max -> largest allowed key size") MEMBER(mod, T_INT, READONLY, "KSZ.mod -> key size must be a multiple of this") #undef MEMBERSTRUCT @@@ -224,7 -226,7 +223,7 @@@ static PyGetSetDef keyszset_pygetset[] = { #define GETSETNAME(op, name) ks##op##_##name GET (min, "KSZ.min -> smallest allowed key size") - GET (max, "KSZ.min -> largest allowed key size") + GET (max, "KSZ.max -> largest allowed key size") #undef GETSETNAME { 0 } }; @@@ -261,7 -263,7 +260,7 @@@ static PyTypeObject keysz_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key size constraints.", +"Key size constraints. Abstract.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -309,8 -311,7 +308,8 @@@ static PyTypeObject keyszany_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key size constraints. This object imposes no constraints on size.", +"KeySZAny(DEFAULT)\n\ + Key size constraints. This object imposes no constraints on size.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -358,9 -359,8 +357,9 @@@ static PyTypeObject keyszrange_pytype_s Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key size constraints. This object asserts minimum and maximum (if\n\ -sizes, and requires the key length to be a multiple of some value.", +"KeySZRange(DEFAULT, [min = 0], [max = 0], [mod = 1])\n\ + Key size constraints. Key size must be between MIN and MAX inclusive,\n\ + and be a multiple of MOD.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -408,8 -408,8 +407,8 @@@ static PyTypeObject keyszset_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key size constraints. This object requires the key to be one of a\n\ -few listed sizes.", +"KeySZSet(DEFAULT, SEQ)\n\ + Key size constraints. Key size must be DEFAULT or one in SEQ.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -457,27 -457,29 +456,27 @@@ PyTypeObject *gccipher_pytype, *gcipher CONVFUNC(gccipher, gccipher *, GCCIPHER_CC) CONVFUNC(gcipher, gcipher *, GCIPHER_C) -PyObject *gcipher_pywrap(PyObject *cobj, gcipher *c, unsigned f) +PyObject *gcipher_pywrap(PyObject *cobj, gcipher *c) { gcipher_pyobj *g; if (!cobj) cobj = gccipher_pywrap((/*unconst*/ gccipher *)GC_CLASS(c)); else Py_INCREF(cobj); g = PyObject_NEW(gcipher_pyobj, (PyTypeObject *)cobj); g->c = c; - g->f = f; return ((PyObject *)g); } static PyObject *gcipher_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "k", 0 }; + static const char *const kwlist[] = { "k", 0 }; char *k; Py_ssize_t sz; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz)) goto end; if (keysz(sz, GCCIPHER_CC(ty)->keysz) != sz) VALERR("bad key length"); return (gcipher_pywrap((PyObject *)ty, - GC_INIT(GCCIPHER_CC(ty), k, sz), - f_freeme)); + GC_INIT(GCCIPHER_CC(ty), k, sz))); end: return (0); } @@@ -501,7 -503,8 +500,7 @@@ PyObject *gccipher_pywrap(gccipher *cc static void gcipher_pydealloc(PyObject *me) { - if (GCIPHER_F(me) & f_freeme) - GC_DESTROY(GCIPHER_C(me)); + GC_DESTROY(GCIPHER_C(me)); Py_DECREF(me->ob_type); FREEOBJ(me); } @@@ -710,1082 -713,6 +709,1082 @@@ static PyTypeObject gcipher_pytype_ske 0 /* @tp_is_gc@ */ }; +/*----- Authenticated encryption ------------------------------------------*/ + +PyTypeObject *gcaead_pytype, *gaeadkey_pytype; +PyTypeObject *gcaeadaad_pytype, *gaeadaad_pytype; +PyTypeObject *gcaeadenc_pytype, *gaeadenc_pytype; +PyTypeObject *gcaeaddec_pytype, *gaeaddec_pytype; + +CONVFUNC(gcaead, gcaead *, GCAEAD_AEC) +CONVFUNC(gaeadkey, gaead_key *, GAEADKEY_K) + +PyObject *gaeadkey_pywrap(PyObject *cobj, gaead_key *k) +{ + gaeadkey_pyobj *gk; + + if (!cobj) cobj = gcaead_pywrap((/*unconst*/ gcaead *)GAEAD_CLASS(k)); + else Py_INCREF(cobj); + gk = PyObject_NEW(gaeadkey_pyobj, (PyTypeObject *)cobj); + gk->k = k; + return ((PyObject *)gk); +} + +static PyObject *gaeadkey_pynew(PyTypeObject *ty, + PyObject *arg, PyObject *kw) +{ + static const char *const kwlist[] = { "k", 0 }; + char *k; + Py_ssize_t sz; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz)) + goto end; + if (keysz(sz, GCAEAD_AEC(ty)->keysz) != sz) VALERR("bad key length"); + return (gaeadkey_pywrap((PyObject *)ty, + GAEAD_KEY(GCAEAD_AEC(ty), k, sz))); +end: + return (0); +} + +PyObject *gcaead_pywrap(gcaead *aec) +{ + gcaead_pyobj *gck; + gcaeadaad_pyobj *gca; + gcaeadenc_pyobj *gce; + gcaeaddec_pyobj *gcd; + +#define MKTYPE(obj, thing, newfn, namefmt) do { \ + (obj) = newtype(gcaead_pytype, 0, 0); \ + (obj)->ty.ht_name = PyString_FromFormat(namefmt, aec->name); \ + (obj)->ty.ht_type.tp_name = PyString_AS_STRING((obj)->ty.ht_name); \ + (obj)->ty.ht_type.tp_basicsize = sizeof(gaead##thing##_pyobj); \ + (obj)->ty.ht_type.tp_base = gaead##thing##_pytype; \ + Py_INCREF(gaead##thing##_pytype); \ + (obj)->ty.ht_type.tp_flags = \ + (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE); \ + (obj)->ty.ht_type.tp_alloc = PyType_GenericAlloc; \ + (obj)->ty.ht_type.tp_free = 0; \ + (obj)->ty.ht_type.tp_new = newfn; \ + typeready(&(obj)->ty.ht_type); \ +} while (0) + + MKTYPE(gck, key, gaeadkey_pynew, "%s(key)"); + MKTYPE(gca, aad, abstract_pynew, "%s(aad-hash)"); + MKTYPE(gce, enc, abstract_pynew, "%s(encrypt)"); + MKTYPE(gcd, dec, abstract_pynew, "%s(decrypt)"); + +#undef MKTYPE + + gck->aec = aec; gck->aad = gca; gck->enc = gce; gck->dec = gcd; + gca->key = gce->key = gcd->key = gck; + return ((PyObject *)gck); +} + +static void gaeadkey_pydealloc(PyObject *me) + { GAEAD_DESTROY(GAEADKEY_K(me)); Py_DECREF(me->ob_type); FREEOBJ(me); } + +static PyObject *gcaeget_name(PyObject *me, void *hunoz) + { return (PyString_FromString(GCAEAD_AEC(me)->name)); } + +static PyObject *gcaeget_keysz(PyObject *me, void *hunoz) + { return (keysz_pywrap(GCAEAD_AEC(me)->keysz)); } + +static PyObject *gcaeget_noncesz(PyObject *me, void *hunoz) + { return (keysz_pywrap(GCAEAD_AEC(me)->noncesz)); } + +static PyObject *gcaeget_tagsz(PyObject *me, void *hunoz) + { return (keysz_pywrap(GCAEAD_AEC(me)->tagsz)); } + +static PyObject *gcaeget_blksz(PyObject *me, void *hunoz) + { return (PyInt_FromLong(GCAEAD_AEC(me)->blksz)); } + +static PyObject *gcaeget_bufsz(PyObject *me, void *hunoz) + { return (PyInt_FromLong(GCAEAD_AEC(me)->bufsz)); } + +static PyObject *gcaeget_ohd(PyObject *me, void *hunoz) + { return (PyInt_FromLong(GCAEAD_AEC(me)->ohd)); } + +static PyObject *gcaeget_flags(PyObject *me, void *hunoz) + { return (PyInt_FromLong(GCAEAD_AEC(me)->f)); } + +static PyGetSetDef gcaead_pygetset[] = { +#define GETSETNAME(op, name) gcae##op##_##name + GET (keysz, "AEC.keysz -> acceptable key sizes") + GET (noncesz, "AEC.noncesz -> acceptable nonce sizes") + GET (tagsz, "AEC.tagsz -> acceptable tag sizes") + GET (blksz, "AEC.blksz -> block size, or zero") + GET (bufsz, "AEC.bufsz -> amount of data buffered internally") + GET (ohd, "AEC.ohd -> maximum encryption overhead") + GET (name, "AEC.name -> name of this kind of AEAD scheme") + GET (flags, "AEC.flags -> mask of `AEADF_...' flags") +#undef GETSETNAME + { 0 } +}; + +static PyObject *gaekmeth_aad(PyObject *me, PyObject *arg) +{ + const gaead_key *k = GAEADKEY_K(me); + PyObject *rc = 0; + + if (!PyArg_ParseTuple(arg, ":aad")) return (0); + if (k->ops->c->f&AEADF_AADNDEP) + VALERR("aad must be associated with enc/dec op"); + rc = gaeadaad_pywrap((PyObject *)GCAEAD_AAD(me->ob_type), + GAEAD_AAD(k), 0, 0); +end: + return (rc); +} + +static int check_aead_encdec(const gcaead *aec, unsigned *f_out, size_t nsz, + PyObject *hszobj, size_t *hsz_out, + PyObject *mszobj, size_t *msz_out, + PyObject *tszobj, size_t *tsz_out) +{ + unsigned f = 0, miss; + int rc = -1; + + if (hszobj != Py_None) + { f |= AEADF_PCHSZ; if (!convszt(hszobj, hsz_out)) goto end; } + if (mszobj != Py_None) + { f |= AEADF_PCMSZ; if (!convszt(mszobj, msz_out)) goto end; } + if (tszobj != Py_None) + { f |= AEADF_PCTSZ; if (!convszt(tszobj, tsz_out)) goto end; } + miss = aec->f&~f; + if (miss&AEADF_PCHSZ) VALERR("header length precommitment required"); + if (miss&AEADF_PCMSZ) VALERR("message length precommitment required"); + if (miss&AEADF_PCTSZ) VALERR("tag length precommitment required"); + if (keysz(nsz, aec->noncesz) != nsz) VALERR("bad nonce length"); + if (tszobj != Py_None && keysz(*tsz_out, aec->tagsz) != *tsz_out) + VALERR("bad tag length"); + *f_out = f | aec->f; rc = 0; +end: + return (rc); +} + +static PyObject *gaekmeth_enc(PyObject *me, PyObject *arg, PyObject *kw) +{ + static const char *const kwlist[] = { "nonce", "hsz", "msz", "tsz", 0 }; + const gaead_key *k = GAEADKEY_K(me); + gaead_enc *e; + PyObject *rc = 0; + char *n; Py_ssize_t nsz; + PyObject *hszobj = Py_None, *mszobj = Py_None, *tszobj = Py_None; + size_t hsz = 0, msz = 0, tsz = 0; + unsigned f; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|OOO:enc", KWLIST, + &n, &nsz, &hszobj, &mszobj, &tszobj)) + goto end; + if (check_aead_encdec(k->ops->c, &f, nsz, + hszobj, &hsz, mszobj, &msz, tszobj, &tsz)) + goto end; + e = GAEAD_ENC(GAEADKEY_K(me), n, nsz, hsz, msz, tsz); + if (!e) VALERR("bad aead parameter combination"); + rc = gaeadenc_pywrap((PyObject *)GCAEAD_ENC(me->ob_type), + e, f, hsz, msz, tsz); +end: + return (rc); +} + +static PyObject *gaekmeth_dec(PyObject *me, PyObject *arg, PyObject *kw) +{ + static const char *const kwlist[] = { "nonce", "hsz", "csz", "tsz", 0 }; + const gaead_key *k = GAEADKEY_K(me); + gaead_dec *d; + PyObject *rc = 0; + char *n; Py_ssize_t nsz; + PyObject *hszobj = Py_None, *cszobj = Py_None, *tszobj = Py_None; + size_t hsz = 0, csz = 0, tsz = 0; + unsigned f; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|OOO:dec", KWLIST, + &n, &nsz, &hszobj, &cszobj, &tszobj)) + goto end; + if (check_aead_encdec(k->ops->c, &f, nsz, + hszobj, &hsz, cszobj, &csz, tszobj, &tsz)) + goto end; + d = GAEAD_DEC(GAEADKEY_K(me), n, nsz, hsz, csz, tsz); + if (!d) VALERR("bad aead parameter combination"); + rc = gaeaddec_pywrap((PyObject *)GCAEAD_DEC(me->ob_type), + d, f, hsz, csz, tsz); +end: + return (rc); +} + +static PyMethodDef gaeadkey_pymethods[] = { +#define METHNAME(name) gaekmeth_##name + METH (aad, "KEY.aad() -> AAD") + KWMETH(enc, "KEY.enc(NONCE, [hsz], [msz], [tsz]) -> ENC") + KWMETH(dec, "KEY.dec(NONCE, [hsz], [csz], [tsz]) -> DEC") +#undef METHNAME + { 0 } +}; + +PyObject *gaeadaad_pywrap(PyObject *cobj, gaead_aad *a, + unsigned f, size_t hsz) +{ + gaeadaad_pyobj *ga; + + assert(cobj); Py_INCREF(cobj); + ga = PyObject_NEW(gaeadaad_pyobj, (PyTypeObject *)cobj); + ga->a = a; ga->f = f; ga->hsz = hsz; ga->hlen = 0; + return ((PyObject *)ga); +} + +static void gaeadaad_pydealloc(PyObject *me) +{ + gaeadaad_pyobj *ga = (gaeadaad_pyobj *)me; + + if (ga->a) GAEAD_DESTROY(ga->a); + Py_DECREF(me->ob_type); FREEOBJ(me); +} + +static int gaea_check(PyObject *me) +{ + gaeadaad_pyobj *ga = (gaeadaad_pyobj *)me; + int rc = -1; + + if ((ga->f&AEADF_DEAD) || !ga->a) VALERR("aad object no longer active"); + rc = 0; +end: + return (rc); +} + +static void gaea_invalidate(gaeadaad_pyobj *ga) + { if (ga) ga->f |= AEADF_DEAD; } + +static void gaea_sever(gaeadaad_pyobj **ga_inout) +{ + gaeadaad_pyobj *ga = *ga_inout; + if (ga) { ga->f |= AEADF_DEAD; ga->a = 0; Py_DECREF(ga); *ga_inout = 0; } +} + +static PyObject *gaeaget_hsz(PyObject *me, void *hunoz) +{ + if (gaea_check(me)) return (0); + else if (GAEADAAD_F(me)&AEADF_PCHSZ) return getulong(GAEADAAD_HSZ(me)); + else RETURN_NONE; +} + +static PyObject *gaeaget_hlen(PyObject *me, void *hunoz) + { return (gaea_check(me) ? 0 : getulong(GAEADAAD_HLEN(me))); } + +static PyGetSetDef gaeadaad_pygetset[] = { +#define GETSETNAME(op, name) gaea##op##_##name + GET (hsz, "AAD.hsz -> precommitted header length or `None'") + GET (hlen, "AAD.hlen -> header length so far") +#undef GETSETNAME + { 0 } +}; + +static PyObject *gaeameth_copy(PyObject *me, PyObject *arg) +{ + PyObject *rc = 0; + + if (!PyArg_ParseTuple(arg, ":copy")) goto end; + if (gaea_check(me)) goto end; + if (GAEADAAD_F(me)&AEADF_AADNDEP) + VALERR("can't duplicate nonce-dependent aad"); + rc = gaeadaad_pywrap((PyObject *)me->ob_type, + GAEAD_DUP(GAEADAAD_A(me)), 0, 0); +end: + return (rc); +} + +static int gaeadaad_hash(PyObject *me, const void *h, size_t hsz) +{ + gaeadaad_pyobj *ga = (gaeadaad_pyobj *)me; + int rc = -1; + + if (gaea_check(me)) goto end; + if ((ga->f&AEADF_NOAAD) && hsz) + VALERR("header data not permitted"); + if ((ga->f&AEADF_PCHSZ) && hsz > ga->hsz - ga->hlen) + VALERR("too large for precommitted header length"); + GAEAD_HASH(ga->a, h, hsz); ga->hlen += hsz; + rc = 0; +end: + return (rc); +} + + +static PyObject *gaeameth_hash(PyObject *me, PyObject *arg) +{ + char *h; Py_ssize_t hsz; + + if (!PyArg_ParseTuple(arg, "s#:hash", &h, &hsz)) return (0); + if (gaeadaad_hash(me, h, hsz)) return (0); + RETURN_ME; +} + +#define GAEAMETH_HASHU_(n, W, w) \ + static PyObject *gaeameth_hashu##w(PyObject *me, PyObject *arg) \ + { \ + uint##n x; octet b[SZ_##W]; \ + if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) return (0); \ + STORE##W(b, x); if (gaeadaad_hash(me, b, sizeof(b))) return (0); \ + RETURN_ME; \ + } +DOUINTCONV(GAEAMETH_HASHU_) + +#define GAEAMETH_HASHBUF_(n, W, w) \ + static PyObject *gaeameth_hashbuf##w(PyObject *me, PyObject *arg) \ + { \ + char *p; Py_ssize_t sz; octet b[SZ_##W]; \ + if (!PyArg_ParseTuple(arg, "s#:hashbuf" #w, &p, &sz)) goto end; \ + if (sz > MASK##n) TYERR("string too long"); \ + STORE##W(b, sz); if (gaeadaad_hash(me, b, sizeof(b))) goto end; \ + if (gaeadaad_hash(me, p, sz)) goto end; \ + RETURN_ME; \ + end: \ + return (0); \ + } +DOUINTCONV(GAEAMETH_HASHBUF_) + +static PyObject *gaeameth_hashstrz(PyObject *me, PyObject *arg) +{ + char *p; + if (!PyArg_ParseTuple(arg, "s:hashstrz", &p)) return (0); + if (gaeadaad_hash(me, p, strlen(p) + 1)) return (0); + RETURN_ME; +} + +static PyMethodDef gaeadaad_pymethods[] = { +#define METHNAME(name) gaeameth_##name + METH (copy, "AAD.copy() -> AAD'") + METH (hash, "AAD.hash(H)") +#define METHU_(n, W, w) METH(hashu##w, "AAD.hashu" #w "(WORD)") + DOUINTCONV(METHU_) +#undef METHU_ +#define METHBUF_(n, W, w) METH(hashbuf##w, "AAD.hashbuf" #w "(BYTES)") + DOUINTCONV(METHBUF_) +#undef METHBUF_ + METH (hashstrz, "AAD.hashstrz(STRING)") +#undef METHNAME + { 0 } +}; + +PyObject *gaeadenc_pywrap(PyObject *cobj, gaead_enc *e, unsigned f, + size_t hsz, size_t msz, size_t tsz) +{ + gaeadenc_pyobj *ge; + + assert(cobj); Py_INCREF(cobj); + ge = PyObject_NEW(gaeadenc_pyobj, (PyTypeObject *)cobj); + ge->e = e; ge->f = f; ge->hsz = hsz; ge->msz = msz; ge->tsz = tsz; + ge->aad = 0; ge->mlen = 0; + return ((PyObject *)ge); +} + +static void gaeadenc_pydealloc(PyObject *me) +{ + gaeadenc_pyobj *ge = (gaeadenc_pyobj *)me; + + gaea_sever(&ge->aad); GAEAD_DESTROY(ge->e); + Py_DECREF(me->ob_type); FREEOBJ(me); +} + +static PyObject *gaeeget_hsz(PyObject *me, void *hunoz) +{ + if (GAEADENC_F(me)&AEADF_PCHSZ) return getulong(GAEADENC_HSZ(me)); + else RETURN_NONE; +} + +static PyObject *gaeeget_msz(PyObject *me, void *hunoz) +{ + if (GAEADENC_F(me)&AEADF_PCMSZ) return getulong(GAEADENC_MSZ(me)); + else RETURN_NONE; +} + +static PyObject *gaeeget_tsz(PyObject *me, void *hunoz) +{ + if (GAEADENC_F(me)&AEADF_PCTSZ) return getulong(GAEADENC_TSZ(me)); + else RETURN_NONE; +} + +static PyObject *gaeeget_mlen(PyObject *me, void *hunoz) + { return getulong(GAEADENC_MLEN(me)); } + +static PyGetSetDef gaeadenc_pygetset[] = { +#define GETSETNAME(op, name) gaee##op##_##name + GET (hsz, "ENC.hsz -> precommitted header length or `None'") + GET (msz, "ENC.msz -> precommitted message length or `None'") + GET (tsz, "ENC.tsz -> precommitted tag length or `None'") + GET (mlen, "ENC.mlen -> message length so far") +#undef GETSETNAME + { 0 } +}; + +static PyObject *gaeemeth_aad(PyObject *me, PyObject *arg) +{ + gaeadenc_pyobj *ge = (gaeadenc_pyobj *)me; + PyObject *rc = 0; + + if (!PyArg_ParseTuple(arg, ":aad")) return (0); + if (!(ge->f&AEADF_AADNDEP)) + rc = gaeadaad_pywrap((PyObject *)GCAEADENC_KEY(ge->ob_type)->aad, + GAEAD_AAD(ge->e), 0, 0); + else { + if ((ge->f&AEADF_AADFIRST) && ge->mlen) + VALERR("too late for aad"); + if (!ge->aad) + ge->aad = (gaeadaad_pyobj *) + gaeadaad_pywrap((PyObject *)GCAEADENC_KEY(ge->ob_type)->aad, + GAEAD_AAD(ge->e), ge->f&AEADF_PCHSZ, ge->hsz); + Py_INCREF(ge->aad); + rc = (PyObject *)ge->aad; + } +end: + return (rc); +} + +static PyObject *gaeemeth_reinit(PyObject *me, PyObject *arg, PyObject *kw) +{ + static const char *const kwlist[] = { "nonce", "hsz", "msz", "tsz", 0 }; + gaeadenc_pyobj *ge = (gaeadenc_pyobj *)me; + char *n; Py_ssize_t nsz; + PyObject *hszobj = Py_None, *mszobj = Py_None, *tszobj = Py_None; + size_t hsz = 0, msz = 0, tsz = 0; + unsigned f; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|OOO:enc", KWLIST, + &n, &nsz, &hszobj, &mszobj, &tszobj)) + goto end; + if (check_aead_encdec(ge->e->ops->c, &f, nsz, + hszobj, &hsz, mszobj, &msz, tszobj, &tsz)) + goto end; + if (GAEAD_REINIT(ge->e, n, nsz, hsz, msz, tsz)) + VALERR("bad aead parameter combination"); + gaea_sever(&ge->aad); + ge->f = f; ge->hsz = hsz; ge->msz = msz; ge->tsz = tsz; +end: + return (0); +} + +static PyObject *gaeemeth_encrypt(PyObject *me, PyObject *arg) +{ + gaeadenc_pyobj *ge = (gaeadenc_pyobj *)me; + char *m; Py_ssize_t msz; + char *c = 0; size_t csz; buf b; + int err; + PyObject *rc = 0; + + if (!PyArg_ParseTuple(arg, "s#:encrypt", &m, &msz)) goto end; + if (ge->f&AEADF_AADFIRST) { + if ((ge->f&AEADF_PCHSZ) && (ge->aad ? ge->aad->hlen : 0) != ge->hsz) + VALERR("header doesn't match precommitted length"); + gaea_invalidate(ge->aad); + } + if ((ge->f&AEADF_PCMSZ) && msz > ge->msz - ge->mlen) + VALERR("too large for precommitted message length"); + csz = msz + ge->e->ops->c->bufsz; c = xmalloc(csz); buf_init(&b, c, csz); + err = GAEAD_ENCRYPT(ge->e, m, msz, &b); assert(!err); (void)err; + buf_flip(&b); rc = bytestring_pywrapbuf(&b); ge->mlen += msz; +end: + xfree(c); + return (rc); +} + +static PyObject *gaeemeth_done(PyObject *me, PyObject *arg, PyObject *kw) +{ + static const char *const kwlist[] = { "tsz", "aad", 0 }; + gaeadenc_pyobj *ge = (gaeadenc_pyobj *)me; + PyObject *aad = Py_None; + char *c = 0; size_t csz; buf b; + PyObject *tszobj = Py_None; PyObject *tag; size_t tsz; + int err; + PyObject *rc = 0; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|OO:done", KWLIST, + &tszobj, &aad)) + goto end; + if (tszobj != Py_None && !convszt(tszobj, &tsz)) goto end; + if (aad != Py_None && + !PyObject_TypeCheck(aad, + (PyTypeObject *)GCAEADENC_KEY(me->ob_type)->aad)) + TYERR("wanted aad"); + if ((ge->f&AEADF_AADNDEP) && aad != Py_None && aad != (PyObject *)ge->aad) + VALERR("mismatched aad"); + if ((ge->f&AEADF_PCHSZ) && + (aad == Py_None ? 0 : GAEADAAD_HLEN(aad)) != ge->hsz) + VALERR("header doesn't match precommitted length"); + if ((ge->f&AEADF_PCMSZ) && ge->mlen != ge->msz) + VALERR("message doesn't match precommitted length"); + if (tszobj == Py_None) { + if (ge->f&AEADF_PCTSZ) tsz = ge->tsz; + else tsz = keysz(0, ge->e->ops->c->tagsz); + } else { + if ((ge->f&AEADF_PCTSZ) && tsz != ge->tsz) + VALERR("tag length doesn't match precommitted value"); + if (keysz(tsz, ge->e->ops->c->tagsz) != tsz) VALERR("bad tag length"); + } + csz = ge->e->ops->c->bufsz; c = xmalloc(csz); buf_init(&b, c, csz); + tag = bytestring_pywrap(0, tsz); + err = GAEAD_DONE(ge->e, aad == Py_None ? 0 : GAEADAAD_A(aad), &b, + PyString_AS_STRING(tag), tsz); + assert(!err); (void)err; + buf_flip(&b); rc = Py_BuildValue("NN", bytestring_pywrapbuf(&b), tag); +end: + xfree(c); + return (rc); +} + +static PyMethodDef gaeadenc_pymethods[] = { +#define METHNAME(name) gaeemeth_##name + METH (aad, "ENC.aad() -> AAD") + KWMETH(reinit, "ENC.reinit(NONCE, [hsz], [msz], [tsz])") + METH (encrypt, "ENC.encrypt(MSG) -> CT") + KWMETH(done, "ENC.done([tsz], [aad]) -> CT, TAG") +#undef METHNAME + { 0 } +}; + +PyObject *gaeaddec_pywrap(PyObject *cobj, gaead_dec *d, unsigned f, + size_t hsz, size_t csz, size_t tsz) +{ + gaeaddec_pyobj *gd; + assert(cobj); Py_INCREF(cobj); + gd = PyObject_NEW(gaeaddec_pyobj, (PyTypeObject *)cobj); + gd->d = d; gd->f = f; gd->hsz = hsz; gd->csz = csz; gd->tsz = tsz; + gd->aad = 0; gd->clen = 0; + return ((PyObject *)gd); +} + +static void gaeaddec_pydealloc(PyObject *me) +{ + gaeaddec_pyobj *gd = (gaeaddec_pyobj *)me; + + gaea_sever(&gd->aad); GAEAD_DESTROY(GAEADDEC_D(me)); + Py_DECREF(me->ob_type); FREEOBJ(me); +} + +static PyObject *gaedget_hsz(PyObject *me, void *hunoz) +{ + if (GAEADDEC_F(me)&AEADF_PCHSZ) return getulong(GAEADDEC_HSZ(me)); + else RETURN_NONE; +} + +static PyObject *gaedget_csz(PyObject *me, void *hunoz) +{ + if (GAEADDEC_F(me)&AEADF_PCMSZ) return getulong(GAEADDEC_CSZ(me)); + else RETURN_NONE; +} + +static PyObject *gaedget_tsz(PyObject *me, void *hunoz) +{ + if (GAEADDEC_F(me)&AEADF_PCTSZ) return getulong(GAEADDEC_TSZ(me)); + else RETURN_NONE; +} + +static PyObject *gaedget_clen(PyObject *me, void *hunoz) + { return getulong(GAEADDEC_CLEN(me)); } + +static PyGetSetDef gaeaddec_pygetset[] = { +#define GETSETNAME(op, name) gaed##op##_##name + GET (hsz, "DEC.hsz -> precommitted header length or `None'") + GET (csz, "DEC.csz -> precommitted ciphertext length or `None'") + GET (tsz, "DEC.tsz -> precommitted tag length or `None'") + GET (clen, "DEC.clen -> ciphertext length so far") +#undef GETSETNAME + { 0 } +}; + +static PyObject *gaedmeth_aad(PyObject *me, PyObject *arg) +{ + gaeaddec_pyobj *gd = (gaeaddec_pyobj *)me; + + if (!PyArg_ParseTuple(arg, ":aad")) return (0); + if (!(gd->f&AEADF_AADNDEP)) + return (gaeadaad_pywrap((PyObject *)GCAEADDEC_KEY(gd->ob_type)->aad, + GAEAD_AAD(gd->d), 0, 0)); + else { + if (!gd->aad) + gd->aad = (gaeadaad_pyobj *) + gaeadaad_pywrap((PyObject *)GCAEADENC_KEY(gd->ob_type)->aad, + GAEAD_AAD(gd->d), gd->f&AEADF_PCHSZ, gd->hsz); + Py_INCREF(gd->aad); + return ((PyObject *)gd->aad); + } +} + +static PyObject *gaedmeth_reinit(PyObject *me, PyObject *arg, PyObject *kw) +{ + static const char *const kwlist[] = { "nonce", "hsz", "csz", "tsz", 0 }; + gaeaddec_pyobj *gd = (gaeaddec_pyobj *)me; + char *n; Py_ssize_t nsz; + PyObject *hszobj = Py_None, *cszobj = Py_None, *tszobj = Py_None; + size_t hsz = 0, csz = 0, tsz = 0; + unsigned f; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|OOO:enc", KWLIST, + &n, &nsz, &hszobj, &cszobj, &tszobj)) + goto end; + if (check_aead_encdec(gd->d->ops->c, &f, nsz, + hszobj, &hsz, cszobj, &csz, tszobj, &tsz)) + goto end; + if (GAEAD_REINIT(gd->d, n, nsz, hsz, csz, tsz)) + VALERR("bad aead parameter combination"); + gaea_sever(&gd->aad); + gd->f = f; gd->hsz = hsz; gd->csz = csz; gd->tsz = tsz; +end: + return (0); +} + +static PyObject *gaedmeth_decrypt(PyObject *me, PyObject *arg) +{ + gaeaddec_pyobj *gd = (gaeaddec_pyobj *)me; + char *c; Py_ssize_t csz; + char *m = 0; size_t msz; buf b; + int err; + PyObject *rc = 0; + + if (!PyArg_ParseTuple(arg, "s#:decrypt", &c, &csz)) goto end; + if (gd->f&AEADF_AADFIRST) { + if ((gd->f&AEADF_PCHSZ) && (gd->aad ? gd->aad->hlen : 0) != gd->hsz) + VALERR("header doesn't match precommitted length"); + gaea_invalidate(gd->aad); + } + if ((gd->f&AEADF_PCMSZ) && csz > gd->csz - gd->clen) + VALERR("too large for precommitted message length"); + msz = csz + gd->d->ops->c->bufsz; m = xmalloc(msz); buf_init(&b, m, msz); + err = GAEAD_DECRYPT(gd->d, c, csz, &b); assert(!err); (void)err; + buf_flip(&b); rc = bytestring_pywrapbuf(&b); gd->clen += csz; +end: + xfree(m); + return (rc); +} + +static PyObject *gaedmeth_done(PyObject *me, PyObject *arg, PyObject *kw) +{ + static const char *const kwlist[] = { "tag", "aad", 0 }; + gaeaddec_pyobj *gd = (gaeaddec_pyobj *)me; + PyObject *aad = Py_None; + char *t; Py_ssize_t tsz; + char *m = 0; size_t msz; buf b; + int err; + PyObject *rc = 0; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O:done", KWLIST, + &t, &tsz, &aad)) + goto end; + if (aad != Py_None && + !PyObject_TypeCheck(aad, + (PyTypeObject *)GCAEADENC_KEY(me->ob_type)->aad)) + TYERR("wanted aad"); + if ((gd->f&AEADF_AADNDEP) && aad != Py_None && aad != (PyObject *)gd->aad) + VALERR("mismatched aad"); + if ((gd->f&AEADF_PCHSZ) && + (aad == Py_None ? 0 : GAEADAAD_HLEN(aad)) != gd->hsz) + VALERR("header doesn't match precommitted length"); + if ((gd->f&AEADF_PCMSZ) && gd->clen != gd->csz) + VALERR("message doesn't match precommitted length"); + if ((gd->f&AEADF_PCTSZ) && tsz != gd->tsz) + VALERR("tag length doesn't match precommitted value"); + if (keysz(tsz, gd->d->ops->c->tagsz) != tsz) VALERR("bad tag length"); + msz = gd->d->ops->c->bufsz; m = xmalloc(msz); buf_init(&b, m, msz); + err = GAEAD_DONE(gd->d, aad == Py_None ? 0 : GAEADAAD_A(aad), &b, t, tsz); + assert(err >= 0); + if (!err) VALERR("decryption failed"); + buf_flip(&b); rc = bytestring_pywrapbuf(&b); +end: + xfree(m); + return (rc); +} + +static PyMethodDef gaeaddec_pymethods[] = { +#define METHNAME(name) gaedmeth_##name + METH (aad, "DEC.aad() -> AAD") + KWMETH(reinit, "DEC.reinit(NONCE, [hsz], [csz], [tsz])") + METH (decrypt, "DEC.decrypt(CT) -> MSG") + KWMETH(done, "DEC.done(TAG, [aad]) -> MSG | None") +#undef METHNAME + { 0 } +}; + +static PyTypeObject gcaead_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "GCAEAD", /* @tp_name@ */ + sizeof(gcaead_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + 0, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Authenticated encryption (key) metaclass.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + 0, /* @tp_methods@ */ + 0, /* @tp_members@ */ + gcaead_pygetset, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +static PyTypeObject gaeadkey_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "GAEKey", /* @tp_name@ */ + sizeof(gaeadkey_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + gaeadkey_pydealloc, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Authenticated encryption key.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + gaeadkey_pymethods, /* @tp_methods@ */ + 0, /* @tp_members@ */ + 0, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +static PyTypeObject gcaeadaad_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "GAEAADClass", /* @tp_name@ */ + sizeof(gcaeadaad_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + 0, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Authenticated encryption additional-data hash metaclass.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + 0, /* @tp_methods@ */ + 0, /* @tp_members@ */ + 0, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +static PyTypeObject gaeadaad_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "GAEAAD", /* @tp_name@ */ + sizeof(gaeadaad_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + gaeadaad_pydealloc, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Authenticated encryption AAD hash.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + gaeadaad_pymethods, /* @tp_methods@ */ + 0, /* @tp_members@ */ + gaeadaad_pygetset, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +static PyTypeObject gcaeadenc_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "GAEEncClass", /* @tp_name@ */ + sizeof(gcaeadenc_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + 0, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Authenticated encryption operation metaclass.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + 0, /* @tp_methods@ */ + 0, /* @tp_members@ */ + 0, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +static PyTypeObject gaeadenc_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "GAEEnc", /* @tp_name@ */ + sizeof(gaeadenc_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + gaeadenc_pydealloc, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Authenticated encryption operation.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + gaeadenc_pymethods, /* @tp_methods@ */ + 0, /* @tp_members@ */ + gaeadenc_pygetset, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +static PyTypeObject gcaeaddec_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "GAEDecClass", /* @tp_name@ */ + sizeof(gcaeaddec_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + 0, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Authenticated decryption operation metaclass.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + 0, /* @tp_methods@ */ + 0, /* @tp_members@ */ + 0, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +static PyTypeObject gaeaddec_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "GAEDec", /* @tp_name@ */ + sizeof(gaeaddec_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + gaeaddec_pydealloc, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Authenticated decryption operation.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + gaeaddec_pymethods, /* @tp_methods@ */ + 0, /* @tp_members@ */ + gaeaddec_pygetset, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + /*----- Hash functions ----------------------------------------------------*/ PyTypeObject *gchash_pytype, *ghash_pytype; @@@ -1795,10 -722,10 +1794,10 @@@ CONVFUNC(ghash, ghash *, GHASH_H static PyObject *ghash_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", kwlist)) + static const char *const kwlist[] = { 0 }; + if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", KWLIST)) goto end; - return (ghash_pywrap((PyObject *)ty, GH_INIT(GCHASH_CH(ty)), f_freeme)); + return (ghash_pywrap((PyObject *)ty, GH_INIT(GCHASH_CH(ty)))); end: return (0); } @@@ -1820,19 -747,21 +1819,19 @@@ PyObject *gchash_pywrap(gchash *ch return ((PyObject *)g); } -PyObject *ghash_pywrap(PyObject *cobj, ghash *h, unsigned f) +PyObject *ghash_pywrap(PyObject *cobj, ghash *h) { ghash_pyobj *g; if (!cobj) cobj = gchash_pywrap((/*unconst*/ gchash *)GH_CLASS(h)); else Py_INCREF(cobj); g = PyObject_NEW(ghash_pyobj, (PyTypeObject *)cobj); g->h = h; - g->f = f; return ((PyObject *)g); } static void ghash_pydealloc(PyObject *me) { - if (GHASH_F(me) & f_freeme) - GH_DESTROY(GHASH_H(me)); + GH_DESTROY(GHASH_H(me)); Py_DECREF(me->ob_type); FREEOBJ(me); } @@@ -1846,12 -775,6 +1845,12 @@@ static PyObject *gchget_hashsz(PyObjec static PyObject *gchget_bufsz(PyObject *me, void *hunoz) { return (PyInt_FromLong(GCHASH_CH(me)->bufsz)); } +static PyObject *ghmeth_copy(PyObject *me, PyObject *arg) +{ + if (!PyArg_ParseTuple(arg, ":copy")) return (0); + return (ghash_pywrap((PyObject *)me->ob_type, GH_COPY(GHASH_H(me)))); +} + static PyObject *ghmeth_hash(PyObject *me, PyObject *arg) { char *p; @@@ -1865,9 -788,11 +1864,9 @@@ static PyObject *ghmeth_hashu##w(PyObject *me, PyObject *arg) \ { \ uint##n x; \ - if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) goto end; \ + if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) return (0); \ GH_HASHU##W(GHASH_H(me), x); \ RETURN_ME; \ - end: \ - return (0); \ } DOUINTCONV(GHMETH_HASHU_) @@@ -1916,7 -841,6 +1915,7 @@@ static PyGetSetDef gchash_pygetset[] = static PyMethodDef ghash_pymethods[] = { #define METHNAME(name) ghmeth_##name + METH (copy, "H.copy() -> HH") METH (hash, "H.hash(M)") #define METHU_(n, W, w) METH(hashu##w, "H.hashu" #w "(WORD)") DOUINTCONV(METHU_) @@@ -2036,27 -960,29 +2035,27 @@@ CONVFUNC(gmhash, ghash *, GHASH_H static PyObject *gmac_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "k", 0 }; + static const char *const kwlist[] = { "k", 0 }; char *k; Py_ssize_t sz; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz)) goto end; if (keysz(sz, GCMAC_CM(ty)->keysz) != sz) VALERR("bad key length"); return (gmac_pywrap((PyObject *)ty, - GM_KEY(GCMAC_CM(ty), k, sz), - f_freeme)); + GM_KEY(GCMAC_CM(ty), k, sz))); end: return (0); } static PyObject *gmhash_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { 0 }; + static const char *const kwlist[] = { 0 }; ghash_pyobj *g; - if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", kwlist)) return (0); + if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", KWLIST)) return (0); g = PyObject_NEW(ghash_pyobj, ty); g->h = GM_INIT(GMAC_M(ty)); - g->f = f_freeme; Py_INCREF(ty); return ((PyObject *)g); } @@@ -2078,7 -1004,7 +2077,7 @@@ PyObject *gcmac_pywrap(gcmac *cm return ((PyObject *)g); } -PyObject *gmac_pywrap(PyObject *cobj, gmac *m, unsigned f) +PyObject *gmac_pywrap(PyObject *cobj, gmac *m) { gmac_pyobj *g; if (!cobj) cobj = gcmac_pywrap((/*unconst*/ gcmac *)GM_CLASS(m)); @@@ -2097,12 -1023,14 +2096,12 @@@ g->ty.ht_type.tp_new = gmhash_pynew; typeready(&g->ty.ht_type); g->m = m; - g->f = f; return ((PyObject *)g); } static void gmac_pydealloc(PyObject *me) { - if (GMAC_F(me) & f_freeme) - GM_DESTROY(GMAC_M(me)); + GM_DESTROY(GMAC_M(me)); Py_DECREF(me->ob_type); PyType_Type.tp_dealloc(me); } @@@ -2292,13 -1220,13 +2291,13 @@@ CONVFUNC(poly1305hash, poly1305_ctx *, static PyObject *poly1305hash_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "mask", 0 }; + static const char *const kwlist[] = { "mask", 0 }; poly1305key_pyobj *pk = (poly1305key_pyobj *)ty; poly1305hash_pyobj *ph; char *m = 0; Py_ssize_t sz; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|s#:new", kwlist, &m, &sz)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|s#:new", KWLIST, &m, &sz)) return (0); if (m && sz != POLY1305_MASKSZ) VALERR("bad mask length"); ph = PyObject_NEW(poly1305hash_pyobj, ty); @@@ -2314,12 -1242,12 +2313,12 @@@ end static PyObject *poly1305key_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "k", 0 }; + static const char *const kwlist[] = { "k", 0 }; poly1305key_pyobj *pk; char *k; Py_ssize_t sz; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz)) goto end; if (keysz(sz, poly1305_keysz) != sz) VALERR("bad key length"); @@@ -2380,9 -1308,11 +2379,9 @@@ static PyObject *polymeth_hash(PyObjec { \ uint##n x; \ octet b[SZ_##W]; \ - if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) goto end; \ + if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) return (0); \ STORE##W(b, x); poly1305_hash(P1305_CTX(me), b, sizeof(b)); \ RETURN_ME; \ - end: \ - return (0); \ } DOUINTCONV(POLYMETH_HASHU_) @@@ -2554,7 -1484,7 +2553,7 @@@ static PyTypeObject poly1305key_pytype_ Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Poly1305 key.", +"poly1305(K): Poly1305 key.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -2637,7 -1567,7 +2636,7 @@@ static PyTypeObject poly1305hash_pytype if (!PyArg_ParseTuple(arg, "s#s#:" #hdance "_prf", \ &k, &ksz, &n, &nsz)) \ goto end; \ - if (ksz != DANCE##_KEYSZ) VALERR("bad key length"); \ + if (ksz != keysz(ksz, dance##_keysz)) VALERR("bad key length"); \ if (nsz != HDANCE##_INSZ) VALERR("bad input length"); \ rc = bytestring_pywrap(0, HSALSA20_OUTSZ); \ dance##_init(&dance, k, ksz, 0); \ @@@ -2670,8 -1600,8 +2669,8 @@@ static PyObject *kxvik_pynew(PyTypeObje { unsigned n = 24; kxvik_pyobj *rc = 0; - char *kwlist[] = { "nround", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", kwlist, + static const char *const kwlist[] = { "nround", 0 }; + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", KWLIST, convuint, &n)) goto end; rc = (kxvik_pyobj *)ty->tp_alloc(ty, 0); @@@ -2681,16 -1611,6 +2680,16 @@@ end return ((PyObject *)rc); } +static PyObject *kxvikmeth_copy(PyObject *me, PyObject *arg) +{ + kxvik_pyobj *k = (kxvik_pyobj *)me, *rc = 0; + if (!PyArg_ParseTuple(arg, ":copy")) goto end; + rc = (kxvik_pyobj *)k->ob_type->tp_alloc(k->ob_type, 0); + rc->s = k->s; rc->n = k->n; +end: + return ((PyObject *)rc); +} + static PyObject *kxvikmeth_mix(PyObject *me, PyObject *arg) { kxvik_pyobj *k = (kxvik_pyobj *)me; @@@ -2724,7 -1644,7 +2723,7 @@@ static PyObject *kxvikmeth_extract(PyOb unsigned i; unsigned n; - if (!PyArg_ParseTuple(arg, "O&:mix", convuint, &n)) goto end; + if (!PyArg_ParseTuple(arg, "O&:extract", convuint, &n)) goto end; if (n > 200) VALERR("out of range"); rc = bytestring_pywrap(0, n); q = (octet *)PyString_AS_STRING(rc); @@@ -2754,10 -1674,14 +2753,14 @@@ static int kxvikset_nround(PyObject *me { kxvik_pyobj *k = (kxvik_pyobj *)me; unsigned n; + int rc = -1; - if (!convuint(val, &n)) return (-1); + if (!val) NIERR("__del__"); + if (!convuint(val, &n)) goto end; k->n = n; - return (0); + rc = 0; + end: + return (rc); } static PyGetSetDef kxvik_pygetset[] = { @@@ -2769,7 -1693,6 +2772,7 @@@ static PyMethodDef kxvik_pymethods[] = { #define METHNAME(func) kxvikmeth_##func + METH (copy, "KECCAK.copy() -> KECCAK'") METH (mix, "KECCAK.mix(DATA)") METH (extract, "KECCAK.extract(NOCTETS)") METH (step, "KECCAK.step()") @@@ -2802,7 -1725,7 +2805,7 @@@ static PyTypeObject kxvik_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Keccak-p[1600, n] state.", +"Keccak1600([nround = 24]): Keccak-p[1600, n] state.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -2845,9 -1768,9 +2848,9 @@@ static PyObject *shake_dopynew(void (*i shake_pyobj *rc = 0; char *p = 0, *f = 0; Py_ssize_t psz = 0, fsz = 0; - char *kwlist[] = { "perso", "func", 0 }; + static const char *const kwlist[] = { "perso", "func", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|s#s#:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|s#s#:new", KWLIST, &p, &psz, &f, &fsz)) goto end; rc = (shake_pyobj *)ty->tp_alloc(ty, 0); @@@ -2888,10 -1811,12 +2891,10 @@@ static PyObject *shakemeth_hash(PyObjec { \ uint##n x; \ octet b[SZ_##W]; \ - if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) goto end; \ - if (shake_check(me, 0)) goto end; \ + if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) return (0); \ + if (shake_check(me, 0)) return (0); \ STORE##W(b, x); shake_hash(SHAKE_H(me), b, sizeof(b)); \ RETURN_ME; \ - end: \ - return (0); \ } DOUINTCONV(SHAKEMETH_HASHU_) @@@ -2954,7 -1879,7 +2957,7 @@@ static PyObject *shakemeth_copy(PyObjec rc->h = *SHAKE_H(me); rc->st = SHAKE_ST(me); end: - return ((PyObject *)me); + return ((PyObject *)rc); } static PyObject *shakemeth_get(PyObject *me, PyObject *arg) @@@ -3097,7 -2022,7 +3100,7 @@@ static PyTypeObject shake128_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"SHAKE128/cSHAKE128 XOF.", +"Shake128([perso = STR], [func = STR]): SHAKE128/cSHAKE128 XOF.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -3145,7 -2070,7 +3148,7 @@@ static PyTypeObject shake256_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"SHAKE256/cSHAKE256 XOF.", +"Shake256([perso = STR], [func = STR]): SHAKE256/cSHAKE256 XOF.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -3227,13 -2152,13 +3230,13 @@@ typedef struct prp static PyObject *gprp_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "key", 0 }; + static const char *const kwlist[] = { "key", 0 }; char *k; Py_ssize_t sz; const prpinfo *prp = GCPRP_PRP(ty); PyObject *me; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz)) goto end; if (keysz(sz, prp->keysz) != sz) VALERR("bad key length"); me = (PyObject *)ty->tp_alloc(ty, 0); @@@ -3456,14 -2381,6 +3459,14 @@@ void algorithms_pyinit(void INITTYPE(keyszset, keysz); INITTYPE(gccipher, type); INITTYPE(gcipher, root); + INITTYPE(gcaead, type); + INITTYPE(gaeadkey, root); + INITTYPE(gcaeadaad, type); + INITTYPE(gaeadaad, root); + INITTYPE(gcaeadenc, type); + INITTYPE(gaeadenc, root); + INITTYPE(gcaeaddec, type); + INITTYPE(gaeaddec, root); INITTYPE(gchash, type); INITTYPE(ghash, root); INITTYPE(gcmac, type); @@@ -3482,7 -2399,6 +3485,7 @@@ } GEN(gcciphers, cipher) +GEN(gcaeads, aead) GEN(gchashes, hash) GEN(gcmacs, mac) #define gcprp prpinfo @@@ -3498,15 -2414,6 +3501,15 @@@ void algorithms_pyinsert(PyObject *mod INSERT("GCCipher", gccipher_pytype); INSERT("GCipher", gcipher_pytype); INSERT("gcciphers", gcciphers()); + INSERT("GCAEAD", gcaead_pytype); + INSERT("GAEKey", gaeadkey_pytype); + INSERT("GAEAADClass", gcaeadaad_pytype); + INSERT("GAEAAD", gaeadaad_pytype); + INSERT("GAEEncClass", gcaeadenc_pytype); + INSERT("GAEEnc", gaeadenc_pytype); + INSERT("GAEDecClass", gcaeaddec_pytype); + INSERT("GAEDec", gaeaddec_pytype); + INSERT("gcaeads", gcaeads()); INSERT("GCHash", gchash_pytype); INSERT("GHash", ghash_pytype); INSERT("gchashes", d = gchashes()); diff --combined algorithms.py index 4b65ce9,46abccb..5730c45 --- a/algorithms.py +++ b/algorithms.py @@@ -25,8 -25,6 +25,8 @@@ serpent noekeo '''.split() pmodes = ''' ecb cbc cfb ofb counter +cmac pmac1 +ccm eax gcm ocb1 ocb3 '''.split() streamciphers = ''' rc4 seal @@@ -39,7 -37,7 +39,7 @@@ chacha20 chacha12 chacha chacha20-ietf chacha12-ietf chacha8-ietf xchacha20 xchacha12 xchacha8 '''.split() - streamciphers += map(lambda s: s.translate(None, '/'), latindances) + streamciphers += map(lambda s: s.replace('/', ''), latindances) hashes = ''' md2 md4 md5 tiger has160 sha sha224 sha256 sha512/224 sha512/256 sha384 sha512 @@@ -96,7 -94,7 +96,7 @@@ for i in latindances if i.endswith('-ietf'): root += '_ietf' print ('\t_("%(name)s", %(root)s_keysz, %(id)s_rand, ' + 'RNG_LATIN, %(ROOT)s_NONCESZ) \\') % \ - {'name': i, 'id': i.translate(None, '/').replace('-', '_'), + {'name': i, 'id': i.replace('/', '').replace('-', '_'), 'root': root, 'ROOT': root.upper()} for i in [128, 256]: print ('\t_("shake%(w)d", shake%(w)d_keysz, cshake%(w)d_rand, ' + diff --combined buffer.c index b88232b,ac3e56b..5b7bb64 --- a/buffer.c +++ b/buffer.c @@@ -55,9 -55,9 +55,9 @@@ static PyObject *rbuf_pynew(PyTypeObjec char *p, *q; Py_ssize_t n; buf_pyobj *me = 0; - static char *kwlist[] = { "data", 0 }; + static const char *const kwlist[] = { "data", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &p, &n)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &p, &n)) goto end; q = xmalloc(n); memcpy(q, p, n); @@@ -112,7 -112,8 +112,8 @@@ end uint##n x; \ if (!PyArg_ParseTuple(arg, ":getu" #w)) goto end; \ if (buf_getu##w(BUF_B(me), &x)) BUFERR(); \ - return (getulong(x)); \ + if (MASK##W <= ULONG_MAX) return (getulong(x)); \ + else { kludge64 y; ASSIGN64(y, x); return (getk64(y)); } \ end: \ return (0); \ } @@@ -171,9 -172,9 +172,9 @@@ end static PyObject *rbmeth_getecpt(PyObject *me, PyObject *arg, PyObject *kw) { PyObject *cobj = Py_None; - static char *kwlist[] = { "curve", 0 }; + static const char *const kwlist[] = { "curve", 0 }; ec pt = EC_INIT; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:getecpt", kwlist, &cobj)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:getecpt", KWLIST, &cobj)) goto end; if (cobj == Py_None) cobj = (PyObject *)ecpt_pytype; if (!PyType_Check(cobj) || @@@ -261,14 -262,14 +262,14 @@@ static PyMethodDef rbuf_pymethods[] = METH(getu##w, "RBUF.getu" #w "() -> INT") DOUINTCONV(RBMETH_DECL_GETU_) #define RBMETH_DECL_GETBLK_(n, W, w) \ - METH(getblk##w, "RBUF.getblk" #w "() -> INT") + METH(getblk##w, "RBUF.getblk" #w "() -> BYTES") BUF_DOSUFFIXES(RBMETH_DECL_GETBLK_) #define RBMETH_DECL_GETBUF_(n, W, w) \ - METH(getbuf##w, "RBUF.getbuf" #w "() -> INT") + METH(getbuf##w, "RBUF.getbuf" #w "() -> RBUF'") BUF_DOSUFFIXES(RBMETH_DECL_GETBUF_) METH (getmp, "RBUF.getmp() -> X") METH (getgf, "RBUF.getgf() -> X") - KWMETH(getecpt, "RBUF.getecpt(curve = None) -> P") + KWMETH(getecpt, "RBUF.getecpt([curve = None]) -> P") METH (getecptraw, "RBUF.getecptraw(CURVE) -> P") METH (getge, "RBUF.getge(GROUP) -> X") METH (getgeraw, "RBUF.getgeraw(GROUP) -> X") @@@ -308,7 -309,7 +309,7 @@@ static PyTypeObject rbuf_pytype_skel = Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "A read buffer.", +"ReadBuffer(STR): a read buffer.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -354,9 -355,9 +355,9 @@@ static PyObject *wbuf_pynew(PyTypeObjec char *p; size_t n = 64; buf_pyobj *me = 0; - static char *kwlist[] = { "size", 0 }; + static const char *const kwlist[] = { "size", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", KWLIST, convszt, &n)) goto end; me = (buf_pyobj *)ty->tp_alloc(ty, 0); @@@ -405,16 -406,20 +406,20 @@@ static PyObject *wbmeth_put(PyObject *m } DOUINTCONV(WBMETH_PUTU_) + #define MASKz 0 #define SZ_z 1 #define WBMETH_PUTBLK_(n, W, w) \ static PyObject *wbmeth_putblk##w(PyObject *me, PyObject *arg) \ { \ char *p; \ Py_ssize_t sz; \ - if (!PyArg_ParseTuple(arg, "s#:putblk" #w, &p, &sz)) return (0); \ + if (!PyArg_ParseTuple(arg, "s#:putblk" #w, &p, &sz)) goto end; \ + if (MASK##W && sz > MASK##W) VALERR("too large"); \ ensure(me, sz + SZ_##n); \ buf_putmem##w(BUF_B(me), p, sz); assert(BOK(BUF_B(me))); \ RETURN_ME; \ + end: \ + return (0); \ } BUF_DOSUFFIXES(WBMETH_PUTBLK_) @@@ -441,8 -446,7 +446,7 @@@ static PyObject *wbmeth_putecpt(PyObjec { ec pt = EC_INIT; if (!PyArg_ParseTuple(arg, "O&:putecpt", convecpt, &pt)) return (0); - if (EC_ATINF(&pt)) ensure(me, 2); - else ensure(me, 4 + mp_octets(pt.x) + mp_octets(pt.y)); + ensure(me, EC_ATINF(&pt) ? 2 : 6 + mp_octets(pt.x) + mp_octets(pt.y)); buf_putec(BUF_B(me), &pt); assert(BOK(BUF_B(me))); EC_DESTROY(&pt); RETURN_ME; @@@ -482,13 -486,9 +486,13 @@@ static PyObject *wbmeth_putgeraw(PyObje static PyObject *wbget_size(PyObject *me, void *hunoz) { return (PyInt_FromLong(BLEN(BUF_B(me)))); } +static PyObject *wbget_contents(PyObject *me, void *hunoz) + { return (bytestring_pywrap(BBASE(BUF_B(me)), BLEN(BUF_B(me)))); } + static PyGetSetDef wbuf_pygetset[] = { #define GETSETNAME(op, name) wb##op##_##name GET (size, "WBUF.size -> SIZE") + GET (contents, "WBUF.contents -> STR") #undef GETSETNAME { 0 } }; @@@ -505,7 -505,7 +509,7 @@@ static PyMethodDef wbuf_pymethods[] = BUF_DOSUFFIXES(WBMETH_DECL_PUTBLK_) METH (putmp, "WBUF.putmp(X)") METH (putgf, "WBUF.putgf(X)") - KWMETH(putecpt, "WBUF.putecpt(P)") + METH (putecpt, "WBUF.putecpt(P)") METH (putecptraw, "WBUF.putecptraw(P)") METH (putge, "WBUF.putge(X)") METH (putgeraw, "WBUF.putgeraw(X)") @@@ -545,7 -545,7 +549,7 @@@ static PyTypeObject wbuf_pytype_skel = Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "A write buffer.", +"WriteBuffer([size = ?]): a write buffer.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ diff --combined catacomb-python.h index df29099,ad27461..6c1ae21 --- a/catacomb-python.h +++ b/catacomb-python.h @@@ -61,7 -61,6 +61,7 @@@ #include #include +#include #include #include #include @@@ -134,8 -133,8 +134,9 @@@ goto end; \ } while (0) #define VALERR(str) EXCERR(PyExc_ValueError, str) + #define OVFERR(str) EXCERR(PyExc_OverflowError, str) #define TYERR(str) EXCERR(PyExc_TypeError, str) +#define IXERR(str) EXCERR(PyExc_IndexError, str) #define ZDIVERR(str) EXCERR(PyExc_ZeroDivisionError, str) #define SYSERR(str) EXCERR(PyExc_SystemError, str) #define NIERR(str) EXCERR(PyExc_NotImplementedError, str) @@@ -147,7 -146,7 +148,7 @@@ PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); \ goto end; \ } while (0) - #define PGENERR do { pgenerr(); goto end; } while (0) + #define PGENERR(exc) do { pgenerr(exc); goto end; } while (0) #define CONVFUNC(ty, cty, ext) \ int conv##ty(PyObject *o, void *p) \ @@@ -173,7 -172,9 +174,9 @@@ } while (0) #define INITTYPE(ty, base) INITTYPE_META(ty, base, type) - #define INSERT(name, ob) do { \ + extern PyObject *home_module; + + #define INSERT(name, ob) do { \ PyObject *_o = (PyObject *)(ob); \ Py_INCREF(_o); \ PyModule_AddObject(mod, name, _o); \ @@@ -233,9 -234,8 +236,10 @@@ MODULES(DO return (d); \ } +#define KWLIST (/*unconst*/ char **)kwlist + - struct nameval { const char *name; unsigned long value; }; + struct nameval { const char *name; unsigned f; unsigned long value; }; + #define CF_SIGNED 1u extern void setconstants(PyObject *, const struct nameval *); extern PyObject *mexp_common(PyObject *, PyObject *, size_t, @@@ -259,7 -259,34 +263,34 @@@ extern PyObject *getulong(unsigned long extern PyObject *getk64(kludge64); extern void *newtype(PyTypeObject *, const PyTypeObject *, const char *); + struct excinfo { PyObject *ty, *val, *tb; }; + #define EXCINFO_INIT { 0, 0, 0 } + extern PyObject *mkexc(PyObject *, PyObject *, const char *, PyMethodDef *); + #define INIT_EXCINFO(exc) do { \ + struct excinfo *_exc = (exc); _exc->ty = _exc->val = _exc->tb = 0; \ + } while (0) + #define RELEASE_EXCINFO(exc) do { \ + struct excinfo *_exc = (exc); \ + Py_XDECREF(_exc->ty); _exc->ty = 0; \ + Py_XDECREF(_exc->val); _exc->val = 0; \ + Py_XDECREF(_exc->tb); _exc->tb = 0; \ + } while (0) + #define STASH_EXCINFO(exc) do { \ + struct excinfo *_exc = (exc); \ + PyErr_Fetch(&_exc->ty, &_exc->val, &_exc->tb); \ + PyErr_NormalizeException(&_exc->ty, &_exc->val, &_exc->tb); \ + } while (0) + #define RESTORE_EXCINFO(exc) do { \ + struct excinfo *_exc = (exc); \ + PyErr_Restore(_exc->ty, _exc->val, _exc->tb); \ + _exc->ty = _exc->val = _exc->tb = 0; \ + } while (0) + extern void report_lost_exception(struct excinfo *, const char *, ...); + extern void report_lost_exception_v(struct excinfo *, const char *, va_list); + extern void stash_exception(struct excinfo *, const char *, ...); + extern void restore_exception(struct excinfo *, const char *, ...); + extern void typeready(PyTypeObject *); extern PyTypeObject *inittype(PyTypeObject *, PyTypeObject *); extern void addmethods(const PyMethodDef *); @@@ -328,6 -355,7 +359,7 @@@ extern mp *getgf(PyObject *) extern int convgf(PyObject *, void *); extern PyObject *mp_pywrap(mp *); extern PyObject *gf_pywrap(mp *); + extern long mphash(mp *); extern mp *mp_frompyobject(PyObject *, int); extern PyObject *mp_topystring(mp *, int, const char *, const char *, const char *); @@@ -346,7 -374,6 +378,6 @@@ extern PyTypeObject *fe_pytype #define FE_FOBJ(o) ((PyObject *)(o)->ob_type) #define FE_X(o) (((fe_pyobj *)(o))->x) extern PyObject *fe_pywrap(PyObject *, mp *); - extern mp *getfe(field *, PyObject *); typedef struct fe_pyobj { PyObject_HEAD @@@ -504,130 -531,24 +535,130 @@@ typedef struct gccipher_pyobj extern PyTypeObject *gccipher_pytype; #define GCCIPHER_PYCHECK(o) PyObject_TypeCheck((o), gccipher_pytype) #define GCCIPHER_CC(o) (((gccipher_pyobj *)(o))->cc) -#define GCCIPHER_F(o) (((gccipher_pyobj *)(o))->f) extern PyObject *gccipher_pywrap(gccipher *); extern int convgccipher(PyObject *, void *); -extern int convgcipher(PyObject *, void *); typedef struct gcipher_pyobj { PyObject_HEAD - unsigned f; gcipher *c; } gcipher_pyobj; extern PyTypeObject *gcipher_pytype; #define GCIPHER_PYCHECK(o) PyObject_TypeCheck((o), gcipher_pytype) #define GCIPHER_C(o) (((gcipher_pyobj *)(o))->c) -#define GCIPHER_F(o) (((gcipher_pyobj *)(o))->f) -extern PyObject *gcipher_pywrap(PyObject *, gcipher *, unsigned); +extern PyObject *gcipher_pywrap(PyObject *, gcipher *); extern int convgcipher(PyObject *, void *); +typedef struct gcaead_pyobj { + PyHeapTypeObject ty; + gcaead *aec; + struct gcaeadaad_pyobj *aad; + struct gcaeadenc_pyobj *enc; + struct gcaeaddec_pyobj *dec; +} gcaead_pyobj; + +extern PyTypeObject *gcaead_pytype; +#define GCAEAD_PYCHECK(o) PyObject_TypeCheck((o), gcaead_pytype) +#define GCAEAD_AEC(o) (((gcaead_pyobj *)(o))->aec) +#define GCAEAD_AAD(o) (((gcaead_pyobj *)(o))->aad) +#define GCAEAD_ENC(o) (((gcaead_pyobj *)(o))->enc) +#define GCAEAD_DEC(o) (((gcaead_pyobj *)(o))->dec) +extern PyObject *gcaead_pywrap(gcaead *); +extern int convgcaead(PyObject *, void *); + +typedef struct gaeadkey_pyobj { + PyObject_HEAD + gaead_key *k; +} gaeadkey_pyobj; + +extern PyTypeObject *gaeadkey_pytype; +#define GAEADKEY_PYCHECK(o) PyObject_TypeCheck((o), gaeadkey_pytype) +#define GAEADKEY_K(o) (((gaeadkey_pyobj *)(o))->k) +extern PyObject *gaeadkey_pywrap(PyObject *, gaead_key *); +extern int convgaeadkey(PyObject *, void *); + +typedef struct gcaeadaad_pyobj { + PyHeapTypeObject ty; + gcaead_pyobj *key; +} gcaeadaad_pyobj; +#define GCAEADAAD_KEY(o) (((gcaeadaad_pyobj *)(o))->key) +extern PyTypeObject *gcaeadaad_pytype; + +typedef struct gaeadaad_pyobj { + PyObject_HEAD + gaead_aad *a; + unsigned f; +#define AEADF_DEAD 32768u + size_t hsz, hlen; +} gaeadaad_pyobj; + +extern PyTypeObject *gaeadaad_pytype; +#define GAEADAAD_PYCHECK(o) PyObject_TypeCheck((o), gaeadaad_pytype) +#define GAEADAAD_A(o) (((gaeadaad_pyobj *)(o))->a) +#define GAEADAAD_F(o) (((gaeadaad_pyobj *)(o))->f) +#define GAEADAAD_HSZ(o) (((gaeadaad_pyobj *)(o))->hsz) +#define GAEADAAD_HLEN(o) (((gaeadaad_pyobj *)(o))->hlen) +extern PyObject *gaeadaad_pywrap(PyObject *, gaead_aad *, unsigned, size_t); +extern int convgaeadaad(PyObject *, void *); + +typedef struct gcaeadenc_pyobj { + PyHeapTypeObject ty; + gcaead_pyobj *key; +} gcaeadenc_pyobj; +#define GCAEADENC_KEY(o) (((gcaeadenc_pyobj *)(o))->key) +extern PyTypeObject *gcaeadenc_pytype; + +typedef struct gaeadenc_pyobj { + PyObject_HEAD + gaead_enc *e; + gaeadaad_pyobj *aad; + unsigned f; + size_t hsz, msz, tsz; + size_t mlen; +} gaeadenc_pyobj; + +extern PyTypeObject *gaeadenc_pytype; +#define GAEADENC_PYCHECK(o) PyObject_TypeCheck((o), gaeadenc_pytype) +#define GAEADENC_AAD(o) (((gaeadenc_pyobj *)(o))->aad) +#define GAEADENC_E(o) (((gaeadenc_pyobj *)(o))->e) +#define GAEADENC_F(o) (((gaeadenc_pyobj *)(o))->f) +#define GAEADENC_HSZ(o) (((gaeadenc_pyobj *)(o))->hsz) +#define GAEADENC_MSZ(o) (((gaeadenc_pyobj *)(o))->msz) +#define GAEADENC_TSZ(o) (((gaeadenc_pyobj *)(o))->tsz) +#define GAEADENC_MLEN(o) (((gaeadenc_pyobj *)(o))->mlen) +extern PyObject *gaeadenc_pywrap(PyObject *, gaead_enc *, unsigned, + size_t, size_t, size_t); +extern int convgaeadenc(PyObject *, void *); + +typedef struct gcaeaddec_pyobj { + PyHeapTypeObject ty; + gcaead_pyobj *key; +} gcaeaddec_pyobj; +#define GCAEADDEC_KEY(o) (((gcaeaddec_pyobj *)(o))->key) +extern PyTypeObject *gcaeaddec_pytype; + +typedef struct gaeaddec_pyobj { + PyObject_HEAD + gaead_dec *d; + gaeadaad_pyobj *aad; + unsigned f; + size_t hsz, csz, tsz; + size_t clen; +} gaeaddec_pyobj; + +extern PyTypeObject *gaeaddec_pytype; +#define GAEADDEC_PYCHECK(o) PyObject_TypeCheck((o), gaeaddec_pytype) +#define GAEADDEC_AAD(o) (((gaeaddec_pyobj *)(o))->aad) +#define GAEADDEC_D(o) (((gaeaddec_pyobj *)(o))->d) +#define GAEADDEC_F(o) (((gaeaddec_pyobj *)(o))->f) +#define GAEADDEC_HSZ(o) (((gaeaddec_pyobj *)(o))->hsz) +#define GAEADDEC_CSZ(o) (((gaeaddec_pyobj *)(o))->csz) +#define GAEADDEC_TSZ(o) (((gaeaddec_pyobj *)(o))->tsz) +#define GAEADDEC_CLEN(o) (((gaeaddec_pyobj *)(o))->clen) +extern PyObject *gaeaddec_pywrap(PyObject *, gaead_dec *, unsigned, + size_t, size_t, size_t); +extern int convgaeaddec(PyObject *, void *); + typedef struct gchash_pyobj { PyHeapTypeObject ty; gchash *ch; @@@ -636,11 -557,13 +667,11 @@@ extern PyTypeObject *gchash_pytype; #define GCHASH_PYCHECK(o) PyObject_TypeCheck((o), gchash_pytype) #define GCHASH_CH(o) (((gchash_pyobj *)(o))->ch) -#define GCHASH_F(o) (((gchash_pyobj *)(o))->f) extern PyObject *gchash_pywrap(gchash *); extern int convgchash(PyObject *, void *); typedef struct ghash_pyobj { PyObject_HEAD - unsigned f; ghash *h; } ghash_pyobj; @@@ -648,7 -571,8 +679,7 @@@ extern PyTypeObject *ghash_pytype, *gmh extern PyObject *sha_pyobj, *has160_pyobj; #define GHASH_PYCHECK(o) PyObject_TypeCheck((o), ghash_pytype) #define GHASH_H(o) (((ghash_pyobj *)(o))->h) -#define GHASH_F(o) (((ghash_pyobj *)(o))->f) -extern PyObject *ghash_pywrap(PyObject *, ghash *, unsigned); +extern PyObject *ghash_pywrap(PyObject *, ghash *); extern int convghash(PyObject *, void *); extern int convgmhash(PyObject *, void *); @@@ -666,6 -590,7 +697,6 @@@ extern int convgcmac(PyObject *, void * typedef struct gmac_pyobj { PyHeapTypeObject ty; - unsigned f; gmac *m; } gmac_pyobj; @@@ -673,7 -598,7 +704,7 @@@ extern PyTypeObject *gmac_pytype #define GMAC_PYCHECK(o) PyObject_TypeCheck((o), gmac_pytype) #define GMAC_M(o) (((gmac_pyobj *)(o))->m) #define GMAC_F(o) (((gmac_pyobj *)(o))->f) -extern PyObject *gmac_pywrap(PyObject *, gmac *, unsigned); +extern PyObject *gmac_pywrap(PyObject *, gmac *); extern int convgmac(PyObject *, void *); /*----- Key generation ----------------------------------------------------*/ @@@ -700,9 -625,15 +731,15 @@@ extern PyTypeObject *pgev_pytype #define PGEV_PYCHECK(o) PyObject_TypeCheck(o, pgev_pytype) #define PGEV_PG(o) (&((pgev_pyobj *)(o))->pg) + typedef struct pypgev { + pgev ev; + PyObject *obj; + struct excinfo *exc; + } pypgev; + extern int convpgev(PyObject *, void *); - extern void droppgev(pgev *); - extern void pgenerr(void); + extern void droppgev(pypgev *); + extern void pgenerr(struct excinfo *exc); /*----- That's all, folks -------------------------------------------------*/ diff --combined catacomb.c index b596b5e,e24e5ec..e9c9513 --- a/catacomb.c +++ b/catacomb.c @@@ -31,14 -31,16 +31,16 @@@ /*----- Main code ---------------------------------------------------------*/ static const struct nameval consts[] = { - #define C(x) { #x, x } + #define CF(f, x) { #x, f, x } + #define C(x) { #x, (x) >= 0 ? 0 : CF_SIGNED, x } C(FTY_PRIME), C(FTY_BINARY), C(PGEN_PASS), C(PGEN_FAIL), C(PGEN_BEGIN), C(PGEN_TRY), C(PGEN_DONE), C(PGEN_ABORT), C(MPW_MAX), + C(RAND_IBITS), C(PMODE_READ), C(PMODE_VERIFY), C(KOPEN_READ), C(KOPEN_WRITE), C(KOPEN_NOFILE), - C(KEXP_FOREVER), C(KEXP_EXPIRE), + CF(0, KEXP_FOREVER), CF(0, KEXP_EXPIRE), C(KF_ENCMASK), C(KENC_BINARY), C(KENC_MP), C(KENC_STRUCT), C(KENC_ENCRYPT), C(KENC_STRING), C(KENC_EC), C(KF_CATMASK), C(KCAT_SYMM), C(KCAT_PRIV), C(KCAT_PUB), C(KCAT_SHARE), @@@ -50,12 -52,11 +52,13 @@@ C(ED25519_KEYSZ), C(ED25519_PUBSZ), C(ED25519_SIGSZ), C(ED25519_MAXPERSOSZ), C(ED448_KEYSZ), C(ED448_PUBSZ), C(ED448_SIGSZ), C(ED448_MAXPERSOSZ), + C(AEADF_PCHSZ), C(AEADF_PCMSZ), C(AEADF_PCTSZ), + C(AEADF_AADNDEP), C(AEADF_AADFIRST), C(AEADF_NOAAD), #define ENTRY(tag, val, str) C(KERR_##tag), KEY_ERRORS(ENTRY) #undef ENTRY #undef C + #undef CF { 0 } }; @@@ -75,7 -76,8 +78,8 @@@ PyObject *mexp_common(PyObject *me, PyO arg = PyTuple_GetItem(arg, 0); Py_INCREF(arg); if (!PySequence_Check(arg)) TYERR("not a sequence"); - n = PySequence_Size(arg); if (!n) { z = id(me); goto end; } + n = PySequence_Size(arg); if (n < 0) goto end; + if (!n) { z = id(me); goto end; } x = PySequence_GetItem(arg, 0); if (PySequence_Check(x)) flat = 0; diff --combined catacomb/__init__.py index 8038815,24265ac..9178475 --- a/catacomb/__init__.py +++ b/catacomb/__init__.py @@@ -27,7 -27,8 +27,8 @@@ from __future__ import with_statemen from binascii import hexlify as _hexify, unhexlify as _unhexify from contextlib import contextmanager as _ctxmgr - import DLFCN as _dlfcn + try: import DLFCN as _dlfcn + except ImportError: _dlfcn = None import os as _os from struct import pack as _pack import sys as _sys @@@ -67,6 -68,15 +68,15 @@@ del _dlflags, _odlflag ## For the benefit of the default keyreporter, we need the program name. _base._ego(_sys.argv[0]) + ## Register our module. + _base._set_home_module(_sys.modules[__name__]) + def default_lostexchook(why, ty, val, tb): + """`catacomb.lostexchook(WHY, TY, VAL, TB)' reports lost exceptions.""" + _sys.stderr.write("\n\n!!! LOST EXCEPTION: %s\n" % why) + _sys.excepthook(ty, val, tb) + _sys.stderr.write("\n") + lostexchook = default_lostexchook + ## How to fix a name back into the right identifier. Alas, the rules are not ## consistent. def _fixname(name): @@@ -75,7 -85,7 +85,7 @@@ name = name.replace('-', '_') ## But slashes might become underscores or just vanish. - if name.startswith('salsa20'): name = name.translate(None, '/') + if name.startswith('salsa20'): name = name.replace('/', '') else: name = name.replace('/', '_') ## Done. @@@ -102,7 -112,7 +112,7 @@@ def _init() for j in b: if j[:plen] == pre: setattr(c, j[plen:], classmethod(b[j])) - for i in [gcciphers, gchashes, gcmacs, gcprps]: + for i in [gcciphers, gcaeads, gchashes, gcmacs, gcprps]: for c in i.itervalues(): d[_fixname(c.name)] = c for c in gccrands.itervalues(): @@@ -183,27 -193,6 +193,27 @@@ _augment(ByteString, _tmp ByteString.__hash__ = str.__hash__ bytes = ByteString.fromhex +###-------------------------------------------------------------------------- +### Symmetric encryption. + +class _tmp: + def encrypt(me, n, m, tsz = None, h = ByteString('')): + if tsz is None: tsz = me.__class__.tagsz.default + e = me.enc(n, len(h), len(m), tsz) + if not len(h): a = None + else: a = e.aad().hash(h) + c0 = e.encrypt(m) + c1, t = e.done(aad = a) + return c0 + c1, t + def decrypt(me, n, c, t, h = ByteString('')): + d = me.dec(n, len(h), len(c), len(t)) + if not len(h): a = None + else: a = d.aad().hash(h) + m = d.decrypt(c) + m += d.done(t, aad = a) + return m +_augment(GAEKey, _tmp) + ###-------------------------------------------------------------------------- ### Hashing. @@@ -217,15 -206,31 +227,31 @@@ _augment(Poly1305Hash, _tmp class _HashBase (object): ## The standard hash methods. Assume that `hash' is defined and returns ## the receiver. - def hashu8(me, n): return me.hash(_pack('B', n)) - def hashu16l(me, n): return me.hash(_pack('H', n)) + def _check_range(me, n, max): + if not (0 <= n <= max): raise OverflowError("out of range") + def hashu8(me, n): + me._check_range(n, 0xff) + return me.hash(_pack('B', n)) + def hashu16l(me, n): + me._check_range(n, 0xffff) + return me.hash(_pack('H', n)) hashu16 = hashu16b - def hashu32l(me, n): return me.hash(_pack('L', n)) + def hashu32l(me, n): + me._check_range(n, 0xffffffff) + return me.hash(_pack('L', n)) hashu32 = hashu32b - def hashu64l(me, n): return me.hash(_pack('Q', n)) + def hashu64l(me, n): + me._check_range(n, 0xffffffffffffffff) + return me.hash(_pack('Q', n)) hashu64 = hashu64b def hashbuf8(me, s): return me.hashu8(len(s)).hash(s) def hashbuf16l(me, s): return me.hashu16l(len(s)).hash(s) @@@ -248,8 -253,8 +274,8 @@@ class _ShakeBase (_HashBase) me._h = me._SHAKE(perso = perso, func = me._FUNC) ## Delegate methods... - def copy(me): new = me.__class__(); new._copy(me) - def _copy(me, other): me._h = other._h + def copy(me): new = me.__class__._bare_new(); new._copy(me); return new + def _copy(me, other): me._h = other._h.copy() def hash(me, m): me._h.hash(m); return me def xof(me): me._h.xof(); return me def get(me, n): return me._h.get(n) @@@ -262,6 -267,8 +288,8 @@@ def buffered(me): return me._h.buffered @property def rate(me): return me._h.rate + @classmethod + def _bare_new(cls): return cls() class _tmp: def check(me, h): @@@ -286,7 -293,7 +314,7 @@@ me.bytepad_after() _augment(Shake, _tmp) _augment(_ShakeBase, _tmp) -Shake._Z = _ShakeBase._Z = ByteString(200*'\0') +Shake._Z = _ShakeBase._Z = ByteString.zero(200) class KMAC (_ShakeBase): _FUNC = 'KMAC' @@@ -300,6 -307,8 +328,8 @@@ def xof(me): me.rightenc(0) return super(KMAC, me).xof() + @classmethod + def _bare_new(cls): return cls("") class KMAC128 (KMAC): _SHAKE = Shake128; _TAGSZ = 16 class KMAC256 (KMAC): _SHAKE = Shake256; _TAGSZ = 32 @@@ -308,12 -317,21 +338,12 @@@ ### NaCl `secretbox'. def secret_box(k, n, m): - E = xsalsa20(k).setiv(n) - r = E.enczero(poly1305.keysz.default) - s = E.enczero(poly1305.masksz) - y = E.encrypt(m) - t = poly1305(r)(s).hash(y).done() - return ByteString(t + y) + y, t = salsa20_naclbox(k).encrypt(n, m) + return t + y def secret_unbox(k, n, c): - E = xsalsa20(k).setiv(n) - r = E.enczero(poly1305.keysz.default) - s = E.enczero(poly1305.masksz) - y = c[poly1305.tagsz:] - if not poly1305(r)(s).hash(y).check(c[0:poly1305.tagsz]): - raise ValueError, 'decryption failed' - return E.decrypt(c[poly1305.tagsz:]) + tsz = poly1305.tagsz + return salsa20_naclbox(k).decrypt(n, c[tsz:], c[0:tsz]) ###-------------------------------------------------------------------------- ### Multiprecision integers and binary polynomials. @@@ -353,15 -371,18 +383,18 @@@ class BaseRat (object) def __mul__(me, you): n, d = _split_rat(you) return type(me)(me._n*n, me._d*d) - def __div__(me, you): + __rmul__ = __mul__ + def __truediv__(me, you): n, d = _split_rat(you) return type(me)(me._n*d, me._d*n) - def __rdiv__(me, you): + def __rtruediv__(me, you): n, d = _split_rat(you) return type(me)(me._d*n, me._n*d) + __div__ = __truediv__ + __rdiv__ = __rtruediv__ def __cmp__(me, you): n, d = _split_rat(you) - return type(me)(me._n*d, n*me._d) + return cmp(me._n*d, n*me._d) def __rcmp__(me, you): n, d = _split_rat(you) return cmp(n*me._d, me._n*d) @@@ -381,8 -402,10 +414,10 @@@ class _tmp def mont(x): return MPMont(x) def barrett(x): return MPBarrett(x) def reduce(x): return MPReduce(x) - def __div__(me, you): return IntRat(me, you) - def __rdiv__(me, you): return IntRat(you, me) + def __truediv__(me, you): return IntRat(me, you) + def __rtruediv__(me, you): return IntRat(you, me) + __div__ = __truediv__ + __rdiv__ = __rtruediv__ _repr_pretty_ = _pp_str _augment(MP, _tmp) @@@ -393,8 -416,10 +428,10 @@@ class _tmp def halftrace(x, y): return x.reduce().halftrace(y) def modsqrt(x, y): return x.reduce().sqrt(y) def quadsolve(x, y): return x.reduce().quadsolve(y) - def __div__(me, you): return GFRat(me, you) - def __rdiv__(me, you): return GFRat(you, me) + def __truediv__(me, you): return GFRat(me, you) + def __rtruediv__(me, you): return GFRat(you, me) + __div__ = __truediv__ + __rdiv__ = __rtruediv__ _repr_pretty_ = _pp_str _augment(GF, _tmp) @@@ -561,7 -586,6 +598,7 @@@ class _tmp def __repr__(me): return '%s(%d)' % (_clsname(me), me.default) def check(me, sz): return True def best(me, sz): return sz + def pad(me, sz): return sz _augment(KeySZAny, _tmp) class _tmp: @@@ -578,15 -602,11 +615,15 @@@ pp.pretty(me.max); pp.text(','); pp.breakable() pp.pretty(me.mod) pp.end_group(ind, ')') - def check(me, sz): return me.min <= sz <= me.max and sz % me.mod == 0 + def check(me, sz): return me.min <= sz <= me.max and sz%me.mod == 0 def best(me, sz): if sz < me.min: raise ValueError, 'key too small' elif sz > me.max: return me.max - else: return sz - (sz % me.mod) + else: return sz - sz%me.mod + def pad(me, sz): + if sz > me.max: raise ValueError, 'key too large' + elif sz < me.min: return me.min + else: sz += me.mod; return sz - sz%me.mod _augment(KeySZRange, _tmp) class _tmp: @@@ -608,12 -628,6 +645,12 @@@ if found < i <= sz: found = i if found < 0: raise ValueError, 'key too small' return found + def pad(me, sz): + found = -1 + for i in me.set: + if sz <= i and (found == -1 or i < found): found = i + if found < 0: raise ValueError, 'key too large' + return found _augment(KeySZSet, _tmp) ###-------------------------------------------------------------------------- @@@ -852,23 -866,21 +889,23 @@@ _augment(RSAPriv, _tmp ### DSA and related schemes. class _tmp: - def __repr__(me): return '%s(G = %r, p = %r)' % (_clsname(me), me.G, me.p) + def __repr__(me): return '%s(G = %r, p = %r, hash = %r)' % \ + (_clsname(me), me.G, me.p, me.hash) def _repr_pretty_(me, pp, cyclep): ind = _pp_bgroup_tyname(pp, me) if cyclep: pp.text('...') else: _pp_kv(pp, 'G', me.G); pp.text(','); pp.breakable() - _pp_kv(pp, 'p', me.p) + _pp_kv(pp, 'p', me.p); pp.text(','); pp.breakable() + _pp_kv(pp, 'hash', me.hash) pp.end_group(ind, ')') _augment(DSAPub, _tmp) _augment(KCDSAPub, _tmp) class _tmp: - def __repr__(me): return '%s(G = %r, u = %s, p = %r)' % \ - (_clsname(me), me.G, _repr_secret(me.u), me.p) + def __repr__(me): return '%s(G = %r, u = %s, p = %r, hash = %r)' % \ + (_clsname(me), me.G, _repr_secret(me.u), me.p, me.hash) def _repr_pretty_(me, pp, cyclep): ind = _pp_bgroup_tyname(pp, me) if cyclep: @@@ -876,8 -888,7 +913,8 @@@ else: _pp_kv(pp, 'G', me.G); pp.text(','); pp.breakable() _pp_kv(pp, 'u', me.u, True); pp.text(','); pp.breakable() - _pp_kv(pp, 'p', me.p) + _pp_kv(pp, 'p', me.p); pp.text(','); pp.breakable() + _pp_kv(pp, 'hash', me.hash) pp.end_group(ind, ')') _augment(DSAPriv, _tmp) _augment(KCDSAPriv, _tmp) diff --combined debian/changelog index 866bc90,ca06b5c..0398864 --- a/debian/changelog +++ b/debian/changelog @@@ -1,26 -1,9 +1,32 @@@ +catacomb-python (1.3.0.1) experimental; urgency=medium + + * Fix required Catacomb version in `setup.py' script. Only affects the + source package. + + -- Mark Wooding Sun, 22 Sep 2019 01:21:28 +0100 + +catacomb-python (1.3.0) experimental; urgency=medium + + * catacomb: Bindings for new blockcipher-based MACs, and AEAD schemes. + * catacomb: Invalidate `grand' objects passed into Python through prime- + generation events. + * catacomb: Improve class docstrings. (They're still extremely terse.) + * catacomb: Add missing `copy' methods on hash and Keccak objects. + * catacomb: Add `WriteBuffer.contents' as a more convenient way to + extract the contents than coercing to `str' or `ByteString'. + * catacomb: Set `RTLD_DEEPBIND' while loading the native module to work + around #868366. + * pock: New program for generating efficiently verifiable prime numbers, + and for verifying their certificates. + + -- Mark Wooding Sat, 21 Sep 2019 23:00:25 +0100 + + catacomb-python (1.2.1.1) experimental; urgency=medium + + * Fixing to build against Debian `stretch'. + + -- Mark Wooding Mon, 24 Dec 2018 15:21:08 +0000 + catacomb-python (1.2.1) experimental; urgency=low * Fix use-after-free bug in ECPt hashing causing hash instability. diff --combined debian/control index 24197f4,61f54a8..1bde721 --- a/debian/control +++ b/debian/control @@@ -3,9 -3,9 +3,9 @@@ Section: pytho Priority: extra XS-Python-Version: >= 2.6, << 2.8 Maintainer: Mark Wooding - Build-Depends: debhelper (>= 9), pkg-config, + Build-Depends: debhelper (>= 9), dh-python, pkg-config, python (>= 2.6.6-3~), python-all-dev, - mlib-dev (>= 2.2.2.1), catacomb-dev (>= 2.4.0) + mlib-dev (>= 2.2.2.1), catacomb-dev (>= 2.5.0) Standards-Version: 3.8.0 Package: python-catacomb diff --combined ec.c index f7d6181,361bbf5..184dc9e --- a/ec.c +++ b/ec.c @@@ -188,38 -188,31 +188,31 @@@ static PyObject *ecpt_pymul(PyObject *x 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) { 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); - h = unihash_hash(&unihash_global, h, BBASE(&b), BLEN(&b)); - xfree(q); - 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; @@@ -259,7 -252,7 +252,7 @@@ static PyObject *epmeth_tobuf(PyObject 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_putec(&b, &p); @@@ -297,11 -290,12 +290,12 @@@ static PyObject *epmeth_ec2osp(PyObjec 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, ++ if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:ec2osp", KWLIST, + convuint, &f)) return (0); len = c->f->noctets * 2 + 1; rc = bytestring_pywrap(0, len); @@@ -419,9 -413,9 +413,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; @@@ -459,7 -453,7 +453,7 @@@ static int ecptxl_1(ec_curve *c, ec *p getecptout(p, x); goto fix; } else if (PyString_Check(x)) { - if (PyObject_AsReadBuffer(x, &q, 0)) + if (PyObject_AsReadBuffer(x, &q, &n)) goto end; qd.p = q; qd.e = 0; @@@ -471,7 -465,7 +465,7 @@@ 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 -473,7 +473,7 @@@ (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 -502,14 +502,14 @@@ static PyObject *ecptnc_pynew(PyTypeObj { 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); } @@@ -548,15 -543,15 +543,15 @@@ static PyObject *ecpt_pynew(PyTypeObjec { 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); } @@@ -645,9 -640,7 +640,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@ */ @@@ -789,10 -782,14 +784,14 @@@ static PyTypeObject ecptcurve_pytype_sk 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)); @@@ -863,12 -860,12 +862,12 @@@ static PyObject *meth__ECPtCurve_os2ecp buf b; PyObject *rc = 0; ec_curve *cc; - int f = EC_XONLY | EC_LSB | EC_SORT | EC_EXPLY; + unsigned f = EC_XONLY | EC_LSB | EC_SORT | EC_EXPLY; ec pp = EC_INIT; - static const char *const kwlist[] = { "buf", "flags", 0 }; - char *kwlist[] = { "class", "buf", "flags", 0 }; ++ static const char *const kwlist[] = { "class", "buf", "flags", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|f:os2ecp", KWLIST, - &me, &p, &len, &f)) - if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|O&:os2ecp", kwlist, ++ if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|O&:os2ecp", KWLIST, + &me, &p, &len, convuint, &f)) return (0); buf_init(&b, p, len); cc = ECCURVE_C(me); @@@ -943,11 -940,11 +942,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); @@@ -1003,10 -1000,10 +1002,10 @@@ static PyObject *eccurve_pynew(PyTypeOb { 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; @@@ -1067,7 -1064,7 +1066,7 @@@ static PyMethodDef eccurve_pymethods[] 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") #undef METHNAME { 0 } }; @@@ -1097,7 -1094,7 +1096,7 @@@ static PyTypeObject eccurve_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "An elliptic curve. Abstract class.", +"An elliptic curve. Abstract class.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1151,8 -1148,7 +1150,8 @@@ static PyTypeObject ecprimecurve_pytype 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@ */ @@@ -1206,8 -1202,7 +1205,8 @@@ static PyTypeObject ecprimeprojcurve_py 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@ */ @@@ -1261,8 -1256,7 +1260,8 @@@ static PyTypeObject ecbincurve_pytype_s 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@ */ @@@ -1316,8 -1310,7 +1315,8 @@@ static PyTypeObject ecbinprojcurve_pyty 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@ */ @@@ -1378,10 -1371,10 +1377,10 @@@ static PyObject *ecinfo_pynew(PyTypeObj { 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; @@@ -1449,11 -1442,11 +1448,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) @@@ -1492,7 -1485,7 +1491,7 @@@ static PyGetSetDef ecinfo_pygetset[] = static PyMethodDef ecinfo_pymethods[] = { #define METHNAME(name) eimeth_##name - KWMETH(check, "I.check() -> None") + KWMETH(check, "I.check([rng = rand]) -> None") #undef METHNAME { 0 } }; @@@ -1522,7 -1515,7 +1521,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@ */ diff --combined field.c index f2a0d2f,224363d..c23f311 --- a/field.c +++ b/field.c @@@ -42,9 -42,9 +42,9 @@@ static PyObject *fe_pynew(PyTypeObject { PyObject *x; mp *z; - char *kwlist[] = { "x", 0 }; + static const char *const kwlist[] = { "x", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:fe", kwlist, &x)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:fe", KWLIST, &x)) return (0); if (FE_PYCHECK(x) && FE_F(x) == FIELD_F(ty)) RETURN_OBJ(x); if ((z = getmp(x)) == 0) return (0); @@@ -126,16 -126,6 +126,6 @@@ static mp *tofe(field *f, PyObject *o return (y); } - mp *getfe(field *f, PyObject *o) - { - mp *x = 0; - if ((x = tofe(f, o)) == 0) { - PyErr_Format(PyExc_TypeError, "can't convert %.100s to fe", - o->ob_type->tp_name); - } - return (x); - } - /*----- Field elements ----------------------------------------------------*/ static int febinop(PyObject *x, PyObject *y, @@@ -229,15 -219,7 +219,7 @@@ end } static long fe_pyhash(PyObject *me) - { - size_t sz = FE_F(me)->noctets; - uint32 h = 0xe0c127ca + FE_F(me)->ops->ty; - octet *p = xmalloc(sz); - mp_storeb(FE_X(me), p, sz); - h = unihash_hash(&unihash_global, h, p, sz); - xfree(p); - return (h % LONG_MAX); - } + { return (mphash(FE_X(me))); } static int fe_pycoerce(PyObject **x, PyObject **y) { @@@ -282,7 -264,7 +264,7 @@@ static PyObject *fe_pylong(PyObject *x #define BASEOP(name, radix, pre) \ static PyObject *fe_py##name(PyObject *x) { \ mp *xx = F_OUT(FE_F(x), MP_NEW, FE_X(x)); \ - PyObject *rc = mp_topystring(FE_X(x), radix, 0, pre, 0); \ + PyObject *rc = mp_topystring(xx, radix, 0, pre, 0); \ MP_DROP(xx); \ return (rc); \ } @@@ -345,8 -327,8 +327,8 @@@ static PyObject *feget__value(PyObject static PyGetSetDef fe_pygetset[] = { #define GETSETNAME(op, name) fe##op##_##name GET (field, "X.field -> field containing X") - GET (value, "X.value -> `natural' integer representation of X") - GET (_value, "X._value -> internal integer representation of X") + GET (value, "X.value -> `natural' MP/GF representation of X") + GET (_value, "X._value -> internal MP/GF representation of X") #undef GETSETNAME { 0 } }; @@@ -474,10 -456,10 +456,10 @@@ end static PyObject *fmeth_rand(PyObject *me, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "rng", 0 }; + static const char *const kwlist[] = { "rng", 0 }; grand *r = &rand_global; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:rand", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:rand", KWLIST, convgrand, &r)) return (0); return (fe_pywrap(me, F_RAND(FIELD_F(me), MP_NEW, r))); @@@ -533,7 -515,7 +515,7 @@@ static PyGetSetDef field_pygetset[] = static PyMethodDef field_pymethods[] = { #define METHNAME(name) fmeth_##name METH (_adopt, "F._adopt(X) -> FE") - KWMETH(rand, "F.rand(rng = rand) -> FE, uniformly distributed") + KWMETH(rand, "F.rand([rng = rand]) -> FE, uniformly distributed") #undef METHNAME { 0 } }; @@@ -593,9 -575,9 +575,9 @@@ static PyObject *primefield_pynew(PyTyp { mp *xx = 0; field *f; - char *kwlist[] = { "p", 0 }; + static const char *const kwlist[] = { "p", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:primefield", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:primefield", KWLIST, convmp, &xx)) goto end; if ((f = field_prime(xx)) == 0) @@@ -641,7 -623,7 +623,7 @@@ static PyTypeObject primefield_pytype_s Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Prime fields.", +"PrimeField(P): prime fields.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -669,10 -651,10 +651,10 @@@ static PyObject *niceprimefield_pynew(P { mp *xx = 0; field *f; - char *kwlist[] = { "p", 0 }; + static const char *const kwlist[] = { "p", 0 }; if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:niceprimefield", - kwlist, convmp, &xx)) + KWLIST, convmp, &xx)) goto end; if ((f = field_niceprime(xx)) == 0) VALERR("bad prime for niceprimefield"); @@@ -708,7 -690,7 +690,7 @@@ static PyTypeObject niceprimefield_pyty Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Nice prime fields.", +"NicePrimeField(P): prime field using Solinas reduction.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -768,7 -750,7 +750,7 @@@ static PyTypeObject binfield_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Binary fields. Abstract class.", +"Binary fields. Abstract class.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -796,9 -778,9 +778,9 @@@ static PyObject *binpolyfield_pynew(PyT { mp *xx = 0; field *f; - char *kwlist[] = { "p", 0 }; + static const char *const kwlist[] = { "p", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:binpolyfield", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:binpolyfield", KWLIST, convgf, &xx)) goto end; if ((f = field_binpoly(xx)) == 0) VALERR("bad poly for binpolyfield"); @@@ -809,8 -791,11 +791,11 @@@ end return (0); } + static PyObject *bfget_p(PyObject *me, void *hunoz) + { return (gf_pywrap(MP_COPY(FIELD_F(me)->m))); } + static PyGetSetDef binpolyfield_pygetset[] = { - #define GETSETNAME(op, name) pf##op##_##name + #define GETSETNAME(op, name) bf##op##_##name GET (p, "F.p -> field polynomial") #undef GETSETNAME { 0 } @@@ -841,7 -826,7 +826,7 @@@ static PyTypeObject binpolyfield_pytype Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Binary fields with polynomial basis representation.", +"BinPolyField(P): binary fields with polynomial basis representation.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -869,10 -854,10 +854,10 @@@ static PyObject *binnormfield_pynew(PyT { mp *xx = 0, *yy = 0; field *f; - char *kwlist[] = { "p", "beta", 0 }; + static const char *const kwlist[] = { "p", "beta", 0 }; if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:binnormfield", - kwlist, convgf, &xx, convgf, &yy)) + KWLIST, convgf, &xx, convgf, &yy)) goto end; if ((f = field_binnorm(xx, yy)) == 0) VALERR("bad args for binnormfield"); MP_DROP(xx); MP_DROP(yy); @@@ -889,7 -874,7 +874,7 @@@ static PyObject *bnfget_beta(PyObject * } static PyGetSetDef binnormfield_pygetset[] = { - #define GETSETNAME(op, name) pf##op##_##name + #define GETSETNAME(op, name) bf##op##_##name GET (p, "F.p -> field polynomial") #undef GETSETNAME #define GETSETNAME(op, name) bnf##op##_##name @@@ -923,7 -908,7 +908,7 @@@ static PyTypeObject binnormfield_pytype Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Binary fields with normal basis representation.", +"BinNormField(P, BETA): binary fields with normal basis representation.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ diff --combined group.c index b5a1815,e00e3fb..3d29070 --- a/group.c +++ b/group.c @@@ -40,11 -40,11 +40,11 @@@ PyObject *fginfo_pywrap(gprime_param *d static PyObject *fginfo_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "p", "r", "g", 0 }; + static const char *const kwlist[] = { "p", "r", "g", 0 }; gprime_param dp = { 0 }; fginfo_pyobj *z = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&O&:new", KWLIST, convmp, &dp.p, convmp, &dp.q, convmp, &dp.g)) @@@ -92,18 -92,20 +92,20 @@@ static PyObject *meth__DHInfo_generate( unsigned ql = 0, pl; unsigned steps = 0; grand *r = &rand_global; - pgev evt = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev evt = { { 0 } }; - char *kwlist[] = + static const char *const kwlist[] = { "class", "pbits", "qbits", "event", "rng", "nsteps", 0 }; PyObject *rc = 0; + evt.exc = &exc; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&|O&O&O&O&:generate", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&|O&O&O&O&:generate", KWLIST, &me, convuint, &pl, convuint, &ql, convpgev, &evt, convgrand, &r, convuint, &steps)) goto end; - if (dh_gen(&dp, ql, pl, steps, r, evt.proc, evt.ctx)) - PGENERR; + if (dh_gen(&dp, ql, pl, steps, r, evt.ev.proc, evt.ev.ctx)) + PGENERR(&exc); rc = fginfo_pywrap(&dp, dhinfo_pytype); end: droppgev(&evt); @@@ -117,19 -119,19 +119,21 @@@ static PyObject *meth__DHInfo_genlimlee unsigned ql, pl; unsigned steps = 0; grand *r = &rand_global; - pgev oe = { 0 }, ie = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev oe = { { 0 } }, ie = { { 0 } }; int subgroupp = 1; unsigned f = 0; - char *kwlist[] = { "class", "pbits", "qbits", "event", "ievent", - "rng", "nsteps", "subgroupp", 0 }; + static const char *const kwlist[] = { + "class", "pbits", "qbits", "event", "ievent", + "rng", "nsteps", "subgroupp", 0 + }; size_t i, nf; mp **v = 0; PyObject *rc = 0, *vec = 0; + oe.exc = ie.exc = &exc; if (!PyArg_ParseTupleAndKeywords(arg, kw, - "OO&O&|O&O&O&O&O&:genlimlee", kwlist, + "OO&O&|O&O&O&O&O&:genlimlee", KWLIST, &me, convuint, &pl, convuint, &ql, convpgev, &oe, convpgev, &ie, convgrand, &r, convuint, &steps, @@@ -137,8 -139,8 +141,8 @@@ goto end; if (subgroupp) f |= DH_SUBGROUP; if (dh_limlee(&dp, ql, pl, f, steps, r, - oe.proc, oe.ctx, ie.proc, ie.ctx, &nf, &v)) - PGENERR; + oe.ev.proc, oe.ev.ctx, ie.ev.proc, ie.ev.ctx, &nf, &v)) + PGENERR(&exc); vec = PyList_New(nf); for (i = 0; i < nf; i++) PyList_SetItem(vec, i, mp_pywrap(v[i])); @@@ -156,19 -158,21 +160,21 @@@ static PyObject *meth__DHInfo_genkcdsa( unsigned ql, pl; unsigned steps = 0; grand *r = &rand_global; - pgev evt = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev evt = { { 0 } }; - char *kwlist[] = { "class", "pbits", "qbits", - "event", "rng", "nsteps", 0 }; + static const char *const kwlist[] = + { "class", "pbits", "qbits", "event", "rng", "nsteps", 0 }; mp *v = MP_NEW; PyObject *rc = 0; + evt.exc = &exc; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&|O&O&O&:genkcdsa", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&|O&O&O&:genkcdsa", KWLIST, &me, convuint, &pl, convuint, &ql, convpgev, &evt, convgrand, &r, convuint, &steps)) goto end; - if (dh_kcdsagen(&dp, ql, pl, 0, steps, r, evt.proc, evt.ctx)) - PGENERR; + if (dh_kcdsagen(&dp, ql, pl, 0, steps, r, evt.ev.proc, evt.ev.ctx)) + PGENERR(&exc); mp_div(&v, 0, dp.p, dp.q); v = mp_lsr(v, v, 1); rc = Py_BuildValue("(NN)", fginfo_pywrap(&dp, dhinfo_pytype), @@@ -187,18 -191,20 +193,20 @@@ static PyObject *meth__DHInfo_gendsa(Py dsa_seed ds; char *k; Py_ssize_t ksz; - pgev evt = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev evt = { { 0 } }; - char *kwlist[] = + static const char *const kwlist[] = { "class", "pbits", "qbits", "seed", "event", "nsteps", 0 }; PyObject *rc = 0; + evt.exc = &exc; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&s#|O&O&:gendsa", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&s#|O&O&:gendsa", KWLIST, &me, convuint, &pl, convuint, &ql, &k, &ksz, convpgev, &evt, convuint, &steps)) goto end; - if (dsa_gen(&dp, ql, pl, steps, k, ksz, &ds, evt.proc, evt.ctx)) - PGENERR; + if (dsa_gen(&dp, ql, pl, steps, k, ksz, &ds, evt.ev.proc, evt.ev.ctx)) + PGENERR(&exc); rc = Py_BuildValue("(NNl)", fginfo_pywrap(&dp, dhinfo_pytype), bytestring_pywrap(ds.p, ds.sz), (long)ds.count); xfree(ds.p); @@@ -327,7 -333,7 +335,7 @@@ static PyTypeObject fginfo_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Abstract base class for field-group information objects.", +"Abstract base class for field-group information objects.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -375,7 -381,7 +383,7 @@@ static PyTypeObject dhinfo_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Standard (integer) Diffie-Hellman group information.", +"DHInfo(P, R, G): standard (integer) Diffie-Hellman group information.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -423,7 -429,7 +431,7 @@@ static PyTypeObject bindhinfo_pytype_sk Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Binary-field Diffie-Hellman group information.", +"BinDHInfo(P, R, G): binary-field Diffie-Hellman group information.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -495,7 -501,7 +503,7 @@@ PyObject *ge_pywrap(PyObject *gobj, ge static PyObject *ge_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "x", 0 }; + static const char *const kwlist[] = { "x", 0 }; PyObject *x; group *g; ec p = EC_INIT; @@@ -504,7 -510,7 +512,7 @@@ mptext_stringctx sc; g = GROUP_G(ty); - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", kwlist, &x)) goto end; + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", KWLIST, &x)) goto end; xx = G_CREATE(g); if (ECPT_PYCHECK(x)) { getecptout(&p, x); @@@ -718,14 -724,14 +726,14 @@@ end static PyObject *gemeth_toec(PyObject *me, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "curve", 0 }; + static const char *const kwlist[] = { "curve", 0 }; PyTypeObject *cty = 0; PyObject *rc = 0; group *g; ec_curve *c; ec p = EC_INIT; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:toec", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:toec", KWLIST, &cty)) goto end; g = GROUP_G(GE_GOBJ(me)); if (cty) { @@@ -802,11 -808,11 +810,11 @@@ static PyObject *gmeth_mexp(PyObject *m static PyObject *gmeth_checkgroup(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&:checkgroup", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:checkgroup", KWLIST, convgrand, &r)) goto end; if ((p = G_CHECK(GROUP_G(me), r)) != 0) @@@ -966,7 -972,7 +974,7 @@@ static PyMethodDef ge_pymethods[] = METH (check, "X.check() -> check X really belongs to its group") METH (toint, "X.toint() -> X converted to an integer") KWMETH(toec, "\ - X.toec(curve = ecpt) -> X converted to elliptic curve point") + X.toec([curve = ECPt]) -> X converted to elliptic curve point") METH (tobuf, "X.tobuf() -> X in buffer representation") METH (toraw, "X.toraw() -> X in raw representation") #undef METHNAME @@@ -1081,7 -1087,7 +1089,7 @@@ static PyMethodDef group_pymethods[] = #define METHNAME(name) gmeth_##name METH (mexp, "\ G.mexp([(X0, N0), (X1, N1), ...]) -> X0^N0 X1^N1 ...") - KWMETH(checkgroup, "G.checkgroup(rand = random): check group is good") + KWMETH(checkgroup, "G.checkgroup([rng = rand]): check group is good") #undef METHNAME { 0 } }; @@@ -1155,9 -1161,9 +1163,9 @@@ static PyObject *primegroup_pynew(PyTyp PyObject *arg, PyObject *kw) { PyObject *i; - char *kwlist[] = { "info", 0 }; + static const char *const kwlist[] = { "info", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!:new", KWLIST, dhinfo_pytype, &i)) return (0); return (group_dopywrap(ty, group_prime(FGINFO_DP(i)))); @@@ -1188,7 -1194,7 +1196,7 @@@ static PyTypeObject primegroup_pytype_s Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Subgroups of prime fields.", +"PrimeGroup(INFO): subgroups of prime fields.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1232,9 -1238,9 +1240,9 @@@ static PyObject *bingroup_pynew(PyTypeO PyObject *arg, PyObject *kw) { PyObject *i; - char *kwlist[] = { "info", 0 }; + static const char *const kwlist[] = { "info", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!:new", KWLIST, bindhinfo_pytype, &i)) return (0); return (group_dopywrap(ty, group_binary(FGINFO_DP(i)))); @@@ -1265,7 -1271,7 +1273,7 @@@ static PyTypeObject bingroup_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Subgroups of binary fields.", +"BinGroup(INFO): subgroups of binary fields.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1309,9 -1315,9 +1317,9 @@@ static PyObject *ecgroup_pynew(PyTypeOb { PyObject *i; ec_info ei; - char *kwlist[] = { "info", 0 }; + static const char *const kwlist[] = { "info", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!:new", KWLIST, ecinfo_pytype, &i)) return (0); ecinfo_copy(&ei, ECINFO_EI(i)); @@@ -1343,7 -1349,7 +1351,7 @@@ static PyTypeObject ecgroup_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Elliptic curve groups.", +"ECGroup(INFO): elliptic curve groups.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1379,16 -1385,16 +1387,16 @@@ static PyMethodDef methods[] = METH (_DHInfo__groupn, 0) METH (_BinDHInfo__groupn, 0) KWMETH(_DHInfo_generate, "\ - generate(PBITS, [qbits = 0, event = pgen_nullev,\n\ - rng = rand, nsteps = 0]) -> D") + generate(PBITS, [qbits = 0], [event = pgen_nullev],\n\ + [rng = rand], [nsteps = 0]) -> D") KWMETH(_DHInfo_genlimlee, "\ - genlimlee(PBITS, QBITS, [event = pgen_nullev, ievent = pgen_nullev,\n\ - rng = rand, nsteps = 0, subgroupp = True]) -> (D, [Q, ...])") + genlimlee(PBITS, QBITS, [event = pgen_nullev], [ievent = pgen_nullev],\n\ + [rng = rand], [nsteps = 0], [subgroupp = True]) -> (D, [Q, ...])") KWMETH(_DHInfo_gendsa, "\ - gendsa(PBITS, QBITS, SEED, [event = pgen_nullev, nsteps = 0])\n\ + gendsa(PBITS, QBITS, SEED, [event = pgen_nullev], [nsteps = 0])\n\ -> (D, SEED, COUNT)") KWMETH(_DHInfo_genkcdsa, "\ - gendsa(PBITS, QBITS, [event = pgen_nullev, rng = rand, nsteps = 0])\n\ + gendsa(PBITS, QBITS, [event = pgen_nullev], [rng = rand], [nsteps = 0])\n\ -> (D, V)") #undef METHNAME { 0 } diff --combined key.c index 1700259,99c25ab..87462ab --- a/key.c +++ b/key.c @@@ -36,29 -36,31 +36,31 @@@ static PyObject *keyfilebrokenexc static PyObject *kxmeth___init__(PyObject *me, PyObject *arg) { - int err; + long err; PyObject *x = 0; + Py_ssize_t n; - if (!PyArg_ParseTuple(arg, "Oi:__init__", &me, &err) || - (x = PyInt_FromLong(err)) == 0 || - PyObject_SetAttrString(me, "err", x)) - goto fail; - Py_DECREF(x); x = 0; - if ((x = PyString_FromString(key_strerror(err))) == 0 || - PyObject_SetAttrString(me, "errstring", x)) - goto fail; + n = PyTuple_GET_SIZE(arg); + if (n < 2) TYERR("__init__() takes at least two arguments"); + me = PyTuple_GET_ITEM(arg, 0); + err = PyInt_AsLong(PyTuple_GET_ITEM(arg, 1)); + if (err == -1 && PyErr_Occurred()) goto end; + if (INT_MIN > err || err > INT_MAX) OVFERR("error code out of range"); + + x = PyInt_FromLong(err); if (!x) goto end; + if (PyObject_SetAttrString(me, "err", x)) goto end; Py_DECREF(x); x = 0; - if ((x = PyString_FromString(key_strerror(err))) == 0 || - PyObject_SetAttrString(me, "errstring", x)) - goto fail; + + x = PyString_FromString(key_strerror(err)); if (!x) goto end; + if (PyObject_SetAttrString(me, "errstring", x)) goto end; Py_DECREF(x); x = 0; - if ((x = PySequence_GetSlice(arg, 1, PySequence_Size(arg))) == 0 || - PyObject_SetAttrString(me, "args", x)) - goto fail; + + x = PyTuple_GetSlice(arg, 1, n); if (!x) goto end; + if (PyObject_SetAttrString(me, "args", x)) goto end; Py_DECREF(x); x = 0; RETURN_NONE; - fail: + end: Py_XDECREF(x); return (0); } @@@ -104,7 -106,7 +106,7 @@@ static PyMethodDef keyexc_pymethods[] static void keyexc_raise(int err) { - PyObject *arg = Py_BuildValue("(is)", err, key_strerror(err)); + PyObject *arg = Py_BuildValue("(i)", err); if (arg) PyErr_SetObject(keyexc, arg); Py_XDECREF(arg); } @@@ -229,8 -231,8 +231,8 @@@ static int convfilter(PyObject *x, voi goto end; else if (n != 2) goto tyerr; - else if ((a = PySequence_GetItem(x, 0)) == 0 || convuint(a, &f->f) || - (b = PySequence_GetItem(x, 1)) == 0 || convuint(b, &f->m)) + else if ((a = PySequence_GetItem(x, 0)) == 0 || !convuint(a, &f->f) || + (b = PySequence_GetItem(x, 1)) == 0 || !convuint(b, &f->m)) goto end; } rc = 1; @@@ -351,10 -353,10 +353,10 @@@ static PyObject *kdmeth_split(PyObject static PyObject *kdmeth_copy(PyObject *me, PyObject *arg, PyObject *kw) { key_filter f = { 0, 0 }; - static char *kwlist[] = { "filter", 0 }; + static const char *const kwlist[] = { "filter", 0 }; key_data *kd; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:copy", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:copy", KWLIST, convfilter, &f)) return (0); if ((kd = key_copydata(KEYDATA_KD(me), &f)) == 0) @@@ -368,9 -370,9 +370,9 @@@ static PyObject *kdmeth_write(PyObject key_filter f = { 0, 0 }; dstr d = DSTR_INIT; PyObject *rc = 0; - static char *kwlist[] = { "filter", 0 }; + static const char *const kwlist[] = { "filter", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:write", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:write", KWLIST, convfilter, &f)) return (0); key_write(KEYDATA_KD(me), &d, &f); @@@ -384,9 -386,9 +386,9 @@@ static PyObject *kdmeth_encode(PyObjec key_filter f = { 0, 0 }; dstr d = DSTR_INIT; PyObject *rc = 0; - static char *kwlist[] = { "filter", 0 }; + static const char *const kwlist[] = { "filter", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:encode", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:encode", KWLIST, convfilter, &f)) return (0); key_encode(KEYDATA_KD(me), &d, &f); @@@ -465,9 -467,9 +467,9 @@@ static PyMethodDef keydata_pymethods[] #define METHNAME(func) kdmeth_##func METH (matchp, "KD.matchp(FILTER) -> BOOL") METH (split, "KD.split()") - KWMETH(write, "KD.write(filter = ) -> STRING") - KWMETH(encode, "KD.encode(filter = ) -> BYTES") - KWMETH(copy, "KD.copy(filter = ) -> KD") + KWMETH(write, "KD.write([filter = ]) -> STRING") + KWMETH(encode, "KD.encode([filter = ]) -> BYTES") + KWMETH(copy, "KD.copy([filter = ]) -> KD") METH (plock, "KD.plock(TAG) -> ENCRYPTED-KD") METH (lock, "KD.lock(KEY) -> ENCRYPTED-KD") #undef METHNAME @@@ -536,9 -538,9 +538,9 @@@ static PyObject *keydatabin_pynew(PyTyp Py_ssize_t n; unsigned f = 0; keydata_pyobj *me = 0; - static char *kwlist[] = { "key", "flags", 0 }; + static const char *const kwlist[] = { "key", "flags", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:new", KWLIST, &p, &n, convflags, &f)) goto end; me = (keydata_pyobj *)ty->tp_alloc(ty, 0); @@@ -583,7 -585,7 +585,7 @@@ static PyTypeObject keydatabin_pytype_s Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key data for binary keys.", +"KeyDataBinary(KEY, [flags = 0]): key data for binary keys.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -613,9 -615,9 +615,9 @@@ static PyObject *keydataenc_pynew(PyTyp Py_ssize_t n; unsigned f = 0; keydata_pyobj *me = 0; - static char *kwlist[] = { "key", "flags", 0 }; + static const char *const kwlist[] = { "key", "flags", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:new", KWLIST, &p, &n, convflags, &f)) goto end; me = (keydata_pyobj *)ty->tp_alloc(ty, 0); @@@ -720,7 -722,7 +722,7 @@@ static PyTypeObject keydataenc_pytype_s Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key data for encrypted keys.", +"KeyDataEncrypted(KEY, [flags = 0]): key data for encrypted keys.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -749,9 -751,9 +751,9 @@@ static PyObject *keydatamp_pynew(PyType mp *x = 0; unsigned f = 0; keydata_pyobj *me = 0; - static char *kwlist[] = { "key", "flags", 0 }; + static const char *const kwlist[] = { "key", "flags", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", KWLIST, convmp, &x, convflags, &f)) goto end; me = (keydata_pyobj *)ty->tp_alloc(ty, 0); @@@ -796,7 -798,7 +798,7 @@@ static PyTypeObject keydatamp_pytype_sk Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key data for large-integer keys.", +"KeyDataMP(KEY, [flags = 0]): key data for large-integer keys.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -825,9 -827,9 +827,9 @@@ static PyObject *keydatastr_pynew(PyTyp char *p; unsigned f = 0; keydata_pyobj *me = 0; - static char *kwlist[] = { "key", "flags", 0 }; + static const char *const kwlist[] = { "key", "flags", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s|O&:new", KWLIST, &p, convflags, &f)) goto end; me = (keydata_pyobj *)ty->tp_alloc(ty, 0); @@@ -871,7 -873,7 +873,7 @@@ static PyTypeObject keydatastr_pytype_s Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key data for string keys.", +"KeyDataString(KEY, [flags = 0]): key data for string keys.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -900,9 -902,9 +902,9 @@@ static PyObject *keydataec_pynew(PyType ec x = EC_INIT; unsigned f = 0; keydata_pyobj *me = 0; - static char *kwlist[] = { "key", "flags", 0 }; + static const char *const kwlist[] = { "key", "flags", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", KWLIST, convecpt, &x, convflags, &f)) goto end; me = (keydata_pyobj *)ty->tp_alloc(ty, 0); @@@ -951,7 -953,7 +953,7 @@@ static PyTypeObject keydataec_pytype_sk Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key data for elliptic-curve keys.", +"KeyDataECPt(KEY, [flags = 0]): key data for elliptic-curve keys.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1053,10 -1055,10 +1055,10 @@@ static PyObject *keydatastruct_pynew(Py char *p; keydata_pyobj *me = 0; key_data *kd = 0; - static char *kwlist[] = { "subkeys", 0 }; + static const char *const kwlist[] = { "subkeys", 0 }; Py_XINCREF(arg); Py_XINCREF(kw); - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:new", kwlist, &sub)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:new", KWLIST, &sub)) goto end; kd = key_newstruct(); if (sub) { @@@ -1157,7 -1159,7 +1159,7 @@@ static PyTypeObject keydatastruct_pytyp Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key data for structured keys.", +"KeyDataStructured([subkeys = []]): key data for structured keys.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1386,12 -1388,11 +1388,12 @@@ static PyObject *key_pynew(PyTypeObjec uint32 id; char *type; unsigned long exptime = KEXP_FOREVER; - static char *kwlist[] = { "keyfile", "id", "type", "exptime", 0 }; + static const char *const kwlist[] = + { "keyfile", "id", "type", "exptime", 0 }; key *k; int err; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O&s|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O&s|O&:new", KWLIST, keyfile_pytype, &kfobj, convu32, &id, &type, convulong, &exptime)) goto end; @@@ -1449,9 -1450,9 +1451,9 @@@ static PyObject *kmeth_extract(PyObjec PyObject *nameobj; char *name; FILE *fp; - static char *kwlist[] = { "file", "filter", 0 }; + static const char *const kwlist[] = { "file", "filter", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!|O&:extract", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!|O&:extract", KWLIST, &PyFile_Type, &file, convfilter, &f) || (fp = PyFile_AsFile(file)) == 0 || @@@ -1470,9 -1471,9 +1472,9 @@@ static PyObject *kmeth_fingerprint(PyOb { ghash *h; key_filter f = { KF_NONSECRET, KF_NONSECRET }; - static char *kwlist[] = { "hash", "filter", 0 }; + static const char *const kwlist[] = { "hash", "filter", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:fingerprint", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:fingerprint", KWLIST, convghash, &h, convfilter, &f)) return (0); return (getbool(key_fingerprint(KEY_K(me), h, &f))); @@@ -1498,6 -1499,7 +1500,7 @@@ static int kset_exptime(PyObject *me, P key *k = KEY_K(me); unsigned long et; + if (!x) NIERR("__del__"); if (!convulong(x, &et)) goto end; if (!(KEY_KF(me)->f & KF_WRITE)) @@@ -1514,6 -1516,7 +1517,7 @@@ static int kset_deltime(PyObject *me, P key *k = KEY_K(me); unsigned long dt; + if (!x) NIERR("__del__"); if (!convulong(x, &dt)) goto end; if (dt == KEXP_FOREVER && k->exp != KEXP_FOREVER) @@@ -1598,8 -1601,8 +1602,8 @@@ static PyMethodDef key_pymethods[] = METH (delete, "KEY.delete()") METH (expire, "KEY.expire()") METH (used, "KEY.used(TIME)") - KWMETH(extract, "KEY.extract(FILE, filter = '')") - KWMETH(fingerprint, "KEY.fingerprint(HASH, filtr = '-secret')") + KWMETH(extract, "KEY.extract(FILE, [filter = ])") + KWMETH(fingerprint, "KEY.fingerprint(HASH, [filter = '-secret'])") #undef METHNAME { 0 } }; @@@ -1646,7 -1649,7 +1650,7 @@@ static PyTypeObject key_pytype_skel = Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Key object.", +"Key(KF, ID, TYPE, [exptime = KEXP_FOREVER]): key object.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1774,10 -1777,10 +1778,10 @@@ static PyObject *keyfile_pynew(PyTypeOb char *file = 0; unsigned how = KOPEN_READ; keyfile_pyobj *rc = 0; - static char *kwlist[] = { "file", "how", "report", 0 }; + static const char *const kwlist[] = { "file", "how", "report", 0 }; Py_XINCREF(arg); Py_XINCREF(kw); - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s|iO:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s|iO:new", KWLIST, &file, &how, &ri.func)) goto end; if (ri.func && !PyCallable_Check(ri.func)) @@@ -1833,10 -1836,10 +1837,10 @@@ static PyObject *kfmeth_merge(PyObject PyObject *x = 0; FILE *fp = 0; int rc; - static char *kwlist[] = { "file", "report", 0 }; + static const char *const kwlist[] = { "file", "report", 0 }; Py_XINCREF(arg); Py_XINCREF(kw); - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!|O:merge", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!|O:merge", KWLIST, &PyFile_Type, &x, &ri.func)) goto end; if (ri.func && !PyCallable_Check(ri.func)) @@@ -1932,11 -1935,11 +1936,11 @@@ static PyObject *kfmeth_newkey(PyObjec uint32 id; char *type; long exptime = KEXP_FOREVER; - static char *kwlist[] = { "id", "type", "exptime", 0 }; + static const char *const kwlist[] = { "id", "type", "exptime", 0 }; key *k; int err; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&s|l:newkey", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&s|l:newkey", KWLIST, convu32, &id, &type, &exptime)) goto end; if ((err = key_new(KEYFILE_KF(me), id, type, exptime, &k)) != 0) @@@ -1954,9 -1957,9 +1958,9 @@@ static PyObject *kfmeth_qtag(PyObject * char *tag; dstr d = DSTR_INIT; PyObject *rc = 0; - static char *kwlist[] = { "tag", "new", 0 }; + static const char *const kwlist[] = { "tag", "new", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s|O!:qtag", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s|O!:qtag", KWLIST, &tag, keydata_pytype, &newkdobj)) goto end; if (key_qtag(KEYFILE_KF(me), tag, &d, &k, &kd)) @@@ -1989,12 -1992,13 +1993,13 @@@ static PyObject *kfget_filep(PyObject * static PyMethodDef keyfile_pymethods[] = { #define METHNAME(func) kfmeth_##func METH (save, "KF.save()") - KWMETH(merge, "KF.merge(FILE, report = )") - KWMETH(newkey, "KF.newkey(ID, TYPE, exptime = KEXP_FOREVER) -> KEY") + KWMETH(merge, "KF.merge(FILE, [report = ])") + KWMETH(newkey, "KF.newkey(ID, TYPE, " + "[exptime = KEXP_FOREVER]) -> KEY") METH (byid, "KF.byid(KEYID) -> KEY|None") METH (bytype, "KF.bytype(TYPE) -> KEY|None") METH (bytag, "KF.bytag(TAG) -> KEY|None") - KWMETH(qtag, "KF.qtag(TAG, new = KD) -> FULLTAG, KEY, OLDKD") + KWMETH(qtag, "KF.qtag(TAG, [new = KD]) -> FULLTAG, KEY, OLDKD") GMAP_ROMETHODS #undef METHNAME { 0 } @@@ -2041,8 -2045,7 +2046,8 @@@ static PyTypeObject keyfile_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Keyring file.", +"KeyFile(FILE, [how = KOPEN_READ], [report = ?]): Keyring file.\n\ + calls REPORT(FILE, LINE, MSG) on problems", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ diff --combined mp.c index e0f72d4,ab15d3f..1448bc2 --- a/mp.c +++ b/mp.c @@@ -211,6 -211,7 +211,7 @@@ mp *tomp(PyObject *o return (MP_COPY(PFILT_F(o)->m)); else if (ECPT_PYCHECK(o)) { ec p = EC_INIT; + if (EC_ATINF(ECPT_P(o))) return (0); getecptout(&p, o); x = MP_COPY(p.x); EC_DESTROY(&p); @@@ -527,9 -528,9 +528,9 @@@ static PyObject *mp_pynew(PyTypeObject mp *z; mp_pyobj *zz = 0; int radix = 0; - char *kwlist[] = { "x", "radix", 0 }; + static const char *const kwlist[] = { "x", "radix", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:new", kwlist, &x, &radix)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:new", KWLIST, &x, &radix)) goto end; if (MP_PYCHECK(x)) RETURN_OBJ(x); if (!good_radix_p(radix, 1)) VALERR("bad radix"); @@@ -544,13 -545,15 +545,15 @@@ end return ((PyObject *)zz); } - static long mp_pyhash(PyObject *me) + long mphash(mp *x) { - long h; - PyObject *l = mp_topylong(MP_X(me)); h = PyObject_Hash(l); + PyObject *l = mp_topylong(x); + long h = PyObject_Hash(l); Py_DECREF(l); return (h); } + static long mp_pyhash(PyObject *me) { return (mphash(MP_X(me))); } + static PyObject *mpmeth_jacobi(PyObject *me, PyObject *arg) { mp *y = 0; @@@ -659,8 -662,8 +662,8 @@@ end static PyObject *mpmeth_tostring(PyObject *me, PyObject *arg, PyObject *kw) { int radix = 10; - char *kwlist[] = { "radix", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|i:tostring", kwlist, &radix)) + static const char *const kwlist[] = { "radix", 0 }; + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|i:tostring", KWLIST, &radix)) goto end; if (!good_radix_p(radix, 0)) VALERR("bad radix"); return (mp_topystring(MP_X(me), radix, 0, 0, 0)); @@@ -700,11 -703,11 +703,11 @@@ end PyObject *arg, PyObject *kw) \ { \ long len = -1; \ - char *kwlist[] = { "len", 0 }; \ + static const char *const kwlist[] = { "len", 0 }; \ PyObject *rc = 0; \ \ if (!PyArg_ParseTupleAndKeywords(arg, kw, "|l:" #name, \ - kwlist, &len)) \ + KWLIST, &len)) \ goto end; \ if (len < 0) { \ len = mp_octets##c(MP_X(me)); \ @@@ -763,10 -766,10 +766,10 @@@ static PyObject *mpmeth_tobuf(PyObject static PyObject *mpmeth_primep(PyObject *me, PyObject *arg, PyObject *kw) { grand *r = &rand_global; - char *kwlist[] = { "rng", 0 }; + static const char *const kwlist[] = { "rng", 0 }; PyObject *rc = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&", kwlist, convgrand, &r)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&", KWLIST, convgrand, &r)) goto end; rc = getbool(pgen_primep(MP_X(me), r)); end: @@@ -793,7 -796,7 +796,7 @@@ static PyGetSetDef mp_pygetset[] = static PyMethodDef mp_pymethods[] = { #define METHNAME(func) mpmeth_##func - METH (jacobi, "X.jacobi(Y) -> Jacobi symbol (Y/X) (NB inversion!)") + METH (jacobi, "X.jacobi(Y) -> Jacobi symbol (Y|X) (NB inversion!)") METH (setbit, "X.setbit(N) -> X with bit N set") METH (clearbit, "X.clearbit(N) -> X with bit N clear") METH (testbit, "X.testbit(N) -> true/false if bit N set/clear in X") @@@ -807,14 -810,14 +810,14 @@@ METH (modsqrt, "X.modsqrt(Y) -> square root of Y mod X, if X prime") METH (leastcongruent, "X.leastcongruent(B, M) -> smallest Z >= B with Z == X (mod M)") - KWMETH(primep, "X.primep(rng = rand) -> true/false if X is prime") - KWMETH(tostring, "X.tostring(radix = 10) -> STR") - KWMETH(storel, "X.storel(len = -1) -> little-endian bytes") - KWMETH(storeb, "X.storeb(len = -1) -> big-endian bytes") + KWMETH(primep, "X.primep([rng = rand]) -> true/false if X is prime") + KWMETH(tostring, "X.tostring([radix = 10]) -> STR") + KWMETH(storel, "X.storel([len = -1]) -> little-endian bytes") + KWMETH(storeb, "X.storeb([len = -1]) -> big-endian bytes") KWMETH(storel2c, - "X.storel2c(len = -1) -> little-endian bytes, two's complement") + "X.storel2c([len = -1]) -> little-endian bytes, two's complement") KWMETH(storeb2c, - "X.storeb2c(len = -1) -> big-endian bytes, two's complement") + "X.storeb2c([len = -1]) -> big-endian bytes, two's complement") METH (tobuf, "X.tobuf() -> buffer format") #undef METHNAME { 0 } @@@ -890,15 -893,19 +893,19 @@@ static PyTypeObject mp_pytype_skel = /* @tp_doc@ */ "Multiprecision integers, similar to `long' but more efficient and\n\ - versatile. Support all the standard arithmetic operations.\n\ + versatile. Support all the standard arithmetic operations, with\n\ + implicit conversions from `PrimeFilter', and other objects which\n\ + convert to `long'.\n\ \n\ - Constructor mp(X, [radix = R]) attempts to convert X to an `mp'. If\n\ + Constructor MP(X, [radix = R]) attempts to convert X to an `MP'. If\n\ X is a string, it's read in radix-R form, or we look for a prefix\n\ - if R = 0. Other acceptable things are ints and longs.\n\ + if R = 0. Other acceptable things are field elements, elliptic curve\n\ + points, group elements, Python `int' and `long' objects, and anything\n\ + with an integer conversion.\n\ \n\ Notes:\n\ \n\ - * Use `//' for division. MPs don't have `/' division.", + * Use `//' for integer division. `/' gives exact rational division.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -930,10 -937,10 +937,10 @@@ static PyObject *meth__MP_fromstring(Py PyObject *z = 0; mp *zz; mptext_stringctx sc; - char *kwlist[] = { "class", "x", "radix", 0 }; + static const char *const kwlist[] = { "class", "x", "radix", 0 }; if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|i:fromstring", - kwlist, &me, &p, &len, &r)) + KWLIST, &me, &p, &len, &r)) goto end; if (!good_radix_p(r, 1)) VALERR("bad radix"); sc.buf = p; sc.lim = p + len; @@@ -1101,7 -1108,7 +1108,7 @@@ static PyTypeObject *mpmul_pytype, mpmu Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"An object for multiplying many small integers.", +"MPMul(N_0, N_1, ....): an object for multiplying many small integers.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1294,10 -1301,10 +1301,10 @@@ static void mpmont_pydealloc(PyObject * static PyObject *mpmont_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { mpmont_pyobj *mm = 0; - char *kwlist[] = { "m", 0 }; + static const char *const kwlist[] = { "m", 0 }; mp *xx = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmp, &xx)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convmp, &xx)) goto end; if (!MP_POSP(xx) || !MP_ODDP(xx)) VALERR("m must be positive and odd"); mm = (mpmont_pyobj *)ty->tp_alloc(ty, 0); @@@ -1368,7 -1375,7 +1375,7 @@@ static PyTypeObject *mpmont_pytype, mpm Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"A Montgomery reduction context.", +"MPMont(N): a Montgomery reduction context.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1448,10 -1455,10 +1455,10 @@@ static PyObject *mpbarrett_pynew(PyType PyObject *arg, PyObject *kw) { mpbarrett_pyobj *mb = 0; - char *kwlist[] = { "m", 0 }; + static const char *const kwlist[] = { "m", 0 }; mp *xx = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmp, &xx)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convmp, &xx)) goto end; if (!MP_POSP(xx)) VALERR("m must be positive"); mb = (mpbarrett_pyobj *)ty->tp_alloc(ty, 0); @@@ -1507,7 -1514,7 +1514,7 @@@ static PyTypeObject *mpbarrett_pytype, Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"A Barrett reduction context.", +"MPBarrett(N): a Barrett reduction context.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1578,10 -1585,10 +1585,10 @@@ static PyObject *mpreduce_pynew(PyTypeO { mpreduce_pyobj *mr = 0; mpreduce r; - char *kwlist[] = { "m", 0 }; + static const char *const kwlist[] = { "m", 0 }; mp *xx = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmp, &xx)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convmp, &xx)) goto end; if (!MP_POSP(xx)) VALERR("m must be positive"); if (mpreduce_create(&r, xx)) VALERR("bad modulus (must be 2^k - ...)"); @@@ -1635,7 -1642,7 +1642,7 @@@ static PyTypeObject *mpreduce_pytype, m Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"A reduction context for reduction modulo primes of special form.", +"MPReduce(N): a reduction context for reduction modulo Solinas primes.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1673,7 -1680,7 +1680,7 @@@ static PyObject *mcmeth_solve(PyObject PyObject *q = 0, *x, *z = 0; mp *xx; mp **v = 0; - int i = 0, n = c->k; + Py_ssize_t i = 0, n = c->k; Py_INCREF(me); if (PyTuple_Size(arg) == n) @@@ -1682,7 -1689,8 +1689,8 @@@ goto end; Py_INCREF(q); if (!PySequence_Check(q)) TYERR("want a sequence of residues"); - if (PySequence_Size(q) != n) VALERR("residue count mismatch"); + i = PySequence_Size(q); if (i < 0) goto end; + if (i != n) VALERR("residue count mismatch"); v = xmalloc(n * sizeof(*v)); for (i = 0; i < n; i++) { if ((x = PySequence_GetItem(q, i)) == 0) goto end; @@@ -1712,30 -1720,41 +1720,41 @@@ static void mpcrt_pydealloc(PyObject *m static PyObject *mpcrt_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { mpcrt_mod *v = 0; - int n, i = 0; + Py_ssize_t n, i = 0, j; - char *kwlist[] = { "mv", 0 }; + static const char *const kwlist[] = { "mv", 0 }; PyObject *q = 0, *x; - mp *xx; + mp *xx = MP_NEW, *y = MP_NEW, *g = MP_NEW; + mpmul mm; mpcrt_pyobj *c = 0; if (PyTuple_Size(arg) > 1) q = arg; - else if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", kwlist, &q)) + else if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", KWLIST, &q)) goto end; Py_INCREF(q); if (!PySequence_Check(q)) TYERR("want a sequence of moduli"); - n = PySequence_Size(q); - if (PyErr_Occurred()) goto end; + n = PySequence_Size(q); if (n < 0) goto end; if (!n) VALERR("want at least one modulus"); v = xmalloc(n * sizeof(*v)); for (i = 0; i < n; i++) { if ((x = PySequence_GetItem(q, i)) == 0) goto end; xx = getmp(x); Py_DECREF(x); if (!xx) goto end; - v[i].m = xx; v[i].n = 0; v[i].ni = 0; v[i].nni = 0; + if (MP_CMP(xx, <=, MP_ZERO)) VALERR("moduli must be positive"); + v[i].m = xx; v[i].n = 0; v[i].ni = 0; v[i].nni = 0; xx = MP_NEW; } + mpmul_init(&mm); + for (j = 0; j < i; j++) mpmul_add(&mm, v[j].m); + xx = mpmul_done(&mm); + for (j = 0; j < i; j++) { + mp_div(&y, 0, xx, v[j].m); + mp_gcd(&g, 0, 0, y, v[j].m); + if (!MP_EQ(g, MP_ONE)) VALERR("moduli must be pairwise coprime"); + } + c = (mpcrt_pyobj *)ty->tp_alloc(ty, 0); mpcrt_create(&c->c, v, n, 0); Py_DECREF(q); + mp_drop(xx); mp_drop(y); mp_drop(g); return ((PyObject *)c); end: @@@ -1746,6 -1765,7 +1765,7 @@@ xfree(v); } Py_XDECREF(q); + mp_drop(xx); mp_drop(y); mp_drop(g); return (0); } @@@ -1804,7 -1824,7 +1824,7 @@@ static PyTypeObject *mpcrt_pytype, mpcr Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"A context for the solution of Chinese Remainder Theorem problems.", +"MPCRT(SEQ): a context for solving Chinese Remainder Theorem problems.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1864,9 -1884,9 +1884,9 @@@ static PyObject *gf_pynew(PyTypeObject mp *z; mp_pyobj *zz = 0; int radix = 0; - char *kwlist[] = { "x", "radix", 0 }; + static const char *const kwlist[] = { "x", "radix", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:gf", kwlist, &x, &radix)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:gf", KWLIST, &x, &radix)) goto end; if (GF_PYCHECK(x)) RETURN_OBJ(x); if (!good_radix_p(radix, 1)) VALERR("radix out of range"); @@@ -1885,15 -1905,6 +1905,6 @@@ end return ((PyObject *)zz); } - static long gf_pyhash(PyObject *me) - { - long i = mp_tolong(MP_X(me)); - i ^= 0xc7ecd67c; /* random perturbance */ - if (i == -1) - i = -2; - return (i); - } - static PyObject *gf_pyexp(PyObject *x, PyObject *y, PyObject *z) { mp *xx = 0, *yy = 0, *zz = 0; @@@ -2006,13 -2017,13 +2017,13 @@@ static PyMethodDef gf_pymethods[] = METH (irreduciblep, "X.irreduciblep() -> true/false") #undef METHNAME #define METHNAME(func) mpmeth_##func - KWMETH(tostring, "X.tostring(radix = 10) -> STR") - KWMETH(storel, "X.storel(len = -1) -> little-endian bytes") - KWMETH(storeb, "X.storeb(len = -1) -> big-endian bytes") + KWMETH(tostring, "X.tostring([radix = 10]) -> STR") + KWMETH(storel, "X.storel([len = -1]) -> little-endian bytes") + KWMETH(storeb, "X.storeb([len = -1]) -> big-endian bytes") KWMETH(storel2c, - "X.storel2c(len = -1) -> little-endian bytes, two's complement") + "X.storel2c([len = -1]) -> little-endian bytes, two's complement") KWMETH(storeb2c, - "X.storeb2c(len = -1) -> big-endian bytes, two's complement") + "X.storeb2c([len = -1]) -> big-endian bytes, two's complement") METH (tobuf, "X.tobuf() -> buffer format") #undef METHNAME { 0 } @@@ -2076,7 -2087,7 +2087,7 @@@ static PyTypeObject gf_pytype_skel = &gf_pynumber, /* @tp_as_number@ */ 0, /* @tp_as_sequence@ */ 0, /* @tp_as_mapping@ */ - gf_pyhash, /* @tp_hash@ */ + mp_pyhash, /* @tp_hash@ */ 0, /* @tp_call@ */ mp_pyhex, /* @tp_str@ */ 0, /* @tp_getattro@ */ @@@ -2090,16 -2101,18 +2101,18 @@@ "Binary polynomials. Support almost all the standard arithmetic\n\ operations.\n\ \n\ - Constructor gf(X, radix = R) attempts to convert X to a `gf'. If\n\ + Constructor GF(X, [radix = R]) attempts to convert X to a `GF'. If\n\ X is a string, it's read in radix-R form, or we look for a prefix\n\ - if R = 0. Other acceptable things are ints and longs.\n\ + if R = 0. Other acceptable things are field elements, elliptic curve\n\ + points, group elements, Python `int' and `long' objects, and anything\n\ + with an integer conversion.\n\ \n\ The name is hopelessly wrong from a technical point of view, but\n\ but it's much easier to type than `p2' or `c2' or whatever.\n\ \n\ Notes:\n\ \n\ - * Use `//' for division. GFs don't have `/' division.", + * Use `//' for Euclidean division. `/' gives exact rational division.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -2131,10 -2144,10 +2144,10 @@@ static PyObject *meth__GF_fromstring(Py PyObject *z = 0; mp *zz; mptext_stringctx sc; - char *kwlist[] = { "class", "x", "radix", 0 }; + static const char *const kwlist[] = { "class", "x", "radix", 0 }; if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|i:fromstring", - kwlist, &me, &p, &len, &r)) + KWLIST, &me, &p, &len, &r)) goto end; if (!good_radix_p(r, 1)) VALERR("bad radix"); sc.buf = p; sc.lim = p + len; @@@ -2249,10 -2262,10 +2262,10 @@@ static PyObject *gfreduce_pynew(PyTypeO { gfreduce_pyobj *mr = 0; gfreduce r; - char *kwlist[] = { "m", 0 }; + static const char *const kwlist[] = { "m", 0 }; mp *xx = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convgf, &xx)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convgf, &xx)) goto end; if (MP_ZEROP(xx)) ZDIVERR("modulus is zero!"); gfreduce_create(&r, xx); @@@ -2310,7 -2323,7 +2323,7 @@@ static PyTypeObject *gfreduce_pytype, g Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"A reduction context for reduction modulo sparse irreducible polynomials.", +"GFReduce(N): a context for reduction modulo sparse polynomials.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -2351,14 -2364,15 +2364,15 @@@ static PyObject *gfn_pynew(PyTypeObjec { mp *p = 0, *beta = 0; gfn_pyobj *gg = 0; - char *kwlist[] = { "p", "beta", 0 }; + static const char *const kwlist[] = { "p", "beta", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST, convgf, &p, convgf, &beta)) goto end; gg = PyObject_New(gfn_pyobj, ty); + gg->p = 0; if (gfn_create(p, beta, &gg->ntop, &gg->pton)) { - FREEOBJ(gg); + Py_DECREF(gg); gg = 0; VALERR("can't invert transformation matrix"); } @@@ -2390,7 -2404,7 +2404,7 @@@ static PyObject *gfnget_beta(PyObject * end: \ mp_drop(xx); \ if (!z) return (0); \ - return (mp_pywrap(z)); \ + return (gf_pywrap(z)); \ } XFORMOP(pton, PTON) XFORMOP(ntop, NTOP) @@@ -2398,8 -2412,11 +2412,11 @@@ static void gfn_pydealloc(PyObject *me) { - gfn_destroy(GFN_PTON(me)); - gfn_destroy(GFN_NTOP(me)); + if (GFN_P(me)) { + MP_DROP(GFN_P(me)); + gfn_destroy(GFN_PTON(me)); + gfn_destroy(GFN_NTOP(me)); + } FREEOBJ(me); } @@@ -2444,8 -2461,8 +2461,8 @@@ static PyTypeObject gfn_pytype_skel = Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"An object for transforming elements of binary fields between polynomial\n\ -and normal basis representations.", +"GFN(P, BETA): an object for transforming elements of binary fields\n\ + between polynomial and normal basis representations.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -2473,13 -2490,13 +2490,13 @@@ static PyMethodDef methods[] = { #define METHNAME(func) meth_##func KWMETH(_MP_fromstring, "\ - fromstring(STR, radix = 0) -> (X, REST)\n\ + fromstring(STR, [radix = 0]) -> (X, REST)\n\ \n\ Parse STR as a large integer, according to radix. If radix is zero,\n\ read a prefix from STR to decide radix: allow `0' for octal, `0x' for hex\n\ or `R_' for other radix R.") KWMETH(_GF_fromstring, "\ - fromstring(STR, radix = 0) -> (X, REST)\n\ + fromstring(STR, [radix = 0]) -> (X, REST)\n\ \n\ Parse STR as a binary polynomial, according to radix. If radix is zero,\n\ read a prefix from STR to decide radix: allow `0' for octal, `0x' for hex\n\ diff --combined pgen.c index 18b0c26,9460310..9f9e1a2 --- a/pgen.c +++ b/pgen.c @@@ -57,10 -57,10 +57,10 @@@ end static PyObject *pfilt_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "x", 0 }; + static const char *const kwlist[] = { "x", 0 }; PyObject *xobj; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", kwlist, &xobj)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", KWLIST, &xobj)) return (0); return (pfilt_pymake(ty, xobj)); } @@@ -219,7 -219,7 +219,7 @@@ static PyTypeObject pfilt_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Small-primes filter.", +"PrimeFilter(X): small-primes filter.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -256,9 -256,9 +256,9 @@@ static PyObject *rabin_pynew(PyTypeObje { mp *x = 0; rabin_pyobj *o = 0; - char *kwlist[] = { "x", 0 }; + static const char *const kwlist[] = { "x", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmp, &x)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convmp, &x)) goto end; if (!MP_POSP(x) || MP_EVENP(x)) VALERR("must be positive and odd"); o = (rabin_pyobj *)ty->tp_alloc(ty, 0); @@@ -352,7 -352,7 +352,7 @@@ static PyTypeObject rabin_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Rabin-Miller strong primality test.", +"RabinMiller(X): Rabin-Miller strong primality test.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -443,6 -443,7 +443,7 @@@ static int peset_x(PyObject *me, PyObje mp *x = 0; pgen_event *ev = PGEVENT_EV(me); int rc = -1; + if (!xobj) NIERR("__del__"); PGEVENT_CHECK(me); if ((x = getmp(xobj)) == 0) goto end; mp_drop(ev->m); @@@ -543,20 -544,19 +544,19 @@@ static PyTypeObject *pgtest_pytype static int pgev_python(int rq, pgen_event *ev, void *p) { - PyObject *py = p; + pypgev *pg = p; PyObject *pyev = 0; PyObject *rc = 0; int st = PGEN_ABORT; long l; - char *meth[] = { - "pg_abort", "pg_done", "pg_begin", "pg_try", "pg_fail", "pg_pass" - }; + static const char *const meth[] = + { "pg_abort", "pg_done", "pg_begin", "pg_try", "pg_fail", "pg_pass" }; - Py_INCREF(py); rq++; if (rq > N(meth)) SYSERR("event code out of range"); pyev = pgevent_pywrap(ev); - if ((rc = PyObject_CallMethod(py, (/*unconst*/ char *)meth[rq], - if ((rc = PyObject_CallMethod(pg->obj, meth[rq], "(O)", pyev)) == 0) ++ if ((rc = PyObject_CallMethod(pg->obj, (/*unconst*/ char *)meth[rq], + "(O)", pyev)) == 0) goto end; if (rc == Py_None) st = PGEN_TRY; @@@ -567,12 -567,13 +567,13 @@@ else st = l; end: + if (PyErr_Occurred()) + stash_exception(pg->exc, "exception from `pgen' handler"); if (pyev) { pgevent_kill(pyev); Py_DECREF(pyev); } Py_XDECREF(rc); - Py_DECREF(py); return (st); } @@@ -587,24 -588,22 +588,22 @@@ static PyObject *pgev_pywrap(const pge int convpgev(PyObject *o, void *p) { - pgev *pg = p; + pypgev *pg = p; if (PGEV_PYCHECK(o)) - *pg = *PGEV_PG(o); + pg->ev = *PGEV_PG(o); else { - pg->proc = pgev_python; - pg->ctx = o; - Py_INCREF(o); + pg->ev.proc = pgev_python; + pg->ev.ctx = pg; + pg->obj = o; Py_INCREF(o); } return (1); } - void droppgev(pgev *p) + void droppgev(pypgev *pg) { - if (p->proc == pgev_python) { - PyObject *py = p->ctx; - Py_DECREF(py); - } + if (pg->ev.proc == pgev_python) + { assert(pg->ev.ctx == pg); Py_DECREF(pg->obj); } } static PyObject *pgmeth_common(PyObject *me, PyObject *arg, int rq) @@@ -635,12 -634,12 +634,12 @@@ static PyObject *pgev_stdev(pgen_proc * static PyMethodDef pgev_pymethods[] = { #define METHNAME(name) pgmeth_##name - METH (pg_abort, "E.pg_abort() -> PGRC -- prime generation aborted") - METH (pg_done, "E.pg_done() -> PGRC -- prime generation finished") - METH (pg_begin, "E.pg_begin() -> PGRC -- commence stepping/testing") - METH (pg_try, "E.pg_try() -> PGRC -- found new candidate") - METH (pg_pass, "E.pg_pass() -> PGRC -- passed primality test") - METH (pg_fail, "E.pg_fail() -> PGRC -- failed primality test") + METH (pg_abort, "E.pg_abort(EV) -> PGRC -- prime generation aborted") + METH (pg_done, "E.pg_done(EV) -> PGRC -- prime generation finished") + METH (pg_begin, "E.pg_begin(EV) -> PGRC -- commence stepping/testing") + METH (pg_try, "E.pg_try(EV) -> PGRC -- found new candidate") + METH (pg_pass, "E.pg_pass(EV) -> PGRC -- passed primality test") + METH (pg_fail, "E.pg_fail(EV) -> PGRC -- failed primality test") #undef METHNAME { 0 } }; @@@ -697,9 -696,9 +696,9 @@@ static PyObject *pgstep_pynew(PyTypeObj { mpw s; pgstep_pyobj *rc = 0; - char *kwlist[] = { "step", 0 }; + static const char *const kwlist[] = { "step", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", kwlist, convmpw, &s)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convmpw, &s)) goto end; rc = (pgstep_pyobj *)ty->tp_alloc(ty, 0); rc->f.step = s; @@@ -744,7 -743,7 +743,7 @@@ static PyTypeObject pgstep_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Simple prime-number stepper with small-factors filter.", +"PrimeGenStepper(STEP): simple stepper with small-factors filter.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -771,9 -770,9 +770,9 @@@ static PyObject *pgjump_pynew(PyTypeObj { PyObject *o, *fobj; pgjump_pyobj *rc = 0; - char *kwlist[] = { "jump", 0 }; + static const char *const kwlist[] = { "jump", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", kwlist, &o) || + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:new", KWLIST, &o) || (fobj = pfilt_pymake(pfilt_pytype, o)) == 0) goto end; rc = (pgjump_pyobj *)ty->tp_alloc(ty, 0); @@@ -826,7 -825,7 +825,7 @@@ static PyTypeObject pgjump_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Stepper for larger steps, with small-factors filter.", +"PrimeGenJumper(JUMP): stepper for larger steps with small-factors filter.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -852,9 -851,9 +851,9 @@@ static PyObject *pgtest_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { pgtest_pyobj *rc = 0; - char *kwlist[] = { 0 }; + static const char *const kwlist[] = { 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", kwlist)) goto end; + if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", KWLIST)) goto end; rc = (pgtest_pyobj *)ty->tp_alloc(ty, 0); rc->pg.proc = pgen_test; rc->pg.ctx = &rc->r; @@@ -887,7 -886,7 +886,7 @@@ static PyTypeObject pgtest_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Rabin-Miller tester.", +"PrimeGenTester(): Rabin-Miller tester.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -912,10 -911,10 +911,10 @@@ /*----- Prime generation functions ----------------------------------------*/ - void pgenerr(void) + void pgenerr(struct excinfo *exc) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_ValueError, "prime generation failed"); + if (exc->ty) RESTORE_EXCINFO(exc); + else PyErr_SetString(PyExc_ValueError, "prime generation failed"); } static PyObject *meth_pgen(PyObject *me, PyObject *arg, PyObject *kw) @@@ -926,26 -925,26 +925,26 @@@ char *p = "p"; pgen_filterctx fc = { 2 }; rabin tc; - pgev step = { 0 }, test = { 0 }, evt = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev step = { { 0 } }, test = { { 0 } }, evt = { { 0 } }; unsigned nsteps = 0, ntests = 0; - char *kwlist[] = { "start", "name", "stepper", "tester", "event", - "nsteps", "ntests", 0 }; + static const char *const kwlist[] = + { "start", "name", "stepper", "tester", "event", "nsteps", "ntests", 0 }; - step.proc = pgen_filter; step.ctx = &fc; - test.proc = pgen_test; test.ctx = &tc; + step.exc = &exc; step.ev.proc = pgen_filter; step.ev.ctx = &fc; + test.exc = &exc; test.ev.proc = pgen_test; test.ev.ctx = &tc; + evt.exc = &exc; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|sO&O&O&O&O&:pgen", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|sO&O&O&O&O&:pgen", KWLIST, convmp, &x, &p, convpgev, &step, convpgev, &test, convpgev, &evt, convuint, &nsteps, convuint, &ntests)) goto end; if (!ntests) ntests = rabin_iters(mp_bits(x)); - if ((r = pgen(p, MP_NEW, x, evt.proc, evt.ctx, - nsteps, step.proc, step.ctx, - ntests, test.proc, test.ctx)) == 0) - PGENERR; - if (PyErr_Occurred()) goto end; - rc = mp_pywrap(r); - r = 0; + if ((r = pgen(p, MP_NEW, x, evt.ev.proc, evt.ev.ctx, + nsteps, step.ev.proc, step.ev.ctx, + ntests, test.ev.proc, test.ev.ctx)) == 0) + PGENERR(&exc); + rc = mp_pywrap(r); r = 0; end: mp_drop(r); mp_drop(x); droppgev(&step); droppgev(&test); droppgev(&evt); @@@ -961,19 -960,20 +960,21 @@@ static PyObject *meth_strongprime_setup unsigned nbits; char *name = "p"; unsigned n = 0; - pgev evt = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev evt = { { 0 } }; PyObject *rc = 0; - char *kwlist[] = { "nbits", "name", "event", "rng", "nsteps", 0 }; + static const char *const kwlist[] = + { "nbits", "name", "event", "rng", "nsteps", 0 }; + evt.exc = &exc; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|sO&O&O&", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|sO&O&O&", KWLIST, convuint, &nbits, &name, convpgev, &evt, convgrand, &r, convuint, &n)) goto end; if ((x = strongprime_setup(name, MP_NEW, &f, nbits, - r, n, evt.proc, evt.ctx)) == 0) - PGENERR; + r, n, evt.ev.proc, evt.ev.ctx)) == 0) + PGENERR(&exc); rc = Py_BuildValue("(NN)", mp_pywrap(x), pfilt_pywrap(&f)); x = 0; end: @@@ -989,19 -989,20 +990,21 @@@ static PyObject *meth_strongprime(PyObj unsigned nbits; char *name = "p"; unsigned n = 0; - pgev evt = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev evt = { { 0 } }; PyObject *rc = 0; - char *kwlist[] = { "nbits", "name", "event", "rng", "nsteps", 0 }; + static const char *const kwlist[] = + { "nbits", "name", "event", "rng", "nsteps", 0 }; + evt.exc = &exc; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|sO&O&O&", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|sO&O&O&", KWLIST, convuint, &nbits, &name, convpgev, &evt, convgrand, &r, convuint, &n)) goto end; if ((x = strongprime(name, MP_NEW, nbits, - r, n, evt.proc, evt.ctx)) == 0) - PGENERR; + r, n, evt.ev.proc, evt.ev.ctx)) == 0) + PGENERR(&exc); rc = mp_pywrap(x); x = 0; end: @@@ -1013,24 -1014,27 +1016,27 @@@ static PyObject *meth_limlee(PyObject *me, PyObject *arg, PyObject *kw) { char *p = "p"; - pgev ie = { 0 }, oe = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev ie = { { 0 } }, oe = { { 0 } }; unsigned ql, pl; grand *r = &rand_global; unsigned on = 0; size_t i, nf = 0; PyObject *rc = 0, *vec; - char *kwlist[] = { "pbits", "qbits", "name", "event", "ievent", - "rng", "nsteps", 0 }; + static const char *const kwlist[] = + { "pbits", "qbits", "name", "event", "ievent", "rng", "nsteps", 0 }; mp *x = 0, **v = 0; + ie.exc = oe.exc = &exc; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|sO&O&O&O&:limlee", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|sO&O&O&O&:limlee", KWLIST, convuint, &pl, convuint, &ql, &p, convpgev, &oe, convpgev, &ie, convgrand, &r, convuint, &on)) goto end; if ((x = limlee(p, MP_NEW, MP_NEW, ql, pl, r, on, - oe.proc, oe.ctx, ie.proc, ie.ctx, &nf, &v)) == 0) - PGENERR; + oe.ev.proc, oe.ev.ctx, ie.ev.proc, ie.ev.ctx, + &nf, &v)) == 0) + PGENERR(&exc);; vec = PyList_New(nf); for (i = 0; i < nf; i++) PyList_SetItem(vec, i, mp_pywrap(v[i])); @@@ -1048,18 -1052,18 +1054,18 @@@ static PyMethodDef methods[] = METH (_PrimeFilter_smallfactor, "smallfactor(X) -> PGRC") METH (_RabinMiller_iters, "iters(NBITS) -> NITERS") KWMETH(pgen, "\ - pgen(START, [name = 'p', stepper = PrimeGenStepper(2),\n\ - tester = PrimeGenTester(), event = pgen_nullev,\n\ - nsteps = 0, ntests = RabinMiller.iters(START.nbits)]) -> P") + pgen(START, [name = 'p'[, [stepper = PrimeGenStepper(2)],\n\ + [tester = PrimeGenTester()], [event = pgen_nullev],\n\ + [nsteps = 0], [ntests = RabinMiller.iters(START.nbits)]) -> P") KWMETH(strongprime_setup, "\ - strongprime_setup(NBITS, [name = 'p', event = pgen_nullev,\n\ - rng = rand, nsteps = 0]) -> (START, JUMP)") + strongprime_setup(NBITS, [name = 'p'], [event = pgen_nullev],\n\ + [rng = rand], [nsteps = 0]) -> (START, JUMP)") KWMETH(strongprime, "\ - strongprime(NBITS, [name = 'p', event = pgen_nullev,\n\ - rng = rand, nsteps = 0]) -> P") + strongprime(NBITS, [name = 'p'], [event = pgen_nullev],\n\ + [rng = rand], [nsteps = 0]) -> P") KWMETH(limlee, "\ - limlee(PBITS, QBITS, [name = 'p', event = pgen_nullev,\n\ - ievent = pgen_nullev, rng = rand, nsteps = 0]) -> (P, [Q, ...])") + limlee(PBITS, QBITS, [name = 'p'], [event = pgen_nullev],\n\ + [ievent = pgen_nullev], [rng = rand], [nsteps = 0]) -> (P, [Q, ...])") #undef METHNAME { 0 } }; diff --combined pubkey.c index 9c43ca7,0abb011..5680429 --- a/pubkey.c +++ b/pubkey.c @@@ -96,9 -96,9 +96,9 @@@ static PyObject *dsapub_pynew(PyTypeObj { PyObject *G, *p, *rng = rand_pyobj, *hash = sha_pyobj; PyObject *rc = 0; - char *kwlist[] = { "G", "p", "hash", "rng", 0 }; + static const char *const kwlist[] = { "G", "p", "hash", "rng", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|O!O!:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|O!O!:new", KWLIST, group_pytype, &G, ge_pytype, &p, gchash_pytype, &hash, @@@ -112,7 -112,7 +112,7 @@@ end static PyObject *dsameth_beginhash(PyObject *me, PyObject *arg) { if (!PyArg_ParseTuple(arg, ":beginhash")) return (0); - return (ghash_pywrap(DSA_HASH(me), gdsa_beginhash(DSA_D(me)), f_freeme)); + return (ghash_pywrap(DSA_HASH(me), gdsa_beginhash(DSA_D(me)))); } static PyObject *dsameth_endhash(PyObject *me, PyObject *arg) @@@ -135,9 -135,9 +135,9 @@@ static PyObject *dsameth_sign(PyObject Py_ssize_t n; mp *k = 0; PyObject *rc = 0; - char *kwlist[] = { "msg", "k", 0 }; + static const char *const kwlist[] = { "msg", "k", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:sign", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:sign", KWLIST, &p, &n, convmp, &k)) goto end; if (n != DSA_D(me)->h->hashsz) @@@ -175,9 -175,9 +175,9 @@@ static PyObject *dsapriv_pynew(PyTypeOb { PyObject *G, *p = 0, *u, *rng = rand_pyobj, *hash = sha_pyobj; PyObject *rc = 0; - char *kwlist[] = { "G", "u", "p", "hash", "rng", 0 }; + static const char *const kwlist[] = { "G", "u", "p", "hash", "rng", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O|O!O!O!:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O|O!O!O!:new", KWLIST, group_pytype, &G, &u, ge_pytype, &p, @@@ -200,7 -200,7 +200,7 @@@ static PyMethodDef dsapub_pymethods[] static PyMethodDef dsapriv_pymethods[] = { #define METHNAME(name) dsameth_##name - KWMETH(sign, "D.sign(MSG, k = K) -> R, S") + KWMETH(sign, "D.sign(MSG, [k = K]) -> R, S") #undef METHNAME { 0 } }; @@@ -247,7 -247,7 +247,7 @@@ static PyTypeObject dsapub_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"DSA public key information.", +"DSAPub(GROUP, P, [hash = sha], [rng = rand]): DSA public key.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -295,7 -295,7 +295,7 @@@ static PyTypeObject dsapriv_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"DSA private key information.", +"DSAPriv(GROUP, U, [p = u G], [hash = sha], [rng = rand]): DSA private key.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -323,9 -323,9 +323,9 @@@ static PyObject *kcdsapub_pynew(PyTypeO { PyObject *G, *p, *rng = rand_pyobj, *hash = has160_pyobj; PyObject *rc = 0; - char *kwlist[] = { "G", "p", "hash", "rng", 0 }; + static const char *const kwlist[] = { "G", "p", "hash", "rng", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|O!O!:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|O!O!:new", KWLIST, group_pytype, &G, ge_pytype, &p, gchash_pytype, &hash, @@@ -348,9 -348,9 +348,9 @@@ static PyObject *kcdsapriv_pynew(PyType { PyObject *G, *u, *p = 0, *rng = rand_pyobj, *hash = has160_pyobj; PyObject *rc = 0; - char *kwlist[] = { "G", "u", "p", "hash", "rng", 0 }; + static const char *const kwlist[] = { "G", "u", "p", "hash", "rng", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O|O!O!O!:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O|O!O!O!:new", KWLIST, group_pytype, &G, &u, ge_pytype, &p, @@@ -366,7 -366,7 +366,7 @@@ end static PyObject *kcdsameth_beginhash(PyObject *me, PyObject *arg) { if (!PyArg_ParseTuple(arg, ":beginhash")) return (0); - return (ghash_pywrap(DSA_HASH(me), gkcdsa_beginhash(DSA_D(me)), f_freeme)); + return (ghash_pywrap(DSA_HASH(me), gkcdsa_beginhash(DSA_D(me)))); } static PyObject *kcdsameth_endhash(PyObject *me, PyObject *arg) @@@ -389,9 -389,9 +389,9 @@@ static PyObject *kcdsameth_sign(PyObjec Py_ssize_t n; mp *k = 0; PyObject *r = 0, *rc = 0; - char *kwlist[] = { "msg", "k", 0 }; + static const char *const kwlist[] = { "msg", "k", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:sign", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:sign", KWLIST, &p, &n, convmp, &k)) goto end; if (n != DSA_D(me)->h->hashsz) @@@ -437,7 -437,7 +437,7 @@@ static PyMethodDef kcdsapub_pymethods[ static PyMethodDef kcdsapriv_pymethods[] = { #define METHNAME(name) kcdsameth_##name - KWMETH(sign, "D.sign(MSG, k = K) -> R, S") + KWMETH(sign, "D.sign(MSG, [k = K]) -> R, S") #undef METHNAME { 0 } }; @@@ -467,7 -467,7 +467,7 @@@ static PyTypeObject kcdsapub_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"KCDSA public key information.", +"KCDSAPub(GROUP, P, [hash = sha], [rng = rand]): KCDSA public key.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -515,7 -515,7 +515,7 @@@ static PyTypeObject kcdsapriv_pytype_sk Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"KCDSA private key information.", +"KCDSAPriv(GROUP, U, [p = u G], [hash = sha], [rng = rand]): KCDSA private key.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -569,9 -569,9 +569,9 @@@ static PyObject *rsapub_pynew(PyTypeObj { rsa_pub rp = { 0 }; rsapub_pyobj *o; - char *kwlist[] = { "n", "e", 0 }; + static const char *const kwlist[] = { "n", "e", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST, convmp, &rp.n, convmp, &rp.e)) goto end; if (!MP_ODDP(rp.n)) VALERR("RSA modulus must be even"); @@@ -636,10 -636,10 +636,10 @@@ static PyObject *rsapriv_pynew(PyTypeOb { rsa_priv rp = { 0 }; PyObject *rng = Py_None; - char *kwlist[] = + static const char *const kwlist[] = { "n", "e", "d", "p", "q", "dp", "dq", "q_inv", "rng", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&O&O&O&O&O&O&O&O:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&O&O&O&O&O&O&O&O:new", KWLIST, convmp, &rp.n, convmp, &rp.e, convmp, &rp.d, convmp, &rp.p, convmp, &rp.q, @@@ -649,7 -649,7 +649,7 @@@ goto end; if ((rp.n && !MP_ODDP(rp.n)) || (rp.p && !MP_ODDP(rp.p)) || - (rp.p && !MP_ODDP(rp.q))) + (rp.q && !MP_ODDP(rp.q))) VALERR("RSA modulus and factors must be odd"); if (rsa_recover(&rp)) VALERR("couldn't construct private key"); if (rng != Py_None && !GRAND_PYCHECK(rng)) @@@ -711,9 -711,9 +711,9 @@@ static PyObject *rsameth_privop(PyObjec PyObject *rng = RSA_RNG(me); mp *x = 0; PyObject *rc = 0; - char *kwlist[] = { "x", "rng", 0 }; + static const char *const kwlist[] = { "x", "rng", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O:privop", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O:privop", KWLIST, convmp, &x, &rng)) goto end; if (rng != Py_None && !GRAND_PYCHECK(rng)) @@@ -733,20 -733,21 +733,22 @@@ static PyObject *meth__RSAPriv_generate unsigned n = 0; rsa_priv rp; mp *e = 0; - pgev evt = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev evt = { { 0 } }; - char *kwlist[] = { "class", "nbits", "event", "rng", "nsteps", "e", 0 }; + static const char *const kwlist[] = + { "class", "nbits", "event", "rng", "nsteps", "e", 0 }; PyObject *rc = 0; + evt.exc = &exc; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&|O&O&O&O&:generate", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&|O&O&O&O&:generate", KWLIST, &me, convuint, &nbits, convpgev, &evt, convgrand, &r, convuint, &n, convmp, &e)) goto end; if (e) MP_COPY(e); else e = mp_fromulong(MP_NEW, 65537); - if (rsa_gen_e(&rp, nbits, e, r, n, evt.proc, evt.ctx)) - PGENERR; + if (rsa_gen_e(&rp, nbits, e, r, n, evt.ev.proc, evt.ev.ctx)) + PGENERR(&exc); rc = rsapriv_pywrap(&rp); end: droppgev(&evt); @@@ -784,7 -785,7 +786,7 @@@ static PyGetSetDef rsapriv_pygetset[] static PyMethodDef rsapriv_pymethods[] = { #define METHNAME(name) rsameth_##name - KWMETH(privop, "R.privop(X, rng = None) -> X^D (mod N)") + KWMETH(privop, "R.privop(X, [rng = None]) -> X^D (mod N)") #undef METHNAME { 0 } }; @@@ -814,7 -815,7 +816,7 @@@ static PyTypeObject rsapub_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"RSA public key information.", +"RSAPub(N, E): RSA public key.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -862,8 -863,7 +864,8 @@@ static PyTypeObject rsapriv_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"RSA private key information.", +"RSAPriv(..., [rng = rand]): RSA private key.\n\ + Keywords: n, e, d, p, q, dp, dq, q_inv; must provide enough", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -899,10 -899,10 +901,10 @@@ static PyObject *meth__p1crypt_encode(P octet *b = 0; size_t sz; mp *x; - char *kwlist[] = { "msg", "nbits", "ep", "rng", 0 }; + static const char *const kwlist[] = { "msg", "nbits", "ep", "rng", 0 }; p1.r = &rand_global; ep = 0; epsz = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|s#O&:encode", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|s#O&:encode", KWLIST, &m, &msz, convulong, &nbits, &ep, &epsz, convgrand, &p1.r)) goto end; @@@ -929,10 -929,10 +931,10 @@@ static PyObject *meth__p1crypt_decode(P octet *b = 0; size_t sz; mp *x = 0; - char *kwlist[] = { "ct", "nbits", "ep", "rng", 0 }; + static const char *const kwlist[] = { "ct", "nbits", "ep", "rng", 0 }; p1.r = &rand_global; ep = 0; epsz = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|s#O&:decode", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|s#O&:decode", KWLIST, convmp, &x, convulong, &nbits, &ep, &epsz, convgrand, &p1.r)) goto end; @@@ -960,10 -960,10 +962,10 @@@ static PyObject *meth__p1sig_encode(PyO octet *b = 0; size_t sz; mp *x; - char *kwlist[] = { "msg", "nbits", "ep", "rng", 0 }; + static const char *const kwlist[] = { "msg", "nbits", "ep", "rng", 0 }; p1.r = &rand_global; ep = 0; epsz = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|s#O&:encode", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|s#O&:encode", KWLIST, &m, &msz, convulong, &nbits, &ep, &epsz, convgrand, &p1.r)) goto end; @@@ -991,11 -991,10 +993,11 @@@ static PyObject *meth__p1sig_decode(PyO octet *b = 0; size_t sz; mp *x = 0; - char *kwlist[] = { "msg", "sig", "nbits", "ep", "rng", 0 }; + static const char *const kwlist[] = + { "msg", "sig", "nbits", "ep", "rng", 0 }; p1.r = &rand_global; ep = 0; epsz = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&|s#O&:decode", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&|s#O&:decode", KWLIST, &hukairz, convmp, &x, convulong, &nbits, &ep, &epsz, convgrand, &p1.r)) goto end; @@@ -1023,11 -1022,10 +1025,11 @@@ static PyObject *meth__oaep_encode(PyOb octet *b = 0; size_t sz; mp *x; - char *kwlist[] = { "msg", "nbits", "mgf", "hash", "ep", "rng", 0 }; + static const char *const kwlist[] = + { "msg", "nbits", "mgf", "hash", "ep", "rng", 0 }; o.r = &rand_global; o.cc = &sha_mgf; o.ch = &sha; ep = 0; epsz = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|O&O&s#O&:encode", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|O&O&s#O&:encode", KWLIST, &m, &msz, convulong, &nbits, convgccipher, &o.cc, convgchash, &o.ch, @@@ -1057,11 -1055,10 +1059,11 @@@ static PyObject *meth__oaep_decode(PyOb octet *b = 0; size_t sz; mp *x = 0; - char *kwlist[] = { "ct", "nbits", "mgf", "hash", "ep", "rng", 0 }; + static const char *const kwlist[] = + { "ct", "nbits", "mgf", "hash", "ep", "rng", 0 }; o.r = &rand_global; o.cc = &sha_mgf; o.ch = &sha; ep = 0; epsz = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&s#O&:decode", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&s#O&:decode", KWLIST, convmp, &x, convulong, &nbits, convgccipher, &o.cc, convgchash, &o.ch, @@@ -1092,11 -1089,10 +1094,11 @@@ static PyObject *meth__pss_encode(PyObj octet *b = 0; size_t sz; mp *x = 0; - char *kwlist[] = { "msg", "nbits", "mgf", "hash", "saltsz", "rng", 0 }; + static const char *const kwlist[] = + { "msg", "nbits", "mgf", "hash", "saltsz", "rng", 0 }; p.cc = &sha_mgf; p.ch = &sha; p.r = &rand_global; p.ssz = (size_t)-1; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|O&O&O&O&:encode", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|O&O&O&O&:encode", KWLIST, &m, &msz, convulong, &nbits, convgccipher, &p.cc, convgchash, &p.ch, @@@ -1126,11 -1122,11 +1128,11 @@@ static PyObject *meth__pss_decode(PyObj size_t sz; int n; mp *x = 0; - char *kwlist[] = + static const char *const kwlist[] = { "msg", "sig", "nbits", "mgf", "hash", "saltsz", "rng", 0 }; p.cc = &sha_mgf; p.ch = &sha; p.r = &rand_global; p.ssz = (size_t)-1; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&O&|O&O&O&O&:decode", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&O&|O&O&O&O&:decode", KWLIST, &m, &msz, convmp, &x, convulong, &nbits, convgccipher, &p.cc, convgchash, &p.ch, @@@ -1206,11 -1202,10 +1208,11 @@@ XDHS(DEFXDH int ph = phdflt; \ PyObject *rc = 0; \ octet pp[ED##_PUBSZ]; \ - char *kwlist[] = { "key", "msg", "pub", "perso", "phflag", 0 }; \ + static const char *const kwlist[] = \ + { "key", "msg", "pub", "perso", "phflag", 0 }; \ if (!PyArg_ParseTupleAndKeywords(arg, kw, \ "s#s#|s#s#O&:" #ed "_sign", \ - kwlist, \ + KWLIST, \ &k, &ksz, &m, &msz, &p, &psz, \ &c, &csz, convbool, &ph)) \ goto end; \ @@@ -1234,11 -1229,10 +1236,11 @@@ Py_ssize_t psz, csz = 0, msz, ssz; \ int ph = phdflt; \ PyObject *rc = 0; \ - char *kwlist[] = { "pub", "msg", "sig", "perso", "phflag", 0 }; \ + static const char *const kwlist[] = \ + { "pub", "msg", "sig", "perso", "phflag", 0 }; \ if (!PyArg_ParseTupleAndKeywords(arg, kw, \ "s#s#s#|s#O&:" #ed "_verify", \ - kwlist, \ + KWLIST, \ &p, &psz, &m, &msz, &s, &ssz, \ &c, &csz, convbool, &ph)) \ goto end; \ @@@ -1269,7 -1263,7 +1271,7 @@@ static PyMethodDef methods[] = KWMETH(_pss_encode, 0) KWMETH(_pss_decode, 0) KWMETH(_RSAPriv_generate, "\ - generate(NBITS, [event = pgen_nullev, rng = rand, nsteps = 0]) -> R") + generate(NBITS, [event = pgen_nullev], [rng = rand], [nsteps = 0]) -> R") #define DEFMETH(X, x) \ METH (x, "\ " #x "(KEY, PUBLIC) -> SHARED") @@@ -1279,11 -1273,11 +1281,11 @@@ METH (ed##_pubkey, "\ " #ed "_pubkey(KEY) -> PUBLIC") \ KWMETH(ed##_sign, "\ - " #ed "_sign(KEY, MSG, [pub = PUBLIC, " \ - "perso = STRING, phflag = BOOL]) -> SIG") \ + " #ed "_sign(KEY, MSG, [pub = PUBLIC], " \ + "[perso = STRING], [phflag = BOOL]) -> SIG") \ KWMETH(ed##_verify, "\ " #ed "_verify(PUBLIC, MSG, SIG, " \ - "[perso = STRING, phflag = BOOL]) -> BOOL") + "[perso = STRING], [phflag = BOOL]) -> BOOL") EDDSAS(DEFMETH) #undef DEFMETH #undef METHNAME diff --combined rand.c index 9afb271,1203f76..d57795a --- a/rand.c +++ b/rand.c @@@ -124,9 -124,9 +124,9 @@@ static PyObject *grmeth_mp(PyObject *me { size_t l; mpw o = 0; - char *kwlist[] = { "bits", "or", 0 }; + static const char *const kwlist[] = { "bits", "or", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:mp", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:mp", KWLIST, convszt, &l, convmpw, &o)) goto end; if (grand_check(me)) return (0); @@@ -214,10 -214,10 +214,10 @@@ end static PyObject *grmeth_seedrand(PyObject *me, PyObject *arg, PyObject *kw) { - char *kwlist[] = { "rng", 0 }; + static const char *const kwlist[] = { "rng", 0 }; grand *r = GRAND_R(me); grand *rr = &rand_global; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:seedrand", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:seedrand", KWLIST, convgrand, &rr) || grand_check(me) || checkop(r, GRAND_SEEDRAND, "seedrand")) goto end; @@@ -332,8 -332,8 +332,8 @@@ static PyTypeObject grand_pytype_skel static PyObject *lcrand_pynew(PyTypeObject *me, PyObject *arg, PyObject *kw) { uint32 n = 0; - char *kwlist[] = { "seed", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", kwlist, convu32, &n)) + static const char *const kwlist[] = { "seed", 0 }; + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", KWLIST, convu32, &n)) return (0); return (grand_dopywrap(lcrand_pytype, lcrand_create(n), f_freeme)); } @@@ -363,7 -363,7 +363,7 @@@ static PyTypeObject lcrand_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Linear congruential generator.", +"LCRand([seed = 0]): linear congruential generator.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -389,8 -389,8 +389,8 @@@ static PyObject *fibrand_pynew(PyTypeObject *me, PyObject *arg, PyObject *kw) { uint32 n = 0; - char *kwlist[] = { "seed", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", kwlist, convu32, &n)) + static const char *const kwlist[] = { "seed", 0 }; + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", KWLIST, convu32, &n)) return (0); return (grand_dopywrap(fibrand_pytype, fibrand_create(n), f_freeme)); } @@@ -420,7 -420,7 +420,7 @@@ static PyTypeObject fibrand_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Fibonacci generator.", +"FibRand([seed = 0]): Fibonacci generator.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -503,10 -503,10 +503,10 @@@ static PyObject *trmeth_timer(PyObject static PyObject *truerand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *kwlist[] = { 0 }; + static const char *const kwlist[] = { 0 }; grand *r; PyObject *rc = 0; - if (PyArg_ParseTupleAndKeywords(arg, kw, ":new", KWLIST)) goto end; - if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", kwlist)) goto end; ++ if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", KWLIST)) goto end; r = rand_create(); r->ops->misc(r, RAND_NOISESRC, &noise_source); r->ops->misc(r, RAND_SEED, 160); @@@ -565,7 -565,7 +565,7 @@@ static PyTypeObject truerand_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"True random number source.", +"TrueRand(): true random number source.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -639,11 -639,11 +639,11 @@@ static const gccrand_info *const gcrand static PyObject *gcrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { const gccrand_info *info = GCCRAND_INFO(ty); - static char *kwlist[] = { "key", 0 }; + static const char *const kwlist[] = { "key", 0 }; char *k; Py_ssize_t n; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &n)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &n)) goto end; if (keysz(n, info->keysz) != n) VALERR("bad key length"); return (grand_dopywrap(ty, info->func(k, n), f_freeme)); @@@ -655,11 -655,11 +655,11 @@@ static PyObject *gcirand_pynew(PyTypeOb { const gccrand_info *info = GCCRAND_INFO(ty); uint32 i = 0; - static char *kwlist[] = { "key", "i", 0 }; + static const char *const kwlist[] = { "key", "i", 0 }; char *k; Py_ssize_t n; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&:new", KWLIST, &k, &n, convu32, &i)) goto end; if (keysz(n, info->keysz) != n) VALERR("bad key length"); @@@ -673,11 -673,11 +673,11 @@@ end static PyObject *gcnrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { const gccrand_info *info = GCCRAND_INFO(ty); - static char *kwlist[] = { "key", "nonce", 0 }; + static const char *const kwlist[] = { "key", "nonce", 0 }; char *k, *n; Py_ssize_t ksz, nsz; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#:new", KWLIST, &k, &ksz, &n, &nsz)) goto end; if (keysz(ksz, info->keysz) != ksz) VALERR("bad key length"); @@@ -693,18 -693,15 +693,18 @@@ static PyObject *gcshakyrand_pynew(PyTy PyObject *arg, PyObject *kw) { const gccrand_info *info = GCCRAND_INFO(ty); - static char *kwlist_shake[] = { "key", "func", "perso", 0 }; - static char *kwlist_func[] = { "key", "perso", 0 }; + static const char + *const kwlist_shake[] = { "key", "func", "perso", 0 }, + *const kwlist_func[] = { "key", "perso", 0 }; char *k, *f = 0, *p = 0; Py_ssize_t ksz, fsz = 0, psz = 0; if ((info->f&RNGF_MASK) == RNG_SHAKE - ? !PyArg_ParseTupleAndKeywords(arg, kw, "s#|s#s#:new", kwlist_shake, + ? !PyArg_ParseTupleAndKeywords(arg, kw, "s#|s#s#:new", + (/*unconst*/ char **)kwlist_shake, &k, &ksz, &f, &fsz, &p, &psz) - : !PyArg_ParseTupleAndKeywords(arg, kw, "s#|s#:new", kwlist_func, + : !PyArg_ParseTupleAndKeywords(arg, kw, "s#|s#:new", + (/*unconst*/ char **)kwlist_func, &k, &ksz, &p, &psz)) goto end; if (keysz(ksz, info->keysz) != ksz) VALERR("bad key length"); @@@ -941,9 -938,9 +941,9 @@@ static PyObject *sslprf_pynew(PyTypeObj int ksz, ssz; const gchash *hco = &md5, *hci = &sha; PyObject *rc = 0; - char *kwlist[] = { "key", "seed", "ohash", "ihash", 0 }; + static const char *const kwlist[] = { "key", "seed", "ohash", "ihash", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&O&:new", KWLIST, &k, &ksz, &s, &ssz, convgchash, &hco, convgchash, &hci)) goto end; @@@ -958,9 -955,9 +958,9 @@@ static PyObject *tlsdx_pynew(PyTypeObje int ksz, ssz; const gcmac *mc = &sha_hmac; PyObject *rc = 0; - char *kwlist[] = { "key", "seed", "mac", 0 }; + static const char *const kwlist[] = { "key", "seed", "mac", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&:new", KWLIST, &k, &ksz, &s, &ssz, convgcmac, &mc)) goto end; @@@ -975,9 -972,9 +975,9 @@@ static PyObject *tlsprf_pynew(PyTypeObj int ksz, ssz; const gcmac *mcl = &md5_hmac, *mcr = &sha_hmac; PyObject *rc = 0; - char *kwlist[] = { "key", "seed", "lmac", "rmac", 0 }; + static const char *const kwlist[] = { "key", "seed", "lmac", "rmac", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&O&:new", KWLIST, &k, &ksz, &s, &ssz, convgcmac, &mcl, convgcmac, &mcr)) goto end; @@@ -1011,8 -1008,7 +1011,8 @@@ static PyTypeObject sslprf_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Random number generator for SSL master secret.", +"SSLRand(KEY, SEED, [ohash = md5], [ihash = sha]):\n\ + RNG for SSL master secret.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1060,8 -1056,7 +1060,8 @@@ static PyTypeObject tlsdx_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"TLS data expansion function.", +"TLSDataExpansion(KEY, SEED, [mac = sha_hmac]):\n\ + TLS data expansion function.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1109,8 -1104,7 +1109,8 @@@ static PyTypeObject tlsprf_pytype_skel Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"TLS pseudorandom function.", +"TLSPRF(KEY, SEED, [lmac = md5_hmac], [rmac = sha_hmac]):\n\ + TLS pseudorandom function.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1140,9 -1134,9 +1140,9 @@@ static PyObject *dsarand_pynew(PyTypeOb char *p; int sz; PyObject *rc = 0; - char *kwlist[] = { "seed", 0 }; + static const char *const kwlist[] = { "seed", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &p, &sz)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &p, &sz)) goto end; rc = grand_dopywrap(ty, dsarand_create(p, sz), f_freeme); end: @@@ -1190,7 -1184,7 +1190,7 @@@ static PyTypeObject dsarand_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Pseudorandom number generator for constructing DSA parameters.", +"DSARand(SEED): pseudorandom number generator for DSA parameters.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1219,9 -1213,9 +1219,9 @@@ static PyObject *bbs_pynew(PyTypeObjec { mp *n = 0, *x = MP_TWO; PyObject *rc = 0; - char *kwlist[] = { "n", "x", 0 }; + static const char *const kwlist[] = { "n", "x", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", KWLIST, convmp, &n, convmp, &x)) goto end; rc = grand_dopywrap(ty, bbs_rand(n, x), f_freeme); @@@ -1267,9 -1261,8 +1267,9 @@@ static PyObject *bbsget_x(PyObject *me static int bbsset_x(PyObject *me, PyObject *val, void *hunoz) { - mp *x = 0; grand *r = GRAND_R(me); int rc = -1; if (!x) NIERR("__del__"); + mp *x = 0; grand *r = GRAND_R(me); int rc = -1; if (!val) NIERR("__del__"); - if ((x = getmp(val)) == 0) goto end; r->ops->misc(r, BBS_SET, x); rc = 0; + if ((x = getmp(val)) == 0) goto end; + r->ops->misc(r, BBS_SET, x); rc = 0; end: mp_drop(x); return (rc); } @@@ -1322,7 -1315,7 +1322,7 @@@ static PyTypeObject bbs_pytype_skel = Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Blum-Blum-Shub strong pseudorandom number generator.", +"BlumBlumShub(N, [x = 2]): Blum-Blum-Shub pseudorandom number generator.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1357,9 -1350,9 +1357,9 @@@ static PyObject *bbspriv_pynew(PyTypeOb { mp *p = 0, *q = 0, *n = 0, *x = MP_TWO; bbspriv_pyobj *rc = 0; - char *kwlist[] = { "n", "p", "q", "seed", 0 }; + static const char *const kwlist[] = { "n", "p", "q", "seed", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&O&O&O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&O&O&O&:new", KWLIST, convmp, &n, convmp, &p, convmp, &q, convmp, &x)) goto end; @@@ -1383,19 -1376,20 +1383,21 @@@ static PyObject *meth__BBSPriv_generate { bbs_priv bp = { 0 }; mp *x = MP_TWO; - pgev evt = { 0 }; + struct excinfo exc = EXCINFO_INIT; + pypgev evt = { { 0 } }; unsigned nbits, n = 0; grand *r = &rand_global; - char *kwlist[] = { "class", "nbits", "event", "rng", "nsteps", "seed", 0 }; + static const char *const kwlist[] = + { "class", "nbits", "event", "rng", "nsteps", "seed", 0 }; bbspriv_pyobj *rc = 0; + evt.exc = &exc; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&|O&O&O&O&:generate", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&|O&O&O&O&:generate", KWLIST, &me, convuint, &nbits, convpgev, &evt, convgrand, &r, convuint, &n, convmp, &x)) goto end; - if (bbs_gen(&bp, nbits, r, n, evt.proc, evt.ctx)) - VALERR("prime genration failed"); + if (bbs_gen(&bp, nbits, r, n, evt.ev.proc, evt.ev.ctx)) + PGENERR(&exc); rc = PyObject_New(bbspriv_pyobj, bbspriv_pytype); rc->gr.r = bbs_rand(bp.n, x); rc->gr.f = f_freeme; @@@ -1481,8 -1475,7 +1483,8 @@@ static PyTypeObject bbspriv_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ -"Blum-Blum-Shub strong pseudorandom generator, with private key.", +"BBSPriv(..., seed = 2]): Blum-Blum-Shub, with private key.\n\ + Keywords: n, p, q; must provide at least two", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -1510,7 -1503,8 +1512,8 @@@ static PyMethodDef methods[] = { #define METHNAME(name) meth_##name KWMETH(_BBSPriv_generate, "\ - generate(NBITS, [event = pgen_nullev, rng = rand, nsteps = 0, seed = 2])") + generate(NBITS, [event = pgen_nullev], [rng = rand],\n\ + [nsteps = 0], [seed = 2]) -> R") #undef METHNAME { 0 } }; diff --combined setup.py index efa922b,80a1547..d778177 --- a/setup.py +++ b/setup.py @@@ -3,8 -3,8 +3,8 @@@ import distutils.core as DC import mdwsetup as MS -MS.pkg_config('catacomb', '2.3.0.1+4') -MS.pkg_config('mLib', '2.0.4') +MS.pkg_config('catacomb', '2.5.0') +MS.pkg_config('mLib', '2.2.2.1') cat = DC.Extension('catacomb._base', ['catacomb.c', 'bytestring.c', 'buffer.c', @@@ -23,7 -23,11 +23,12 @@@ MS.setup(name = 'catacomb-python' author_email = 'mdw@distorted.org.uk', license = 'GNU General Public License', packages = ['catacomb'], - scripts = ['pwsafe'], + scripts = ['pock', 'pwsafe'], + data_files = [('share/man/man1', ['pock.1', 'pwsafe.1'])], genfiles = [MS.Generate('algorithms.h')], + unittest_dir = "t", + unittests = ["t-misc", "t-algorithms", "t-bytes", "t-buffer", + "t-convert", "t-ec", "t-field", "t-group", "t-key", + "t-mp", "t-passphrase", "t-pgen", "t-pubkey", + "t-rand", "t-rat", "t-share"], ext_modules = [cat]) diff --combined util.c index 2e6ee25,29f7d12..723c819 --- a/util.c +++ b/util.c @@@ -28,9 -28,12 +28,12 @@@ #include "catacomb-python.h" + /* #undef HAVE_LONG_LONG */ + /*----- External values ---------------------------------------------------*/ static PyObject *modname = 0; + PyObject *home_module = 0; /*----- Conversions -------------------------------------------------------*/ @@@ -42,12 -45,17 +45,17 @@@ PyObject *getulong(unsigned long w return (PyLong_FromUnsignedLong(w)); } + #ifndef HAVE_LONG_LONG static PyObject *i32 = 0; static int init_i32(void) { if (!i32 && (i32 = PyInt_FromLong(32)) == 0) return (-1); return (0); } + #endif PyObject *getk64(kludge64 u) { + #ifdef HAVE_LONG_LONG + return (PyLong_FromUnsignedLongLong(GET64(unsigned PY_LONG_LONG, u))); + #else PyObject *i = 0, *j = 0, *t; PyObject *rc = 0; @@@ -63,6 -71,7 +71,7 @@@ end if (i) Py_DECREF(i); if (j) Py_DECREF(j); return (rc); + #endif } PyObject *getbool(int b) @@@ -99,15 -108,32 +108,32 @@@ end return (0); } + #ifdef HAVE_UINT64 + # define CONVu64(n) do { \ + kludge64 k; \ + uint64 t; \ + if (!convk64(o, &k)) goto end; \ + t = GET64(uint64, k); \ + if (t > MASK##n) VALERR("out of range"); \ + *p = t; \ + } while (0) + #else + # define CONVu64(n) assert(!"shouldn't be possible") + #endif + #define CONVU_(n) \ int convu##n(PyObject *o, void *pp) \ { \ unsigned long u; \ uint##n *p = pp; \ \ - if (!convulong(o, &u)) goto end; \ - if (u > MASK##n) VALERR("out of range"); \ - *p = u; \ + if (MASK##n > ULONG_MAX) \ + CONVu64(n); \ + else { \ + if (!convulong(o, &u)) goto end; \ + if (u > MASK##n) VALERR("out of range"); \ + *p = u; \ + } \ return (1); \ end: \ return (0); \ @@@ -129,11 -155,22 +155,22 @@@ end int convk64(PyObject *o, void *pp) { - PyObject *i = 0, *t; + PyObject *i = 0; int rc = 0; + #if HAVE_LONG_LONG + unsigned PY_LONG_LONG t; + #else + PyObject *t; uint32 lo, hi; + #endif if (!o) VALERR("can't delete"); + #if HAVE_LONG_LONG + if ((i = PyNumber_Long(o)) == 0) goto end; + t = PyLong_AsUnsignedLongLong(i); + if (t == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) goto end; + ASSIGN64(*(kludge64 *)pp, t); + #else if (init_i32()) goto end; if ((i = PyNumber_Int(o)) == 0) goto end; lo = PyInt_AsUnsignedLongMask(i); @@@ -144,7 -181,9 +181,9 @@@ Py_DECREF(i); i = t; if (PyObject_IsTrue(i)) VALERR("out of range"); SET64(*(kludge64 *)pp, hi, lo); + #endif rc = 1; + end: if (i) Py_DECREF(i); return (rc); @@@ -241,14 -280,14 +280,14 @@@ PyTypeObject *inittype(PyTypeObject *ty void setconstants(PyObject *mod, const struct nameval *c) { PyObject *x; + unsigned long u; while (c->name) { - if (c->value > LONG_MAX) - x = PyLong_FromUnsignedLong(c->value); - else - x = PyInt_FromLong(c->value); - PyModule_AddObject(mod, (/*unconst*/ char *)c->name, x); - c++; + u = c->value; + if (u <= LONG_MAX) x = PyInt_FromLong(u); + else if (c->f&CF_SIGNED) x = PyInt_FromLong(-1 - (long)(ULONG_MAX - u)); + else x = PyLong_FromUnsignedLong(u); + PyModule_AddObject(mod, (/*unconst*/ char *)c->name, x); c++; } } @@@ -285,13 -324,7 +324,7 @@@ PyObject *mkexc(PyObject *mod, PyObjec PyObject *func = 0; PyObject *meth = 0; - if ((nameobj = PyString_FromFormat("%s.%s", - PyModule_GetName(mod), - name)) == 0 || - (dict = PyDict_New()) == 0 || - (exc = PyErr_NewException(PyString_AS_STRING(nameobj), - base, dict)) == 0) - goto fail; + if ((dict = PyDict_New()) == 0) goto fail; if (mm) { while (mm->ml_name) { @@@ -305,6 -338,13 +338,13 @@@ } } + if ((nameobj = PyString_FromFormat("%s.%s", + PyModule_GetName(mod), + name)) == 0 || + (exc = PyErr_NewException(PyString_AS_STRING(nameobj), + base, dict)) == 0) + goto fail; + done: Py_XDECREF(nameobj); Py_XDECREF(dict); @@@ -318,6 -358,101 +358,101 @@@ fail goto done; } + void report_lost_exception_v(struct excinfo *exc, + const char *why, va_list ap) + { + PyObject *hookfn = 0; + PyObject *whyobj = 0; + PyObject *obj = 0; + + /* Make sure we start out without a pending exception, or this will get + * really confusing. + */ + assert(!PyErr_Occurred()); + + /* Format the explanation. */ + if (why) whyobj = PyString_FromFormatV(why, ap); + else { whyobj = Py_None; Py_INCREF(whyobj); } + + /* Find our home module's `lostexchook' function. This won't work if + * there's no module, or the function isn't defined, or it's `None'. + */ + if (!home_module) goto sys; + hookfn = PyObject_GetAttrString(home_module, "lostexchook"); + if (hookfn == Py_None) goto sys; + else if (hookfn) ; + else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto ouch; + else { PyErr_Clear(); goto sys; } + + /* Call the hook function. */ + obj = PyObject_CallFunction(hookfn, "(OOOO)", + whyobj, exc->ty, exc->val, exc->tb); + if (!obj) goto ouch; + goto end; + + /* Something went wrong reporting the problem. */ + ouch: + PySys_WriteStderr("\n!!! FAILURE REPORTING LOST EXCEPTION\n"); + PyErr_Print(); + /* drop through... */ + + /* There was no hook, so try to do something sensible using + * `sys.excepthook'. + */ + sys: + PySys_WriteStderr("\n!!! LOST EXCEPTION: %s\n", + PyString_AS_STRING(whyobj)); + RESTORE_EXCINFO(exc); + PyErr_Print(); + /* drop through... */ + + /* Clean up afterwards. */ + end: + Py_XDECREF(hookfn); + Py_XDECREF(whyobj); + Py_XDECREF(obj); + } + + void report_lost_exception(struct excinfo *exc, const char *why, ...) + { + va_list ap; + + va_start(ap, why); + report_lost_exception_v(exc, why, ap); + va_end(ap); + } + + void stash_exception(struct excinfo *exc, const char *why, ...) + { + va_list ap; + struct excinfo stash; + + if (!exc->ty) + STASH_EXCINFO(exc); + else { + va_start(ap, why); + STASH_EXCINFO(&stash); + report_lost_exception_v(&stash, why, ap); + va_end(ap); + } + } + + void restore_exception(struct excinfo *exc, const char *why, ...) + { + va_list ap; + struct excinfo stash; + + if (!PyErr_Occurred()) + RESTORE_EXCINFO(exc); + else { + va_start(ap, why); + STASH_EXCINFO(&stash); + report_lost_exception_v(exc, why, ap); + RESTORE_EXCINFO(&stash); + va_end(ap); + } + } + /*----- Generic dictionary methods ----------------------------------------*/ static PyTypeObject *itemiter_pytype, *valiter_pytype; @@@ -369,7 -504,7 +504,7 @@@ static PyTypeObject itemiter_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Iterates over the items of a mapping.", + "Iterates over the keys of a mapping.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -427,7 -562,7 +562,7 @@@ static PyTypeObject valiter_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "Iterates over the items of a mapping.", + "Iterates over the values of a mapping.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@@ -466,8 -601,7 +601,7 @@@ PySequenceMethods gmap_pysequence = Py_ssize_t gmap_pysize(PyObject *me) { PyObject *i = 0, *x = 0; - int rc = -1; - int n = 0; + Py_ssize_t rc = -1, n = 0; if ((i = PyObject_GetIter(me)) == 0) goto done; while ((x = PyIter_Next(i)) != 0) { n++; Py_DECREF(x); x = 0; } @@@ -603,15 -737,13 +737,15 @@@ end return (rc); } -static char *def_kwlist[] = { "key", "default", 0 }; +static const char *const def_kwlist[] = { "key", "default", 0 }; PyObject *gmapmeth_get(PyObject *me, PyObject *arg, PyObject *kw) { PyObject *k, *def = Py_None, *v; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO:get", - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|O:get", def_kwlist, &k, &def)) ++ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|O:get", + (/*unconst*/ char **)def_kwlist, + &k, &def)) return (0); if ((v = PyObject_GetItem(me, k)) != 0) return (v); PyErr_Clear(); @@@ -622,9 -754,8 +756,9 @@@ PyObject *gmapmeth_setdefault(PyObject { PyObject *k, *def = Py_None, *v; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO:setdefault", + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|O:setdefault", - def_kwlist, &k, &def)) + (/*unconst*/ char **)def_kwlist, + &k, &def)) return (0); if ((v = PyObject_GetItem(me, k)) != 0) return (v); PyErr_Clear(); @@@ -636,16 -767,16 +770,18 @@@ PyObject *gmapmeth_pop(PyObject *me, Py { PyObject *k, *def = 0, *v; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO:pop", - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|O:pop", def_kwlist, &k, &def)) ++ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|O:pop", + (/*unconst*/ char **)def_kwlist, + &k, &def)) return (0); if ((v = PyObject_GetItem(me, k)) != 0) { PyObject_DelItem(me, k); return (v); - } - PyErr_Clear(); - RETURN_OBJ(def); + } else if (def) { + PyErr_Clear(); + RETURN_OBJ(def); + } else + return (0); } PyObject *gmapmeth_update(PyObject *me, PyObject *arg) @@@ -675,7 -806,7 +811,7 @@@ PyObject *gmapmeth_popitem(PyObject *me PyObject *i = 0, *k = 0, *v = 0, *rc = 0; if (!PyArg_ParseTuple(arg, ":popitem") || - (i = PyObject_GetIter(me))) + (i = PyObject_GetIter(me)) == 0) goto end; if ((k = PyIter_Next(i)) == 0) { if (!PyErr_Occurred()) VALERR("popitem(): mapping is empty"); @@@ -697,11 -828,29 +833,29 @@@ PyMethodDef gmap_pymethods[] = /*----- Initialization ----------------------------------------------------*/ + static PyObject *meth__set_home_module(PyObject *me, PyObject *arg) + { + PyObject *mod; + + if (!PyArg_ParseTuple(arg, "O!:_set_home_module", &PyModule_Type, &mod)) + return (0); + Py_XDECREF(home_module); home_module = mod; Py_INCREF(home_module); + RETURN_NONE; + } + + static const PyMethodDef methods[] = { + #define METHNAME(func) meth_##func + METH (_set_home_module, "_set_home_module(MOD)") + #undef METHNAME + { 0 } + }; + void util_pyinit(void) { modname = PyString_FromString("catacomb"); INITTYPE(itemiter, root); INITTYPE(valiter, root); + addmethods(methods); } void util_pyinsert(PyObject *mod)