Deploy the new <ctype.h> and `foocmp' macros from mLib.
[catacomb] / progs / cc-sig.c
index f14b4b8..4c1defc 100644 (file)
 
 #include <stdlib.h>
 
+#include <mLib/macros.h>
 #include <mLib/report.h>
 
 #include "rand.h"
 #include "sha.h"
 #include "has160.h"
 #include "sha512.h"
+#include "sha3.h"
 
 #include "ct.h"
 #include "ec.h"
@@ -46,6 +48,7 @@
 #include "gkcdsa.h"
 #include "rsa.h"
 #include "ed25519.h"
+#include "ed448.h"
 
 #include "cc.h"
 
@@ -574,60 +577,92 @@ static const sigops eckcdsa_vrf = {
   eckcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
 };
 
-/* --- Ed25519 --- */
+/* --- EdDSA --- */
 
-static sig *ed25519_siginit(key *k, void *kd, const gchash *hc)
-  { sig *s = CREATE(sig); s->h = 0; return (s); }
+#define EDDSAS(_)                                                      \
+  _(ed25519, ed25519ctx, ED25519, "Ed25519", sha512)                   \
+  _(ed448, ed448, ED448, "Ed448", shake256)
 
-static int ed25519_sigdoit(sig *s, dstr *d)
-{
-  ed25519_priv *k = s->kd;
-
-  dstr_ensure(d, ED25519_SIGSZ);
-  ed25519_sign((octet *)d->buf, k->priv.k, k->priv.sz, k->pub.k,
-              GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz);
-  d->len += ED25519_SIGSZ;
-  return (0);
-}
-
-static const char *ed25519_sigcheck(sig *s)
-{
-  ed25519_priv *k = s->kd;
-
-  if (k->pub.sz != ED25519_PUBSZ)
-    return ("incorrect Ed25519 public key length");
-  return (0);
-}
-
-static void ed25519_sigdestroy(sig *s) { DESTROY(s); }
-
-static const sigops ed25519_sig = {
-  ed25519_privfetch, sizeof(ed25519_priv),
-  ed25519_siginit, ed25519_sigdoit, ed25519_sigcheck, ed25519_sigdestroy
-};
-
-static int ed25519_vrfdoit(sig *s, dstr *d)
-{
-  ed25519_pub *k = s->kd;
-
-  if (d->len != ED25519_SIGSZ) return (-1);
-  return (ed25519_verify(k->pub.k, GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,
-                        (const octet *)d->buf));
-}
+typedef struct eddsa_sigctx {
+  sig s;
+  const char *perso;
+} eddsa_sigctx;
 
-static const char *ed25519_vrfcheck(sig *s)
+static sig *eddsa_siginit(key *k, void *kd, const gchash *hc)
 {
-  ed25519_pub *k = s->kd;
-
-  if (k->pub.sz != ED25519_PUBSZ)
-    return ("incorrect Ed25519 public key length");
-  return (0);
-}
-
-static const sigops ed25519_vrf = {
-  ed25519_pubfetch, sizeof(ed25519_pub),
-  ed25519_siginit, ed25519_vrfdoit, ed25519_vrfcheck, ed25519_sigdestroy
-};
+  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 --- */
 
@@ -727,7 +762,10 @@ const struct sigtab sigtab[] = {
   { "kcdsa",   &kcdsa_sig,     &kcdsa_vrf,     &has160 },
   { "binkcdsa",        &binkcdsa_sig,  &binkcdsa_vrf,  &has160 },
   { "eckcdsa", &eckcdsa_sig,   &eckcdsa_vrf,   &has160 },
-  { "ed25519", &ed25519_sig,   &ed25519_vrf,   &sha512 },
+#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 }
 };
@@ -772,7 +810,7 @@ sig *getsig(key *k, const char *app, int wantpriv)
   if ((q = key_getattr(0, k, "sig")) != 0) {
     dstr_puts(&d, q);
     p = d.buf;
-  } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') {
+  } else if (STRNCMP(k->type, ==, app, n) && k->type[n] == '-') {
     dstr_puts(&d, k->type);
     p = d.buf + n + 1;
   } else
@@ -795,7 +833,7 @@ sig *getsig(key *k, const char *app, int wantpriv)
   /* --- Look up the algorithms in the table --- */
 
   for (st = sigtab; st->name; st++) {
-    if (strcmp(st->name, salg) == 0)
+    if (STRCMP(st->name, ==, salg))
       goto s_found;
   }
   die(EXIT_FAILURE, "signature algorithm `%s' not found in key `%s'",