chiark / gitweb /
rand: Generators based on symmetric algorithms; fixing
authorMark Wooding <mdw@distorted.org.uk>
Sat, 28 Jan 2006 19:09:57 +0000 (19:09 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 28 Jan 2006 19:09:57 +0000 (19:09 +0000)
  * Include support for the various generators based on symmetric
    algorithms: i.e., counter and OFB modes for block ciphers, and SEAL
    and RC4.

  * Recognise, and return correct subclass instance for, TLS and SSL
    generators, and the symmetric crypto-based generators.

rand.c

diff --git a/rand.c b/rand.c
index d779846fa7d52d265dc282206e70d06c9f71cfe8..4b40a750580212e21230f55a3e4da897db373c19 100644 (file)
--- a/rand.c
+++ b/rand.c
@@ -29,6 +29,7 @@
 /*----- Header files ------------------------------------------------------*/
 
 #include "catacomb-python.h"
+#include "algorithms.h"
 
 /*----- Main code ---------------------------------------------------------*/
 
@@ -38,6 +39,8 @@ PyTypeObject *dsarand_pytype, *bbs_pytype, *bbspriv_pytype;
 PyTypeObject *sslprf_pytype, *tlsdx_pytype, *tlsprf_pytype;
 PyObject *rand_pyobj;
 
+static PyObject *gccrands_dict;
+
 static PyObject *grand_dopywrap(PyTypeObject *ty, grand *r, unsigned f)
 {
   grand_pyobj *g;
@@ -51,12 +54,18 @@ static PyObject *grand_dopywrap(PyTypeObject *ty, grand *r, unsigned f)
 PyObject *grand_pywrap(grand *r, unsigned f)
 {
   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;
+  else if ((ob = PyDict_GetItemString(gccrands_dict, r->ops->name)) != 0)
+    ty = (PyTypeObject *)ob;
   return (grand_dopywrap(ty, r, f));
 }
 
@@ -441,12 +450,22 @@ static PyObject *trmeth_stretch(PyObject *me, PyObject *arg)
   RETURN_ME;
 }
 
+static PyObject *trmeth_add(PyObject *me, PyObject *arg)
+{
+  grand *r = GRAND_R(me);
+  char *p; int 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);
+  RETURN_ME;
+}
+
 static PyObject *trmeth_key(PyObject *me, PyObject *arg)
 {
   grand *r = GRAND_R(me);
   char *p; int n;
   if (!PyArg_ParseTuple(arg, "s#:key", &p, &n)) return (0);
-  r->ops->misc(r, RAND_KEY, p, n);
+  r->ops->misc(r, RAND_KEY, p, (size_t)n);
   RETURN_ME;
 }
 
