X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/catacomb-python/blobdiff_plain/989638174888e6f73bcc67008469da25bb393d57..de3b64326f850d72b0cbbf269e9fa98dd4c093eb:/rand.c diff --git a/rand.c b/rand.c index 3bcd0a9..4fcb155 100644 --- a/rand.c +++ b/rand.c @@ -90,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); @@ -112,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); @@ -256,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)") @@ -270,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@ */ @@ -327,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@ */ @@ -384,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@ */ @@ -529,7 +530,7 @@ static PyGetSetDef truerand_pygetset[] = { 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@ */ @@ -581,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 }; @@ -639,6 +645,25 @@ end: 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); @@ -651,11 +676,10 @@ static PyObject *gccrand_pywrap(const gccrand_info *info) 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 - g->ty.ht_type.tp_new = gcrand_pynew; - PyType_Ready(&g->ty.ht_type); + 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); } @@ -674,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@ */ @@ -722,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@ */ @@ -823,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@ */ @@ -871,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@ */ @@ -919,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@ */ @@ -999,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@ */ @@ -1130,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@ */ @@ -1288,7 +1312,7 @@ static PyGetSetDef bbspriv_pygetset[] = { 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@ */