[or-cvs] r14585: Backport: Implement a proposal to let a directory authority (in tor/branches/tor-0_2_0-patches: . contrib src/or src/win32)

nickm at seul.org nickm at seul.org
Mon May 12 02:14:16 UTC 2008


Author: nickm
Date: 2008-05-11 22:14:15 -0400 (Sun, 11 May 2008)
New Revision: 14585

Modified:
   tor/branches/tor-0_2_0-patches/
   tor/branches/tor-0_2_0-patches/ChangeLog
   tor/branches/tor-0_2_0-patches/configure.in
   tor/branches/tor-0_2_0-patches/contrib/tor-mingw.nsi.in
   tor/branches/tor-0_2_0-patches/src/or/config.c
   tor/branches/tor-0_2_0-patches/src/or/dirserv.c
   tor/branches/tor-0_2_0-patches/src/or/dirvote.c
   tor/branches/tor-0_2_0-patches/src/or/or.h
   tor/branches/tor-0_2_0-patches/src/or/router.c
   tor/branches/tor-0_2_0-patches/src/or/routerparse.c
   tor/branches/tor-0_2_0-patches/src/win32/orconfig.h
Log:
 r19691 at catbus:  nickm | 2008-05-11 22:13:41 -0400
 Backport: Implement a proposal to let a directory authority migrate its identity key without ceasing to sign consensuses.



Property changes on: tor/branches/tor-0_2_0-patches
___________________________________________________________________
 svk:merge ticket from /tor/020 [r19691] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/branches/tor-0_2_0-patches/ChangeLog
===================================================================
--- tor/branches/tor-0_2_0-patches/ChangeLog	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/ChangeLog	2008-05-12 02:14:15 UTC (rev 14585)
@@ -1,3 +1,9 @@
+Changes in version 0.2.0.26-rc - 2008-05-??
+  o Minor features:
+    - Add a new V3AuthUseLegacyKey option to make it easier for authorities
+      to change their identity keys if they have to.
+
+
 Changes in version 0.2.0.25-rc - 2008-04-23
   Tor 0.2.0.25-rc makes Tor work again on OS X and certain BSDs.
 

Modified: tor/branches/tor-0_2_0-patches/configure.in
===================================================================
--- tor/branches/tor-0_2_0-patches/configure.in	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/configure.in	2008-05-12 02:14:15 UTC (rev 14585)
@@ -5,7 +5,7 @@
 dnl See LICENSE for licensing information
 
 AC_INIT
-AM_INIT_AUTOMAKE(tor, 0.2.0.25-rc)
+AM_INIT_AUTOMAKE(tor, 0.2.0.25-rc-dev)
 AM_CONFIG_HEADER(orconfig.h)
 
 AC_CANONICAL_HOST

Modified: tor/branches/tor-0_2_0-patches/contrib/tor-mingw.nsi.in
===================================================================
--- tor/branches/tor-0_2_0-patches/contrib/tor-mingw.nsi.in	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/contrib/tor-mingw.nsi.in	2008-05-12 02:14:15 UTC (rev 14585)
@@ -9,7 +9,7 @@
 !include "FileFunc.nsh"
 !insertmacro GetParameters
   
-!define VERSION "0.2.0.25-rc"
+!define VERSION "0.2.0.25-rc-dev"
 !define INSTALLER "tor-${VERSION}-win32.exe"
 !define WEBSITE "https://www.torproject.org/"
 !define LICENSE "LICENSE"

Modified: tor/branches/tor-0_2_0-patches/src/or/config.c
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/config.c	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/src/or/config.c	2008-05-12 02:14:15 UTC (rev 14585)
@@ -301,6 +301,7 @@
   V(V3AuthVoteDelay,             INTERVAL, "5 minutes"),
   V(V3AuthDistDelay,             INTERVAL, "5 minutes"),
   V(V3AuthNIntervalsValid,       UINT,     "3"),
+  V(V3AuthUseLegacyKey,          BOOL,     "0"),
   VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
   V(VirtualAddrNetwork,          STRING,   "127.192.0.0/10"),
   V(WarnPlaintextPorts,          CSV,      "23,109,110,143"),

Modified: tor/branches/tor-0_2_0-patches/src/or/dirserv.c
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/dirserv.c	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/src/or/dirserv.c	2008-05-12 02:14:15 UTC (rev 14585)
@@ -2285,6 +2285,13 @@
   voter->or_port = options->ORPort;
   voter->contact = tor_strdup(contact);
   memcpy(voter->signing_key_digest, signing_key_digest, DIGEST_LEN);
+  if (options->V3AuthUseLegacyKey) {
+    authority_cert_t *c = get_my_v3_legacy_cert();
+    if (c) {
+      crypto_pk_get_digest(c->identity_key, voter->legacy_id_digest);
+    }
+  }
+
   v3_out->voters = smartlist_create();
   smartlist_add(v3_out->voters, voter);
   v3_out->cert = authority_cert_dup(cert);

Modified: tor/branches/tor-0_2_0-patches/src/or/dirvote.c
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/dirvote.c	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/src/or/dirvote.c	2008-05-12 02:14:15 UTC (rev 14585)
@@ -105,7 +105,7 @@
     tor_snprintf(status, len,
                  "network-status-version 3\n"
                  "vote-status vote\n"
-                 "consensus-methods 1 2\n"
+                 "consensus-methods 1 2 3\n"
                  "published %s\n"
                  "valid-after %s\n"
                  "fresh-until %s\n"
@@ -125,6 +125,14 @@
     tor_free(flags);
     outp = status + strlen(status);
     endp = status + len;
+
+    if (!tor_digest_is_zero(voter->legacy_id_digest)) {
+      char fpbuf[HEX_DIGEST_LEN+1];
+      base16_encode(fpbuf, sizeof(fpbuf), voter->legacy_id_digest, DIGEST_LEN);
+      tor_snprintf(outp, endp-outp, "legacy-dir-key %s\n", fpbuf);
+      outp += strlen(outp);
+    }
+
     tor_assert(outp + cert->cache_info.signed_descriptor_len < endp);
     memcpy(outp, cert->cache_info.signed_descriptor_body,
            cert->cache_info.signed_descriptor_len);
@@ -207,6 +215,12 @@
   return smartlist_get(vote->voters, 0);
 }
 
+typedef struct {
+  networkstatus_t *v;
+  const char *digest;
+  int is_legacy;
+} dir_src_ent_t;
+
 /** Helper for sorting networkstatus_t votes (not consensuses) by the
  * hash of their voters' identity digests. */
 static int
@@ -217,6 +231,19 @@
                 get_voter(b)->identity_digest, DIGEST_LEN);
 }
 
+static int
+_compare_dir_src_ents_by_authority_id(const void **_a, const void **_b)
+{
+  const dir_src_ent_t *a = *_a, *b = *_b;
+  const networkstatus_voter_info_t *a_v = get_voter(a->v),
+    *b_v = get_voter(b->v);
+  const char *a_id, *b_id;
+  a_id = a->is_legacy ? a_v->legacy_id_digest : a_v->identity_digest;
+  b_id = b->is_legacy ? b_v->legacy_id_digest : b_v->identity_digest;
+
+  return memcmp(a_id, b_id, DIGEST_LEN);
+}
+
 /** Given a sorted list of strings <b>in</b>, add every member to <b>out</b>
  * that occurs more than <b>min</b> times. */
 static void
@@ -416,7 +443,7 @@
 static int
 consensus_method_is_supported(int method)
 {
-  return (method >= 1) && (method <= 2);
+  return (method >= 1) && (method <= 3);
 }
 
 /** Given a list of vote networkstatus_t in <b>votes</b>, our public
@@ -581,34 +608,65 @@
   /* Sort the votes. */
   smartlist_sort(votes, _compare_votes_by_authority_id);
   /* Add the authority sections. */
