Merge branch '2.5.x'
[catacomb] / progs / cc-sig.c
index 35f1701..a416c6e 100644 (file)
 #include "rand.h"
 #include "sha.h"
 #include "has160.h"
+#include "sha512.h"
+#include "sha3.h"
 
+#include "ct.h"
 #include "ec.h"
 #include "ec-keys.h"
 #include "dh.h"
 #include "gdsa.h"
 #include "gkcdsa.h"
 #include "rsa.h"
+#include "ed25519.h"
+#include "ed448.h"
 
 #include "cc.h"
 
@@ -182,11 +187,11 @@ static sig *rsapss_siginit(key *k, void *kd, const gchash *hc)
 {
   rsapss_sigctx *rs = CREATE(rsapss_sigctx);
   rsa_privcreate(&rs->rp, kd, &rand_global);
+  rs->s.h = 0;
   rs->p.r = &rand_global;
   rs->p.cc = getmgf(k, hc);
   rs->p.ch = hc;
   rs->p.ssz = hc->hashsz;
-  rsa_privdestroy(&rs->rp);
   return (&rs->s);
 }
 
@@ -233,6 +238,7 @@ static sig *rsapss_vrfinit(key *k, void *kd, const gchash *hc)
 {
   rsapss_vrfctx *rv = CREATE(rsapss_vrfctx);
   rsa_pubcreate(&rv->rp, kd);
+  rv->s.h = 0;
   rv->p.r = &rand_global;
   rv->p.cc = getmgf(k, hc);
   rv->p.ch = hc;
@@ -570,6 +576,93 @@ static const sigops eckcdsa_vrf = {
   eckcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
 };
 
+/* --- EdDSA --- */
+
+#define EDDSAS(_)                                                      \
+  _(ed25519, ed25519ctx, ED25519, "Ed25519", sha512)                   \
+  _(ed448, ed448, ED448, "Ed448", shake256)
+
+typedef struct eddsa_sigctx {
+  sig s;
+  const char *perso;
+} eddsa_sigctx;
+
+static sig *eddsa_siginit(key *k, void *kd, const gchash *hc)
+{
+  eddsa_sigctx *es = CREATE(eddsa_sigctx);
+  es->s.h = 0;
+  es->perso = key_getattr(0, k, "perso");
+  if (es->perso && strlen(es->perso) > ED25519_MAXPERSOSZ) {
+    die(1, "EdDSA personalization string too long (max length %d)",
+       ED25519_MAXPERSOSZ);
+  }
+  return (&es->s);
+}
+
+static void eddsa_sigdestroy(sig *s)
+  { eddsa_sigctx *es = (eddsa_sigctx *)s; DESTROY(es); }
+
+#define EDDSADEF(ed, sigver, ED, name, hash)                           \
+                                                                       \
+  static int ed##_sigdoit(sig *s, dstr *d)                             \
+  {                                                                    \
+    eddsa_sigctx *es = (eddsa_sigctx *)s;                              \
+    ed##_priv *k = es->s.kd;                                           \
+                                                                       \
+    dstr_ensure(d, ED##_SIGSZ);                                                \
+    sigver##_sign((octet *)d->buf, k->priv.k, k->priv.sz, k->pub.k,    \
+                 es->perso ? 1 : -1, es->perso,                        \
+                 es->perso ? strlen(es->perso) : 0,                    \
+                 GH_DONE(es->s.h, 0), GH_CLASS(es->s.h)->hashsz);      \
+    d->len += ED##_SIGSZ;                                              \
+    return (0);                                                                \
+  }                                                                    \
+                                                                       \
+  static const char *ed##_sigcheck(sig *s)                             \
+  {                                                                    \
+    eddsa_sigctx *es = (eddsa_sigctx *)s;                              \
+    ed##_priv *k = es->s.kd;                                           \
+                                                                       \
+    if (k->pub.sz != ED##_PUBSZ)                                       \
+      return ("incorrect " #name " public key length");                        \
+    return (0);                                                                \
+  }                                                                    \
+                                                                       \
+  static const sigops ed##_sig = {                                     \
+    ed##_privfetch, sizeof(ed##_priv),                                 \
+    eddsa_siginit, ed##_sigdoit, ed##_sigcheck, eddsa_sigdestroy       \
+  };                                                                   \
+                                                                       \
+  static int ed##_vrfdoit(sig *s, dstr *d)                             \
+  {                                                                    \
+    eddsa_sigctx *es = (eddsa_sigctx *)s;                              \
+    ed##_pub *k = es->s.kd;                                            \
+                                                                       \
+    if (d->len != ED##_SIGSZ) return (-1);                             \
+    return (sigver##_verify(k->pub.k,                                  \
+                           es->perso ? 1 : -1, es->perso,              \
+                           es->perso ? strlen(es->perso) : 0,          \
+                           GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,   \
+                           (const octet *)d->buf));                    \
+  }                                                                    \
+                                                                       \
+  static const char *ed##_vrfcheck(sig *s)                             \
+  {                                                                    \
+    ed##_pub *k = s->kd;                                               \
+                                                                       \
+    if (k->pub.sz != ED##_PUBSZ)                                       \
+      return ("incorrect " #name " public key length");                        \
+    return (0);                                                                \
+  }                                                                    \
+                                                                       \
+  static const sigops ed##_vrf = {                                     \
+    ed##_pubfetch, sizeof(ed##_pub),                                   \
+    eddsa_siginit, ed##_vrfdoit, ed##_vrfcheck, eddsa_sigdestroy       \
+  };
+
+EDDSAS(EDDSADEF)
+#undef EDDSADEF
+
 /* --- Symmetric message authentication --- */
 
 typedef struct mac_ctx {
@@ -633,7 +726,7 @@ static int mac_vrfdoit(sig *s, dstr *d)
   const octet *t;
 
   t = GH_DONE(m->s.h, 0);
-  if (d->len != m->mc->hashsz || memcmp(d->buf, t, d->len) != 0)
+  if (d->len != m->mc->hashsz || !ct_memeq(d->buf, t, d->len))
     return (-1);
   return (0);
 }
@@ -668,6 +761,10 @@ const struct sigtab sigtab[] = {
   { "kcdsa",   &kcdsa_sig,     &kcdsa_vrf,     &has160 },
   { "binkcdsa",        &binkcdsa_sig,  &binkcdsa_vrf,  &has160 },
   { "eckcdsa", &eckcdsa_sig,   &eckcdsa_vrf,   &has160 },
+#define EDDSATAB(ed, sigver, ED, name, hash)                           \
+  { #ed,       &ed##_sig,      &ed##_vrf,      &hash },
+  EDDSAS(EDDSATAB)
+#undef EDDSATAB
   { "mac",     &mac_sig,       &mac_vrf,       &rmd160 },
   { 0,         0,              0 }
 };