Browse Source

Include ed25519 keys in microdescriptors.

Nick Mathewson 9 years ago
parent
commit
24b720a984
6 changed files with 138 additions and 5 deletions
  1. 15 4
      src/or/dirvote.c
  2. 5 1
      src/or/dirvote.h
  3. 1 0
      src/or/microdesc.c
  4. 2 0
      src/or/or.h
  5. 22 0
      src/or/routerparse.c
  6. 93 0
      src/test/test_microdesc.c

+ 15 - 4
src/or/dirvote.c

@@ -17,6 +17,7 @@
 #include "routerlist.h"
 #include "routerparse.h"
 #include "entrynodes.h" /* needed for guardfraction methods */
+#include "torcert.h"
 
 /**
  * \file dirvote.c
@@ -3486,9 +3487,18 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
   }
 
   if (consensus_method >= MIN_METHOD_FOR_ID_HASH_IN_MD) {
-    char idbuf[BASE64_DIGEST_LEN+1];
-    digest_to_base64(idbuf, ri->cache_info.identity_digest);
-    smartlist_add_asprintf(chunks, "id rsa1024 %s\n", idbuf);
+    char idbuf[ED25519_BASE64_LEN+1];
+    const char *keytype;
+    if (consensus_method >= MIN_METHOD_FOR_ED25519_ID_IN_MD &&
+        ri->signing_key_cert &&
+        ri->signing_key_cert->signing_key_included) {
+      keytype = "ed25519";
+      ed25519_public_to_base64(idbuf, &ri->signing_key_cert->signing_key);
+    } else {
+      keytype = "rsa1024";
+      digest_to_base64(idbuf, ri->cache_info.identity_digest);
+    }
+    smartlist_add_asprintf(chunks, "id %s %s\n", keytype, idbuf);
   }
 
   output = smartlist_join_strings(chunks, "", 0, NULL);
@@ -3561,7 +3571,8 @@ static const struct consensus_method_range_t {
   {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1},
   {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1},
   {MIN_METHOD_FOR_NTOR_KEY, MIN_METHOD_FOR_ID_HASH_IN_MD - 1},
-  {MIN_METHOD_FOR_ID_HASH_IN_MD,  MAX_SUPPORTED_CONSENSUS_METHOD},
+  {MIN_METHOD_FOR_ID_HASH_IN_MD, MIN_METHOD_FOR_ED25519_ID_IN_MD - 1},
+  {MIN_METHOD_FOR_ED25519_ID_IN_MD, MAX_SUPPORTED_CONSENSUS_METHOD},
   {-1, -1}
 };
 

+ 5 - 1
src/or/dirvote.h

@@ -55,7 +55,7 @@
 #define MIN_SUPPORTED_CONSENSUS_METHOD 13
 
 /** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 20
+#define MAX_SUPPORTED_CONSENSUS_METHOD 21
 
 /** Lowest consensus method where microdesc consensuses omit any entry
  * with no microdesc. */
@@ -86,6 +86,10 @@
  * GuardFraction information in microdescriptors. */
 #define MIN_METHOD_FOR_GUARDFRACTION 20
 
+/** Lowest consensus method where authorities may include an "id" line for
+ * ed25519 identities in microdescriptors. */
+#define MIN_METHOD_FOR_ED25519_ID_IN_MD 21
+
 /** Default bandwidth to clip unmeasured bandwidths to using method >=
  * MIN_METHOD_TO_CLIP_UNMEASURED_BW.  (This is not a consensus method; do not
  * get confused with the above macros.) */

+ 1 - 0
src/or/microdesc.c

@@ -738,6 +738,7 @@ microdesc_free_(microdesc_t *md, const char *fname, int lineno)
   if (md->onion_pkey)
     crypto_pk_free(md->onion_pkey);
   tor_free(md->onion_curve25519_pkey);
+  tor_free(md->ed25519_identity_pkey);
   if (md->body && md->saved_location != SAVED_IN_CACHE)
     tor_free(md->body);
 

+ 2 - 0
src/or/or.h

