Browse Source

Merge remote-tracking branch 'asn-mytor/bug4548_take2'

Nick Mathewson 12 years ago
parent
commit
da6c136817
11 changed files with 391 additions and 49 deletions
  1. 6 0
      changes/bug4548
  2. 6 0
      doc/tor.1.txt
  3. 280 23
      src/common/crypto.c
  4. 2 0
      src/common/crypto.h
  5. 28 14
      src/common/util.c
  6. 3 0
      src/common/util.h
  7. 49 0
      src/or/config.c
  8. 1 4
      src/or/main.c
  9. 2 0
      src/or/or.h
  10. 13 8
      src/or/router.c
  11. 1 0
      src/or/router.h

+ 6 - 0
changes/bug4548

@@ -0,0 +1,6 @@
+  o Privacy/anonymity features (bridge detection):
+    - Introduce a new config option 'DynamicDHGroups', enabled by
+      default, which provides each bridge with a unique prime DH
+      modulus to be used during SSL handshakes. This option attempts
+      to help against censors using the Apache DH modulus as a static
+      identifier for bridges.

+ 6 - 0
doc/tor.1.txt

@@ -245,6 +245,12 @@ Other options can be specified either on the command-line (--option
     distinguishable from other users, because you won't believe the same
     authorities they do.
 
+**DynamicPrimes** **0**|**1**::
+    If this option is set to 1, use a dynamic Diffie-Hellman prime
+    modulus instead of using the modulus of Apache's mod_ssl. This
+    option might help circumvent censorship based on static
+    Diffie-Hellman parameters. (Default: 1).
+
 **AlternateDirAuthority** [__nickname__] [**flags**] __address__:__port__ __fingerprint__ +
 
 **AlternateHSAuthority** [__nickname__] [**flags**] __address__:__port__ __fingerprint__ +

+ 280 - 23
src/common/crypto.c

@@ -1812,6 +1812,9 @@ crypto_hmac_sha256(char *hmac_out,
 
 /* DH */
 
+/** Our DH 'g' parameter */
+#define DH_GENERATOR 2
+
 /** Shared P parameter for our circuit-crypto DH key exchanges. */
 static BIGNUM *dh_param_p = NULL;
 /** Shared P parameter for our TLS DH key exchanges. */
@@ -1819,49 +1822,303 @@ static BIGNUM *dh_param_p_tls = NULL;
 /** Shared G parameter for our DH key exchanges. */
 static BIGNUM *dh_param_g = NULL;
 
+/** Generate and return a reasonable and safe DH parameter p. */
+static BIGNUM *
+crypto_generate_dynamic_dh_modulus(void)
+{
+  BIGNUM *dynamic_dh_modulus;
+  DH *dh_parameters;
+  int r, dh_codes;
+  char *s;
+
+  dynamic_dh_modulus = BN_new();
+  tor_assert(dynamic_dh_modulus);
+
+  dh_parameters = DH_generate_parameters(DH_BYTES*8, DH_GENERATOR, NULL, NULL);
+  tor_assert(dh_parameters);
+
+  r = DH_check(dh_parameters, &dh_codes);
+  tor_assert(r && !dh_codes);
+
+  BN_copy(dynamic_dh_modulus, dh_parameters->p);
+  tor_assert(dynamic_dh_modulus);
+
+  DH_free(dh_parameters);
+
+  { /* log the dynamic DH modulus: */
+    s = BN_bn2hex(dynamic_dh_modulus);
+    tor_assert(s);
+    log_info(LD_OR, "Dynamic DH modulus generated: [%s]", s);
+    OPENSSL_free(s);
+  }
+
+  return dynamic_dh_modulus;
+}
+
+/** Store our dynamic DH modulus (and its group parameters) to
+    <b>fname</b> for future use. */
+static int
+crypto_store_dynamic_dh_modulus(const char *fname)
+{
+  int len, new_len;
+  DH *dh = NULL;
+  unsigned char *dh_string_repr = NULL, *cp = NULL;
+  char *base64_encoded_dh = NULL;
+  int retval = -1;
+
+  tor_assert(fname);
+
+  if (!dh_param_p_tls) {
+    log_info(LD_CRYPTO, "Tried to store a DH modulus that does not exist.");
+    goto done;
+  }
+
+  if (!(dh = DH_new()))
+    goto done;
+  if (!(dh->p = BN_dup(dh_param_p_tls)))
+    goto done;
+  if (!(dh->g = BN_new()))
+    goto done;
+  if (!BN_set_word(dh->g, DH_GENERATOR))
+    goto done;
+
+  len = i2d_DHparams(dh, NULL);
+  if (len < 0) {
+    log_warn(LD_CRYPTO, "Error occured while DER encoding DH modulus (1).");
+    goto done;
+  }
+
+  cp = dh_string_repr = tor_malloc_zero(len+1);
+  len = i2d_DHparams(dh, &cp);
+  if ((len < 0) || ((cp - dh_string_repr) != len)) {
+    log_warn(LD_CRYPTO, "Error occured while DER encoding DH modulus (2).");
+    goto done;
+  }
+
+  base64_encoded_dh = tor_malloc_zero(len * 2); /* should be enough */
+  new_len = base64_encode(base64_encoded_dh, len * 2,
+                          (char *)dh_string_repr, len);
+  if (new_len < 0) {
+    log_warn(LD_CRYPTO, "Error occured while base64-encoding DH modulus.");
+    goto done;
+  }
+
+  if (write_bytes_to_new_file(fname, base64_encoded_dh, new_len, 0) < 0) {
+    log_info(LD_CRYPTO, "'%s' was already occupied.", fname);
+    goto done;
+  }
+
+  retval = 0;
+
+ done:
+  if (dh)
+    DH_free(dh);
+  tor_free(dh_string_repr);
+  tor_free(base64_encoded_dh);
+
+  return retval;
+}
+
+/** Return the dynamic DH modulus stored in <b>fname</b>. If there is no
+    dynamic DH modulus stored in <b>fname</b>, return NULL. */
+static BIGNUM *
+crypto_get_stored_dynamic_dh_modulus(const char *fname)
+{
+  int retval;
+  char *contents = NULL;
+  int dh_codes;
+  char *fname_new = NULL;
+  DH *stored_dh = NULL;
+  BIGNUM *dynamic_dh_modulus = NULL;
+  int length = 0;
+  unsigned char *base64_decoded_dh = NULL;
+  const unsigned char *cp = NULL;
+
+  tor_assert(fname);
+
+  contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL);
+  if (!contents) {
+    log_info(LD_CRYPTO, "Could not open file '%s'", fname);
+    goto done; /*usually means that ENOENT. don't try to move file to broken.*/
+  }
+
+  /* 'fname' contains the DH parameters stored in base64-ed DER
+     format. We are only interested in the DH modulus. */
+
+  cp = base64_decoded_dh = tor_malloc_zero(strlen(contents));
+  length = base64_decode((char *)base64_decoded_dh, strlen(contents),
+                         contents, strlen(contents));
+  if (length < 0) {
+    log_warn(LD_CRYPTO, "Stored dynamic DH modulus seems corrupted (base64).");
+    goto err;
+  }
+
+  stored_dh = d2i_DHparams(NULL, &cp, length);
+  if ((!stored_dh) || (cp - base64_decoded_dh != length)) {
+    log_warn(LD_CRYPTO, "Stored dynamic DH modulus seems corrupted (d2i).");
+    goto err;
+  }
+
+  { /* check the cryptographic qualities of the stored dynamic DH modulus: */
+    retval = DH_check(stored_dh, &dh_codes);
+    if (!retval || dh_codes) {
+      log_warn(LD_CRYPTO, "Stored dynamic DH modulus is not a safe prime.");
+      goto err;
+    }
+
+    retval = DH_size(stored_dh);
+    if (retval < DH_BYTES) {
+      log_warn(LD_CRYPTO, "Stored dynamic DH modulus is smaller "
+               "than '%d' bits.", DH_BYTES*8);
+      goto err;
+    }
+
+    if (!BN_is_word(stored_dh->g, 2)) {
+      log_warn(LD_CRYPTO, "Stored dynamic DH parameters do not use '2' "
+               "as the group generator.");
+      goto err;
+    }
+  }
+
+  { /* log the dynamic DH modulus: */
+    char *s = BN_bn2hex(stored_dh->p);
+    tor_assert(s);
+    log_info(LD_OR, "Found stored dynamic DH modulus: [%s]", s);
+    OPENSSL_free(s);
+  }
+
+  goto done;
+
+ err:
+
+  { /* move broken prime to $filename.broken */
+    fname_new = tor_malloc(strlen(fname) + 8);
+
+    /* no can do if these functions return error */
+    strlcpy(fname_new, fname, strlen(fname) + 8);
+    strlcat(fname_new, ".broken", strlen(fname) + 8);
+
+    log_warn(LD_CRYPTO, "Moving broken dynamic DH prime to '%s'.", fname_new);
+
+    if (replace_file(fname, fname_new))
+      log_notice(LD_CRYPTO, "Error while moving '%s' to '%s'.",
+                 fname, fname_new);
+
+    tor_free(fname_new);
+  }
+
+  if (stored_dh) {
+    DH_free(stored_dh);
+    stored_dh = NULL;
+  }
+
+ done:
+  tor_free(contents);
+  tor_free(base64_decoded_dh);
+
+  if (stored_dh) {
+    dynamic_dh_modulus = BN_dup(stored_dh->p);
+    DH_free(stored_dh);
+  }
+
+  return dynamic_dh_modulus;
+}
+
+/** Set the global TLS Diffie-Hellman modulus.
+ * If <b>dynamic_dh_modulus_fname</b> is set, try to read a dynamic DH modulus
+ * off it and use it as the DH modulus. If that's not possible,
+ * generate a new dynamic DH modulus.
+ * If <b>dynamic_dh_modulus_fname</b> is NULL, use the Apache mod_ssl DH
+ * modulus. */
+void
+crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname)
+{
+  BIGNUM *tls_prime = NULL;
+  int store_dh_prime_afterwards = 0;
+  int r;
+
+  /* If the space is occupied, free the previous TLS DH prime */
+  if (dh_param_p_tls) {
+    BN_free(dh_param_p_tls);
+    dh_param_p_tls = NULL;
+  }
+
+  if (dynamic_dh_modulus_fname) { /* use dynamic DH modulus: */
+    log_info(LD_OR, "Using stored dynamic DH modulus.");
+    tls_prime = crypto_get_stored_dynamic_dh_modulus(dynamic_dh_modulus_fname);
+
+    if (!tls_prime) {
+      log_notice(LD_OR, "Generating fresh dynamic DH modulus. "
+                 "This might take a while...");
+      tls_prime = crypto_generate_dynamic_dh_modulus();
+
+      store_dh_prime_afterwards++;
+    }
+  } else { /* use the static DH prime modulus used by Apache in mod_ssl: */
+    tls_prime = BN_new();
+    tor_assert(tls_prime);
+
+    /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see
+     * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this
+     * prime.
+     */
+    r =BN_hex2bn(&tls_prime,
+                 "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
+                 "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
+                 "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
+                 "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
+                 "B0E7393E0F24218EB3");
+    tor_assert(r);
+  }
+
+  tor_assert(tls_prime);
+
+  dh_param_p_tls = tls_prime;
+
+  if (store_dh_prime_afterwards)
+    /* save the new dynamic DH modulus to disk. */
+    if (crypto_store_dynamic_dh_modulus(dynamic_dh_modulus_fname)) {
+      log_notice(LD_CRYPTO, "Failed while storing dynamic DH modulus. "
+                 "Make sure your data directory is sane.");
+    }
+}
+
 /** Initialize dh_param_p and dh_param_g if they are not already
  * set. */
 static void
 init_dh_param(void)
 {
-  BIGNUM *p, *p2, *g;
+  BIGNUM *circuit_dh_prime, *generator;
   int r;
-  if (dh_param_p && dh_param_g && dh_param_p_tls)
+  if (dh_param_p && dh_param_g)
     return;
 
-  p = BN_new();
-  p2 = BN_new();
-  g = BN_new();
-  tor_assert(p);
-  tor_assert(p2);
-  tor_assert(g);
+  circuit_dh_prime = BN_new();
+  generator = BN_new();
+  tor_assert(circuit_dh_prime && generator);
+
+  /* Set our generator for all DH parameters */
+  r = BN_set_word(generator, DH_GENERATOR);
+  tor_assert(r);
 
   /* This is from rfc2409, section 6.2.  It's a safe prime, and
      supposedly it equals:
         2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
   */
-  r = BN_hex2bn(&p,
+  r = BN_hex2bn(&circuit_dh_prime,
                 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
                 "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
                 "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
                 "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
                 "49286651ECE65381FFFFFFFFFFFFFFFF");
   tor_assert(r);
-  /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see
-   * modules/ssl/ssl_engine_dh.c */
-  r = BN_hex2bn(&p2,
-                  "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98"
-                "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A"
-                "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7"
-                "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68"
-                "B0E7393E0F24218EB3");
-  tor_assert(r);
 
-  r = BN_set_word(g, 2);
-  tor_assert(r);
-  dh_param_p = p;
-  dh_param_p_tls = p2;
-  dh_param_g = g;
+  /* Set the new values as the global DH parameters. */
+  dh_param_p = circuit_dh_prime;
+  dh_param_g = generator;
+
+  /* Should be already set by config.c. */
+  tor_assert(dh_param_p_tls);
 }
 
 /** Number of bits to use when choosing the x or y value in a Diffie-Hellman

+ 2 - 0
src/common/crypto.h

@@ -91,6 +91,8 @@ int crypto_global_cleanup(void);
 crypto_pk_env_t *crypto_new_pk_env(void);
 void crypto_free_pk_env(crypto_pk_env_t *env);
 
+void crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname);
+
 /* convenience function: wraps crypto_create_crypto_env, set_key, and init. */
 crypto_cipher_env_t *crypto_create_init_cipher(const char *key,
                                                int encrypt_mode);

+ 28 - 14
src/common/util.c

@@ -2137,13 +2137,12 @@ write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin)
   return write_chunks_to_file_impl(fname, chunks, flags);
 }
 
