summaryrefslogtreecommitdiffstats
path: root/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c')
-rw-r--r--src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c170
1 files changed, 86 insertions, 84 deletions
diff --git a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
index d743d9c..cd5df2d 100644
--- a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
+++ b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
@@ -63,21 +63,22 @@
#endif
-struct _fastd_protocol_context {
+struct _fastd_protocol_config {
ecc_secret_key_256 secret_key;
ecc_public_key_256 public_key;
};
typedef enum _handshake_state {
- HANDSHAKE_STATE_INIT = 0,
+ HANDSHAKE_STATE_INIT,
HANDSHAKE_STATE_RESPONSE,
- HANDSHAKE_STATE_FINISH,
HANDSHAKE_STATE_ESTABLISHED
} handshake_state;
-struct _fastd_protocol_peer_state {
- ecc_public_key_256 peer_public_key;
+struct _fastd_protocol_peer_config {
+ ecc_public_key_256 public_key;
+};
+struct _fastd_protocol_peer_state {
handshake_state state;
ecc_secret_key_256 handshake_secret_key;
ecc_public_key_256 handshake_public_key;
@@ -96,31 +97,29 @@ typedef enum _handshake_packet_type {
HANDSHAKE_PACKET_FINISH
} handshake_packet_type;
-typedef struct __attribute__ ((__packed__)) _protocol_handshake_init_packet {
+
+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 {
- uint8_t noncepad[NONCEBYTES];
- uint8_t type;
-
- uint8_t sender_key[PUBLICKEYBYTES];
- uint8_t receipient_key[PUBLICKEYBYTES];
+ 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 {
- struct {
- uint8_t noncepad[NONCEBYTES];
- uint8_t type;
- };
+ protocol_handshake_packet_common common;
protocol_handshake_init_packet init;
protocol_handshake_response_packet response;
protocol_handshake_finish_packet finish;
@@ -176,18 +175,38 @@ static inline bool is_nonce_valid(const uint8_t nonce[NONCEBYTES], const uint8_t
return false;
}
-static void protocol_init(fastd_context *ctx) {
- ctx->protocol_context = malloc(sizeof(fastd_protocol_context));
+static void protocol_init(fastd_context *ctx, fastd_config *conf) {
+ conf->protocol_config = malloc(sizeof(fastd_protocol_config));
- if (!ctx->conf->secret)
+ if (!conf->secret)
exit_error(ctx, "no secret key configured");
- if (!read_key(ctx->protocol_context->secret_key.s, ctx->conf->secret))
+ if (!read_key(conf->protocol_config->secret_key.s, conf->secret))
exit_error(ctx, "invalid secret key");
ecc_25519_work work;
- ecc_25519_scalarmult_base(&work, &ctx->protocol_context->secret_key);
- ecc_25519_store(&ctx->protocol_context->public_key, &work);
+ ecc_25519_scalarmult_base(&work, &conf->protocol_config->secret_key);
+ ecc_25519_store(&conf->protocol_config->public_key, &work);
+
+ fastd_peer_config *peer;
+ for (peer = conf->peers; peer; peer = peer->next) {
+ ecc_public_key_256 key;
+
+ if (!peer->key) {
+ pr_warn(ctx, "no key configured for %P, disabling peer", peer);
+ peer->enabled = false;
+ continue;
+ }
+
+ if (!read_key(key.p, peer->key)) {
+ pr_warn(ctx, "invalid key configured for %P, disabling peer", peer);
+ peer->enabled = false;
+ continue;
+ }
+
+ peer->protocol_config = malloc(sizeof(sizeof(fastd_protocol_peer_config)));
+ peer->protocol_config->public_key = key;
+ }
}
static size_t protocol_max_packet_size(fastd_context *ctx) {
@@ -243,7 +262,7 @@ static bool create_peer_state(fastd_context *ctx, fastd_peer *peer) {
return false;
}
- if (!read_key(peer->protocol_state->peer_public_key.p, peer->config->key)) {
+ if (!read_key(peer->config->protocol_config->public_key.p, peer->config->key)) {
pr_warn(ctx, "invalid public key configured - ignoring peer %P", peer);
return false;
}
@@ -274,10 +293,10 @@ static void protocol_init_peer(fastd_context *ctx, fastd_peer *peer) {
fastd_buffer buffer = fastd_buffer_alloc(sizeof(protocol_handshake_init_packet), 0, 0);
protocol_handshake_init_packet *packet = buffer.data;
- memset(packet->noncepad, 0, NONCEBYTES);
- packet->type = HANDSHAKE_PACKET_INIT;
- memcpy(packet->sender_key, ctx->protocol_context->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->receipient_key, peer->protocol_state->peer_public_key.p, PUBLICKEYBYTES);
+ 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->config->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(packet->handshake_key, peer->protocol_state->handshake_public_key.p, PUBLICKEYBYTES);
fastd_task_put_send(ctx, peer, buffer);
@@ -298,8 +317,8 @@ static void respond_handshake(fastd_context *ctx, fastd_peer *peer) {
memcpy(hashinput, peer->protocol_state->handshake_public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->peer_handshake_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+2*PUBLICKEYBYTES, ctx->protocol_context->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+3*PUBLICKEYBYTES, peer->protocol_state->peer_public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+2*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+3*PUBLICKEYBYTES, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
crypto_hash_sha256(hashbuf, hashinput, 4*PUBLICKEYBYTES);
@@ -311,11 +330,11 @@ static void respond_handshake(fastd_context *ctx, fastd_peer *peer) {
d.s[15] |= 0x80;
e.s[15] |= 0x80;
- ecc_25519_secret_mult(&eb, &e, &ctx->protocol_context->secret_key);
+ ecc_25519_secret_mult(&eb, &e, &ctx->conf->protocol_config->secret_key);
ecc_25519_secret_add(&s, &eb, &peer->protocol_state->handshake_secret_key);
ecc_25519_work workX;
- ecc_25519_load(&work, &peer->protocol_state->peer_public_key);
+ ecc_25519_load(&work, &peer->config->protocol_config->public_key);
ecc_25519_load(&workX, &peer->protocol_state->peer_handshake_key);
ecc_25519_scalarmult(&work, &d, &work);
@@ -327,16 +346,16 @@ static void respond_handshake(fastd_context *ctx, fastd_peer *peer) {
memcpy(hashinput+4*PUBLICKEYBYTES, peer->protocol_state->sigma.p, PUBLICKEYBYTES);
crypto_hash_sha256(peer->protocol_state->shared_handshake_key, hashinput, 5*PUBLICKEYBYTES);
- memcpy(hashinput, ctx->protocol_context->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->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;
- memset(packet->noncepad, 0, NONCEBYTES);
- packet->type = HANDSHAKE_PACKET_RESPONSE;
- memcpy(packet->sender_key, ctx->protocol_context->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->receipient_key, peer->protocol_state->peer_public_key.p, PUBLICKEYBYTES);
+ 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->config->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(packet->handshake_key, peer->protocol_state->peer_handshake_key.p, PUBLICKEYBYTES);
memcpy(packet->handshake_key2, peer->protocol_state->handshake_public_key.p, PUBLICKEYBYTES);
@@ -370,8 +389,8 @@ static void finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMA
memcpy(hashinput, peer->protocol_state->peer_handshake_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->handshake_public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+2*PUBLICKEYBYTES, peer->protocol_state->peer_public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+3*PUBLICKEYBYTES, ctx->protocol_context->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+2*PUBLICKEYBYTES, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+3*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
crypto_hash_sha256(hashbuf, hashinput, 4*PUBLICKEYBYTES);
@@ -383,11 +402,11 @@ static void finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMA
d.s[15] |= 0x80;
e.s[15] |= 0x80;
- ecc_25519_secret_mult(&da, &d, &ctx->protocol_context->secret_key);
+ ecc_25519_secret_mult(&da, &d, &ctx->conf->protocol_config->secret_key);
ecc_25519_secret_add(&s, &da, &peer->protocol_state->handshake_secret_key);
ecc_25519_work work, workY;
- ecc_25519_load(&work, &peer->protocol_state->peer_public_key);
+ ecc_25519_load(&work, &peer->config->protocol_config->public_key);
ecc_25519_load(&workY, &peer->protocol_state->peer_handshake_key);
ecc_25519_scalarmult(&work, &e, &work);
@@ -399,7 +418,7 @@ static void finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMA
memcpy(hashinput+4*PUBLICKEYBYTES, peer->protocol_state->sigma.p, PUBLICKEYBYTES);
crypto_hash_sha256(peer->protocol_state->shared_handshake_key, hashinput, 5*PUBLICKEYBYTES);
- memcpy(hashinput, peer->protocol_state->peer_public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->peer_handshake_key.p, PUBLICKEYBYTES);
if(crypto_auth_hmacsha256_verify(t, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->shared_handshake_key) != 0) {
@@ -407,16 +426,16 @@ static void finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMA
return;
}
- memcpy(hashinput, ctx->protocol_context->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->handshake_public_key.p, PUBLICKEYBYTES);
fastd_buffer buffer = fastd_buffer_alloc(sizeof(protocol_handshake_finish_packet), 0, 0);
protocol_handshake_finish_packet *packet = buffer.data;
- memset(packet->noncepad, 0, NONCEBYTES);
- packet->type = HANDSHAKE_PACKET_FINISH;
- memcpy(packet->sender_key, ctx->protocol_context->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->receipient_key, peer->protocol_state->peer_public_key.p, PUBLICKEYBYTES);
+ 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->config->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(packet->handshake_key, peer->protocol_state->peer_handshake_key.p, PUBLICKEYBYTES);
memcpy(packet->handshake_key2, peer->protocol_state->handshake_public_key.p, PUBLICKEYBYTES);
@@ -426,8 +445,8 @@ static void finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMA
memcpy(hashinput, peer->protocol_state->handshake_public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->peer_handshake_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+2*PUBLICKEYBYTES, ctx->protocol_context->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+3*PUBLICKEYBYTES, peer->protocol_state->peer_public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+2*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+3*PUBLICKEYBYTES, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+4*PUBLICKEYBYTES, peer->protocol_state->sigma.p, PUBLICKEYBYTES);
crypto_hash_sha256(peer->protocol_state->shared_session_key, hashinput, 5*PUBLICKEYBYTES);
@@ -437,7 +456,7 @@ static void finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMA
static void handle_finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_t t[HMACBYTES]) {
uint8_t hashinput[5*PUBLICKEYBYTES];
- memcpy(hashinput, peer->protocol_state->peer_public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->peer_handshake_key.p, PUBLICKEYBYTES);
if(crypto_auth_hmacsha256_verify(t, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->shared_handshake_key) != 0) {
@@ -447,8 +466,8 @@ static void handle_finish_handshake(fastd_context *ctx, fastd_peer *peer, uint8_
memcpy(hashinput, peer->protocol_state->peer_handshake_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->handshake_public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+2*PUBLICKEYBYTES, peer->protocol_state->peer_public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+3*PUBLICKEYBYTES, ctx->protocol_context->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+2*PUBLICKEYBYTES, 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->sigma.p, PUBLICKEYBYTES);
crypto_hash_sha256(peer->protocol_state->shared_session_key, hashinput, 5*PUBLICKEYBYTES);
@@ -461,7 +480,7 @@ static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buf
/* protocol handshake */
if (is_nonce_zero(buffer.data)) {
- if (buffer.len < NONCEBYTES+1) {
+ if (buffer.len < sizeof(protocol_handshake_packet_common)) {
pr_debug(ctx, "received short protocol handshake from %P", peer);
goto end;
}
@@ -478,23 +497,23 @@ static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buf
goto end; /* TODO disable peer */
}
- switch (packet->type) {
+ if (memcmp(ctx->conf->protocol_config->public_key.p, packet->common.receipient_key, PUBLICKEYBYTES) != 0) {
+ pr_debug(ctx, "received protocol handshake with wrong receipient key from %P", peer);
+ goto end;
+ }
+
+ if (memcmp(peer->config->protocol_config->public_key.p, packet->common.sender_key, PUBLICKEYBYTES) != 0) {
+ pr_debug(ctx, "received protocol handshake with wrong sender key from %P", peer);
+ goto end;
+ }
+
+ 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 (memcmp(ctx->protocol_context->public_key.p, packet->init.receipient_key, PUBLICKEYBYTES) != 0) {
- pr_debug(ctx, "received protocol handshake init with wrong receipient key from %P", peer);
- goto end;
- }
-
- if (memcmp(peer->protocol_state->peer_public_key.p, packet->init.sender_key, PUBLICKEYBYTES) != 0) {
- pr_debug(ctx, "received protocol handshake init with wrong sender key from %P", peer);
- goto end;
- }
-
if (peer->protocol_state->state != HANDSHAKE_STATE_INIT) {
pr_debug(ctx, "received unexpected protocol handshake init from %P", peer);
goto end;
@@ -514,16 +533,6 @@ static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buf
goto end;
}
- if (memcmp(ctx->protocol_context->public_key.p, packet->response.receipient_key, PUBLICKEYBYTES) != 0) {
- pr_debug(ctx, "received protocol handshake response with wrong receipient key from %P", peer);
- goto end;
- }
-
- if (memcmp(peer->protocol_state->peer_public_key.p, packet->response.sender_key, PUBLICKEYBYTES) != 0) {
- pr_debug(ctx, "received protocol handshake response with wrong sender key from %P", peer);
- goto end;
- }
-
if (memcmp(peer->protocol_state->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;
@@ -548,16 +557,6 @@ static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buf
goto end;
}
- if (memcmp(ctx->protocol_context->public_key.p, packet->finish.receipient_key, PUBLICKEYBYTES) != 0) {
- pr_debug(ctx, "received protocol handshake finish with wrong receipient key from %P", peer);
- goto end;
- }
-
- if (memcmp(peer->protocol_state->peer_public_key.p, packet->finish.sender_key, PUBLICKEYBYTES) != 0) {
- pr_debug(ctx, "received protocol handshake finish with wrong sender key from %P", peer);
- goto end;
- }
-
if (memcmp(peer->protocol_state->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;
@@ -577,8 +576,11 @@ static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buf
pr_debug(ctx, "received protocol handshake finish from %P", peer);
handle_finish_handshake(ctx, peer, packet->finish.t);
-
break;
+
+ default:
+ pr_debug(ctx, "received protocol handshake with invalid type from %P", peer);
+ goto end;
}
}
else {
@@ -601,7 +603,7 @@ static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buf
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->shared_session_key) != 0) {
- pr_debug(ctx, "varification failed for packet received from %P", peer);
+ pr_debug(ctx, "verification failed for packet received from %P", peer);
goto end;
}