{
char *kwlist[] = { "k", 0 };
char *k;
- int sz;
+ Py_ssize_t sz;
if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz))
goto end;
static PyObject *gcmeth_encrypt(PyObject *me, PyObject *arg)
{
char *p;
- int sz;
+ Py_ssize_t sz;
PyObject *rc = 0;
if (!PyArg_ParseTuple(arg, "s#:encrypt", &p, &sz)) return (0);
static PyObject *gcmeth_decrypt(PyObject *me, PyObject *arg)
{
char *p;
- int sz;
+ Py_ssize_t sz;
PyObject *rc = 0;
if (!PyArg_ParseTuple(arg, "s#:decrypt", &p, &sz)) return (0);
static PyObject *gcmeth_setiv(PyObject *me, PyObject *arg)
{
char *p;
- int sz;
+ Py_ssize_t sz;
if (!PyArg_ParseTuple(arg, "s#:setiv", &p, &sz)) goto end;
+ if (!GCIPHER_C(me)->ops->setiv) VALERR("`setiv' not supported");
if (!GC_CLASS(GCIPHER_C(me))->blksz) VALERR("not a block cipher mode");
if (sz != GC_CLASS(GCIPHER_C(me))->blksz) VALERR("bad IV length");
GC_SETIV(GCIPHER_C(me), p);
static PyObject *gcmeth_bdry(PyObject *me, PyObject *arg)
{
if (!PyArg_ParseTuple(arg, ":bdry")) goto end;
+ if (!GCIPHER_C(me)->ops->bdry) VALERR("`bdry' not supported");
if (!GC_CLASS(GCIPHER_C(me))->blksz) VALERR("not a block cipher mode");
GC_BDRY(GCIPHER_C(me));
RETURN_ME;
static PyObject *ghmeth_hash(PyObject *me, PyObject *arg)
{
char *p;
- int sz;
+ Py_ssize_t sz;
if (!PyArg_ParseTuple(arg, "s#:hash", &p, &sz)) return (0);
GH_HASH(GHASH_H(me), p, sz);
RETURN_ME;
}
-static PyObject *ghmeth_done(PyObject *me, PyObject *arg)
-{
- ghash *g;
- PyObject *rc;
- if (!PyArg_ParseTuple(arg, ":done")) return (0);
- g = GH_COPY(GHASH_H(me));
- rc = bytestring_pywrap(0, g->ops->c->hashsz);
- GH_DONE(g, PyString_AS_STRING(rc));
- GH_DESTROY(g);
- return (rc);
-}
-
-static PyGetSetDef gchash_pygetset[] = {
-#define GETSETNAME(op, name) gch##op##_##name
- GET (bufsz, "CH.bufsz -> hash buffer size, or zero")
- GET (hashsz, "CH.blksz -> hash output size")
- GET (name, "CH.name -> name of this kind of hash")
-#undef GETSETNAME
- { 0 }
-};
-
#define GHMETH_HASHU_(n, W, w) \
static PyObject *ghmeth_hashu##w(PyObject *me, PyObject *arg) \
{ \
static PyObject *ghmeth_hashbuf##w(PyObject *me, PyObject *arg) \
{ \
char *p; \
- int sz; \
+ Py_ssize_t 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;
}
+static PyObject *ghmeth_done(PyObject *me, PyObject *arg)
+{
+ ghash *g;
+ PyObject *rc;
+ if (!PyArg_ParseTuple(arg, ":done")) return (0);
+ g = GH_COPY(GHASH_H(me));
+ rc = bytestring_pywrap(0, g->ops->c->hashsz);
+ GH_DONE(g, PyString_AS_STRING(rc));
+ GH_DESTROY(g);
+ return (rc);
+}
+
+static PyGetSetDef gchash_pygetset[] = {
+#define GETSETNAME(op, name) gch##op##_##name
+ GET (bufsz, "CH.bufsz -> hash buffer size, or zero")
+ GET (hashsz, "CH.hashsz -> hash output size")
+ GET (name, "CH.name -> name of this kind of hash")
+#undef GETSETNAME
+ { 0 }
+};
+
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_)
+#undef METHU_
#define METHBUF_(n, W, w) METH(hashbuf##w, "H.hashbuf" #w "(BYTES)")
DOUINTCONV(METHBUF_)
+#undef METHBUF_
METH (hashstrz, "H.hashstrz(STRING)")
METH (done, "H.done() -> HASH")
#undef METHNAME
{
char *kwlist[] = { "k", 0 };
char *k;
- int sz;
+ Py_ssize_t sz;
if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz))
goto end;
if (!cobj) cobj = gcmac_pywrap((/*unconst*/ gcmac *)GM_CLASS(m));
else Py_INCREF(cobj);
g = newtype((PyTypeObject *)cobj, 0, 0);
+ g->ty.ht_type.tp_basicsize = sizeof(ghash_pyobj);
g->ty.ht_name = PyString_FromFormat("%s(keyed)", m->ops->c->name);
g->ty.ht_type.tp_name = PyString_AS_STRING(g->ty.ht_name);
g->ty.ht_type.tp_base = gmhash_pytype;
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;
+ Py_ssize_t 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;
+ Py_ssize_t 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;
+ Py_ssize_t 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, x); 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; \
+ 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"); \
+ STORE##W(b, sz); 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_flushzero(PyObject *me, PyObject *arg)
+{
+ if (!PyArg_ParseTuple(arg, ":flushzero")) return (0);
+ poly1305_flushzero(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 (flushzero, "P.flushzero()")
+ 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; \
+ Py_ssize_t 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;
{
char *kwlist[] = { "key", 0 };
char *k;
- int sz;
+ Py_ssize_t sz;
const prpinfo *prp = GCPRP_PRP(ty);
PyObject *me;
static PyObject *gpmeth_encrypt(PyObject *me, PyObject *arg)
{
char *p;
- int n;
+ Py_ssize_t n;
PyObject *rc = 0;
if (!PyArg_ParseTuple(arg, "s#:encrypt", &p, &n)) goto end;
static PyObject *gpmeth_decrypt(PyObject *me, PyObject *arg)
{
char *p;
- int n;
+ Py_ssize_t n;
PyObject *rc = 0;
if (!PyArg_ParseTuple(arg, "s#:decrypt", &p, &n)) goto end;
toif(N) -> M: convert work factor to integer factorization problem size")
METH (_KeySZ_toec, "\
toec(N) -> M: convert work factor to elliptic curve group order")
+ METH (_KeySZ_toec, "\
+toec(N) -> M: convert work factor to elliptic curve group order")
+#define METH_HDANCE(hdance, HDance) METH(hdance##_prf, "\
+" #hdance "_prf(K, N) -> H: calculate " HDance " hash of N with K")
+ METH_HDANCE(hsalsa20, "HSalsa20")
+ METH_HDANCE(hsalsa2012, "HSalsa20/12")
+ METH_HDANCE(hsalsa208, "HSalsa20/8")
+ METH_HDANCE(hchacha20, "HChaCha20")
+ METH_HDANCE(hchacha12, "HChaCha12")
+ METH_HDANCE(hchacha8, "HChaCha8")
+#undef METH_DANCE
#undef METHNAME
{ 0 }
};
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);
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());
rc4 seal
'''.split()
latindances = '''
-salsa20 salsa20/12 salsa20/8 xsalsa20 xsalsa20/12 xsalsa20/8
-chacha20 chacha12 chacha8 xchacha20 xchacha12 xchacha8
+salsa20 salsa20/12 salsa20/8
+salsa20-ietf salsa20/12-ietf salsa20/8-ietf
+xsalsa20 xsalsa20/12 xsalsa20/8
+chacha20 chacha12 chacha8
+chacha20-ietf chacha12-ietf chacha8-ietf
+xchacha20 xchacha12 xchacha8
'''.split()
streamciphers += map(lambda s: s.translate(None, '/'), latindances)
hashes = '''
break
else:
raise ValueError, 'failed to find root name for %s' % i
+ if i.endswith('-ietf'): root += '_ietf'
print ('\t_("%(name)s", %(root)s_keysz, %(id)s_rand, ' +
- 'RNGF_NONCE, %(ROOT)s_NONCESZ) \\') % \
- {'name': i, 'id': i.translate(None, '/'),
+ 'RNGF_NONCE | RNGF_LATIN, %(ROOT)s_NONCESZ) \\') % \
+ {'name': i, 'id': i.translate(None, '/').replace('-', '_'),
'root': root, 'ROOT': root.upper()}
print '\t/* end */'
print
static PyObject *rbuf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
{
char *p, *q;
- int n;
+ Py_ssize_t n;
buf_pyobj *me = 0;
static char *kwlist[] = { "data", 0 };
static PyObject *wbmeth_put(PyObject *me, PyObject *arg)
{
void *p;
- int n;
+ Py_ssize_t n;
if (!PyArg_ParseTuple(arg, "s#:put", &p, &n)) return (0);
ensure(me, n);
buf_put(BUF_B(me), p, n); assert(BOK(BUF_B(m)));
static PyObject *wbmeth_putblk##w(PyObject *me, PyObject *arg) \
{ \
char *p; \
- int sz; \
+ Py_ssize_t sz; \
if (!PyArg_ParseTuple(arg, "s#:putblk" #w, &p, &sz)) return (0); \
ensure(me, sz + SZ_##n); \
buf_putmem##w(BUF_B(me), p, sz); assert(BOK(BUF_B(me))); \
PyObject *arg, PyObject *kw)
{
const char *p;
- int n;
+ Py_ssize_t n;
static char *kwlist[] = { "data", 0 };
if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &p, &n))
return (0);
return (dowrap(ty, p, n));
}
+static PyObject *meth_ctstreq(PyObject *me, PyObject *args)
+{
+ char *p, *q;
+ Py_ssize_t psz, qsz;
+ if (!PyArg_ParseTuple(args, "s#s#:ctstreq", &p, &psz, &q, &qsz))
+ goto end;
+ if (psz == qsz && ct_memeq(p, q, psz)) RETURN_TRUE;
+ else RETURN_FALSE;
+end:
+ return (0);
+}
+
+static PyObject *bytestring_pyrichcompare(PyObject *me,
+ PyObject *you, int op)
+{
+ int b;
+ void *mystr, *yourstr;
+ Py_ssize_t mylen, yourlen, minlen;
+
+ if (!PyString_Check(me) || !PyString_Check(you)) RETURN_NOTIMPL;
+ mystr = PyString_AS_STRING(me); mylen = PyString_GET_SIZE(me);
+ yourstr = PyString_AS_STRING(you); yourlen = PyString_GET_SIZE(you);
+
+ switch (op) {
+ case Py_EQ:
+ b = mylen == yourlen && ct_memeq(mystr, yourstr, mylen);
+ break;
+ case Py_NE:
+ b = mylen != yourlen || !ct_memeq(mystr, yourstr, mylen);
+ break;
+ default:
+ minlen = mylen < yourlen ? mylen : yourlen;
+ b = memcmp(mystr, yourstr, minlen);
+ if (!b) b = mylen < yourlen ? -1 : mylen > yourlen ? +1 : 0;
+ switch (op) {
+ case Py_LT: b = b < 0; break;
+ case Py_LE: b = b <= 0; break;
+ case Py_GE: b = b >= 0; break;
+ case Py_GT: b = b > 0; break;
+ default: abort();
+ }
+ }
+ if (b) RETURN_TRUE;
+ else RETURN_FALSE;
+}
+
#define BINOP(name, op) \
static PyObject *bytestring_py##name(PyObject *x, PyObject *y) { \
const void *xv, *yv; \
0, /* @tp_traverse@ */
0, /* @tp_clear@ */
- 0, /* @tp_richcompare@ */
+ bytestring_pyrichcompare, /* @tp_richcompare@ */
0, /* @tp_weaklistoffset@ */
0, /* @tp_iter@ */
0, /* @tp_iternext@ */
/*----- Initialization ----------------------------------------------------*/
+static PyMethodDef methods[] = {
+#define METHNAME(func) meth_##func
+ METH (ctstreq, "ctstreq(S, T) -> BOOL")
+#undef METHNAME
+ { 0 }
+};
+
#define string_pytype &PyString_Type
void bytestring_pyinit(void)
{
INITTYPE(bytestring, string);
+ addmethods(methods);
}
void bytestring_pyinsert(PyObject *mod)
/*----- Header files ------------------------------------------------------*/
+#define PY_SSIZE_T_CLEAN
+
#include <Python.h>
#include <longintrepr.h>
#include <structmember.h>
-#undef ULLONG_MAX
-#undef ULONG_LONG_MAX
-
#include <mLib/darray.h>
#include <mLib/dstr.h>
#include <mLib/macros.h>
#include <mLib/unihash.h>
#include <catacomb/buf.h>
+#include <catacomb/ct.h>
#include <catacomb/grand.h>
#include <catacomb/rand.h>
#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>
#include <catacomb/ptab.h>
#include <catacomb/bintab.h>
#include <catacomb/dsa.h>
+#include <catacomb/x25519.h>
+#include <catacomb/x448.h>
+#include <catacomb/ed25519.h>
#include <catacomb/gf.h>
#include <catacomb/gfreduce.h>
#define root_pytype 0
#define type_pytype &PyType_Type
-#define INITTYPE(ty, base) do { \
+#define INITTYPE_META(ty, base, meta) do { \
ty##_pytype_skel.tp_base = base##_pytype; \
- ty##_pytype = inittype(&ty##_pytype_skel); \
+ ty##_pytype = inittype(&ty##_pytype_skel, meta##_pytype); \
} while (0)
+#define INITTYPE(ty, base) INITTYPE_META(ty, base, type)
#define INSERT(name, ob) do { \
PyObject *_o = (PyObject *)(ob); \
DOUINTSZ(DECL_CONVU_)
extern int convmpw(PyObject *, void *);
extern int convuint(PyObject *, void *);
+extern int convk64(PyObject *, void *);
extern int convszt(PyObject *, void *);
extern int convbool(PyObject *, void *);
extern PyObject *abstract_pynew(PyTypeObject *, PyObject *, PyObject *);
extern PyObject *getbool(int);
extern PyObject *getulong(unsigned long);
+extern PyObject *getk64(kludge64);
extern void *newtype(PyTypeObject *, const PyTypeObject *, const char *);
extern PyObject *mkexc(PyObject *, PyObject *, const char *, PyMethodDef *);
extern void typeready(PyTypeObject *);
-extern PyTypeObject *inittype(PyTypeObject *);
+extern PyTypeObject *inittype(PyTypeObject *, PyTypeObject *);
extern void addmethods(const PyMethodDef *);
extern PyMethodDef *donemethods(void);
C(KF_NONSECRET),
C(KF_BURN), C(KF_OPT),
C(EC_XONLY), C(EC_YBIT), C(EC_LSB), C(EC_CMPR), C(EC_EXPLY), C(EC_SORT),
+ C(X25519_KEYSZ), C(X25519_PUBSZ), C(X25519_OUTSZ),
+ C(X448_KEYSZ), C(X448_PUBSZ), C(X448_OUTSZ),
+ C(ED25519_KEYSZ), C(ED25519_PUBSZ), C(ED25519_SIGSZ),
#define ENTRY(tag, val, str) C(KERR_##tag),
KEY_ERRORS(ENTRY)
#undef ENTRY
raise SyntaxError, 'junk at end of string'
return x
+## Some pretty-printing utilities.
+PRINT_SECRETS = False
+def _clsname(me): return type(me).__name__
+def _repr_secret(thing, secretp = True):
+ if not secretp or PRINT_SECRETS: return repr(thing)
+ else: return '#<SECRET>'
+def _pp_str(me, pp, cyclep): pp.text(cyclep and '...' or str(me))
+def _pp_secret(pp, thing, secretp = True):
+ if not secretp or PRINT_SECRETS: pp.pretty(thing)
+ else: pp.text('#<SECRET>')
+def _pp_bgroup(pp, text):
+ ind = len(text)
+ pp.begin_group(ind, text)
+ return ind
+def _pp_bgroup_tyname(pp, obj, open = '('):
+ return _pp_bgroup(pp, _clsname(obj) + open)
+def _pp_kv(pp, k, v, secretp = False):
+ ind = _pp_bgroup(pp, k + ' = ')
+ _pp_secret(pp, v, secretp)
+ pp.end_group(ind, '')
+def _pp_commas(pp, printfn, items):
+ firstp = True
+ for i in items:
+ if firstp: firstp = False
+ else: pp.text(','); pp.breakable()
+ printfn(i)
+def _pp_dict(pp, items):
+ def p((k, v)):
+ pp.begin_group(0)
+ pp.pretty(k)
+ pp.text(':')
+ pp.begin_group(2)
+ pp.breakable()
+ pp.pretty(v)
+ pp.end_group(2)
+ pp.end_group(0)
+ _pp_commas(pp, p, items)
+
###--------------------------------------------------------------------------
### Bytestrings.
def __repr__(me):
return 'bytes(%r)' % hex(me)
_augment(ByteString, _tmp)
+ByteString.__hash__ = str.__hash__
bytes = ByteString.fromhex
+###--------------------------------------------------------------------------
+### Hashing.
+
+class _tmp:
+ def check(me, h):
+ hh = me.done()
+ return ctstreq(h, hh)
+_augment(GHash, _tmp)
+_augment(Poly1305Hash, _tmp)
+
+###--------------------------------------------------------------------------
+### NaCl `secretbox'.
+
+def secret_box(k, n, m):
+ E = xsalsa20(k).setiv(n)
+ r = E.enczero(poly1305.keysz.default)
+ s = E.enczero(poly1305.masksz)
+ y = E.encrypt(m)
+ t = poly1305(r)(s).hash(y).done()
+ return ByteString(t + y)
+
+def secret_unbox(k, n, c):
+ E = xsalsa20(k).setiv(n)
+ r = E.enczero(poly1305.keysz.default)
+ s = E.enczero(poly1305.masksz)
+ y = c[poly1305.tagsz:]
+ if not poly1305(r)(s).hash(y).check(c[0:poly1305.tagsz]):
+ raise ValueError, 'decryption failed'
+ return E.decrypt(c[poly1305.tagsz:])
+
###--------------------------------------------------------------------------
### Multiprecision integers and binary polynomials.
@property
def denom(me): return me._d
def __str__(me): return '%s/%s' % (me._n, me._d)
- def __repr__(me): return '%s(%s, %s)' % (type(me).__name__, me._n, me._d)
+ def __repr__(me): return '%s(%s, %s)' % (_clsname(me), me._n, me._d)
+ _repr_pretty_ = _pp_str
def __add__(me, you):
n, d = _split_rat(you)
def reduce(x): return MPReduce(x)
def __div__(me, you): return IntRat(me, you)
def __rdiv__(me, you): return IntRat(you, me)
+ _repr_pretty_ = _pp_str
_augment(MP, _tmp)
class _tmp:
def quadsolve(x, y): return x.reduce().quadsolve(y)
def __div__(me, you): return GFRat(me, you)
def __rdiv__(me, you): return GFRat(you, me)
+ _repr_pretty_ = _pp_str
_augment(GF, _tmp)
class _tmp:
_augment(Field, _tmp)
class _tmp:
- def __repr__(me): return '%s(%sL)' % (type(me).__name__, me.p)
+ def __repr__(me): return '%s(%sL)' % (_clsname(me), me.p)
def __hash__(me): return 0x114401de ^ hash(me.p)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep: pp.text('...')
+ else: pp.pretty(me.p)
+ pp.end_group(ind, ')')
def ec(me, a, b): return ECPrimeProjCurve(me, a, b)
_augment(PrimeField, _tmp)
class _tmp:
- def __repr__(me): return '%s(%sL)' % (type(me).__name__, hex(me.p))
+ def __repr__(me): return '%s(%#xL)' % (_clsname(me), me.p)
def ec(me, a, b): return ECBinProjCurve(me, a, b)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep: pp.text('...')
+ else: pp.text('%#x' % me.p)
+ pp.end_group(ind, ')')
_augment(BinField, _tmp)
class _tmp:
class _tmp:
def __str__(me): return str(me.value)
def __repr__(me): return '%s(%s)' % (repr(me.field), repr(me.value))
+ _repr_pretty_ = _pp_str
_augment(FE, _tmp)
###--------------------------------------------------------------------------
class _tmp:
def __repr__(me):
- return '%s(%r, %s, %s)' % (type(me).__name__, me.field, me.a, me.b)
+ return '%s(%r, %s, %s)' % (_clsname(me), me.field, me.a, me.b)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ pp.pretty(me.field); pp.text(','); pp.breakable()
+ pp.pretty(me.a); pp.text(','); pp.breakable()
+ pp.pretty(me.b)
+ pp.end_group(ind, ')')
def frombuf(me, s):
return ecpt.frombuf(me, s)
def fromraw(me, s):
class _tmp:
def __repr__(me):
- if not me: return 'ECPt()'
- return 'ECPt(%s, %s)' % (me.ix, me.iy)
+ if not me: return '%s()' % _clsname(me)
+ return '%s(%s, %s)' % (_clsname(me), me.ix, me.iy)
def __str__(me):
if not me: return 'inf'
return '(%s, %s)' % (me.ix, me.iy)
+ def _repr_pretty_(me, pp, cyclep):
+ if cyclep:
+ pp.text('...')
+ elif not me:
+ pp.text('inf')
+ else:
+ ind = _pp_bgroup(pp, '(')
+ pp.pretty(me.ix); pp.text(','); pp.breakable()
+ pp.pretty(me.iy)
+ pp.end_group(ind, ')')
_augment(ECPt, _tmp)
class _tmp:
def __repr__(me):
- return 'ECInfo(curve = %r, G = %r, r = %s, h = %s)' % \
- (me.curve, me.G, me.r, me.h)
+ return '%s(curve = %r, G = %r, r = %s, h = %s)' % \
+ (_clsname(me), me.curve, me.G, me.r, me.h)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ _pp_kv(pp, 'curve', me.curve); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'G', me.G); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'r', me.r); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'h', me.h)
+ pp.end_group(ind, ')')
def __hash__(me):
h = 0x9bedb8de
h ^= hash(me.curve)
def __str__(me):
if not me: return 'inf'
return '(%s, %s)' % (me.x, me.y)
+ def _repr_pretty_(me, pp, cyclep):
+ if cyclep:
+ pp.text('...')
+ elif not me:
+ pp.text('inf')
+ else:
+ ind = _pp_bgroup(pp, '(')
+ pp.pretty(me.x); pp.text(','); pp.breakable()
+ pp.pretty(me.y)
+ pp.end_group(ind, ')')
_augment(ECPtCurve, _tmp)
###--------------------------------------------------------------------------
### Key sizes.
class _tmp:
- def __repr__(me): return 'KeySZAny(%d)' % me.default
+ def __repr__(me): return '%s(%d)' % (_clsname(me), me.default)
def check(me, sz): return True
def best(me, sz): return sz
_augment(KeySZAny, _tmp)
class _tmp:
def __repr__(me):
- return 'KeySZRange(%d, %d, %d, %d)' % \
- (me.default, me.min, me.max, me.mod)
+ return '%s(%d, %d, %d, %d)' % \
+ (_clsname(me), me.default, me.min, me.max, me.mod)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ pp.pretty(me.default); pp.text(','); pp.breakable()
+ pp.pretty(me.min); pp.text(','); pp.breakable()
+ pp.pretty(me.max); pp.text(','); pp.breakable()
+ pp.pretty(me.mod)
+ pp.end_group(ind, ')')
def check(me, sz): return me.min <= sz <= me.max and sz % me.mod == 0
def best(me, sz):
if sz < me.min: raise ValueError, 'key too small'
_augment(KeySZRange, _tmp)
class _tmp:
- def __repr__(me): return 'KeySZSet(%d, %s)' % (me.default, me.set)
+ def __repr__(me): return '%s(%d, %s)' % (_clsname(me), me.default, me.set)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ pp.pretty(me.default); pp.text(','); pp.breakable()
+ ind1 = _pp_bgroup(pp, '{')
+ _pp_commas(pp, pp.pretty, me.set)
+ pp.end_group(ind1, '}')
+ pp.end_group(ind, ')')
def check(me, sz): return sz in me.set
def best(me, sz):
found = -1
return found
_augment(KeySZSet, _tmp)
+###--------------------------------------------------------------------------
+### Key data objects.
+
+class _tmp:
+ def __repr__(me): return '%s(%r)' % (_clsname(me), me.name)
+_augment(KeyFile, _tmp)
+
+class _tmp:
+ def __repr__(me): return '%s(%r)' % (_clsname(me), me.fulltag)
+_augment(Key, _tmp)
+
+class _tmp:
+ def __repr__(me):
+ return '%s({%s})' % (_clsname(me),
+ ', '.join(['%r: %r' % kv for kv in me.iteritems()]))
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep: pp.text('...')
+ else: _pp_dict(pp, me.iteritems())
+ pp.end_group(ind, ')')
+_augment(KeyAttributes, _tmp)
+
+class _tmp:
+ def __repr__(me):
+ return '%s(%s, %r)' % (_clsname(me),
+ _repr_secret(me._guts(),
+ not (me.flags & KF_NONSECRET)),
+ me.writeflags(me.flags))
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ _pp_secret(pp, me._guts(), not (me.flags & KF_NONSECRET))
+ pp.text(','); pp.breakable()
+ pp.pretty(me.writeflags(me.flags))
+ pp.end_group(ind, ')')
+_augment(KeyData, _tmp)
+
+class _tmp:
+ def _guts(me): return me.bin
+_augment(KeyDataBinary, _tmp)
+
+class _tmp:
+ def _guts(me): return me.ct
+_augment(KeyDataEncrypted, _tmp)
+
+class _tmp:
+ def _guts(me): return me.mp
+_augment(KeyDataMP, _tmp)
+
+class _tmp:
+ def _guts(me): return me.str
+_augment(KeyDataString, _tmp)
+
+class _tmp:
+ def _guts(me): return me.ecpt
+_augment(KeyDataECPt, _tmp)
+
+class _tmp:
+ def __repr__(me):
+ return '%s({%s})' % (_clsname(me),
+ ', '.join(['%r: %r' % kv for kv in me.iteritems()]))
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me, '({ ')
+ if cyclep: pp.text('...')
+ else: _pp_dict(pp, me.iteritems())
+ pp.end_group(ind, ' })')
+_augment(KeyDataStructured, _tmp)
+
###--------------------------------------------------------------------------
### Abstract groups.
class _tmp:
def __repr__(me):
- return '%s(p = %s, r = %s, g = %s)' % \
- (type(me).__name__, me.p, me.r, me.g)
+ return '%s(p = %s, r = %s, g = %s)' % (_clsname(me), me.p, me.r, me.g)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ _pp_kv(pp, 'p', me.p); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'r', me.r); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'g', me.g)
+ pp.end_group(ind, ')')
_augment(FGInfo, _tmp)
class _tmp:
class _tmp:
def __repr__(me):
- return '%s(%r)' % (type(me).__name__, me.info)
+ return '%s(%r)' % (_clsname(me), me.info)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep: pp.text('...')
+ else: pp.pretty(me.info)
+ pp.end_group(ind, ')')
_augment(Group, _tmp)
class _tmp:
h ^= 2*hash(info.r) & 0xffffffff
h ^= 5*hash(info.g) & 0xffffffff
return h
+ def _get_geval(me, x): return MP(x)
_augment(PrimeGroup, _tmp)
class _tmp:
h ^= 2*hash(info.r) & 0xffffffff
h ^= 5*hash(info.g) & 0xffffffff
return h
+ def _get_geval(me, x): return GF(x)
_augment(BinGroup, _tmp)
class _tmp:
def __hash__(me): return 0x0ec23dab ^ hash(me.info)
+ def _get_geval(me, x): return x.toec()
_augment(ECGroup, _tmp)
class _tmp:
def __repr__(me):
return '%r(%r)' % (me.group, str(me))
+ def _repr_pretty_(me, pp, cyclep):
+ pp.pretty(type(me)._get_geval(me))
_augment(GE, _tmp)
###--------------------------------------------------------------------------
return x is None or x == msg
except ValueError:
return False
+ def __repr__(me):
+ return '%s(n = %r, e = %r)' % (_clsname(me), me.n, me.e)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ _pp_kv(pp, 'n', me.n); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'e', me.e)
+ pp.end_group(ind, ')')
_augment(RSAPub, _tmp)
class _tmp:
def decrypt(me, ct, enc): return enc.decode(me.privop(ct), me.n.nbits)
def sign(me, msg, enc): return me.privop(enc.encode(msg, me.n.nbits))
+ def __repr__(me):
+ return '%s(n = %r, e = %r, d = %s, ' \
+ 'p = %s, q = %s, dp = %s, dq = %s, q_inv = %s)' % \
+ (_clsname(me), me.n, me.e,
+ _repr_secret(me.d), _repr_secret(me.p), _repr_secret(me.q),
+ _repr_secret(me.dp), _repr_secret(me.dq), _repr_secret(me.q_inv))
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ _pp_kv(pp, 'n', me.n); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'e', me.e); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'd', me.d, secretp = True); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'p', me.p, secretp = True); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'q', me.q, secretp = True); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'dp', me.dp, secretp = True); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'dq', me.dq, secretp = True); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'q_inv', me.q_inv, secretp = True)
+ pp.end_group(ind, ')')
_augment(RSAPriv, _tmp)
+###--------------------------------------------------------------------------
+### DSA and related schemes.
+
+class _tmp:
+ def __repr__(me): return '%s(G = %r, p = %r)' % (_clsname(me), me.G, me.p)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ _pp_kv(pp, 'G', me.G); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'p', me.p)
+ pp.end_group(ind, ')')
+_augment(DSAPub, _tmp)
+_augment(KCDSAPub, _tmp)
+
+class _tmp:
+ def __repr__(me): return '%s(G = %r, u = %s, p = %r)' % \
+ (_clsname(me), me.G, _repr_secret(me.u), me.p)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ _pp_kv(pp, 'G', me.G); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'u', me.u, True); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'p', me.p)
+ pp.end_group(ind, ')')
+_augment(DSAPriv, _tmp)
+_augment(KCDSAPriv, _tmp)
+
+###--------------------------------------------------------------------------
+### Bernstein's elliptic curve crypto and related schemes.
+
+X25519_BASE = \
+ bytes('0900000000000000000000000000000000000000000000000000000000000000')
+
+X448_BASE = \
+ bytes('05000000000000000000000000000000000000000000000000000000'
+ '00000000000000000000000000000000000000000000000000000000')
+
+Z128 = bytes('00000000000000000000000000000000')
+
+class _BoxyPub (object):
+ def __init__(me, pub, *kw, **kwargs):
+ if len(pub) != me._PUBSZ: raise ValueError, 'bad public key'
+ super(_BoxyPub, me).__init__(*kw, **kwargs)
+ me.pub = pub
+ def __repr__(me): return '%s(pub = %r)' % (_clsname(me), me.pub)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ _pp_kv(pp, 'pub', me.pub)
+ pp.end_group(ind, ')')
+
+class _BoxyPriv (_BoxyPub):
+ def __init__(me, priv, pub = None, *kw, **kwargs):
+ if len(priv) != me._KEYSZ: raise ValueError, 'bad private key'
+ if pub is None: pub = me._op(priv, me._BASE)
+ super(_BoxyPriv, me).__init__(pub = pub, *kw, **kwargs)
+ me.priv = priv
+ def agree(me, you): return me._op(me.priv, you.pub)
+ def boxkey(me, recip):
+ return me._hashkey(me.agree(recip))
+ def box(me, recip, n, m):
+ return secret_box(me.boxkey(recip), n, m)
+ def unbox(me, recip, n, c):
+ return secret_unbox(me.boxkey(recip, n, c))
+ def __repr__(me): return '%s(priv = %s, pub = %r)' % \
+ (_clsname(me), _repr_secret(me.priv), me.pub)
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup_tyname(pp, me)
+ if cyclep:
+ pp.text('...')
+ else:
+ _pp_kv(pp, 'priv', me.priv, True); pp.text(','); pp.breakable()
+ _pp_kv(pp, 'pub', me.pub)
+ pp.end_group(ind, ')')
+
+class X25519Pub (_BoxyPub):
+ _PUBSZ = X25519_PUBSZ
+ _BASE = X25519_BASE
+
+class X25519Priv (_BoxyPriv, X25519Pub):
+ _KEYSZ = X25519_KEYSZ
+ def _op(me, k, X): return x25519(k, X)
+ def _hashkey(me, z): return hsalsa20_prf(z, Z128)
+
+class X448Pub (_BoxyPub):
+ _PUBSZ = X448_PUBSZ
+ _BASE = X448_BASE
+
+class X448Priv (_BoxyPriv, X448Pub):
+ _KEYSZ = X448_KEYSZ
+ def _op(me, k, X): return x448(k, X)
+ ##def _hashkey(me, z): return ???
+
+class Ed25519Pub (object):
+ def __init__(me, pub):
+ me.pub = pub
+ def verify(me, msg, sig):
+ return ed25519_verify(me.pub, msg, sig)
+
+class Ed25519Priv (Ed25519Pub):
+ def __init__(me, priv):
+ me.priv = priv
+ Ed25519Pub.__init__(me, ed25519_pubkey(priv))
+ def sign(me, msg):
+ return ed25519_sign(me.priv, msg, pub = me.pub)
+ @classmethod
+ def generate(cls, rng = rand):
+ return cls(rng.block(ED25519_KEYSZ))
+
###--------------------------------------------------------------------------
### Built-in named curves and prime groups.
def __init__(me, map, nth):
me.map = map
me.nth = nth
- me.i = [None] * (max(map.values()) + 1)
+ me._n = max(map.values()) + 1
+ me.i = me._n*[None]
def __repr__(me):
- return '{%s}' % ', '.join(['%r: %r' % (k, me[k]) for k in me])
+ return '{%s}' % ', '.join(['%r: %r' % kv for kv in me.iteritems()])
+ def _repr_pretty_(me, pp, cyclep):
+ ind = _pp_bgroup(pp, '{ ')
+ if cyclep: pp.text('...')
+ else: _pp_dict(pp, me.iteritems())
+ pp.end_group(ind, ' }')
+ def __len__(me):
+ return me._n
def __contains__(me, k):
return k in me.map
def __getitem__(me, k):
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
static PyObject *meth__ECPtCurve_fromraw(PyObject *me, PyObject *arg)
{
char *p;
- int len;
+ Py_ssize_t len;
buf b;
PyObject *rc = 0;
ec_curve *cc;
PyObject *arg, PyObject *kw)
{
char *p;
- int len;
+ Py_ssize_t len;
buf b;
PyObject *rc = 0;
ec_curve *cc;
{
buf b;
char *p;
- int sz;
+ Py_ssize_t sz;
PyObject *rc = 0;
ec pp = EC_INIT;
unsigned steps = 0;
dsa_seed ds;
char *k;
- int ksz;
+ Py_ssize_t ksz;
pgev evt = { 0 };
char *kwlist[] =
{ "class", "pbits", "qbits", "seed", "event", "nsteps", 0 };
PyTypeObject *ge_pytype, *group_pytype;
PyTypeObject *primegroup_pytype, *bingroup_pytype, *ecgroup_pytype;
-#ifdef GROUP_GUTS_MPSTRUCT
-# define GG_GEN(gg) ((gg)->gen.x)
-#else
-# define GG_GEN(gg) ((gg)->gen)
-#endif
-
group *group_copy(group *g)
{
if (strcmp(G_NAME(g), "prime") == 0) {
static PyObject *gemeth_toec(PyObject *me, PyObject *arg, PyObject *kw)
{
char *kwlist[] = { "curve", 0 };
- PyTypeObject *cty = ecpt_pytype;
+ PyTypeObject *cty = 0;
+ PyObject *rc = 0;
+ group *g;
+ ec_curve *c;
ec p = EC_INIT;
if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:toec", kwlist,
&cty)) goto end;
- if (!PyType_Check(cty) || !PyType_IsSubtype(cty, ecpt_pytype))
- TYERR("want subtype of catacomb.ECPt");
- if (G_TOEC(GE_G(me), &p, GE_X(me)))
+ g = GROUP_G(GE_GOBJ(me));
+ if (cty) {
+ if (!PyType_Check(cty) || !PyType_IsSubtype(cty, ecpt_pytype))
+ TYERR("want subtype of catacomb.ECPt");
+ Py_INCREF((PyObject *)cty);
+ } else if (strcmp(G_NAME(g), "ec") == 0) {
+ c = eccurve_copy(((gctx_ec *)g)->ei.c);
+ cty = (PyTypeObject *)eccurve_pywrap(0, c);
+ } else {
+ cty = ecpt_pytype;
+ Py_INCREF((PyObject *)cty);
+ }
+ if (G_TOEC(GE_G(me), &p, GE_X(me))) {
+ Py_DECREF((PyObject *)cty);
TYERR("can't convert to ec point");
- return (ecpt_pywrapout(cty, &p));
+ }
+ rc = ecpt_pywrapout(cty, &p);
+ Py_DECREF((PyObject *)cty);
end:
- return (0);
+ return (rc);
}
static PyObject *gemeth_tobuf(PyObject *me, PyObject *arg)
{
buf b;
char *p;
- int n;
+ Py_ssize_t n;
group *g;
ge *x = 0;
{
buf b;
char *p;
- int n;
+ Py_ssize_t n;
group *g;
ge *x = 0;
{
mptext_stringctx sc;
char *p;
- int n;
+ Py_ssize_t n;
group *g;
ge *x = 0;
if (G_READ(g, x, &mptext_stringops, &sc))
VALERR("bad group element string");
return (Py_BuildValue("(Ns#)", ge_pywrap(me, x),
- sc.buf, (int)(sc.lim - sc.buf)));
+ sc.buf, (Py_ssize_t)(sc.lim - sc.buf)));
end:
if (x) G_DESTROY(g, x);
return (0);
gctx_prime *gg = (gctx_prime *)GROUP_G(me);
dp.p = MP_COPY(gg->mm.m);
dp.q = MP_COPY(gg->g.r);
- dp.g = mpmont_reduce(&gg->mm, MP_NEW, GG_GEN(gg));
+ dp.g = mpmont_reduce(&gg->mm, MP_NEW, gg->gen.x);
return (fginfo_pywrap(&dp, dhinfo_pytype));
}
gctx_bin *gg = (gctx_bin *)GROUP_G(me);
dp.p = MP_COPY(gg->r.p);
dp.q = MP_COPY(gg->g.r);
- dp.g = MP_COPY(GG_GEN(gg));
+ dp.g = MP_COPY(gg->gen.x);
return (fginfo_pywrap(&dp, bindhinfo_pytype));
}
static PyObject *kdmeth_lock(PyObject *me, PyObject *arg)
{
char *p;
- int n;
+ Py_ssize_t n;
PyObject *rc = 0;
key_data *kd;
static PyObject *meth__KeyData_decode(PyObject *me, PyObject *arg)
{
const char *p;
- int n;
+ Py_ssize_t n;
key_data *kd;
PyObject *rc = 0;
PyObject *arg, PyObject *kw)
{
char *p;
- int n;
+ Py_ssize_t n;
unsigned f = 0;
keydata_pyobj *me = 0;
static char *kwlist[] = { "key", "flags", 0 };
PyObject *arg, PyObject *kw)
{
char *p;
- int n;
+ Py_ssize_t n;
unsigned f = 0;
keydata_pyobj *me = 0;
static char *kwlist[] = { "key", "flags", 0 };
static PyObject *kdemeth_lock(PyObject *me, PyObject *arg)
{
char *hunoz;
- int hukairz;
+ Py_ssize_t hukairz;
if (!PyArg_ParseTuple(arg, "s#:lock", &hunoz, &hukairz)) goto end;
KEYERR(KERR_WRONGTYPE);
end:
static PyObject *kdemeth_unlock(PyObject *me, PyObject *arg)
{
char *p;
- int n;
+ Py_ssize_t n;
int err;
PyObject *rc = 0;
key_data *kd;
}
key_incref(*kd);
rc = Py_BuildValue("(s#NN)",
- d.buf, d.len,
+ d.buf, (Py_ssize_t)d.len,
key_pywrap(me, k),
keydata_pywrap(okd));
end:
{ \
buf b; \
char *p; \
- int sz; \
+ Py_ssize_t sz; \
PyObject *rc = 0; \
mp *x; \
\
{
int r = 0;
char *p;
- int len;
+ Py_ssize_t len;
PyObject *z = 0;
mp *zz;
mptext_stringctx sc;
sc.buf = p; sc.lim = p + len;
if ((zz = mp_read(MP_NEW, r, &mptext_stringops, &sc)) == 0)
VALERR("bad integer");
- z = Py_BuildValue("(Ns#)", mp_pywrap(zz), sc.buf, (int)(sc.lim - sc.buf));
+ z = Py_BuildValue("(Ns#)", mp_pywrap(zz),
+ sc.buf, (Py_ssize_t)(sc.lim - sc.buf));
end:
return (z);
}
static PyObject *meth__##py##_##name(PyObject *me, PyObject *arg) \
{ \
char *p; \
- int len; \
+ Py_ssize_t len; \
if (!PyArg_ParseTuple(arg, "Os#:" #name, &me, &p, &len)) return (0); \
return (pre##_pywrap(mp_##name(MP_NEW, p, len))); \
}
{
int r = 0;
char *p;
- int len;
+ Py_ssize_t len;
PyObject *z = 0;
mp *zz;
mptext_stringctx sc;
if (zz) MP_DROP(zz);
VALERR("bad binary polynomial");
}
- z = Py_BuildValue("(Ns#)", gf_pywrap(zz), sc.buf, (int)(sc.lim - sc.buf));
+ z = Py_BuildValue("(Ns#)", gf_pywrap(zz),
+ sc.buf, (Py_ssize_t)(sc.lim - sc.buf));
end:
return (z);
}
}
static PyObject *dsa_setup(PyTypeObject *ty, PyObject *G, PyObject *u,
- PyObject *p, PyObject *rng, PyObject *hash)
+ PyObject *p, PyObject *rng, PyObject *hash,
+ void (*calcpub)(group *, ge *, mp *))
{
dsa_pyobj *g;
+ ge *pp;
g = PyObject_New(dsa_pyobj, ty);
- if (GROUP_G(G) != GE_G(p) && !group_samep(GROUP_G(G), GE_G(p)))
- TYERR("public key not from group");
+ if (p) Py_INCREF(p);
if (!u) {
g->d.u = 0;
u = Py_None;
} else if ((g->d.u = getmp(u)) == 0)
goto end;
+ if (!p) {
+ assert(g->d.u); assert(calcpub);
+ pp = G_CREATE(GROUP_G(G));
+ calcpub(GROUP_G(G), pp, g->d.u);
+ p = ge_pywrap(G, pp);
+ } else if (GROUP_G(G) != GE_G(p) && !group_samep(GROUP_G(G), GE_G(p)))
+ TYERR("public key not from group");
g->d.g = GROUP_G(G);
g->d.p = GE_X(p);
g->d.r = GRAND_R(rng);
g->d.h = GCHASH_CH(hash);
- g->G = G; Py_INCREF(G); g->u = u; Py_INCREF(u); g->p = p; Py_INCREF(p);
+ g->G = G; Py_INCREF(G); g->u = u; Py_INCREF(u); g->p = p;
g->rng = rng; Py_INCREF(rng); g->hash = hash; Py_INCREF(hash);
return ((PyObject *)g);
end:
+ if (p) Py_DECREF(p);
FREEOBJ(g);
return (0);
}
static PyObject *dsapub_pynew(PyTypeObject *ty,
PyObject *arg, PyObject *kw)
{
- PyObject *G, *p, *u = 0, *rng = rand_pyobj, *hash = sha_pyobj;
+ PyObject *G, *p, *rng = rand_pyobj, *hash = sha_pyobj;
PyObject *rc = 0;
- char *kwlist[] = { "G", "p", "u", "hash", "rng", 0 };
+ char *kwlist[] = { "G", "p", "hash", "rng", 0 };
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|OO!O!:new", kwlist,
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|O!O!:new", kwlist,
group_pytype, &G,
ge_pytype, &p,
- &u,
gchash_pytype, &hash,
grand_pytype, &rng) ||
- (rc = dsa_setup(dsapub_pytype, G, u, p, rng, hash)) == 0)
+ (rc = dsa_setup(dsapub_pytype, G, 0, p, rng, hash, 0)) == 0)
goto end;
end:
return (rc);
{
gdsa_sig s = GDSA_SIG_INIT;
char *p;
- int n;
+ Py_ssize_t n;
mp *k = 0;
PyObject *rc = 0;
char *kwlist[] = { "msg", "k", 0 };
static PyObject *dsameth_verify(PyObject *me, PyObject *arg)
{
char *p;
- int n;
+ Py_ssize_t n;
gdsa_sig s = GDSA_SIG_INIT;
PyObject *rc = 0;
return (rc);
}
+static void dsa_calcpub(group *g, ge *p, mp *u) { G_EXP(g, p, g->g, u); }
+
static PyObject *dsapriv_pynew(PyTypeObject *ty,
PyObject *arg, PyObject *kw)
{
- PyObject *G, *p, *u = Py_None, *rng = rand_pyobj, *hash = sha_pyobj;
+ PyObject *G, *p = 0, *u, *rng = rand_pyobj, *hash = sha_pyobj;
PyObject *rc = 0;
- char *kwlist[] = { "G", "p", "u", "hash", "rng", 0 };
+ char *kwlist[] = { "G", "u", "p", "hash", "rng", 0 };
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!O|O!O!:new", kwlist,
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O|O!O!O!:new", kwlist,
group_pytype, &G,
- ge_pytype, &p,
&u,
+ ge_pytype, &p,
gchash_pytype, &hash,
grand_pytype, &rng) ||
- (rc = dsa_setup(dsapriv_pytype, G, u, p, rng, hash)) == 0)
+ (rc = dsa_setup(dsapriv_pytype, G, u, p, rng, hash, dsa_calcpub)) == 0)
goto end;
end:
return (rc);
static PyObject *kcdsapub_pynew(PyTypeObject *ty,
PyObject *arg, PyObject *kw)
{
- PyObject *G, *p, *u = 0, *rng = rand_pyobj, *hash = has160_pyobj;
+ PyObject *G, *p, *rng = rand_pyobj, *hash = has160_pyobj;
PyObject *rc = 0;
- char *kwlist[] = { "G", "p", "u", "hash", "rng", 0 };
+ char *kwlist[] = { "G", "p", "hash", "rng", 0 };
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!O|O!O!:new", kwlist,
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|O!O!:new", kwlist,
group_pytype, &G,
ge_pytype, &p,
- &u,
gchash_pytype, &hash,
grand_pytype, &rng) ||
- (rc = dsa_setup(kcdsapub_pytype, G, u, p, rng, hash)) == 0)
+ (rc = dsa_setup(kcdsapub_pytype, G, 0, p, rng, hash, 0)) == 0)
goto end;
end:
return (rc);
}
+static void kcdsa_calcpub(group *g, ge *p, mp *u)
+{
+ mp *uinv = mp_modinv(MP_NEW, u, g->r);
+ G_EXP(g, p, g->g, uinv);
+ mp_drop(uinv);
+}
+
static PyObject *kcdsapriv_pynew(PyTypeObject *ty,
PyObject *arg, PyObject *kw)
{
- PyObject *G, *p, *u = Py_None, *rng = rand_pyobj, *hash = has160_pyobj;
+ PyObject *G, *u, *p = 0, *rng = rand_pyobj, *hash = has160_pyobj;
PyObject *rc = 0;
char *kwlist[] = { "G", "p", "u", "hash", "rng", 0 };
- if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|OO!O!:new", kwlist,
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O|O!O!O!:new", kwlist,
group_pytype, &G,
- ge_pytype, &p,
&u,
+ ge_pytype, &p,
gchash_pytype, &hash,
grand_pytype, &rng) ||
- (rc = dsa_setup(kcdsapriv_pytype, G, u, p, rng, hash)) == 0)
+ (rc = dsa_setup(kcdsapriv_pytype, G, u, p,
+ rng, hash, kcdsa_calcpub)) == 0)
goto end;
end:
return (rc);
{
gkcdsa_sig s = GKCDSA_SIG_INIT;
char *p;
- int n;
+ Py_ssize_t n;
mp *k = 0;
PyObject *r = 0, *rc = 0;
char *kwlist[] = { "msg", "k", 0 };
static PyObject *kcdsameth_verify(PyObject *me, PyObject *arg)
{
char *p;
- int n, rn;
+ Py_ssize_t n, rn;
gkcdsa_sig s = GKCDSA_SIG_INIT;
PyObject *rc = 0;
{
pkcs1 p1;
char *m, *ep;
- int msz, epsz;
+ Py_ssize_t msz, epsz;
unsigned long nbits;
PyObject *rc = 0;
octet *b = 0;
{
pkcs1 p1;
char *ep;
- int epsz;
+ Py_ssize_t epsz;
unsigned long nbits;
int n;
PyObject *rc = 0;
{
pkcs1 p1;
char *m, *ep;
- int msz, epsz;
+ Py_ssize_t msz, epsz;
unsigned long nbits;
PyObject *rc = 0;
octet *b = 0;
{
pkcs1 p1;
char *ep;
- int epsz;
+ Py_ssize_t epsz;
unsigned long nbits;
int n;
PyObject *hukairz;
{
oaep o;
char *m, *ep;
- int msz, epsz;
+ Py_ssize_t msz, epsz;
unsigned long nbits;
PyObject *rc = 0;
octet *b = 0;
{
oaep o;
char *ep;
- int epsz;
+ Py_ssize_t epsz;
unsigned long nbits;
int n;
PyObject *rc = 0;
{
pss p;
char *m;
- int msz;
+ Py_ssize_t msz;
unsigned long nbits;
PyObject *rc = 0;
octet *b = 0;
{
pss p;
char *m;
- int msz;
+ Py_ssize_t msz;
unsigned long nbits;
PyObject *rc = 0;
octet *b = 0;
return (rc);
}
+/*----- X25519 and related algorithms -------------------------------------*/
+
+static PyObject *meth_x25519(PyObject *me, PyObject *arg)
+{
+ const char *k, *p;
+ Py_ssize_t ksz, psz;
+ PyObject *rc = 0;
+ if (!PyArg_ParseTuple(arg, "s#s#:x25519", &k, &ksz, &p, &psz)) goto end;
+ if (ksz != X25519_KEYSZ) VALERR("bad key length");
+ if (psz != X25519_PUBSZ) VALERR("bad public length");
+ rc = bytestring_pywrap(0, X25519_OUTSZ);
+ x25519((octet *)PyString_AS_STRING(rc),
+ (const octet *)k, (const octet *)p);
+ return (rc);
+end:
+ return (0);
+}
+
+static PyObject *meth_x448(PyObject *me, PyObject *arg)
+{
+ const char *k, *p;
+ Py_ssize_t ksz, psz;
+ PyObject *rc = 0;
+ if (!PyArg_ParseTuple(arg, "s#s#:x448", &k, &ksz, &p, &psz)) goto end;
+ if (ksz != X448_KEYSZ) VALERR("bad key length");
+ if (psz != X448_PUBSZ) VALERR("bad public length");
+ rc = bytestring_pywrap(0, X448_OUTSZ);
+ x448((octet *)PyString_AS_STRING(rc),
+ (const octet *)k, (const octet *)p);
+ return (rc);
+end:
+ return (0);
+}
+
+/*----- Ed25519 -----------------------------------------------------------*/
+
+static PyObject *meth_ed25519_pubkey(PyObject *me, PyObject *arg)
+{
+ const char *k;
+ Py_ssize_t ksz;
+ PyObject *rc = 0;
+ if (!PyArg_ParseTuple(arg, "s#:ed25519_pubkey", &k, &ksz)) goto end;
+ rc = bytestring_pywrap(0, ED25519_PUBSZ);
+ ed25519_pubkey((octet *)PyString_AS_STRING(rc), k, ksz);
+ return (rc);
+end:
+ return (0);
+}
+
+static PyObject *meth_ed25519_sign(PyObject *me, PyObject *arg, PyObject *kw)
+{
+ const char *k, *p = 0, *m;
+ Py_ssize_t ksz, psz, msz;
+ PyObject *rc = 0;
+ octet pp[ED25519_PUBSZ];
+ char *kwlist[] = { "key", "msg", "pub", 0 };
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|s#:ed25519_sign", kwlist,
+ &k, &ksz, &m, &msz, &p, &psz))
+ goto end;
+ if (p && psz != ED25519_PUBSZ) VALERR("bad public length");
+ if (!p) { p = (const char *)pp; ed25519_pubkey(pp, k, ksz); }
+ rc = bytestring_pywrap(0, ED25519_SIGSZ);
+ ed25519_sign((octet *)PyString_AS_STRING(rc), k, ksz,
+ (const octet *)p, m, msz);
+ return (rc);
+end:
+ return (0);
+}
+
+static PyObject *meth_ed25519_verify(PyObject *me, PyObject *arg)
+{
+ const char *p, *m, *s;
+ Py_ssize_t psz, msz, ssz;
+ PyObject *rc = 0;
+ if (!PyArg_ParseTuple(arg, "s#s#s#:ed25519_verify",
+ &p, &psz, &m, &msz, &s, &ssz))
+ goto end;
+ if (psz != ED25519_PUBSZ) VALERR("bad public length");
+ if (ssz != ED25519_SIGSZ) VALERR("bad signature length");
+ rc = getbool(!ed25519_verify((const octet *)p, m, msz, (const octet *)s));
+ return (rc);
+end:
+ return (0);
+}
+
/*----- Global stuff ------------------------------------------------------*/
static PyMethodDef methods[] = {
KWMETH(_pss_decode, 0)
KWMETH(_RSAPriv_generate, "\
generate(NBITS, [event = pgen_nullev, rng = rand, nsteps = 0]) -> R")
+ METH (x25519, "\
+x25519(KEY, PUBLIC) -> SHARED")
+ METH (x448, "\
+x448(KEY, PUBLIC) -> SHARED")
+ METH (ed25519_pubkey, "\
+ed25519_pubkey(KEY) -> PUBLIC")
+ KWMETH(ed25519_sign, "\
+ed25519_sign(KEY, MSG, [PUBLIC]) -> SIG")
+ METH (ed25519_verify, "\
+ed25519_verify(PUBLIC, MSG, SIG) -> BOOL")
#undef METHNAME
{ 0 }
};
static PyObject *grmeth_seedblock(PyObject *me, PyObject *arg)
{
char *p;
- int n;
+ Py_ssize_t n;
grand *r = GRAND_R(me);
if (!PyArg_ParseTuple(arg, "s#:seedblock", &p, &n) ||
checkop(r, GRAND_SEEDBLOCK, "seedblock"))
{
grand *r = GRAND_R(me);
char *p, *q;
- int sz;
+ Py_ssize_t sz;
PyObject *rc;
if (!PyArg_ParseTuple(arg, "s#:mask", &p, &sz)) return (0);
static PyObject *trmeth_add(PyObject *me, PyObject *arg)
{
grand *r = GRAND_R(me);
- char *p; int n; unsigned goodbits;
+ char *p; Py_ssize_t 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);
static PyObject *trmeth_key(PyObject *me, PyObject *arg)
{
grand *r = GRAND_R(me);
- char *p; int n;
+ char *p; Py_ssize_t n;
if (!PyArg_ParseTuple(arg, "s#:key", &p, &n)) return (0);
r->ops->misc(r, RAND_KEY, p, (size_t)n);
RETURN_ME;
/*----- Generators from symmetric encryption algorithms -------------------*/
-static PyTypeObject *gccrand_pytype, *gcrand_pytype;
+static PyTypeObject *gccrand_pytype, *gcrand_pytype, *gclatinrand_pytype;
typedef grand *gcrand_func(const void *, size_t sz);
typedef grand *gcirand_func(const void *, size_t sz, uint32);
#define RNGF_INT 1u
#define RNGF_NONCE 2u
+#define RNGF_LATIN 4u
typedef struct gccrand_pyobj {
PyHeapTypeObject ty;
const gccrand_info *info = GCCRAND_INFO(ty);
static char *kwlist[] = { "key", 0 };
char *k;
- int n;
+ Py_ssize_t n;
if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &n))
goto end;
uint32 i = 0;
static char *kwlist[] = { "key", "i", 0 };
char *k;
- int n;
+ Py_ssize_t n;
if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&:new", kwlist,
&k, &n, convu32, &i))
const gccrand_info *info = GCCRAND_INFO(ty);
static char *kwlist[] = { "key", "nonce", 0 };
char *k, *n;
- int ksz, nsz;
+ Py_ssize_t ksz, nsz;
if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#:new", kwlist,
&k, &ksz, &n, &nsz))
gccrand_pyobj *g = newtype(gccrand_pytype, 0, info->name);
g->info = info;
g->ty.ht_type.tp_basicsize = sizeof(grand_pyobj);
- g->ty.ht_type.tp_base = gcrand_pytype;
- Py_INCREF(gcrand_pytype);
+ g->ty.ht_type.tp_base =
+ (info->f & RNGF_LATIN) ? gclatinrand_pytype : gcrand_pytype;
+ Py_INCREF(g->ty.ht_type.tp_base);
g->ty.ht_type.tp_flags = (Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HEAPTYPE);
static PyObject *gccrget_keysz(PyObject *me, void *hunoz)
{ return (keysz_pywrap(GCCRAND_INFO(me)->keysz)); }
+static PyObject *gclrmeth_tell(PyObject *me, PyObject *arg)
+{
+ grand *r = GRAND_R(me);
+ PyObject *rc = 0;
+ kludge64 off;
+
+ if (!PyArg_ParseTuple(arg, ":tell")) return (0);
+ r->ops->misc(r, SALSA20_TELLU64, &off);
+ rc = getk64(off);
+ return (rc);
+}
+
+static PyObject *gclrmeth_seek(PyObject *me, PyObject *arg)
+{
+ grand *r = GRAND_R(me);
+ kludge64 off;
+
+ if (!PyArg_ParseTuple(arg, "O&:seek", convk64, &off)) return (0);
+ r->ops->misc(r, SALSA20_SEEKU64, off);
+ RETURN_ME;
+}
+
static PyGetSetDef gccrand_pygetset[] = {
#define GETSETNAME(op, name) gccr##op##_##name
GET (keysz, "CR.keysz -> acceptable key sizes")
{ 0 }
};
+static PyMethodDef gclatinrand_pymethods[] = {
+#define METHNAME(name) gclrmeth_##name
+ METH (tell, "R.tell() -> OFF")
+ METH (seek, "R.seek(OFF)")
+#undef METHNAME
+ { 0 }
+};
+
static PyTypeObject gccrand_pytype_skel = {
PyObject_HEAD_INIT(0) 0, /* Header */
"GCCRand", /* @tp_name@ */
0 /* @tp_is_gc@ */
};
+static PyTypeObject gclatinrand_pytype_skel = {
+ PyObject_HEAD_INIT(0) 0, /* Header */
+ "GCLatinRand", /* @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@ */
+ gclatinrand_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@ */
+};
+
/*----- SSL and TLS generators --------------------------------------------*/
static PyObject *sslprf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
INITTYPE(tlsprf, grand);
INITTYPE(gccrand, type);
INITTYPE(gcrand, grand);
+ INITTYPE(gclatinrand, gcrand);
rand_noisesrc(RAND_GLOBAL, &noise_source);
rand_seed(RAND_GLOBAL, 160);
addmethods(methods);
INSERT("BBSPriv", bbspriv_pytype);
INSERT("GCCRand", gccrand_pytype);
INSERT("GCRand", gcrand_pytype);
+ INSERT("GCLatinRand", gclatinrand_pytype);
rand_pyobj = grand_pywrap(&rand_global, 0); Py_INCREF(rand_pyobj);
gccrands_dict = gccrands(); Py_INCREF(gccrands_dict);
INSERT("gccrands", gccrands_dict);
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',
PyObject *arg, PyObject *kw)
{
char *p;
- int n;
+ Py_ssize_t n;
unsigned t;
grand *r = &rand_global;
gfshare_pyobj *s;
{
unsigned i;
char *p;
- int n;
+ Py_ssize_t n;
if (!PyArg_ParseTuple(arg, "O&s#:add", convuint, &i, &p, &n)) goto end;
if (i > 254) VALERR("index must be < 255");
if (n != GFSHARE_S(me)->sz) VALERR("bad share size");
return (PyLong_FromUnsignedLong(w));
}
+static PyObject *i32 = 0;
+static int init_i32(void)
+ { if (!i32 && (i32 = PyInt_FromLong(32)) == 0) return (-1); return (0); }
+
+PyObject *getk64(kludge64 u)
+{
+ PyObject *i = 0, *j = 0, *t;
+ PyObject *rc = 0;
+
+ if (init_i32()) goto end;
+ if ((i = PyLong_FromUnsignedLong(HI64(u))) == 0) goto end;
+ if ((t = PyNumber_InPlaceLshift(i, i32)) == 0) goto end;
+ Py_DECREF(i); i = t;
+ if ((j = PyLong_FromUnsignedLong(LO64(u))) == 0) goto end;
+ if ((t = PyNumber_InPlaceOr(i, j)) == 0) goto end;
+ Py_DECREF(i); i = t;
+ if ((rc = PyNumber_Int(i)) == 0) goto end;
+end:
+ if (i) Py_DECREF(i);
+ if (j) Py_DECREF(j);
+ return (rc);
+}
+
PyObject *getbool(int b)
{
if (b) RETURN_TRUE;
return (0);
}
+int convk64(PyObject *o, void *pp)
+{
+ PyObject *i = 0, *t;
+ int rc = 0;
+ uint32 lo, hi;
+
+ if (init_i32()) goto end;
+ if ((i = PyNumber_Int(o)) == 0) goto end;
+ lo = PyInt_AsUnsignedLongMask(i);
+ if ((t = PyNumber_InPlaceRshift(i, i32)) == 0) goto end;
+ Py_DECREF(i); i = t;
+ hi = PyInt_AsUnsignedLongMask(i);
+ if ((t = PyNumber_InPlaceRshift(i, i32)) == 0) goto end;
+ Py_DECREF(i); i = t;
+ if (PyObject_IsTrue(i)) VALERR("out of range");
+ SET64(*(kludge64 *)pp, hi, lo);
+ rc = 1;
+end:
+ if (i) Py_DECREF(i);
+ return (rc);
+}
+
int convmpw(PyObject *o, void *pp)
{
unsigned long u;
PyDict_SetItemString(ty->tp_dict, "__module__", modname);
}
-PyTypeObject *inittype(PyTypeObject *tyskel)
+PyTypeObject *inittype(PyTypeObject *tyskel, PyTypeObject *meta)
{
- PyTypeObject *ty = newtype(&PyType_Type, tyskel, 0);
+ PyTypeObject *ty = newtype(meta, tyskel, 0);
ty->tp_flags |= Py_TPFLAGS_HEAPTYPE;
typeready(ty);
return (ty);
/*----- Exceptions --------------------------------------------------------*/
-PyObject * mkexc(PyObject *mod, PyObject *base,
- const char *name, PyMethodDef *mm)
+PyObject *mkexc(PyObject *mod, PyObject *base,
+ const char *name, PyMethodDef *mm)
{
PyObject *nameobj = 0;
PyObject *dict = 0;