commit 853b54dea4c56ea2913caf58ad6d337502b18b91 Author: Alexander Færøy ahf@torproject.org Date: Fri Mar 10 13:00:20 2017 +0100
Add periodic timer for expiring old onion keys.
This patch adds a new timer that is executed when it is time to expire our current set of old onion keys. Because of proposal #274 this can no longer be assumed to be at the same time we rotate our onion keys since they will be updated less frequently.
See: https://bugs.torproject.org/21641 --- changes/bug21641 | 5 +++++ src/or/main.c | 29 +++++++++++++++++++++++++++++ src/or/router.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/or/router.h | 1 + 4 files changed, 80 insertions(+)
diff --git a/changes/bug21641 b/changes/bug21641 new file mode 100644 index 0000000..96fdf5f --- /dev/null +++ b/changes/bug21641 @@ -0,0 +1,5 @@ + o Minor feature (defaults, directory): + - Onion key rotation and expiry intervals are now defined as a network + consensus parameter as per proposal #274. The default lifetime of an + onion key is bumped from 7 to 28 days. Old onion keys will expire after 7 + days by default. Fixes bug #21641. diff --git a/src/or/main.c b/src/or/main.c index 107a484..d24c674 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1161,6 +1161,7 @@ static int periodic_events_initialized = 0; #define CALLBACK(name) \ static int name ## _callback(time_t, const or_options_t *) CALLBACK(rotate_onion_key); +CALLBACK(check_onion_keys_expiry_time); CALLBACK(check_ed_keys); CALLBACK(launch_descriptor_fetches); CALLBACK(rotate_x509_certificate); @@ -1192,6 +1193,7 @@ CALLBACK(heartbeat);
static periodic_event_item_t periodic_events[] = { CALLBACK(rotate_onion_key), + CALLBACK(check_onion_keys_expiry_time), CALLBACK(check_ed_keys), CALLBACK(launch_descriptor_fetches), CALLBACK(rotate_x509_certificate), @@ -1499,6 +1501,33 @@ rotate_onion_key_callback(time_t now, const or_options_t *options) return PERIODIC_EVENT_NO_UPDATE; }
+/* Period callback: Check if our old onion keys are still valid after the + * period of time defined by the consensus parameter + * "onion-key-grace-period-days", otherwise expire them by setting them to + * NULL. + */ +static int +check_onion_keys_expiry_time_callback(time_t now, const or_options_t *options) +{ + if (server_mode(options)) { + int onion_key_grace_period = get_onion_key_grace_period(); + time_t expiry_time = get_onion_key_set_at()+onion_key_grace_period; + + if (expiry_time > now) { + return safe_timer_diff(now, expiry_time); + } + + log_info(LD_GENERAL, "Expiring old onion keys."); + + expire_old_onion_keys(); + cpuworkers_rotate_keyinfo(); + + return onion_key_grace_period; + } + + return PERIODIC_EVENT_NO_UPDATE; +} + /* Periodic callback: Every 30 seconds, check whether it's time to make new * Ed25519 subkeys. */ diff --git a/src/or/router.c b/src/or/router.c index 2985753..dd869d2 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -148,6 +148,51 @@ dup_onion_keys(crypto_pk_t **key, crypto_pk_t **last) tor_mutex_release(key_lock); }
+/** Expire our old set of onion keys. This is done by setting + * last_curve25519_onion_key and lastonionkey to all zero's and NULL + * respectively. + * + * This function does not perform any grace period checks for the old onion + * keys. + */ +void +expire_old_onion_keys(void) +{ + char *fname = NULL; + + tor_mutex_acquire(key_lock); + + /* Free lastonionkey and set it to NULL. */ + if (lastonionkey) { + crypto_pk_free(lastonionkey); + lastonionkey = NULL; + } + + /* We zero out the keypair. See the tor_mem_is_zero() check made in + * construct_ntor_key_map() below. */ + memset(&last_curve25519_onion_key, 0, sizeof(last_curve25519_onion_key)); + + tor_mutex_release(key_lock); + + fname = get_datadir_fname2("keys", "secret_onion_key.old"); + if (file_status(fname) == FN_FILE) { + if (tor_unlink(fname) != 0) { + log_warn(LD_FS, "Couldn't unlink old onion key file %s: %s", + fname, strerror(errno)); + } + } + tor_free(fname); + + fname = get_datadir_fname2("keys", "secret_onion_key_ntor.old"); + if (file_status(fname) == FN_FILE) { + if (tor_unlink(fname) != 0) { + log_warn(LD_FS, "Couldn't unlink old ntor onion key file %s: %s", + fname, strerror(errno)); + } + } + tor_free(fname); +} + /** Return the current secret onion key for the ntor handshake. Must only * be called from the main thread. */ static const curve25519_keypair_t * diff --git a/src/or/router.h b/src/or/router.h index 55a3927..a02488f 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -27,6 +27,7 @@ crypto_pk_t *get_my_v3_authority_signing_key(void); authority_cert_t *get_my_v3_legacy_cert(void); crypto_pk_t *get_my_v3_legacy_signing_key(void); void dup_onion_keys(crypto_pk_t **key, crypto_pk_t **last); +void expire_old_onion_keys(void); void rotate_onion_key(void); crypto_pk_t *init_key_from_file(const char *fname, int generate, int severity, int log_greeting);
tor-commits@lists.torproject.org