chiark / gitweb /
debian/: Use `dh_python2' for packaging.
[catacomb-python] / rand.c
diff --git a/rand.c b/rand.c
index 784fd9312aa9c8311dc201c9014017d1f655d114..9da7f663cccc4b0a0d81faebbf82a92e8ac38923 100644 (file)
--- a/rand.c
+++ b/rand.c
@@ -173,7 +173,7 @@ end:
 static PyObject *grmeth_seedblock(PyObject *me, PyObject *arg)
 {
   char *p;
-  int n;
+  Py_ssize_t n;
   grand *r = GRAND_R(me);
   if (!PyArg_ParseTuple(arg, "s#:seedblock", &p, &n) ||
       checkop(r, GRAND_SEEDBLOCK, "seedblock"))
@@ -219,7 +219,7 @@ static PyObject *grmeth_mask(PyObject *me, PyObject *arg)
 {
   grand *r = GRAND_R(me);
   char *p, *q;
-  int sz;
+  Py_ssize_t sz;
   PyObject *rc;
 
   if (!PyArg_ParseTuple(arg, "s#:mask", &p, &sz)) return (0);
@@ -351,7 +351,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@ */
@@ -408,7 +408,7 @@ static PyTypeObject fibrand_pytype_skel = {
     Py_TPFLAGS_BASETYPE,
 
   /* @tp_doc@ */
-"Fibonacci generator.",
+"FibRand([seed = 0]): Fibonacci generator.",
 
   0,                                   /* @tp_traverse@ */
   0,                                   /* @tp_clear@ */
@@ -452,7 +452,7 @@ static PyObject *trmeth_stretch(PyObject *me, PyObject *arg)
 static PyObject *trmeth_add(PyObject *me, PyObject *arg)
 {
   grand *r = GRAND_R(me);
-  char *p; int n; unsigned goodbits;
+  char *p; Py_ssize_t n; unsigned goodbits;
   if (!PyArg_ParseTuple(arg, "s#O&:add", &p, &n, convuint, &goodbits))
     return (0);
   r->ops->misc(r, RAND_ADD, p, (size_t)n, goodbits);
@@ -462,7 +462,7 @@ static PyObject *trmeth_add(PyObject *me, PyObject *arg)
 static PyObject *trmeth_key(PyObject *me, PyObject *arg)
 {
   grand *r = GRAND_R(me);
-  char *p; int n;
+  char *p; Py_ssize_t n;
   if (!PyArg_ParseTuple(arg, "s#:key", &p, &n)) return (0);
   r->ops->misc(r, RAND_KEY, p, (size_t)n);
   RETURN_ME;
@@ -553,7 +553,7 @@ static PyTypeObject truerand_pytype_skel = {
     Py_TPFLAGS_BASETYPE,
 
   /* @tp_doc@ */
-"True random number source.",
+"TrueRand(): true random number source.",
 
   0,                                   /* @tp_traverse@ */
   0,                                   /* @tp_clear@ */
@@ -583,6 +583,12 @@ static PyTypeObject *gccrand_pytype, *gcrand_pytype, *gclatinrand_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 grand *gcshakerand_func(const void *, size_t,
+                               const void *, size_t,
+                               const void *, size_t);
+typedef grand *gcshafuncrand_func(const void *, size_t,
+                                 const void *, size_t);
+typedef grand *gckmacrand_func(const void *, size_t, const void *, size_t);
 typedef struct gccrand_info {
   const char *name;
   const octet *keysz;
@@ -591,9 +597,15 @@ typedef struct gccrand_info {
   gcrand_func *func;
 } gccrand_info;
 
-#define RNGF_INT 1u
-#define RNGF_NONCE 2u
-#define RNGF_LATIN 4u
+#define RNGF_MASK 255u
+
+enum {
+  RNG_PLAIN = 0,
+  RNG_SEAL,
+  RNG_LATIN,
+  RNG_SHAKE,
+  RNG_KMAC
+};
 
 typedef struct gccrand_pyobj {
   PyHeapTypeObject ty;
@@ -617,7 +629,7 @@ static PyObject *gcrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
   const gccrand_info *info = GCCRAND_INFO(ty);
   static char *kwlist[] = { "key", 0 };
   char *k;
-  int n;
+  Py_ssize_t n;
 
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &n))
     goto end;
@@ -633,7 +645,7 @@ static PyObject *gcirand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
   uint32 i = 0;
   static char *kwlist[] = { "key", "i", 0 };
   char *k;
-  int n;
+  Py_ssize_t n;
 
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&:new", kwlist,
                                   &k, &n, convu32, &i))
@@ -651,7 +663,7 @@ 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;
+  Py_ssize_t ksz, nsz;
 
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#:new", kwlist,
                                   &k, &ksz, &n, &nsz))
@@ -665,22 +677,56 @@ end:
   return (0);
 }
 
+static PyObject *gcshakyrand_pynew(PyTypeObject *ty,
+                                  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 };
+  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,
+                                      &k, &ksz, &f, &fsz, &p, &psz)
+       : !PyArg_ParseTupleAndKeywords(arg, kw, "s#|s#:new", kwlist_func,
+                                      &k, &ksz, &p, &psz))
+    goto end;
+  if (keysz(ksz, info->keysz) != ksz) VALERR("bad key length");
+  return (grand_dopywrap(ty,
+                        (info->f&RNGF_MASK) == RNG_SHAKE
+                          ? ((gcshakerand_func *)info->func)(f, fsz,
+                                                             p, psz,
+                                                             k, ksz)
+                          : ((gcshafuncrand_func *)info->func)(p, psz,
+                                                               k, ksz),
+                        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.ht_type.tp_basicsize = sizeof(grand_pyobj);
-  g->ty.ht_type.tp_base =
-    (info->f & RNGF_LATIN) ? gclatinrand_pytype : gcrand_pytype;
+  switch (info->f&RNGF_MASK) {
+    case RNG_LATIN: g->ty.ht_type.tp_base = gclatinrand_pytype; break;
+    default: g->ty.ht_type.tp_base = gcrand_pytype; break;
+  }
   Py_INCREF(g->ty.ht_type.tp_base);
   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;
+  switch (info->f&RNGF_MASK) {
+    case RNG_LATIN: g->ty.ht_type.tp_new = gcnrand_pynew; break;
+    case RNG_SEAL: g->ty.ht_type.tp_new = gcirand_pynew; break;
+    case RNG_SHAKE: case RNG_KMAC:
+      g->ty.ht_type.tp_new = gcshakyrand_pynew; break;
+    default: g->ty.ht_type.tp_new = gcrand_pynew; break;
+  }
   typeready(&g->ty.ht_type);
   return ((PyObject *)g);
 }
@@ -950,7 +996,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@ */
@@ -998,7 +1045,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@ */
@@ -1046,7 +1094,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@ */
@@ -1126,7 +1175,7 @@ static PyTypeObject dsarand_pytype_skel = {
     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@ */
@@ -1204,7 +1253,8 @@ static PyObject *bbsget_x(PyObject *me, void *hunoz)
 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__");
-  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);
 }
 
@@ -1257,7 +1307,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@ */
@@ -1415,7 +1465,8 @@ static PyTypeObject bbspriv_pytype_skel = {
     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@ */