X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/c65df27983057ec76ed0e72bb370f9a5ae7dad28..b2776fdf2a98ea586bbdad50eca4ed95e967b0d7:/cc-sig.c diff --git a/cc-sig.c b/cc-sig.c index b7ce0b7..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); } @@ -288,14 +290,16 @@ static void dsa_initcommon(dsa_sigctx *ds, const gchash *hc, } static dsa_sigctx *dsa_doinit(key *k, const gprime_param *gp, - mp *y, const gchash *hc) + mp *y, const gchash *hc, + group *(*makegroup)(const gprime_param *), + const char *what) { dsa_sigctx *ds = CREATE(dsa_sigctx); dstr t = DSTR_INIT; key_fulltag(k, &t); - if ((ds->g.g = group_prime(gp)) == 0) - die(EXIT_FAILURE, "bad prime group in key `%s'", t.buf); + if ((ds->g.g = makegroup(gp)) == 0) + die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf); ds->g.p = G_CREATE(ds->g.g); if (G_FROMINT(ds->g.g, ds->g.p, y)) die(EXIT_FAILURE, "bad public key in key `%s'", t.buf); @@ -327,7 +331,15 @@ static dsa_sigctx *ecdsa_doinit(key *k, const char *cstr, static sig *dsa_siginit(key *k, void *kd, const gchash *hc) { dh_priv *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc); + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); + ds->g.u = MP_COPY(dp->x); + return (&ds->s); +} + +static sig *bindsa_siginit(key *k, void *kd, const gchash *hc) +{ + dh_priv *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); ds->g.u = MP_COPY(dp->x); return (&ds->s); } @@ -372,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 = { @@ -379,6 +392,11 @@ static const sigops dsa_sig = { dsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy }; +static const sigops bindsa_sig = { + dh_privfetch, sizeof(dh_priv), + bindsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy +}; + static const sigops ecdsa_sig = { ec_privfetch, sizeof(ec_priv), ecdsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy @@ -387,7 +405,14 @@ static const sigops ecdsa_sig = { static sig *dsa_vrfinit(key *k, void *kd, const gchash *hc) { dh_pub *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc); + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); + return (&ds->s); +} + +static sig *bindsa_vrfinit(key *k, void *kd, const gchash *hc) +{ + dh_pub *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); return (&ds->s); } @@ -417,6 +442,11 @@ static const sigops dsa_vrf = { dsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy }; +static const sigops bindsa_vrf = { + dh_pubfetch, sizeof(dh_pub), + bindsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy +}; + static const sigops ecdsa_vrf = { ec_pubfetch, sizeof(ec_pub), ecdsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy @@ -433,7 +463,16 @@ static void kcdsa_sethash(dsa_sigctx *ds, const gchash *hc) static sig *kcdsa_siginit(key *k, void *kd, const gchash *hc) { dh_priv *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc); + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); + kcdsa_privkey(ds, dp->x); + kcdsa_sethash(ds, hc); + return (&ds->s); +} + +static sig *binkcdsa_siginit(key *k, void *kd, const gchash *hc) +{ + dh_priv *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); kcdsa_privkey(ds, dp->x); kcdsa_sethash(ds, hc); return (&ds->s); @@ -468,6 +507,11 @@ static const sigops kcdsa_sig = { kcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy }; +static const sigops binkcdsa_sig = { + dh_privfetch, sizeof(dh_priv), + binkcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy +}; + static const sigops eckcdsa_sig = { ec_privfetch, sizeof(ec_priv), eckcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy @@ -476,7 +520,15 @@ static const sigops eckcdsa_sig = { static sig *kcdsa_vrfinit(key *k, void *kd, const gchash *hc) { dh_pub *dp = kd; - dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc); + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime"); + kcdsa_sethash(ds, hc); + return (&ds->s); +} + +static sig *binkcdsa_vrfinit(key *k, void *kd, const gchash *hc) +{ + dh_pub *dp = kd; + dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary"); kcdsa_sethash(ds, hc); return (&ds->s); } @@ -510,20 +562,115 @@ static const sigops kcdsa_vrf = { kcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy }; +static const sigops binkcdsa_vrf = { + dh_pubfetch, sizeof(dh_pub), + binkcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy +}; + static const sigops eckcdsa_vrf = { ec_pubfetch, sizeof(ec_pub), 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[] = { { "rsapkcs1", &rsap1_sig, &rsap1_vrf, &sha }, { "rsapss", &rsapss_sig, &rsapss_vrf, &sha }, { "dsa", &dsa_sig, &dsa_vrf, &sha }, + { "bindsa", &bindsa_sig, &bindsa_vrf, &sha }, { "ecdsa", &ecdsa_sig, &ecdsa_vrf, &sha }, { "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 } }; @@ -608,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 --- */ @@ -638,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); }