Merge branch 'master' of git+ssh://metalzone.distorted.org.uk/~mdw/public-git/catacomb/
authorMark Wooding <mdw@ncipher.com>
Wed, 22 Nov 2006 11:38:39 +0000 (11:38 +0000)
committerMark Wooding <mdw@ncipher.com>
Wed, 22 Nov 2006 11:38:39 +0000 (11:38 +0000)
catcrypt.1
catcrypt.c
catsign.1
catsign.c
cc-kem.c
cc-sig.c
cc.h

index d4ef3e1..61da7f9 100644 (file)
@@ -184,6 +184,16 @@ Use the
 algorithm of the
 .BR key (1))
 command to generate the key.
+.TP
+.B symm
+This is a simple symmetric encapsulation scheme.  It works by hashing a
+binary key with a randomly-generated salt.  Use the
+.B binary
+algorithm of the
+.B key add
+command (see
+.BR key (1))
+to generate the key.
 .PP
 As well as the KEM itself, a number of supporting algorithms are used.
 These are taken from appropriately named attributes on the key or,
@@ -335,6 +345,21 @@ algorithm of the
 command (see
 .BR key (1))
 to generate the key.
+.TP
+.B mac
+This uses a symmetric message-authentication algorithm rather than a
+digital signature.  The precise message-authentication scheme used is
+determined by the
+.B mac
+attribute on the key, which defaults to
+.IB hash -hmac
+if unspecified.  Use the
+.B binary
+algorithm of the
+.B key add
+command (see
+.BR key (1))
+to generate the key.
 .PP
 As well as the signature algorithm itself, a hash function is used.
 This is taken from the
index 8468552..cbbf694 100644 (file)
@@ -138,7 +138,7 @@ static int encrypt(int argc, char *argv[])
   octet *tag, *ct;
   buf b;
   size_t seq;
-  char bb[16384];
+  char bb[65536];
   unsigned f = 0;
   key_file kf;
   key *k;
index e762712..3f1cd5e 100644 (file)
--- a/catsign.1
+++ b/catsign.1
@@ -243,6 +243,21 @@ algorithm of the
 command (see
 .BR key (1))
 to generate the key.
+.TP
+.B mac
+This uses a symmetric message-authentication algorithm rather than a
+digital signature.  The precise message-authentication scheme used is
+determined by the
+.B mac
+attribute on the key, which defaults to
+.IB hash -hmac
+if unspecified.  Use the
+.B binary
+algorithm of the
+.B key add
+command (see
+.BR key (1))
+to generate the key.
 .PP
 As well as the signature algorithm itself, a hash function is used.
 This is taken from the
index 93f3236..727c980 100644 (file)
--- a/catsign.c
+++ b/catsign.c
@@ -367,7 +367,7 @@ static void keyhash(key *k, sig *s, dstr *d)
   ghash *h;
   key_filter kf;
 
-  h = GH_INIT(GH_CLASS(s->h));
+  h = GH_INIT(s->ch);
   kf.f = KCAT_PUB;
   kf.m = KF_CATMASK;
   key_fingerprint(k, h, &kf);
index aaa21bd..1766c8e 100644 (file)
--- a/cc-kem.c
+++ b/cc-kem.c
@@ -269,6 +269,7 @@ static void dh_encdestroy(kem *k)
   G_DESTROY(de->g, de->y);
   mp_drop(de->x);
   G_DESTROYGROUP(de->g);
