chiark / gitweb /
algorithms.c: Add support for Poly1305.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 26 May 2016 08:26:09 +0000 (09:26 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 7 Apr 2017 10:46:51 +0000 (11:46 +0100)
algorithms.c
catacomb-python.h
debian/control
setup.py

index b2eff8b36d5402a1c884af1b93d69cca7bc37681..4561b9ae34e9b5d503fbac233d9993dd3474b3bd 100644 (file)
@@ -1185,6 +1185,357 @@ static PyTypeObject gmhash_pytype_skel = {
   0                                    /* @tp_is_gc@ */
 };
 
+/*----- Special snowflake for Poly1305 ------------------------------------*/
+
+PyTypeObject *poly1305cls_pytype, *poly1305key_pytype, *poly1305hash_pytype;
+
+typedef struct poly1305key_pyobj {
+  PyHeapTypeObject ty;
+  poly1305_key k;
+} poly1305key_pyobj;
+
+typedef struct poly1305hash_pyobj {
+  PyObject_HEAD
+  unsigned f;
+#define f_mask 1u
+  poly1305_ctx ctx;
+} poly1305hash_pyobj;
+
+#define P1305_F(o) (((poly1305hash_pyobj *)(o))->f)
+#define P1305_CTX(o) (&((poly1305hash_pyobj *)(o))->ctx)
+CONVFUNC(poly1305hash, poly1305_ctx *, P1305_CTX)
+
+static PyObject *poly1305hash_pynew(PyTypeObject *ty,
+                                   PyObject *arg, PyObject *kw)
+{
+  char *kwlist[] = { "mask", 0 };
+  poly1305key_pyobj *pk = (poly1305key_pyobj *)ty;
+  poly1305hash_pyobj *ph;
+  char *m = 0;
+  int sz;
+
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "|s#:new", kwlist, &m, &sz))
+    return (0);
+  if (m && sz != POLY1305_MASKSZ) VALERR("bad mask length");
+  ph = PyObject_NEW(poly1305hash_pyobj, ty);
+  ph->f = 0;
+  if (m) ph->f |= f_mask;
+  poly1305_macinit(&ph->ctx, &pk->k, m);
+  Py_INCREF(ty);
+  return ((PyObject *)ph);
+end:
+  return (0);
+}
+
+static PyObject *poly1305key_pynew(PyTypeObject *ty,
+                                  PyObject *arg, PyObject *kw)
+{
+  char *kwlist[] = { "k", 0 };
+  poly1305key_pyobj *pk;
+  char *k;
+  int sz;
+
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz))
+    goto end;
+  if (keysz(sz, poly1305_keysz) != sz) VALERR("bad key length");
+
+  pk = newtype(ty, 0, 0);
+  pk->ty.ht_name = PyString_FromString("poly1305(keyed)");
+  pk->ty.ht_type.tp_basicsize = sizeof(poly1305hash_pyobj);
+  pk->ty.ht_type.tp_name = PyString_AS_STRING(pk->ty.ht_name);
+  pk->ty.ht_type.tp_base = poly1305hash_pytype;
+  Py_INCREF(poly1305key_pytype);
+  pk->ty.ht_type.tp_flags = (Py_TPFLAGS_DEFAULT |
+                            Py_TPFLAGS_BASETYPE |
+                            Py_TPFLAGS_HEAPTYPE);
+  pk->ty.ht_type.tp_alloc = PyType_GenericAlloc;
+  pk->ty.ht_type.tp_free = 0;
+  pk->ty.ht_type.tp_new = poly1305hash_pynew;
+  typeready(&pk->ty.ht_type);
+
+  poly1305_keyinit(&pk->k, k, sz);
+  return ((PyObject *)pk);
+
+end:
+  return (0);
+}
+
+static PyObject *poly1305clsget_name(PyObject *me, void *hunoz)
+  { return (PyString_FromString("poly1305")); }
+
+static PyObject *poly1305clsget_keysz(PyObject *me, void *hunoz)
+  { return (keysz_pywrap(poly1305_keysz)); }
+
+static PyObject *poly1305clsget_masksz(PyObject *me, void *hunoz)
+  { return (PyInt_FromLong(POLY1305_MASKSZ)); }
+
+static PyObject *poly1305clsget_tagsz(PyObject *me, void *hunoz)
+  { return (PyInt_FromLong(POLY1305_TAGSZ)); }
+
+static PyObject *polymeth_copy(PyObject *me, PyObject *arg)
+{
+  poly1305hash_pyobj *ph;
+  if (!PyArg_ParseTuple(arg, ":copy")) return (0);
+  ph = PyObject_NEW(poly1305hash_pyobj, me->ob_type);
+  poly1305_copy(&ph->ctx, P1305_CTX(me));
+  Py_INCREF(me->ob_type);
+  return ((PyObject *)ph);
+}
+
+static PyObject *polymeth_hash(PyObject *me, PyObject *arg)
+{
+  char *p;
+  int sz;
+  if (!PyArg_ParseTuple(arg, "s#:hash", &p, &sz)) return (0);
+  poly1305_hash(P1305_CTX(me), p, sz);
+  RETURN_ME;
+}
+
+#define POLYMETH_HASHU_(n, W, w)                                       \
+  static PyObject *polymeth_hashu##w(PyObject *me, PyObject *arg)      \
+  {                                                                    \
+    uint##n x;                                                         \
+    octet b[SZ_##W];                                                   \
+    if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) goto end; \
+    STORE##W(b, n); poly1305_hash(P1305_CTX(me), b, sizeof(b));                \
+    RETURN_ME;                                                         \
+  end:                                                                 \
+    return (0);                                                                \
+  }
+DOUINTCONV(POLYMETH_HASHU_)
+
+#define POLYMETH_HASHBUF_(n, W, w)                                     \
+  static PyObject *polymeth_hashbuf##w(PyObject *me, PyObject *arg)    \
+  {                                                                    \
+    char *p;                                                           \
+    int sz;                                                            \
+    octet b[SZ_##W];                                                   \
+    if (!PyArg_ParseTuple(arg, "s#:hashbuf" #w, &p, &sz)) goto end;    \
+    if (sz > MASK##n) TYERR("string too long");                                \
+    STORE##W(b, n); poly1305_hash(P1305_CTX(me), b, sizeof(b));                \
+    poly1305_hash(P1305_CTX(me), p, sz);                               \
+    RETURN_ME;                                                         \
+  end:                                                                 \
+    return (0);                                                                \
+  }
+DOUINTCONV(POLYMETH_HASHBUF_)
+
+static PyObject *polymeth_hashstrz(PyObject *me, PyObject *arg)
+{
+  char *p;
+  if (!PyArg_ParseTuple(arg, "s:hashstrz", &p)) return (0);
+  poly1305_hash(P1305_CTX(me), p, strlen(p) + 1);
+  RETURN_ME;
+}
+
+static PyObject *polymeth_flush(PyObject *me, PyObject *arg)
+{
+  if (!PyArg_ParseTuple(arg, ":flush")) return (0);
+  poly1305_flush(P1305_CTX(me));
+  RETURN_ME;
+}
+
+static PyObject *polymeth_concat(PyObject *me, PyObject *arg)
+{
+  PyObject *pre, *suff;
+  if (!PyArg_ParseTuple(arg, "OO:concat", &pre, &suff)) return (0);
+  if (!PyObject_TypeCheck(pre, poly1305hash_pytype) ||
+      !PyObject_TypeCheck(suff, poly1305hash_pytype))
+    TYERR("wanted a poly1305hash");
+  if (me->ob_type != pre->ob_type || me->ob_type != suff->ob_type)
+    TYERR("key mismatch");
+  if (P1305_CTX(pre)->nbuf) VALERR("prefix is not block-aligned");
+  poly1305_concat(P1305_CTX(me), P1305_CTX(pre), P1305_CTX(suff));
+  RETURN_ME;
+end:
+  return (0);
+}
+
+static PyObject *polymeth_done(PyObject *me, PyObject *arg)
+{
+  PyObject *rc;
+  if (!PyArg_ParseTuple(arg, ":done")) return (0);
+  if (!(P1305_F(me) & f_mask)) VALERR("no mask");
+  rc = bytestring_pywrap(0, POLY1305_TAGSZ);
+  poly1305_done(P1305_CTX(me), PyString_AS_STRING(rc));
+  return (rc);
+end:
+  return (0);
+}
+
+static PyGetSetDef poly1305cls_pygetset[] = {
+#define GETSETNAME(op, name) poly1305cls##op##_##name
+  GET  (keysz,                 "PC.keysz -> acceptable key sizes")
+  GET  (masksz,                "PC.masksz -> mask size")
+  GET  (tagsz,                 "PC.tagsz -> MAC output size")
+  GET  (name,                  "PC.name -> name of this kind of MAC")
+#undef GETSETNAME
+  { 0 }
+};
+
+static PyMethodDef poly1305hash_pymethods[] = {
+#define METHNAME(name) polymeth_##name
+  METH  (copy,                 "P.copy() -> PP")
+  METH (hash,                  "P.hash(M)")
+#define METHU_(n, W, w) METH(hashu##w, "P.hashu" #w "(WORD)")
+  DOUINTCONV(METHU_)
+#undef METHU_
+#define METHBUF_(n, W, w) METH(hashbuf##w, "P.hashbuf" #w "(BYTES)")
+  DOUINTCONV(METHBUF_)
+#undef METHBUF_
+  METH (hashstrz,              "P.hashstrz(STRING)")
+  METH  (flush,                        "P.flush()")
+  METH  (concat,               "P.concat(PREFIX, SUFFIX)")
+  METH (done,                  "P.done() -> TAG")
+#undef METHNAME
+  { 0 }
+};
+
+static PyTypeObject poly1305cls_pytype_skel = {
+  PyObject_HEAD_INIT(0) 0,             /* Header */
+  "Poly1305Class",                     /* @tp_name@ */
+  sizeof(PyHeapTypeObject),            /* @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@ */
+"Poly1305 metametaclass.  Best not to ask.",
+
+  0,                                   /* @tp_traverse@ */
+  0,                                   /* @tp_clear@ */
+  0,                                   /* @tp_richcompare@ */
+  0,                                   /* @tp_weaklistoffset@ */
+  0,                                   /* @tp_iter@ */
+  0,                                   /* @tp_iternext@ */
+  0,                                   /* @tp_methods@ */
+  0,                                   /* @tp_members@ */
+  poly1305cls_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 poly1305key_pytype_skel = {
+  PyObject_HEAD_INIT(0) 0,             /* Header */
+  "poly1305",                          /* @tp_name@ */
+  sizeof(poly1305key_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@ */
+"Poly1305 key.",
+
+  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@ */
+  poly1305key_pynew,                   /* @tp_new@ */
+  0,                                   /* @tp_free@ */
+  0                                    /* @tp_is_gc@ */
+};
+
+static PyTypeObject poly1305hash_pytype_skel = {
+  PyObject_HEAD_INIT(0) 0,             /* Header */
+  "Poly1305Hash",                      /* @tp_name@ */
+  sizeof(poly1305hash_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@ */
+"Poly1305 MAC context base class.",
+
+  0,                                   /* @tp_traverse@ */
+  0,                                   /* @tp_clear@ */
+  0,                                   /* @tp_richcompare@ */
+  0,                                   /* @tp_weaklistoffset@ */
+  0,                                   /* @tp_iter@ */
+  0,                                   /* @tp_iternext@ */
+  poly1305hash_pymethods,              /* @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@ */
+};
+
+
 /*----- Pseudorandom permutations -----------------------------------------*/
 
 static PyTypeObject *gcprp_pytype, *gprp_pytype;
@@ -1467,6 +1818,9 @@ void algorithms_pyinit(void)
   INITTYPE(gcmac, type);
   INITTYPE(gmac, type);
   INITTYPE(gmhash, ghash);
+  INITTYPE(poly1305cls, type);
+  INITTYPE_META(poly1305key, type, poly1305cls);
+  INITTYPE(poly1305hash, root);
   INITTYPE(gcprp, type);
   INITTYPE(gprp, root);
   addmethods(methods);
@@ -1497,6 +1851,9 @@ void algorithms_pyinsert(PyObject *mod)
   INSERT("GMAC", gmac_pytype);
   INSERT("GMACHash", gmhash_pytype);
   INSERT("gcmacs", gcmacs());
+  INSERT("Poly1305Class", poly1305cls_pytype);
+  INSERT("poly1305", poly1305key_pytype);
+  INSERT("Poly1305Hash", poly1305hash_pytype);
   INSERT("GCPRP", gcprp_pytype);
   INSERT("GPRP", gprp_pytype);
   INSERT("gcprps", gcprps());
index ecdbc30d8758d2e323bcb320a57726445bbb519e..0949562de460e319ec89a0ff319e26095e13c693 100644 (file)
@@ -62,6 +62,7 @@
 #include <catacomb/gmac.h>
 #include <catacomb/md5.h>
 #include <catacomb/md5-hmac.h>
+#include <catacomb/poly1305.h>
 #include <catacomb/sha.h>
 #include <catacomb/sha-mgf.h>
 #include <catacomb/sha-hmac.h>
index 444feba7e87eca68a2d944bbcfa2e1e65c84f92a..c9e5b41a1ef905849a466b997e8ac3c32edffa0c 100644 (file)
@@ -5,7 +5,7 @@ XS-Python-Version: >= 2.6, << 2.8
 Maintainer: Mark Wooding <mdw@distorted.org.uk>
 Build-Depends: debhelper (>= 9), pkg-config,
        python, python2.6-dev, python2.7-dev,
-       mlib-dev (>= 2.2.2.1), catacomb-dev (>= 2.2.5+14)
+       mlib-dev (>= 2.2.2.1), catacomb-dev (>= 2.3.0.1+3)
 Standards-Version: 3.8.0
 
 Package: python-catacomb
index 161e2afcfa56f31584feea6e7f10dee2c1e1bf2e..fe0ed538bf9389645be87fb2e89a64086ebdf969 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
 import distutils.core as DC
 import mdwsetup as MS
 
-MS.pkg_config('catacomb', '2.2.0')
+MS.pkg_config('catacomb', '2.3.0.1+4')
 MS.pkg_config('mLib', '2.0.4')
 
 cat = DC.Extension('catacomb._base',