chiark / gitweb /
Merge remote-tracking branch 'origin/HEAD'
[catacomb-python] / pubkey.c
index 5611508c976e951d4e7deb1f91358a5e0da3791c..5167a973791f1930f18b4b7831a6ce6d4aa240ea 100644 (file)
--- a/pubkey.c
+++ b/pubkey.c
@@ -65,8 +65,12 @@ static PyObject *dsa_setup(PyTypeObject *ty, PyObject *G, PyObject *u,
   if (!u) {
     g->d.u = 0;
     u = Py_None;
-  } else if ((g->d.u = getmp(u)) == 0)
-    goto end;
+  } else {
+    if ((g->d.u = getmp(u)) == 0)
+      goto end;
+    if (MP_PYCHECK(u)) Py_INCREF(u);
+    else u = mp_pywrap(g->d.u);
+  }
   if (!p) {
     assert(g->d.u); assert(calcpub);
     pp = G_CREATE(GROUP_G(G));
@@ -78,7 +82,7 @@ static PyObject *dsa_setup(PyTypeObject *ty, PyObject *G, PyObject *u,
   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;
+  g->G = G; Py_INCREF(G); g->u = u; g->p = p;
   g->rng = rng; Py_INCREF(rng); g->hash = hash; Py_INCREF(hash);
   return ((PyObject *)g);
 end:
@@ -344,7 +348,7 @@ static PyObject *kcdsapriv_pynew(PyTypeObject *ty,
 {
   PyObject *G, *u, *p = 0, *rng = rand_pyobj, *hash = has160_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,
                                   group_pytype, &G,
@@ -728,19 +732,24 @@ static PyObject *meth__RSAPriv_generate(PyObject *me,
   unsigned nbits;
   unsigned n = 0;
   rsa_priv rp;
+  mp *e = 0;
   pgev evt = { 0 };
-  char *kwlist[] = { "class", "nbits", "event", "rng", "nsteps", 0 };
+  char *kwlist[] = { "class", "nbits", "event", "rng", "nsteps", "e", 0 };
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&|O&O&O&:generate", kwlist,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&|O&O&O&O&:generate", kwlist,
                                   &me, convuint, &nbits, convpgev, &evt,
-                                  convgrand, &r, convuint, &n))
+                                  convgrand, &r, convuint, &n,
+                                  convmp, &e))
     goto end;
-  if (rsa_gen(&rp, nbits, r, n, evt.proc, evt.ctx))
+  if (e) MP_COPY(e);
+  else e = mp_fromulong(MP_NEW, 65537);
+  if (rsa_gen_e(&rp, nbits, e, r, n, evt.proc, evt.ctx))
     PGENERR;
   rc = rsapriv_pywrap(&rp);
 end:
   droppgev(&evt);
+  mp_drop(e);
   return (rc);
 }
 
@@ -1161,56 +1170,83 @@ end:
 XDHS(DEFXDH)
 #undef DEFXDH
 
-/*----- Ed25519 -----------------------------------------------------------*/
+/*----- Ed25519 and related algorithms ------------------------------------*/
 
-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);
-}
+#define EDDSAS(_)                                                      \
+  _(ED25519, ed25519, -1, ctx)                                         \
+  _(ED448, ed448, 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);
-}
+#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 ------------------------------------------------------*/
 
@@ -1231,12 +1267,17 @@ generate(NBITS, [event = pgen_nullev, rng = rand, nsteps = 0]) -> R")
 " #x "(KEY, PUBLIC) -> SHARED")
   XDHS(DEFMETH)
 #undef DEFMETH
-  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")
+#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 }
 };