/* -*-c-*-
- *
- * $Id$
*
* Key exchange protocol
*
* (c) 2001 Straylight/Edgeware
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This file is part of Trivial IP Encryption (TrIPE).
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* TrIPE 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 General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with TrIPE; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* %$r_A = g^{\rho_A}$% Alice's challenge
* %$c_A = H(\cookie{cookie}, r_A)$% Alice's cookie
* %$v_A = \rho_A \xor H(\cookie{expected-reply}, a, r_A, r_B, b^{\rho_A})$%
- * Alice's challenge check value
+ * Alice's challenge check value
* %$r_B^\alpha = a^{\rho_B}$% Alice's reply
* %$K = r_B^{\rho_A} = r_B^{\rho_A} = g^{\rho_A\rho_B}$%
- * Alice and Bob's shared secret key
+ * Alice and Bob's shared secret key
* %$w_A = H(\cookie{switch-request}, c_A, c_B)$%
- * Alice's switch request value
+ * Alice's switch request value
* %$u_A = H(\cookie{switch-confirm}, c_A, c_B)$%
- * Alice's switch confirm value
+ * Alice's switch confirm value
*
* The messages are then:
*
*
* %$\cookie{kx-switch-ok}, E_K(u_A))$%
* Switch received. Committed; send data; move to @KXS_SWITCH@.
- */
-
-/*----- Tunable parameters ------------------------------------------------*/
-
-#define T_VALID MIN(2) /* Challenge validity period */
-#define T_RETRY SEC(10) /* Challenge retransmit interval */
-
-#define VALIDP(kx, now) ((now) < (kx)->t_valid)
+ */
/*----- Static tables -----------------------------------------------------*/
static const char *const pkname[] = {
- "pre-challenge", "cookie", "challenge",
- "reply", "switch-rq", "switch-ok"
+ "pre-challenge", "challenge", "reply", "switch-rq", "switch-ok"
};
/*----- Various utilities -------------------------------------------------*/
+/* --- @VALIDP@ --- *
+ *
+ * Arguments: @const keyexch *kx@ = key exchange state
+ * @time_t now@ = current time in seconds
+ *
+ * Returns: Whether the challenge in the key-exchange state is still
+ * valid or should be regenerated.
+ */
+
+#define VALIDP(kx, now) ((now) < (kx)->t_valid)
+
/* --- @hashge@ --- *
*
* Arguments: @ghash *h@ = pointer to hash context
/* --- @settimer@ --- *
*
* Arguments: @keyexch *kx@ = pointer to key exchange context
- * @time_t t@ = when to set the timer for
+ * @struct timeval *tv@ = when to set the timer for
*
* Returns: ---
*
* Use: Sets the timer for the next key exchange attempt.
*/
-static void settimer(keyexch *kx, time_t t)
+static void settimer(keyexch *kx, struct timeval *tv)
{
- struct timeval tv;
- if (kx->f & KXF_TIMER)
- sel_rmtimer(&kx->t);
- tv.tv_sec = t;
- tv.tv_usec = 0;
- sel_addtimer(&sel, &kx->t, &tv, timer, kx);
+ if (kx->f & KXF_TIMER) sel_rmtimer(&kx->t);
+ sel_addtimer(&sel, &kx->t, tv, timer, kx);
kx->f |= KXF_TIMER;
}
goto badcheck;
/* --- Fill in a new challenge block --- */
-
+
kxc = kxc_new(kx);
G_COPY(gg, kxc->c, c);
G_COPY(gg, kxc->r, r);
h = GH_INIT(algs.h);
HASH_STRING(h, "tripe-check-hash");
GH_HASH(h, ck, indexsz);
- GH_DONE(h, kxc->hc);
+ GH_DONE(h, kxc->ck);
GH_DESTROY(h);
h = GH_INIT(algs.h);
G_DESTROY(gg, cc);
G_DESTROY(gg, r);
mp_drop(cv);
- return (0);
+ return (0);
}
/* --- @dochallenge@ --- *
kxchal *kxc;
buf bb;
stats *st = p_stats(kx->p);
+ struct timeval tv;
buf *b;
switch (kx->s) {
p_txend(kx->p);
}
- if (kx->s < KXS_SWITCH)
- settimer(kx, time(0) + T_RETRY);
+ if (kx->s < KXS_SWITCH) {
+ gettimeofday(&tv, 0);
+ tv.tv_sec += T_RETRY;
+ settimer(kx, &tv);
+ }
}
/* --- @decryptrest@ --- *
a_warn("KX", "?PEER", kx->p, "decrypt-failed", "%s", pkname[msg], A_END);
return (-1);
}
+ if (!BOK(&bb)) return (-1);
buf_init(b, BBASE(&bb), BLEN(&bb));
return (0);
}
kx->r[0] = kxc;
kx->nr = 1;
kxc_stoptimer(kxc);
- ksl_link(kx->ks, kxc->ks);
+ ksl_link(kx->ks, kxc->ks);
}
/* --- @doreply@ --- *
if (BLEFT(b)) {
a_warn("KX", "?PEER", kx->p, "invalid", "reply", A_END);
goto bad;
- }
+ }
if (kx->s == KXS_CHAL) {
commit(kx, kxc);
kx->s = KXS_COMMIT;
static void kxfinish(keyexch *kx)
{
kxchal *kxc = kx->r[0];
+ struct timeval tv;
+
ks_activate(kxc->ks);
- settimer(kx, ks_tregen(kxc->ks));
+ gettimeofday(&tv, 0);
+ tv.tv_sec += T_REGEN;
+ settimer(kx, &tv);
kx->s = KXS_SWITCH;
a_notify("KXDONE", "?PEER", kx->p, A_END);
p_stats(kx->p)->t_kx = time(0);
return (0);
bad:
- return (-1);
+ return (-1);
}
/*----- Main code ---------------------------------------------------------*/
assert(kx->f & KXF_DEAD);
- 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);
void kx_message(keyexch *kx, unsigned msg, buf *b)
{
- time_t now = time(0);
+ struct timeval now, tv;
stats *st = p_stats(kx->p);
size_t sz = BSZ(b);
int rc;
+ gettimeofday(&now, 0);
+ if (kx->f & KXF_CORK) {
+ start(kx, now.tv_sec);
+ TV_ADDL(&tv, &now, T_RETRY, 0);
+ settimer(kx, &tv);
+ a_notify("KXSTART", A_END);
+ }
+
if (checkpub(kx))
return;
- if (!VALIDP(kx, now)) {
+ if (!VALIDP(kx, now.tv_sec)) {
stop(kx);
- start(kx, now);
+ start(kx, now.tv_sec);
}
-
T( trace(T_KEYEXCH, "keyexch: processing %s packet from `%s'",
msg < KX_NMSG ? pkname[msg] : "unknown", p_name(kx->p)); )
void kx_newkeys(keyexch *kx)
{
- if (km_getpubkey(p_name(kx->p), kx->kpub, &kx->texp_kpub))
+ if (km_getpubkey(p_tag(kx->p), kx->kpub, &kx->texp_kpub))
return;
kx->f |= KXF_PUBKEY;
if ((kx->f & KXF_DEAD) || kx->s != KXS_SWITCH) {
* Arguments: @keyexch *kx@ = pointer to key exchange context
* @peer *p@ = pointer to peer context
* @keyset **ks@ = pointer to keyset list
+ * @unsigned f@ = various useful flags
*
* Returns: Zero if OK, nonzero if it failed.
*
* exchange.
*/
-int kx_init(keyexch *kx, peer *p, keyset **ks)
+int kx_init(keyexch *kx, peer *p, keyset **ks, unsigned f)
{
kx->ks = ks;
kx->p = p;
kx->kpub = G_CREATE(gg);
- if (km_getpubkey(p_name(p), kx->kpub, &kx->texp_kpub)) {
+ if (km_getpubkey(p_tag(p), kx->kpub, &kx->texp_kpub)) {
G_DESTROY(gg, kx->kpub);
return (-1);
}
- kx->f = KXF_DEAD | KXF_PUBKEY;
- start(kx, time(0));
- resend(kx);
- /* Don't notify here: the ADD message hasn't gone out yet. */
+ kx->f = KXF_DEAD | KXF_PUBKEY | f;
+ if (!(kx->f & KXF_CORK)) {
+ start(kx, time(0));
+ resend(kx);
+ /* Don't notify here: the ADD message hasn't gone out yet. */
+ }
return (0);
}