X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/6f313264de6d6f898478db9251700a5b38bf998d..02dfbd5b7af7816959dbd39c1fe628451204e35f:/cc-sig.c diff --git a/cc-sig.c b/cc-sig.c index 45679ce..dbcf902 100644 --- 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); }