summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2020-11-10 17:30:54 +0100
committert3sserakt <t3ss@posteo.de>2020-11-10 17:30:54 +0100
commitfdc0373871cbd3e303616d21ec68ba2067cff2a4 (patch)
tree0e72addef6f83d219761680b040f68c89fa88966
parent63fe195e40e55f13ab29e3ba578e97017fc4cc48 (diff)
- added inband rekeying for udp communicatorudpcom
-rw-r--r--src/transport/gnunet-communicator-udp.c725
-rw-r--r--src/transport/test_communicator_udp_backchannel_peer1.conf1
-rw-r--r--src/transport/test_communicator_udp_rekey_peer1.conf11
-rw-r--r--src/transport/test_communicator_udp_rekey_peer2.conf11
-rw-r--r--src/transport/transport-testing2.c3
-rw-r--r--src/transport/transport_api2_communication.c4
6 files changed, 623 insertions, 132 deletions
diff --git a/src/transport/gnunet-communicator-udp.c b/src/transport/gnunet-communicator-udp.c
index e967e8e9a..8a20bb3eb 100644
--- a/src/transport/gnunet-communicator-udp.c
+++ b/src/transport/gnunet-communicator-udp.c
@@ -51,7 +51,7 @@
/**
* How often do we rekey based on time (at least)
*/
-#define REKEY_TIME_INTERVAL GNUNET_TIME_UNIT_DAYS
+#define DEFAULT_REKEY_TIME_INTERVAL GNUNET_TIME_UNIT_DAYS
/**
* How long do we wait until we must have received the initial KX?
@@ -207,6 +207,11 @@ struct InitialKX
* key derived from the handshake with sequence number zero.
*/
char gcm_tag[GCM_TAG_SIZE];
+
+ /**
+ * A flag indicating, if the sender whishes to do rekeying.
+ */
+ int do_rekey;
};
@@ -339,6 +344,41 @@ struct UDPBox
* `struct UdpHandshakeSignature`.
*/
char gcm_tag[GCM_TAG_SIZE];
+
+ /**
+ * A flag indicating, if the sender whishes to do rekeying.
+ */
+ int do_rekey;
+};
+
+/**
+ * UDP message box. Always sent encrypted, only allowed after
+ * the receiver sent a `struct UDPAck` for the base key!
+ */
+struct UDPRekey
+{
+ /**
+ * Key and IV identification code. KDF applied to an acknowledged
+ * base key and a sequence number. Sequence numbers must be used
+ * monotonically increasing up to the maximum specified in
+ * `struct UDPAck`. Without further `struct UDPAck`s, the sender
+ * must fall back to sending handshakes!
+ */
+ struct GNUNET_ShortHashCode kid;
+
+ /**
+ * 128-bit authentication tag for the following encrypted message,
+ * from GCM. MAC starts at the @e body_start that follows and
+ * extends until the end of the UDP payload. If the @e hmac is
+ * wrong, the receiver should check if the message might be a
+ * `struct UdpHandshakeSignature`.
+ */
+ char gcm_tag[GCM_TAG_SIZE];
+
+ /**
+ * Sender's identity
+ */
+ struct GNUNET_PeerIdentity sender;
};
@@ -471,6 +511,11 @@ struct SharedSecret
struct SenderAddress
{
/**
+ * Flag indicating sender is initiated rekeying for this receiver.
+ */
+ int rekeying;
+
+ /**
* To whom are we talking to.
*/
struct GNUNET_PeerIdentity target;
@@ -520,6 +565,11 @@ struct SenderAddress
* Which network type does this queue use?
*/
enum GNUNET_NetworkType nt;
+
+ /**
+ * sender_destroy already called on sender.
+ */
+ int sender_destroy_called;
};
@@ -530,6 +580,31 @@ struct SenderAddress
struct ReceiverAddress
{
/**
+ * Flag indicating sender is initiated rekeying for this receiver.
+ */
+ int rekeying;
+
+ /**
+ * Shared secret we use with @e target for rekeying.
+ */
+ struct SharedSecret *ss_rekey;
+
+ /**
+ * Numer of kce we retain for sending the rekeying shared secret.
+ */
+ int number_rekeying_kce;
+
+ /**
+ * Send bytes for this receiver address.
+ */
+ uint64_t rekey_send_bytes;
+
+ /**
+ * Timeout for this receiver address.
+ */
+ struct GNUNET_TIME_Absolute rekey_timeout;
+
+ /**
* To whom are we talking to.
*/
struct GNUNET_PeerIdentity target;
@@ -612,9 +687,19 @@ struct ReceiverAddress
unsigned int acks_available;
/**
+ * Acks available when we started rekeying.
+ */
+ unsigned int rekey_acks_available;
+
+ /**
* Which network type does this queue use?
*/
enum GNUNET_NetworkType nt;
+
+ /**
+ * receiver_destroy already called on receiver.
+ */
+ int receiver_destroy_called;
};
@@ -671,9 +756,9 @@ struct BroadcastInterface
};
/**
- * Timeout for this receiver address.
- */
-struct GNUNET_TIME_Absolute *rekey_timeout;
+ * The rekey interval
+ */
+static struct GNUNET_TIME_Relative rekey_interval;
/**
* Shared secret we finished the last kce working queue for.
@@ -834,24 +919,27 @@ receiver_destroy (struct ReceiverAddress *receiver)
{
struct GNUNET_MQ_Handle *mq;
+ receiver->receiver_destroy_called = GNUNET_YES;
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Disconnecting receiver for peer `%s'\n",
GNUNET_i2s (&receiver->target));
- if (NULL != (mq = receiver->kx_mq))
+ /*if (NULL != (mq = receiver->kx_mq))
{
receiver->kx_mq = NULL;
GNUNET_MQ_destroy (mq);
- }
+ }*/
if (NULL != receiver->kx_qh)
{
GNUNET_TRANSPORT_communicator_mq_del (receiver->kx_qh);
receiver->kx_qh = NULL;
+ receiver->kx_mq = NULL;
}
- if (NULL != (mq = receiver->d_mq))
+ /*if (NULL != (mq = receiver->d_mq))
{
receiver->d_mq = NULL;
GNUNET_MQ_destroy (mq);
- }
+ }*/
if (NULL != receiver->d_qh)
{
GNUNET_TRANSPORT_communicator_mq_del (receiver->d_qh);
@@ -949,16 +1037,20 @@ kce_generate (struct SharedSecret *ss, uint32_t seq)
"# KIDs active",
GNUNET_CONTAINER_multishortmap_size (key_cache),
GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Generated kce %s with cmac %s.\n",
+ GNUNET_sh2s (&kce->kid),
+ GNUNET_h2s (&ss->cmac));
}
-
/**
* Destroy @a ss and associated key cache entries.
*
* @param ss shared secret to destroy
+ * @param withoutKce Do we keep those secrets with kce or those without.
*/
static void
-secret_destroy (struct SharedSecret *ss, int withoutKce)
+secret_destroy (struct SharedSecret *ss, int withOrWithoutKce)
{
struct SenderAddress *sender;
struct ReceiverAddress *receiver;
@@ -966,10 +1058,12 @@ secret_destroy (struct SharedSecret *ss, int withoutKce)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"secret destroy %u %u\n",
- withoutKce,
+ withOrWithoutKce,
ss->sequence_allowed);
- if (withoutKce && (ss->sequence_allowed > 0))
+ if ((withOrWithoutKce && (ss->sequence_allowed > 0)) || (! withOrWithoutKce &&
+ (ss->sequence_allowed
+ == 0)))
return;
if (NULL != (sender = ss->sender))
@@ -992,9 +1086,52 @@ secret_destroy (struct SharedSecret *ss, int withoutKce)
"# KIDs active",
GNUNET_CONTAINER_multishortmap_size (key_cache),
GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "secret with cmac %s destroyed\n",
+ GNUNET_h2s (&ss->cmac));
GNUNET_free (ss);
}
+/**
+ * Destroying all secrets. Depending on parameter we keep those secrets having a kce.
+ *
+ * @param ss The secret we will not destroy.
+ * @param withOrWithoutKce Do we keep those secrets with kce or only those without.
+ */
+static void
+destroy_all_secrets (struct SharedSecret *ss, int withOrWithoutKce)
+{
+ struct SenderAddress *sender;
+ struct ReceiverAddress *receiver;
+ struct SharedSecret *ss_to_destroy;
+ struct SharedSecret *ss_start;
+ struct SharedSecret *pos;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting destroy all.\n");
+
+ if (NULL != (sender = ss->sender))
+ {
+ ss_start = sender->ss_head;
+ }
+ if (NULL != (receiver = ss->receiver))
+ {
+ ss_start = receiver->ss_head;
+ }
+
+ pos = ss_start;
+ while ( NULL != pos)
+ {
+ ss_to_destroy = pos;
+ pos = pos->next;
+
+ if (ss != ss_to_destroy)
+ secret_destroy (ss_to_destroy, withOrWithoutKce);
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Finished destroy all.\n");
+}
+
/**
* Functions with this signature are called whenever we need
@@ -1005,6 +1142,9 @@ secret_destroy (struct SharedSecret *ss, int withoutKce)
static void
sender_destroy (struct SenderAddress *sender)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "destroying sender.\n");
+ sender->sender_destroy_called = GNUNET_YES;
GNUNET_assert (
GNUNET_YES ==
GNUNET_CONTAINER_multipeermap_remove (senders, &sender->target, sender));
@@ -1100,20 +1240,26 @@ check_timeouts (void *cls)
rt = GNUNET_TIME_UNIT_FOREVER_REL;
while (NULL != (receiver = GNUNET_CONTAINER_heap_peek (receivers_heap)))
{
- rt = GNUNET_TIME_absolute_get_remaining (receiver->timeout);
- if (0 != rt.rel_value_us)
- break;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Receiver timed out\n");
- receiver_destroy (receiver);
+ if (GNUNET_YES != receiver->receiver_destroy_called)
+ {
+ rt = GNUNET_TIME_absolute_get_remaining (receiver->timeout);
+ if (0 != rt.rel_value_us)
+ break;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Receiver timed out\n");
+ receiver_destroy (receiver);
+ }
}
st = GNUNET_TIME_UNIT_FOREVER_REL;
while (NULL != (sender = GNUNET_CONTAINER_heap_peek (senders_heap)))
{
- st = GNUNET_TIME_absolute_get_remaining (sender->timeout);
- if (0 != st.rel_value_us)
- break;
- sender_destroy (sender);
+ if (GNUNET_YES != sender->sender_destroy_called)
+ {
+ st = GNUNET_TIME_absolute_get_remaining (sender->timeout);
+ if (0 != st.rel_value_us)
+ break;
+ sender_destroy (sender);
+ }
}
delay = GNUNET_TIME_relative_min (rt, st);
if (delay.rel_value_us < GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
@@ -1122,7 +1268,7 @@ check_timeouts (void *cls)
/**
- * Calcualte cmac from master in @a ss.
+ * Calculate cmac from master in @a ss.
*
* @param ss[in,out] data structure to complete
*/
@@ -1289,19 +1435,23 @@ setup_shared_secret_dec (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral)
*/
static struct SharedSecret *
setup_shared_secret_enc (const struct GNUNET_CRYPTO_EcdhePrivateKey *ephemeral,
- struct ReceiverAddress *receiver)
+ struct ReceiverAddress *receiver, int add_to_receiver)
{
struct SharedSecret *ss;
ss = GNUNET_new (struct SharedSecret);
GNUNET_CRYPTO_ecdh_eddsa (ephemeral,
- &receiver->target.public_key,
+ &receiver->target.
+ public_key,
&ss->master);
calculate_cmac (ss);
ss->receiver = receiver;
- GNUNET_CONTAINER_DLL_insert (receiver->ss_head, receiver->ss_tail, ss);
- receiver->num_secrets++;
- GNUNET_STATISTICS_update (stats, "# Secrets active", 1, GNUNET_NO);
+ if (add_to_receiver)
+ {
+ GNUNET_CONTAINER_DLL_insert (receiver->ss_head, receiver->ss_tail, ss);
+ receiver->num_secrets++;
+ GNUNET_STATISTICS_update (stats, "# Secrets active", 1, GNUNET_NO);
+ }
return ss;
}
@@ -1316,6 +1466,51 @@ setup_shared_secret_enc (const struct GNUNET_CRYPTO_EcdhePrivateKey *ephemeral,
static void
setup_receiver_mq (struct ReceiverAddress *receiver);
+static void
+add_acks (struct SharedSecret *ss, int acks_to_add, int remove_from_receiver)
+{
+
+ struct ReceiverAddress *receiver = ss->receiver;
+
+ if (NULL == ss)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "secret NULL!\n");
+
+ if (NULL == receiver)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Receiver NULL!\n");
+ if (NULL == receiver->d_qh)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Queue NULL!\n");
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Tell transport we have more acks!\n");
+ GNUNET_TRANSPORT_communicator_mq_update (ch,
+ receiver->d_qh,
+ acks_to_add,
+ 1);
+ // Until here for alternativ 1
+
+ /* move ss to head to avoid discarding it anytime soon! */
+ if (remove_from_receiver)
+ GNUNET_CONTAINER_DLL_remove (receiver->ss_head, receiver->ss_tail, ss);
+ GNUNET_CONTAINER_DLL_insert (receiver->ss_head, receiver->ss_tail, ss);
+ destroy_all_secrets (ss, GNUNET_YES);
+
+
+ // Uncomment this for alternativ 2 of backchannel functionality
+ /*if (receiver->acks_available != ack->acks_available)
+ {
+ receiver->acks_available = ack->acks_available;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Tell transport we have different number of acks!\n");
+ GNUNET_TRANSPORT_communicator_mq_update (ch,
+ receiver->d_qh,
+ receiver->acks_available,
+ 1);
+ }*/
+ // Until here for alternativ 2
+}
/**
* We received an ACK for @a pid. Check if it is for
@@ -1332,18 +1527,40 @@ handle_ack (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
{
const struct UDPAck *ack = cls;
struct ReceiverAddress *receiver = value;
- struct SharedSecret *pos;
+ int acks_to_add;
+ uint32_t allowed;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"in handle ack\n");
- struct SharedSecret *ss_to_destroy;
+
+ if ((GNUNET_YES == receiver->rekeying) && (0 == memcmp (&ack->cmac,
+ &receiver->ss_rekey->
+ cmac, sizeof(struct
+ GNUNET_HashCode))) )
+ {
+ allowed = ntohl (ack->sequence_max);
+
+ if (allowed > receiver->ss_rekey->sequence_allowed)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%u > %u (%u %u) for rekey secrect %s\n", allowed,
+ receiver->ss_rekey->sequence_allowed,
+ receiver->acks_available,
+ ack->acks_available,
+ GNUNET_h2s (&receiver->ss_rekey->master));
+
+ receiver->ss_rekey->sequence_allowed = allowed;
+
+ return GNUNET_NO;
+ }
+ }
(void) pid;
for (struct SharedSecret *ss = receiver->ss_head; NULL != ss; ss = ss->next)
{
if (0 == memcmp (&ack->cmac, &ss->cmac, sizeof(struct GNUNET_HashCode)))
{
- uint32_t allowed;
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Found matching mac\n");
@@ -1358,41 +1575,17 @@ handle_ack (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
ack->acks_available,
GNUNET_h2s (&ss->master));
// Uncomment this for alternativ 1 of backchannel functionality
- receiver->acks_available += (allowed - ss->sequence_allowed);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Tell transport we have more acks!\n");
- GNUNET_TRANSPORT_communicator_mq_update (ch,
- receiver->d_qh,
- (allowed
- - ss->sequence_allowed),
- 1);
- // Until here for alternativ 1
+ if (receiver->number_rekeying_kce < 3)
+ acks_to_add = allowed - ss->sequence_allowed;
+ else
+ acks_to_add = allowed - ss->sequence_allowed - (3
+ - receiver->
+ number_rekeying_kce);
+ receiver->acks_available += acks_to_add;
ss->sequence_allowed = allowed;
- /* move ss to head to avoid discarding it anytime soon! */
- GNUNET_CONTAINER_DLL_remove (receiver->ss_head, receiver->ss_tail, ss);
- GNUNET_CONTAINER_DLL_insert (receiver->ss_head, receiver->ss_tail, ss);
- pos = receiver->ss_head;
- while ( NULL != pos)
- {
- ss_to_destroy = pos;
- pos = pos->next;
- secret_destroy (ss_to_destroy, GNUNET_YES);
- }
+ add_acks (ss, acks_to_add, GNUNET_YES);
}
-
- // Uncomment this for alternativ 2 of backchannel functionality
- /*if (receiver->acks_available != ack->acks_available)
- {
- receiver->acks_available = ack->acks_available;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Tell transport we have different number of acks!\n");
- GNUNET_TRANSPORT_communicator_mq_update (ch,
- receiver->d_qh,
- receiver->acks_available,
- 1);
- }*/
- // Until here for alternativ 2
return GNUNET_NO;
}
}
@@ -1451,7 +1644,8 @@ kce_generate_cb (void *cls)
{
struct SharedSecret *ss = cls;
-
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Enough keys generated?\n");
if (ss->sender->acks_available < KCN_TARGET)
{
@@ -1489,8 +1683,6 @@ kce_generate_cb (void *cls)
static void
consider_ss_ack (struct SharedSecret *ss, int initial)
{
- struct SharedSecret *ss_to_destroy;
- struct SharedSecret *pos;
GNUNET_assert (NULL != ss->sender);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1535,18 +1727,15 @@ consider_ss_ack (struct SharedSecret *ss, int initial)
&ss_finished->sender->target,
COMMUNICATOR_ADDRESS_PREFIX,
&ack.header);
- pos = ss->sender->ss_head;
- while ( NULL != pos)
- {
- ss_to_destroy = pos;
- pos = pos->next;
- secret_destroy (ss_to_destroy, GNUNET_YES);
- }
+ destroy_all_secrets (ss, GNUNET_YES);
kce_task = NULL;
+ kce_task_finished = GNUNET_NO;
}
- else if (((NULL == kce_task) && (KCN_THRESHOLD >
- ss->sender->acks_available)) ||
- (ss->sender->num_secrets > MAX_SECRETS) )
+ else if (((NULL == kce_task) && ((GNUNET_YES == ss->sender->rekeying) ||
+ ((KCN_THRESHOLD >
+ ss
+ ->sender->acks_available)) ||
+ (ss->sender->num_secrets > MAX_SECRETS))))
{
// kce_generate (ss, ++ss->sequence_allowed);
@@ -1619,6 +1808,9 @@ decrypt_box (const struct UDPBox *box,
"# Decryption failures with valid KCE",
1,
GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Decryption with kid %s failed\n",
+ GNUNET_sh2s (&box->kid));
kce_destroy (kce);
return;
}
@@ -1628,12 +1820,108 @@ decrypt_box (const struct UDPBox *box,
sizeof(out_buf),
GNUNET_NO);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "decrypted UDPBox with kid %s\n",
- GNUNET_sh2s (&box->kid));
+ "decrypted UDPBox with kid %s and do_reky %u\n",
+ GNUNET_sh2s (&box->kid),
+ box->do_rekey);
try_handle_plaintext (ss->sender, out_buf, sizeof(out_buf));
- consider_ss_ack (ss, GNUNET_NO);
+ if ((GNUNET_NO == box->do_rekey) && (GNUNET_YES == ss->sender->rekeying))
+ {
+ ss->sender->rekeying = GNUNET_NO;
+ destroy_all_secrets (ss, GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Receiver stopped rekeying.\n");
+ }
+ else if (GNUNET_NO == box->do_rekey)
+ consider_ss_ack (ss, GNUNET_NO);
+ else
+ {
+ ss->sender->rekeying = GNUNET_YES;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Receiver started rekeying.\n");
+ }
}
+/**
+ * We received a @a rekey with matching @a kce. Decrypt and process it.
+ *
+ * @param rekey the data we received
+ * @param rekey_len number of bytes in @a rekey
+ * @param kce key index to decrypt @a rekey
+ */
+static void
+decrypt_rekey (const struct UDPRekey *rekey,
+ size_t rekey_len,
+ struct KeyCacheEntry *kce,
+ struct SenderAddress *sender)
+{
+ struct SharedSecret *ss = kce->ss;
+ struct SharedSecret *ss_rekey;
+ char out_buf[rekey_len - sizeof(*rekey)];
+ struct GNUNET_HashCode *cmac;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "decrypt_rekey.\n");
+
+ GNUNET_assert (NULL != ss->sender);
+ if (GNUNET_OK != try_decrypt (ss,
+ rekey->gcm_tag,
+ kce->sequence_number,
+ (const char *) &rekey[1],
+ sizeof(out_buf),
+ out_buf))
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# Decryption failures with valid KCE",
+ 1,
+ GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Decryption with kid %s failed\n",
+ GNUNET_sh2s (&rekey->kid));
+ kce_destroy (kce);
+ return;
+ }
+ kce_destroy (kce);
+ GNUNET_STATISTICS_update (stats,
+ "# bytes decrypted with BOX",
+ sizeof(out_buf),
+ GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "decrypted UDPRekey with kid %s\n",
+ GNUNET_sh2s (&rekey->kid));
+ /*cmac = (struct GNUNET_HashCode *) out_buf;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received secret with cmac %s \n",
+ GNUNET_h2s (&cmac));*/
+ ss_rekey = (struct SharedSecret *) out_buf;
+ calculate_cmac (ss_rekey);
+ ss_rekey->sender = sender;
+ ss_rekey->sequence_used = 0;
+ // ss_rekey->sequence_allowed = 0;
+ ss_rekey->active_kce_count = 0;
+ ss_rekey->prev = NULL;
+ ss_rekey->next = NULL;
+ GNUNET_assert (ss_rekey->prev == NULL && sender->ss_head != ss_rekey);
+ GNUNET_assert (ss_rekey->next == NULL && sender->ss_tail != ss_rekey);
+ GNUNET_CONTAINER_DLL_insert (sender->ss_head, sender->ss_tail, ss_rekey);
+ sender->num_secrets++;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received secret with cmac %s\n",
+ GNUNET_h2s (&(ss_rekey->cmac)));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received secret with master %s.\n",
+ GNUNET_h2s (&(ss_rekey->master)));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We have %u sequence_allowed.\n",
+ ss_rekey->sequence_allowed);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We have a sender %p\n",
+ ss_rekey->sender);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We have %u acks available.\n",
+ ss_rekey->sender->acks_available);
+ consider_ss_ack (ss_rekey, GNUNET_YES);
+
+}
/**
* Closure for #find_sender_by_address()
@@ -1832,6 +2120,38 @@ sock_read (void *cls)
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Read %lu bytes\n", rcvd);
+
+ if (rcvd > sizeof(struct UDPRekey))
+ {
+ const struct UDPRekey *rekey;
+ const struct UDPBox *box;
+ struct KeyCacheEntry *kce;
+ struct SenderAddress *sender;
+ int do_decrypt = GNUNET_NO;
+
+ rekey = (const struct UDPRekey *) buf;
+ box = (const struct UDPBox *) buf;
+ kce = GNUNET_CONTAINER_multishortmap_get (key_cache, &rekey->kid);
+
+ if ((GNUNET_YES == box->do_rekey)||(GNUNET_NO == box->do_rekey))
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "UDPRekey has do_rekey %u\n",
+ box->do_rekey);
+ else
+ do_decrypt = GNUNET_YES;
+ if ((GNUNET_YES == do_decrypt)&& (NULL != kce) && (GNUNET_YES ==
+ kce->ss->sender->rekeying))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "UDPRekey with kid %s\n",
+ GNUNET_sh2s (&rekey->kid));
+ sender = setup_sender (&rekey->sender, (const struct sockaddr *) &sa,
+ salen);
+ decrypt_rekey (rekey, (size_t) rcvd, kce, sender);
+ return;
+ }
+ }
+
/* first, see if it is a UDPBox */
if (rcvd > sizeof(struct UDPBox))
{
@@ -1941,6 +2261,10 @@ sock_read (void *cls)
calculate_cmac (ss);
sender = setup_sender (&uc->sender, (const struct sockaddr *) &sa, salen);
ss->sender = sender;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received secret from Intial with cmac %s and master %s\n",
+ GNUNET_h2s (&(ss->cmac)),
+ GNUNET_h2s (&(ss->master)));
GNUNET_CONTAINER_DLL_insert (sender->ss_head, sender->ss_tail, ss);
sender->num_secrets++;
GNUNET_STATISTICS_update (stats, "# Secrets active", 1, GNUNET_NO);
@@ -1949,7 +2273,20 @@ sock_read (void *cls)
1,
GNUNET_NO);
try_handle_plaintext (sender, &uc[1], sizeof(pbuf) - sizeof(*uc));
- consider_ss_ack (ss, GNUNET_YES);
+ if ((GNUNET_NO == kx->do_rekey) && (GNUNET_YES == ss->sender->rekeying))
+ {
+ ss->sender->rekeying = GNUNET_NO;
+ destroy_all_secrets (ss, GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Receiver stopped rekeying.\n");
+ }
+ else if (GNUNET_NO == kx->do_rekey)
+ consider_ss_ack (ss, GNUNET_YES);
+ else{
+ ss->sender->rekeying = GNUNET_YES;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Receiver started rekeying.\n");
+ }
/*if (sender->num_secrets > MAX_SECRETS)
secret_destroy (sender->ss_tail);*/
}
@@ -2138,26 +2475,13 @@ mq_send_kx (struct GNUNET_MQ_Handle *mq,
size_t dpos;
gcry_cipher_hd_t out_cipher;
struct SharedSecret *ss;
- struct SharedSecret *ss_to_destroy;
- struct SharedSecret *pos;
-
- if (receiver->num_secrets > MAX_SECRETS)
- {
- pos = receiver->ss_head;
- while ( NULL != pos)
- {
- ss_to_destroy = pos;
- pos = pos->next;
- secret_destroy (ss_to_destroy, GNUNET_YES);
- }
- }
-
GNUNET_assert (mq == receiver->kx_mq);
if (msize > receiver->kx_mtu)
{
GNUNET_break (0);
- receiver_destroy (receiver);
+ if (GNUNET_YES != receiver->receiver_destroy_called)
+ receiver_destroy (receiver);
return;
}
reschedule_receiver_timeout (receiver);
@@ -2165,7 +2489,13 @@ mq_send_kx (struct GNUNET_MQ_Handle *mq,
/* setup key material */
GNUNET_CRYPTO_ecdhe_key_create (&epriv);
- ss = setup_shared_secret_enc (&epriv, receiver);
+ ss = setup_shared_secret_enc (&epriv, receiver, GNUNET_YES);
+
+ if (receiver->num_secrets > MAX_SECRETS)
+ {
+ destroy_all_secrets (ss, GNUNET_YES);
+ }
+
setup_cipher (&ss->master, 0, &out_cipher);
/* compute 'uc' */
uc.sender = my_identity;
@@ -2199,6 +2529,10 @@ mq_send_kx (struct GNUNET_MQ_Handle *mq,
GNUNET_assert (
0 == gcry_cipher_gettag (out_cipher, kx.gcm_tag, sizeof(kx.gcm_tag)));
gcry_cipher_close (out_cipher);
+ if (GNUNET_NO == receiver->rekeying)
+ kx.do_rekey = GNUNET_NO;
+ else
+ kx.do_rekey = GNUNET_YES;
memcpy (dgram, &kx, sizeof(kx));
if (-1 == GNUNET_NETWORK_socket_sendto (udp_sock,
dgram,
@@ -2229,14 +2563,15 @@ mq_send_d (struct GNUNET_MQ_Handle *mq,
struct ReceiverAddress *receiver = impl_state;
uint16_t msize = ntohs (msg->size);
struct GNUNET_TIME_Relative rt;
- struct SharedSecret *pos;
+ struct GNUNET_CRYPTO_EcdhePrivateKey epriv;
GNUNET_assert (mq == receiver->d_mq);
if ((msize > receiver->d_mtu) ||
(0 == receiver->acks_available))
{
GNUNET_break (0);
- receiver_destroy (receiver);
+ if (GNUNET_YES != receiver->receiver_destroy_called)
+ receiver_destroy (receiver);
return;
}
reschedule_receiver_timeout (receiver);
@@ -2260,9 +2595,12 @@ mq_send_d (struct GNUNET_MQ_Handle *mq,
continue;
}
char dgram[sizeof(struct UDPBox) + receiver->d_mtu];
+ char rekey_dgram[sizeof(struct UDPRekey) + receiver->d_mtu];
struct UDPBox *box;
gcry_cipher_hd_t out_cipher;
size_t dpos;
+ struct UDPRekey *rekey;
+ uint16_t not_below;
box = (struct UDPBox *) dgram;
ss->sequence_used++;
@@ -2278,6 +2616,49 @@ mq_send_d (struct GNUNET_MQ_Handle *mq,
box->gcm_tag,
sizeof(box->gcm_tag)));
gcry_cipher_close (out_cipher);
+
+ receiver->rekey_send_bytes += sizeof(struct UDPBox) + receiver->d_mtu;
+
+ if (GNUNET_NO == receiver->rekeying)
+ box->do_rekey = GNUNET_NO;
+ else
+ box->do_rekey = GNUNET_YES;
+
+ if (0 == receiver->rekey_timeout.abs_value_us)
+ {
+ receiver->rekey_timeout = GNUNET_TIME_relative_to_absolute (
+ rekey_interval);
+ }
+ else
+ {
+ rt = GNUNET_TIME_absolute_get_remaining (receiver->rekey_timeout);
+ if ((0 == rt.rel_value_us)||(receiver->rekey_send_bytes >
+ REKEY_MAX_BYTES) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Bytes send %lu greater than %llu max bytes\n.",
+ receiver->rekey_send_bytes,
+ REKEY_MAX_BYTES);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Relative time is %lu and timeout is %lu\n.",
+ rt.rel_value_us,
+ receiver->rekey_timeout.abs_value_us);
+
+ receiver->rekey_timeout.abs_value_us = 0;
+ receiver->rekey_send_bytes = 0;
+ // destroy_all_secrets (ss, GNUNET_NO);
+ receiver->rekeying = GNUNET_YES;
+ receiver->rekey_acks_available = receiver->acks_available;
+ box->do_rekey = GNUNET_YES;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sender started rekeying.\n");
+ if (GNUNET_YES == box->do_rekey)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending do_rekey with kid %s\n",
+ GNUNET_sh2s (&box->kid));
+ }
+ }
+
if (-1 == GNUNET_NETWORK_socket_sendto (udp_sock,
dgram,
sizeof(dgram),
@@ -2288,39 +2669,123 @@ mq_send_d (struct GNUNET_MQ_Handle *mq,
"Sending UDPBox to %s\n", GNUNET_a2s (receiver->address,
receiver->address_len));
GNUNET_MQ_impl_send_continue (mq);
- // receiver->acks_available--;
+ receiver->acks_available--;
+
if (0 == receiver->acks_available)
{
/* We have no more ACKs */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"No more acks\n");
- }
+ if (GNUNET_YES == receiver->rekeying)
+ {
+ receiver->rekeying = GNUNET_NO;
- /* (NULL == rekey_timeout)
- rekey_timeout = GNUNET_TIME_relative_to_absolute (REKEY_TIME_INTERVAL);
- else
+ add_acks (receiver->ss_rekey, receiver->ss_rekey->sequence_allowed,
+ GNUNET_NO);
+ receiver->ss_rekey = NULL;
+ }
+ }
+ else if ((GNUNET_YES == receiver->rekeying) )
{
- rt = GNUNET_TIME_absolute_get_remaining (rekey_timeout);
- if (0 == rt.rel_value_us)
+ uint8_t first = GNUNET_NO;
+ uint8_t second = GNUNET_NO;
+ uint8_t third = GNUNET_NO;
+
+ if (NULL != receiver->ss_rekey)
+ {
+ not_below = (receiver->rekey_acks_available
+ - (receiver->rekey_acks_available % 3)) / 3;
+ first = (0 == receiver->ss_rekey->sequence_allowed);
+ second = (receiver->acks_available > not_below);
+ third = (0 == (receiver->acks_available - not_below) % not_below);
+ }
+ else if (NULL == receiver->ss_rekey)
{
- rekey_timeout = NULL;
- pos = receiver->ss_head;
- while ( NULL != pos)
+ /* setup key material */
+ GNUNET_CRYPTO_ecdhe_key_create (&epriv);
+ receiver->ss_rekey = setup_shared_secret_enc (&epriv, receiver,
+ GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Setup secret with cmac %s\n",
+ GNUNET_h2s (&(receiver->ss_rekey->cmac)));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Setup secret with master %s.\n",
+ GNUNET_h2s (&(receiver->ss_rekey->master)));
+ }
+
+ if ((NULL == receiver->ss_rekey) || (first && second && third))
+ {
+ gcry_cipher_hd_t rekey_out_cipher;
+
+ while (NULL != ss && ss->sequence_used >= ss->sequence_allowed)
{
- ss_to_destroy = pos;
- pos = pos->next;
- secret_destroy (ss_to_destroy, GNUNET_NO);
+ ss = ss->prev;
+ }
+
+ if (NULL != ss)
+ {
+ rekey = (struct UDPRekey *) rekey_dgram;
+ rekey->sender = my_identity;
+ ss->sequence_used++;
+ get_kid (&ss->master, ss->sequence_used, &rekey->kid);
+ setup_cipher (&ss->master, ss->sequence_used, &rekey_out_cipher);
+ /* Append encrypted payload to dgram */
+ dpos = sizeof(struct UDPRekey);
+
+ GNUNET_assert (
+ 0 == gcry_cipher_encrypt (rekey_out_cipher, &rekey_dgram[dpos],
+ /*sizeof(receiver->ss_rekey->cmac),
+ &(receiver->ss_rekey->cmac),
+ sizeof(receiver->ss_rekey->cmac)));
+ dpos += sizeof(receiver->ss_rekey->cmac);*/
+ sizeof(receiver->ss_rekey),
+ receiver->ss_rekey,
+ sizeof(receiver->ss_rekey)));
+ dpos += sizeof(receiver->ss_rekey);
+ do_pad (rekey_out_cipher, &rekey_dgram[dpos], sizeof(rekey_dgram)
+ - dpos);
+ GNUNET_assert (0 == gcry_cipher_gettag (rekey_out_cipher,
+ rekey->gcm_tag,
+ sizeof(rekey->gcm_tag)));
+ gcry_cipher_close (rekey_out_cipher);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending rekey with kid %s and master %s\n",
+ GNUNET_sh2s (&rekey->kid),
+ GNUNET_h2s (&(receiver->ss_rekey->master)));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending rekey with cmac %s\n",
+ GNUNET_h2s (&(receiver->ss_rekey->cmac)));
+
+ if (-1 == GNUNET_NETWORK_socket_sendto (udp_sock,
+ rekey_dgram,
+ sizeof(rekey_dgram),
+ receiver->address,
+ receiver->address_len))
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending UDPRekey to %s\n", GNUNET_a2s (receiver->address,
+ receiver->
+ address_len));
}
- if (0 != receiver->acks_available)
- GNUNET_TRANSPORT_communicator_mq_update (ch,
- receiver->d_qh,
- // TODO We can not do this. But how can we signal this queue is not able to handle a message. Test code interprets q-len as additional length.
- -receiver->acks_available,
- 1);
}
- }*/
+
+ /*GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "First %d\n",
+ first);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Second %d\n",
+ second);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Third %d\n",
+ third);*/
+ }
+
return;
}
}
@@ -2343,7 +2808,8 @@ mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
if (mq == receiver->d_mq)
{
receiver->d_mq = NULL;
- receiver_destroy (receiver);
+ if (GNUNET_YES != receiver->receiver_destroy_called)
+ receiver_destroy (receiver);
}
}
@@ -2365,7 +2831,8 @@ mq_destroy_kx (struct GNUNET_MQ_Handle *mq, void *impl_state)
if (mq == receiver->kx_mq)
{
receiver->kx_mq = NULL;
- receiver_destroy (receiver);
+ if (GNUNET_YES != receiver->receiver_destroy_called)
+ receiver_destroy (receiver);
}
}
@@ -2402,7 +2869,8 @@ mq_error (void *cls, enum GNUNET_MQ_Error error)
"MQ error in queue to %s: %d\n",
GNUNET_i2s (&receiver->target),
(int) error);
- receiver_destroy (receiver);
+ if (GNUNET_YES != receiver->receiver_destroy_called)
+ receiver_destroy (receiver);
}
@@ -2535,9 +3003,11 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
in = udp_address_to_sockaddr (path, &in_len);
receiver = GNUNET_new (struct ReceiverAddress);
+ receiver->number_rekeying_kce = 0;
receiver->address = in;
receiver->address_len = in_len;
receiver->target = *peer;
+ receiver->rekeying = GNUNET_NO;
receiver->nt = GNUNET_NT_scanner_get_type (is, in, in_len);
(void) GNUNET_CONTAINER_multipeermap_put (
receivers,
@@ -2582,7 +3052,8 @@ get_receiver_delete_it (void *cls,
(void) cls;
(void) target;
- receiver_destroy (receiver);
+ if (GNUNET_YES != receiver->receiver_destroy_called)
+ receiver_destroy (receiver);
return GNUNET_OK;
}
@@ -2604,7 +3075,8 @@ get_sender_delete_it (void *cls,
(void) cls;
(void) target;
- sender_destroy (sender);
+ if (GNUNET_YES != sender->sender_destroy_called)
+ sender_destroy (sender);
return GNUNET_OK;
}
@@ -2997,6 +3469,13 @@ run (void *cls,
return;
}
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_time (cfg,
+ COMMUNICATOR_CONFIG_SECTION,
+ "REKEY_INTERVAL",
+ &rekey_interval))
+ rekey_interval = DEFAULT_REKEY_TIME_INTERVAL;
+
in = udp_address_to_sockaddr (bindto, &in_len);
if (NULL == in)
{
diff --git a/src/transport/test_communicator_udp_backchannel_peer1.conf b/src/transport/test_communicator_udp_backchannel_peer1.conf
index b99a76d6c..fef1bb419 100644
--- a/src/transport/test_communicator_udp_backchannel_peer1.conf
+++ b/src/transport/test_communicator_udp_backchannel_peer1.conf
@@ -35,6 +35,7 @@ BINDTO = 60002
DISABLE_V6 = YES
[communicator-udp]
+#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
BINDTO = 60002
DISABLE_V6 = YES
MAX_QUEUE_LENGTH=5000
diff --git a/src/transport/test_communicator_udp_rekey_peer1.conf b/src/transport/test_communicator_udp_rekey_peer1.conf
index e7161e488..794811bff 100644
--- a/src/transport/test_communicator_udp_rekey_peer1.conf
+++ b/src/transport/test_communicator_udp_rekey_peer1.conf
@@ -30,10 +30,13 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
[communicator-unix]
UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
-[communicator-tcp]
+[communicator-udp]
+#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
+#PREFIX = valgrind --leak-check=full --track-origins=yes
BINDTO = 60002
DISABLE_V6 = YES
-REKEY_INTERVAL = 100ms
+MAX_QUEUE_LENGTH=5000
+REKEY_INTERVAL = 1s
-[communicator-udp]
-BINDTO = 60002
+[communicator-test]
+BACKCHANNEL_ENABLED = YES
diff --git a/src/transport/test_communicator_udp_rekey_peer2.conf b/src/transport/test_communicator_udp_rekey_peer2.conf
index 8f175a405..5850d9824 100644
--- a/src/transport/test_communicator_udp_rekey_peer2.conf
+++ b/src/transport/test_communicator_udp_rekey_peer2.conf
@@ -30,10 +30,13 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
[communicator-unix]
UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
-[communicator-tcp]
+[communicator-udp]
+#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
+#PREFIX = valgrind --leak-check=full --track-origins=yes
BINDTO = 60003
DISABLE_V6 = YES
-REKEY_INTERVAL = 100ms
+MAX_QUEUE_LENGTH=5000
+REKEY_INTERVAL = 1s
-[communicator-udp]
-BINDTO = 60003
+[communicator-test]
+BACKCHANNEL_ENABLED = YES \ No newline at end of file
diff --git a/src/transport/transport-testing2.c b/src/transport/transport-testing2.c
index 076fbf331..191560afc 100644
--- a/src/transport/transport-testing2.c
+++ b/src/transport/transport-testing2.c
@@ -553,6 +553,9 @@ handle_update_queue_message (void *cls,
tc_queue->mtu = ntohl (msg->mtu);
tc_queue->cs = msg->cs;
tc_queue->priority = ntohl (msg->priority);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "%u added to queue length.\n",
+ GNUNET_ntohll (msg->q_len));
// Uncomment this for alternativ 1 of backchannel functionality
tc_queue->q_len += GNUNET_ntohll (msg->q_len);
// Until here for alternativ 1
diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c
index b048ad851..3c7d30357 100644
--- a/src/transport/transport_api2_communication.c
+++ b/src/transport/transport_api2_communication.c
@@ -1046,6 +1046,8 @@ GNUNET_TRANSPORT_communicator_mq_del (struct GNUNET_TRANSPORT_QueueHandle *qh)
send_del_queue (qh);
GNUNET_CONTAINER_DLL_remove (ch->queue_head, ch->queue_tail, qh);
+ if (NULL == qh->mq)
+ return;
GNUNET_MQ_destroy (qh->mq);
GNUNET_free (qh->address);
GNUNET_free (qh);
@@ -1106,7 +1108,7 @@ GNUNET_TRANSPORT_communicator_address_remove (
*/
void
GNUNET_TRANSPORT_communicator_address_remove_all (
- struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
+ struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
{
for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; NULL != ai;
ai = ai->next)