/* -*-c-*-
*
- * $Id: keyexch.c,v 1.2 2001/02/16 21:24:27 mdw Exp $
+ * $Id: keyexch.c,v 1.4 2001/06/22 19:40:36 mdw Exp $
*
* Key exchange protocol
*
/*----- 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.
+ *
* Revision 1.2 2001/02/16 21:24:27 mdw
* Rewrite for new key exchange protocol.
*
/* --- @kxc_new@ --- *
*
* Arguments: @keyexch *kx@ = pointer to key exchange block
- * @
*
* Returns: A pointer to the challenge block.
*
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);
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);
{
unsigned i;
+ if (kx->f & KXF_DEAD)
+ return;
+
if (kx->f & KXF_TIMER)
sel_rmtimer(&kx->t);
for (i = 0; i < kx->nr; i++)
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@ --- *
{
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);
})
}
+/* --- @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
{
time_t now = time(0);
+ if (checkpub(kx))
+ return;
if (!ISVALID(kx, now)) {
stop(kx);
start(kx, now);
};
#endif
+ if (checkpub(kx))
+ return;
+
if (!ISVALID(kx, now)) {
stop(kx);
start(kx, now);
void kx_free(keyexch *kx)
{
stop(kx);
- dh_pubfree(&kx->kpub);
+ if (kx->f & KXF_PUBKEY)
+ dh_pubfree(&kx->kpub);
}
/* --- @kx_newkeys@ --- *
{
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);
}
}
{
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);