-/** As write_str_to_file, but does not assume a NUL-terminated
- * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */
-int
-write_bytes_to_file(const char *fname, const char *str, size_t len,
-                    int bin)
+/** Write <b>len</b> bytes, starting at <b>str</b>, to <b>fname</b>
+    using the open() flags passed in <b>flags</b>. */
+static int
+write_bytes_to_file_impl(const char *fname, const char *str, size_t len,
+                         int flags)
 {
-  int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
   int r;
   sized_chunk_t c = { str, len };
   smartlist_t *chunks = smartlist_create();
@@ -2153,20 +2152,35 @@ write_bytes_to_file(const char *fname, const char *str, size_t len,
   return r;
 }
 
+/** As write_str_to_file, but does not assume a NUL-terminated
+ * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */
+int
+write_bytes_to_file(const char *fname, const char *str, size_t len,
+                    int bin)
+{
+  return write_bytes_to_file_impl(fname, str, len,
+                                  OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT));
+}
+
 /** As write_bytes_to_file, but if the file already exists, append the bytes
  * to the end of the file instead of overwriting it. */
 int
 append_bytes_to_file(const char *fname, const char *str, size_t len,
                      int bin)
 {
-  int flags = OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT);
-  int r;
-  sized_chunk_t c = { str, len };
-  smartlist_t *chunks = smartlist_create();
-  smartlist_add(chunks, &c);
-  r = write_chunks_to_file_impl(fname, chunks, flags);
-  smartlist_free(chunks);
-  return r;
+  return write_bytes_to_file_impl(fname, str, len,
+                                  OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT));
+}
+
+/** Like write_str_to_file(), but also return -1 if there was a file
+    already residing in <b>fname</b>. */
+int
+write_bytes_to_new_file(const char *fname, const char *str, size_t len,
+                        int bin)
+{
+  return write_bytes_to_file_impl(fname, str, len,
+                                  OPEN_FLAGS_DONT_REPLACE|
+                                  (bin?O_BINARY:O_TEXT));
 }
 
 /** Read the contents of <b>filename</b> into a newly allocated

+ 3 - 0
src/common/util.h

@@ -311,6 +311,7 @@ int check_private_dir(const char *dirname, cpd_check_t check,
                       const char *effective_user);
 #define OPEN_FLAGS_REPLACE (O_WRONLY|O_CREAT|O_TRUNC)
 #define OPEN_FLAGS_APPEND (O_WRONLY|O_CREAT|O_APPEND)
+#define OPEN_FLAGS_DONT_REPLACE (O_CREAT|O_EXCL|O_APPEND|O_WRONLY)
 typedef struct open_file_t open_file_t;
 int start_writing_to_file(const char *fname, int open_flags, int mode,
                           open_file_t **data_out);
@@ -332,6 +333,8 @@ int write_chunks_to_file(const char *fname, const struct smartlist_t *chunks,
                          int bin);
 int append_bytes_to_file(const char *fname, const char *str, size_t len,
                          int bin);
+int write_bytes_to_new_file(const char *fname, const char *str, size_t len,
+                            int bin);
 
 /** Flag for read_file_to_str: open the file in binary mode. */
 #define RFTS_BIN            1