+  DESTROY(de);
 }
 
 static const kemops dh_encops = {
@@ -349,6 +350,67 @@ static const kemops ec_decops = {
   ec_decinit, dh_decdoit, dh_enccheck, dh_encdestroy
 };
 
+/* --- Symmetric --- */
+
+typedef struct symm_ctx {
+  kem k;
+  key_packdef kp;
+  key_bin kb;
+} symm_ctx;
+
+static kem *symm_init(key *k, void *kd)
+{
+  symm_ctx *s;
+  dstr d = DSTR_INIT;
+  int err;
+
+  s = CREATE(symm_ctx);
+
+  key_fulltag(k, &d);
+  s->kp.e = KENC_BINARY;
+  s->kp.p = &s->kb;
+  s->kp.kd = 0;
+
+  if ((err = key_unpack(&s->kp, kd, &d)) != 0) {
+    die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s",
+       d.buf, key_strerror(err));
+  }
+  dstr_destroy(&d);
+  return (&s->k);
+}
+
+static int symm_decdoit(kem *k, dstr *d, ghash *h)
+{
+  symm_ctx *s = (symm_ctx *)k;
+
+  GH_HASH(h, s->kb.k, s->kb.sz);
+  GH_HASH(h, d->buf, d->len);
+  return (0);
+}
+
+static int symm_encdoit(kem *k, dstr *d, ghash *h)
+{
+  dstr_ensure(d, h->ops->c->hashsz);
+  d->len += h->ops->c->hashsz;
+  rand_get(RAND_GLOBAL, d->buf, d->len);
+  return (symm_decdoit(k, d, h));
+}
+
+static const char *symm_check(kem *k) { return (0); }
+
+static void symm_destroy(kem *k)
+  { symm_ctx *s = (symm_ctx *)k; key_unpackdone(&s->kp); }
+
+static const kemops symm_encops = {
+  0, 0,
+  symm_init, symm_encdoit, symm_check, symm_destroy
+};
+
+static const kemops symm_decops = {
+  0, 0,
+  symm_init, symm_decdoit, symm_check, symm_destroy
+};
+
 /* --- The switch table --- */
 
 const struct kemtab kemtab[] = {
@@ -356,6 +418,7 @@ const struct kemtab kemtab[] = {
   { "dh",      &dh_encops,     &dh_decops },
   { "bindh",   &bindh_encops,  &bindh_decops },
   { "ec",      &ec_encops,     &ec_decops },
+  { "symm",    &symm_encops,   &symm_decops },
   { 0,         0,              0 }
 };
 
@@ -436,10 +499,17 @@ kem *getkem(key *k, const char *app, int wantpriv)
       kalg, t.buf);
 k_found:;
   ko = wantpriv ? kt->decops : kt->encops;
-  kd = xmalloc(ko->kdsz);
-  kp = key_fetchinit(ko->kf, 0, kd);
-  if ((e = key_fetch(kp, k)) != 0)
-    die(EXIT_FAILURE, "error fetching key `%s': %s", t.buf, key_strerror(e));
+  if (!ko->kf) {
+    kd = k->k;
+    key_incref(kd);
+  } else {
+    kd = xmalloc(ko->kdsz);
+    kp = key_fetchinit(ko->kf, 0, kd);
+    if ((e = key_fetch(kp, k)) != 0) {
+      die(EXIT_FAILURE, "error fetching key `%s': %s",
+         t.buf, key_strerror(e));
+    }
+  }
   kk = ko->init(k, kd);
   kk->kp = kp;
   kk->ops = ko;
@@ -544,8 +614,12 @@ done:
 
 void freekem(kem *k)
 {
-  key_fetchdone(k->kp);
-  xfree(k->kd);
+  if (!k->ops->kf)
+    key_drop(k->kd);
+  else {
+    key_fetchdone(k->kp);
+    xfree(k->kd);
+  }
   k->ops->destroy(k);
 }
 
index 45679ce..dbcf902 100644 (file)
--- a/cc-sig.c
+++ b/cc-sig.c
@@ -570,6 +570,93 @@ static const sigops eckcdsa_vrf = {
   eckcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
 };
 