@@ -2234,6 +2234,8 @@ typedef struct microdesc_t {
   crypto_pk_t *onion_pkey;
   /** As routerinfo_t.onion_curve25519_pkey */
   curve25519_public_key_t *onion_curve25519_pkey;
+  /** Ed25519 identity key, if included. */
+  ed25519_public_key_t *ed25519_identity_pkey;
   /** As routerinfo_t.ipv6_add */
   tor_addr_t ipv6_addr;
   /** As routerinfo_t.ipv6_orport */

+ 22 - 0
src/or/routerparse.c

@@ -72,6 +72,7 @@ typedef enum {
   K_CLIENT_VERSIONS,
   K_SERVER_VERSIONS,
   K_OR_ADDRESS,
+  K_ID,
   K_P,
   K_P6,
   K_R,
@@ -503,6 +504,7 @@ static token_rule_t networkstatus_detached_signature_token_table[] = {
 static token_rule_t microdesc_token_table[] = {
   T1_START("onion-key",        K_ONION_KEY,        NO_ARGS,     NEED_KEY_1024),
   T01("ntor-onion-key",        K_ONION_KEY_NTOR,   GE(1),       NO_OBJ ),
+  T0N("id",                    K_ID,               GE(2),       NO_OBJ ),
   T0N("a",                     K_A,                GE(1),       NO_OBJ ),
   T01("family",                K_FAMILY,           ARGS,        NO_OBJ ),
   T01("p",                     K_P,                CONCAT_ARGS, NO_OBJ ),
@@ -4372,6 +4374,26 @@ microdescs_parse_from_string(const char *s, const char *eos,
         tor_memdup(&k, sizeof(curve25519_public_key_t));
     }
 
+    smartlist_t *id_lines = find_all_by_keyword(tokens, K_ID);
+    if (id_lines) {
+      SMARTLIST_FOREACH_BEGIN(id_lines, directory_token_t *, t) {
+        tor_assert(t->n_args >= 2);
+        if (!strcmp(t->args[0], "ed25519")) {
+          if (md->ed25519_identity_pkey) {
+            log_warn(LD_DIR, "Extra ed25519 key in microdesc");
+            goto next;
+          }
+          ed25519_public_key_t k;
+          if (ed25519_public_from_base64(&k, t->args[1])<0) {
+            log_warn(LD_DIR, "Bogus ed25519 key in microdesc");
+            goto next;
+          }
+          md->ed25519_identity_pkey = tor_memdup(&k, sizeof(k));
+        }
+      } SMARTLIST_FOREACH_END(t);
+      smartlist_free(id_lines);
+    }
+
     {
       smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
       if (a_lines) {

+ 93 - 0
src/test/test_microdesc.c

@@ -10,6 +10,7 @@
 #include "networkstatus.h"
 #include "routerlist.h"
 #include "routerparse.h"
+#include "torcert.h"
 
 #include "test.h"
 
@@ -335,6 +336,59 @@ static const char test_ri[] =
   "t0xkIE39ss/EwmQr7iIgkdVH4oRIMsjYnFFJBG26nYY=\n"
   "-----END SIGNATURE-----\n";
 
+static const char test_ri2[] =
+  "router test001a 127.0.0.1 5001 0 7001\n"
+  "identity-ed25519\n"
+  "-----BEGIN ED25519 CERT-----\n"
+  "AQQABf/FAf5iDuKCZP2VxnAaQWdklilAh6kaEeFX4z8261Yx2T1/AQAgBADCp8vO\n"
+  "B8K1F9g2DzwuwvVCnPFLSK1qknVqPpNucHLH9DY7fuIYogBAdz4zHv1qC7RKaMNG\n"
+  "Jux/tMO2tzPcm62Ky5PjClMQplKUOnZNQ+RIpA3wYCIfUDy/cQnY7XWgNQ0=\n"
+  "-----END ED25519 CERT-----\n"
+  "platform Tor 0.2.6.0-alpha-dev on Darwin\n"
+  "protocols Link 1 2 Circuit 1\n"
+  "published 2014-10-08 12:58:04\n"
+  "fingerprint B7E2 7F10 4213 C36F 13E7 E982 9182 845E 4959 97A0\n"
+  "uptime 0\n"
+  "bandwidth 1073741824 1073741824 0\n"
+  "extra-info-digest 568F27331B6D8C73E7024F1EF5D097B90DFC7CDB\n"
+  "caches-extra-info\n"
+  "onion-key\n"
+  "-----BEGIN RSA PUBLIC KEY-----\n"
+  "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n"
+  "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n"
+  "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n"
+  "-----END RSA PUBLIC KEY-----\n"
+  "signing-key\n"
+  "-----BEGIN RSA PUBLIC KEY-----\n"
+  "MIGJAoGBAN8+78KUVlgHXdMMkYJxcwh1Zv2y+Gb5eWUyltUaQRajhrT9ij2T5JZs\n"
+  "M0g85xTcuM3jNVVpV79+33hiTohdC6UZ+Bk4USQ7WBFzRbVFSXoVKLBJFkCOIexg\n"
+  "SMGNd5WEDtHWrXl58mizmPFu1eG6ZxHzt7RuLSol5cwBvawXPNkFAgMBAAE=\n"
+  "-----END RSA PUBLIC KEY-----\n"
+  "onion-key-crosscert\n"
+  "-----BEGIN CROSSCERT-----\n"
+  "ETFDzU49bvNfoZnKK1j6JeBP2gDirgj6bBCgWpUYs663OO9ypbZRO0JwWANssKl6\n"
+  "oaq9vKTsKGRsaNnqnz/JGMhehymakjjNtqg7crWwsahe8+7Pw9GKmW+YjFtcOkUf\n"
+  "KfOn2bmKBa1FoJb4yW3oXzHcdlLSRuCciKqPn+Hky5o=\n"
+  "-----END CROSSCERT-----\n"
+  "ntor-onion-key-crosscert 0\n"
+  "-----BEGIN ED25519 CERT-----\n"
+  "AQoABf2dAcKny84HwrUX2DYPPC7C9UKc8UtIrWqSdWo+k25wcsf0AFohutG+xI06\n"
+  "Ef21c5Zl1j8Hw6DzHDjYyJevXLFuOneaL3zcH2Ldn4sjrG3kc5UuVvRfTvV120UO\n"
+  "xk4f5s5LGwY=\n"
+  "-----END ED25519 CERT-----\n"
+  "hidden-service-dir\n"
+  "contact auth1@test.test\n"
+  "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n"
+  "reject *:*\n"
+  "router-sig-ed25519 5aQXyTif7PExIuL2di37UvktmJECKnils2OWz2vDi"
+                     "hFxi+5TTAAPxYkS5clhc/Pjvw34itfjGmTKFic/8httAQ\n"
+  "router-signature\n"
+  "-----BEGIN SIGNATURE-----\n"
+  "BaUB+aFPQbb3BwtdzKsKqV3+6cRlSqJF5bI3UTmwRoJk+Z5Pz+W5NWokNI0xArHM\n"
+  "T4T5FZCCP9350jXsUCIvzyIyktU6aVRCGFt76rFlo1OETpN8GWkMnQU0w18cxvgS\n"
+  "cf34GXHv61XReJF3AlzNHFpbrPOYmowmhrTULKyMqow=\n"
+  "-----END SIGNATURE-----\n";
+
 static const char test_md_8[] =
   "onion-key\n"
   "-----BEGIN RSA PUBLIC KEY-----\n"
@@ -365,6 +419,26 @@ static const char test_md_18[] =
   "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
   "id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4\n";
 
+static const char test_md2_18[] =
+  "onion-key\n"
+  "-----BEGIN RSA PUBLIC KEY-----\n"
+  "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n"
+  "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n"
+  "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n"
+  "-----END RSA PUBLIC KEY-----\n"
+  "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n"
+  "id rsa1024 t+J/EEITw28T5+mCkYKEXklZl6A\n";
+
+static const char test_md2_21[] =
+  "onion-key\n"
+  "-----BEGIN RSA PUBLIC KEY-----\n"
+  "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n"
+  "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n"
+  "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n"
+  "-----END RSA PUBLIC KEY-----\n"
+  "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n"
+  "id ed25519 wqfLzgfCtRfYNg88LsL1QpzxS0itapJ1aj6TbnByx/Q\n";
+
 static void
 test_md_generate(void *arg)
 {
@@ -391,6 +465,25 @@ test_md_generate(void *arg)
   md = dirvote_create_microdescriptor(ri, 18);
   tt_str_op(md->body, OP_EQ, test_md_18);
 
+  microdesc_free(md);
+  md = NULL;
+  md = dirvote_create_microdescriptor(ri, 21);
+  tt_str_op(md->body, ==, test_md_18);
+
+  ri = router_parse_entry_from_string(test_ri2, NULL, 0, 0, NULL, NULL);
+
+  microdesc_free(md);
+  md = NULL;
+  md = dirvote_create_microdescriptor(ri, 18);
+  tt_str_op(md->body, ==, test_md2_18);
+
+  microdesc_free(md);
+  md = NULL;
+  md = dirvote_create_microdescriptor(ri, 21);
+  tt_str_op(md->body, ==, test_md2_21);
+  tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey,
+                              &ri->signing_key_cert->signing_key));
+
  done:
   microdesc_free(md);
   routerinfo_free(ri);