+ 49 - 0
src/or/config.c

@@ -249,6 +249,7 @@ static config_var_t _option_vars[] = {
   V(DisableAllSwap,              BOOL,     "0"),
   V(DisableDebuggerAttachment,   BOOL,     "1"),
   V(DisableIOCP,                 BOOL,     "1"),
+  V(DynamicDHGroups,             BOOL,     "1"),
   V(DNSPort,                     LINELIST, NULL),
   V(DNSListenAddress,            LINELIST, NULL),
   V(DownloadExtraInfo,           BOOL,     "0"),
@@ -1285,6 +1286,24 @@ get_effective_bwburst(const or_options_t *options)
   return (uint32_t)bw;
 }
 
+/** Return True if any changes from <b>old_options</b> to
+ * <b>new_options</b> needs us to refresh our TLS context. */
+static int
+options_transition_requires_fresh_tls_context(const or_options_t *old_options,
+                                              const or_options_t *new_options)
+{
+  tor_assert(new_options);
+
+  if (!old_options)
+    return 0;
+
+  if ((old_options->DynamicDHGroups != new_options->DynamicDHGroups)) {
+    return 1;
+  }
+
+  return 0;
+}
+
 /** Fetch the active option list, and take actions based on it. All of the
  * things we do should survive being done repeatedly.  If present,
  * <b>old_options</b> contains the previous value of the options.
@@ -1388,6 +1407,29 @@ options_act(const or_options_t *old_options)
     finish_daemon(options->DataDirectory);
   }
 
+  /* If needed, generate a new TLS DH prime according to the current torrc. */
+  if (server_mode(options)) {
+    if (!old_options) {
+      if (options->DynamicDHGroups) {
+        char *fname = get_datadir_fname2("keys", "dynamic_dh_params");
+        crypto_set_tls_dh_prime(fname);
+        tor_free(fname);
+      } else {
+        crypto_set_tls_dh_prime(NULL);
+      }
+    } else {
+      if (options->DynamicDHGroups && !old_options->DynamicDHGroups) {
+        char *fname = get_datadir_fname2("keys", "dynamic_dh_params");
+        crypto_set_tls_dh_prime(fname);
+        tor_free(fname);
+      } else if (!options->DynamicDHGroups && old_options->DynamicDHGroups) {
+        crypto_set_tls_dh_prime(NULL);
+      }
+    }
+  } else { /* clients don't need a dynamic DH prime. */
+    crypto_set_tls_dh_prime(NULL);
+  }
+
   /* We want to reinit keys as needed before we do much of anything else:
      keys are important, and other things can depend on them. */
   if (transition_affects_workers ||
@@ -1397,6 +1439,13 @@ options_act(const or_options_t *old_options)
       log_warn(LD_BUG,"Error initializing keys; exiting");
       return -1;
     }
+  } else if (old_options &&
+             options_transition_requires_fresh_tls_context(old_options,
+                                                           options)) {
+    if (router_initialize_tls_context() < 0) {
+      log_warn(LD_BUG,"Error initializing TLS context.");
+      return -1;
+    }
   }
 
   /* Write our PID to the PID file. If we do not have write permissions we

+ 1 - 4
src/or/main.c

@@ -1189,10 +1189,7 @@ run_scheduled_events(time_t now)
     last_rotated_x509_certificate = now;
   if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME_INTERNAL < now) {
     log_info(LD_GENERAL,"Rotating tls context.");
-    if (tor_tls_context_init(public_server_mode(options),
-                             get_tlsclient_identity_key(),
-                             is_server ? get_server_identity_key() : NULL,
-                             MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) {
+    if (router_initialize_tls_context() < 0) {
       log_warn(LD_BUG, "Error reinitializing TLS context");
       /* XXX is it a bug here, that we just keep going? -RD */
     }

+ 2 - 0
src/or/or.h

@@ -2889,6 +2889,8 @@ typedef struct {
   char *Address; /**< OR only: configured address for this onion router. */
   char *PidFile; /**< Where to store PID of Tor process. */
 
+  int DynamicDHGroups; /**< Dynamic generation of prime moduli for use in DH.*/
+
   routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
                            * country codes and IP address patterns of ORs to
                            * consider as exits. */

+ 13 - 8
src/or/router.c

@@ -484,6 +484,16 @@ v3_authority_check_key_expiry(void)
   last_warned = now;
 }
 
+int
+router_initialize_tls_context(void)
+{
+  return tor_tls_context_init(public_server_mode(get_options()),
+                              get_tlsclient_identity_key(),
+                              server_mode(get_options()) ?
+                              get_server_identity_key() : NULL,
+                              MAX_SSL_KEY_LIFETIME_ADVERTISED);
+}
+
 /** Initialize all OR private keys, and the TLS context, as necessary.
  * On OPs, this only initializes the tls context. Return 0 on success,
  * or -1 if Tor should die.
@@ -530,10 +540,7 @@ init_keys(void)
     }
     set_client_identity_key(prkey);
     /* Create a TLS context. */
-    if (tor_tls_context_init(0,
-                             get_tlsclient_identity_key(),
-                             NULL,
-                             MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) {
+    if (router_initialize_tls_context() < 0) {
       log_err(LD_GENERAL,"Error creating TLS context for Tor client.");
       return -1;
     }
@@ -626,13 +633,11 @@ init_keys(void)
   tor_free(keydir);
 
   /* 3. Initialize link key and TLS context. */
-  if (tor_tls_context_init(public_server_mode(options),
-                           get_tlsclient_identity_key(),
-                           get_server_identity_key(),
-                           MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) {
+  if (router_initialize_tls_context() < 0) {
     log_err(LD_GENERAL,"Error initializing TLS context");
     return -1;
   }
+
   /* 4. Build our router descriptor. */
   /* Must be called after keys are initialized. */
   mydesc = router_get_my_descriptor();

+ 1 - 0
src/or/router.h

@@ -30,6 +30,7 @@ crypto_pk_env_t *init_key_from_file(const char *fname, int generate,
                                     int severity);
 void v3_authority_check_key_expiry(void);
 
+int router_initialize_tls_context(void);
 int init_keys(void);
 
 int check_whether_orport_reachable(void);