+/* --- Symmetric message authentication --- */
+
+typedef struct mac_ctx {
+  sig s;
+  const gcmac *mc;
+  gmac *m;
+  key_packdef kp;
+  key_bin kb;
+} mac_ctx;
+
+static sig *mac_init(key *k, void *kd, const gchash *hc)
+{
+  mac_ctx *m;
+  dstr d = DSTR_INIT;
+  int err;
+  const char *mm;
+
+  m = CREATE(mac_ctx);
+
+  key_fulltag(k, &d);
+  m->kp.e = KENC_BINARY;
+  m->kp.p = &m->kb;
+  m->kp.kd = 0;
+
+  if ((mm = key_getattr(0 /*yik*/, k, "mac")) == 0) {
+    dstr_putf(&d, "%s-hmac", hc->name);
+    mm = d.buf;
+  }
+  if ((m->mc = gmac_byname(mm)) == 0)
+    die(EXIT_FAILURE, "unknown message authentication scheme `%s'", mm);
+  dstr_reset(&d);
+
+  if ((err = key_unpack(&m->kp, kd, &d)) != 0) {
+    die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s",
+       d.buf, key_strerror(err));
+  }
+  dstr_destroy(&d);
+
+  if (keysz(m->kb.sz, m->mc->keysz) != m->kb.sz) {
+    die(EXIT_FAILURE, "bad key size %lu for `%s'",
+       (unsigned long)m->kb.sz, m->mc->name);
+  }
+  m->m = GM_KEY(m->mc, m->kb.k, m->kb.sz);
+  m->s.h = GM_INIT(m->m);
+  return (&m->s);
+}
+
+static int mac_sigdoit(sig *s, dstr *d)
+{
+  mac_ctx *m = (mac_ctx *)s;
+
+  dstr_ensure(d, m->mc->hashsz);
+  GH_DONE(m->s.h, d->buf);
+  d->len += m->mc->hashsz;
+  return (0);
+}
+
+static int mac_vrfdoit(sig *s, dstr *d)
+{
+  mac_ctx *m = (mac_ctx *)s;
+  const octet *t;
+
+  t = GH_DONE(m->s.h, 0);
+  if (d->len != m->mc->hashsz || memcmp(d->buf, t, d->len) != 0)
+    return (-1);
+  return (0);
+}
+
+static const char *mac_check(sig *s) { return (0); }
+
+static void mac_destroy(sig *s)
+{
+  mac_ctx *m = (mac_ctx *)s;
+  GM_DESTROY(m->m);
+  key_unpackdone(&m->kp);
+}
+
+static const sigops mac_sig = {
+  0, 0,
+  mac_init, mac_sigdoit, mac_check, mac_destroy
+};
+
+static const sigops mac_vrf = {
+  0, 0,
+  mac_init, mac_vrfdoit, mac_check, mac_destroy
+};
+
 /* --- The switch table --- */
 
 const struct sigtab sigtab[] = {
@@ -581,6 +668,7 @@ const struct sigtab sigtab[] = {
   { "kcdsa",   &kcdsa_sig,     &kcdsa_vrf,     &has160 },
   { "binkcdsa",        &binkcdsa_sig,  &binkcdsa_vrf,  &has160 },
   { "eckcdsa", &eckcdsa_sig,   &eckcdsa_vrf,   &has160 },
+  { "mac",     &mac_sig,       &mac_vrf,       &rmd160 },
   { 0,         0,              0 }
 };
 
@@ -665,16 +753,24 @@ s_found:;
 
   /* --- Load the key --- */
 
-  kd = xmalloc(so->kdsz);
-  kp = key_fetchinit(so->kf, 0, kd);
-  if ((e = key_fetch(kp, k)) != 0)
-    die(EXIT_FAILURE, "error fetching key `%s': %s", t.buf, key_strerror(e));
+  if (!so->kf) {
+    kd = k->k;
+    key_incref(kd);
+  } else {
+    kd = xmalloc(so->kdsz);
+    kp = key_fetchinit(so->kf, 0, kd);
+    if ((e = key_fetch(kp, k)) != 0) {
+      die(EXIT_FAILURE, "error fetching key `%s': %s",
+         t.buf, key_strerror(e));
+    }
+  }
   s = so->init(k, kd, ch);
   if (!s->h)
     s->h = GH_INIT(ch);
   s->kp = kp;
   s->ops = so;
   s->kd = kd;
+  s->ch = ch;
 
   /* --- Free stuff up --- */
 
@@ -695,8 +791,12 @@ s_found:;
 void freesig(sig *s)
 {
   GH_DESTROY(s->h);
-  key_fetchdone(s->kp);
-  xfree(s->kd);
+  if (!s->ops->kf)
+    key_drop(s->kd);
+  else {    
+    key_fetchdone(s->kp);
+    xfree(s->kd);
+  }
   s->ops->destroy(s);
 }
 
diff --git a/cc.h b/cc.h
index 5574e9e..4124b82 100644 (file)
--- a/cc.h
+++ b/cc.h
@@ -82,6 +82,7 @@ typedef struct sig {
   const struct sigops *ops;
   key_packdef *kp;
   void *kd;
+  gchash *ch;
   ghash *h;
 } sig;