diff options
Diffstat (limited to 'src/protocols/ec25519_fhmqvc/handshake.c')
-rw-r--r-- | src/protocols/ec25519_fhmqvc/handshake.c | 178 |
1 files changed, 94 insertions, 84 deletions
diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c index d1c0bf9..43f5797 100644 --- a/src/protocols/ec25519_fhmqvc/handshake.c +++ b/src/protocols/ec25519_fhmqvc/handshake.c @@ -49,26 +49,85 @@ #define RECORD_T RECORD_PROTOCOL5 -static bool backoff(fastd_context_t *ctx, const fastd_peer_t *peer) { - return (peer->protocol_state && is_session_valid(ctx, &peer->protocol_state->session) - && timespec_diff(&ctx->now, &peer->protocol_state->session.established) < 15000); +static inline void supersede_session(fastd_context_t *ctx, fastd_peer_t *peer, const fastd_method_t *method) { + if (is_session_valid(ctx, &peer->protocol_state->session) && !is_session_valid(ctx, &peer->protocol_state->old_session)) { + if (peer->protocol_state->old_session.method) + peer->protocol_state->old_session.method->session_free(ctx, peer->protocol_state->old_session.method_state); + peer->protocol_state->old_session = peer->protocol_state->session; + } + else { + if (peer->protocol_state->session.method) + peer->protocol_state->session.method->session_free(ctx, peer->protocol_state->session.method_state); + } + + if (peer->protocol_state->old_session.method) { + if (peer->protocol_state->old_session.method != method) { + pr_debug(ctx, "method of %P has changed, terminating old session", peer); + peer->protocol_state->old_session.method->session_free(ctx, peer->protocol_state->old_session.method_state); + peer->protocol_state->old_session = (protocol_session_t){}; + } + else { + peer->protocol_state->old_session.method->session_superseded(ctx, peer->protocol_state->old_session.method_state); + } + } } -void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer) { - fastd_protocol_ec25519_fhmqvc_maintenance(ctx); +static inline void new_session(fastd_context_t *ctx, fastd_peer_t *peer, const fastd_method_t *method, bool initiator, + const aligned_int256_t *A, const aligned_int256_t *B, const aligned_int256_t *X, + const aligned_int256_t *Y, const aligned_int256_t *sigma, uint64_t serial) { + supersede_session(ctx, peer, method); - fastd_buffer_t buffer = fastd_handshake_new_init(ctx, 3*(4+PUBLICKEYBYTES) /* sender key, receipient key, handshake key */); + fastd_sha256_t hash; + fastd_sha256_blocks(&hash, X->p, Y->p, A->p, B->p, sigma->p, NULL); - fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->key.public.p); + peer->protocol_state->session.established = ctx->now; + peer->protocol_state->session.handshakes_cleaned = false; + peer->protocol_state->session.refreshing = false; + peer->protocol_state->session.method = method; + peer->protocol_state->session.method_state = method->session_init_compat(ctx, hash.b, HASHBYTES, initiator); + peer->protocol_state->last_serial = serial; +} - if (peer) - fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->protocol_config->public_key.p); +static bool establish(fastd_context_t *ctx, fastd_peer_t *peer, const char *method_name, fastd_socket_t *sock, + const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, bool initiator, + const aligned_int256_t *A, const aligned_int256_t *B, const aligned_int256_t *X, + const aligned_int256_t *Y, const aligned_int256_t *sigma, uint64_t serial) { + if (serial <= peer->protocol_state->last_serial) { + pr_debug(ctx, "ignoring handshake from %P[%I] because of handshake key reuse", peer, remote_addr); + return false; + } + + pr_verbose(ctx, "%I authorized as %P", remote_addr, peer); + + if (!fastd_peer_claim_address(ctx, peer, sock, local_addr, remote_addr)) { + pr_warn(ctx, "can't set address %I which is used by a fixed peer", remote_addr); + fastd_peer_reset(ctx, peer); + return false; + } + + const fastd_method_t *method = fastd_method_get_by_name(method_name); + new_session(ctx, peer, method, initiator, A, B, X, Y, sigma, serial); + + fastd_peer_seen(ctx, peer); + fastd_peer_set_established(ctx, peer); + + pr_verbose(ctx, "new session with %P established using method `%s'.", peer, method_name); + + if (initiator) + fastd_peer_schedule_handshake_default(ctx, peer); else - pr_debug(ctx, "sending handshake to unknown peer %I", remote_addr); + fastd_protocol_ec25519_fhmqvc_send_empty(ctx, peer, &peer->protocol_state->session); - fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, ctx->protocol_state->handshake_key.key1.public.p); + return true; +} - fastd_send_handshake(ctx, sock, local_addr, remote_addr, peer, buffer); + +static inline bool has_field(const fastd_handshake_t *handshake, uint8_t type, size_t length) { + return (handshake->records[type].length == length); +} + +static inline bool secure_handshake(const fastd_handshake_t *handshake) { + return has_field(handshake, RECORD_TLV_MAC, HASHBYTES); } @@ -183,78 +242,6 @@ static void respond_handshake(fastd_context_t *ctx, const fastd_socket_t *sock, fastd_send_handshake(ctx, sock, local_addr, remote_addr, peer, buffer); } -static bool establish(fastd_context_t *ctx, fastd_peer_t *peer, const char *method_name, fastd_socket_t *sock, - const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, bool initiator, - const aligned_int256_t *A, const aligned_int256_t *B, const aligned_int256_t *X, - const aligned_int256_t *Y, const aligned_int256_t *sigma, uint64_t serial) { - if (serial <= peer->protocol_state->last_serial) { - pr_debug(ctx, "ignoring handshake from %P[%I] because of handshake key reuse", peer, remote_addr); - return false; - } - - pr_verbose(ctx, "%I authorized as %P", remote_addr, peer); - - if (!fastd_peer_claim_address(ctx, peer, sock, local_addr, remote_addr)) { - pr_warn(ctx, "can't set address %I which is used by a fixed peer", remote_addr); - fastd_peer_reset(ctx, peer); - return false; - } - - const fastd_method_t *method = fastd_method_get_by_name(method_name); - - if (is_session_valid(ctx, &peer->protocol_state->session) && !is_session_valid(ctx, &peer->protocol_state->old_session)) { - if (peer->protocol_state->old_session.method) - peer->protocol_state->old_session.method->session_free(ctx, peer->protocol_state->old_session.method_state); - peer->protocol_state->old_session = peer->protocol_state->session; - } - else { - if (peer->protocol_state->session.method) - peer->protocol_state->session.method->session_free(ctx, peer->protocol_state->session.method_state); - } - - if (peer->protocol_state->old_session.method) { - if (peer->protocol_state->old_session.method != method) { - pr_debug(ctx, "method of %P[%I] has changed, terminating old session", peer, remote_addr); - peer->protocol_state->old_session.method->session_free(ctx, peer->protocol_state->old_session.method_state); - peer->protocol_state->old_session = (protocol_session_t){}; - } - else { - peer->protocol_state->old_session.method->session_superseded(ctx, peer->protocol_state->old_session.method_state); - } - } - - fastd_sha256_t hash; - fastd_sha256_blocks(&hash, X->p, Y->p, A->p, B->p, sigma->p, NULL); - - peer->protocol_state->session.established = ctx->now; - peer->protocol_state->session.handshakes_cleaned = false; - peer->protocol_state->session.refreshing = false; - peer->protocol_state->session.method = method; - peer->protocol_state->session.method_state = method->session_init_compat(ctx, hash.b, HASHBYTES, initiator); - peer->protocol_state->last_serial = serial; - - fastd_peer_seen(ctx, peer); - - fastd_peer_set_established(ctx, peer); - - pr_verbose(ctx, "new session with %P established using method `%s'.", peer, method_name); - - if (initiator) - fastd_peer_schedule_handshake_default(ctx, peer); - else - fastd_protocol_ec25519_fhmqvc_send_empty(ctx, peer, &peer->protocol_state->session); - - return true; -} - -static inline bool has_field(const fastd_handshake_t *handshake, uint8_t type, size_t length) { - return (handshake->records[type].length == length); -} - -static inline bool secure_handshake(const fastd_handshake_t *handshake) { - return has_field(handshake, RECORD_TLV_MAC, HASHBYTES); -} - static void finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const handshake_key_t *handshake_key, const aligned_int256_t *peer_handshake_key, const fastd_handshake_t *handshake, const char *method) { pr_debug(ctx, "finishing handshake with %P[%I]...", peer, remote_addr); @@ -467,10 +454,33 @@ static inline fastd_peer_t* add_temporary(fastd_context_t *ctx, const fastd_peer return peer; } + +static inline bool backoff(fastd_context_t *ctx, const fastd_peer_t *peer) { + return (peer->protocol_state && is_session_valid(ctx, &peer->protocol_state->session) + && timespec_diff(&ctx->now, &peer->protocol_state->session.established) < 15000); +} + static inline keypair_t* get_handshake_keypair(handshake_key_t *handshake_key, uint8_t type) { return (type % 2) ? &handshake_key->key2 : &handshake_key->key1; } +void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer) { + fastd_protocol_ec25519_fhmqvc_maintenance(ctx); + + fastd_buffer_t buffer = fastd_handshake_new_init(ctx, 3*(4+PUBLICKEYBYTES) /* sender key, receipient key, handshake key */); + + fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->key.public.p); + + if (peer) + fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->protocol_config->public_key.p); + else + pr_debug(ctx, "sending handshake to unknown peer %I", remote_addr); + + fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, ctx->protocol_state->handshake_key.key1.public.p); + + fastd_send_handshake(ctx, sock, local_addr, remote_addr, peer, buffer); +} + void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_context_t *ctx, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, const char *method) { bool temporary_added = false; |