chiark / gitweb /
catacomb-python.h: Don't inhibit 64-bit type detection any more.
[catacomb-python] / rand.c
diff --git a/rand.c b/rand.c
index 4b40a750580212e21230f55a3e4da897db373c19..4fcb15502b4a62554bd54f72f88816eff7f1c16a 100644 (file)
--- 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.
  *
  * 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@ */