summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/handshake.c52
-rw-r--r--src/handshake.h34
-rw-r--r--src/peer.c2
-rw-r--r--src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c412
-rw-r--r--src/protocol_null.c12
5 files changed, 240 insertions, 272 deletions
diff --git a/src/handshake.c b/src/handshake.c
index fcec5af..ce8895d 100644
--- a/src/handshake.c
+++ b/src/handshake.c
@@ -39,6 +39,11 @@ static const char const *RECORD_TYPES[RECORD_MAX] = {
"flags",
"mode",
"protocol name",
+ "(protocol specific 1)",
+ "(protocol specific 2)",
+ "(protocol specific 3)",
+ "(protocol specific 4)",
+ "(protocol specific 5)",
};
static const char const *REPLY_TYPES[REPLY_MAX] = {
@@ -49,31 +54,6 @@ static const char const *REPLY_TYPES[REPLY_MAX] = {
#define AS_UINT8(ptr) (*(uint8_t*)(ptr).data)
-static inline void handshake_add(fastd_context *ctx, fastd_buffer *buffer, fastd_handshake_record_type type, size_t len, const void *data) {
- if ((uint8_t*)buffer->data + buffer->len + 2 + len > (uint8_t*)buffer->base + buffer->base_len)
- exit_bug(ctx, "not enough buffer allocated for handshake");
-
- uint8_t *dst = (uint8_t*)buffer->data + buffer->len;
-
- dst[0] = type;
- dst[1] = len;
- memcpy(dst+2, data, len);
-
- buffer->len += 2 + len;
-}
-
-static inline void handshake_add_uint8(fastd_context *ctx, fastd_buffer *buffer, fastd_handshake_record_type type, uint8_t value) {
- if ((uint8_t*)buffer->data + buffer->len + 3 > (uint8_t*)buffer->base + buffer->base_len)
- exit_bug(ctx, "not enough buffer allocated for handshake");
-
- uint8_t *dst = (uint8_t*)buffer->data + buffer->len;
-
- dst[0] = type;
- dst[1] = 1;
- dst[2] = value;
-
- buffer->len += 3;
-}
fastd_buffer fastd_handshake_new_init(fastd_context *ctx, fastd_peer *peer, size_t tail_space) {
size_t protocol_len = strlen(ctx->conf->protocol->name);
@@ -87,10 +67,10 @@ fastd_buffer fastd_handshake_new_init(fastd_context *ctx, fastd_peer *peer, size
request->req_id = ++peer->last_req_id;
request->rsv = 0;
- handshake_add_uint8(ctx, &buffer, RECORD_HANDSHAKE_TYPE, 1);
- handshake_add_uint8(ctx, &buffer, RECORD_MODE, ctx->conf->mode);
+ fastd_handshake_add_uint8(ctx, &buffer, RECORD_HANDSHAKE_TYPE, 1);
+ fastd_handshake_add_uint8(ctx, &buffer, RECORD_MODE, ctx->conf->mode);
- handshake_add(ctx, &buffer, RECORD_PROTOCOL_NAME, protocol_len, ctx->conf->protocol->name);
+ fastd_handshake_add(ctx, &buffer, RECORD_PROTOCOL_NAME, protocol_len, ctx->conf->protocol->name);
return buffer;
}
@@ -105,8 +85,8 @@ fastd_buffer fastd_handshake_new_reply(fastd_context *ctx, fastd_peer *peer, con
request->req_id = handshake->req_id;
request->rsv = 0;
- handshake_add_uint8(ctx, &buffer, RECORD_HANDSHAKE_TYPE, AS_UINT8(handshake->records[RECORD_HANDSHAKE_TYPE])+1);
- handshake_add_uint8(ctx, &buffer, RECORD_REPLY_CODE, 0);
+ fastd_handshake_add_uint8(ctx, &buffer, RECORD_HANDSHAKE_TYPE, AS_UINT8(handshake->records[RECORD_HANDSHAKE_TYPE])+1);
+ fastd_handshake_add_uint8(ctx, &buffer, RECORD_REPLY_CODE, 0);
return buffer;
}
@@ -145,7 +125,9 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b
if (handshake.records[RECORD_HANDSHAKE_TYPE].length != 1)
goto end_free;
- if (AS_UINT8(handshake.records[RECORD_HANDSHAKE_TYPE]) == 1) {
+ handshake.type = AS_UINT8(handshake.records[RECORD_HANDSHAKE_TYPE]);
+
+ if (handshake.type == 1) {
uint8_t reply_code = REPLY_SUCCESS;
uint8_t error_detail = 0;
@@ -182,16 +164,16 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b
reply->req_id = packet->req_id;
reply->rsv = 0;
- handshake_add_uint8(ctx, &reply_buffer, RECORD_HANDSHAKE_TYPE, 2);
- handshake_add_uint8(ctx, &reply_buffer, RECORD_REPLY_CODE, reply_code);
- handshake_add_uint8(ctx, &reply_buffer, RECORD_ERROR_DETAIL, error_detail);
+ fastd_handshake_add_uint8(ctx, &reply_buffer, RECORD_HANDSHAKE_TYPE, 2);
+ fastd_handshake_add_uint8(ctx, &reply_buffer, RECORD_REPLY_CODE, reply_code);
+ fastd_handshake_add_uint8(ctx, &reply_buffer, RECORD_ERROR_DETAIL, error_detail);
}
else {
ctx->conf->protocol->handshake_handle(ctx, peer, &handshake);
}
}
else {
- if ((AS_UINT8(handshake.records[RECORD_HANDSHAKE_TYPE]) & 1) == 0) {
+ if ((handshake.type & 1) == 0) {
if (packet->req_id != peer->last_req_id) {
pr_warn(ctx, "received handshake reply with request ID %u from %P while %u was expected", packet->req_id, peer, peer->last_req_id);
goto end_free;
diff --git a/src/handshake.h b/src/handshake.h
index 064e167..c59d141 100644
--- a/src/handshake.h
+++ b/src/handshake.h
@@ -28,7 +28,6 @@
#define _FASTD_HANDSHAKE_H_
#include "fastd.h"
-#include "packet.h"
typedef enum _fastd_handshake_record_type {
@@ -38,6 +37,11 @@ typedef enum _fastd_handshake_record_type {
RECORD_FLAGS,
RECORD_MODE,
RECORD_PROTOCOL_NAME,
+ RECORD_PROTOCOL1,
+ RECORD_PROTOCOL2,
+ RECORD_PROTOCOL3,
+ RECORD_PROTOCOL4,
+ RECORD_PROTOCOL5,
RECORD_MAX,
} fastd_handshake_record_type;
@@ -56,6 +60,7 @@ typedef struct _fastd_handshake_record {
struct _fastd_handshake {
uint8_t req_id;
+ uint8_t type;
fastd_handshake_record records[RECORD_MAX];
};
@@ -66,4 +71,31 @@ fastd_buffer fastd_handshake_new_reply(fastd_context *ctx, fastd_peer *peer, con
void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer);
+static inline void fastd_handshake_add(fastd_context *ctx, fastd_buffer *buffer, fastd_handshake_record_type type, size_t len, const void *data) {
+ if ((uint8_t*)buffer->data + buffer->len + 2 + len > (uint8_t*)buffer->base + buffer->base_len)
+ exit_bug(ctx, "not enough buffer allocated for handshake");
+
+ uint8_t *dst = (uint8_t*)buffer->data + buffer->len;
+
+ dst[0] = type;
+ dst[1] = len;
+ memcpy(dst+2, data, len);
+
+ buffer->len += 2 + len;
+}
+
+static inline void fastd_handshake_add_uint8(fastd_context *ctx, fastd_buffer *buffer, fastd_handshake_record_type type, uint8_t value) {
+ if ((uint8_t*)buffer->data + buffer->len + 3 > (uint8_t*)buffer->base + buffer->base_len)
+ exit_bug(ctx, "not enough buffer allocated for handshake");
+
+ uint8_t *dst = (uint8_t*)buffer->data + buffer->len;
+
+ dst[0] = type;
+ dst[1] = 1;
+ dst[2] = value;
+
+ buffer->len += 3;
+}
+
+
#endif /* _FASTD_HANDSHAKE_H_ */
diff --git a/src/peer.c b/src/peer.c
index ea53e95..ff72c8e 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -169,6 +169,8 @@ fastd_peer* fastd_peer_set_established_merge(fastd_context *ctx, fastd_peer *per
fastd_peer_reset(ctx, temp_peer);
+ pr_info(ctx, "Connection with %P established.", perm_peer);
+
return perm_peer;
}
diff --git a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
index 449a1c6..5b05041 100644
--- a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
+++ b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
@@ -27,6 +27,7 @@
#define _GNU_SOURCE
#include "fastd.h"
+#include "handshake.h"
#include "peer.h"
#include "task.h"
@@ -105,39 +106,12 @@ struct _fastd_protocol_peer_state {
protocol_handshake *accepting_handshake;
};
-typedef enum _handshake_packet_type {
- HANDSHAKE_PACKET_INIT = 0,
- HANDSHAKE_PACKET_RESPONSE,
- HANDSHAKE_PACKET_FINISH
-} handshake_packet_type;
-
-typedef struct __attribute__ ((__packed__)) _protocol_handshake_packet_common {
- uint8_t noncepad[NONCEBYTES];
- uint8_t type;
-
- uint8_t sender_key[PUBLICKEYBYTES];
- uint8_t receipient_key[PUBLICKEYBYTES];
-} protocol_handshake_packet_common;
-
-typedef struct __attribute__ ((__packed__)) _protocol_handshake_init_packet {
- protocol_handshake_packet_common common;
- uint8_t handshake_key[PUBLICKEYBYTES];
-} protocol_handshake_init_packet;
-
-typedef struct __attribute__ ((__packed__)) _protocol_handshake_response_finish_packet {
- protocol_handshake_packet_common common;
- uint8_t handshake_key[PUBLICKEYBYTES];
- uint8_t handshake_key2[PUBLICKEYBYTES];
- uint8_t t[HMACBYTES];
-} protocol_handshake_response_packet, protocol_handshake_finish_packet;
-
-typedef union _protocol_handshake_packet {
- protocol_handshake_packet_common common;
- protocol_handshake_init_packet init;
- protocol_handshake_response_packet response;
- protocol_handshake_finish_packet finish;
-} protocol_handshake_packet;
+#define RECORD_SENDER_KEY RECORD_PROTOCOL1
+#define RECORD_RECEIPIENT_KEY RECORD_PROTOCOL2
+#define RECORD_SENDER_HANDSHAKE_KEY RECORD_PROTOCOL3
+#define RECORD_RECEIPIENT_HANDSHAKE_KEY RECORD_PROTOCOL4
+#define RECORD_T RECORD_PROTOCOL5
static inline bool read_key(uint8_t key[32], const char *hexkey) {
@@ -235,7 +209,10 @@ static size_t protocol_min_decrypt_head_space(fastd_context *ctx) {
return (crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES - NONCEBYTES);
}
-static void create_peer_state(fastd_context *ctx, fastd_peer *peer) {
+static void init_peer_state(fastd_context *ctx, fastd_peer *peer) {
+ if (peer->protocol_state)
+ return;
+
peer->protocol_state = malloc(sizeof(fastd_protocol_peer_state));
peer->protocol_state->old_session.valid = false;
@@ -251,7 +228,7 @@ static inline void free_handshake(protocol_handshake *handshake) {
}
}
-static void new_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_peer_config *peer_config, bool initiate) {
+static protocol_handshake* new_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_peer_config *peer_config, bool initiate) {
protocol_handshake **handshake;
if (initiate)
@@ -273,50 +250,39 @@ static void new_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_peer
ecc_25519_work work;
ecc_25519_scalarmult_base(&work, &(*handshake)->secret_key);
ecc_25519_store(&(*handshake)->public_key, &work);
-}
-static void protocol_handshake_init(fastd_context *ctx, fastd_peer *peer) {
+ return *handshake;
}
-static void protocol_handshake_handle(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
-}
-
-#if 0
-static void protocol_init_peer(fastd_context *ctx, fastd_peer *peer) {
- pr_info(ctx, "Initializing session with %P...", peer);
+static void protocol_handshake_init(fastd_context *ctx, fastd_peer *peer) {
+ init_peer_state(ctx, peer);
- if (peer->protocol_state) {
- pr_warn(ctx, "trying to reinitialize session with %P", peer);
- return;
- }
+ fastd_buffer buffer = fastd_handshake_new_init(ctx, peer, 3*(2+PUBLICKEYBYTES) /* sender key, receipient key, handshake key */);
- if (fastd_peer_is_temporary(peer)) {
- pr_warn(ctx, "trying to initialize session for temporary peer %P", peer);
- return;
- }
+ protocol_handshake *handshake = new_handshake(ctx, peer, peer->config, true);
- create_peer_state(ctx, peer);
+ fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p);
- new_handshake(ctx, peer, peer->config, true);
+ if (handshake->peer_config)
+ fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, handshake->peer_config->protocol_config->public_key.p);
+ else
+ pr_debug(ctx, "sending handshake to unknown peer %P", peer);
- fastd_buffer buffer = fastd_buffer_alloc(sizeof(protocol_handshake_init_packet), 0, 0);
- protocol_handshake_init_packet *packet = buffer.data;
+ fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, handshake->public_key.p);
- memset(packet->common.noncepad, 0, NONCEBYTES);
- packet->common.type = HANDSHAKE_PACKET_INIT;
- memcpy(packet->common.sender_key, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->common.receipient_key, peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->handshake_key, peer->protocol_state->initiating_handshake->public_key.p, PUBLICKEYBYTES);
+ fastd_task_put_send_handshake(ctx, peer, buffer);
+}
- fastd_task_put_send(ctx, peer, buffer);
+static inline bool has_field(const fastd_handshake *handshake, uint8_t type, size_t length) {
+ return (handshake->records[type].length == length);
}
-#endif
-static void respond_handshake(fastd_context *ctx, fastd_peer *peer) {
- pr_info(ctx, "Responding protocol handshake with %P...", peer);
+static void respond_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
+ pr_info(ctx, "Responding handshake with %P...", peer);
uint8_t hashinput[5*PUBLICKEYBYTES];
uint8_t hashbuf[HASHBYTES];
+ uint8_t hmacbuf[HMACBYTES];
memcpy(hashinput, peer->protocol_state->accepting_handshake->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_key.p, PUBLICKEYBYTES);
@@ -355,25 +321,36 @@ static void respond_handshake(fastd_context *ctx, fastd_peer *peer) {
memcpy(hashinput, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->public_key.p, PUBLICKEYBYTES);
- fastd_buffer buffer = fastd_buffer_alloc(sizeof(protocol_handshake_response_packet), 0, 0);
- protocol_handshake_response_packet *packet = buffer.data;
+ crypto_auth_hmacsha256(hmacbuf, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->shared_handshake_key);
- memset(packet->common.noncepad, 0, NONCEBYTES);
- packet->common.type = HANDSHAKE_PACKET_RESPONSE;
- memcpy(packet->common.sender_key, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->common.receipient_key, peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->handshake_key, peer->protocol_state->accepting_handshake->peer_key.p, PUBLICKEYBYTES);
- memcpy(packet->handshake_key2, peer->protocol_state->accepting_handshake->public_key.p, PUBLICKEYBYTES);
+ fastd_buffer buffer = fastd_handshake_new_reply(ctx, peer, handshake, 4*(2+PUBLICKEYBYTES) + 2+HMACBYTES);
- crypto_auth_hmacsha256(packet->t, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->shared_handshake_key);
+ fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->public_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_T, HMACBYTES, hmacbuf);
- fastd_task_put_send(ctx, peer, buffer);
+ fastd_task_put_send_handshake(ctx, peer, buffer);
peer->protocol_state->accepting_handshake->state = HANDSHAKE_STATE_RESPONSE;
}
-static void establish(fastd_context *ctx, fastd_peer *peer, const fastd_peer_config *peer_config, bool initiator) {
+static void establish(fastd_context *ctx, fastd_peer *peer, const fastd_peer_config *peer_config, bool initiator,
+ const ecc_public_key_256 *A, const ecc_public_key_256 *B, const ecc_public_key_256 *X,
+ const ecc_public_key_256 *Y, const ecc_public_key_256 *sigma) {
int i;
+ uint8_t hashinput[5*PUBLICKEYBYTES];
+
+ if (peer->protocol_state->session.valid)
+ peer->protocol_state->old_session = peer->protocol_state->session;
+
+ memcpy(hashinput, X->p, PUBLICKEYBYTES);
+ memcpy(hashinput+PUBLICKEYBYTES, Y->p, PUBLICKEYBYTES);
+ memcpy(hashinput+2*PUBLICKEYBYTES, A->p, PUBLICKEYBYTES);
+ memcpy(hashinput+3*PUBLICKEYBYTES, B->p, PUBLICKEYBYTES);
+ memcpy(hashinput+4*PUBLICKEYBYTES, sigma->p, PUBLICKEYBYTES);
+ crypto_hash_sha256(peer->protocol_state->session.key, hashinput, 5*PUBLICKEYBYTES);
peer->protocol_state->session.valid = true;
peer->protocol_state->session.since = ctx->now;
@@ -385,7 +362,7 @@ static void establish(fastd_context *ctx, fastd_peer *peer, const fastd_peer_con
peer->protocol_state->session.receive_nonce[i] = 0;
}
- pr_info(ctx, "Connection with %P established.", peer);
+ peer->seen = ctx->now;
if (peer_config != peer->config) {
fastd_peer *perm_peer;
@@ -396,13 +373,17 @@ static void establish(fastd_context *ctx, fastd_peer *peer, const fastd_peer_con
}
}
}
+ else {
+ fastd_peer_set_established(ctx, peer);
+ }
}
-static void finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMACBYTES]) {
+static void finish_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
pr_info(ctx, "Finishing protocol handshake with %P...", peer);
uint8_t hashinput[5*PUBLICKEYBYTES];
uint8_t hashbuf[HASHBYTES];
+ uint8_t hmacbuf[HMACBYTES];
memcpy(hashinput, peer->protocol_state->initiating_handshake->peer_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->public_key.p, PUBLICKEYBYTES);
@@ -441,68 +422,55 @@ static void finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMA
memcpy(hashinput, peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->peer_key.p, PUBLICKEYBYTES);
- if(crypto_auth_hmacsha256_verify(t, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->shared_handshake_key) != 0) {
+ if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->shared_handshake_key) != 0) {
pr_warn(ctx, "received invalid protocol handshake response from %P", peer);
return;
}
memcpy(hashinput, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->public_key.p, PUBLICKEYBYTES);
+ crypto_auth_hmacsha256(hmacbuf, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->shared_handshake_key);
- fastd_buffer buffer = fastd_buffer_alloc(sizeof(protocol_handshake_finish_packet), 0, 0);
- protocol_handshake_finish_packet *packet = buffer.data;
-
- memset(packet->common.noncepad, 0, NONCEBYTES);
- packet->common.type = HANDSHAKE_PACKET_FINISH;
- memcpy(packet->common.sender_key, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->common.receipient_key, peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->handshake_key, peer->protocol_state->initiating_handshake->peer_key.p, PUBLICKEYBYTES);
- memcpy(packet->handshake_key2, peer->protocol_state->initiating_handshake->public_key.p, PUBLICKEYBYTES);
+ fastd_buffer buffer = fastd_handshake_new_reply(ctx, peer, handshake, 4*(2+PUBLICKEYBYTES) + 2+HMACBYTES);
- crypto_auth_hmacsha256(packet->t, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->shared_handshake_key);
+ fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->public_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->peer_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_T, HMACBYTES, hmacbuf);
- fastd_task_put_send(ctx, peer, buffer);
-
- if (peer->protocol_state->session.valid)
- peer->protocol_state->old_session = peer->protocol_state->session;
-
- memcpy(hashinput, peer->protocol_state->initiating_handshake->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->peer_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+2*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+3*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+4*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->sigma.p, PUBLICKEYBYTES);
- crypto_hash_sha256(peer->protocol_state->session.key, hashinput, 5*PUBLICKEYBYTES);
+ fastd_task_put_send_handshake(ctx, peer, buffer);
- establish(ctx, peer, peer->protocol_state->initiating_handshake->peer_config, true);
+ establish(ctx, peer, peer->protocol_state->initiating_handshake->peer_config, true,
+ &peer->protocol_state->initiating_handshake->public_key,
+ &peer->protocol_state->initiating_handshake->peer_key,
+ &ctx->conf->protocol_config->public_key,
+ &peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key,
+ &peer->protocol_state->initiating_handshake->sigma);
}
-static void handle_finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMACBYTES]) {
- uint8_t hashinput[5*PUBLICKEYBYTES];
+static void handle_finish_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
+ uint8_t hashinput[2*PUBLICKEYBYTES];
memcpy(hashinput, peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_key.p, PUBLICKEYBYTES);
- if(crypto_auth_hmacsha256_verify(t, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->shared_handshake_key) != 0) {
+ if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->shared_handshake_key) != 0) {
pr_warn(ctx, "received invalid protocol handshake finish from %P", peer);
return;
}
- if (peer->protocol_state->session.valid)
- peer->protocol_state->old_session = peer->protocol_state->session;
-
- memcpy(hashinput, peer->protocol_state->accepting_handshake->peer_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+2*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+3*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+4*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->sigma.p, PUBLICKEYBYTES);
- crypto_hash_sha256(peer->protocol_state->session.key, hashinput, 5*PUBLICKEYBYTES);
-
- establish(ctx, peer, peer->protocol_state->accepting_handshake->peer_config, false);
+ establish(ctx, peer, peer->protocol_state->accepting_handshake->peer_config, false,
+ &peer->protocol_state->accepting_handshake->peer_key,
+ &peer->protocol_state->accepting_handshake->public_key,
+ &peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key,
+ &ctx->conf->protocol_config->public_key,
+ &peer->protocol_state->accepting_handshake->sigma);
}
-static inline const fastd_peer_config* match_sender_key(fastd_context *ctx, const fastd_peer *peer, const protocol_handshake_packet *packet) {
+static inline const fastd_peer_config* match_sender_key(fastd_context *ctx, const fastd_peer *peer, const unsigned char key[32]) {
if (peer->config) {
- if (memcmp(peer->config->protocol_config->public_key.p, packet->common.sender_key, PUBLICKEYBYTES) == 0)
+ if (memcmp(peer->config->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0)
return peer->config;
}
@@ -512,7 +480,7 @@ static inline const fastd_peer_config* match_sender_key(fastd_context *ctx, cons
if (!fastd_peer_config_is_floating(config))
continue;
- if (memcmp(config->protocol_config->public_key.p, packet->common.sender_key, PUBLICKEYBYTES) == 0)
+ if (memcmp(config->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0)
return config;
}
}
@@ -520,148 +488,136 @@ static inline const fastd_peer_config* match_sender_key(fastd_context *ctx, cons
return NULL;
}
-static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) {
- if (buffer.len < NONCEBYTES)
- goto end;
-
- /* protocol handshake */
- if (is_nonce_zero(buffer.data)) {
- if (buffer.len < sizeof(protocol_handshake_packet_common)) {
- pr_debug(ctx, "received short protocol handshake from %P", peer);
- goto end;
- }
+static void protocol_handshake_handle(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
+ init_peer_state(ctx, peer);
- protocol_handshake_packet *packet = buffer.data;
+ if (!has_field(handshake, RECORD_SENDER_KEY, PUBLICKEYBYTES)) {
+ pr_debug(ctx, "received handshake without sender key from %P", peer);
+ return;
+ }
- if (!peer->protocol_state)
- create_peer_state(ctx, peer);
+ const fastd_peer_config *peer_config = match_sender_key(ctx, peer, handshake->records[RECORD_SENDER_KEY].data);
- if (memcmp(ctx->conf->protocol_config->public_key.p, packet->common.receipient_key, PUBLICKEYBYTES) != 0) {
+ if (handshake->type > 1 && !has_field(handshake, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES)) {
+ pr_debug(ctx, "received handshake reply without receipient key from %P", peer);
+ return;
+ }
+ else if(has_field(handshake, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES)) {
+ if (memcmp(ctx->conf->protocol_config->public_key.p, handshake->records[RECORD_RECEIPIENT_KEY].data, PUBLICKEYBYTES) != 0) {
pr_debug(ctx, "received protocol handshake with wrong receipient key from %P", peer);
- goto end;
+ return;
}
+ }
- const fastd_peer_config *peer_config = match_sender_key(ctx, peer, packet);
-
- switch (packet->common.type) {
- case HANDSHAKE_PACKET_INIT:
- if (buffer.len < sizeof(protocol_handshake_init_packet)) {
- pr_debug(ctx, "received short protocol handshake init from %P", peer);
- goto end;
- }
-
- if (!peer_config) {
- pr_debug(ctx, "received protocol handshake init with wrong sender key from %P", peer);
- goto end;
- }
-
- pr_debug(ctx, "received protocol handshake init from %P", peer);
-
- new_handshake(ctx, peer, peer_config, false);
- memcpy(peer->protocol_state->accepting_handshake->peer_key.p, packet->init.handshake_key, PUBLICKEYBYTES);
-
- fastd_peer_set_established(ctx, peer);
- respond_handshake(ctx, peer);
-
- break;
-
- case HANDSHAKE_PACKET_RESPONSE:
- if (buffer.len < sizeof(protocol_handshake_response_packet)) {
- pr_debug(ctx, "received short protocol handshake response from %P", peer);
- goto end;
- }
+ if (!has_field(handshake, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES)) {
+ pr_debug(ctx, "received handshake without sender handshake key from %P", peer);
+ return;
+ }
- if (!peer->protocol_state->initiating_handshake || peer->protocol_state->initiating_handshake->state != HANDSHAKE_STATE_INIT) {
- pr_debug(ctx, "received unexpected protocol handshake response from %P", peer);
- goto end;
- }
+ if (handshake->type > 1 && !has_field(handshake, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES)) {
+ pr_debug(ctx, "received handshake reply without receipient handshake key from %P", peer);
+ return;
+ }
- if (peer->protocol_state->initiating_handshake->peer_config != peer_config) {
- pr_debug(ctx, "received protocol handshake response with wrong sender key from %P", peer);
- goto end;
- }
+ if (handshake->type > 1 && !has_field(handshake, RECORD_T, HMACBYTES)) {
+ pr_debug(ctx, "received handshake reply without HMAC from %P", peer);
+ return;
+ }
- if (memcmp(peer->protocol_state->initiating_handshake->public_key.p, packet->response.handshake_key, PUBLICKEYBYTES) != 0) {
- pr_debug(ctx, "received protocol handshake response with unexpected handshake key from %P", peer);
- goto end;
- }
+ switch(handshake->type) {
+ case 1:
+ new_handshake(ctx, peer, peer_config, false);
+ memcpy(peer->protocol_state->accepting_handshake->peer_key.p, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, PUBLICKEYBYTES);
+ respond_handshake(ctx, peer, handshake);
+ break;
+
+ case 2:
+ if (!peer->protocol_state->initiating_handshake || peer->protocol_state->initiating_handshake->state != HANDSHAKE_STATE_INIT) {
+ pr_debug(ctx, "received unexpected handshake response from %P", peer);
+ return;
+ }
- pr_debug(ctx, "received protocol handshake response from %P", peer);
- memcpy(peer->protocol_state->initiating_handshake->peer_key.p, packet->response.handshake_key2, PUBLICKEYBYTES);
+ if (peer->protocol_state->initiating_handshake->peer_config != peer_config) {
+ pr_debug(ctx, "received handshake response with wrong sender key from %P", peer);
+ return;
+ }
- finish_handshake(ctx, peer, packet->response.t);
+ if (memcmp(peer->protocol_state->initiating_handshake->public_key.p, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) != 0) {
+ pr_debug(ctx, "received handshake response with unexpected receipient handshake key from %P", peer);
+ return;
+ }
- break;
+ pr_debug(ctx, "received handshake response from %P", peer);
+ memcpy(peer->protocol_state->initiating_handshake->peer_key.p, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, PUBLICKEYBYTES);
- case HANDSHAKE_PACKET_FINISH:
- if (buffer.len < sizeof(protocol_handshake_finish_packet)) {
- pr_debug(ctx, "received short protocol handshake finish from %P", peer);
- goto end;
- }
+ finish_handshake(ctx, peer, handshake);
+ break;
- if (!peer->protocol_state->accepting_handshake || peer->protocol_state->accepting_handshake->state != HANDSHAKE_STATE_RESPONSE) {
- pr_debug(ctx, "received unexpected protocol handshake finish from %P", peer);
- goto end;
- }
+ case 3:
+ if (!peer->protocol_state->accepting_handshake || peer->protocol_state->accepting_handshake->state != HANDSHAKE_STATE_RESPONSE) {
+ pr_debug(ctx, "received unexpected protocol handshake finish from %P", peer);
+ return;
+ }
- if (peer->protocol_state->accepting_handshake->peer_config != peer_config) {
- pr_debug(ctx, "received protocol handshake finish with wrong sender key from %P", peer);
- goto end;
- }
+ if (peer->protocol_state->accepting_handshake->peer_config != peer_config) {
+ pr_debug(ctx, "received protocol handshake finish with wrong sender key from %P", peer);
+ return;
+ }
- if (memcmp(peer->protocol_state->accepting_handshake->public_key.p, packet->finish.handshake_key, PUBLICKEYBYTES) != 0) {
- pr_debug(ctx, "received protocol handshake finish with unexpected handshake key from %P", peer);
- goto end;
- }
+ if (memcmp(peer->protocol_state->accepting_handshake->public_key.p, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) != 0) {
+ pr_debug(ctx, "received handshake response with unexpected receipient handshake key from %P", peer);
+ return;
+ }
- if (memcmp(peer->protocol_state->accepting_handshake->peer_key.p, packet->finish.handshake_key2, PUBLICKEYBYTES) != 0) {
- pr_debug(ctx, "received protocol handshake finish with unexpected peer handshake key from %P", peer);
- goto end;
- }
+ if (memcmp(peer->protocol_state->accepting_handshake->peer_key.p, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, PUBLICKEYBYTES) != 0) {
+ pr_debug(ctx, "received handshake response with unexpected sender handshake key from %P", peer);
+ return;
+ }
+ handle_finish_handshake(ctx, peer, handshake);
+ break;
+ default:
+ pr_debug(ctx, "received handshake reply with unknown type %u", handshake->type);
+ }
+}
- pr_debug(ctx, "received protocol handshake finish from %P", peer);
+static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) {
+ if (!fastd_peer_is_established(peer))
+ goto end;
- handle_finish_handshake(ctx, peer, packet->finish.t);
- break;
+ if (buffer.len < NONCEBYTES)
+ goto end;
- default:
- pr_debug(ctx, "received protocol handshake with invalid type from %P", peer);
- goto end;
- }
+ if (!peer->protocol_state || !peer->protocol_state->session.valid) {
+ pr_debug(ctx, "received unexpected packet from %P", peer);
+ goto end;
}
- else {
- if (!peer->protocol_state || !peer->protocol_state->session.valid) {
- pr_debug(ctx, "received unexpected non-handshake packet from %P", peer);
- goto end;
- }
- if (!is_nonce_valid(buffer.data, peer->protocol_state->session.receive_nonce)) {
- pr_debug(ctx, "received packet with invalid nonce from %P", peer);
- goto end;
- }
+ if (!is_nonce_valid(buffer.data, peer->protocol_state->session.receive_nonce)) {
+ pr_debug(ctx, "received packet with invalid nonce from %P", peer);
+ goto end;
+ }
- uint8_t nonce[crypto_secretbox_xsalsa20poly1305_NONCEBYTES];
- memcpy(nonce, buffer.data, NONCEBYTES);
- memset(nonce+NONCEBYTES, 0, crypto_secretbox_xsalsa20poly1305_NONCEBYTES-NONCEBYTES);
+ uint8_t nonce[crypto_secretbox_xsalsa20poly1305_NONCEBYTES];
+ memcpy(nonce, buffer.data, NONCEBYTES);
+ memset(nonce+NONCEBYTES, 0, crypto_secretbox_xsalsa20poly1305_NONCEBYTES-NONCEBYTES);
- fastd_buffer_pull_head(&buffer, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES-NONCEBYTES);
- memset(buffer.data, 0, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES);
+ fastd_buffer_pull_head(&buffer, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES-NONCEBYTES);
+ memset(buffer.data, 0, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES);
- fastd_buffer recv_buffer = fastd_buffer_alloc(buffer.len, 0, 0);
+ fastd_buffer recv_buffer = fastd_buffer_alloc(buffer.len, 0, 0);
- if (crypto_secretbox_xsalsa20poly1305_open(recv_buffer.data, buffer.data, buffer.len, nonce, peer->protocol_state->session.key) != 0) {
- pr_debug(ctx, "verification failed for packet received from %P", peer);
- fastd_buffer_free(recv_buffer);
- goto end;
- }
+ if (crypto_secretbox_xsalsa20poly1305_open(recv_buffer.data, buffer.data, buffer.len, nonce, peer->protocol_state->session.key) != 0) {
+ pr_debug(ctx, "verification failed for packet received from %P", peer);
+ fastd_buffer_free(recv_buffer);
+ goto end;
+ }
- fastd_buffer_push_head(&recv_buffer, crypto_secretbox_xsalsa20poly1305_ZEROBYTES);
- fastd_task_put_handle_recv(ctx, peer, recv_buffer);
+ fastd_buffer_push_head(&recv_buffer, crypto_secretbox_xsalsa20poly1305_ZEROBYTES);
+ fastd_task_put_handle_recv(ctx, peer, recv_buffer);
- memcpy(peer->protocol_state->session.receive_nonce, nonce, NONCEBYTES);
- }
+ memcpy(peer->protocol_state->session.receive_nonce, nonce, NONCEBYTES);
end:
fastd_buffer_free(buffer);
diff --git a/src/protocol_null.c b/src/protocol_null.c
index 3a85e6c..d9588b3 100644
--- a/src/protocol_null.c
+++ b/src/protocol_null.c
@@ -34,9 +34,6 @@
#include <arpa/inet.h>
-#define AS_UINT8(ptr) (*(uint8_t*)(ptr).data)
-
-
static void protocol_init(fastd_context *ctx, fastd_config *conf) {
if (conf->n_floating > 1)
exit_error(ctx, "with protocol `null' use can't define more than one floating peer");
@@ -56,6 +53,8 @@ static void protocol_handshake_init(fastd_context *ctx, fastd_peer *peer) {
}
static void establish(fastd_context *ctx, fastd_peer *peer) {
+ peer->seen = ctx->now;
+
if (fastd_peer_is_temporary(peer)) {
fastd_peer *perm_peer;
for (perm_peer = ctx->peers; perm_peer; perm_peer = perm_peer->next) {
@@ -77,27 +76,24 @@ static void establish(fastd_context *ctx, fastd_peer *peer) {
static void protocol_handshake_handle(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
fastd_buffer buffer;
- switch(AS_UINT8(handshake->records[RECORD_HANDSHAKE_TYPE])) {
+ switch(handshake->type) {
case 1:
buffer = fastd_handshake_new_reply(ctx, peer, handshake, 0);
fastd_task_put_send_handshake(ctx, peer, buffer);
break;
case 2:
- peer->seen = ctx->now;
establish(ctx, peer);
buffer = fastd_handshake_new_reply(ctx, peer, handshake, 0);
fastd_task_put_send_handshake(ctx, peer, buffer);
break;
case 3:
- peer->seen = ctx->now;
establish(ctx, peer);
break;
default:
- pr_debug(ctx, "received handshake reply with unknown type %u", AS_UINT8(handshake->records[RECORD_HANDSHAKE_TYPE]));
- break;
+ pr_debug(ctx, "received handshake reply with unknown type %u", handshake->type);
}
}