X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/c65df27983057ec76ed0e72bb370f9a5ae7dad28..20fa0f6976d598481208c0583d72b2ccef637be9:/cc-kem.c diff --git a/cc-kem.c b/cc-kem.c index 8ba29fd..63199fc 100644 --- a/cc-kem.c +++ b/cc-kem.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 @@ -169,14 +171,16 @@ typedef struct dh_encctx { ge *y; } dh_encctx; -static dh_encctx *dh_doinit(key *k, const gprime_param *gp, mp *y) +static dh_encctx *dh_doinit(key *k, const gprime_param *gp, mp *y, + group *(*makegroup)(const gprime_param *), + const char *what) { dh_encctx *de = CREATE(dh_encctx); dstr t = DSTR_INIT; key_fulltag(k, &t); - if ((de->g = group_prime(gp)) == 0) - die(EXIT_FAILURE, "bad prime group in key `%s'", t.buf); + if ((de->g = makegroup(gp)) == 0) + die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf); de->x = MP_NEW; de->y = G_CREATE(de->g); if (G_FROMINT(de->g, de->y, y)) @@ -207,7 +211,14 @@ static dh_encctx *ec_doinit(key *k, const char *cstr, const ec *y) static kem *dh_encinit(key *k, void *kd) { dh_pub *dp = kd; - dh_encctx *de = dh_doinit(k, &dp->dp, dp->y); + dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime"); + return (&de->k); +} + +static kem *bindh_encinit(key *k, void *kd) +{ + dh_pub *dp = kd; + dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary"); return (&de->k); } @@ -226,7 +237,7 @@ static int dh_encdoit(kem *k, dstr *d, ghash *h) ge *y = G_CREATE(de->g); size_t n = de->g->noctets; buf b; - + G_EXP(de->g, x, de->g->g, r); G_EXP(de->g, y, de->y, r); dstr_ensure(d, n); @@ -260,6 +271,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 = { @@ -267,6 +279,11 @@ static const kemops dh_encops = { dh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy }; +static const kemops bindh_encops = { + dh_pubfetch, sizeof(dh_pub), + bindh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy +}; + static const kemops ec_encops = { ec_pubfetch, sizeof(ec_pub), ec_encinit, dh_encdoit, dh_enccheck, dh_encdestroy @@ -275,7 +292,15 @@ static const kemops ec_encops = { static kem *dh_decinit(key *k, void *kd) { dh_priv *dp = kd; - dh_encctx *de = dh_doinit(k, &dp->dp, dp->y); + dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime"); + de->x = MP_COPY(dp->x); + return (&de->k); +} + +static kem *bindh_decinit(key *k, void *kd) +{ + dh_priv *dp = kd; + dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary"); de->x = MP_COPY(dp->x); return (&de->k); } @@ -317,17 +342,85 @@ static const kemops dh_decops = { dh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy }; +static const kemops bindh_decops = { + dh_privfetch, sizeof(dh_priv), + bindh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy +}; + static const kemops ec_decops = { ec_privfetch, sizeof(ec_priv), 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[] = { { "rsa", &rsa_encops, &rsa_decops }, { "dh", &dh_encops, &dh_decops }, + { "bindh", &bindh_encops, &bindh_decops }, { "ec", &ec_encops, &ec_decops }, + { "symm", &symm_encops, &symm_decops }, { 0, 0, 0 } }; @@ -408,10 +501,18 @@ 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); + kp = 0; + } 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; @@ -442,7 +543,7 @@ k_found:; die(EXIT_FAILURE, "encryption scheme (KDF) `%s' not found in key `%s'", q, t.buf); } - + dstr_reset(&d); if ((q = key_getattr(0, k, "mac")) == 0) { dstr_putf(&d, "%s-hmac", kk->h->name); @@ -516,8 +617,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); }