#define DUMP_KEYS_TO_STDERR GNUNET_NO
#endif
+#define MIN_TUNNEL_BUFFER 8
+#define MAX_TUNNEL_BUFFER 64
#define MAX_SKIPPED_KEYS 64
#define MAX_KEY_GAP 256
#define AX_HEADER_SIZE (sizeof (uint32_t) * 2\
*/
struct GNUNET_CRYPTO_EcdhePrivateKey *kx_0;
- /**
- * ECDH Identity key (recv).
- */
- struct GNUNET_CRYPTO_EcdhePublicKey DHIr;
-
/**
* ECDH Ratchet key (send).
*/
};
-/**
- * Cached Axolotl key with signature.
- */
-struct CadetAxolotlSignedKey
-{
- /**
- * Information about what is being signed (@a permanent_key).
- */
- struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
-
- /**
- * Permanent public ECDH key.
- */
- struct GNUNET_CRYPTO_EcdhePublicKey permanent_key;
-
- /**
- * An EdDSA signature of the permanent ECDH key with the Peer's ID key.
- */
- struct GNUNET_CRYPTO_EddsaSignature signature;
-} GNUNET_PACKED;
-
-
/******************************************************************************/
/******************************* GLOBALS ***********************************/
/******************************************************************************/
/******************************** AXOLOTL ************************************/
-static struct GNUNET_CRYPTO_EcdhePrivateKey *ax_key;
-
-/**
- * Own Axolotl permanent public key (cache).
- */
-static struct CadetAxolotlSignedKey ax_identity;
-
/**
* How many messages are needed to trigger a ratchet advance.
*/
}
-/**
- * Ephemeral key message purpose size.
- *
- * @return Size of the part of the ephemeral key message that must be signed.
- */
-static size_t
-ax_purpose_size (void)
-{
- return sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
-}
-
-
/**
* Size of the encrypted part of a ping message.
*
* @param t Tunnel on which the message came.
* @param msg The ephemeral key message.
*
- * @return GNUNET_OK if message is fine, GNUNET_SYSERR otherwise.
+ * @return #GNUNET_OK if message is fine, #GNUNET_SYSERR otherwise.
*/
int
check_ephemeral (struct CadetTunnel *t,
}
-
/**
* The peer's ephemeral key has changed: update the symmetrical keys.
*
* @param msg Key eXchange Pong message.
*/
static void
-handle_pong (struct CadetTunnel *t, const struct GNUNET_CADET_KX_Pong *msg)
+handle_pong (struct CadetTunnel *t,
+ const struct GNUNET_CADET_KX_Pong *msg)
{
uint32_t challenge;
struct CadetTunnelAxolotl *ax;
struct GNUNET_HashCode key_material[3];
struct GNUNET_CRYPTO_SymmetricSessionKey keys[5];
- const struct GNUNET_CRYPTO_EcdhePublicKey *pub;
- const struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
const char salt[] = "CADET Axolotl salt";
const struct GNUNET_PeerIdentity *pid;
int am_I_alice;
return;
}
- if (GNUNET_OK != GCP_check_key (t->peer, &msg->permanent_key,
- &msg->purpose, &msg->signature))
- {
- GNUNET_break_op (0);
- return;
- }
-
pid = GCT_get_destination (t);
if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, pid))
am_I_alice = GNUNET_YES;
return;
}
- if (GNUNET_YES == ntohl (msg->force_reply))
+ if (GNUNET_CADET_AX_KX_FLAG_FORCE_REPLY ==
+ (GNUNET_CADET_AX_KX_FLAG_FORCE_REPLY & ntohl (msg->flags)))
GCT_send_ax_kx (t, GNUNET_NO);
if (CADET_TUNNEL_KEY_OK == t->estate)
ax = t->ax;
ax->DHRr = msg->ratchet_key;
- ax->DHIr = msg->permanent_key;
/* ECDH A B0 */
if (GNUNET_YES == am_I_alice)
{
- priv = ax_key; /* A */
- pub = &msg->ephemeral_key; /* B0 */
+ GNUNET_CRYPTO_eddsa_ecdh (id_key, /* A */
+ &msg->ephemeral_key, /* B0 */
+ &key_material[0]);
}
else
{
- priv = ax->kx_0; /* B0 */
- pub = &ax->DHIr; /* A */
+ GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* B0 */
+ &pid->public_key, /* A */
+ &key_material[0]);
}
- GNUNET_CRYPTO_ecc_ecdh (priv, pub, &key_material[0]);
/* ECDH A0 B */
if (GNUNET_YES == am_I_alice)
{
- priv = ax->kx_0; /* A0 */
- pub = &ax->DHIr; /* B */
+ GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* A0 */
+ &pid->public_key, /* B */
+ &key_material[1]);
}
else
{
- priv = ax_key; /* B */
- pub = &msg->ephemeral_key; /* A0 */
+ GNUNET_CRYPTO_eddsa_ecdh (id_key, /* A */
+ &msg->ephemeral_key, /* B0 */
+ &key_material[1]);
+
+
}
- GNUNET_CRYPTO_ecc_ecdh (priv, pub, &key_material[1]);
- /* ECDH A0 B0*/
- priv = ax->kx_0; /* A0 or B0 */
- pub = &msg->ephemeral_key; /* B0 or A0 */
- GNUNET_CRYPTO_ecc_ecdh (priv, pub, &key_material[2]);
+ /* 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 */
+ &msg->ephemeral_key, /* B0 or A0 */
+ &key_material[2]);
#if DUMP_KEYS_TO_STDERR
{
size_t payload_size;
int decrypted_size;
uint16_t type;
- struct GNUNET_MessageHeader *msgh;
+ const struct GNUNET_MessageHeader *msgh;
unsigned int off;
type = ntohs (msg->type);
- if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == type)
+ switch (type)
{
- const struct GNUNET_CADET_Encrypted *emsg;
+ case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+ {
+ const struct GNUNET_CADET_Encrypted *emsg;
- emsg = (struct GNUNET_CADET_Encrypted *) msg;
- payload_size = size - sizeof (struct GNUNET_CADET_Encrypted);
- decrypted_size = t_decrypt_and_validate (t, cbuf, &emsg[1], payload_size,
- emsg->iv, &emsg->hmac);
- }
- else if (GNUNET_MESSAGE_TYPE_CADET_AX == type)
- {
- const struct GNUNET_CADET_AX *emsg;
+ emsg = (const struct GNUNET_CADET_Encrypted *) msg;
+ payload_size = size - sizeof (struct GNUNET_CADET_Encrypted);
+ decrypted_size = t_decrypt_and_validate (t, cbuf, &emsg[1], payload_size,
+ emsg->iv, &emsg->hmac);
+ }
+ break;
+ case GNUNET_MESSAGE_TYPE_CADET_AX:
+ {
+ const struct GNUNET_CADET_AX *emsg;
- emsg = (struct GNUNET_CADET_AX *) msg;
- decrypted_size = t_ax_decrypt_and_validate (t, cbuf, emsg, size);
+ emsg = (const struct GNUNET_CADET_AX *) msg;
+ decrypted_size = t_ax_decrypt_and_validate (t, cbuf, emsg, size);
+ }
+ break;
+ default:
+ GNUNET_break_op (0);
+ return;
}
-
if (-1 == decrypted_size)
{
GNUNET_break_op (0);
return;
}
+ /* FIXME: this is bad, as the structs returned from
+ this loop may be unaligned, see util's MST for
+ how to do this right. */
off = 0;
while (off < decrypted_size)
{
uint16_t msize;
- msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
+ msgh = (const struct GNUNET_MessageHeader *) &cbuf[off];
msize = ntohs (msgh->size);
if (msize < sizeof (struct GNUNET_MessageHeader))
{
otr_kx_msg.purpose.size = htonl (ephemeral_purpose_size ());
otr_kx_msg.origin_identity = my_full_id;
rekey_task = GNUNET_SCHEDULER_add_now (&global_otr_rekey, NULL);
-
- ax_key = GNUNET_CRYPTO_ecdhe_key_create ();
- GNUNET_CRYPTO_ecdhe_key_get_public (ax_key, &ax_identity.permanent_key);
- ax_identity.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CADET_AXKX);
- ax_identity.purpose.size = htonl (ax_purpose_size ());
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_eddsa_sign (id_key,
- &ax_identity.purpose,
- &ax_identity.signature));
-
tunnels = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
}
}
GNUNET_CONTAINER_multipeermap_iterate (tunnels, &destroy_iterator, NULL);
GNUNET_CONTAINER_multipeermap_destroy (tunnels);
- GNUNET_free (ax_key);
}
GNUNET_CONTAINER_multipeermap_remove (tunnels,
GCP_get_id (t->peer), t));
+ while (NULL != t->tq_head)
+ unqueue_data (t->tq_head);
+
for (iter_c = t->connection_head; NULL != iter_c; iter_c = next_c)
{
next_c = iter_c->next;
{
/* Probably getting buffer for a channel create/handshake. */
LOG (GNUNET_ERROR_TYPE_DEBUG, " no channels, allow max\n");
- return 64;
+ return MIN_TUNNEL_BUFFER;
}
buffer = 0;
if (ch_buf > buffer)
buffer = ch_buf;
}
+ if (MIN_TUNNEL_BUFFER > buffer)
+ return MIN_TUNNEL_BUFFER;
+
+ if (MAX_TUNNEL_BUFFER < buffer)
+ {
+ GNUNET_break (0);
+ return MAX_TUNNEL_BUFFER;
+ }
return buffer;
}
if (NULL != t->channel_head)
LOG (GNUNET_ERROR_TYPE_DEBUG, " head ch: %p\n", t->channel_head->ch);
+ if (NULL != t->tq_head)
+ send_queued_data (t);
+
/* Get buffer space */
buffer = GCT_get_connections_buffer (t);
if (0 == buffer)
{
if (NULL != q->cq)
{
+ GNUNET_assert (NULL == q->tqd);
GCC_cancel (q->cq);
/* tun_message_sent() will be called and free q */
}
GCT_send_ax_kx (struct CadetTunnel *t, int force_reply)
{
struct GNUNET_CADET_AX_KX msg;
+ enum GNUNET_CADET_AX_KX_Flags flags;
LOG (GNUNET_ERROR_TYPE_INFO, "===> AX_KX for %s\n", GCT_2s (t));
if (NULL != t->ephm_h)
msg.header.size = htons (sizeof (msg));
msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_AX_KX);
- msg.force_reply = htonl (force_reply);
- msg.permanent_key = ax_identity.permanent_key;
- msg.purpose = ax_identity.purpose;
- msg.signature = ax_identity.signature;
+ flags = GNUNET_CADET_AX_KX_FLAG_NONE;
+ if (force_reply)
+ flags |= GNUNET_CADET_AX_KX_FLAG_FORCE_REPLY;
+ msg.flags = htonl (flags);
GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->kx_0, &msg.ephemeral_key);
GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &msg.ratchet_key);
LOG2 (level, "TTT CKr\t %s\n",
GNUNET_h2s ((struct GNUNET_HashCode *) &ax->CKr));
- GNUNET_CRYPTO_ecdhe_key_get_public (ax_key, &pub);
- LOG2 (level, "TTT DHIs\t %s\n",
- GNUNET_h2s ((struct GNUNET_HashCode *) &pub));
- LOG2 (level, "TTT DHIr\t %s\n",
- GNUNET_h2s ((struct GNUNET_HashCode *) &ax->DHIr));
GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs, &pub);
LOG2 (level, "TTT DHRs\t %s\n",
- GNUNET_h2s ((struct GNUNET_HashCode *) &pub));
+ GNUNET_i2s ((struct GNUNET_PeerIdentity *) &pub));
LOG2 (level, "TTT DHRr\t %s\n",
GNUNET_h2s ((struct GNUNET_HashCode *) &ax->DHRr));