@@ -491,6 +510,7 @@ static PyMethodDef truerand_pymethods[] = {
   METH (stretch,       "R.stretch()")
   METH (key,           "R.key(BYTES)")
   METH (seed,          "R.seed(NBITS)")
+  METH (add,           "R.add(BYTES, GOODBITS")
   METH (timer,         "R.timer()")
 #undef METHNAME
   { 0 }
@@ -557,6 +577,199 @@ static PyTypeObject truerand_pytype_skel = {
   0                                    /* @tp_is_gc@ */
 };
 
+/*----- Generators from symmetric encryption algorithms -------------------*/
+
+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 struct gccrand_info {
+  const char *name;
+  const octet *keysz;
+  unsigned f;
+  gcrand_func *func;
+} gccrand_info;
+
+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)                                        \
+  static const gccrand_info func##_info =                              \
+    { name, ksz, f, (gcrand_func *)func };
+RNGS(GCCRAND_DEF)
+
+static const gccrand_info *const gcrandtab[] = {
+#define GCCRAND_ENTRY(name, ksz, func, f) &func##_info,
+  RNGS(GCCRAND_ENTRY)
+  0
+};
+
+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;
+
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &n))
+    goto end;
+  if (keysz(n, info->keysz) != n) VALERR("bad key length");
+  return (grand_dopywrap(ty, info->func(k, n), f_freeme));
+end:
+  return (0);  
+}
+
+static PyObject *gcirand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
+{
+  const gccrand_info *info = GCCRAND_INFO(ty);
+  uint32 i = 0;
+  static char *kwlist[] = { "key", "i", 0 };
+  char *k;
+  int n;
+
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&:new", kwlist,
+                                  &k, &n, convu32, &i))
+    goto end;
+  if (keysz(n, info->keysz) != n) VALERR("bad key length");
+  return (grand_dopywrap(ty,
+                        ((gcirand_func *)info->func)(k, n, i),
+                        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;
+  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);
+  return ((PyObject *)g);
+}
+
+static PyObject *gccrget_name(PyObject *me, void *hunoz)
+  { return (PyString_FromString(GCCRAND_INFO(me)->name)); }
+static PyObject *gccrget_keysz(PyObject *me, void *hunoz)
+  { return (keysz_pywrap(GCCRAND_INFO(me)->keysz)); }
+
+static PyGetSetDef gccrand_pygetset[] = {
+#define GETSETNAME(op, name) gccr##op##_##name
+  GET  (keysz,                 "CR.keysz -> acceptable key sizes")
+  GET  (name,                  "CR.name -> name of this kind of generator")
+#undef GETSETNAME
+  { 0 }
+};
+
+static PyTypeObject gccrand_pytype_skel = {
+  PyObject_HEAD_INIT(0) 0,             /* Header */
+  "catacomb.GCCRand",                  /* @tp_name@ */
+  sizeof(gccrand_pyobj),               /* @tp_basicsize@ */
+  0,                                   /* @tp_itemsize@ */
+
+  0,                                   /* @tp_dealloc@ */
+  0,                                   /* @tp_print@ */
+  0,                                   /* @tp_getattr@ */
+  0,                                   /* @tp_setattr@ */
+  0,                                   /* @tp_compare@ */
+  0,                                   /* @tp_repr@ */
+  0,                                   /* @tp_as_number@ */
+  0,                                   /* @tp_as_sequence@ */
+  0,                                   /* @tp_as_mapping@ */
+  0,                                   /* @tp_hash@ */
+  0,                                   /* @tp_call@ */
+  0,                                   /* @tp_str@ */
+  0,                                   /* @tp_getattro@ */
+  0,                                   /* @tp_setattro@ */
+  0,                                   /* @tp_as_buffer@ */
+  Py_TPFLAGS_DEFAULT |                 /* @tp_flags@ */
+    Py_TPFLAGS_BASETYPE,
+
+  /* @tp_doc@ */
+"Metaclass for symmetric crypto-based generators.",
+
+  0,                                   /* @tp_traverse@ */
+  0,                                   /* @tp_clear@ */
+  0,                                   /* @tp_richcompare@ */
+  0,                                   /* @tp_weaklistoffset@ */
+  0,                                   /* @tp_iter@ */
+  0,                                   /* @tp_iternext@ */
+  0,                                   /* @tp_methods@ */
+  0,                                   /* @tp_members@ */
+  gccrand_pygetset,                    /* @tp_getset@ */
+  0,                                   /* @tp_base@ */
+  0,                                   /* @tp_dict@ */
+  0,                                   /* @tp_descr_get@ */
+  0,                                   /* @tp_descr_set@ */
+  0,                                   /* @tp_dictoffset@ */
+  0,                                   /* @tp_init@ */
+  PyType_GenericAlloc,                 /* @tp_alloc@ */
+  abstract_pynew,                      /* @tp_new@ */
+  0,                                   /* @tp_free@ */
+  0                                    /* @tp_is_gc@ */
+};
+
+static PyTypeObject gcrand_pytype_skel = {
+  PyObject_HEAD_INIT(0) 0,             /* Header */
+  "catacomb.GCRand",                   /* @tp_name@ */
+  sizeof(grand_pyobj),                 /* @tp_basicsize@ */
+  0,                                   /* @tp_itemsize@ */
+
+  grand_pydealloc,                     /* @tp_dealloc@ */
+  0,                                   /* @tp_print@ */
+  0,                                   /* @tp_getattr@ */
+  0,                                   /* @tp_setattr@ */
+  0,                                   /* @tp_compare@ */
+  0,                                   /* @tp_repr@ */
+  0,                                   /* @tp_as_number@ */
+  0,                                   /* @tp_as_sequence@ */
+  0,                                   /* @tp_as_mapping@ */
+  0,                                   /* @tp_hash@ */
+  0,                                   /* @tp_call@ */
+  0,                                   /* @tp_str@ */
+  0,                                   /* @tp_getattro@ */
+  0,                                   /* @tp_setattro@ */
+  0,                                   /* @tp_as_buffer@ */
+  Py_TPFLAGS_DEFAULT |                 /* @tp_flags@ */
+    Py_TPFLAGS_BASETYPE,
+
+  /* @tp_doc@ */
+"Abstract base class for symmetric crypto-based generators.",
+
+  0,                                   /* @tp_traverse@ */
+  0,                                   /* @tp_clear@ */
+  0,                                   /* @tp_richcompare@ */
+  0,                                   /* @tp_weaklistoffset@ */
+  0,                                   /* @tp_iter@ */
+  0,                                   /* @tp_iternext@ */
+  0,                                   /* @tp_methods@ */
+  0,                                   /* @tp_members@ */
+  0,                                   /* @tp_getset@ */
+  0,                                   /* @tp_base@ */
+  0,                                   /* @tp_dict@ */
+  0,                                   /* @tp_descr_get@ */
+  0,                                   /* @tp_descr_set@ */
+  0,                                   /* @tp_dictoffset@ */
+  0,                                   /* @tp_init@ */
+  PyType_GenericAlloc,                 /* @tp_alloc@ */
+  abstract_pynew,                      /* @tp_new@ */
+  0,                                   /* @tp_free@ */
+  0                                    /* @tp_is_gc@ */
+};
+
 /*----- SSL and TLS generators --------------------------------------------*/
 
 static PyObject *sslprf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
@@ -1145,11 +1358,16 @@ void rand_pyinit(void)
   INITTYPE(sslprf, grand);
   INITTYPE(tlsdx, grand);
   INITTYPE(tlsprf, grand);
+  INITTYPE(gccrand, type);
+  INITTYPE(gcrand, grand);
   rand_noisesrc(RAND_GLOBAL, &noise_source);
   rand_seed(RAND_GLOBAL, 160);
   addmethods(methods);
 }
 
+#define gccrand gccrand_info
+GEN(gccrands, crand)
+
 void rand_pyinsert(PyObject *mod)
 {
   INSERT("GRand", grand_pytype);
@@ -1162,7 +1380,11 @@ void rand_pyinsert(PyObject *mod)
   INSERT("DSARand", dsarand_pytype);
   INSERT("BlumBlumShub", bbs_pytype);
   INSERT("BBSPriv", bbspriv_pytype);
+  INSERT("GCCRand", gccrand_pytype);
+  INSERT("GCRand", gcrand_pytype);
   rand_pyobj = grand_pywrap(&rand_global, 0); Py_INCREF(rand_pyobj);
+  gccrands_dict = gccrands(); Py_INCREF(gccrands_dict);
+  INSERT("gccrands", gccrands_dict);
   INSERT("rand", rand_pyobj);
 }