X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/850a4b483975ef7081ea7fabfa2e90f99a1844a9..9f9ea9ea4df181faa5fa7acadf3a022b25234f3e:/rand.c diff --git a/rand.c b/rand.c index 4b40a75..4fcb155 100644 --- a/rand.c +++ b/rand.c @@ -1,13 +1,11 @@ /* -*-c-*- * - * $Id$ - * * Random-number generators * * (c) 2004 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of the Python interface to Catacomb. * @@ -15,12 +13,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * Catacomb/Python is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with Catacomb/Python; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -80,7 +78,7 @@ static PyObject *grmeth_byte(PyObject *me, PyObject *arg) static PyObject *grmeth_word(PyObject *me, PyObject *arg) { if (!PyArg_ParseTuple(arg, ":word")) return (0); - return (getu32(grand_word(GRAND_R(me)))); + return (getulong(grand_word(GRAND_R(me)))); } static PyObject *grmeth_range(PyObject *me, PyObject *arg) @@ -92,20 +90,20 @@ static PyObject *grmeth_range(PyObject *me, PyObject *arg) if (!PyArg_ParseTuple(arg, "O:range", &m)) return (0); if (PyInt_Check(m)) { long mm = PyInt_AS_LONG(m); - if (mm < 0) - goto negative; + if (mm <= 0) + goto notpos; if (mm <= 0xffffffff) return (PyInt_FromLong(grand_range(GRAND_R(me), mm))); } if ((x = getmp(m)) == 0) goto end; - if (MP_NEGP(x)) - goto negative; + if (!MP_POSP(x)) + goto notpos; y = mprand_range(MP_NEW, x, GRAND_R(me), 0); MP_DROP(x); return (mp_pywrap(y)); -negative: - TYERR("range must be nonnegative"); +notpos: + VALERR("range must be strictly positive"); end: if (x) MP_DROP(x); return (0); @@ -114,12 +112,13 @@ end: static PyObject *grmeth_mp(PyObject *me, PyObject *arg, PyObject *kw) { size_t l; - mpw o; + mpw o = 0; char *kwlist[] = { "bits", "or", 0 }; if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:mp", kwlist, convszt, &l, convmpw, &o)) goto end; + if (l < MPW_BITS && (o >> l)) VALERR("or mask too large"); return (mp_pywrap(mprand(MP_NEW, l, GRAND_R(me), o))); end: return (0); @@ -258,7 +257,7 @@ static PyMethodDef grand_pymethods[] = { METH (byte, "R.byte() -> BYTE") METH (word, "R.word() -> WORD") METH (block, "R.block(N) -> STRING") - KWMETH(mp, "R.mp(bits, or = 0) -> MP") + KWMETH(mp, "R.mp(bits, [or = 0]) -> MP") METH (range, "R.range(MAX) -> INT") METH (mask, "R.mask(STR) -> STR") METH (seedint, "R.seedint(I)") @@ -272,7 +271,7 @@ static PyMethodDef grand_pymethods[] = { static PyTypeObject grand_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.GRand", /* @tp_name@ */ + "GRand", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -329,7 +328,7 @@ static PyObject *lcrand_pynew(PyTypeObject *me, PyObject *arg, PyObject *kw) static PyTypeObject lcrand_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.LCRand", /* @tp_name@ */ + "LCRand", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -386,7 +385,7 @@ static PyObject *fibrand_pynew(PyTypeObject *me, PyObject *arg, PyObject *kw) static PyTypeObject fibrand_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.FibRand", /* @tp_name@ */ + "FibRand", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -524,14 +523,14 @@ static PyObject *trget_goodbits(PyObject *me, void *hunoz) static PyGetSetDef truerand_pygetset[] = { #define GETSETNAME(op, name) tr##op##_##name - GET (goodbits, "R.goodbits -> good bits of entropy remaining") + GET (goodbits, "R.goodbits -> good bits of entropy remaining") #undef GETSETNAME { 0 } }; static PyTypeObject truerand_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.TrueRand", /* @tp_name@ */ + "TrueRand", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -583,26 +582,31 @@ static PyTypeObject *gccrand_pytype, *gcrand_pytype; typedef grand *gcrand_func(const void *, size_t sz); typedef grand *gcirand_func(const void *, size_t sz, uint32); +typedef grand *gcnrand_func(const void *, size_t sz, const void *); typedef struct gccrand_info { const char *name; const octet *keysz; unsigned f; + size_t noncesz; gcrand_func *func; } gccrand_info; +#define RNGF_INT 1u +#define RNGF_NONCE 2u + typedef struct gccrand_pyobj { PyHeapTypeObject ty; const gccrand_info *info; } gccrand_pyobj; #define GCCRAND_INFO(o) (((gccrand_pyobj *)(o))->info) -#define GCCRAND_DEF(name, ksz, func, f) \ +#define GCCRAND_DEF(name, ksz, func, f, nsz) \ static const gccrand_info func##_info = \ - { name, ksz, f, (gcrand_func *)func }; + { name, ksz, f, nsz, (gcrand_func *)func }; RNGS(GCCRAND_DEF) static const gccrand_info *const gcrandtab[] = { -#define GCCRAND_ENTRY(name, ksz, func, f) &func##_info, +#define GCCRAND_ENTRY(name, ksz, func, f, nsz) &func##_info, RNGS(GCCRAND_ENTRY) 0 }; @@ -619,7 +623,7 @@ static PyObject *gcrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) if (keysz(n, info->keysz) != n) VALERR("bad key length"); return (grand_dopywrap(ty, info->func(k, n), f_freeme)); end: - return (0); + return (0); } static PyObject *gcirand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) @@ -638,26 +642,44 @@ static PyObject *gcirand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) ((gcirand_func *)info->func)(k, n, i), f_freeme)); end: - return (0); + return (0); +} + +static PyObject *gcnrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) +{ + const gccrand_info *info = GCCRAND_INFO(ty); + static char *kwlist[] = { "key", "nonce", 0 }; + char *k, *n; + int ksz, nsz; + + 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"); + if (nsz != info->noncesz) VALERR("bad nonce length"); + return (grand_dopywrap(ty, + ((gcnrand_func *)info->func)(k, ksz, n), + f_freeme)); +end: + return (0); } static PyObject *gccrand_pywrap(const gccrand_info *info) { gccrand_pyobj *g = newtype(gccrand_pytype, 0, info->name); g->info = info; - g->ty.type.tp_basicsize = sizeof(grand_pyobj); - g->ty.type.tp_base = gcrand_pytype; + g->ty.ht_type.tp_basicsize = sizeof(grand_pyobj); + g->ty.ht_type.tp_base = gcrand_pytype; Py_INCREF(gcrand_pytype); - g->ty.type.tp_flags = (Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HEAPTYPE); - g->ty.type.tp_alloc = PyType_GenericAlloc; - g->ty.type.tp_free = 0; - if (info->f & RNGF_INT) - g->ty.type.tp_new = gcirand_pynew; - else - g->ty.type.tp_new = gcrand_pynew; - PyType_Ready(&g->ty.type); + g->ty.ht_type.tp_flags = (Py_TPFLAGS_DEFAULT | + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HEAPTYPE); + g->ty.ht_type.tp_alloc = PyType_GenericAlloc; + g->ty.ht_type.tp_free = 0; + if (info->f & RNGF_INT) g->ty.ht_type.tp_new = gcirand_pynew; + else if (info->f & RNGF_NONCE) g->ty.ht_type.tp_new = gcnrand_pynew; + else g->ty.ht_type.tp_new = gcrand_pynew; + typeready(&g->ty.ht_type); return ((PyObject *)g); } @@ -676,7 +698,7 @@ static PyGetSetDef gccrand_pygetset[] = { static PyTypeObject gccrand_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.GCCRand", /* @tp_name@ */ + "GCCRand", /* @tp_name@ */ sizeof(gccrand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -724,7 +746,7 @@ static PyTypeObject gccrand_pytype_skel = { static PyTypeObject gcrand_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.GCRand", /* @tp_name@ */ + "GCRand", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -825,7 +847,7 @@ end: static PyTypeObject sslprf_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.SSLRand", /* @tp_name@ */ + "SSLRand", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -873,7 +895,7 @@ static PyTypeObject sslprf_pytype_skel = { static PyTypeObject tlsdx_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.TLSDataExpansion", /* @tp_name@ */ + "TLSDataExpansion", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -921,7 +943,7 @@ static PyTypeObject tlsdx_pytype_skel = { static PyTypeObject tlsprf_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.TLSPRF", /* @tp_name@ */ + "TLSPRF", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -980,7 +1002,7 @@ static PyObject *dsarand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) goto end; rc = grand_dopywrap(ty, dsarand_create(p, sz), f_freeme); end: - return (0); + return (rc); } static PyObject *drget_seed(PyObject *me, void *hunoz) @@ -1001,7 +1023,7 @@ static PyGetSetDef dsarand_pygetset[] = { static PyTypeObject dsarand_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.DSARand", /* @tp_name@ */ + "DSARand", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1076,7 +1098,7 @@ static PyObject *bbsmeth_bits(PyObject *me, PyObject *arg) grand *r = GRAND_R(me); unsigned n; uint32 w; if (!PyArg_ParseTuple(arg, "O&:bits", convuint, &n)) goto end; if (n > 32) VALERR("can't get more than 32 bits"); - r->ops->misc(r, BBS_BITS, n, &w); return (getu32(w)); + r->ops->misc(r, BBS_BITS, n, &w); return (getulong(w)); end: return (0); } @@ -1132,7 +1154,7 @@ static PyGetSetDef bbs_pygetset[] = { static PyTypeObject bbs_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.BlumBlumShub", /* @tp_name@ */ + "BlumBlumShub", /* @tp_name@ */ sizeof(grand_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -1236,7 +1258,7 @@ static PyObject *meth__BBSPriv_generate(PyObject *me, rc->bp.n = MP_COPY(bp.n); end: mp_drop(bp.p); mp_drop(bp.q); mp_drop(bp.n); mp_drop(x); - return ((PyObject *)rc); + return ((PyObject *)rc); } static void bbspriv_pydealloc(PyObject *me) @@ -1281,16 +1303,16 @@ static PyMethodDef bbspriv_pymethods[] = { static PyGetSetDef bbspriv_pygetset[] = { #define GETSETNAME(op, name) bp##op##_##name - GET (n, "R.n -> Blum modulus") - GET (p, "R.p -> one of the factors of the modulus") - GET (q, "R.q -> one of the factors of the modulus") + GET (n, "R.n -> Blum modulus") + GET (p, "R.p -> one of the factors of the modulus") + GET (q, "R.q -> one of the factors of the modulus") #undef GETSETNAME { 0 } }; static PyTypeObject bbspriv_pytype_skel = { PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.BBSPriv", /* @tp_name@ */ + "BBSPriv", /* @tp_name@ */ sizeof(bbspriv_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */