From: Mark Wooding Date: Tue, 26 May 2015 14:13:23 +0000 (+0100) Subject: algorithms.py, rand.c: Support `Latin dances' stream ciphers. X-Git-Tag: 1.1.0~2^2~2 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/catacomb-python/commitdiff_plain/3f4f64b80b775c630201089785c43e1af24060bb algorithms.py, rand.c: Support `Latin dances' stream ciphers. --- diff --git a/algorithms.py b/algorithms.py index 320d060..3ceb207 100644 --- a/algorithms.py +++ b/algorithms.py @@ -29,6 +29,11 @@ ecb cbc cfb ofb counter streamciphers = ''' rc4 seal '''.split() +latindances = ''' +salsa20 salsa20/12 salsa20/8 xsalsa20 xsalsa20/12 xsalsa20/8 +chacha20 chacha12 chacha8 xchacha20 xchacha12 xchacha8 +'''.split() +streamciphers += map(lambda s: s.translate(None, '/'), latindances) hashes = ''' md2 md4 md5 tiger has160 sha sha224 sha256 sha384 sha512 @@ -64,13 +69,24 @@ print print '#define RNGS(_) \\' for i in (cross(prps, ['ofb', 'counter'])): print ('\t_("%(prim)s-%(mode)s", %(prim)s_keysz, ' + - '%(prim)s_%(mode)srand, 0) \\') % \ + '%(prim)s_%(mode)srand, 0, 0) \\') % \ {'prim': i[0], 'mode': i[1]} for i in (cross(hashes, 'mgf')): print ('\t_("%(prim)s-%(mode)s", %(prim)s_%(mode)skeysz, ' + - '%(prim)s_%(mode)srand, 0) \\') % \ + '%(prim)s_%(mode)srand, 0, 0) \\') % \ {'prim': i[0], 'mode': i[1]} -print '\t_("rc4", rc4_keysz, rc4_rand, 0) \\' -print '\t_("seal", seal_keysz, seal_rand, RNGF_INT) \\' +print '\t_("rc4", rc4_keysz, rc4_rand, 0, 0) \\' +print '\t_("seal", seal_keysz, seal_rand, RNGF_INT, 0) \\' +for i in latindances: + for r in ['salsa20', 'xsalsa20', 'chacha', 'xchacha']: + if i.startswith(r): + root = r + break + else: + raise ValueError, 'failed to find root name for %s' % i + print ('\t_("%(name)s", %(root)s_keysz, %(id)s_rand, ' + + 'RNGF_NONCE, %(ROOT)s_NONCESZ) \\') % \ + {'name': i, 'id': i.translate(None, '/'), + 'root': root, 'ROOT': root.upper()} print '\t/* end */' print diff --git a/rand.c b/rand.c index 1c008b7..49aaa38 100644 --- a/rand.c +++ b/rand.c @@ -581,14 +581,17 @@ static PyTypeObject *gccrand_pytype, *gcrand_pytype; typedef grand *gcrand_func(const void *, size_t sz); typedef grand *gcirand_func(const void *, size_t sz, uint32); +typedef grand *gcnrand_func(const void *, size_t sz, const void *); typedef struct gccrand_info { const char *name; const octet *keysz; unsigned f; + size_t noncesz; gcrand_func *func; } gccrand_info; #define RNGF_INT 1u +#define RNGF_NONCE 2u typedef struct gccrand_pyobj { PyHeapTypeObject ty; @@ -596,13 +599,13 @@ typedef struct gccrand_pyobj { } gccrand_pyobj; #define GCCRAND_INFO(o) (((gccrand_pyobj *)(o))->info) -#define GCCRAND_DEF(name, ksz, func, f) \ +#define GCCRAND_DEF(name, ksz, func, f, nsz) \ static const gccrand_info func##_info = \ - { name, ksz, f, (gcrand_func *)func }; + { name, ksz, f, nsz, (gcrand_func *)func }; RNGS(GCCRAND_DEF) static const gccrand_info *const gcrandtab[] = { -#define GCCRAND_ENTRY(name, ksz, func, f) &func##_info, +#define GCCRAND_ENTRY(name, ksz, func, f, nsz) &func##_info, RNGS(GCCRAND_ENTRY) 0 }; @@ -641,6 +644,25 @@ end: return (0); } +static PyObject *gcnrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) +{ + const gccrand_info *info = GCCRAND_INFO(ty); + static char *kwlist[] = { "key", "nonce", 0 }; + char *k, *n; + int ksz, nsz; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#:new", kwlist, + &k, &ksz, &n, &nsz)) + goto end; + if (keysz(ksz, info->keysz) != ksz) VALERR("bad key length"); + if (nsz != info->noncesz) VALERR("bad nonce length"); + return (grand_dopywrap(ty, + ((gcnrand_func *)info->func)(k, ksz, n), + f_freeme)); +end: + return (0); +} + static PyObject *gccrand_pywrap(const gccrand_info *info) { gccrand_pyobj *g = newtype(gccrand_pytype, 0, info->name); @@ -653,10 +675,9 @@ static PyObject *gccrand_pywrap(const gccrand_info *info) Py_TPFLAGS_HEAPTYPE); g->ty.ht_type.tp_alloc = PyType_GenericAlloc; g->ty.ht_type.tp_free = 0; - if (info->f & RNGF_INT) - g->ty.ht_type.tp_new = gcirand_pynew; - else - g->ty.ht_type.tp_new = gcrand_pynew; + if (info->f & RNGF_INT) g->ty.ht_type.tp_new = gcirand_pynew; + else if (info->f & RNGF_NONCE) g->ty.ht_type.tp_new = gcnrand_pynew; + else g->ty.ht_type.tp_new = gcrand_pynew; typeready(&g->ty.ht_type); return ((PyObject *)g); }