-  SMARTLIST_FOREACH(votes, networkstatus_t *, v,
   {
-    char buf[1024];
-    struct in_addr in;
-    char ip[INET_NTOA_BUF_LEN];
-    char fingerprint[HEX_DIGEST_LEN+1];
-    char votedigest[HEX_DIGEST_LEN+1];
-    networkstatus_voter_info_t *voter = get_voter(v);
+    smartlist_t *dir_sources = smartlist_create();
+    SMARTLIST_FOREACH(votes, networkstatus_t *, v,
+    {
+      dir_src_ent_t *e = tor_malloc_zero(sizeof(dir_src_ent_t));
+      e->v = v;
+      e->digest = get_voter(v)->identity_digest;
+      e->is_legacy = 0;
+      smartlist_add(dir_sources, e);
+      if (consensus_method >= 3 &&
+          !tor_digest_is_zero(get_voter(v)->legacy_id_digest)) {
+        dir_src_ent_t *e_legacy = tor_malloc_zero(sizeof(dir_src_ent_t));
+        e_legacy->v = v;
+        e_legacy->digest = get_voter(v)->legacy_id_digest;
+        e_legacy->is_legacy = 1;
+        smartlist_add(dir_sources, e);
+      }
+    });
+    smartlist_sort(dir_sources, _compare_dir_src_ents_by_authority_id);
 
-    in.s_addr = htonl(voter->addr);
-    tor_inet_ntoa(&in, ip, sizeof(ip));
-    base16_encode(fingerprint, sizeof(fingerprint), voter->identity_digest,
-                  DIGEST_LEN);
-    base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
-                  DIGEST_LEN);
+    SMARTLIST_FOREACH(dir_sources, const dir_src_ent_t *, e,
+    {
+      char buf[1024];
+      struct in_addr in;
+      char ip[INET_NTOA_BUF_LEN];
+      char fingerprint[HEX_DIGEST_LEN+1];
+      char votedigest[HEX_DIGEST_LEN+1];
+      networkstatus_t *v = e->v;
+      networkstatus_voter_info_t *voter = get_voter(v);
 
-    tor_snprintf(buf, sizeof(buf),
-                 "dir-source %s %s %s %s %d %d\n"
-                 "contact %s\n"
-                 "vote-digest %s\n",
-                 voter->nickname, fingerprint, voter->address, ip,
-                    voter->dir_port,
-                    voter->or_port,
-                 voter->contact,
-                 votedigest);
-    smartlist_add(chunks, tor_strdup(buf));
-  });
+      if (e->is_legacy)
+        tor_assert(consensus_method >= 2);
 
+      in.s_addr = htonl(voter->addr);
+      tor_inet_ntoa(&in, ip, sizeof(ip));
+      base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN);
+      base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
+                    DIGEST_LEN);
+
+      tor_snprintf(buf, sizeof(buf),
+                   "dir-source %s%s %s %s %s %d %d\n",
+                   voter->nickname, e->is_legacy ? "-legacy" : "",
+                   fingerprint, voter->address, ip,
+                   voter->dir_port,
+                   voter->or_port);
+      smartlist_add(chunks, tor_strdup(buf));
+      if (! e->is_legacy) {
+        tor_snprintf(buf, sizeof(buf),
+                     "contact %s\n"
+                     "vote-digest %s\n",
+                     voter->contact,
+                     votedigest);
+        smartlist_add(chunks, tor_strdup(buf));
+      }
+    });
+    SMARTLIST_FOREACH(dir_sources, dir_src_ent_t *, e, tor_free(e));
+    smartlist_free(dir_sources);
+  }
+
   /* Add the actual router entries. */
   {
     int *index; /* index[j] is the current index into votes[j]. */
@@ -904,6 +962,22 @@
       return NULL; /* This leaks, but it should never happen. */
     }
     smartlist_add(chunks, tor_strdup(buf));
+
+    if (get_options()->V3AuthUseLegacyKey && consensus_method >= 3) {
+      crypto_pk_env_t *legacy_key = get_my_v3_legacy_signing_key();
+      authority_cert_t *legacy_cert = get_my_v3_legacy_cert();
+      smartlist_add(chunks, tor_strdup("directory-signature "));
+      crypto_pk_get_fingerprint(legacy_cert->identity_key, fingerprint, 0);
+      crypto_pk_get_fingerprint(legacy_key, signing_key_fingerprint, 0);
+      tor_snprintf(buf, sizeof(buf), "%s %s\n", fingerprint,
+                   signing_key_fingerprint);
+      if (router_append_dirobj_signature(buf, sizeof(buf), digest,
+                                         signing_key)) {
+        log_warn(LD_BUG, "Couldn't sign consensus networkstatus.");
+        return NULL; /* This leaks, but it should never happen. */
+      }
+      smartlist_add(chunks, tor_strdup(buf));
+    }
   }
 
   result = smartlist_join_strings(chunks, "", 0, NULL);

