[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [gnunet] branch master updated: importing KX logic, integra
From: |
gnunet |
Subject: |
[GNUnet-SVN] [gnunet] branch master updated: importing KX logic, integrating encryption logic |
Date: |
Tue, 17 Jan 2017 14:21:00 +0100 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository gnunet.
The following commit(s) were added to refs/heads/master by this push:
new 23c86a4ca importing KX logic, integrating encryption logic
23c86a4ca is described below
commit 23c86a4ca5d1cd879550cd07afed4869475fb765
Author: Christian Grothoff <address@hidden>
AuthorDate: Tue Jan 17 14:20:59 2017 +0100
importing KX logic, integrating encryption logic
---
src/cadet/gnunet-service-cadet-new.c | 35 ++
src/cadet/gnunet-service-cadet-new.h | 15 +
src/cadet/gnunet-service-cadet-new_connection.c | 24 +-
src/cadet/gnunet-service-cadet-new_connection.h | 12 +
src/cadet/gnunet-service-cadet-new_tunnels.c | 689 +++++++++++++++++++++++-
5 files changed, 763 insertions(+), 12 deletions(-)
diff --git a/src/cadet/gnunet-service-cadet-new.c
b/src/cadet/gnunet-service-cadet-new.c
index b2f39b3cd..3bb7d9cdf 100644
--- a/src/cadet/gnunet-service-cadet-new.c
+++ b/src/cadet/gnunet-service-cadet-new.c
@@ -175,6 +175,16 @@ struct GNUNET_CONTAINER_MultiPeerMap *peers;
*/
struct GNUNET_CONTAINER_MultiHashMap *connections;
+/**
+ * How many messages are needed to trigger an AXOLOTL ratchet advance.
+ */
+unsigned long long ratchet_messages;
+
+/**
+ * How long until we trigger a ratched advance due to time.
+ */
+struct GNUNET_TIME_Relative ratchet_time;
+
/**
@@ -1221,6 +1231,31 @@ run (void *cls,
const struct GNUNET_CONFIGURATION_Handle *c,
struct GNUNET_SERVICE_Handle *service)
{
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (c,
+ "CADET",
+ "RATCHET_MESSAGES",
+ &ratchet_messages))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+ "CADET",
+ "RATCHET_MESSAGES",
+ "needs to be a number");
+ ratchet_messages = 64;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_time (c,
+ "CADET",
+ "RATCHET_TIME",
+ &ratchet_time))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+ "CADET",
+ "RATCHET_TIME",
+ "need delay value");
+ ratchet_time = GNUNET_TIME_UNIT_HOURS;
+ }
+
my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
if (NULL == my_private_key)
{
diff --git a/src/cadet/gnunet-service-cadet-new.h
b/src/cadet/gnunet-service-cadet-new.h
index 416c9d13a..903ceed94 100644
--- a/src/cadet/gnunet-service-cadet-new.h
+++ b/src/cadet/gnunet-service-cadet-new.h
@@ -101,6 +101,10 @@ struct CadetPeerPathEntry
};
+/**
+ * Entry in list of connections used by tunnel, with metadata.
+ */
+struct CadetTConnection;
/**
* Active path through the network (used by a tunnel). There may
@@ -156,6 +160,17 @@ extern struct GNUNET_CONTAINER_MultiHashMap
*loose_channels;
*/
extern struct GNUNET_CONTAINER_MultiPeerMap *peers;
+/**
+ * How many messages are needed to trigger an AXOLOTL ratchet advance.
+ */
+extern unsigned long long ratchet_messages;
+
+/**
+ * How long until we trigger a ratched advance due to time.
+ */
+extern struct GNUNET_TIME_Relative ratchet_time;
+
+
/**
* Send a message to a client.
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c
b/src/cadet/gnunet-service-cadet-new_connection.c
index 1f31331a5..6a9c210b8 100644
--- a/src/cadet/gnunet-service-cadet-new_connection.c
+++ b/src/cadet/gnunet-service-cadet-new_connection.c
@@ -21,7 +21,8 @@
/**
* @file cadet/gnunet-service-cadet-new_connection.c
- * @brief
+ * @brief management of CORE-level end-to-end connections; establishes
+ * end-to-end routes and transmits messages along the route
* @author Bartlomiej Polot
* @author Christian Grothoff
*/
@@ -88,6 +89,11 @@ struct CadetConnection
struct CadetPeer *destination;
/**
+ * Which tunnel is using this connection?
+ */
+ struct CadetTConnection *ct;
+
+ /**
* Path we are using to our destination.
*/
struct CadetPeerPath *path;
@@ -231,6 +237,19 @@ GCC_get_h (const struct CadetConnection *cc)
/**
+ * Return the tunnel associated with this connection.
+ *
+ * @param cc connection to query
+ * @return corresponding entry in the tunnel's connection list
+ */
+struct CadetTConnection *
+GCC_get_ct (struct CadetConnection *cc)
+{
+ return cc->ct;
+}
+
+
+/**
* An ACK was received for this connection, process it.
*
* @param cc the connection that got the ACK.
@@ -355,6 +374,7 @@ manage_first_hop_mq (void *cls,
*
* @param destination where to go
* @param path which path to take (may not be the full path)
+ * @param ct tunnel that uses the connection
* @param ready_cb function to call when ready to transmit
* @param ready_cb_cls closure for @a cb
* @return handle to the connection
@@ -362,6 +382,7 @@ manage_first_hop_mq (void *cls,
struct CadetConnection *
GCC_create (struct CadetPeer *destination,
struct CadetPeerPath *path,
+ struct CadetTConnection *ct,
GNUNET_SCHEDULER_TaskCallback ready_cb,
void *ready_cb_cls)
{
@@ -373,6 +394,7 @@ GCC_create (struct CadetPeer *destination,
destination);
GNUNET_assert (UINT_MAX > off);
cc = GNUNET_new (struct CadetConnection);
+ cc->ct = ct;
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&cc->cid,
sizeof (cc->cid));
diff --git a/src/cadet/gnunet-service-cadet-new_connection.h
b/src/cadet/gnunet-service-cadet-new_connection.h
index c9738d86e..66d19ae0c 100644
--- a/src/cadet/gnunet-service-cadet-new_connection.h
+++ b/src/cadet/gnunet-service-cadet-new_connection.h
@@ -58,6 +58,7 @@ GCC_destroy (struct CadetConnection *cc);
*
* @param destination where to go
* @param path which path to take (may not be the full path)
+ * @param ct which tunnel uses this connection
* @param ready_cb function to call when ready to transmit
* @param ready_cb_cls closure for @a cb
* @return handle to the connection
@@ -65,6 +66,7 @@ GCC_destroy (struct CadetConnection *cc);
struct CadetConnection *
GCC_create (struct CadetPeer *destination,
struct CadetPeerPath *path,
+ struct CadetTConnection *ct,
GNUNET_SCHEDULER_TaskCallback ready_cb,
void *ready_cb_cls);
@@ -87,6 +89,16 @@ GCC_transmit (struct CadetConnection *cc,
/**
+ * Return the tunnel associated with this connection.
+ *
+ * @param cc connection to query
+ * @return corresponding entry in the tunnel's connection list
+ */
+struct CadetTConnection *
+GCC_get_ct (struct CadetConnection *cc);
+
+
+/**
* Obtain the path used by this connection.
*
* @param cc connection
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c
b/src/cadet/gnunet-service-cadet-new_tunnels.c
index 18c469b67..b5a4e0112 100644
--- a/src/cadet/gnunet-service-cadet-new_tunnels.c
+++ b/src/cadet/gnunet-service-cadet-new_tunnels.c
@@ -29,6 +29,7 @@
* - when managing connections, distinguish those that
* have (recently) had traffic from those that were
* never ready (or not recently)
+ * - clean up KX logic!
*/
#include "platform.h"
#include "gnunet_util_lib.h"
@@ -43,11 +44,33 @@
#include "gnunet-service-cadet-new_paths.h"
+#define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__)
+
+
/**
* How long do we wait until tearing down an idle tunnel?
*/
#define IDLE_DESTROY_DELAY
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90)
+/**
+ * Yuck, replace by 'offsetof' expression?
+ * FIXME.
+ */
+#define AX_HEADER_SIZE (sizeof (uint32_t) * 2\
+ + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey))
+
+
+/**
+ * Maximum number of skipped keys we keep in memory per tunnel.
+ */
+#define MAX_SKIPPED_KEYS 64
+
+/**
+ * Maximum number of keys (and thus ratchet steps) we are willing to
+ * skip before we decide this is either a bogus packet or a DoS-attempt.
+ */
+#define MAX_KEY_GAP 256
+
/**
* Struct to old keys for skipped messages while advancing the Axolotl ratchet.
@@ -271,6 +294,12 @@ struct CadetTunnelQueueEntry
* Envelope of message to send follows.
*/
struct GNUNET_MQ_Envelope *env;
+
+ /**
+ * Where to put the connection identifier into the payload
+ * of the message in @e env once we have it?
+ */
+ struct GNUNET_CADET_ConnectionTunnelIdentifier *cid;
};
@@ -476,6 +505,619 @@ GCT_get_estate (struct CadetTunnel *t)
/**
+ * Create a new Axolotl ephemeral (ratchet) key.
+ *
+ * @param t Tunnel.
+ */
+static void
+new_ephemeral (struct CadetTunnel *t)
+{
+ GNUNET_free_non_null (t->ax.DHRs);
+ t->ax.DHRs = GNUNET_CRYPTO_ecdhe_key_create ();
+}
+
+
+/* ************************************** start core crypto
***************************** */
+
+
+/**
+ * Calculate HMAC.
+ *
+ * @param plaintext Content to HMAC.
+ * @param size Size of @c plaintext.
+ * @param iv Initialization vector for the message.
+ * @param key Key to use.
+ * @param hmac[out] Destination to store the HMAC.
+ */
+static void
+t_hmac (const void *plaintext,
+ size_t size,
+ uint32_t iv,
+ const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+ struct GNUNET_CADET_Hash *hmac)
+{
+ static const char ctx[] = "cadet authentication key";
+ struct GNUNET_CRYPTO_AuthKey auth_key;
+ struct GNUNET_HashCode hash;
+
+ GNUNET_CRYPTO_hmac_derive_key (&auth_key,
+ key,
+ &iv, sizeof (iv),
+ key, sizeof (*key),
+ ctx, sizeof (ctx),
+ NULL);
+ /* Two step: CADET_Hash is only 256 bits, HashCode is 512. */
+ GNUNET_CRYPTO_hmac (&auth_key,
+ plaintext,
+ size,
+ &hash);
+ GNUNET_memcpy (hmac,
+ &hash,
+ sizeof (*hmac));
+}
+
+
+/**
+ * Perform a HMAC.
+ *
+ * @param key Key to use.
+ * @param hash[out] Resulting HMAC.
+ * @param source Source key material (data to HMAC).
+ * @param len Length of @a source.
+ */
+static void
+t_ax_hmac_hash (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+ struct GNUNET_HashCode *hash,
+ const void *source,
+ unsigned int len)
+{
+ static const char ctx[] = "axolotl HMAC-HASH";
+ struct GNUNET_CRYPTO_AuthKey auth_key;
+
+ GNUNET_CRYPTO_hmac_derive_key (&auth_key,
+ key,
+ ctx, sizeof (ctx),
+ NULL);
+ GNUNET_CRYPTO_hmac (&auth_key,
+ source,
+ len,
+ hash);
+}
+
+
+/**
+ * Derive a symmetric encryption key from an HMAC-HASH.
+ *
+ * @param key Key to use for the HMAC.
+ * @param[out] out Key to generate.
+ * @param source Source key material (data to HMAC).
+ * @param len Length of @a source.
+ */
+static void
+t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+ struct GNUNET_CRYPTO_SymmetricSessionKey *out,
+ const void *source,
+ unsigned int len)
+{
+ static const char ctx[] = "axolotl derive key";
+ struct GNUNET_HashCode h;
+
+ t_ax_hmac_hash (key,
+ &h,
+ source,
+ len);
+ GNUNET_CRYPTO_kdf (out, sizeof (*out),
+ ctx, sizeof (ctx),
+ &h, sizeof (h),
+ NULL);
+}
+
+
+/**
+ * Encrypt data with the axolotl tunnel key.
+ *
+ * @param t Tunnel whose key to use.
+ * @param dst Destination with @a size bytes for the encrypted data.
+ * @param src Source of the plaintext. Can overlap with @c dst, must contain
@a size bytes
+ * @param size Size of the buffers at @a src and @a dst
+ */
+static void
+t_ax_encrypt (struct CadetTunnel *t,
+ void *dst,
+ const void *src,
+ size_t size)
+{
+ struct GNUNET_CRYPTO_SymmetricSessionKey MK;
+ struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+ struct CadetTunnelAxolotl *ax;
+ size_t out_size;
+
+ ax = &t->ax;
+ ax->ratchet_counter++;
+ if ( (GNUNET_YES == ax->ratchet_allowed) &&
+ ( (ratchet_messages <= ax->ratchet_counter) ||
+ (0 == GNUNET_TIME_absolute_get_remaining
(ax->ratchet_expiration).rel_value_us)) )
+ {
+ ax->ratchet_flag = GNUNET_YES;
+ }
+ if (GNUNET_YES == ax->ratchet_flag)
+ {
+ /* Advance ratchet */
+ struct GNUNET_CRYPTO_SymmetricSessionKey keys[3];
+ struct GNUNET_HashCode dh;
+ struct GNUNET_HashCode hmac;
+ static const char ctx[] = "axolotl ratchet";
+
+ new_ephemeral (t);
+ ax->HKs = ax->NHKs;
+
+ /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
+ GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
+ &ax->DHRr,
+ &dh);
+ t_ax_hmac_hash (&ax->RK,
+ &hmac,
+ &dh,
+ sizeof (dh));
+ GNUNET_CRYPTO_kdf (keys, sizeof (keys),
+ ctx, sizeof (ctx),
+ &hmac, sizeof (hmac),
+ NULL);
+ ax->RK = keys[0];
+ ax->NHKs = keys[1];
+ ax->CKs = keys[2];
+
+ ax->PNs = ax->Ns;
+ ax->Ns = 0;
+ ax->ratchet_flag = GNUNET_NO;
+ ax->ratchet_allowed = GNUNET_NO;
+ ax->ratchet_counter = 0;
+ ax->ratchet_expiration
+ = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
+ ratchet_time);
+ }
+
+ t_hmac_derive_key (&ax->CKs,
+ &MK,
+ "0",
+ 1);
+ GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+ &MK,
+ NULL, 0,
+ NULL);
+
+ out_size = GNUNET_CRYPTO_symmetric_encrypt (src,
+ size,
+ &MK,
+ &iv,
+ dst);
+ GNUNET_assert (size == out_size);
+ t_hmac_derive_key (&ax->CKs,
+ &ax->CKs,
+ "1",
+ 1);
+}
+
+
+/**
+ * Decrypt data with the axolotl tunnel key.
+ *
+ * @param t Tunnel whose key to use.
+ * @param dst Destination for the decrypted data, must contain @a size bytes.
+ * @param src Source of the ciphertext. Can overlap with @c dst, must contain
@a size bytes.
+ * @param size Size of the @a src and @a dst buffers
+ */
+static void
+t_ax_decrypt (struct CadetTunnel *t,
+ void *dst,
+ const void *src,
+ size_t size)
+{
+ struct GNUNET_CRYPTO_SymmetricSessionKey MK;
+ struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+ struct CadetTunnelAxolotl *ax;
+ size_t out_size;
+
+ ax = &t->ax;
+ t_hmac_derive_key (&ax->CKr,
+ &MK,
+ "0",
+ 1);
+ GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+ &MK,
+ NULL, 0,
+ NULL);
+ GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
+ out_size = GNUNET_CRYPTO_symmetric_decrypt (src,
+ size,
+ &MK,
+ &iv,
+ dst);
+ GNUNET_assert (out_size == size);
+ t_hmac_derive_key (&ax->CKr,
+ &ax->CKr,
+ "1",
+ 1);
+}
+
+
+/**
+ * Encrypt header with the axolotl header key.
+ *
+ * @param t Tunnel whose key to use.
+ * @param msg Message whose header to encrypt.
+ */
+static void
+t_h_encrypt (struct CadetTunnel *t,
+ struct GNUNET_CADET_Encrypted *msg)
+{
+ struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+ struct CadetTunnelAxolotl *ax;
+ size_t out_size;
+
+ ax = &t->ax;
+ GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+ &ax->HKs,
+ NULL, 0,
+ NULL);
+ out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->Ns,
+ AX_HEADER_SIZE,
+ &ax->HKs,
+ &iv,
+ &msg->Ns);
+ GNUNET_assert (AX_HEADER_SIZE == out_size);
+}
+
+
+/**
+ * Decrypt header with the current axolotl header key.
+ *
+ * @param t Tunnel whose current ax HK to use.
+ * @param src Message whose header to decrypt.
+ * @param dst Where to decrypt header to.
+ */
+static void
+t_h_decrypt (struct CadetTunnel *t,
+ const struct GNUNET_CADET_Encrypted *src,
+ struct GNUNET_CADET_Encrypted *dst)
+{
+ struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+ struct CadetTunnelAxolotl *ax;
+ size_t out_size;
+
+ ax = &t->ax;
+ GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+ &ax->HKr,
+ NULL, 0,
+ NULL);
+ out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns,
+ AX_HEADER_SIZE,
+ &ax->HKr,
+ &iv,
+ &dst->Ns);
+ GNUNET_assert (AX_HEADER_SIZE == out_size);
+}
+
+
+/**
+ * Delete a key from the list of skipped keys.
+ *
+ * @param t Tunnel to delete from.
+ * @param key Key to delete.
+ */
+static void
+delete_skipped_key (struct CadetTunnel *t,
+ struct CadetTunnelSkippedKey *key)
+{
+ GNUNET_CONTAINER_DLL_remove (t->ax.skipped_head,
+ t->ax.skipped_tail,
+ key);
+ GNUNET_free (key);
+ t->ax.skipped--;
+}
+
+
+/**
+ * Decrypt and verify data with the appropriate tunnel key and verify that the
+ * data has not been altered since it was sent by the remote peer.
+ *
+ * @param t Tunnel whose key to use.
+ * @param dst Destination for the plaintext.
+ * @param src Source of the message. Can overlap with @c dst.
+ * @param size Size of the message.
+ * @return Size of the decrypted data, -1 if an error was encountered.
+ */
+static ssize_t
+try_old_ax_keys (struct CadetTunnel *t,
+ void *dst,
+ const struct GNUNET_CADET_Encrypted *src,
+ size_t size)
+{
+ struct CadetTunnelSkippedKey *key;
+ struct GNUNET_CADET_Hash *hmac;
+ struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+ struct GNUNET_CADET_Encrypted plaintext_header;
+ struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
+ size_t esize;
+ size_t res;
+ size_t len;
+ unsigned int N;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying skipped keys\n");
+ hmac = &plaintext_header.hmac;
+ esize = size - sizeof (struct GNUNET_CADET_Encrypted);
+
+ /* Find a correct Header Key */
+ valid_HK = NULL;
+ for (key = t->ax.skipped_head; NULL != key; key = key->next)
+ {
+ t_hmac (&src->Ns,
+ AX_HEADER_SIZE + esize,
+ 0,
+ &key->HK,
+ hmac);
+ if (0 == memcmp (hmac,
+ &src->hmac,
+ sizeof (*hmac)))
+ {
+ valid_HK = &key->HK;
+ break;
+ }
+ }
+ if (NULL == key)
+ return -1;
+
+ /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
+ GNUNET_assert (size > sizeof (struct GNUNET_CADET_Encrypted));
+ len = size - sizeof (struct GNUNET_CADET_Encrypted);
+ GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader));
+
+ /* Decrypt header */
+ GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+ &key->HK,
+ NULL, 0,
+ NULL);
+ res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns,
+ AX_HEADER_SIZE,
+ &key->HK,
+ &iv,
+ &plaintext_header.Ns);
+ GNUNET_assert (AX_HEADER_SIZE == res);
+
+ /* Find the correct message key */
+ N = ntohl (plaintext_header.Ns);
+ while ( (NULL != key) &&
+ (N != key->Kn) )
+ key = key->next;
+ if ( (NULL == key) ||
+ (0 != memcmp (&key->HK,
+ valid_HK,
+ sizeof (*valid_HK))) )
+ return -1;
+
+ /* Decrypt payload */
+ GNUNET_CRYPTO_symmetric_derive_iv (&iv,
+ &key->MK,
+ NULL,
+ 0,
+ NULL);
+ res = GNUNET_CRYPTO_symmetric_decrypt (&src[1],
+ len,
+ &key->MK,
+ &iv,
+ dst);
+ delete_skipped_key (t,
+ key);
+ return res;
+}
+
+
+/**
+ * Delete a key from the list of skipped keys.
+ *
+ * @param t Tunnel to delete from.
+ * @param HKr Header Key to use.
+ */
+static void
+store_skipped_key (struct CadetTunnel *t,
+ const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr)
+{
+ struct CadetTunnelSkippedKey *key;
+
+ key = GNUNET_new (struct CadetTunnelSkippedKey);
+ key->timestamp = GNUNET_TIME_absolute_get ();
+ key->Kn = t->ax.Nr;
+ key->HK = t->ax.HKr;
+ t_hmac_derive_key (&t->ax.CKr,
+ &key->MK,
+ "0",
+ 1);
+ t_hmac_derive_key (&t->ax.CKr,
+ &t->ax.CKr,
+ "1",
+ 1);
+ GNUNET_CONTAINER_DLL_insert (t->ax.skipped_head,
+ t->ax.skipped_tail,
+ key);
+ t->ax.skipped++;
+ t->ax.Nr++;
+}
+
+
+/**
+ * Stage skipped AX keys and calculate the message key.
+ * Stores each HK and MK for skipped messages.
+ *
+ * @param t Tunnel where to stage the keys.
+ * @param HKr Header key.
+ * @param Np Received meesage number.
+ * @return #GNUNET_OK if keys were stored.
+ * #GNUNET_SYSERR if an error ocurred (Np not expected).
+ */
+static int
+store_ax_keys (struct CadetTunnel *t,
+ const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr,
+ uint32_t Np)
+{
+ int gap;
+
+ gap = Np - t->ax.Nr;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Storing skipped keys [%u, %u)\n",
+ t->ax.Nr,
+ Np);
+ if (MAX_KEY_GAP < gap)
+ {
+ /* Avoid DoS (forcing peer to do 2^33 chain HMAC operations) */
+ /* TODO: start new key exchange on return */
+ GNUNET_break_op (0);
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Got message %u, expected %u+\n",
+ Np,
+ t->ax.Nr);
+ return GNUNET_SYSERR;
+ }
+ if (0 > gap)
+ {
+ /* Delayed message: don't store keys, flag to try old keys. */
+ return GNUNET_SYSERR;
+ }
+
+ while (t->ax.Nr < Np)
+ store_skipped_key (t,
+ HKr);
+
+ while (t->ax.skipped > MAX_SKIPPED_KEYS)
+ delete_skipped_key (t,
+ t->ax.skipped_tail);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Decrypt and verify data with the appropriate tunnel key and verify that the
+ * data has not been altered since it was sent by the remote peer.
+ *
+ * @param t Tunnel whose key to use.
+ * @param dst Destination for the plaintext.
+ * @param src Source of the message. Can overlap with @c dst.
+ * @param size Size of the message.
+ * @return Size of the decrypted data, -1 if an error was encountered.
+ */
+static ssize_t
+t_ax_decrypt_and_validate (struct CadetTunnel *t,
+ void *dst,
+ const struct GNUNET_CADET_Encrypted *src,
+ size_t size)
+{
+ struct CadetTunnelAxolotl *ax;
+ struct GNUNET_CADET_Hash msg_hmac;
+ struct GNUNET_HashCode hmac;
+ struct GNUNET_CADET_Encrypted plaintext_header;
+ uint32_t Np;
+ uint32_t PNp;
+ size_t esize; /* Size of encryped payload */
+
+ esize = size - sizeof (struct GNUNET_CADET_Encrypted);
+ ax = &t->ax;
+
+ /* Try current HK */
+ t_hmac (&src->Ns,
+ AX_HEADER_SIZE + esize,
+ 0, &ax->HKr,
+ &msg_hmac);
+ if (0 != memcmp (&msg_hmac,
+ &src->hmac,
+ sizeof (msg_hmac)))
+ {
+ static const char ctx[] = "axolotl ratchet";
+ struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */
+ struct GNUNET_CRYPTO_SymmetricSessionKey HK;
+ struct GNUNET_HashCode dh;
+ struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;
+
+ /* Try Next HK */
+ t_hmac (&src->Ns,
+ AX_HEADER_SIZE + esize,
+ 0,
+ &ax->NHKr,
+ &msg_hmac);
+ if (0 != memcmp (&msg_hmac,
+ &src->hmac,
+ sizeof (msg_hmac)))
+ {
+ /* Try the skipped keys, if that fails, we're out of luck. */
+ return try_old_ax_keys (t,
+ dst,
+ src,
+ size);
+ }
+ HK = ax->HKr;
+ ax->HKr = ax->NHKr;
+ t_h_decrypt (t,
+ src,
+ &plaintext_header);
+ Np = ntohl (plaintext_header.Ns);
+ PNp = ntohl (plaintext_header.PNs);
+ DHRp = &plaintext_header.DHRs;
+ store_ax_keys (t,
+ &HK,
+ PNp);
+
+ /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
+ GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
+ DHRp,
+ &dh);
+ t_ax_hmac_hash (&ax->RK,
+ &hmac,
+ &dh, sizeof (dh));
+ GNUNET_CRYPTO_kdf (keys, sizeof (keys),
+ ctx, sizeof (ctx),
+ &hmac, sizeof (hmac),
+ NULL);
+
+ /* Commit "purported" keys */
+ ax->RK = keys[0];
+ ax->NHKr = keys[1];
+ ax->CKr = keys[2];
+ ax->DHRr = *DHRp;
+ ax->Nr = 0;
+ ax->ratchet_allowed = GNUNET_YES;
+ }
+ else
+ {
+ t_h_decrypt (t,
+ src,
+ &plaintext_header);
+ Np = ntohl (plaintext_header.Ns);
+ PNp = ntohl (plaintext_header.PNs);
+ }
+ if ( (Np != ax->Nr) &&
+ (GNUNET_OK != store_ax_keys (t,
+ &ax->HKr,
+ Np)) )
+ {
+ /* Try the skipped keys, if that fails, we're out of luck. */
+ return try_old_ax_keys (t,
+ dst,
+ src,
+ size);
+ }
+
+ t_ax_decrypt (t,
+ dst,
+ &src[1],
+ esize);
+ ax->Nr = Np + 1;
+ return esize;
+}
+
+
+/* ************************************** end core crypto
***************************** */
+
+
+/**
* Add a channel to a tunnel.
*
* @param t Tunnel.
@@ -569,6 +1211,8 @@ connection_ready_cb (void *cls)
GNUNET_CONTAINER_DLL_remove (t->tq_head,
t->tq_tail,
tq);
+ if (NULL != tq->cid)
+ *tq->cid = *GCC_get_id (ct->cc);
GCC_transmit (ct->cc,
tq->env);
tq->cont (tq->cont_cls);
@@ -694,6 +1338,7 @@ consider_path_cb (void *cls,
ct->t = t;
ct->cc = GCC_create (t->destination,
path,
+ ct,
&connection_ready_cb,
t);
/* FIXME: schedule job to kill connection (and path?) if it takes
@@ -794,23 +1439,45 @@ GCT_send (struct CadetTunnel *t,
GNUNET_SCHEDULER_TaskCallback cont,
void *cont_cls)
{
- struct CadetTunnelQueueEntry *q;
+ struct CadetTunnelQueueEntry *tq;
uint16_t payload_size;
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_CADET_Encrypted *ax_msg;
- payload_size = ntohs (message->size);
+ /* FIXME: what about KX not yet being ready? (see "is_ready()" check in old
code!) */
- q = GNUNET_malloc (sizeof (*q) +
- payload_size);
- /* FIXME: encrypt 'message' to end of 'q' */
- q->t = t;
- q->cont = cont;
- q->cont_cls = cont_cls;
+ payload_size = ntohs (message->size);
+ env = GNUNET_MQ_msg_extra (ax_msg,
+ payload_size,
+ GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED);
+ t_ax_encrypt (t,
+ &ax_msg[1],
+ message,
+ payload_size);
+ ax_msg->Ns = htonl (t->ax.Ns++);
+ ax_msg->PNs = htonl (t->ax.PNs);
+ GNUNET_CRYPTO_ecdhe_key_get_public (t->ax.DHRs,
+ &ax_msg->DHRs);
+ t_h_encrypt (t,
+ ax_msg);
+ t_hmac (&ax_msg->Ns,
+ AX_HEADER_SIZE + payload_size,
+ 0,
+ &t->ax.HKs,
+ &ax_msg->hmac);
+ // ax_msg->pid = htonl (GCC_get_pid (c, fwd)); // FIXME: connection
flow-control not (re)implemented yet!
+
+ tq = GNUNET_malloc (sizeof (*tq));
+ tq->t = t;
+ tq->env = env;
+ tq->cid = &ax_msg->cid;
+ tq->cont = cont;
+ tq->cont_cls = cont_cls;
GNUNET_CONTAINER_DLL_insert_tail (t->tq_head,
t->tq_tail,
- q);
- /* FIXME: what about KX being ready? */
+ tq);
trigger_transmissions (t);
- return q;
+ return tq;
}
--
To stop receiving notification emails like this one, please contact
address@hidden
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] [gnunet] branch master updated: importing KX logic, integrating encryption logic,
gnunet <=