diff options
-rw-r--r-- | src/config.c | 1 | ||||
-rw-r--r-- | src/fastd.h | 2 | ||||
-rw-r--r-- | src/method_aes128_gcm.c | 9 | ||||
-rw-r--r-- | src/method_null.c | 4 | ||||
-rw-r--r-- | src/method_xsalsa20_poly1305.c | 9 | ||||
-rw-r--r-- | src/protocol_ec25519_fhmqvc.c | 15 |
6 files changed, 35 insertions, 5 deletions
diff --git a/src/config.c b/src/config.c index d5165dd..48a9c8c 100644 --- a/src/config.c +++ b/src/config.c @@ -107,6 +107,7 @@ static void default_config(fastd_config_t *conf) { conf->protocol = &fastd_protocol_ec25519_fhmqvc; conf->method_default = &fastd_method_null; conf->key_valid = 3600; /* 60 minutes */ + conf->key_valid_old = 60; /* 1 minute */ conf->key_refresh = 3300; /* 55 minutes */ conf->key_refresh_splay = 300; /* 5 minutes */ diff --git a/src/fastd.h b/src/fastd.h index f74cb9d..c6e25cb 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -94,6 +94,7 @@ struct fastd_method { bool (*session_is_valid)(fastd_context_t *ctx, fastd_method_session_state_t *session); bool (*session_is_initiator)(fastd_context_t *ctx, fastd_method_session_state_t *session); bool (*session_want_refresh)(fastd_context_t *ctx, fastd_method_session_state_t *session); + void (*session_superseded)(fastd_context_t *ctx, fastd_method_session_state_t *session); void (*session_free)(fastd_context_t *ctx, fastd_method_session_state_t *session); bool (*encrypt)(fastd_context_t *ctx, fastd_peer_t *peer, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in); @@ -212,6 +213,7 @@ struct fastd_config { char *secret; unsigned key_valid; + unsigned key_valid_old; unsigned key_refresh; unsigned key_refresh_splay; diff --git a/src/method_aes128_gcm.c b/src/method_aes128_gcm.c index 4e51ecf..1b91925 100644 --- a/src/method_aes128_gcm.c +++ b/src/method_aes128_gcm.c @@ -145,6 +145,14 @@ static bool method_session_want_refresh(fastd_context_t *ctx, fastd_method_sessi return timespec_after(&ctx->now, &session->refresh_after); } +static void method_session_superseded(fastd_context_t *ctx, fastd_method_session_state_t *session) { + struct timespec valid_max = ctx->now; + valid_max.tv_sec += ctx->conf->key_valid_old; + + if (timespec_after(&session->valid_till, &valid_max)) + session->valid_till = valid_max; +} + static void method_session_free(fastd_context_t *ctx, fastd_method_session_state_t *session) { if(session) { ctx->conf->crypto_aes128ctr->free_state(ctx, session->cstate_aes128ctr); @@ -301,6 +309,7 @@ const fastd_method_t fastd_method_aes128_gcm = { .session_is_valid = method_session_is_valid, .session_is_initiator = method_session_is_initiator, .session_want_refresh = method_session_want_refresh, + .session_superseded = method_session_superseded, .session_free = method_session_free, .encrypt = method_encrypt, diff --git a/src/method_null.c b/src/method_null.c index 640c341..75e248d 100644 --- a/src/method_null.c +++ b/src/method_null.c @@ -54,6 +54,9 @@ static bool method_session_want_refresh(fastd_context_t *ctx UNUSED, fastd_metho return false; } +static void method_session_superseded(fastd_context_t *ctx UNUSED, fastd_method_session_state_t *session UNUSED) { +} + static void method_session_free(fastd_context_t *ctx UNUSED, fastd_method_session_state_t *session UNUSED) { } @@ -75,6 +78,7 @@ const fastd_method_t fastd_method_null = { .session_is_valid = method_session_is_valid, .session_is_initiator = method_session_is_initiator, .session_want_refresh = method_session_want_refresh, + .session_superseded = method_session_superseded, .session_free = method_session_free, .encrypt = method_passthrough, diff --git a/src/method_xsalsa20_poly1305.c b/src/method_xsalsa20_poly1305.c index d0d31f4..395f322 100644 --- a/src/method_xsalsa20_poly1305.c +++ b/src/method_xsalsa20_poly1305.c @@ -129,6 +129,14 @@ static bool method_session_want_refresh(fastd_context_t *ctx, fastd_method_sessi return timespec_after(&ctx->now, &session->refresh_after); } +static void method_session_superseded(fastd_context_t *ctx, fastd_method_session_state_t *session) { + struct timespec valid_max = ctx->now; + valid_max.tv_sec += ctx->conf->key_valid_old; + + if (timespec_after(&session->valid_till, &valid_max)) + session->valid_till = valid_max; +} + static void method_session_free(fastd_context_t *ctx UNUSED, fastd_method_session_state_t *session) { if(session) { secure_memzero(session, sizeof(fastd_method_session_state_t)); @@ -231,6 +239,7 @@ const fastd_method_t fastd_method_xsalsa20_poly1305 = { .session_is_valid = method_session_is_valid, .session_is_initiator = method_session_is_initiator, .session_want_refresh = method_session_want_refresh, + .session_superseded = method_session_superseded, .session_free = method_session_free, .encrypt = method_encrypt, diff --git a/src/protocol_ec25519_fhmqvc.c b/src/protocol_ec25519_fhmqvc.c index 889793b..fd9c6a4 100644 --- a/src/protocol_ec25519_fhmqvc.c +++ b/src/protocol_ec25519_fhmqvc.c @@ -408,10 +408,15 @@ static bool establish(fastd_context_t *ctx, fastd_peer_t *peer, const fastd_meth peer->protocol_state->session.method->session_free(ctx, peer->protocol_state->session.method_state); } - if (peer->protocol_state->old_session.method && 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){}; + 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; @@ -782,7 +787,7 @@ static void protocol_handle_recv(fastd_context_t *ctx, fastd_peer_t *peer, fastd if (peer->protocol_state->session.method->decrypt(ctx, peer, peer->protocol_state->session.method_state, &recv_buffer, buffer)) { ok = true; - if (peer->protocol_state->old_session.method_state) { + if (peer->protocol_state->old_session.method) { pr_debug(ctx, "invalidating old session with %P", 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){}; |