Merge branch 'master' of ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet-new_tunnels.c
index ff07ac6653866e7378284a22b4a234e95a5d7bc5..d50860629312b54edd47d843109a8bee3a97927d 100644 (file)
@@ -173,18 +173,14 @@ struct CadetTunnelAxolotl
   struct GNUNET_CRYPTO_SymmetricSessionKey CKr;
 
   /**
-   * ECDH for key exchange (A0 / B0).  Note that for the
-   * 'unverified_ax', this member is an alias with the main
-   * 't->ax.kx_0' value, so do not free it!
+   * ECDH for key exchange (A0 / B0).
    */
-  struct GNUNET_CRYPTO_EcdhePrivateKey *kx_0;
+  struct GNUNET_CRYPTO_EcdhePrivateKey kx_0;
 
   /**
-   * ECDH Ratchet key (our private key in the current DH).  Note that
-   * for the 'unverified_ax', this member is an alias with the main
-   * 't->ax.kx_0' value, so do not free it!
+   * ECDH Ratchet key (our private key in the current DH).
    */
-  struct GNUNET_CRYPTO_EcdhePrivateKey *DHRs;
+  struct GNUNET_CRYPTO_EcdhePrivateKey DHRs;
 
   /**
    * ECDH Ratchet key (other peer's public key in the current DH).
@@ -607,7 +603,11 @@ GCT_count_any_connections (const struct CadetTunnel *t)
 static struct CadetTConnection *
 get_ready_connection (struct CadetTunnel *t)
 {
-  return t->connection_ready_head;
+  struct CadetTConnection *hd = t->connection_ready_head;
+
+  GNUNET_assert ( (NULL == hd) ||
+                  (GNUNET_YES == hd->is_ready) );
+  return hd;
 }
 
 
@@ -648,10 +648,10 @@ trigger_transmissions (void *cls);
 static void
 new_ephemeral (struct CadetTunnelAxolotl *ax)
 {
-  GNUNET_free_non_null (ax->DHRs);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Creating new ephemeral ratchet key (DHRs)\n");
-  ax->DHRs = GNUNET_CRYPTO_ecdhe_key_create ();
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_ecdhe_key_create2 (&ax->DHRs));
 }
 
 
@@ -786,7 +786,7 @@ t_ax_encrypt (struct CadetTunnelAxolotl *ax,
     ax->HKs = ax->NHKs;
 
     /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
-    GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
+    GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs,
                             &ax->DHRr,
                             &dh);
     t_ax_hmac_hash (&ax->RK,
@@ -1192,7 +1192,7 @@ t_ax_decrypt_and_validate (struct CadetTunnelAxolotl *ax,
                    PNp);
 
     /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
-    GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
+    GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs,
                             DHRp,
                             &dh);
     t_ax_hmac_hash (&ax->RK,
@@ -1319,7 +1319,8 @@ send_kx (struct CadetTunnel *t,
   struct GNUNET_CADET_TunnelKeyExchangeMessage *msg;
   enum GNUNET_CADET_KX_Flags flags;
 
-  if (NULL == ct)
+  if ( (NULL == ct) ||
+       (GNUNET_NO == ct->is_ready) )
     ct = get_ready_connection (t);
   if (NULL == ct)
   {
@@ -1332,7 +1333,7 @@ send_kx (struct CadetTunnel *t,
   }
   cc = ct->cc;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Sending KX on %s via %s using %s in state %s\n",
+       "Sending KX on %s via %s in state %s\n",
        GCT_2s (t),
        GCC_2s (cc),
        estate2s (t->estate));
@@ -1341,9 +1342,9 @@ send_kx (struct CadetTunnel *t,
   flags = GNUNET_CADET_KX_FLAG_FORCE_REPLY; /* always for KX */
   msg->flags = htonl (flags);
   msg->cid = *GCC_get_id (cc);
-  GNUNET_CRYPTO_ecdhe_key_get_public (ax->kx_0,
+  GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0,
                                       &msg->ephemeral_key);
-  GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs,
+  GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs,
                                       &msg->ratchet_key);
   mark_connection_unready (ct);
   t->kx_retry_delay = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay);
@@ -1406,9 +1407,9 @@ send_kx_auth (struct CadetTunnel *t,
     flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
   msg->kx.flags = htonl (flags);
   msg->kx.cid = *GCC_get_id (cc);
-  GNUNET_CRYPTO_ecdhe_key_get_public (ax->kx_0,
+  GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0,
                                       &msg->kx.ephemeral_key);
-  GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs,
+  GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs,
                                       &msg->kx.ratchet_key);
   /* Compute authenticator (this is the main difference to #send_kx()) */
   GNUNET_CRYPTO_hash (&ax->RK,
@@ -1447,8 +1448,8 @@ cleanup_ax (struct CadetTunnelAxolotl *ax)
     delete_skipped_key (ax,
                         ax->skipped_head);
   GNUNET_assert (0 == ax->skipped);
-  GNUNET_free_non_null (ax->kx_0);
-  GNUNET_free_non_null (ax->DHRs);
+  GNUNET_CRYPTO_ecdhe_key_clear (&ax->kx_0);
+  GNUNET_CRYPTO_ecdhe_key_clear (&ax->DHRs);
 }
 
 
