From 35c8b547dde529693875087d67fa60bf88319d2b Mon Sep 17 00:00:00 2001 Message-Id: <35c8b547dde529693875087d67fa60bf88319d2b.1714298574.git.mdw@distorted.org.uk> From: Mark Wooding Date: Wed, 25 Jan 2012 23:18:20 +0000 Subject: [PATCH] server: Use the new kdata system. Organization: Straylight/Edgeware From: Mark Wooding Challenges use the algorithms associated with the master key. This will continue to be the case, since there isn't a specific private or public key to associate with the challenge. It looks like the keyexch subsystem has been turned upside-down, but apart from the initialization and key refresh it's all just a matter of adding the necessary indirections into group and algorithm lookups. Since algorithms are now (logically, at least) distinct for different peer associations, allow a `peer' argument to the ALGS command, and pass the correct information to the ifup script so that it can calculate the MTU properly. At this point, we no longer need the compatibility interface in keymgmt, so remove it, and the molly-guard preventing updates to the master key. --- py/tripe.py.in | 5 +- server/admin.c | 42 +++-- server/chal.c | 16 +- server/keyexch.c | 405 ++++++++++++++++++++++++++-------------- server/keymgmt.c | 78 +------- server/keyset.c | 15 +- server/tripe-admin.5.in | 23 ++- server/tripe.h | 25 +-- svc/watch.in | 8 +- 9 files changed, 340 insertions(+), 277 deletions(-) diff --git a/py/tripe.py.in b/py/tripe.py.in index cefb667f..78a305b8 100644 --- a/py/tripe.py.in +++ b/py/tripe.py.in @@ -836,8 +836,9 @@ class TripeCommandDispatcher (TripeConnection): list(addr))) def addr(me, peer): return _oneline(me.command('ADDR', peer)) - def algs(me): - return _keyvals(me.command('ALGS')) + def algs(me, peer = None): + return _keyvals(me.command('ALGS', + *((peer is not None and [peer]) or []))) def checkchal(me, chal): return _simple(me.command('CHECKCHAL', chal)) def daemon(me): diff --git a/server/admin.c b/server/admin.c index e8920547..0fb57cd8 100644 --- a/server/admin.c +++ b/server/admin.c @@ -1697,28 +1697,42 @@ static void acmd_bgcancel(admin *a, unsigned ac, char *av[]) static void acmd_algs(admin *a, unsigned ac, char *av[]) { + peer *p; + const kdata *kd; + const group *g; + const algswitch *algs; + + if (!ac) + kd = master; + else { + if ((p = a_findpeer(a, av[0])) == 0) return; + kd = p->kx.kpriv; + } + g = kd->g; + algs = &kd->algs; + a_info(a, - "kx-group=%s", gg->ops->name, - "kx-group-order-bits=%lu", (unsigned long)mp_bits(gg->r), - "kx-group-elt-bits=%lu", (unsigned long)gg->nbits, + "kx-group=%s", g->ops->name, + "kx-group-order-bits=%lu", (unsigned long)mp_bits(g->r), + "kx-group-elt-bits=%lu", (unsigned long)g->nbits, A_END); a_info(a, - "hash=%s", algs.h->name, - "mgf=%s", algs.mgf->name, - "hash-sz=%lu", (unsigned long)algs.h->hashsz, + "hash=%s", algs->h->name, + "mgf=%s", algs->mgf->name, + "hash-sz=%lu", (unsigned long)algs->h->hashsz, A_END); a_info(a, - "cipher=%s", algs.c->name, - "cipher-keysz=%lu", (unsigned long)algs.cksz, - "cipher-blksz=%lu", (unsigned long)algs.c->blksz, + "cipher=%s", algs->c->name, + "cipher-keysz=%lu", (unsigned long)algs->cksz, + "cipher-blksz=%lu", (unsigned long)algs->c->blksz, A_END); a_info(a, - "cipher-data-limit=%lu", (unsigned long)algs.expsz, + "cipher-data-limit=%lu", (unsigned long)algs->expsz, A_END); a_info(a, - "mac=%s", algs.m->name, - "mac-keysz=%lu", (unsigned long)algs.mksz, - "mac-tagsz=%lu", (unsigned long)algs.tagsz, + "mac=%s", algs->m->name, + "mac-keysz=%lu", (unsigned long)algs->mksz, + "mac-tagsz=%lu", (unsigned long)algs->tagsz, A_END); a_ok(a); } @@ -1924,7 +1938,7 @@ static void acmd_help(admin */*a*/, unsigned /*ac*/, char */*av*/[]); static const acmd acmdtab[] = { { "add", "[OPTIONS] PEER ADDR ...", 2, 0xffff, acmd_add }, { "addr", "PEER", 1, 1, acmd_addr }, - { "algs", 0, 0, 0, acmd_algs }, + { "algs", "[PEER]", 0, 1, acmd_algs }, { "bgcancel", "TAG", 1, 1, acmd_bgcancel }, { "checkchal", "CHAL", 1, 1, acmd_checkchal }, { "daemon", 0, 0, 0, acmd_daemon }, diff --git a/server/chal.c b/server/chal.c index 3824bb63..12b64e21 100644 --- a/server/chal.c +++ b/server/chal.c @@ -47,16 +47,16 @@ static seqwin iseq; static void c_genkey(void) { - if (mac && GM_CLASS(mac) == algs.m && oseq < 0x07ffffff) return; + if (mac && GM_CLASS(mac) == master->algs.m && oseq < 0x07ffffff) return; if (mac) GM_DESTROY(mac); - assert(algs.mksz < sizeof(buf_t)); - rand_get(RAND_GLOBAL, buf_t, algs.mksz); - mac = GM_KEY(algs.m, buf_t, algs.mksz); + assert(master->algs.mksz < sizeof(buf_t)); + rand_get(RAND_GLOBAL, buf_t, master->algs.mksz); + mac = GM_KEY(master->algs.m, buf_t, master->algs.mksz); oseq = 0; seq_reset(&iseq); IF_TRACING(T_CHAL, { trace(T_CHAL, "chal: generated new challenge key"); - trace_block(T_CRYPTO, "chal: new key", buf_t, algs.mksz); + trace_block(T_CRYPTO, "chal: new key", buf_t, master->algs.mksz); }) } @@ -79,7 +79,7 @@ int c_new(buf *b) if (buf_putu32(b, oseq++)) return (-1); h = GM_INIT(mac); GH_HASH(h, p, BCUR(b) - p); - buf_put(b, GH_DONE(h, 0), algs.tagsz); + buf_put(b, GH_DONE(h, 0), master->algs.tagsz); GH_DESTROY(h); if (BBAD(b)) return (-1); IF_TRACING(T_CHAL, { @@ -101,7 +101,7 @@ int c_new(buf *b) int c_check(buf *b) { const octet *p; - size_t sz = 4 + algs.tagsz; + size_t sz = 4 + master->algs.tagsz; uint32 seq; ghash *h; int ok; @@ -117,7 +117,7 @@ int c_check(buf *b) } h = GM_INIT(mac); GH_HASH(h, p, 4); - ok = (memcmp(GH_DONE(h, 0), p + 4, algs.tagsz) == 0); + ok = (memcmp(GH_DONE(h, 0), p + 4, master->algs.tagsz) == 0); GH_DESTROY(h); if (!ok) { a_warn("CHAL", "incorrect-tag", A_END); diff --git a/server/keyexch.c b/server/keyexch.c index 4280f86e..1527a297 100644 --- a/server/keyexch.c +++ b/server/keyexch.c @@ -93,6 +93,7 @@ static const char *const pkname[] = { /* --- @hashge@ --- * * * Arguments: @ghash *h@ = pointer to hash context + * @group *g@ = pointer to group * @ge *x@ = pointer to group element * * Returns: --- @@ -101,11 +102,12 @@ static const char *const pkname[] = { * @buf_t@. */ -static void hashge(ghash *h, ge *x) +static void hashge(ghash *h, group *g, ge *x) { buf b; + buf_init(&b, buf_t, sizeof(buf_t)); - G_TOBUF(gg, &b, x); + G_TOBUF(g, &b, x); assert(BOK(&b)); GH_HASH(h, BBASE(&b), BLEN(&b)); } @@ -115,6 +117,7 @@ static void hashge(ghash *h, ge *x) * Arguments: @buf *b@ = output buffer * @mp *x@ = the plaintext integer * @size_t n@ = the expected size of the plaintext + * @gcipher *mgfc@ = mask-generating function to use * @const octet *k@ = pointer to key material * @size_t ksz@ = size of the key * @@ -124,14 +127,15 @@ static void hashge(ghash *h, ge *x) * it's a random oracle thing rather than an encryption thing. */ -static octet *mpmask(buf *b, mp *x, size_t n, const octet *k, size_t ksz) +static octet *mpmask(buf *b, mp *x, size_t n, + const gccipher *mgfc, const octet *k, size_t ksz) { gcipher *mgf; octet *p; if ((p = buf_get(b, n)) == 0) return (0); - mgf = GC_INIT(algs.mgf, k, ksz); + mgf = GC_INIT(mgfc, k, ksz); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { trace(T_CRYPTO, "crypto: masking index = %s", mpstr(x)); trace_block(T_CRYPTO, "crypto: masking key", k, ksz); @@ -151,6 +155,7 @@ static octet *mpmask(buf *b, mp *x, size_t n, const octet *k, size_t ksz) * Arguments: @mp *d@ = the output integer * @const octet *p@ = pointer to the ciphertext * @size_t n@ = the size of the ciphertext + * @gcipher *mgfc@ = mask-generating function to use * @const octet *k@ = pointer to key material * @size_t ksz@ = size of the key * @@ -160,11 +165,11 @@ static octet *mpmask(buf *b, mp *x, size_t n, const octet *k, size_t ksz) */ static mp *mpunmask(mp *d, const octet *p, size_t n, - const octet *k, size_t ksz) + const gccipher *mgfc, const octet *k, size_t ksz) { gcipher *mgf; - mgf = GC_INIT(algs.mgf, k, ksz); + mgf = GC_INIT(mgfc, k, ksz); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { trace_block(T_CRYPTO, "crypto: unmasking key", k, ksz); trace_block(T_CRYPTO, "crypto: masked ciphertext", p, n); @@ -181,7 +186,8 @@ static mp *mpunmask(mp *d, const octet *p, size_t n, /* --- @hashcheck@ --- * * - * Arguments: @ge *kpub@ = sender's public key + * Arguments: @keyexch *kx@ = pointer to key-exchange block + * @ge *kpub@ = sender's public key * @ge *cc@ = receiver's challenge * @ge *c@ = sender's challenge * @ge *y@ = reply to sender's challenge @@ -198,23 +204,24 @@ static mp *mpunmask(mp *d, const octet *p, size_t n, * key-exchange is deniable. */ -static const octet *hashcheck(ge *kpub, ge *cc, ge *c, ge *y) +static const octet *hashcheck(keyexch *kx, ge *kpub, ge *cc, ge *c, ge *y) { - ghash *h = GH_INIT(algs.h); + ghash *h = GH_INIT(kx->kpriv->algs.h); + group *g = kx->kpriv->g; HASH_STRING(h, "tripe-expected-reply"); - hashge(h, kpub); - hashge(h, cc); - hashge(h, c); - hashge(h, y); + hashge(h, g, kpub); + hashge(h, g, cc); + hashge(h, g, c); + hashge(h, g, y); GH_DONE(h, buf_t); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { trace(T_CRYPTO, "crypto: computing challenge check hash"); - trace(T_CRYPTO, "crypto: public key = %s", gestr(gg, kpub)); - trace(T_CRYPTO, "crypto: receiver challenge = %s", gestr(gg, cc)); - trace(T_CRYPTO, "crypto: sender challenge = %s", gestr(gg, c)); - trace(T_CRYPTO, "crypto: sender reply = %s", gestr(gg, y)); - trace_block(T_CRYPTO, "crypto: hash output", buf_t, algs.hashsz); + trace(T_CRYPTO, "crypto: public key = %s", gestr(g, kpub)); + trace(T_CRYPTO, "crypto: receiver challenge = %s", gestr(g, cc)); + trace(T_CRYPTO, "crypto: sender challenge = %s", gestr(g, c)); + trace(T_CRYPTO, "crypto: sender reply = %s", gestr(g, y)); + trace_block(T_CRYPTO, "crypto: hash output", buf_t, kx->kpriv->algs.hashsz); })) GH_DESTROY(h); return (buf_t); @@ -234,10 +241,11 @@ static const octet *hashcheck(ge *kpub, ge *cc, ge *c, ge *y) static void sendchallenge(keyexch *kx, buf *b, ge *c, const octet *hc) { - G_TOBUF(gg, b, kx->c); - buf_put(b, hc, algs.hashsz); - mpmask(b, kx->alpha, indexsz, - hashcheck(kpub, c, kx->c, kx->rx), algs.hashsz); + G_TOBUF(kx->kpriv->g, b, kx->c); + buf_put(b, hc, kx->kpriv->algs.hashsz); + mpmask(b, kx->alpha, kx->kpriv->indexsz, kx->kpriv->algs.mgf, + hashcheck(kx, kx->kpriv->kpub, c, kx->c, kx->rx), + kx->kpriv->algs.hashsz); } /* --- @timer@ --- * @@ -307,8 +315,8 @@ static void kxc_destroy(kxchal *kxc) { if (kxc->f & KXF_TIMER) sel_rmtimer(&kxc->t); - G_DESTROY(gg, kxc->c); - G_DESTROY(gg, kxc->r); + G_DESTROY(kxc->kx->kpriv->g, kxc->c); + G_DESTROY(kxc->kx->kpriv->g, kxc->r); ks_drop(kxc->ks); DESTROY(kxc); } @@ -357,8 +365,8 @@ static kxchal *kxc_new(keyexch *kx) /* --- Fill in the new structure --- */ kxc = CREATE(kxchal); - kxc->c = G_CREATE(gg); - kxc->r = G_CREATE(gg); + kxc->c = G_CREATE(kx->kpriv->g); + kxc->r = G_CREATE(kx->kpriv->g); kxc->ks = 0; kxc->kx = kx; kxc->f = 0; @@ -381,7 +389,7 @@ static kxchal *kxc_bychal(keyexch *kx, ge *c) unsigned i; for (i = 0; i < kx->nr; i++) { - if (G_EQ(gg, c, kx->r[i]->c)) + if (G_EQ(kx->kpriv->g, c, kx->r[i]->c)) return (kx->r[i]); } return (0); @@ -402,7 +410,7 @@ static kxchal *kxc_byhc(keyexch *kx, const octet *hc) unsigned i; for (i = 0; i < kx->nr; i++) { - if (memcmp(hc, kx->r[i]->hc, algs.hashsz) == 0) + if (memcmp(hc, kx->r[i]->hc, kx->kpriv->algs.hashsz) == 0) return (kx->r[i]); } return (0); @@ -440,7 +448,7 @@ static void kxc_answer(keyexch *kx, kxchal *kxc) T( trace(T_KEYEXCH, "keyexch: sending reply to `%s'", p_name(kx->p)); ) sendchallenge(kx, b, kxc->c, kxc->hc); buf_init(&bb, buf_i, sizeof(buf_i)); - G_TORAW(gg, &bb, kxc->r); + G_TORAW(kx->kpriv->g, &bb, kxc->r); buf_flip(&bb); ks_encrypt(kxc->ks, MSG_KEYEXCH | KX_REPLY, &bb, b); @@ -477,7 +485,7 @@ static void kxc_answer(keyexch *kx, kxchal *kxc) static int doprechallenge(keyexch *kx, buf *b) { stats *st = p_stats(kx->p); - ge *c = G_CREATE(gg); + ge *c = G_CREATE(kx->kpriv->g); ghash *h; /* --- Ensure that we're in a sensible state --- */ @@ -489,19 +497,19 @@ static int doprechallenge(keyexch *kx, buf *b) /* --- Unpack the packet --- */ - if (G_FROMBUF(gg, b, c) || BLEFT(b)) + if (G_FROMBUF(kx->kpriv->g, b, c) || BLEFT(b)) goto bad; IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { - trace(T_CRYPTO, "crypto: challenge = %s", gestr(gg, c)); + trace(T_CRYPTO, "crypto: challenge = %s", gestr(kx->kpriv->g, c)); })) /* --- Send out a full challenge by return --- */ b = p_txstart(kx->p, MSG_KEYEXCH | KX_CHAL); - h = GH_INIT(algs.h); + h = GH_INIT(kx->kpriv->algs.h); HASH_STRING(h, "tripe-cookie"); - hashge(h, c); + hashge(h, kx->kpriv->g, c); sendchallenge(kx, b, c, GH_DONE(h, 0)); GH_DESTROY(h); st->n_kxout++; @@ -510,11 +518,11 @@ static int doprechallenge(keyexch *kx, buf *b) /* --- Done --- */ - G_DESTROY(gg, c); + G_DESTROY(kx->kpriv->g, c); return (0); bad: - if (c) G_DESTROY(gg, c); + if (c) G_DESTROY(kx->kpriv->g, c); return (-1); } @@ -532,9 +540,12 @@ bad: static kxchal *respond(keyexch *kx, unsigned msg, buf *b) { - ge *c = G_CREATE(gg); - ge *r = G_CREATE(gg); - ge *cc = G_CREATE(gg); + group *g = kx->kpriv->g; + const algswitch *algs = &kx->kpriv->algs; + size_t ixsz = kx->kpriv->indexsz; + ge *c = G_CREATE(g); + ge *r = G_CREATE(g); + ge *cc = G_CREATE(g); const octet *hc, *ck; size_t x, y, z; mp *cv = 0; @@ -545,21 +556,21 @@ static kxchal *respond(keyexch *kx, unsigned msg, buf *b) /* --- Unpack the packet --- */ - if (G_FROMBUF(gg, b, c) || - (hc = buf_get(b, algs.hashsz)) == 0 || - (ck = buf_get(b, indexsz)) == 0) { + if (G_FROMBUF(g, b, c) || + (hc = buf_get(b, algs->hashsz)) == 0 || + (ck = buf_get(b, ixsz)) == 0) { a_warn("KX", "?PEER", kx->p, "invalid", "%s", pkname[msg], A_END); goto bad; } IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { - trace(T_CRYPTO, "crypto: challenge = %s", gestr(gg, c)); - trace_block(T_CRYPTO, "crypto: cookie", hc, algs.hashsz); - trace_block(T_CRYPTO, "crypto: check-value", ck, indexsz); + trace(T_CRYPTO, "crypto: challenge = %s", gestr(g, c)); + trace_block(T_CRYPTO, "crypto: cookie", hc, algs->hashsz); + trace_block(T_CRYPTO, "crypto: check-value", ck, ixsz); })) /* --- Discard a packet with an invalid cookie --- */ - if (hc && memcmp(hc, kx->hc, algs.hashsz) != 0) { + if (hc && memcmp(hc, kx->hc, algs->hashsz) != 0) { a_warn("KX", "?PEER", kx->p, "incorrect", "cookie", A_END); goto bad; } @@ -573,97 +584,96 @@ static kxchal *respond(keyexch *kx, unsigned msg, buf *b) */ if ((kxc = kxc_bychal(kx, c)) != 0) { - h = GH_INIT(algs.h); + h = GH_INIT(algs->h); HASH_STRING(h, "tripe-check-hash"); - GH_HASH(h, ck, indexsz); - ok = !memcmp(kxc->ck, GH_DONE(h, 0), algs.hashsz); + GH_HASH(h, ck, ixsz); + ok = !memcmp(kxc->ck, GH_DONE(h, 0), algs->hashsz); GH_DESTROY(h); if (!ok) goto badcheck; } else { /* --- Compute the reply, and check the magic --- */ - G_EXP(gg, r, c, kpriv); - cv = mpunmask(MP_NEW, ck, indexsz, - hashcheck(kx->kpub, kx->c, c, r), algs.hashsz); + G_EXP(g, r, c, kx->kpriv->kpriv); + cv = mpunmask(MP_NEW, ck, ixsz, algs->mgf, + hashcheck(kx, kx->kpub->kpub, kx->c, c, r), + algs->hashsz); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { - trace(T_CRYPTO, "crypto: computed reply = %s", gestr(gg, r)); + trace(T_CRYPTO, "crypto: computed reply = %s", gestr(g, r)); trace(T_CRYPTO, "crypto: recovered log = %s", mpstr(cv)); })) - if (MP_CMP(cv, >, gg->r) || - (G_EXP(gg, cc, gg->g, cv), !G_EQ(gg, c, cc))) + if (MP_CMP(cv, >, g->r) || + (G_EXP(g, cc, g->g, cv), + !G_EQ(g, c, cc))) goto badcheck; /* --- Fill in a new challenge block --- */ kxc = kxc_new(kx); - G_COPY(gg, kxc->c, c); - G_COPY(gg, kxc->r, r); + G_COPY(g, kxc->c, c); + G_COPY(g, kxc->r, r); - h = GH_INIT(algs.h); - HASH_STRING(h, "tripe-check-hash"); - GH_HASH(h, ck, indexsz); - GH_DONE(h, kxc->ck); - GH_DESTROY(h); + h = GH_INIT(algs->h); HASH_STRING(h, "tripe-check-hash"); + GH_HASH(h, ck, ixsz); + GH_DONE(h, kxc->ck); GH_DESTROY(h); - h = GH_INIT(algs.h); - HASH_STRING(h, "tripe-cookie"); - hashge(h, kxc->c); - GH_DONE(h, kxc->hc); - GH_DESTROY(h); + h = GH_INIT(algs->h); HASH_STRING(h, "tripe-cookie"); + hashge(h, g, kxc->c); + GH_DONE(h, kxc->hc); GH_DESTROY(h); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { - trace_block(T_CRYPTO, "crypto: computed cookie", kxc->hc, algs.hashsz); + trace_block(T_CRYPTO, "crypto: computed cookie", + kxc->hc, algs->hashsz); })) /* --- Work out the shared key --- */ - G_EXP(gg, r, c, kx->alpha); + G_EXP(g, r, c, kx->alpha); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { - trace(T_CRYPTO, "crypto: shared secret = %s", gestr(gg, r)); + trace(T_CRYPTO, "crypto: shared secret = %s", gestr(g, r)); })) /* --- Compute the switch messages --- */ - h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-request"); - hashge(h, kx->c); hashge(h, kxc->c); + h = GH_INIT(algs->h); HASH_STRING(h, "tripe-switch-request"); + hashge(h, g, kx->c); hashge(h, g, kxc->c); GH_DONE(h, kxc->hswrq_out); GH_DESTROY(h); - h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-confirm"); - hashge(h, kx->c); hashge(h, kxc->c); + h = GH_INIT(algs->h); HASH_STRING(h, "tripe-switch-confirm"); + hashge(h, g, kx->c); hashge(h, g, kxc->c); GH_DONE(h, kxc->hswok_out); GH_DESTROY(h); - h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-request"); - hashge(h, kxc->c); hashge(h, kx->c); + h = GH_INIT(algs->h); HASH_STRING(h, "tripe-switch-request"); + hashge(h, g, kxc->c); hashge(h, g, kx->c); GH_DONE(h, kxc->hswrq_in); GH_DESTROY(h); - h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-confirm"); - hashge(h, kxc->c); hashge(h, kx->c); + h = GH_INIT(algs->h); HASH_STRING(h, "tripe-switch-confirm"); + hashge(h, g, kxc->c); hashge(h, g, kx->c); GH_DONE(h, kxc->hswok_in); GH_DESTROY(h); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { trace_block(T_CRYPTO, "crypto: outbound switch request", - kxc->hswrq_out, algs.hashsz); + kxc->hswrq_out, algs->hashsz); trace_block(T_CRYPTO, "crypto: outbound switch confirm", - kxc->hswok_out, algs.hashsz); + kxc->hswok_out, algs->hashsz); trace_block(T_CRYPTO, "crypto: inbound switch request", - kxc->hswrq_in, algs.hashsz); + kxc->hswrq_in, algs->hashsz); trace_block(T_CRYPTO, "crypto: inbound switch confirm", - kxc->hswok_in, algs.hashsz); + kxc->hswok_in, algs->hashsz); })) /* --- Create a new symmetric keyset --- */ buf_init(&bb, buf_o, sizeof(buf_o)); - G_TOBUF(gg, &bb, kx->c); x = BLEN(&bb); - G_TOBUF(gg, &bb, kxc->c); y = BLEN(&bb); - G_TOBUF(gg, &bb, r); z = BLEN(&bb); + G_TOBUF(g, &bb, kx->c); x = BLEN(&bb); + G_TOBUF(g, &bb, kxc->c); y = BLEN(&bb); + G_TOBUF(g, &bb, r); z = BLEN(&bb); assert(BOK(&bb)); kxc->ks = ks_gen(BBASE(&bb), x, y, z, kx->p); } - G_DESTROY(gg, c); - G_DESTROY(gg, cc); - G_DESTROY(gg, r); + G_DESTROY(g, c); + G_DESTROY(g, cc); + G_DESTROY(g, r); mp_drop(cv); return (kxc); @@ -671,9 +681,9 @@ badcheck: a_warn("KX", "?PEER", kx->p, "bad-expected-reply-log", A_END); goto bad; bad: - G_DESTROY(gg, c); - G_DESTROY(gg, cc); - G_DESTROY(gg, r); + G_DESTROY(g, c); + G_DESTROY(g, cc); + G_DESTROY(g, r); mp_drop(cv); return (0); } @@ -731,18 +741,18 @@ static void resend(keyexch *kx) T( trace(T_KEYEXCH, "keyexch: sending prechallenge to `%s'", p_name(kx->p)); ) b = p_txstart(kx->p, MSG_KEYEXCH | KX_PRECHAL); - G_TOBUF(gg, b, kx->c); + G_TOBUF(kx->kpriv->g, b, kx->c); break; case KXS_COMMIT: T( trace(T_KEYEXCH, "keyexch: sending switch request to `%s'", p_name(kx->p)); ) kxc = kx->r[0]; b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCH); - buf_put(b, kx->hc, algs.hashsz); - buf_put(b, kxc->hc, algs.hashsz); + buf_put(b, kx->hc, kx->kpriv->algs.hashsz); + buf_put(b, kxc->hc, kx->kpriv->algs.hashsz); buf_init(&bb, buf_i, sizeof(buf_i)); - G_TORAW(gg, &bb, kxc->r); - buf_put(&bb, kxc->hswrq_out, algs.hashsz); + G_TORAW(kx->kpriv->g, &bb, kxc->r); + buf_put(&bb, kxc->hswrq_out, kx->kpriv->algs.hashsz); buf_flip(&bb); ks_encrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCH, &bb, b); break; @@ -752,7 +762,7 @@ static void resend(keyexch *kx) kxc = kx->r[0]; b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCHOK); buf_init(&bb, buf_i, sizeof(buf_i)); - buf_put(&bb, kxc->hswok_out, algs.hashsz); + buf_put(&bb, kxc->hswok_out, kx->kpriv->algs.hashsz); buf_flip(&bb); ks_encrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCHOK, &bb, b); break; @@ -811,25 +821,26 @@ static int decryptrest(keyexch *kx, kxchal *kxc, unsigned msg, buf *b) static int checkresponse(keyexch *kx, unsigned msg, buf *b) { - ge *r = G_CREATE(gg); + group *g = kx->kpriv->g; + ge *r = G_CREATE(g); - if (G_FROMRAW(gg, b, r)) { + if (G_FROMRAW(g, b, r)) { a_warn("KX", "?PEER", kx->p, "invalid", "%s", pkname[msg], A_END); goto bad; } IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { - trace(T_CRYPTO, "crypto: reply = %s", gestr(gg, r)); + trace(T_CRYPTO, "crypto: reply = %s", gestr(g, r)); })) - if (!G_EQ(gg, r, kx->rx)) { + if (!G_EQ(g, r, kx->rx)) { a_warn("KX", "?PEER", kx->p, "incorrect", "response", A_END); goto bad; } - G_DESTROY(gg, r); + G_DESTROY(g, r); return (0); bad: - G_DESTROY(gg, r); + G_DESTROY(g, r); return (-1); } @@ -927,34 +938,35 @@ static void kxfinish(keyexch *kx) static int doswitch(keyexch *kx, buf *b) { + size_t hsz = kx->kpriv->algs.hashsz; const octet *hc_in, *hc_out, *hswrq; kxchal *kxc; - if ((hc_in = buf_get(b, algs.hashsz)) == 0 || - (hc_out = buf_get(b, algs.hashsz)) == 0) { + if ((hc_in = buf_get(b, hsz)) == 0 || + (hc_out = buf_get(b, hsz)) == 0) { a_warn("KX", "?PEER", kx->p, "invalid", "switch-rq", A_END); goto bad; } IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { - trace_block(T_CRYPTO, "crypto: challenge", hc_in, algs.hashsz); - trace_block(T_CRYPTO, "crypto: cookie", hc_out, algs.hashsz); + trace_block(T_CRYPTO, "crypto: challenge", hc_in, hsz); + trace_block(T_CRYPTO, "crypto: cookie", hc_out, hsz); })) if ((kxc = kxc_byhc(kx, hc_in)) == 0 || - memcmp(hc_out, kx->hc, algs.hashsz) != 0) { + memcmp(hc_out, kx->hc, hsz) != 0) { a_warn("KX", "?PEER", kx->p, "incorrect", "switch-rq", A_END); goto bad; } if (decryptrest(kx, kxc, KX_SWITCH, b) || checkresponse(kx, KX_SWITCH, b)) goto bad; - if ((hswrq = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) { + if ((hswrq = buf_get(b, hsz)) == 0 || BLEFT(b)) { a_warn("KX", "?PEER", kx->p, "invalid", "switch-rq", A_END); goto bad; } IF_TRACING(T_KEYEXCH, { - trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, algs.hashsz); + trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, hsz); }) - if (memcmp(hswrq, kxc->hswrq_in, algs.hashsz) != 0) { + if (memcmp(hswrq, kxc->hswrq_in, hsz) != 0) { a_warn("KX", "?PEER", kx->p, "incorrect", "switch-rq", A_END); goto bad; } @@ -981,6 +993,7 @@ bad: static int doswitchok(keyexch *kx, buf *b) { + size_t hsz = kx->kpriv->algs.hashsz; const octet *hswok; kxchal *kxc; buf bb; @@ -993,15 +1006,15 @@ static int doswitchok(keyexch *kx, buf *b) buf_init(&bb, buf_o, sizeof(buf_o)); if (decryptrest(kx, kxc, KX_SWITCHOK, b)) goto bad; - if ((hswok = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) { + if ((hswok = buf_get(b, hsz)) == 0 || BLEFT(b)) { a_warn("KX", "?PEER", kx->p, "invalid", "switch-ok", A_END); goto bad; } IF_TRACING(T_KEYEXCH, { trace_block(T_CRYPTO, "crypto: switch confirmation hash", - hswok, algs.hashsz); + hswok, hsz); }) - if (memcmp(hswok, kxc->hswok_in, algs.hashsz) != 0) { + if (memcmp(hswok, kxc->hswok_in, hsz) != 0) { a_warn("KX", "?PEER", kx->p, "incorrect", "switch-ok", A_END); goto bad; } @@ -1041,8 +1054,8 @@ static void stop(keyexch *kx) for (i = 0; i < kx->nr; i++) kxc_destroy(kx->r[i]); mp_drop(kx->alpha); - G_DESTROY(gg, kx->c); - G_DESTROY(gg, kx->rx); + G_DESTROY(kx->kpriv->g, kx->c); + G_DESTROY(kx->kpriv->g, kx->rx); kx->t_valid = 0; kx->f |= KXF_DEAD; kx->f &= ~KXF_TIMER; @@ -1061,21 +1074,23 @@ static void stop(keyexch *kx) static void start(keyexch *kx, time_t now) { + algswitch *algs = &kx->kpriv->algs; + group *g = kx->kpriv->g; ghash *h; assert(kx->f & KXF_DEAD); kx->f &= ~(KXF_DEAD | KXF_CORK); kx->nr = 0; - kx->alpha = mprand_range(MP_NEW, gg->r, &rand_global, 0); - kx->c = G_CREATE(gg); G_EXP(gg, kx->c, gg->g, kx->alpha); - kx->rx = G_CREATE(gg); G_EXP(gg, kx->rx, kx->kpub, kx->alpha); + kx->alpha = mprand_range(MP_NEW, g->r, &rand_global, 0); + kx->c = G_CREATE(g); G_EXP(g, kx->c, g->g, kx->alpha); + kx->rx = G_CREATE(g); G_EXP(g, kx->rx, kx->kpub->kpub, kx->alpha); kx->s = KXS_CHAL; kx->t_valid = now + T_VALID; - h = GH_INIT(algs.h); + h = GH_INIT(algs->h); HASH_STRING(h, "tripe-cookie"); - hashge(h, kx->c); + hashge(h, g, kx->c); GH_DONE(h, kx->hc); GH_DESTROY(h); @@ -1083,9 +1098,10 @@ static void start(keyexch *kx, time_t now) trace(T_KEYEXCH, "keyexch: creating new challenge"); IF_TRACING(T_CRYPTO, { trace(T_CRYPTO, "crypto: secret = %s", mpstr(kx->alpha)); - trace(T_CRYPTO, "crypto: challenge = %s", gestr(gg, kx->c)); - trace(T_CRYPTO, "crypto: expected response = %s", gestr(gg, kx->rx)); - trace_block(T_CRYPTO, "crypto: challenge cookie", kx->hc, algs.hashsz); + trace(T_CRYPTO, "crypto: challenge = %s", gestr(g, kx->c)); + trace(T_CRYPTO, "crypto: expected response = %s", gestr(g, kx->rx)); + trace_block(T_CRYPTO, "crypto: challenge cookie", + kx->hc, algs->hashsz); }) }) } @@ -1103,13 +1119,17 @@ static void start(keyexch *kx, time_t now) static int checkpub(keyexch *kx) { time_t now; + unsigned f = 0; + if (kx->f & KXF_DEAD) return (-1); now = time(0); - if (KEY_EXPIRED(now, kx->texp_kpub)) { + if (KEY_EXPIRED(now, kx->kpriv->t_exp)) f |= 1; + if (KEY_EXPIRED(now, kx->kpub->t_exp)) f |= 2; + if (f) { stop(kx); - a_warn("KX", "?PEER", kx->p, "public-key-expired", A_END); - G_COPY(gg, kx->kpub, gg->i); + if (f & 1) a_warn("KX", "?PEER", kx->p, "private-key-expired", A_END); + if (f & 2) a_warn("KX", "?PEER", kx->p, "public-key-expired", A_END); kx->f &= ~KXF_PUBKEY; return (-1); } @@ -1219,7 +1239,8 @@ void kx_message(keyexch *kx, unsigned msg, buf *b) void kx_free(keyexch *kx) { stop(kx); - G_DESTROY(gg, kx->kpub); + km_unref(kx->kpub); + km_unref(kx->kpriv); } /* --- @kx_newkeys@ --- * @@ -1236,13 +1257,111 @@ void kx_free(keyexch *kx) void kx_newkeys(keyexch *kx) { - if (km_getpubkey(p_tag(kx->p), kx->kpub, &kx->texp_kpub)) - return; + kdata *kpriv, *kpub; + unsigned i; + int switchp; + time_t now = time(0); + + T( trace(T_KEYEXCH, "keyexch: checking new keys for `%s'", + p_name(kx->p)); ) + + /* --- Find out whether we can use new keys --- * + * + * Try each available combination of new and old, public and private, + * except both old (which is status quo anyway). The selection is encoded + * in @i@, with bit 0 for the private key and bit 1 for public key; a set + * bit means to use the old value, and a clear bit means to use the new + * one. + * + * This means that we currently prefer `old private and new public' over + * `new private and old public'. I'm not sure which way round this should + * actually be. + */ + + for (i = 0; i < 3; i++) { + + /* --- Select the keys we're going to examine --- * + * + * If we're meant to have a new key and don't, then skip this + * combination. + */ + + T( trace(T_KEYEXCH, "keyexch: checking %s private, %s public", + i & 1 ? "old" : "new", i & 2 ? "old" : "new"); ) + + if (i & 1) kpriv = kx->kpriv; + else if (kx->kpriv->kn->kd != kx->kpriv) kpriv = kx->kpriv->kn->kd; + else { + T( trace(T_KEYEXCH, "keyexch: private key unchanged, skipping"); ) + continue; + } + + if (i & 2) kpub = kx->kpub; + else if (kx->kpub->kn->kd != kx->kpub) kpub = kx->kpub->kn->kd; + else { + T( trace(T_KEYEXCH, "keyexch: public key unchanged, skipping"); ) + continue; + } + + /* --- Skip if either key is expired --- * + * + * We're not going to get far with expired keys, and this simplifies the + * logic below. + */ + + if (KEY_EXPIRED(now, kx->kpriv->t_exp) || + KEY_EXPIRED(now, kx->kpub->t_exp)) { + T( trace(T_KEYEXCH, "keyexch: %s expired, skipping", + !KEY_EXPIRED(now, kx->kpriv->t_exp) ? "public key" : + !KEY_EXPIRED(now, kx->kpub->t_exp) ? "private key" : + "both keys"); ) + continue; + } + + /* --- If the groups don't match then we can't use this pair --- */ + + if (!km_samealgsp(kpriv, kpub)) { + T( trace(T_KEYEXCH, "keyexch: peer `%s' group mismatch; " + "%s priv `%s' and %s pub `%s'", p_name(kx->p), + i & 1 ? "old" : "new", km_tag(kx->kpriv), + i & 2 ? "old" : "new", km_tag(kx->kpub)); ) + continue; + } + goto newkeys; + } + T( trace(T_KEYEXCH, "keyexch: peer `%s' continuing with old keys", + p_name(kx->p)); ) + return; + + /* --- We've chosen new keys --- * + * + * Switch the new ones into place. Neither of the keys we're switching to + * is expired (we checked that above), so we should just crank everything + * up. + * + * A complication arises: we don't really want to force a new key exchange + * unless we have to. If the group is unchanged, and we're currently + * running OK, then we should just let things lie. + */ + +newkeys: + switchp = ((kx->f & KXF_DEAD) || + kx->s != KXS_SWITCH || + !group_samep(kx->kpriv->g, kpriv->g)); + + T( trace(T_KEYEXCH, "keyexch: peer `%s' adopting " + "%s priv `%s' and %s pub `%s'; %sforcing exchange", p_name(kx->p), + i & 1 ? "old" : "new", km_tag(kx->kpriv), + i & 2 ? "old" : "new", km_tag(kx->kpub), + switchp ? "" : "not "); ) + + if (switchp) stop(kx); + km_ref(kpriv); km_unref(kx->kpriv); kx->kpriv = kpriv; + km_ref(kpub); km_unref(kx->kpub); kx->kpub = kpub; kx->f |= KXF_PUBKEY; - if ((kx->f & KXF_DEAD) || kx->s != KXS_SWITCH) { + if (switchp) { T( trace(T_KEYEXCH, "keyexch: restarting key negotiation with `%s'", p_name(kx->p)); ) - stop(kx); start(kx, time(0)); resend(kx); } @@ -1264,13 +1383,18 @@ void kx_newkeys(keyexch *kx) int kx_init(keyexch *kx, peer *p, keyset **ks, unsigned f) { + if ((kx->kpriv = km_findpriv(tag_priv)) == 0) goto fail_0; + if ((kx->kpub = km_findpub(p_tag(p))) == 0) goto fail_1; + if (!km_samealgsp(kx->kpriv, kx->kpub)) { + a_warn("KX", "?PEER", kx->p, "algorithms-mismatch", + "local-private-key", "%s", tag_priv, + "peer-public-key", "%s", p_tag(p), + A_END); + goto fail_2; + } + kx->ks = ks; kx->p = p; - kx->kpub = G_CREATE(gg); - if (km_getpubkey(p_tag(p), kx->kpub, &kx->texp_kpub)) { - G_DESTROY(gg, kx->kpub); - return (-1); - } kx->f = KXF_DEAD | KXF_PUBKEY | f; if (!(kx->f & KXF_CORK)) { start(kx, time(0)); @@ -1278,6 +1402,13 @@ int kx_init(keyexch *kx, peer *p, keyset **ks, unsigned f) /* Don't notify here: the ADD message hasn't gone out yet. */ } return (0); + +fail_2: + km_unref(kx->kpub); +fail_1: + km_unref(kx->kpriv); +fail_0: + return (-1); } /*----- That's all, folks -------------------------------------------------*/ diff --git a/server/keymgmt.c b/server/keymgmt.c index 69ea74a5..ef4f6a6b 100644 --- a/server/keymgmt.c +++ b/server/keymgmt.c @@ -727,46 +727,6 @@ static int kh_refresh(keyhalf *kh) const char *tag_priv; kdata *master; -group *gg; -mp *kpriv; -ge *kpub; -algswitch algs; -size_t indexsz; - -/* --- @update_compat@ --- * - * - * Arguments: @kdata *kd@ = proposed new master key - * - * Returns: Zero on success, nonzero to refuse the replacement. - * - * Use: Updates the exported private key variables for compatibility. - */ - -static int update_compat(kdata *kd) -{ - if (gg) { - if (!group_samep(kd->g, gg)) { - a_warn("KEYMGMT", "private-keyring", - "%s", kd->kn->kh->kr, "key", "%s", kd->tag, - "changed-group", A_END); - return (-1); - } - G_DESTROYGROUP(gg); - } - gg = kd->g; - - if (kpriv) mp_drop(kpriv); - kpriv = MP_COPY(kd->kpriv); - if (kpub) G_DESTROY(gg, kpub); - kpub = G_CREATE(gg); - G_COPY(gg, kpub, kd->kpub); - - algs = kd->algs; - indexsz = kd->indexsz; - - return (0); -} - /* --- @km_init@ --- * * * Arguments: @const char *privkr@ = private keyring file @@ -795,8 +755,6 @@ void km_init(const char *privkr, const char *pubkr, const char *ptag) tag_priv = ptag; if ((master = km_findpriv(ptag)) == 0) exit(EXIT_FAILURE); - - if (update_compat(master)) exit(EXIT_FAILURE); } /* --- @km_reload@ --- * @@ -816,7 +774,7 @@ int km_reload(void) if (kh_refresh(&priv)) { changep = 1; kd = master->kn->kd; - if (kd != master && !update_compat(kd)) { + if (kd != master) { km_unref(master); km_ref(kd); master = kd; @@ -885,38 +843,4 @@ void km_unref(kdata *kd) G_DESTROYGROUP(kd->g); } -/* --- @km_getpubkey@ --- * - * - * Arguments: @const char *tag@ = public key tag to load - * @ge *kpub@ = where to put the public key - * @time_t *t_exp@ = where to put the expiry time - * - * Returns: Zero if OK, nonzero if it failed. - * - * Use: Fetches a public key from the keyring. (Temporary - * compatibility hack.) - */ - -int km_getpubkey(const char *tag, ge *kpub, time_t *t_exp) -{ - kdata *kd; - int rc = -1; - - if ((kd = km_findpub(tag)) == 0) - goto done_0; - if (!km_samealgsp(kd, master)) { - a_warn("KEYMGMT", "public-keyring", - "%s", kd->kn->kh->kr, "key", "%s", kd->tag, - "algorithm-mismatch", A_END); - goto done_1; - } - G_COPY(gg, kpub, kd->kpub); - *t_exp = kd->t_exp; - rc = 0; -done_1: - km_unref(kd); -done_0: - return (rc); -} - /*----- That's all, folks -------------------------------------------------*/ diff --git a/server/keyset.c b/server/keyset.c index 1f580ff7..898c55a4 100644 --- a/server/keyset.c +++ b/server/keyset.c @@ -293,6 +293,7 @@ keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p) keyset *ks = CREATE(keyset); time_t now = time(0); const octet *pp = k; + const algswitch *algs = &p->kx.kpriv->algs; T( static unsigned seq = 0; ) T( trace(T_KEYSET, "keyset: adding new keyset %u", seq); ) @@ -308,21 +309,21 @@ keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p) #define HASH_in MINE; YOURS; OURS #define HASH_out YOURS; MINE; OURS -#define INIT_c(k) GC_INIT(algs.c, (k), algs.cksz) -#define INIT_m(k) GM_KEY(algs.m, (k), algs.mksz) +#define INIT_c(k) GC_INIT(algs->c, (k), algs->cksz) +#define INIT_m(k) GM_KEY(algs->m, (k), algs->mksz) #define STR_c "encryption" #define STR_m "integrity" #define STR_in "incoming" #define STR_out "outgoing" #define SETKEY(a, dir) do { \ - h = GH_INIT(algs.h); \ + h = GH_INIT(algs->h); \ HASH_STRING(h, "tripe-" STR_##a); \ HASH_##dir; \ hh = GH_DONE(h, 0); \ IF_TRACING(T_KEYSET, { \ trace_block(T_CRYPTO, "crypto: " STR_##dir " key " STR_##a, \ - hh, algs.a##ksz); \ + hh, algs->a##ksz); \ }) \ ks->a##dir = INIT_##a(hh); \ GH_DESTROY(h); \ @@ -347,14 +348,14 @@ keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p) T( ks->seq = seq++; ) ks->ref = 1; ks->t_exp = now + T_EXP; - ks->sz_exp = algs.expsz; - ks->sz_regen = algs.expsz/2; + ks->sz_exp = algs->expsz; + ks->sz_regen = algs->expsz/2; ks->oseq = 0; seq_reset(&ks->iseq); ks->next = 0; ks->p = p; ks->f = KSF_LISTEN; - ks->tagsz = algs.tagsz; + ks->tagsz = algs->tagsz; return (ks); } diff --git a/server/tripe-admin.5.in b/server/tripe-admin.5.in index 0ab6711b..a27179d8 100644 --- a/server/tripe-admin.5.in +++ b/server/tripe-admin.5.in @@ -375,10 +375,15 @@ Emits an line reporting the IP address and port number stored for .IR peer . .SP -.B "ALGS" +.BI "ALGS \fR[" peer \fR] Emits information about the cryptographic algorithms in use, in -key-value form. The keys are as follows. +key-value form. If a +.I peer +is given, then describe the algorithms used in the association with that +peer; otherwise describe the default algorithms. .RS +.PP +The keys are as follows. .TP .B kx-group Type of key-exchange group in use, currently either @@ -1306,6 +1311,12 @@ is one of the tokens or .BR switch-ok . .SP +.BI "KX " peer " algorithms-mismatch local-private-key " privtag " peer-public-key " pubtag +The algorithms specified in the peer's public key +.I pubtag +don't match the ones described in the private key +.IR privtag . +.SP .BI "KX " peer " bad-expected-reply-log" The challenges .B tripe @@ -1329,9 +1340,11 @@ A message didn't contain the right magic data. This may be a replay of some old exchange, or random packets being sent in an attempt to waste CPU. .SP -.BI "KX " peer " public-key-expired" -The peer's public key has expired. It's maintainer should have given -you a replacement before now. +.BI "KX " peer " " which "-key-expired" +The local private key or the peer's public key (distinguished by +.IR which ) +has expired. Either you or the peer's maintainer should have arranged +for a replacement before now. .SP .BI "KX " peer " sending-cookie" We've received too many bogus pre-challenge messages. Someone is trying diff --git a/server/tripe.h b/server/tripe.h index 217a88df..b22dccce 100644 --- a/server/tripe.h +++ b/server/tripe.h @@ -153,8 +153,6 @@ typedef struct algswitch { size_t cksz, mksz; /* Key lengths for @c@ and @m@ */ } algswitch; -extern algswitch algs; - typedef struct kdata { unsigned ref; /* Reference counter */ struct knode *kn; /* Pointer to cache entry */ @@ -277,12 +275,12 @@ typedef struct kxchal { typedef struct keyexch { struct peer *p; /* Pointer back to the peer */ + kdata *kpriv; /* Private key and related info */ + kdata *kpub; /* Peer's public key */ keyset **ks; /* Peer's list of keysets */ unsigned f; /* Various useful flags */ unsigned s; /* Current state in exchange */ sel_timer t; /* Timer for next exchange */ - ge *kpub; /* Peer's public key */ - time_t texp_kpub; /* Expiry time for public key */ mp *alpha; /* My temporary secret */ ge *c; /* My challenge */ ge *rx; /* The expected response */ @@ -519,10 +517,6 @@ typedef struct admin { /*----- Global variables --------------------------------------------------*/ extern sel_state sel; /* Global I/O event state */ -extern group *gg; /* The group we work in */ -extern size_t indexsz; /* Size of exponent for the group */ -extern mp *kpriv; /* Our private key */ -extern ge *kpub; /* Our public key */ extern octet buf_i[PKBUFSZ], buf_o[PKBUFSZ], buf_t[PKBUFSZ], buf_u[PKBUFSZ]; extern const tunnel_ops *tunnels[]; /* Table of tunnels (0-term) */ extern const tunnel_ops *tun_default; /* Default tunnel to use */ @@ -621,21 +615,6 @@ extern void km_unref(kdata */*kd*/); extern const char *km_tag(kdata */*kd*/); -/* --- @km_getpubkey@ --- * - * - * Arguments: @const char *tag@ = public key tag to load - * @ge *kpub@ = where to put the public key - * @time_t *t_exp@ = where to put the expiry time - * - * Returns: Zero if OK, nonzero if it failed. - * - * Use: Fetches a public key from the keyring. (Temporary - * compatibility hack.) - */ - -extern int km_getpubkey(const char */*tag*/, ge */*kpub*/, - time_t */*t_exp*/); - /*----- Key exchange ------------------------------------------------------*/ /* --- @kx_start@ --- * diff --git a/svc/watch.in b/svc/watch.in index 140f1fce..5917c79e 100644 --- a/svc/watch.in +++ b/svc/watch.in @@ -577,15 +577,15 @@ def encode_envvars(env, prefix, vars): env[prefix + r_bad.sub('_', k.upper())] = v r_bad = RX.compile(r'[\W_]+') -def envvars(info): +def envvars(peer, info): """ - Translate the database INFO dictionary for a peer into a dictionary of + Translate the database INFO dictionary for a PEER into a dictionary of environment variables with plausible upper-case names and a P_ prefix. Also collect the crypto information into A_ variables. """ env = {} encode_envvars(env, 'P_', info) - encode_envvars(env, 'A_', S.algs()) + encode_envvars(env, 'A_', S.algs(peer)) return env def ifupdown(what, peer, info, *args): @@ -602,7 +602,7 @@ def ifupdown(what, peer, info, *args): c = Command([what, peer], q, what, M.split(info[what], quotep = True)[0] + [peer] + list(args), - envvars(info)) + envvars(peer, info)) potwatch(what, peer, q) def addpeer(info, peer, ifname, *addr): -- [mdw]