};
static PyTypeObject keysz_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.KeySZ", /* @tp_name@ */
sizeof(keysz_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
0, /* @tp_methods@ */
keysz_pymembers, /* @tp_members@ */
0, /* @tp_getset@ */
};
static PyTypeObject keyszany_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.KeySZAny", /* @tp_name@ */
sizeof(keysz_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
0, /* @tp_methods@ */
0, /* @tp_members@ */
keyszany_pygetset, /* @tp_getset@ */
};
static PyTypeObject keyszrange_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.KeySZRange", /* @tp_name@ */
sizeof(keyszrange_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
0, /* @tp_methods@ */
keyszrange_pymembers, /* @tp_members@ */
0, /* @tp_getset@ */
};
static PyTypeObject keyszset_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.KeySZSet", /* @tp_name@ */
sizeof(keyszset_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
0, /* @tp_methods@ */
keyszset_pymembers, /* @tp_members@ */
keyszset_pygetset, /* @tp_getset@ */
};
static PyTypeObject gccipher_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.GCCipher", /* @tp_name@ */
sizeof(gccipher_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
0, /* @tp_methods@ */
0, /* @tp_members@ */
gccipher_pygetset, /* @tp_getset@ */
};
static PyTypeObject gcipher_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.GCipher", /* @tp_name@ */
sizeof(gcipher_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
gcipher_pymethods, /* @tp_methods@ */
0, /* @tp_members@ */
0, /* @tp_getset@ */
{ 0 }
};
+#define GHMETH_HASHU_(n, W, w) \
+ static PyObject *ghmeth_hashu##w(PyObject *me, PyObject *arg) \
+ { \
+ uint##n x; \
+ if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) goto end; \
+ GH_HASHU##W(GHASH_H(me), x); \
+ RETURN_ME; \
+ end: \
+ return (0); \
+ }
+DOUINTCONV(GHMETH_HASHU_)
+
+#define GHMETH_HASHBUF_(n, W, w) \
+ static PyObject *ghmeth_hashbuf##w(PyObject *me, PyObject *arg) \
+ { \
+ char *p; \
+ int sz; \
+ if (!PyArg_ParseTuple(arg, "s#:hashbuf" #w, &p, &sz)) goto end; \
+ if (sz > MASK##n) TYERR("string too long"); \
+ GH_HASHBUF##W(GHASH_H(me), p, sz); \
+ RETURN_ME; \
+ end: \
+ return (0); \
+ }
+DOUINTCONV(GHMETH_HASHBUF_)
+
+static PyObject *ghmeth_hashstrz(PyObject *me, PyObject *arg)
+{
+ char *p;
+ if (!PyArg_ParseTuple(arg, "s:hashstrz", &p)) return (0);
+ GH_HASHSTRZ(GHASH_H(me), p);
+ RETURN_ME;
+}
+
static PyMethodDef ghash_pymethods[] = {
#define METHNAME(name) ghmeth_##name
METH (hash, "H.hash(M)")
+#define METHU_(n, W, w) METH(hashu##w, "H.hashu" #w "(WORD)")
+ DOUINTCONV(METHU_)
+#define METHBUF_(n, W, w) METH(hashbuf##w, "H.hashbuf" #w "(BYTES)")
+ DOUINTCONV(METHBUF_)
+ METH (hashstrz, "H.hashstrz(STRING)")
METH (done, "H.done() -> HASH")
#undef METHNAME
{ 0 }
};
static PyTypeObject gchash_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.GCHash", /* @tp_name@ */
sizeof(gchash_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
0, /* @tp_methods@ */
0, /* @tp_members@ */
gchash_pygetset, /* @tp_getset@ */
};
static PyTypeObject ghash_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.GHash", /* @tp_name@ */
sizeof(ghash_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
ghash_pymethods, /* @tp_methods@ */
0, /* @tp_members@ */
0, /* @tp_getset@ */
};
static PyTypeObject gcmac_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.GCMAC", /* @tp_name@ */
sizeof(gchash_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
0, /* @tp_methods@ */
0, /* @tp_members@ */
gcmac_pygetset, /* @tp_getset@ */
};
static PyTypeObject gmac_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.GMAC", /* @tp_name@ */
sizeof(gmac_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
0, /* @tp_methods@ */
0, /* @tp_members@ */
0, /* @tp_getset@ */
};
static PyTypeObject gmhash_pytype_skel = {
- PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
+ PyObject_HEAD_INIT(0) 0, /* Header */
"catacomb.GMACHash", /* @tp_name@ */
sizeof(ghash_pyobj), /* @tp_basicsize@ */
0, /* @tp_itemsize@ */
0, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
- 0, /* @tp_iternexr@ */
+ 0, /* @tp_iternext@ */
0, /* @tp_methods@ */
0, /* @tp_members@ */
0, /* @tp_getset@ */
0 /* @tp_is_gc@ */
};
+/*----- Pseudorandom permutations -----------------------------------------*/
+
+static PyTypeObject *gcprp_pytype, *gprp_pytype;
+
+typedef struct prpinfo {
+ const char *name;
+ const octet *keysz;
+ size_t ctxsz;
+ size_t blksz;
+ void (*init)(void *, const void *, size_t);
+ void (*eblk)(void *, const void *, void *);
+ void (*dblk)(void *, const void *, void *);
+} prpinfo;
+
+#define PRP_DEF(PRE, pre) \
+ static void pre##_prpinit(void *ctx, const void *k, size_t ksz) \
+ { pre##_init(ctx, k, ksz); } \
+ static void pre##_prpeblk(void *ctx, const void *in, void *out) \
+ { \
+ uint32 w[PRE##_BLKSZ/4]; BLKC_LOAD(PRE, w, in); \
+ pre##_eblk(ctx, w, w); BLKC_STORE(PRE, out, w); \
+ } \
+ static void pre##_prpdblk(void *ctx, const void *in, void *out) \
+ { \
+ uint32 w[PRE##_BLKSZ/4]; BLKC_LOAD(PRE, w, in); \
+ pre##_dblk(ctx, w, w); BLKC_STORE(PRE, out, w); \
+ } \
+ static const prpinfo pre##_prpinfo = { \
+ #pre, pre##_keysz, sizeof(pre##_ctx), PRE##_BLKSZ, \
+ pre##_prpinit, pre##_prpeblk, pre##_prpdblk \
+ };
+PRPS(PRP_DEF)
+
+static const struct prpinfo *const gprptab[] = {
+#define PRP_ENTRY(PRE, pre) &pre##_prpinfo,
+ PRPS(PRP_ENTRY)
+ 0
+};
+
+typedef struct gcprp_pyobj {
+ PyHeapTypeObject ty;
+ const prpinfo *prp;
+} gcprp_pyobj;
+#define GCPRP_PRP(o) (((gcprp_pyobj *)(o))->prp)
+
+typedef struct gprp_pyobj {
+ PyObject_HEAD
+ const prpinfo *prp;
+} gprp_pyobj;
+#define GPRP_PRP(o) (((gprp_pyobj *)(o))->prp)
+#define GPRP_CTX(o) (((gprp_pyobj *)(o)) + 1)
+
+typedef struct prp {
+ const prpinfo *prp;
+ void *ctx;
+} prp;
+
+static PyObject *gprp_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
+{
+ char *kwlist[] = { "key", 0 };
+ char *k;
+ int sz;
+ const prpinfo *prp = GCPRP_PRP(ty);
+ PyObject *me;
+
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz))
+ goto end;
+ if (keysz(sz, prp->keysz) != sz) VALERR("bad key length");
+ me = (PyObject *)ty->tp_alloc(ty, 0);
+ GPRP_PRP(me) = prp;
+ prp->init(GPRP_CTX(me), k, sz);
+ Py_INCREF(me);
+ return (me);
+end:
+ return (0);
+}
+
+static void gprp_pydealloc(PyObject *me)
+ { Py_DECREF(me->ob_type); FREEOBJ(me); }
+
+static PyObject *gcprp_pywrap(const prpinfo *prp)
+{
+ gcprp_pyobj *g = newtype(gcprp_pytype, 0, prp->name);
+ g->prp = prp;
+ g->ty.type.tp_basicsize = sizeof(gprp_pyobj) + prp->ctxsz;
+ g->ty.type.tp_base = gprp_pytype;
+ Py_INCREF(gprp_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;
+ g->ty.type.tp_new = gprp_pynew;
+ PyType_Ready(&g->ty.type);
+ return ((PyObject *)g);
+}
+
+static PyObject *gcpget_name(PyObject *me, void *hunoz)
+ { return (PyString_FromString(GCPRP_PRP(me)->name)); }
+static PyObject *gcpget_keysz(PyObject *me, void *hunoz)
+ { return (keysz_pywrap(GCPRP_PRP(me)->keysz)); }
+static PyObject *gcpget_blksz(PyObject *me, void *hunoz)
+ { return (PyInt_FromLong(GCPRP_PRP(me)->blksz)); }
+
+static PyObject *gpmeth_encrypt(PyObject *me, PyObject *arg)
+{
+ char *p;
+ int n;
+ PyObject *rc = 0;
+
+ if (!PyArg_ParseTuple(arg, "s#:encrypt", &p, &n)) goto end;
+ if (n != GPRP_PRP(me)->blksz) VALERR("incorrect block length");
+ rc = bytestring_pywrap(0, n);
+ GPRP_PRP(me)->eblk(GPRP_CTX(me), p, PyString_AS_STRING(rc));
+end:
+ return (rc);
+}
+
+static PyObject *gpmeth_decrypt(PyObject *me, PyObject *arg)
+{
+ char *p;
+ int n;
+ PyObject *rc = 0;
+
+ if (!PyArg_ParseTuple(arg, "s#:decrypt", &p, &n)) goto end;
+ if (n != GPRP_PRP(me)->blksz) VALERR("incorrect block length");
+ rc = bytestring_pywrap(0, n);
+ GPRP_PRP(me)->dblk(GPRP_CTX(me), p, PyString_AS_STRING(rc));
+end:
+ return (rc);
+}
+
+static PyGetSetDef gcprp_pygetset[] = {
+#define GETSETNAME(op, name) gcp##op##_##name
+ GET (keysz, "CP.keysz -> acceptable key sizes")
+ GET (blksz, "CP.blksz -> block size")
+ GET (name, "CP.name -> name of this kind of PRP")
+#undef GETSETNAME
+ { 0 }
+};
+
+static PyMethodDef gprp_pymethods[] = {
+#define METHNAME(name) gpmeth_##name
+ METH (encrypt, "P.encrypt(PT) -> CT")
+ METH (decrypt, "P.decrypt(CT) -> PT")
+#undef METHNAME
+ { 0 }
+};
+
+static PyTypeObject gcprp_pytype_skel = {
+ PyObject_HEAD_INIT(0) 0, /* Header */
+ "catacomb.GCPRP", /* @tp_name@ */
+ sizeof(gcprp_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@ */
+"Pseudorandom permutation metaclass.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ 0, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ 0, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ 0, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ gcprp_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 gprp_pytype_skel = {
+ PyObject_HEAD_INIT(0) 0, /* Header */
+ "catacomb.GPRP", /* @tp_name@ */
+ sizeof(gprp_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ gprp_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@ */
+"Pseudorandom permutation, abstract base class.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ 0, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ 0, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ gprp_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@ */
+};
+
/*----- Main code ---------------------------------------------------------*/
void algorithms_pyinit(void)
INITTYPE(gcmac, type);
INITTYPE(gmac, type);
INITTYPE(gmhash, ghash);
+ INITTYPE(gcprp, type);
+ INITTYPE(gprp, root);
}
#define GEN(func, base) \
GEN(gcciphers, cipher)
GEN(gchashes, hash)
GEN(gcmacs, mac)
+#define gcprp prpinfo
+GEN(gcprps, prp)
void algorithms_pyinsert(PyObject *mod)
{
INSERT("GMAC", gmac_pytype);
INSERT("GMACHash", gmhash_pytype);
INSERT("gcmacs", gcmacs());
+ INSERT("GCPRP", gcprp_pytype);
+ INSERT("GPRP", gprp_pytype);
+ INSERT("gcprps", gcprps());
}
/*----- That's all, folks -------------------------------------------------*/