@@ -1508,7 +1509,7 @@ update_ax_by_kx (struct CadetTunnelAxolotl *ax,
   }
   else
   {
-    GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0,            /* B0 */
+    GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0,            /* B0 */
                               &pid->public_key,    /* A */
                               &key_material[0]);
   }
@@ -1516,7 +1517,7 @@ update_ax_by_kx (struct CadetTunnelAxolotl *ax,
   /* ECDH A0 B */
   if (GNUNET_YES == am_I_alice)
   {
-    GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0,            /* A0 */
+    GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0,            /* A0 */
                               &pid->public_key,    /* B */
                               &key_material[1]);
   }
@@ -1532,7 +1533,7 @@ update_ax_by_kx (struct CadetTunnelAxolotl *ax,
   /* ECDH A0 B0 */
   /* (This is the triple-DH, we could probably safely skip this,
      as A0/B0 are already in the key material.) */
-  GNUNET_CRYPTO_ecc_ecdh (ax->kx_0,             /* A0 or B0 */
+  GNUNET_CRYPTO_ecc_ecdh (&ax->kx_0,             /* A0 or B0 */
                           ephemeral_key,  /* B0 or A0 */
                           &key_material[2]);
 
@@ -1804,7 +1805,17 @@ GCT_handle_kx_auth (struct CadetTConnection *ct,
                          GCP_get_id (t->destination),
                          &msg->kx.ephemeral_key,
                          &msg->kx.ratchet_key);
-  GNUNET_break (GNUNET_OK == ret);
+  if (GNUNET_OK != ret)
+  {
+    if (GNUNET_NO == ret)
+      GNUNET_STATISTICS_update (stats,
+                                "# redundant KX_AUTH received",
+                                1,
+                                GNUNET_NO);
+    else
+      GNUNET_break (0); /* connect to self!? */
+    return;
+  }
   GNUNET_CRYPTO_hash (&ax_tmp.RK,
                       sizeof (ax_tmp.RK),
                       &kx_auth);
@@ -1814,9 +1825,12 @@ GCT_handle_kx_auth (struct CadetTConnection *ct,
   {
     /* This KX_AUTH is not using the latest KX/KX_AUTH data
        we transmitted to the sender, refuse it, try KX again. */
-    GNUNET_break_op (0);
+    GNUNET_STATISTICS_update (stats,
+                              "# KX_AUTH not using our last KX received (auth failure)",
+                              1,
+                              GNUNET_NO);
     send_kx (t,
-             NULL,
+             ct,
              &t->ax);
     return;
   }
@@ -1825,8 +1839,6 @@ GCT_handle_kx_auth (struct CadetTConnection *ct,
   if (NULL != t->unverified_ax)
   {
     /* We got some "stale" KX before, drop that. */
-    t->unverified_ax->DHRs = NULL; /* aliased with ax.DHRs */
-    t->unverified_ax->kx_0 = NULL; /* aliased with ax.DHRs */
     cleanup_ax (t->unverified_ax);
     GNUNET_free (t->unverified_ax);
     t->unverified_ax = NULL;
@@ -1884,12 +1896,12 @@ get_next_free_ctn (struct CadetTunnel *t)
   ctn = ntohl (t->next_ctn.cn);
   while (NULL !=
          GNUNET_CONTAINER_multihashmap32_get (t->channels,
-                                              ctn))
+                                              ctn | highbit))
   {
-    ctn = ((ctn + 1) & (~ HIGH_BIT)) | highbit;
+    ctn = ((ctn + 1) & (~ HIGH_BIT));
   }
-  t->next_ctn.cn = htonl (((ctn + 1) & (~ HIGH_BIT)) | highbit);
-  ret.cn = ntohl (ctn);
+  t->next_ctn.cn = htonl ((ctn + 1) & (~ HIGH_BIT));
+  ret.cn = htonl (ctn | highbit);
   return ret;
 }
 
@@ -1910,6 +1922,11 @@ GCT_add_channel (struct CadetTunnel *t,
   struct GNUNET_CADET_ChannelTunnelNumber ctn;
 
   ctn = get_next_free_ctn (t);
+  if (NULL != t->destroy_task)
+  {
+    GNUNET_SCHEDULER_cancel (t->destroy_task);
+    t->destroy_task = NULL;
+  }
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CONTAINER_multihashmap32_put (t->channels,
                                                       ntohl (ctn.cn),
@@ -1959,13 +1976,19 @@ GCT_connection_lost (struct CadetTConnection *ct)
   struct CadetTunnel *t = ct->t;
 
   if (GNUNET_YES == ct->is_ready)
+  {
     GNUNET_CONTAINER_DLL_remove (t->connection_ready_head,
                                  t->connection_ready_tail,
                                  ct);
+    t->num_ready_connections--;
+  }
   else
+  {
     GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
                                  t->connection_busy_tail,
                                  ct);
+    t->num_busy_connections--;
+  }
   GNUNET_free (ct);
 }
 
@@ -2039,8 +2062,6 @@ destroy_tunnel (void *cls)
   GNUNET_MQ_destroy (t->mq);
   if (NULL != t->unverified_ax)
   {
-    t->unverified_ax->DHRs = NULL; /* aliased with ax.DHRs */
-    t->unverified_ax->kx_0 = NULL; /* aliased with ax.DHRs */
     cleanup_ax (t->unverified_ax);
     GNUNET_free (t->unverified_ax);
   }
@@ -2416,12 +2437,14 @@ consider_path_cb (void *cls,
   struct EvaluationSummary es;
   struct CadetTConnection *ct;
 
+  GNUNET_assert (off < GCPP_get_length (path));
   es.min_length = UINT_MAX;
   es.max_length = 0;
   es.max_desire = 0;
   es.min_desire = UINT64_MAX;
   es.path = path;
   es.duplicate = GNUNET_NO;
+  es.worst = NULL;
 
   /* Compute evaluation summary over existing connections. */
   GCT_iterate_connections (t,
@@ -2467,6 +2490,7 @@ consider_path_cb (void *cls,
   ct->t = t;
   ct->cc = GCC_create (t->destination,
                        path,
+                       off,
                        GNUNET_CADET_OPTION_DEFAULT, /* FIXME: set based on what channels want/need! */
                        ct,
                        &connection_ready_cb,
@@ -2566,6 +2590,10 @@ GCT_consider_path (struct CadetTunnel *t,
                    struct CadetPeerPath *p,
                    unsigned int off)
 {
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Considering %s for %s\n",
+       GCPP_2s (p),
+       GCT_2s (t));
   (void) consider_path_cb (t,
                            p,
                            off);
@@ -2630,7 +2658,7 @@ handle_plaintext_data (void *cls,
     /* We don't know about such a channel, might have been destroyed on our
        end in the meantime, or never existed. Send back a DESTROY. */
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Receicved %u bytes of application data for unknown channel %u, sending DESTROY\n",
+         "Received %u bytes of application data for unknown channel %u, sending DESTROY\n",
          (unsigned int) (ntohs (msg->header.size) - sizeof (*msg)),
          ntohl (msg->ctn.cn));
     GCT_send_channel_destroy (t,
@@ -2665,7 +2693,7 @@ handle_plaintext_data_ack (void *cls,
     /* We don't know about such a channel, might have been destroyed on our
        end in the meantime, or never existed. Send back a DESTROY. */
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Receicved DATA_ACK for unknown channel %u, sending DESTROY\n",
+         "Received DATA_ACK for unknown channel %u, sending DESTROY\n",
          ntohl (ack->ctn.cn));
     GCT_send_channel_destroy (t,
                               ack->ctn);
@@ -2696,7 +2724,7 @@ handle_plaintext_channel_open (void *cls,
   if (NULL != ch)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Receicved duplicate channel OPEN on port %s from %s (%s), resending ACK\n",
+         "Received duplicate channel CHANNEL_OPEN on port %s from %s (%s), resending ACK\n",
          GNUNET_h2s (&copen->port),
          GCT_2s (t),
          GCCH_2s (ch));
@@ -2705,13 +2733,18 @@ handle_plaintext_channel_open (void *cls,
     return;
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Receicved channel OPEN on port %s from %s\n",
+       "Received CHANNEL_OPEN on port %s from %s\n",
        GNUNET_h2s (&copen->port),
        GCT_2s (t));
   ch = GCCH_channel_incoming_new (t,
                                   copen->ctn,
                                   &copen->port,
                                   ntohl (copen->opt));
+  if (NULL != t->destroy_task)
+  {
+    GNUNET_SCHEDULER_cancel (t->destroy_task);
+    t->destroy_task = NULL;
+  }
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONTAINER_multihashmap32_put (t->channels,
                                                       ntohl (copen->ctn.cn),
@@ -2809,7 +2842,7 @@ handle_plaintext_channel_destroy (void *cls,
     return;
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Receicved channel DESTROY on %s from %s\n",
+       "Received channel DESTROY on %s from %s\n",
        GCCH_2s (ch),
        GCT_2s (t));
   GCCH_handle_remote_destroy (ch,
@@ -2894,7 +2927,8 @@ GCT_create_tunnel (struct CadetPeer *destination)
 
   t->kx_retry_delay = INITIAL_KX_RETRY_DELAY;
   new_ephemeral (&t->ax);
-  t->ax.kx_0 = GNUNET_CRYPTO_ecdhe_key_create ();
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_ecdhe_key_create2 (&t->ax.kx_0));
   t->destination = destination;
   t->channels = GNUNET_CONTAINER_multihashmap32_create (8);
   t->maintain_connections_task
@@ -2992,8 +3026,21 @@ GCT_handle_encrypted (struct CadetTConnection *ct,
   case CADET_TUNNEL_KEY_UNINITIALIZED:
   case CADET_TUNNEL_KEY_AX_RECV:
     /* We did not even SEND our KX, how can the other peer
-       send us encrypted data? */
-    GNUNET_break_op (0);
+       send us encrypted data? Must have been that we went
+       down and the other peer still things we are up.
+       Let's send it KX back. */
+    GNUNET_STATISTICS_update (stats,
+                              "# received encrypted without any KX",
+                              1,
+                              GNUNET_NO);
+    if (NULL != t->kx_task)
+    {
+      GNUNET_SCHEDULER_cancel (t->kx_task);
+      t->kx_task = NULL;
+    }
+    send_kx (t,
+             ct,
+             &t->ax);
     return;
   case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
     /* We send KX, and other peer send KX to us at the same time.
@@ -3035,10 +3082,6 @@ GCT_handle_encrypted (struct CadetTConnection *ct,
     break;
   }
 
-  GNUNET_STATISTICS_update (stats,
-                            "# received encrypted",
-                            1,
-                            GNUNET_NO);
   decrypted_size = -1;
   if (CADET_TUNNEL_KEY_OK == t->estate)
   {
@@ -3063,8 +3106,6 @@ GCT_handle_encrypted (struct CadetTConnection *ct,
     if (-1 != decrypted_size)
     {
       /* It worked! Treat this as authentication of the AX data! */
-      t->ax.DHRs = NULL; /* aliased with ax.DHRs */
-      t->ax.kx_0 = NULL; /* aliased with ax.DHRs */
       cleanup_ax (&t->ax);
       t->ax = *t->unverified_ax;
       GNUNET_free (t->unverified_ax);
@@ -3095,8 +3136,6 @@ GCT_handle_encrypted (struct CadetTConnection *ct,
          t->unverified_attempts);
     if (t->unverified_attempts > MAX_UNVERIFIED_ATTEMPTS)
     {
-      t->unverified_ax->DHRs = NULL; /* aliased with ax.DHRs */
-      t->unverified_ax->kx_0 = NULL; /* aliased with ax.DHRs */
       cleanup_ax (t->unverified_ax);
       GNUNET_free (t->unverified_ax);
       t->unverified_ax = NULL;
@@ -3106,16 +3145,27 @@ GCT_handle_encrypted (struct CadetTConnection *ct,
   if (-1 == decrypted_size)
   {
     /* Decryption failed for good, complain. */
-    GNUNET_break_op (0);
     LOG (GNUNET_ERROR_TYPE_WARNING,
-         "%s failed to decrypt and validate encrypted data\n",
+         "%s failed to decrypt and validate encrypted data, retrying KX\n",
          GCT_2s (t));
     GNUNET_STATISTICS_update (stats,
                               "# unable to decrypt",
                               1,
                               GNUNET_NO);
+    if (NULL != t->kx_task)
+    {
+      GNUNET_SCHEDULER_cancel (t->kx_task);
+      t->kx_task = NULL;
+    }
+    send_kx (t,
+             ct,
+             &t->ax);
     return;
   }
+  GNUNET_STATISTICS_update (stats,
+                            "# decrypted bytes",
+                            decrypted_size,
+                            GNUNET_NO);
 
   /* The MST will ultimately call #handle_decrypted() on each message. */
   t->current_ct = ct;
@@ -3167,12 +3217,16 @@ GCT_send (struct CadetTunnel *t,
                 &ax_msg[1],
                 message,
                 payload_size);
+  GNUNET_STATISTICS_update (stats,
+                            "# encrypted bytes",
+                            payload_size,
+                            GNUNET_NO);
   ax_msg->ax_header.Ns = htonl (t->ax.Ns++);
   ax_msg->ax_header.PNs = htonl (t->ax.PNs);
   /* FIXME: we should do this once, not once per message;
      this is a point multiplication, and DHRs does not
      change all the time. */
-  GNUNET_CRYPTO_ecdhe_key_get_public (t->ax.DHRs,
+  GNUNET_CRYPTO_ecdhe_key_get_public (&t->ax.DHRs,
                                       &ax_msg->ax_header.DHRs);
   t_h_encrypt (&t->ax,
                ax_msg);