From 00e64b67d321bf53224d546dcba58c52834a7b79 Mon Sep 17 00:00:00 2001 Message-Id: <00e64b67d321bf53224d546dcba58c52834a7b79.1715514464.git.mdw@distorted.org.uk> From: Mark Wooding Date: Fri, 22 Jun 2001 19:40:36 +0000 Subject: [PATCH] Support expiry of other peers' public keys. Organization: Straylight/Edgeware From: mdw --- keyexch.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++--------- keymgmt.c | 15 +++++++++--- tripe.h | 12 +++++++-- 3 files changed, 83 insertions(+), 17 deletions(-) diff --git a/keyexch.c b/keyexch.c index 55e302cf..c17f4009 100644 --- a/keyexch.c +++ b/keyexch.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: keyexch.c,v 1.3 2001/06/19 22:07:09 mdw Exp $ + * $Id: keyexch.c,v 1.4 2001/06/22 19:40:36 mdw Exp $ * * Key exchange protocol * @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: keyexch.c,v $ + * 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. * @@ -537,12 +540,14 @@ static void resend(keyexch *kx) switch (kx->s) { case KXS_CHAL: - T( trace(T_KEYEXCH, "sending prechallenge to `%s'", p_name(kx->p)); ) + T( trace(T_KEYEXCH, "keyexch: sending prechallenge to `%s'", + p_name(kx->p)); ) b = p_txstart(kx->p, MSG_KEYEXCH | KX_PRECHAL); buf_putmp(b, kx->c); break; case KXS_COMMIT: - T( trace(T_KEYEXCH, "sending switch request to `%s'", p_name(kx->p)); ) + 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, HASHSZ); @@ -554,7 +559,7 @@ static void resend(keyexch *kx) ks_encrypt(kxc->ks, &bb, b); break; case KXS_SWITCH: - T( trace(T_KEYEXCH, "sending switch confirmation to `%s'", + T( trace(T_KEYEXCH, "keyexch: sending switch confirmation to `%s'", p_name(kx->p)); ) kxc = kx->r[0]; b = p_txstart(kx->p, MSG_KEYEXCH | KX_SWITCHOK); @@ -845,6 +850,9 @@ static void stop(keyexch *kx) { unsigned i; + if (kx->f & KXF_DEAD) + return; + if (kx->f & KXF_TIMER) sel_rmtimer(&kx->t); for (i = 0; i < kx->nr; i++) @@ -852,6 +860,9 @@ static void stop(keyexch *kx) mp_drop(kx->alpha); mp_drop(kx->c); mp_drop(kx->rx); + kx->t_valid = 0; + kx->f |= KXF_DEAD; + kx->f &= ~KXF_TIMER; } /* --- @start@ --- * @@ -869,8 +880,10 @@ static void start(keyexch *kx, time_t now) { HASH_CTX h; + assert(kx->f & KXF_DEAD); + + kx->f &= ~KXF_DEAD; kx->nr = 0; - kx->f = 0; kx->alpha = mprand_range(MP_NEW, kpriv.dp.q, &rand_global, 0); kx->c = mpmont_exp(&mg, MP_NEW, kpriv.dp.g, kx->alpha); kx->rx = mpmont_exp(&mg, MP_NEW, kx->kpub.y, kx->alpha); @@ -893,6 +906,32 @@ static void start(keyexch *kx, time_t now) }) } +/* --- @checkpub@ --- * + * + * Arguments: @keyexch *kx@ = pointer to key exchange context + * + * Returns: Zero if OK, nonzero if the peer's public key has expired. + * + * Use: Deactivates the key-exchange until the peer acquires a new + * public key. + */ + +static int checkpub(keyexch *kx) +{ + time_t now; + if (kx->f & KXF_DEAD) + return (-1); + now = time(0); + if (KEY_EXPIRED(now, kx->texp_kpub)) { + stop(kx); + a_warn("public key for `%s' has expired", p_name(kx->p)); + dh_pubfree(&kx->kpub); + kx->f &= ~KXF_PUBKEY; + return (-1); + } + return (0); +} + /* --- @kx_start@ --- * * * Arguments: @keyexch *kx@ = pointer to key exchange context @@ -908,6 +947,8 @@ void kx_start(keyexch *kx) { time_t now = time(0); + if (checkpub(kx)) + return; if (!ISVALID(kx, now)) { stop(kx); start(kx, now); @@ -941,6 +982,9 @@ void kx_message(keyexch *kx, unsigned msg, buf *b) }; #endif + if (checkpub(kx)) + return; + if (!ISVALID(kx, now)) { stop(kx); start(kx, now); @@ -991,7 +1035,8 @@ void kx_message(keyexch *kx, unsigned msg, buf *b) void kx_free(keyexch *kx) { stop(kx); - dh_pubfree(&kx->kpub); + if (kx->f & KXF_PUBKEY) + dh_pubfree(&kx->kpub); } /* --- @kx_newkeys@ --- * @@ -1010,15 +1055,18 @@ void kx_newkeys(keyexch *kx) { dh_pub dp; - if (km_getpubkey(p_name(kx->p), &dp)) + if (km_getpubkey(p_name(kx->p), &dp, &kx->texp_kpub)) return; - dh_pubfree(&kx->kpub); + if (kx->f & KXF_PUBKEY) + dh_pubfree(&kx->kpub); kx->kpub = dp; - if (kx->s != KXS_SWITCH) { + kx->f |= KXF_PUBKEY; + if ((kx->f & KXF_DEAD) || kx->s != KXS_SWITCH) { T( trace(T_KEYEXCH, "keyexch: restarting key negotiation with `%s'", p_name(kx->p)); ) - kx->t_valid = 0; - kx_start(kx); + stop(kx); + start(kx, time(0)); + resend(kx); } } @@ -1039,8 +1087,9 @@ int kx_init(keyexch *kx, peer *p, keyset **ks) { kx->ks = ks; kx->p = p; - if (km_getpubkey(p_name(p), &kx->kpub)) + if (km_getpubkey(p_name(p), &kx->kpub, &kx->texp_kpub)) return (-1); + kx->f = KXF_DEAD | KXF_PUBKEY; start(kx, time(0)); resend(kx); return (0); diff --git a/keymgmt.c b/keymgmt.c index 55a188bb..54a31b0b 100644 --- a/keymgmt.c +++ b/keymgmt.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: keymgmt.c,v 1.2 2001/06/19 22:07:09 mdw Exp $ + * $Id: keymgmt.c,v 1.3 2001/06/22 19:40:36 mdw Exp $ * * Key loading and storing * @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: keymgmt.c,v $ + * Revision 1.3 2001/06/22 19:40:36 mdw + * Support expiry of other peers' public keys. + * * Revision 1.2 2001/06/19 22:07:09 mdw * Cosmetic fixes. * @@ -233,21 +236,26 @@ void km_init(const char *priv, const char *pub, const char *tag) * * Arguments: @const char *tag@ = public key tag to load * @dh_pub *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. */ -int km_getpubkey(const char *tag, dh_pub *kpub) +int km_getpubkey(const char *tag, dh_pub *kpub, time_t *t_exp) { key_packstruct kps[DH_PUBFETCHSZ]; key_packdef *kp; + key *k; dh_pub dp; int e; kp = key_fetchinit(dh_pubfetch, kps, &dp); - e = key_fetchbyname(kp, kf_pub, tag); + if ((k = key_bytag(kf_pub, tag)) == 0) + e = KERR_NOTFOUND; + else + e = key_fetch(kp, k); key_fetchdone(kp); if (e) { a_warn("error loading public key `%s': %s", tag, key_strerror(e)); @@ -272,6 +280,7 @@ int km_getpubkey(const char *tag, dh_pub *kpub) kpub->dp.q = MP_COPY(dp.dp.q); kpub->dp.g = MP_COPY(dp.dp.g); kpub->y = MP_COPY(dp.y); + *t_exp = k->exp; return (0); } diff --git a/tripe.h b/tripe.h index 9a180328..06fbf8f1 100644 --- a/tripe.h +++ b/tripe.h @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: tripe.h,v 1.8 2001/06/19 22:10:57 mdw Exp $ + * $Id: tripe.h,v 1.9 2001/06/22 19:40:36 mdw Exp $ * * Main header file for TrIPE * @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: tripe.h,v $ + * Revision 1.9 2001/06/22 19:40:36 mdw + * Support expiry of other peers' public keys. + * * Revision 1.8 2001/06/19 22:10:57 mdw * Some more constants for the algorithms. Document the packet format * change for non-malleability. Moved @buf@ definitions to separate header @@ -335,6 +338,7 @@ typedef struct keyexch { unsigned s; /* Current state in exchange */ sel_timer t; /* Timer for next exchange */ dh_pub kpub; /* Peer's public key */ + time_t texp_kpub; /* Expiry time for public key */ mp *alpha; /* My temporary secret */ mp *c; /* My challenge */ mp *rx; /* The expected response */ @@ -345,6 +349,8 @@ typedef struct keyexch { } keyexch; #define KXF_TIMER 1u /* Waiting for a timer to go off */ +#define KXF_DEAD 2u /* The key-exchanger isn't up */ +#define KXF_PUBKEY 4u /* Key exchanger has a public key */ enum { KXS_DEAD, /* Uninitialized state (magical) */ @@ -484,13 +490,15 @@ extern void km_init(const char */*kr_priv*/, const char */*kr_pub*/, * * Arguments: @const char *tag@ = public key tag to load * @dh_pub *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. */ -extern int km_getpubkey(const char */*tag*/, dh_pub */*kpub*/); +extern int km_getpubkey(const char */*tag*/, dh_pub */*kpub*/, + time_t */*t_exp*/); /*----- Key exchange ------------------------------------------------------*/ -- [mdw]