Modified: tor/branches/tor-0_2_0-patches/src/or/or.h
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/or.h	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/src/or/or.h	2008-05-12 02:14:15 UTC (rev 14585)
@@ -1452,6 +1452,7 @@
   uint16_t or_port; /**< OR port of this voter */
   char *contact; /**< Contact information for this voter. */
   char vote_digest[DIGEST_LEN]; /**< Digest of this voter's vote, as signed. */
+  char legacy_id_digest[DIGEST_LEN]; /**< From vote only. DOCDOC */
 
   /* Nothing from here on is signed. */
   char signing_key_digest[DIGEST_LEN]; /**< Declared digest of signing key
@@ -2330,6 +2331,10 @@
   /** The number of intervals we think a consensus should be valid. */
   int V3AuthNIntervalsValid;
 
+  /** Should advertise and sign consensuses with a legacy key, for key
+   * migration purposes? */
+  int V3AuthUseLegacyKey;
+
   /** File to check for a consensus networkstatus, if we don't have one
    * cached. */
   char *FallbackNetworkstatusFile;
@@ -3751,6 +3756,8 @@
 int identity_key_is_set(void);
 authority_cert_t *get_my_v3_authority_cert(void);
 crypto_pk_env_t *get_my_v3_authority_signing_key(void);
