X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/catacomb-python/blobdiff_plain/3aa33042dc760937bb9da54c09f7c668f00eb241..f1b0cf0da6b3bcc530d7f72982278510d94f6456:/pubkey.c diff --git a/pubkey.c b/pubkey.c index ef44845..7374429 100644 --- a/pubkey.c +++ b/pubkey.c @@ -1,13 +1,11 @@ /* -*-c-*- - * - * $Id$ * * Public-key cryptography * * (c) 2004 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of the Python interface to Catacomb. * @@ -15,12 +13,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * Catacomb/Python is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with Catacomb/Python; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -56,26 +54,35 @@ static void dsa_pydealloc(PyObject *me) } 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); - rng = g->rng; Py_INCREF(rng); g->hash = hash; Py_INCREF(hash); + 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); } @@ -83,17 +90,16 @@ end: 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!O!|OO!: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); @@ -122,7 +128,7 @@ static PyObject *dsameth_sign(PyObject *me, PyObject *arg, PyObject *kw) { 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 }; @@ -142,7 +148,7 @@ end: 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; @@ -151,27 +157,29 @@ static PyObject *dsameth_verify(PyObject *me, PyObject *arg) goto end; if (n != DSA_D(me)->h->hashsz) VALERR("bad message length (doesn't match hash size)"); - rc = getbool(gdsa_verify(DSA_D(me), &s, p)); + rc = getbool(!gdsa_verify(DSA_D(me), &s, p)); end: mp_drop(s.r); mp_drop(s.s); 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!OO!: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, p, u, rng, hash)) == 0) + (rc = dsa_setup(dsapriv_pytype, G, u, p, rng, hash, dsa_calcpub)) == 0) goto end; end: return (rc); @@ -198,7 +206,7 @@ static PyMemberDef dsapub_pymembers[] = { MEMBER(G, T_OBJECT, READONLY, "D.G -> group to work in") MEMBER(p, T_OBJECT, READONLY, "D.p -> public key (group element") MEMBER(rng, T_OBJECT, READONLY, "D.rng -> random number generator") - MEMBER(hash, T_OBJECT, READONLY, "D.hash -> hash class") + MEMBER(hash, T_OBJECT, READONLY, "D.hash -> hash class") #undef MEMBERSTRUCT { 0 } }; @@ -211,8 +219,8 @@ static PyMemberDef dsapriv_pymembers[] = { }; static PyTypeObject dsapub_pytype_skel = { - PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */ - "catacomb.DSAPub", /* @tp_name@ */ + PyObject_HEAD_INIT(0) 0, /* Header */ + "DSAPub", /* @tp_name@ */ sizeof(dsa_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -242,7 +250,7 @@ static PyTypeObject dsapub_pytype_skel = { 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ - 0, /* @tp_iternexr@ */ + 0, /* @tp_iternext@ */ dsapub_pymethods, /* @tp_methods@ */ dsapub_pymembers, /* @tp_members@ */ 0, /* @tp_getset@ */ @@ -259,8 +267,8 @@ static PyTypeObject dsapub_pytype_skel = { }; static PyTypeObject dsapriv_pytype_skel = { - PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */ - "catacomb.DSAPriv", /* @tp_name@ */ + PyObject_HEAD_INIT(0) 0, /* Header */ + "DSAPriv", /* @tp_name@ */ sizeof(dsa_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -290,7 +298,7 @@ static PyTypeObject dsapriv_pytype_skel = { 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ - 0, /* @tp_iternexr@ */ + 0, /* @tp_iternext@ */ dsapriv_pymethods, /* @tp_methods@ */ dsapriv_pymembers, /* @tp_members@ */ 0, /* @tp_getset@ */ @@ -309,36 +317,43 @@ static PyTypeObject dsapriv_pytype_skel = { 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!|OO!: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, p, u, 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!|O!OO!: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, p, u, rng, hash)) == 0) + (rc = dsa_setup(kcdsapriv_pytype, G, u, p, + rng, hash, kcdsa_calcpub)) == 0) goto end; end: return (rc); @@ -367,7 +382,7 @@ static PyObject *kcdsameth_sign(PyObject *me, PyObject *arg, PyObject *kw) { 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 }; @@ -378,9 +393,9 @@ static PyObject *kcdsameth_sign(PyObject *me, PyObject *arg, PyObject *kw) if (n != DSA_D(me)->h->hashsz) VALERR("bad message length (doesn't match hash size)"); r = bytestring_pywrap(0, DSA_D(me)->h->hashsz); - s.r = PyString_AS_STRING(r); + s.r = (octet *)PyString_AS_STRING(r); gkcdsa_sign(DSA_D(me), &s, p, k); - rc = Py_BuildValue("(NN)", r, mp_pywrap(s.s)); + rc = Py_BuildValue("(ON)", r, mp_pywrap(s.s)); end: Py_XDECREF(r); mp_drop(k); @@ -390,7 +405,7 @@ end: 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; @@ -401,7 +416,7 @@ static PyObject *kcdsameth_verify(PyObject *me, PyObject *arg) VALERR("bad message length (doesn't match hash size)"); if (rn != DSA_D(me)->h->hashsz) VALERR("bad signature `r' length (doesn't match hash size)"); - rc = getbool(gkcdsa_verify(DSA_D(me), &s, p)); + rc = getbool(!gkcdsa_verify(DSA_D(me), &s, p)); end: mp_drop(s.s); return (rc); @@ -424,8 +439,8 @@ static PyMethodDef kcdsapriv_pymethods[] = { }; static PyTypeObject kcdsapub_pytype_skel = { - PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */ - "catacomb.KCDSAPub", /* @tp_name@ */ + PyObject_HEAD_INIT(0) 0, /* Header */ + "KCDSAPub", /* @tp_name@ */ sizeof(dsa_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -455,7 +470,7 @@ static PyTypeObject kcdsapub_pytype_skel = { 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ - 0, /* @tp_iternexr@ */ + 0, /* @tp_iternext@ */ kcdsapub_pymethods, /* @tp_methods@ */ dsapub_pymembers, /* @tp_members@ */ 0, /* @tp_getset@ */ @@ -472,8 +487,8 @@ static PyTypeObject kcdsapub_pytype_skel = { }; static PyTypeObject kcdsapriv_pytype_skel = { - PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */ - "catacomb.KCDSAPriv", /* @tp_name@ */ + PyObject_HEAD_INIT(0) 0, /* Header */ + "KCDSAPriv", /* @tp_name@ */ sizeof(dsa_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -503,7 +518,7 @@ static PyTypeObject kcdsapriv_pytype_skel = { 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ - 0, /* @tp_iternexr@ */ + 0, /* @tp_iternext@ */ kcdsapriv_pymethods, /* @tp_methods@ */ dsapriv_pymembers, /* @tp_members@ */ 0, /* @tp_getset@ */ @@ -555,6 +570,7 @@ static PyObject *rsapub_pynew(PyTypeObject *ty, if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", kwlist, convmp, &rp.n, convmp, &rp.e)) goto end; + if (!MP_ODDP(rp.n)) VALERR("RSA modulus must be even"); o = (rsapub_pyobj *)ty->tp_alloc(ty, 0); o->pub = rp; rsa_pubcreate(&o->pubctx, &o->pub); @@ -627,6 +643,10 @@ static PyObject *rsapriv_pynew(PyTypeObject *ty, convmp, &rp.q_inv, &rng)) goto end; + if ((rp.n && !MP_ODDP(rp.n)) || + (rp.p && !MP_ODDP(rp.p)) || + (rp.p && !MP_ODDP(rp.q))) + VALERR("RSA modulus and factors must be odd"); if (rsa_recover(&rp)) VALERR("couldn't construct private key"); if (rng != Py_None && !GRAND_PYCHECK(rng)) TYERR("not a random number source"); @@ -670,7 +690,9 @@ static PyObject *rsaget_rng(PyObject *me, void *hunoz) static int rsaset_rng(PyObject *me, PyObject *val, void *hunoz) { int rc = -1; - if (val != Py_None && !GRAND_PYCHECK(val)) + if (!val) + val = Py_None; + else if (val != Py_None && !GRAND_PYCHECK(val)) TYERR("expected grand or None"); Py_DECREF(RSA_RNG(me)); RSA_RNG(me) = val; @@ -758,8 +780,8 @@ static PyMethodDef rsapriv_pymethods[] = { }; static PyTypeObject rsapub_pytype_skel = { - PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */ - "catacomb.RSAPub", /* @tp_name@ */ + PyObject_HEAD_INIT(0) 0, /* Header */ + "RSAPub", /* @tp_name@ */ sizeof(rsapub_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -789,7 +811,7 @@ static PyTypeObject rsapub_pytype_skel = { 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ - 0, /* @tp_iternexr@ */ + 0, /* @tp_iternext@ */ rsapub_pymethods, /* @tp_methods@ */ 0, /* @tp_members@ */ rsapub_pygetset, /* @tp_getset@ */ @@ -806,8 +828,8 @@ static PyTypeObject rsapub_pytype_skel = { }; static PyTypeObject rsapriv_pytype_skel = { - PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */ - "catacomb.RSAPriv", /* @tp_name@ */ + PyObject_HEAD_INIT(0) 0, /* Header */ + "RSAPriv", /* @tp_name@ */ sizeof(rsapriv_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -837,7 +859,7 @@ static PyTypeObject rsapriv_pytype_skel = { 0, /* @tp_richcompare@ */ 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ - 0, /* @tp_iternexr@ */ + 0, /* @tp_iternext@ */ rsapriv_pymethods, /* @tp_methods@ */ 0, /* @tp_members@ */ rsapriv_pygetset, /* @tp_getset@ */ @@ -860,7 +882,7 @@ static PyObject *meth__p1crypt_encode(PyObject *me, { pkcs1 p1; char *m, *ep; - int msz, epsz; + Py_ssize_t msz, epsz; unsigned long nbits; PyObject *rc = 0; octet *b = 0; @@ -889,7 +911,7 @@ static PyObject *meth__p1crypt_decode(PyObject *me, { pkcs1 p1; char *ep; - int epsz; + Py_ssize_t epsz; unsigned long nbits; int n; PyObject *rc = 0; @@ -921,7 +943,7 @@ static PyObject *meth__p1sig_encode(PyObject *me, { pkcs1 p1; char *m, *ep; - int msz, epsz; + Py_ssize_t msz, epsz; unsigned long nbits; PyObject *rc = 0; octet *b = 0; @@ -950,7 +972,7 @@ static PyObject *meth__p1sig_decode(PyObject *me, { pkcs1 p1; char *ep; - int epsz; + Py_ssize_t epsz; unsigned long nbits; int n; PyObject *hukairz; @@ -983,7 +1005,7 @@ static PyObject *meth__oaep_encode(PyObject *me, { oaep o; char *m, *ep; - int msz, epsz; + Py_ssize_t msz, epsz; unsigned long nbits; PyObject *rc = 0; octet *b = 0; @@ -1015,7 +1037,7 @@ static PyObject *meth__oaep_decode(PyObject *me, { oaep o; char *ep; - int epsz; + Py_ssize_t epsz; unsigned long nbits; int n; PyObject *rc = 0; @@ -1050,7 +1072,7 @@ static PyObject *meth__pss_encode(PyObject *me, { pss p; char *m; - int msz; + Py_ssize_t msz; unsigned long nbits; PyObject *rc = 0; octet *b = 0; @@ -1082,7 +1104,7 @@ static PyObject *meth__pss_decode(PyObject *me, { pss p; char *m; - int msz; + Py_ssize_t msz; unsigned long nbits; PyObject *rc = 0; octet *b = 0; @@ -1113,6 +1135,109 @@ end: return (rc); } +/*----- X25519 and related algorithms -------------------------------------*/ + +#define XDHS(_) \ + _(X25519, x25519) \ + _(X448, x448) + +#define DEFXDH(X, x) \ + static PyObject *meth_##x(PyObject *me, PyObject *arg) \ + { \ + const char *k, *p; \ + Py_ssize_t ksz, psz; \ + PyObject *rc = 0; \ + if (!PyArg_ParseTuple(arg, "s#s#:" #x, &k, &ksz, &p, &psz)) \ + goto end; \ + if (ksz != X##_KEYSZ) VALERR("bad key length"); \ + if (psz != X##_PUBSZ) VALERR("bad public length"); \ + rc = bytestring_pywrap(0, X##_OUTSZ); \ + x((octet *)PyString_AS_STRING(rc), \ + (const octet *)k, (const octet *)p); \ + return (rc); \ + end: \ + return (0); \ + } +XDHS(DEFXDH) +#undef DEFXDH + +/*----- Ed25519 and related algorithms ------------------------------------*/ + +#define EDDSAS(_) \ + _(ED25519, ed25519, -1, ctx) + +#define DEFEDDSA(ED, ed, phdflt, sigver) \ + \ + static PyObject *meth_##ed##_pubkey(PyObject *me, PyObject *arg) \ + { \ + const char *k; \ + Py_ssize_t ksz; \ + PyObject *rc = 0; \ + if (!PyArg_ParseTuple(arg, "s#:" #ed "_pubkey", &k, &ksz)) \ + goto end; \ + rc = bytestring_pywrap(0, ED##_PUBSZ); \ + ed##_pubkey((octet *)PyString_AS_STRING(rc), k, ksz); \ + return (rc); \ + end: \ + return (0); \ + } \ + \ + static PyObject *meth_##ed##_sign(PyObject *me, PyObject *arg, \ + PyObject *kw) \ + { \ + const char *k, *p = 0, *c = 0, *m; \ + Py_ssize_t ksz, psz, csz = 0, msz; \ + int ph = phdflt; \ + PyObject *rc = 0; \ + octet pp[ED##_PUBSZ]; \ + char *kwlist[] = { "key", "msg", "pub", "perso", "phflag", 0 }; \ + if (!PyArg_ParseTupleAndKeywords(arg, kw, \ + "s#s#|s#s#O&:" #ed "_sign", \ + kwlist, \ + &k, &ksz, &m, &msz, &p, &psz, \ + &c, &csz, convbool, &ph)) \ + goto end; \ + if (p && psz != ED##_PUBSZ) VALERR("bad public length"); \ + if (c && csz > ED##_MAXPERSOSZ) \ + VALERR("personalization string too long"); \ + if (c && ph == -1) ph = 0; \ + if (!p) { p = (const char *)pp; ed##_pubkey(pp, k, ksz); } \ + rc = bytestring_pywrap(0, ED##_SIGSZ); \ + ed##sigver##_sign((octet *)PyString_AS_STRING(rc), k, ksz, \ + (const octet *)p, ph, c, csz, m, msz); \ + return (rc); \ + end: \ + return (0); \ + } \ + \ + static PyObject *meth_##ed##_verify(PyObject *me, \ + PyObject *arg, PyObject *kw) \ + { \ + const char *p, *c = 0, *m, *s; \ + Py_ssize_t psz, csz = 0, msz, ssz; \ + int ph = phdflt; \ + PyObject *rc = 0; \ + char *kwlist[] = { "pub", "msg", "sig", "perso", "phflag", 0 }; \ + if (!PyArg_ParseTupleAndKeywords(arg, kw, \ + "s#s#s#|s#O&:" #ed "_verify", \ + kwlist, \ + &p, &psz, &m, &msz, &s, &ssz, \ + &c, &csz, convbool, &ph)) \ + goto end; \ + if (psz != ED##_PUBSZ) VALERR("bad public length"); \ + if (ssz != ED##_SIGSZ) VALERR("bad signature length"); \ + if (c && csz > ED##_MAXPERSOSZ) \ + VALERR("personalization string too long"); \ + if (c && ph == -1) ph = 0; \ + rc = getbool(!ed##sigver##_verify((const octet *)p, ph, c, csz, \ + m, msz, (const octet *)s)); \ + return (rc); \ + end: \ + return (0); \ + } +EDDSAS(DEFEDDSA) +#undef DEFEDDSA + /*----- Global stuff ------------------------------------------------------*/ static PyMethodDef methods[] = { @@ -1127,6 +1252,22 @@ static PyMethodDef methods[] = { KWMETH(_pss_decode, 0) KWMETH(_RSAPriv_generate, "\ generate(NBITS, [event = pgen_nullev, rng = rand, nsteps = 0]) -> R") +#define DEFMETH(X, x) \ + METH (x, "\ +" #x "(KEY, PUBLIC) -> SHARED") + XDHS(DEFMETH) +#undef DEFMETH +#define DEFMETH(ED, ed, phdflt, sigver) \ + METH (ed##_pubkey, "\ +" #ed "_pubkey(KEY) -> PUBLIC") \ + KWMETH(ed##_sign, "\ +" #ed "_sign(KEY, MSG, [pub = PUBLIC, " \ + "perso = STRING, phflag = BOOL]) -> SIG") \ + KWMETH(ed##_verify, "\ +" #ed "_verify(PUBLIC, MSG, SIG, " \ + "[perso = STRING, phflag = BOOL]) -> BOOL") + EDDSAS(DEFMETH) +#undef DEFMETH #undef METHNAME { 0 } };