keyexch, keymgmt: Include the peer's public key in the check hash.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 27 Oct 2006 16:55:27 +0000 (17:55 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 27 Oct 2006 16:55:27 +0000 (17:55 +0100)
This turns out to be necessary for security: otherwise an adversary can
cross over two sessions, which is probably undesirable.  This also
requires that we know our own public key, which was previously
unnecessary.

Except for session-ids (we don't care if two `sessions' with the same
peer get crossed over, because we don't distinguish them anyway), the
protocol now matches the one described and proved secure in the crypto
paper.

keyexch.c
keymgmt.c
tripe.h

index 80e0132..f6786e0 100644 (file)
--- a/keyexch.c
+++ b/keyexch.c
@@ -47,7 +47,7 @@
  *
  * %$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}, r_A, r_B, b^{\rho_A})$%
+ * %$v_A = \rho_A \xor H(\cookie{expected-reply}, a, r_A, r_B, b^{\rho_A})$%
  *                                     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}$%
@@ -415,6 +415,7 @@ static ge *getreply(keyexch *kx, ge *c, mp *ck)
   G_EXP(gg, r, c, kpriv);
   h = GH_INIT(algs.h);
   HASH_STRING(h, "tripe-expected-reply");
+  hashge(h, kx->kpub);
   hashge(h, c);
   hashge(h, kx->c);
   hashge(h, r);
@@ -427,8 +428,12 @@ static ge *getreply(keyexch *kx, ge *c, mp *ck)
     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 (MP_CMP(a, >=, gg->r))
+    ok = 0;
+  else{
+    G_EXP(gg, y, gg->g, a);
+    ok = G_EQ(gg, y, c);
+  }
   if (!ok) {
     a_warn("KX", "?PEER", kx->p, "bad-expected-reply-log", A_END);
     IF_TRACING(T_KEYEXCH, IF_TRACING(T_CRYPTO, {
@@ -553,6 +558,7 @@ static int dochallenge(keyexch *kx, unsigned msg, buf *b)
 
     h = GH_INIT(algs.h);
     HASH_STRING(h, "tripe-expected-reply");
+    hashge(h, kpub);
     hashge(h, kx->c);
     hashge(h, kxc->c);
     hashge(h, kx->rx);
index 7163ddd..f645d15 100644 (file)
--- a/keymgmt.c
+++ b/keymgmt.c
@@ -34,6 +34,7 @@
 
 group *gg;
 mp *kpriv;
+ge *kpub;
 algswitch algs;
 
 /*----- Static variables --------------------------------------------------*/
@@ -398,6 +399,11 @@ tymatch:;
   if (kpriv)
     mp_drop(kpriv);
 
+  if (kpub)
+    G_DESTROY(g, kpub);
+  kpub = G_CREATE(g);
+  G_EXP(g, kpub, g->g, x);
+
   /* --- Dump out the group --- */
 
   IF_TRACING(T_KEYMGMT, {
diff --git a/tripe.h b/tripe.h
index 25255f3..5f62f16 100644 (file)
--- a/tripe.h
+++ b/tripe.h
@@ -426,6 +426,7 @@ typedef struct admin {
 extern sel_state sel;                  /* Global I/O event state */
 extern group *gg;                      /* The group we work in */
 extern mp *kpriv;                      /* Our private key */
+extern ge *kpub;                       /* Our public key */
 extern octet buf_i[PKBUFSZ], buf_o[PKBUFSZ], buf_t[PKBUFSZ];
 extern const tunnel_ops *tunnels[];    /* Table of tunnels (0-term) */
 extern const tunnel_ops *tun_default;  /* Default tunnel to use */