+authority_cert_t *get_my_v3_legacy_cert(void);
+crypto_pk_env_t *get_my_v3_legacy_signing_key(void);
 void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last);
 void rotate_onion_key(void);
 crypto_pk_env_t *init_key_from_file(const char *fname, int generate,

Modified: tor/branches/tor-0_2_0-patches/src/or/router.c
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/router.c	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/src/or/router.c	2008-05-12 02:14:15 UTC (rev 14585)
@@ -45,6 +45,9 @@
  * authorities. */
 static authority_cert_t *authority_key_certificate = NULL;
 
+static crypto_pk_env_t *legacy_signing_key = NULL;
+static authority_cert_t *legacy_key_certificate = NULL;
+
 /* (Note that v3 authorities also have a separate "authority identity key",
  * but this key is never actually loaded by the Tor process.  Instead, it's
  * used by tor-gencert to sign new signing keys and make new key
@@ -144,6 +147,18 @@
   return authority_signing_key;
 }
 
+authority_cert_t *
+get_my_v3_legacy_cert(void)
+{
+  return legacy_key_certificate;
+}
+
+crypto_pk_env_t *
+get_my_v3_legacy_signing_key(void)
+{
+  return legacy_signing_key;
+}
+
 /** Replace the previous onion key with the current onion key, and generate
  * a new previous onion key.  Immediately after calling this function,
  * the OR should:
@@ -258,26 +273,26 @@
   return NULL;
 }
 
-/** Load the v3 (voting) authority signing key and certificate, if they are
- * present.  Return -1 if anything is missing, mismatched, or unloadable;
- * return 0 on success. */
 static int
-init_v3_authority_keys(void)
+load_authority_keyset(int legacy, crypto_pk_env_t **key_out,
+                       authority_cert_t **cert_out)
 {
+  int r = -1;
   char *fname = NULL, *cert = NULL;
   const char *eos = NULL;
   crypto_pk_env_t *signing_key = NULL;
   authority_cert_t *parsed = NULL;
-  int r = -1;
 
-  fname = get_datadir_fname2("keys", "authority_signing_key");
+  fname = get_datadir_fname2("keys",
+                 legacy ? "legacy_signing_key" : "authority_signing_key");
   signing_key = init_key_from_file(fname, 0, LOG_INFO);
   if (!signing_key) {
     log_warn(LD_DIR, "No version 3 directory key found in %s", fname);
     goto done;
   }
   tor_free(fname);
-  fname = get_datadir_fname2("keys", "authority_certificate");
+  fname = get_datadir_fname2("keys",
+               legacy ? "legacy_certificate" : "authority_certificate");
   cert = read_file_to_str(fname, 0, NULL);
   if (!cert) {
     log_warn(LD_DIR, "Signing key found, but no certificate found in %s",
@@ -298,18 +313,16 @@
   parsed->cache_info.signed_descriptor_len = eos-cert;
   cert = NULL;
 
-  /* Free old values... */
-  if (authority_key_certificate)
-    authority_cert_free(authority_key_certificate);
-  if (authority_signing_key)
-    crypto_free_pk_env(authority_signing_key);
-  /* ...and replace them. */
-  authority_key_certificate = parsed;
-  authority_signing_key = signing_key;
+  if (*key_out)
+    crypto_free_pk_env(*key_out);
+  if (*cert_out)
+    authority_cert_free(*cert_out);
+  *key_out = signing_key;
+  *cert_out = parsed;
+  r = 0;
+  signing_key = NULL;
   parsed = NULL;
-  signing_key = NULL;
 
-  r = 0;
  done:
   tor_free(fname);
   tor_free(cert);
@@ -320,6 +333,24 @@
   return r;
 }
 
+/** Load the v3 (voting) authority signing key and certificate, if they are
+ * present.  Return -1 if anything is missing, mismatched, or unloadable;
+ * return 0 on success. */
+static int
+init_v3_authority_keys(void)
+{
+  if (load_authority_keyset(0, &authority_signing_key,
+                            &authority_key_certificate)<0)
+    return -1;
+
+  if (get_options()->V3AuthUseLegacyKey &&
+      load_authority_keyset(0, &legacy_signing_key,
+                            &legacy_key_certificate)<0)
+    return -1;
+
+  return 0;
+}
+
 /** If we're a v3 authority, check whether we have a certificate that's
  * likely to expire soon.  Warn if we do, but not too often. */
 void
@@ -1956,6 +1987,10 @@
     crypto_free_pk_env(authority_signing_key);
   if (authority_key_certificate)
     authority_cert_free(authority_key_certificate);
+  if (legacy_signing_key)
+    crypto_free_pk_env(legacy_signing_key);
+  if (legacy_key_certificate)
+    authority_cert_free(legacy_key_certificate);
 
   if (warned_nonexistent_family) {
     SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp));

Modified: tor/branches/tor-0_2_0-patches/src/or/routerparse.c
===================================================================
--- tor/branches/tor-0_2_0-patches/src/or/routerparse.c	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/src/or/routerparse.c	2008-05-12 02:14:15 UTC (rev 14585)
@@ -78,6 +78,7 @@
   K_CONSENSUS_DIGEST,
   K_CONSENSUS_METHODS,
   K_CONSENSUS_METHOD,
+  K_LEGACY_DIR_KEY,
 
   A_PURPOSE,
   _A_UNKNOWN,
@@ -358,6 +359,7 @@
   T0N("opt",                 K_OPT,             CONCAT_ARGS, OBJ_OK ),
   T1( "contact",             K_CONTACT,         CONCAT_ARGS, NO_OBJ ),
   T1( "dir-source",          K_DIR_SOURCE,      GE(6),       NO_OBJ ),
+  T01("legacy-dir-key",      K_LEGACY_DIR_KEY,  GE(1),       NO_OBJ ),
   T1( "known-flags",         K_KNOWN_FLAGS,     CONCAT_ARGS, NO_OBJ ),
   T01("client-versions",     K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
   T01("server-versions",     K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
@@ -2213,6 +2215,23 @@
     goto err;
   }
 
+  if (is_vote &&
+      (tok = find_first_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
+    int bad = 1;
+    if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
+      networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
+      if (base16_decode(voter->legacy_id_digest, DIGEST_LEN,
+                        tok->args[0], HEX_DIGEST_LEN)<0)
+        bad = 1;
+      else
+        bad = 0;
+    }
+    if (bad) {
+      log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
+               escaped(tok->args[0]));
+    }
+  }
+
   /* Parse routerstatus lines. */
   rs_tokens = smartlist_create();
   s = end_of_header;

Modified: tor/branches/tor-0_2_0-patches/src/win32/orconfig.h
===================================================================
--- tor/branches/tor-0_2_0-patches/src/win32/orconfig.h	2008-05-12 02:14:01 UTC (rev 14584)
+++ tor/branches/tor-0_2_0-patches/src/win32/orconfig.h	2008-05-12 02:14:15 UTC (rev 14585)
@@ -227,6 +227,6 @@
 #define USING_TWOS_COMPLEMENT
 
 /* Version number of package */
-#define VERSION "0.2.0.25-rc"
+#define VERSION "0.2.0.25-rc-dev"
 
 



More information about the tor-commits mailing list