From 599aeef9bc9e707ec7146da79b2018bf2f2924b3 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Sat, 9 Mar 2013 16:42:35 -0500 Subject: [PATCH 1/3] parameterize SSLKeyLifetime no actual changes in behavior yet --- src/or/config.c | 1 + src/or/or.h | 5 +++-- src/or/router.c | 7 +++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/or/config.c b/src/or/config.c index dad571967e..b7613bdf92 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -380,6 +380,7 @@ static config_var_t option_vars_[] = { V(SocksPolicy, LINELIST, NULL), VPORT(SocksPort, LINELIST, NULL), V(SocksTimeout, INTERVAL, "2 minutes"), + V(SSLKeyLifetime, INTERVAL, "365 days"), OBSOLETE("StatusFetchPeriod"), V(StrictNodes, BOOL, "0"), OBSOLETE("SysLog"), diff --git a/src/or/or.h b/src/or/or.h index c2cd8a6cae..a71468c1c6 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -177,8 +177,6 @@ #define MIN_ONION_KEY_LIFETIME (7*24*60*60) /** How often do we rotate TLS contexts? */ #define MAX_SSL_KEY_LIFETIME_INTERNAL (2*60*60) -/** What expiry time shall we place on our SSL certs? */ -#define MAX_SSL_KEY_LIFETIME_ADVERTISED (365*24*60*60) /** How old do we allow a router to get before removing it * from the router list? In seconds. */ @@ -4010,6 +4008,9 @@ typedef struct { */ int DisableV2DirectoryInfo_; + /** What expiry time shall we place on our SSL certs? */ + int SSLKeyLifetime; + } or_options_t; /** Persistent state for an onion router, as saved to disk. */ diff --git a/src/or/router.c b/src/or/router.c index 95aa70a9c4..c9c35f6132 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -650,6 +650,7 @@ router_initialize_tls_context(void) { unsigned int flags = 0; const or_options_t *options = get_options(); + int lifetime = options->SSLKeyLifetime; if (public_server_mode(options)) flags |= TOR_TLS_CTX_IS_PUBLIC_SERVER; if (options->TLSECGroup) { @@ -659,11 +660,13 @@ router_initialize_tls_context(void) flags |= TOR_TLS_CTX_USE_ECDHE_P224; } + /* It's ok to pass lifetime in as an unsigned int, since + * config_parse_interval() checked it. */ return tor_tls_context_init(flags, get_tlsclient_identity_key(), - server_mode(get_options()) ? + server_mode(options) ? get_server_identity_key() : NULL, - MAX_SSL_KEY_LIFETIME_ADVERTISED); + (unsigned int)lifetime); } /** Initialize all OR private keys, and the TLS context, as necessary. From edd6f02273c58bfe39a978dd5c7b8765aae0b886 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Sat, 9 Mar 2013 17:16:11 -0500 Subject: [PATCH 2/3] randomize SSLKeyLifetime by default resolves ticket 8443. --- changes/ticket8443 | 4 ++++ doc/tor.1.txt | 9 +++++++-- src/or/config.c | 2 +- src/or/or.h | 3 ++- src/or/router.c | 4 ++++ 5 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 changes/ticket8443 diff --git a/changes/ticket8443 b/changes/ticket8443 new file mode 100644 index 0000000000..ca6fb2f471 --- /dev/null +++ b/changes/ticket8443 @@ -0,0 +1,4 @@ + o Minor features: + - Randomize the lifetime of our SSL link certificate, so censors can't + use the static value for filtering Tor flows. Resolves ticket 8443; + related to ticket 4014 which was included in 0.2.2.33. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 75bca79378..505a0834b5 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1500,8 +1500,13 @@ is non-zero): **ShutdownWaitLength** __NUM__:: When we get a SIGINT and we're a server, we begin shutting down: we close listeners and start refusing new circuits. After **NUM** - seconds, we exit. If we get a second SIGINT, we exit immedi- - ately. (Default: 30 seconds) + seconds, we exit. If we get a second SIGINT, we exit immediately. + (Default: 30 seconds) + +**SSLKeyLifetime** __N__ **minutes**|**hours**|**days**|**weeks**:: + When creating a link certificate for our outermost SSL handshake, + set its lifetime to this amount of time. If set to 0, Tor will choose + some reasonable random defaults. (Default: 0) **HeartbeatPeriod** __N__ **minutes**|**hours**|**days**|**weeks**:: Log a heartbeat message every **HeartbeatPeriod** seconds. This is diff --git a/src/or/config.c b/src/or/config.c index b7613bdf92..15138f9d7b 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -380,7 +380,7 @@ static config_var_t option_vars_[] = { V(SocksPolicy, LINELIST, NULL), VPORT(SocksPort, LINELIST, NULL), V(SocksTimeout, INTERVAL, "2 minutes"), - V(SSLKeyLifetime, INTERVAL, "365 days"), + V(SSLKeyLifetime, INTERVAL, "0"), OBSOLETE("StatusFetchPeriod"), V(StrictNodes, BOOL, "0"), OBSOLETE("SysLog"), diff --git a/src/or/or.h b/src/or/or.h index a71468c1c6..c7d259853b 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4008,7 +4008,8 @@ typedef struct { */ int DisableV2DirectoryInfo_; - /** What expiry time shall we place on our SSL certs? */ + /** What expiry time shall we place on our SSL certs? "0" means we + * should guess a suitable value. */ int SSLKeyLifetime; } or_options_t; diff --git a/src/or/router.c b/src/or/router.c index c9c35f6132..211366351b 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -659,6 +659,10 @@ router_initialize_tls_context(void) else if (!strcasecmp(options->TLSECGroup, "P224")) flags |= TOR_TLS_CTX_USE_ECDHE_P224; } + if (!lifetime) { /* we should guess a good ssl cert lifetime */ + /* choose between 1 and 365 days */ + lifetime = 1*24*3600 + crypto_rand_int(364*24*3600); + } /* It's ok to pass lifetime in as an unsigned int, since * config_parse_interval() checked it. */ From 0196647970a91d2bdb052f38b3749dd0e99348e4 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Sun, 10 Mar 2013 16:28:28 -0400 Subject: [PATCH 3/3] start part-way through the ssl cert lifetime also, snap the start time and end time to a day boundary, since most certs in the wild seem to do this. --- src/common/tortls.c | 16 +++++++++++----- src/or/router.c | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/common/tortls.c b/src/common/tortls.c index 94cedba24b..a08910b3a2 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -234,7 +234,7 @@ static X509* tor_tls_create_certificate(crypto_pk_t *rsa, crypto_pk_t *rsa_sign, const char *cname, const char *cname_sign, - unsigned int lifetime); + unsigned int cert_lifetime); static int tor_tls_context_init_one(tor_tls_context_t **ppcontext, crypto_pk_t *identity, @@ -608,9 +608,10 @@ tor_x509_name_new(const char *cname) /** Generate and sign an X509 certificate with the public key rsa, * signed by the private key rsa_sign. The commonName of the * certificate will be cname; the commonName of the issuer will be - * cname_sign. The cert will be valid for cert_lifetime seconds - * starting from now. Return a certificate on success, NULL on - * failure. + * cname_sign. The cert will be valid for cert_lifetime + * seconds, starting from some time in the past. + * + * Return a certificate on success, NULL on failure. */ static X509 * tor_tls_create_certificate(crypto_pk_t *rsa, @@ -632,7 +633,12 @@ tor_tls_create_certificate(crypto_pk_t *rsa, tor_tls_init(); - start_time = time(NULL); + /* Make sure we're part-way through the certificate lifetime, rather + * than having it start right now. Don't choose quite uniformly, since + * then we might pick a time where we're about to expire. Lastly, be + * sure to start on a day boundary. */ + start_time = time(NULL) - crypto_rand_int(cert_lifetime) + 2*24*3600; + start_time -= start_time % (24*3600); tor_assert(rsa); tor_assert(cname); diff --git a/src/or/router.c b/src/or/router.c index 211366351b..422fe5db2e 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -660,8 +660,18 @@ router_initialize_tls_context(void) flags |= TOR_TLS_CTX_USE_ECDHE_P224; } if (!lifetime) { /* we should guess a good ssl cert lifetime */ - /* choose between 1 and 365 days */ - lifetime = 1*24*3600 + crypto_rand_int(364*24*3600); + + /* choose between 5 and 365 days, and round to the day */ + lifetime = 5*24*3600 + crypto_rand_int(361*24*3600); + lifetime -= lifetime % (24*3600); + + if (crypto_rand_int(2)) { + /* Half the time we expire at midnight, and half the time we expire + * one second before midnight. (Some CAs wobble their expiry times a + * bit in practice, perhaps to reduce collision attacks; see ticket + * 8443 for details about observed certs in the wild.) */ + lifetime--; + } } /* It's ok to pass lifetime in as an unsigned int, since