chiark / gitweb /
server/keyset.c: Return more informative error codes from ks_decrypt.
[tripe] / server / keyexch.c
index ae8c9c5..8eaf1e8 100644 (file)
@@ -1,13 +1,11 @@
 /* -*-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_VALID SEC(20)                        /* Challenge validity period */
 #define T_RETRY SEC(10)                        /* Challenge retransmit interval */
 
 #define VALIDP(kx, now) ((now) < (kx)->t_valid)
@@ -87,8 +85,7 @@
 /*----- 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 -------------------------------------------------*/
@@ -563,7 +560,7 @@ static kxchal *respond(keyexch *kx, unsigned msg, buf *b)
   /* --- Discard a packet with an invalid cookie --- */
 
   if (hc && memcmp(hc, kx->hc, algs.hashsz) != 0) {
-    a_warn("KX", "?PEER", "incorrect", "cookie", A_END);
+    a_warn("KX", "?PEER", kx->p, "incorrect", "cookie", A_END);
     goto bad;
   }
 
@@ -598,7 +595,7 @@ static kxchal *respond(keyexch *kx, unsigned msg, buf *b)
       goto badcheck;
 
     /* --- Fill in a new challenge block --- */
-    
+
     kxc = kxc_new(kx);
     G_COPY(gg, kxc->c, c);
     G_COPY(gg, kxc->r, r);
@@ -606,7 +603,7 @@ static kxchal *respond(keyexch *kx, unsigned msg, buf *b)
     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);
@@ -678,7 +675,7 @@ bad:
   G_DESTROY(gg, cc);
   G_DESTROY(gg, r);
   mp_drop(cv);
-  return (0);  
+  return (0);
 }
 
 /* --- @dochallenge@ --- *
@@ -795,6 +792,7 @@ static int decryptrest(keyexch *kx, kxchal *kxc, unsigned msg, buf *b)
     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);
 }
@@ -857,7 +855,7 @@ static void commit(keyexch *kx, kxchal *kxc)
   kx->r[0] = kxc;
   kx->nr = 1;
   kxc_stoptimer(kxc);
-  ksl_link(kx->ks, kxc->ks);  
+  ksl_link(kx->ks, kxc->ks);
 }
 
 /* --- @doreply@ --- *
@@ -886,7 +884,7 @@ static int doreply(keyexch *kx, buf *b)
   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;
@@ -950,7 +948,7 @@ static int doswitch(keyexch *kx, buf *b)
       checkresponse(kx, KX_SWITCH, b))
     goto bad;
   if ((hswrq = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
-    a_warn("KX", "?PEER", "invalid", "switch-rq", A_END);
+    a_warn("KX", "?PEER", kx->p, "invalid", "switch-rq", A_END);
     goto bad;
   }
   IF_TRACING(T_KEYEXCH, {
@@ -996,7 +994,7 @@ static int doswitchok(keyexch *kx, buf *b)
   if (decryptrest(kx, kxc, KX_SWITCHOK, b))
     goto bad;
   if ((hswok = buf_get(b, algs.hashsz)) == 0 || BLEFT(b)) {
-    a_warn("KX", "?PEER", "invalid", "switch-ok", A_END);
+    a_warn("KX", "?PEER", kx->p, "invalid", "switch-ok", A_END);
     goto bad;
   }
   IF_TRACING(T_KEYEXCH, {
@@ -1012,7 +1010,7 @@ static int doswitchok(keyexch *kx, buf *b)
   return (0);
 
 bad:
-  return (-1);  
+  return (-1);
 }
 
 /*----- Main code ---------------------------------------------------------*/
@@ -1067,7 +1065,7 @@ static void start(keyexch *kx, time_t now)
 
   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);
@@ -1163,6 +1161,12 @@ void kx_message(keyexch *kx, unsigned msg, buf *b)
   size_t sz = BSZ(b);
   int rc;
 
+  if (kx->f & KXF_CORK) {
+    start(kx, now);
+    settimer(kx, now + T_RETRY);
+    a_notify("KXSTART", A_END);
+  }
+
   if (checkpub(kx))
     return;
 
@@ -1170,7 +1174,6 @@ void kx_message(keyexch *kx, unsigned msg, buf *b)
     stop(kx);
     start(kx, now);
   }
-
   T( trace(T_KEYEXCH, "keyexch: processing %s packet from `%s'",
           msg < KX_NMSG ? pkname[msg] : "unknown", p_name(kx->p)); )
 
@@ -1233,7 +1236,7 @@ void kx_free(keyexch *kx)
 
 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) {
@@ -1250,6 +1253,7 @@ void kx_newkeys(keyexch *kx)
  * 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.
  *
@@ -1258,19 +1262,21 @@ void kx_newkeys(keyexch *kx)
  *             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);
 }