X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/b35fdbe6fd7d9d46d5e195ae8cfd14d5729d3234..cb46f06b084bb7574b6f7cde13bf413f58a1e91c:/algorithms.c diff --git a/algorithms.c b/algorithms.c index e4233fa..0f05f75 100644 --- a/algorithms.c +++ b/algorithms.c @@ -1745,6 +1745,351 @@ static PyTypeObject kxvik_pytype_skel = { 0 /* @tp_is_gc@ */ }; +static PyTypeObject *shake_pytype, *shake128_pytype, *shake256_pytype; + +typedef struct shake_pyobj { + PyObject_HEAD + int st; + shake_ctx h; +} shake_pyobj; + +#define SHAKE_H(o) (&((shake_pyobj *)(o))->h) +#define SHAKE_ST(o) (((shake_pyobj *)(o))->st) + +static PyObject *shake_dopynew(void (*initfn)(shake_ctx *, + const void *, size_t, + const void *, size_t), + PyTypeObject *ty, + PyObject *arg, PyObject *kw) +{ + shake_pyobj *rc = 0; + char *p = 0, *f = 0; + Py_ssize_t psz = 0, fsz = 0; + char *kwlist[] = { "perso", "func", 0 }; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|s#s#:new", kwlist, + &p, &psz, &f, &fsz)) + goto end; + rc = (shake_pyobj *)ty->tp_alloc(ty, 0); + initfn(&rc->h, f, fsz, p, psz); + rc->st = 0; +end: + return ((PyObject *)rc); +} + +static PyObject *shake128_pynew(PyTypeObject *ty, + PyObject *arg, PyObject *kw) + { return (shake_dopynew(cshake128_init, ty, arg, kw)); } + +static PyObject *shake256_pynew(PyTypeObject *ty, + PyObject *arg, PyObject *kw) + { return (shake_dopynew(cshake256_init, ty, arg, kw)); } + +static int shake_check(PyObject *me, int st) +{ + if (SHAKE_ST(me) != st) VALERR("wrong state"); + return (0); +end: + return (-1); +} + +static PyObject *shakemeth_hash(PyObject *me, PyObject *arg) +{ + char *p; + Py_ssize_t sz; + if (!PyArg_ParseTuple(arg, "s#:hash", &p, &sz)) return (0); + if (shake_check(me, 0)) return (0); + shake_hash(SHAKE_H(me), p, sz); + RETURN_ME; +} + +#define SHAKEMETH_HASHU_(n, W, w) \ + static PyObject *shakemeth_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; \ + if (shake_check(me, 0)) goto end; \ + STORE##W(b, x); shake_hash(SHAKE_H(me), b, sizeof(b)); \ + RETURN_ME; \ + end: \ + return (0); \ + } +DOUINTCONV(SHAKEMETH_HASHU_) + +#define SHAKEMETH_HASHBUF_(n, W, w) \ + static PyObject *shakemeth_hashbuf##w(PyObject *me, PyObject *arg) \ + { \ + char *p; \ + Py_ssize_t sz; \ + octet b[SZ_##W]; \ + if (!PyArg_ParseTuple(arg, "s#:hashbuf" #w, &p, &sz)) goto end; \ + if (sz > MASK##n) TYERR("string too long"); \ + if (shake_check(me, 0)) goto end; \ + STORE##W(b, sz); shake_hash(SHAKE_H(me), b, sizeof(b)); \ + shake_hash(SHAKE_H(me), p, sz); \ + RETURN_ME; \ + end: \ + return (0); \ + } +DOUINTCONV(SHAKEMETH_HASHBUF_) + +static PyObject *shakemeth_hashstrz(PyObject *me, PyObject *arg) +{ + char *p; + if (!PyArg_ParseTuple(arg, "s:hashstrz", &p)) return (0); + if (shake_check(me, 0)) return (0); + shake_hash(SHAKE_H(me), p, strlen(p) + 1); + RETURN_ME; +} + +static PyObject *shakemeth_xof(PyObject *me, PyObject *arg) +{ + if (!PyArg_ParseTuple(arg, ":xof")) goto end; + if (shake_check(me, 0)) goto end; + shake_xof(SHAKE_H(me)); + SHAKE_ST(me) = 1; + RETURN_ME; +end: + return (0); +} + +static PyObject *shakemeth_done(PyObject *me, PyObject *arg) +{ + PyObject *rc = 0; + size_t n; + if (!PyArg_ParseTuple(arg, "O&:done", convszt, &n)) goto end; + if (shake_check(me, 0)) goto end; + rc = bytestring_pywrap(0, n); + shake_done(SHAKE_H(me), PyString_AS_STRING(rc), n); + SHAKE_ST(me) = -1; +end: + return (rc); +} + +static PyObject *shakemeth_copy(PyObject *me, PyObject *arg) +{ + shake_pyobj *rc = 0; + + if (!PyArg_ParseTuple(arg, ":copy")) goto end; + rc = PyObject_NEW(shake_pyobj, me->ob_type); + rc->h = *SHAKE_H(me); + rc->st = SHAKE_ST(me); +end: + return ((PyObject *)me); +} + +static PyObject *shakemeth_get(PyObject *me, PyObject *arg) +{ + PyObject *rc = 0; + size_t sz; + + if (!PyArg_ParseTuple(arg, "O&:get", convszt, &sz)) goto end; + if (shake_check(me, 1)) goto end; + rc = bytestring_pywrap(0, sz); + shake_get(SHAKE_H(me), PyString_AS_STRING(rc), sz); +end: + return (rc); +} + +static PyObject *shakemeth_mask(PyObject *me, PyObject *arg) +{ + PyObject *rc = 0; + char *p; Py_ssize_t sz; + + if (!PyArg_ParseTuple(arg, "s#:mask", &p, &sz)) goto end; + if (shake_check(me, 1)) goto end; + rc = bytestring_pywrap(0, sz); + shake_mask(SHAKE_H(me), p, PyString_AS_STRING(rc), sz); +end: + return (rc); +} + +static PyObject *shakeget_rate(PyObject *me, void *hunoz) + { return (PyInt_FromLong(SHAKE_H(me)->h.r)); } + +static PyObject *shakeget_buffered(PyObject *me, void *hunoz) + { return (PyInt_FromLong(SHAKE_H(me)->h.n)); } + +static PyObject *shakeget_state(PyObject *me, void *hunoz) +{ + int st = SHAKE_ST(me); + return (PyString_FromString(st == 0 ? "absorb" : + st == 1 ? "squeeze" : "dead")); +} + +static PyGetSetDef shake_pygetset[] = { +#define GETSETNAME(op, name) shake##op##_##name + GET (rate, "S.rate -> rate, in bytes") + GET (buffered, "S.buffered -> amount currently buffered") + GET (state, "S.state -> `absorb', `squeeze', `dead'") +#undef GETSETNAME + { 0 } +}; + +static PyMethodDef shake_pymethods[] = { +#define METHNAME(func) shakemeth_##func + METH (copy, "S.copy() -> SS") + METH (hash, "S.hash(M)") +#define METHU_(n, W, w) METH(hashu##w, "S.hashu" #w "(WORD)") + DOUINTCONV(METHU_) +#undef METHU_ +#define METHBUF_(n, W, w) METH(hashbuf##w, "S.hashbuf" #w "(BYTES)") + DOUINTCONV(METHBUF_) +#undef METHBUF_ + METH (hashstrz, "S.hashstrz(STRING)") + METH (xof, "S.xof()") + METH (done, "S.done(LEN) ->H") + METH (get, "S.get(LEN) -> H") + METH (mask, "S.mask(M) -> C") +#undef METHNAME + { 0 } +}; + +static PyTypeObject shake_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "Shake", /* @tp_name@ */ + sizeof(shake_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@ */ +"SHAKE/cSHAKE base class.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + 0, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + shake_pymethods, /* @tp_methods@ */ + 0, /* @tp_members@ */ + shake_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 shake128_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "Shake128", /* @tp_name@ */ + 0, /* @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@ */ +"SHAKE128/cSHAKE128 XOF.", + + 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@ */ + shake128_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +static PyTypeObject shake256_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "Shake256", /* @tp_name@ */ + 0, /* @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@ */ +"SHAKE256/cSHAKE256 XOF.", + + 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@ */ + shake256_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + /*----- Pseudorandom permutations -----------------------------------------*/ static PyTypeObject *gcprp_pytype, *gprp_pytype; @@ -2042,6 +2387,9 @@ void algorithms_pyinit(void) INITTYPE_META(poly1305key, type, poly1305cls); INITTYPE(poly1305hash, root); INITTYPE(kxvik, root); + INITTYPE(shake, root); + INITTYPE(shake128, shake); + INITTYPE(shake256, shake); INITTYPE(gcprp, type); INITTYPE(gprp, root); addmethods(methods); @@ -2076,6 +2424,9 @@ void algorithms_pyinsert(PyObject *mod) INSERT("poly1305", poly1305key_pytype); INSERT("Poly1305Hash", poly1305hash_pytype); INSERT("Keccak1600", kxvik_pytype); + INSERT("Shake", shake_pytype); + INSERT("Shake128", shake128_pytype); + INSERT("Shake256", shake256_pytype); INSERT("GCPRP", gcprp_pytype); INSERT("GPRP", gprp_pytype); INSERT("gcprps", gcprps());