X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/3688eb757240b2332f67ec827be8caf6f6abe924..b2776fdf2a98ea586bbdad50eca4ed95e967b0d7:/cc-sig.c diff --git a/cc-sig.c b/cc-sig.c index 027fa52..54b58f3 100644 --- a/cc-sig.c +++ b/cc-sig.c @@ -7,7 +7,7 @@ * (c) 2004 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Catacomb. * @@ -15,12 +15,12 @@ * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * Catacomb is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with Catacomb; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, @@ -29,6 +29,8 @@ /*----- Header files ------------------------------------------------------*/ +#define _FILE_OFFSET_BITS 64 + #include #include @@ -199,7 +201,7 @@ static int rsapss_sigdoit(sig *s, dstr *d) pss_encode, &rs->p); if (!m) return (-1); n = mp_octets(rs->rp.rp->n); dstr_ensure(d, n); mp_storeb(m, d->buf, n); - d->len += n; mp_drop(m); + d->len += n; mp_drop(m); return (0); } @@ -382,6 +384,7 @@ static void dsa_sigdestroy(sig *s) G_DESTROY(ds->g.g, ds->g.p); mp_drop(ds->g.u); G_DESTROYGROUP(ds->g.g); + DESTROY(ds); } static const sigops dsa_sig = { @@ -569,6 +572,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[] = { @@ -580,6 +670,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 } }; @@ -664,16 +755,25 @@ 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); + kp = 0; + } 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 --- */ @@ -694,8 +794,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); }