+/*----- 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@ */
+};
+
+/*----- Special snowflake for HSalsa and HChaCha --------------------------*/
+
+#define DEF_HDANCE(DANCE, HDANCE, dance, hdance) \
+ static PyObject *meth_##hdance##_prf(PyObject *me, PyObject *arg) \
+ { \
+ dance##_ctx dance; \
+ char *k, *n; \
+ int ksz, nsz; \
+ PyObject *rc; \
+ if (!PyArg_ParseTuple(arg, "s#s#:" #hdance "_prf", \
+ &k, &ksz, &n, &nsz)) \
+ goto end; \
+ if (ksz != DANCE##_KEYSZ) VALERR("bad key length"); \
+ if (nsz != HDANCE##_INSZ) VALERR("bad input length"); \
+ rc = bytestring_pywrap(0, HSALSA20_OUTSZ); \
+ dance##_init(&dance, k, ksz, 0); \
+ hdance##_prf(&dance, n, PyString_AS_STRING(rc)); \
+ return (rc); \
+ end: \
+ return (0); \
+ }
+
+DEF_HDANCE(SALSA20, HSALSA20, salsa20, hsalsa20)
+DEF_HDANCE(SALSA20, HSALSA20, salsa20, hsalsa2012)
+DEF_HDANCE(SALSA20, HSALSA20, salsa20, hsalsa208)
+
+DEF_HDANCE(CHACHA, HCHACHA, chacha, hchacha20)
+DEF_HDANCE(CHACHA, HCHACHA, chacha, hchacha12)
+DEF_HDANCE(CHACHA, HCHACHA, chacha, hchacha8)
+
+/*----- 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.ht_type.tp_basicsize = sizeof(gprp_pyobj) + prp->ctxsz;
+ g->ty.ht_type.tp_base = gprp_pytype;
+ Py_INCREF(gprp_pytype);
+ 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;
+ g->ty.ht_type.tp_new = gprp_pynew;
+ typeready(&g->ty.ht_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 */
+ "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 */
+ "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@ */
+};
+