X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/52c03a2aa0b5c3461055ca0dcf38e29f2ca88f35..452bf3f6897b8c6a22b51e1ef228da39136d51a7:/keyexch.c?ds=inline diff --git a/keyexch.c b/keyexch.c index ea503583..ea4748e2 100644 --- a/keyexch.c +++ b/keyexch.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: keyexch.c,v 1.11 2004/04/03 12:35:13 mdw Exp $ + * $Id$ * * Key exchange protocol * @@ -26,48 +26,6 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: keyexch.c,v $ - * Revision 1.11 2004/04/03 12:35:13 mdw - * Support elliptic curve key exchange. - * - * Revision 1.10 2003/10/15 09:29:38 mdw - * Cosmetic fix to changelog comment. - * - * Revision 1.9 2003/07/13 11:53:14 mdw - * Add protocol commentary. - * - * Revision 1.8 2003/07/13 11:19:49 mdw - * Incompatible protocol fix! Include message type code under MAC tag to - * prevent cut-and-paste from key-exchange messages to general packet - * transport. - * - * Revision 1.7 2003/05/17 11:01:28 mdw - * Handle flags on challenge timers correctly to prevent confusing the event - * list. - * - * Revision 1.6 2003/04/06 10:26:35 mdw - * Report peer name on decrypt errors. - * - * Revision 1.5 2002/01/13 14:54:40 mdw - * Patch up zero-knowledge property by passing an encrypted log with a - * challenge, so that the prover can verify that the challenge is good. - * - * Revision 1.4 2001/06/22 19:40:36 mdw - * Support expiry of other peers' public keys. - * - * Revision 1.3 2001/06/19 22:07:09 mdw - * Cosmetic fixes. - * - * Revision 1.2 2001/02/16 21:24:27 mdw - * Rewrite for new key exchange protocol. - * - * Revision 1.1 2001/02/03 20:26:37 mdw - * Initial checkin. - * - */ - /*----- Header files ------------------------------------------------------*/ #include "tripe.h" @@ -114,7 +72,7 @@ * Challenge accpeted: here's the answer. Commit to my challenge. Move * to @KXS_COMMIT@. * - * %$\cookie{kx-switch}, c_A, c_B, E_K(r_B^\alpha, w_A))$% + * %$\cookie{kx-switch-rq}, c_A, c_B, E_K(r_B^\alpha, w_A))$% * Reply received: here's my reply. Committed; send data; move to * @KXS_SWITCH@. * @@ -127,13 +85,20 @@ #define T_VALID MIN(2) /* Challenge validity period */ #define T_RETRY SEC(10) /* Challenge retransmit interval */ -#define ISVALID(kx, now) ((now) < (kx)->t_valid) +#define VALIDP(kx, now) ((now) < (kx)->t_valid) + +/*----- Static tables -----------------------------------------------------*/ + +static const char *const pkname[] = { + "pre-challenge", "cookie", "challenge", + "reply", "switch-rq", "switch-ok" +}; /*----- Various utilities -------------------------------------------------*/ /* --- @hashge@ --- * * - * Arguments: @HASH_CTX *r@ = pointer to hash context + * Arguments: @ghash *h@ = pointer to hash context * @ge *x@ = pointer to group element * * Returns: --- @@ -142,22 +107,21 @@ * @buf_t@. */ -static void hashge(HASH_CTX *r, ge *x) +static void hashge(ghash *h, ge *x) { buf b; buf_init(&b, buf_t, sizeof(buf_t)); G_TOBUF(gg, &b, x); assert(BOK(&b)); - HASH(r, BBASE(&b), BLEN(&b)); + GH_HASH(h, BBASE(&b), BLEN(&b)); } -/* --- @mpcrypt@ --- * +/* --- @mpencrypt@, @mpdecrypt@ --- * * * Arguments: @mp *d@ = the destination integer * @mp *x@ = the plaintext/ciphertext integer * @size_t sz@ = the expected size of the plaintext * @const octet *k@ = pointer to key material - * @size_t ksz@ = size of the key * * Returns: The encrypted/decrypted integer. * @@ -167,13 +131,25 @@ static void hashge(HASH_CTX *r, ge *x) * encryption thing. */ -static mp *mpcrypt(mp *d, mp *x, size_t sz, const octet *k, size_t ksz) +static mp *mpencrypt(mp *d, mp *x, size_t sz, const octet *k) { - MGF_CTX m; + gcipher *mgf; - MGF_INIT(&m, k, ksz, 0); + mgf = GC_INIT(algs.mgf, k, algs.hashsz); mp_storeb(x, buf_t, sz); - MGF_CRYPT(&m, buf_t, buf_t, sz); + GC_ENCRYPT(mgf, buf_t, buf_t, sz); + GC_DESTROY(mgf); + return (mp_loadb(d, buf_t, sz)); +} + +static mp *mpdecrypt(mp *d, mp *x, size_t sz, const octet *k) +{ + gcipher *mgf; + + mgf = GC_INIT(algs.mgf, k, algs.hashsz); + mp_storeb(x, buf_t, sz); + GC_DECRYPT(mgf, buf_t, buf_t, sz); + GC_DESTROY(mgf); return (mp_loadb(d, buf_t, sz)); } @@ -192,7 +168,7 @@ static void timer(struct timeval *tv, void *v) keyexch *kx = v; kx->f &= ~KXF_TIMER; T( trace(T_KEYEXCH, "keyexch: timer has popped"); ) - kx_start(kx); + kx_start(kx, 0); } /* --- @settimer@ --- * @@ -341,7 +317,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, HASHSZ) == 0) + if (memcmp(hc, kx->r[i]->hc, algs.hashsz) == 0) return (kx->r[i]); } return (0); @@ -379,8 +355,8 @@ static void kxc_answer(keyexch *kx, kxchal *kxc) if (!kxc->r) G_TOBUF(gg, b, kx->c); else - buf_put(b, kx->hc, HASHSZ); - buf_put(b, kxc->hc, HASHSZ); + buf_put(b, kx->hc, algs.hashsz); + buf_put(b, kxc->hc, algs.hashsz); buf_putmp(b, kxc->ck); /* --- Maybe send an actual reply, if we have one --- */ @@ -432,28 +408,29 @@ static ge *getreply(keyexch *kx, ge *c, mp *ck) ge *r = G_CREATE(gg); ge *y = G_CREATE(gg); mp *a = MP_NEW; - HASH_CTX h; - octet buf[HASHSZ]; + ghash *h; + const octet *hh; int ok; G_EXP(gg, r, c, kpriv); - HASH_INIT(&h); - HASH_STRING(&h, "tripe-expected-reply"); - hashge(&h, c); - hashge(&h, kx->c); - hashge(&h, r); - HASH_DONE(&h, buf); - - a = mpcrypt(MP_NEW, ck, mp_octets(gg->r), buf, sizeof(buf)); + h = GH_INIT(algs.h); + HASH_STRING(h, "tripe-expected-reply"); + hashge(h, c); + hashge(h, kx->c); + hashge(h, r); + hh = GH_DONE(h, 0); + + a = mpdecrypt(MP_NEW, ck, mp_octets(gg->r), hh); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { trace(T_CRYPTO, "crypto: computed reply = %s", gestr(gg, r)); - trace_block(T_CRYPTO, "crypto: computed reply hash", buf, HASHSZ); + trace_block(T_CRYPTO, "crypto: computed reply hash", hh, algs.hashsz); trace(T_CRYPTO, "crypto: recovered log = %s", mpstr(a)); })) + GH_DESTROY(h); G_EXP(gg, y, gg->g, a); ok = G_EQ(gg, y, c); if (!ok) { - a_warn("invalid expected-reply check from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "bad-expected-reply-log", A_END); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { trace(T_CRYPTO, "crypto: computed challenge = %s", gestr(gg, y)); })) @@ -482,29 +459,28 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b) mp *ck = MP_NEW; const octet *hc = 0; kxchal *kxc; - HASH_CTX h; - octet buf[HASHSZ]; + ghash *h; /* --- Ensure that we're in a sensible state --- */ if (kx->s != KXS_CHAL) { - a_warn("unexpected challenge from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unexpected", "%s", pkname[msg], A_END); goto bad; } /* --- Unpack the packet --- */ if (G_FROMBUF(gg, b, c) || - (msg >= KX_COOKIE && (hc = buf_get(b, HASHSZ)) == 0) || + (msg >= KX_COOKIE && (hc = buf_get(b, algs.hashsz)) == 0) || (msg >= KX_CHAL && (ck = buf_getmp(b)) == 0) || BLEFT(b)) { - a_warn("malformed packet from `%s'", p_name(kx->p)); + 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)); - if (hc) trace_block(T_CRYPTO, "crypto: cookie", hc, HASHSZ); + if (hc) trace_block(T_CRYPTO, "crypto: cookie", hc, algs.hashsz); if (ck) trace(T_CRYPTO, "crypto: check value = %s", mpstr(ck)); })) @@ -515,20 +491,22 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b) if (!hc && kx->nr >= KX_THRESH) { T( trace(T_KEYEXCH, "keyexch: too many challenges -- sending cookie"); ) + a_warn("KX", "?PEER", p_name, "sending-cookie", A_END); b = p_txstart(kx->p, MSG_KEYEXCH | KX_COOKIE); G_TOBUF(gg, b, kx->c); - HASH_INIT(&h); - HASH_STRING(&h, "tripe-cookie"); - hashge(&h, c); - HASH_DONE(&h, buf_get(b, HASHSZ)); + h = GH_INIT(algs.h); + HASH_STRING(h, "tripe-cookie"); + hashge(h, c); + GH_DONE(h, buf_get(b, algs.hashsz)); + GH_DESTROY(h); p_txend(kx->p); goto tidy; } /* --- Discard a packet with an invalid cookie --- */ - if (hc && memcmp(hc, kx->hc, HASHSZ) != 0) { - a_warn("incorrect cookie from `%s'", p_name(kx->p)); + if (hc && memcmp(hc, kx->hc, algs.hashsz) != 0) { + a_warn("KX", "?PEER", "incorrect", "cookie", A_END); goto bad; } @@ -561,57 +539,64 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b) /* --- Work out the cookie for this challenge --- */ - HASH_INIT(&h); - HASH_STRING(&h, "tripe-cookie"); - hashge(&h, kxc->c); - HASH_DONE(&h, kxc->hc); + h = GH_INIT(algs.h); + HASH_STRING(h, "tripe-cookie"); + hashge(h, 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); + })) /* --- Compute the expected-reply hash --- */ - HASH_INIT(&h); - HASH_STRING(&h, "tripe-expected-reply"); - hashge(&h, kx->c); - hashge(&h, kxc->c); - hashge(&h, kx->rx); - HASH_DONE(&h, buf); - kxc->ck = mpcrypt(MP_NEW, kx->alpha, mp_octets(gg->r), - buf, sizeof(buf)); + h = GH_INIT(algs.h); + HASH_STRING(h, "tripe-expected-reply"); + hashge(h, kx->c); + hashge(h, kxc->c); + hashge(h, kx->rx); + hc = GH_DONE(h, 0); + kxc->ck = mpencrypt(MP_NEW, kx->alpha, mp_octets(gg->r), hc); + IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { + trace_block(T_CRYPTO, "crypto: expected-reply hash", hc, algs.hashsz); + trace(T_CRYPTO, "crypto: my reply check = %s", mpstr(kxc->ck)); + })) + GH_DESTROY(h); /* --- Work out the shared key --- */ r = G_CREATE(gg); G_EXP(gg, r, c, kx->alpha); + IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { + trace(T_CRYPTO, "crypto: shared secret = %s", gestr(gg, r)); + })) /* --- Compute the switch messages --- */ - HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-request"); - hashge(&h, kx->c); hashge(&h, kxc->c); - HASH_DONE(&h, kxc->hswrq_out); - HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-confirm"); - hashge(&h, kx->c); hashge(&h, kxc->c); - HASH_DONE(&h, kxc->hswok_out); + h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-request"); + hashge(h, kx->c); hashge(h, 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); + GH_DONE(h, kxc->hswok_out); GH_DESTROY(h); - HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-request"); - hashge(&h, kxc->c); hashge(&h, kx->c); - HASH_DONE(&h, kxc->hswrq_in); - HASH_INIT(&h); HASH_STRING(&h, "tripe-switch-confirm"); - hashge(&h, kxc->c); hashge(&h, kx->c); - HASH_DONE(&h, kxc->hswok_in); + h = GH_INIT(algs.h); HASH_STRING(h, "tripe-switch-request"); + hashge(h, kxc->c); hashge(h, 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); + GH_DONE(h, kxc->hswok_in); GH_DESTROY(h); IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { - trace_block(T_CRYPTO, "crypto: computed cookie", kxc->hc, HASHSZ); - trace_block(T_CRYPTO, "crypto: expected-reply hash", - buf, HASHSZ); - trace(T_CRYPTO, "crypto: my reply check = %s", mpstr(kxc->ck)); - trace(T_CRYPTO, "crypto: shared secret = %s", gestr(gg, r)); trace_block(T_CRYPTO, "crypto: outbound switch request", - kxc->hswrq_out, HASHSZ); + kxc->hswrq_out, algs.hashsz); trace_block(T_CRYPTO, "crypto: outbound switch confirm", - kxc->hswok_out, HASHSZ); + kxc->hswok_out, algs.hashsz); trace_block(T_CRYPTO, "crypto: inbound switch request", - kxc->hswrq_in, HASHSZ); + kxc->hswrq_in, algs.hashsz); trace_block(T_CRYPTO, "crypto: inbound switch confirm", - kxc->hswok_in, HASHSZ); + kxc->hswok_in, algs.hashsz); })) /* --- Create a new symmetric keyset --- */ @@ -678,11 +663,11 @@ static void resend(keyexch *kx) p_name(kx->p)); ) kxc = kx->r[0]; b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCH); - buf_put(b, kx->hc, HASHSZ); - buf_put(b, kxc->hc, HASHSZ); + buf_put(b, kx->hc, algs.hashsz); + buf_put(b, kxc->hc, algs.hashsz); buf_init(&bb, buf_i, sizeof(buf_i)); G_TOBUF(gg, &bb, kxc->r); - buf_put(&bb, kxc->hswrq_out, HASHSZ); + buf_put(&bb, kxc->hswrq_out, algs.hashsz); buf_flip(&bb); ks_encrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCH, &bb, b); break; @@ -692,7 +677,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, HASHSZ); + buf_put(&bb, kxc->hswok_out, algs.hashsz); buf_flip(&bb); ks_encrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCHOK, &bb, b); break; @@ -737,16 +722,16 @@ static kxchal *matchreply(keyexch *kx, unsigned ty, const octet *hc_in, /* --- Check the plaintext portions of the data --- */ IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { - trace_block(T_CRYPTO, "crypto: challenge", hc_in, HASHSZ); - trace_block(T_CRYPTO, "crypto: cookie", hc_out, HASHSZ); + trace_block(T_CRYPTO, "crypto: challenge", hc_in, algs.hashsz); + trace_block(T_CRYPTO, "crypto: cookie", hc_out, algs.hashsz); if (ck) trace(T_CRYPTO, "crypto: check value = %s", mpstr(ck)); })) - if (memcmp(hc_out, kx->hc, HASHSZ) != 0) { - a_warn("incorrect cookie from `%s'", p_name(kx->p)); + if (memcmp(hc_out, kx->hc, algs.hashsz) != 0) { + a_warn("KX", "?PEER", kx->p, "incorrect", "cookie", A_END); goto bad; } if ((kxc = kxc_byhc(kx, hc_in)) == 0) { - a_warn("received reply for unknown challenge from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unknown-challenge", A_END); goto bad; } @@ -754,7 +739,7 @@ static kxchal *matchreply(keyexch *kx, unsigned ty, const octet *hc_in, if (!kxc->r) { if (!ck) { - a_warn("unexpected switch request from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unexpected", "switch-rq", A_END); goto bad; } if ((r = getreply(kx, kxc->c, ck)) == 0) @@ -767,20 +752,20 @@ static kxchal *matchreply(keyexch *kx, unsigned ty, const octet *hc_in, buf_init(&bb, buf_o, sizeof(buf_o)); if (ks_decrypt(kxc->ks, ty, b, &bb)) { - a_warn("failed to decrypt reply from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "decrypt-failed", "reply", A_END); goto bad; } buf_init(b, BBASE(&bb), BLEN(&bb)); r = G_CREATE(gg); if (G_FROMBUF(gg, b, r)) { - a_warn("invalid reply packet from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "invalid", "reply", A_END); goto bad; } IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, { trace(T_CRYPTO, "crypto: reply = %s", gestr(gg, r)); })) if (!G_EQ(gg, r, kx->rx)) { - a_warn("incorrect reply from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "incorrect", "reply", A_END); goto bad; } @@ -837,20 +822,20 @@ static int doreply(keyexch *kx, buf *b) kxchal *kxc; if (kx->s != KXS_CHAL && kx->s != KXS_COMMIT) { - a_warn("unexpected reply from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unexpected", "reply", A_END); goto bad; } - if ((hc_in = buf_get(b, HASHSZ)) == 0 || - (hc_out = buf_get(b, HASHSZ)) == 0 || + if ((hc_in = buf_get(b, algs.hashsz)) == 0 || + (hc_out = buf_get(b, algs.hashsz)) == 0 || (ck = buf_getmp(b)) == 0) { - a_warn("invalid reply packet from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "invalid", "reply", A_END); goto bad; } if ((kxc = matchreply(kx, MSG_KEYEXCH | KX_REPLY, hc_in, hc_out, ck, b)) == 0) goto bad; if (BLEFT(b)) { - a_warn("invalid reply packet from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "invalid", "reply", A_END); goto bad; } if (kx->s == KXS_CHAL) { @@ -865,6 +850,25 @@ bad: return (-1); } +/* --- @kxfinish@ --- * + * + * Arguments: @keyexch *kx@ = pointer to key exchange block + * + * Returns: --- + * + * Use: Sets everything up following a successful key exchange. + */ + +static void kxfinish(keyexch *kx) +{ + kxchal *kxc = kx->r[0]; + ks_activate(kxc->ks); + settimer(kx, ks_tregen(kxc->ks)); + kx->s = KXS_SWITCH; + a_notify("KXDONE", "?PEER", kx->p, A_END); + p_stats(kx->p)->t_kx = time(0); +} + /* --- @doswitch@ --- * * * Arguments: @keyexch *kx@ = pointer to key exchange block @@ -880,32 +884,30 @@ static int doswitch(keyexch *kx, buf *b) const octet *hc_in, *hc_out, *hswrq; kxchal *kxc; - if ((hc_in = buf_get(b, HASHSZ)) == 0 || - (hc_out = buf_get(b, HASHSZ)) == 0) { - a_warn("invalid switch request from `%s'", p_name(kx->p)); + if ((hc_in = buf_get(b, algs.hashsz)) == 0 || + (hc_out = buf_get(b, algs.hashsz)) == 0) { + a_warn("KX", "?PEER", kx->p, "invalid", "switch-rq", A_END); goto bad; } if ((kxc = matchreply(kx, MSG_KEYEXCH | KX_SWITCH, hc_in, hc_out, 0, b)) == 0) goto bad; - if ((hswrq = buf_get(b, HASHSZ)) == 0 || BLEFT(b)) { - a_warn("invalid switch request from `%s'", p_name(kx->p)); + if ((hswrq = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) { + a_warn("KX", "?PEER", "invalid", "switch-rq", A_END); goto bad; } IF_TRACING(T_KEYEXCH, { - trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, HASHSZ); + trace_block(T_CRYPTO, "crypto: switch request hash", hswrq, algs.hashsz); }) - if (memcmp(hswrq, kxc->hswrq_in, HASHSZ) != 0) { - a_warn("incorrect switch request hash from `%s'", p_name(kx->p)); + if (memcmp(hswrq, kxc->hswrq_in, algs.hashsz) != 0) { + a_warn("KX", "?PEER", kx->p, "incorrect", "switch-rq", A_END); goto bad; } switch (kx->s) { case KXS_CHAL: commit(kx, kxc); case KXS_COMMIT: - ks_activate(kxc->ks); - settimer(kx, ks_tregen(kxc->ks)); - kx->s = KXS_SWITCH; + kxfinish(kx); break; } resend(kx); @@ -932,32 +934,30 @@ static int doswitchok(keyexch *kx, buf *b) buf bb; if (kx->s < KXS_COMMIT) { - a_warn("unexpected switch confirmation from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unexpected", "switch-ok", A_END); goto bad; } kxc = kx->r[0]; buf_init(&bb, buf_o, sizeof(buf_o)); if (ks_decrypt(kxc->ks, MSG_KEYEXCH | KX_SWITCHOK, b, &bb)) { - a_warn("failed to decrypt switch confirmation from `%s'", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "decrypt-failed", "switch-ok", A_END); goto bad; } buf_init(b, BBASE(&bb), BLEN(&bb)); - if ((hswok = buf_get(b, HASHSZ)) == 0 || BLEFT(b)) { - a_warn("invalid switch confirmation from `%s'", p_name(kx->p)); + if ((hswok = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) { + a_warn("KX", "?PEER", "invalid", "switch-ok", A_END); goto bad; } IF_TRACING(T_KEYEXCH, { - trace_block(T_CRYPTO, "crypto: switch confirmation hash", hswok, HASHSZ); + trace_block(T_CRYPTO, "crypto: switch confirmation hash", + hswok, algs.hashsz); }) - if (memcmp(hswok, kxc->hswok_in, HASHSZ) != 0) { - a_warn("incorrect switch confirmation hash from `%s'", p_name(kx->p)); + if (memcmp(hswok, kxc->hswok_in, algs.hashsz) != 0) { + a_warn("KX", "?PEER", kx->p, "incorrect", "switch-ok", A_END); goto bad; } - if (kx->s < KXS_SWITCH) { - ks_activate(kxc->ks); - settimer(kx, ks_tregen(kxc->ks)); - kx->s = KXS_SWITCH; - } + if (kx->s < KXS_SWITCH) + kxfinish(kx); return (0); bad: @@ -1012,7 +1012,7 @@ static void stop(keyexch *kx) static void start(keyexch *kx, time_t now) { - HASH_CTX h; + ghash *h; assert(kx->f & KXF_DEAD); @@ -1024,10 +1024,11 @@ static void start(keyexch *kx, time_t now) kx->s = KXS_CHAL; kx->t_valid = now + T_VALID; - HASH_INIT(&h); - HASH_STRING(&h, "tripe-cookie"); - hashge(&h, kx->c); - HASH_DONE(&h, kx->hc); + h = GH_INIT(algs.h); + HASH_STRING(h, "tripe-cookie"); + hashge(h, kx->c); + GH_DONE(h, kx->hc); + GH_DESTROY(h); IF_TRACING(T_KEYEXCH, { trace(T_KEYEXCH, "keyexch: creating new challenge"); @@ -1035,7 +1036,7 @@ static void start(keyexch *kx, time_t now) 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, HASHSZ); + trace_block(T_CRYPTO, "crypto: challenge cookie", kx->hc, algs.hashsz); }) }) } @@ -1058,7 +1059,7 @@ static int checkpub(keyexch *kx) now = time(0); if (KEY_EXPIRED(now, kx->texp_kpub)) { stop(kx); - a_warn("public key for `%s' has expired", p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "public-key-expired", A_END); G_COPY(gg, kx->kpub, gg->i); kx->f &= ~KXF_PUBKEY; return (-1); @@ -1069,6 +1070,7 @@ static int checkpub(keyexch *kx) /* --- @kx_start@ --- * * * Arguments: @keyexch *kx@ = pointer to key exchange context + * @int forcep@ = nonzero to ignore the quiet timer * * Returns: --- * @@ -1077,15 +1079,16 @@ static int checkpub(keyexch *kx) * this); if no exchange is in progress, one is commenced. */ -void kx_start(keyexch *kx) +void kx_start(keyexch *kx, int forcep) { time_t now = time(0); if (checkpub(kx)) return; - if (!ISVALID(kx, now)) { + if (forcep || !VALIDP(kx, now)) { stop(kx); start(kx, now); + a_notify("KXSTART", "?PEER", kx->p, A_END); } resend(kx); } @@ -1109,17 +1112,10 @@ void kx_message(keyexch *kx, unsigned msg, buf *b) size_t sz = BSZ(b); int rc; -#ifndef NTRACE - static const char *const pkname[] = { - "prechallenge", "cookie", "challenge", - "reply", "switch request", "switch confirmation" - }; -#endif - if (checkpub(kx)) return; - if (!ISVALID(kx, now)) { + if (!VALIDP(kx, now)) { stop(kx); start(kx, now); } @@ -1143,8 +1139,7 @@ void kx_message(keyexch *kx, unsigned msg, buf *b) rc = doswitchok(kx, b); break; default: - a_warn("unexpected key exchange message type %u from `%p'", - p_name(kx->p)); + a_warn("KX", "?PEER", kx->p, "unknown-message", "0x%02x", msg, A_END); rc = -1; break; } @@ -1223,6 +1218,7 @@ int kx_init(keyexch *kx, peer *p, keyset **ks) kx->f = KXF_DEAD | KXF_PUBKEY; start(kx, time(0)); resend(kx); + /* Don't notify here: the ADD message hasn't gone out yet. */ return (0); }