From: Mark Wooding Date: Wed, 27 Nov 2019 15:12:23 +0000 (+0000) Subject: Merge branch '1.3.x' X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/commitdiff_plain/740847afe208bb8f33e7d6cf642acaf4aa739f6a?hp=-c Merge branch '1.3.x' * 1.3.x: (101 commits) rand.c: Show keyword argument as optional. mp.c: Fix punctuation error in docstrings. t/t-*.py: Use the `WriteBuffer.contents' property. t/t-bytes.py: Check that indexing, slicing, etc. return `C.ByteString'. t/t-algorithms.py: Add a simple test for `Keccak1600.copy'. t/t-algorithms.py: Add tests for other HSalsa20 and HChaCha key sizes. t/t-algorithms.py: Add AEAD tests. t/t-algorithms.py: Add tests for the new `KeySZ.pad' method. catacomb/__init__.py (KeySZRange.pad): Return correct value. algorithms.c: Propagate `AEADF_NOAAD' to `aad' objects. algorithms.c (AEADAAD.copy): Propagate the hashed length to the copy. 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. ... --- 740847afe208bb8f33e7d6cf642acaf4aa739f6a diff --combined algorithms.c index 2a3bece,064fb03..888ceb0 --- a/algorithms.c +++ b/algorithms.c @@@ -27,9 -27,7 +27,9 @@@ /*----- Header files ------------------------------------------------------*/ #include "catacomb-python.h" +PUBLIC_SYMBOLS; #include "algorithms.h" +PRIVATE_SYMBOLS; /*----- Key sizes ---------------------------------------------------------*/ @@@ -137,9 -135,8 +137,8 @@@ static PyObject *keyszset_pynew(PyTypeO 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); @@@ -208,7 -205,7 +207,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 } }; @@@ -216,7 -213,7 +215,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 @@@ -226,7 -223,7 +225,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 } }; @@@ -990,6 -987,7 +989,7 @@@ static PyObject *gaeameth_copy(PyObjec VALERR("can't duplicate nonce-dependent aad"); rc = gaeadaad_pywrap((PyObject *)me->ob_type, GAEAD_DUP(GAEADAAD_A(me)), 0, 0); + GAEADAAD_HLEN(rc) = GAEADAAD_HLEN(me); end: return (rc); } @@@ -1133,7 -1131,8 +1133,8 @@@ static PyObject *gaeemeth_aad(PyObject 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); + GAEAD_AAD(ge->e), ge->f&(AEADF_PCHSZ | AEADF_NOAAD), + ge->hsz); Py_INCREF(ge->aad); rc = (PyObject *)ge->aad; } @@@ -1304,7 -1303,8 +1305,8 @@@ static PyObject *gaedmeth_aad(PyObject 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); + GAEAD_AAD(gd->d), gd->f&(AEADF_PCHSZ | AEADF_NOAAD), + gd->hsz); Py_INCREF(gd->aad); return ((PyObject *)gd->aad); } @@@ -2639,7 -2639,7 +2641,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); \ @@@ -2667,7 -2667,8 +2669,7 @@@ typedef struct kxvik_pyobj unsigned n; } kxvik_pyobj; -static PyObject *kxvik_pynew(PyTypeObject *ty, - PyObject *arg, PyObject *kw) +static PyObject *kxvik_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { unsigned n = 24; kxvik_pyobj *rc = 0; @@@ -2725,7 -2726,7 +2727,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); @@@ -2755,10 -2756,14 +2757,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[] = { @@@ -2955,7 -2960,7 +2961,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) diff --combined catacomb-python.h index 5815343,6c1ae21..bf3d426 --- a/catacomb-python.h +++ b/catacomb-python.h @@@ -120,21 -120,6 +120,21 @@@ #include #include +/*----- Other preliminaries -----------------------------------------------*/ + +#define GOBBLE_SEMI extern int notexist +#if defined(__GNUC__) && defined(__ELF__) +# define PRIVATE_SYMBOLS _Pragma("GCC visibility push(hidden)") GOBBLE_SEMI +# define PUBLIC_SYMBOLS _Pragma("GCC visibility pop") GOBBLE_SEMI +# define EXPORT __attribute__((__visibility__("default"))) +#else +# define PRIVATE_SYMBOLS GOBBLE_SEMI +# define PUBLIC_SYMBOLS GOBBLE_SEMI +# define EXPORT +#endif + +PRIVATE_SYMBOLS; + /*----- Utility macros ----------------------------------------------------*/ #define RETURN_OBJ(obj) do { Py_INCREF(obj); return (obj); } while (0) @@@ -149,6 -134,7 +149,7 @@@ 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) @@@ -162,7 -148,7 +163,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) \ @@@ -188,7 -174,9 +189,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); \ @@@ -250,7 -238,8 +253,8 @@@ MODULES(DO #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, @@@ -274,7 -263,34 +278,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 *); @@@ -343,6 -359,7 +374,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 *); @@@ -361,7 -378,6 +393,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 @@@ -715,9 -731,15 +746,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 572f80f,e9c9513..e868f0f --- 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), @@@ -56,6 -58,7 +58,7 @@@ KEY_ERRORS(ENTRY) #undef ENTRY #undef C + #undef CF { 0 } }; @@@ -75,7 -78,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; @@@ -140,7 -144,7 +144,7 @@@ static PyObject *meth__ego(PyObject *me char *argv0; if (!PyArg_ParseTuple(arg, "s:_ego", &argv0)) return (0); - if (strcmp(QUIS, "") == 0) + if (STRCMP(QUIS, ==, "")) ego(argv0); RETURN_NONE; } @@@ -160,14 -164,14 +164,14 @@@ static void init_random(void if (!Py_HashRandomizationFlag) return; seed = getenv("PYTHONHASHSEED"); - if (!seed || strcmp(seed, "random") == 0) r = GR_WORD(&rand_global); + if (!seed || STRCMP(seed, ==, "random")) r = GR_WORD(&rand_global); else r = strtoul(seed, 0, 0); if (!r) r = 0xe011f220; /* zero doesn't work well */ unihash_setkey(&unihash_global, r); #endif } -void init_base(void) +EXPORT void init_base(void) { PyObject *mod; addmethods(methods); diff --combined debian/changelog index fad1029,0398864..66c14f7 --- a/debian/changelog +++ b/debian/changelog @@@ -1,9 -1,3 +1,9 @@@ +catacomb-python (1.3.99~) experimental; urgency=medium + + * (placeholder for next release) + + -- Mark Wooding Tue, 01 Oct 2019 12:57:58 +0100 + catacomb-python (1.3.0.1) experimental; urgency=medium * Fix required Catacomb version in `setup.py' script. Only affects the @@@ -27,6 -21,12 +27,12 @@@ catacomb-python (1.3.0) experimental; u -- 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 84a43a0,1bde721..7b7400d --- 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 (>= 10), pkg-config, -Build-Depends: debhelper (>= 9), dh-python, pkg-config, ++Build-Depends: debhelper (>= 10), dh-python, pkg-config, python (>= 2.6.6-3~), python-all-dev, - mlib-dev (>= 2.2.2.1), catacomb-dev (>= 2.5.0) + mlib-dev (>= 2.4.99~), catacomb-dev (>= 2.5.0) Standards-Version: 3.8.0 Package: python-catacomb diff --combined ec.c index 6d5e31f,184dc9e..a660eb6 --- a/ec.c +++ b/ec.c @@@ -48,13 -48,13 +48,13 @@@ ec_curve *eccurve_copy(ec_curve *c return (0); a = F_OUT(f, MP_NEW, c->a); b = F_OUT(f, MP_NEW, c->b); - if (strcmp(EC_NAME(c), "prime") == 0) + if (STRCMP(EC_NAME(c), ==, "prime")) c = ec_prime(f, a, b); - else if (strcmp(EC_NAME(c), "primeproj") == 0) + else if (STRCMP(EC_NAME(c), ==, "primeproj")) c = ec_primeproj(f, a, b); - else if (strcmp(EC_NAME(c), "bin") == 0) + else if (STRCMP(EC_NAME(c), ==, "bin")) c = ec_bin(f, a, b); - else if (strcmp(EC_NAME(c), "binproj") == 0) + else if (STRCMP(EC_NAME(c), ==, "binproj")) c = ec_binproj(f, a, b); else c = 0; @@@ -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; static const char *const kwlist[] = { "flags", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|i:ectosp", KWLIST, &f)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:ec2osp", KWLIST, + convuint, &f)) return (0); len = c->f->noctets * 2 + 1; rc = bytestring_pywrap(0, len); @@@ -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; @@@ -514,7 -509,7 +509,7 @@@ static PyObject *ecptnc_pynew(PyTypeObj 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); } @@@ -556,7 -551,7 +551,7 @@@ static PyObject *ecpt_pynew(PyTypeObjec 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); } @@@ -789,10 -784,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 -862,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 }; + 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, + &me, &p, &len, convuint, &f)) return (0); buf_init(&b, p, len); cc = ECCURVE_C(me); @@@ -984,13 -983,13 +983,13 @@@ PyObject *eccurve_pywrap(PyObject *fobj else Py_INCREF(fobj); assert(FIELD_F(fobj) == c->f); - if (strcmp(EC_NAME(c), "prime") == 0) + if (STRCMP(EC_NAME(c), ==, "prime")) ty = ecprimecurve_pytype; - else if (strcmp(EC_NAME(c), "primeproj") == 0) + else if (STRCMP(EC_NAME(c), ==, "primeproj")) ty = ecprimeprojcurve_pytype; - else if (strcmp(EC_NAME(c), "bin") == 0) + else if (STRCMP(EC_NAME(c), ==, "bin")) ty = ecbincurve_pytype; - else if (strcmp(EC_NAME(c), "binproj") == 0) + else if (STRCMP(EC_NAME(c), ==, "binproj")) ty = ecbinprojcurve_pytype; else abort(); @@@ -1067,7 -1066,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 } }; @@@ -1492,7 -1491,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 } }; diff --combined field.c index b78c166,c23f311..417c550 --- a/field.c +++ b/field.c @@@ -74,23 -74,23 +74,23 @@@ PyObject *field_pywrap(field *f { PyTypeObject *ty; - if (strcmp(F_NAME(f), "prime") == 0) ty = primefield_pytype; - else if (strcmp(F_NAME(f), "niceprime") == 0) ty = niceprimefield_pytype; - else if (strcmp(F_NAME(f), "binpoly") == 0) ty = binpolyfield_pytype; - else if (strcmp(F_NAME(f), "binnorm") == 0) ty = binnormfield_pytype; + if (STRCMP(F_NAME(f), ==, "prime")) ty = primefield_pytype; + else if (STRCMP(F_NAME(f), ==, "niceprime")) ty = niceprimefield_pytype; + else if (STRCMP(F_NAME(f), ==, "binpoly")) ty = binpolyfield_pytype; + else if (STRCMP(F_NAME(f), ==, "binnorm")) ty = binnormfield_pytype; else abort(); return (field_dopywrap(ty, f)); } field *field_copy(field *f) { - if (strcmp(F_NAME(f), "prime") == 0) + if (STRCMP(F_NAME(f), ==, "prime")) f = field_prime(f->m); - else if (strcmp(F_NAME(f), "niceprime") == 0) + else if (STRCMP(F_NAME(f), ==, "niceprime")) f = field_niceprime(f->m); - else if (strcmp(F_NAME(f), "binpoly") == 0) + else if (STRCMP(F_NAME(f), ==, "binpoly")) f = field_binpoly(f->m); - else if (strcmp(F_NAME(f), "binnorm") == 0) { + else if (STRCMP(F_NAME(f), ==, "binnorm")) { fctx_binnorm *fc = (fctx_binnorm *)f; f = field_binnorm(f->m, fc->ntop.r[fc->ntop.n - 1]); } else @@@ -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 } }; @@@ -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 } }; @@@ -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 } @@@ -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 diff --combined group.c index c3d2386,3d29070..239456f --- a/group.c +++ b/group.c @@@ -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 } }; 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, &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,7 -119,8 +119,8 @@@ 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; static const char *const kwlist[] = { @@@ -128,6 -131,7 +131,7 @@@ 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, &me, convuint, &pl, convuint, &ql, @@@ -137,8 -141,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 -160,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 } }; 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, &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 -193,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 } }; 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, &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); @@@ -453,7 -461,7 +461,7 @@@ PyTypeObject *primegroup_pytype, *bingr group *group_copy(group *g) { - if (strcmp(G_NAME(g), "prime") == 0) { + if (STRCMP(G_NAME(g), ==, "prime")) { gctx_prime *gc = (gctx_prime *)g; gprime_param gp; gp.g = G_TOINT(g, MP_NEW, g->g); @@@ -461,7 -469,7 +469,7 @@@ gp.q = gc->g.r; g = group_prime(&gp); MP_DROP(gp.g); - } else if (strcmp(G_NAME(g), "bin") == 0) { + } else if (STRCMP(G_NAME(g), ==, "bin")) { gctx_bin *gc = (gctx_bin *)g; gbin_param gb; gb.g = G_TOINT(g, MP_NEW, g->g); @@@ -469,7 -477,7 +477,7 @@@ gb.q = gc->g.r; g = group_binary(&gb); MP_DROP(gb.g); - } else if (strcmp(G_NAME(g), "ec") == 0) { + } else if (STRCMP(G_NAME(g), ==, "ec")) { gctx_ec *gc = (gctx_ec *)g; ec_info ei; if ((ei.c = eccurve_copy(gc->ei.c)) == 0) @@@ -552,9 -560,9 +560,9 @@@ PyObject *group_pywrap(group *g { PyTypeObject *ty; - if (strcmp(G_NAME(g), "prime") == 0) ty = primegroup_pytype; - else if (strcmp(G_NAME(g), "bin") == 0) ty = bingroup_pytype; - else if (strcmp(G_NAME(g), "ec") == 0) ty = ecgroup_pytype; + if (STRCMP(G_NAME(g), ==, "prime")) ty = primegroup_pytype; + else if (STRCMP(G_NAME(g), ==, "bin")) ty = bingroup_pytype; + else if (STRCMP(G_NAME(g), ==, "ec")) ty = ecgroup_pytype; else abort(); return (group_dopywrap(ty, g)); } @@@ -732,7 -740,7 +740,7 @@@ static PyObject *gemeth_toec(PyObject * if (!PyType_Check(cty) || !PyType_IsSubtype(cty, ecpt_pytype)) TYERR("want subtype of catacomb.ECPt"); Py_INCREF((PyObject *)cty); - } else if (strcmp(G_NAME(g), "ec") == 0) { + } else if (STRCMP(G_NAME(g), ==, "ec")) { c = eccurve_copy(((gctx_ec *)g)->ei.c); cty = (PyTypeObject *)eccurve_pywrap(0, c); } else { @@@ -966,7 -974,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 -1089,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 } }; @@@ -1379,16 -1387,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 rand.c index 964a6a2,b662fd5..37ab5e4 --- a/rand.c +++ b/rand.c @@@ -27,9 -27,7 +27,9 @@@ /*----- Header files ------------------------------------------------------*/ #include "catacomb-python.h" +PUBLIC_SYMBOLS; #include "algorithms.h" +PRIVATE_SYMBOLS; /*----- Main code ---------------------------------------------------------*/ @@@ -56,14 -54,14 +56,14 @@@ PyObject *grand_pywrap(grand *r, unsign PyTypeObject *ty = grand_pytype; PyObject *ob; - if (strcmp(r->ops->name, "rand") == 0) ty = truerand_pytype; - else if (strcmp(r->ops->name, "lcrand") == 0) ty = lcrand_pytype; - else if (strcmp(r->ops->name, "fibrand") == 0) ty = fibrand_pytype; - else if (strcmp(r->ops->name, "dsarand") == 0) ty = dsarand_pytype; - else if (strcmp(r->ops->name, "bbs") == 0) ty = bbs_pytype; - else if (strcmp(r->ops->name, "sslprf") == 0) ty = sslprf_pytype; - else if (strcmp(r->ops->name, "tlsdx") == 0) ty = tlsdx_pytype; - else if (strcmp(r->ops->name, "tlsprf") == 0) ty = tlsprf_pytype; + if (STRCMP(r->ops->name, ==, "rand")) ty = truerand_pytype; + else if (STRCMP(r->ops->name, ==, "lcrand")) ty = lcrand_pytype; + else if (STRCMP(r->ops->name, ==, "fibrand")) ty = fibrand_pytype; + else if (STRCMP(r->ops->name, ==, "dsarand")) ty = dsarand_pytype; + else if (STRCMP(r->ops->name, ==, "bbs")) ty = bbs_pytype; + else if (STRCMP(r->ops->name, ==, "sslprf")) ty = sslprf_pytype; + else if (STRCMP(r->ops->name, ==, "tlsdx")) ty = tlsdx_pytype; + else if (STRCMP(r->ops->name, ==, "tlsprf")) ty = tlsprf_pytype; else if ((ob = PyDict_GetItemString(gccrands_dict, r->ops->name)) != 0) ty = (PyTypeObject *)ob; return (grand_dopywrap(ty, r, f)); @@@ -508,7 -506,7 +508,7 @@@ static PyObject *truerand_pynew(PyTypeO 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; r = rand_create(); r->ops->misc(r, RAND_NOISESRC, &noise_source); r->ops->misc(r, RAND_SEED, 160); @@@ -1269,7 -1267,7 +1269,7 @@@ 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; end: mp_drop(x); return (rc); @@@ -1385,19 -1383,21 +1385,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; 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, &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; @@@ -1483,7 -1483,7 +1485,7 @@@ static PyTypeObject bbspriv_pytype_ske Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "BBSPriv(..., seed = 2]): Blum-Blum-Shub, with private key.\n\ + "BBSPriv(..., [seed = 2]): Blum-Blum-Shub, with private key.\n\ Keywords: n, p, q; must provide at least two", 0, /* @tp_traverse@ */ @@@ -1512,7 -1512,8 +1514,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 69bf393,d778177..8ac72ab --- a/setup.py +++ b/setup.py @@@ -4,7 -4,7 +4,7 @@@ import distutils.core as D import mdwsetup as MS MS.pkg_config('catacomb', '2.5.0') -MS.pkg_config('mLib', '2.2.2.1') +MS.pkg_config('mLib', '2.4.99~') cat = DC.Extension('catacomb._base', ['catacomb.c', 'bytestring.c', 'buffer.c', @@@ -26,4 -26,9 +26,9 @@@ MS.setup(name = 'catacomb-python' 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])