diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-03-17 11:16:24 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-03-17 11:16:24 -0400 |
commit | 58680d04299ab69ea99ee86c5f1a194f44fc1d12 (patch) | |
tree | 814c4ebcbd458585695ec1d3e66c7c78a93e77ff | |
parent | 6657fe1e54743e90e33c453de154343fbf94bad4 (diff) | |
parent | 946ccf3e4de883b98aa62666b8a5bdc3eb535447 (diff) | |
download | tor-58680d04299ab69ea99ee86c5f1a194f44fc1d12.tar.gz tor-58680d04299ab69ea99ee86c5f1a194f44fc1d12.zip |
Merge branch 'ahf_bugs_21641_squashed'
-rw-r--r-- | changes/bug21641 | 5 | ||||
-rw-r--r-- | src/or/config.c | 2 | ||||
-rw-r--r-- | src/or/main.c | 39 | ||||
-rw-r--r-- | src/or/or.h | 23 | ||||
-rw-r--r-- | src/or/router.c | 90 | ||||
-rw-r--r-- | src/or/router.h | 3 | ||||
-rw-r--r-- | src/test/test_dir.c | 2 |
7 files changed, 152 insertions, 12 deletions
diff --git a/changes/bug21641 b/changes/bug21641 new file mode 100644 index 0000000000..96fdf5fe22 --- /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/config.c b/src/or/config.c index 8277d0b337..7ae40053ee 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -2815,7 +2815,7 @@ compute_publishserverdescriptor(or_options_t *options) #define MAX_PREDICTED_CIRCS_RELEVANCE (60*60) /** Highest allowable value for RendPostPeriod. */ -#define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2) +#define MAX_DIR_PERIOD ((7*24*60*60)/2) /** Lowest allowable value for MaxCircuitDirtiness; if this is too low, Tor * will generate too many circuits and potentially overload the network. */ diff --git a/src/or/main.c b/src/or/main.c index b9b6bca0e4..894fd054b9 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), @@ -1472,17 +1474,18 @@ run_scheduled_events(time_t now) pt_configure_remaining_proxies(); } -/* Periodic callback: Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion - * keys, shut down and restart all cpuworkers, and update our descriptor if - * necessary. +/* Periodic callback: rotate the onion keys after the period defined by the + * "onion-key-rotation-days" consensus parameter, shut down and restart all + * cpuworkers, and update our descriptor if necessary. */ static int rotate_onion_key_callback(time_t now, const or_options_t *options) { if (server_mode(options)) { - time_t rotation_time = get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME; + int onion_key_lifetime = get_onion_key_lifetime(); + time_t rotation_time = get_onion_key_set_at()+onion_key_lifetime; if (rotation_time > now) { - return safe_timer_diff(now, rotation_time); + return ONION_KEY_CONSENSUS_CHECK_INTERVAL; } log_info(LD_GENERAL,"Rotating onion key."); @@ -1493,11 +1496,35 @@ rotate_onion_key_callback(time_t now, const or_options_t *options) } if (advertised_server_mode() && !options->DisableNetwork) router_upload_dir_desc_to_dirservers(0); - return MIN_ONION_KEY_LIFETIME; + return ONION_KEY_CONSENSUS_CHECK_INTERVAL; } 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 ONION_KEY_CONSENSUS_CHECK_INTERVAL; + } + + log_info(LD_GENERAL, "Expiring old onion keys."); + expire_old_onion_keys(); + cpuworkers_rotate_keyinfo(); + return ONION_KEY_CONSENSUS_CHECK_INTERVAL; + } + + 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/or.h b/src/or/or.h index 476cc384b9..9b0ccaffa0 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -147,8 +147,27 @@ /** Maximum size of a single extrainfo document, as above. */ #define MAX_EXTRAINFO_UPLOAD_SIZE 50000 -/** How often do we rotate onion keys? */ -#define MIN_ONION_KEY_LIFETIME (7*24*60*60) +/** Minimum lifetime for an onion key in days. */ +#define MIN_ONION_KEY_LIFETIME_DAYS (1) + +/** Maximum lifetime for an onion key in days. */ +#define MAX_ONION_KEY_LIFETIME_DAYS (90) + +/** Default lifetime for an onion key in days. */ +#define DEFAULT_ONION_KEY_LIFETIME_DAYS (28) + +/** Minimum grace period for acceptance of an onion key in days. + * The maximum value is defined in proposal #274 as being the current network + * consensus parameter for "onion-key-rotation-days". */ +#define MIN_ONION_KEY_GRACE_PERIOD_DAYS (1) + +/** Default grace period for acceptance of an onion key in days. */ +#define DEFAULT_ONION_KEY_GRACE_PERIOD_DAYS (7) + +/** How often we should check the network consensus if it is time to rotate or + * expire onion keys. */ +#define ONION_KEY_CONSENSUS_CHECK_INTERVAL (60*60) + /** How often do we rotate TLS contexts? */ #define MAX_SSL_KEY_LIFETIME_INTERNAL (2*60*60) diff --git a/src/or/router.c b/src/or/router.c index 180bd499b0..7fb49e8eba 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 * @@ -683,6 +728,47 @@ v3_authority_check_key_expiry(void) last_warned = now; } +/** Get the lifetime of an onion key in days. This value is defined by the + * network consesus parameter "onion-key-rotation-days". Always returns a value + * between <b>MIN_ONION_KEY_LIFETIME_DAYS</b> and + * <b>MAX_ONION_KEY_LIFETIME_DAYS</b>. + */ +static int +get_onion_key_rotation_days_(void) +{ + return networkstatus_get_param(NULL, + "onion-key-rotation-days", + DEFAULT_ONION_KEY_LIFETIME_DAYS, + MIN_ONION_KEY_LIFETIME_DAYS, + MAX_ONION_KEY_LIFETIME_DAYS); +} + +/** Get the current lifetime of an onion key in seconds. This value is defined + * by the network consesus parameter "onion-key-rotation-days", but the value + * is converted to seconds. + */ +int +get_onion_key_lifetime(void) +{ + return get_onion_key_rotation_days_()*24*60*60; +} + +/** Get the grace period of an onion key in seconds. This value is defined by + * the network consesus parameter "onion-key-grace-period-days", but the value + * is converted to seconds. + */ +int +get_onion_key_grace_period(void) +{ + int grace_period; + grace_period = networkstatus_get_param(NULL, + "onion-key-grace-period-days", + DEFAULT_ONION_KEY_GRACE_PERIOD_DAYS, + MIN_ONION_KEY_GRACE_PERIOD_DAYS, + get_onion_key_rotation_days_()); + return grace_period*24*60*60; +} + /** Set up Tor's TLS contexts, based on our configuration and keys. Return 0 * on success, and -1 on failure. */ int @@ -928,7 +1014,7 @@ init_keys(void) /* We have no LastRotatedOnionKey set; either we just created the key * or it's a holdover from 0.1.2.4-alpha-dev or earlier. In either case, * start the clock ticking now so that we will eventually rotate it even - * if we don't stay up for a full MIN_ONION_KEY_LIFETIME. */ + * if we don't stay up for the full lifetime of an onion key. */ state->LastRotatedOnionKey = onionkey_set_at = now; or_state_mark_dirty(state, options->AvoidDiskWrites ? time(NULL)+3600 : 0); @@ -2760,7 +2846,7 @@ router_dump_router_to_string(routerinfo_t *router, make_ntor_onion_key_crosscert(ntor_keypair, &router->cache_info.signing_key_cert->signing_key, router->cache_info.published_on, - MIN_ONION_KEY_LIFETIME, &sign); + get_onion_key_lifetime(), &sign); if (!cert) { log_warn(LD_BUG,"make_ntor_onion_key_crosscert failed!"); goto err; diff --git a/src/or/router.h b/src/or/router.h index 0c5425501e..9c5def5218 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -27,10 +27,13 @@ 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); void v3_authority_check_key_expiry(void); +int get_onion_key_lifetime(void); +int get_onion_key_grace_period(void); di_digest256_map_t *construct_ntor_key_map(void); void ntor_key_map_free(di_digest256_map_t *map); diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 2bc327a2dd..e0c92a74c5 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -329,7 +329,7 @@ test_dir_formats(void *arg) ntor_cc = make_ntor_onion_key_crosscert(&r2_onion_keypair, &kp1.pubkey, r2->cache_info.published_on, - MIN_ONION_KEY_LIFETIME, + get_onion_key_lifetime(), &ntor_cc_sign); tt_assert(ntor_cc); base64_encode(cert_buf, sizeof(cert_buf), |