[tor-commits] [tor/master] test_dir: Test rsa + ed25519 extrainfo creation and parsing

asn at torproject.org asn at torproject.org
Tue Mar 26 13:37:54 UTC 2019


commit 8e5df40018acd0bd80626073b16b6cc070129109
Author: teor <teor at torproject.org>
Date:   Mon Feb 18 17:37:47 2019 +1000

    test_dir: Test rsa + ed25519 extrainfo creation and parsing
    
    Also fix a missing mock in rsa-only parsing.
---
 src/feature/relay/router.c     |   5 +-
 src/feature/relay/router.h     |   2 +
 src/feature/relay/routerkeys.c |   8 +-
 src/feature/relay/routerkeys.h |   4 +-
 src/test/test_dir.c            | 196 ++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 206 insertions(+), 9 deletions(-)

diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 18c837529..cbd5f2f91 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -271,11 +271,12 @@ expire_old_onion_keys(void)
 
 /** Return the current secret onion key for the ntor handshake. Must only
  * be called from the main thread. */
-static const curve25519_keypair_t *
-get_current_curve25519_keypair(void)
+MOCK_IMPL(STATIC const struct curve25519_keypair_t *,
+get_current_curve25519_keypair,(void))
 {
   return &curve25519_onion_key;
 }
+
 /** Return a map from KEYID (the key itself) to keypairs for use in the ntor
  * handshake. Must only be called from the main thread. */
 di_digest256_map_t *
diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h
index d4ad52c9d..f17e6a943 100644
--- a/src/feature/relay/router.h
+++ b/src/feature/relay/router.h
@@ -124,6 +124,8 @@ STATIC smartlist_t *get_my_declared_family(const or_options_t *options);
 extern time_t desc_clean_since;
 extern const char *desc_dirty_reason;
 void set_server_identity_key_digest_testing(const uint8_t *digest);
+MOCK_DECL(STATIC const struct curve25519_keypair_t *,
+                                       get_current_curve25519_keypair,(void));
 
 MOCK_DECL(STATIC int,
               router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out));
diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c
index 876f908d4..bdd7a82b5 100644
--- a/src/feature/relay/routerkeys.c
+++ b/src/feature/relay/routerkeys.c
@@ -631,14 +631,14 @@ get_master_identity_keypair(void)
 }
 #endif /* defined(TOR_UNIT_TESTS) */
 
-const ed25519_keypair_t *
-get_master_signing_keypair(void)
+MOCK_IMPL(const ed25519_keypair_t *,
+get_master_signing_keypair,(void))
 {
   return master_signing_key;
 }
 
-const struct tor_cert_st *
-get_master_signing_key_cert(void)
+MOCK_IMPL(const struct tor_cert_st *,
+get_master_signing_key_cert,(void))
 {
   return signing_key_cert;
 }
diff --git a/src/feature/relay/routerkeys.h b/src/feature/relay/routerkeys.h
index 0badd3419..cde07b52c 100644
--- a/src/feature/relay/routerkeys.h
+++ b/src/feature/relay/routerkeys.h
@@ -7,8 +7,8 @@
 #include "lib/crypt_ops/crypto_ed25519.h"
 
 const ed25519_public_key_t *get_master_identity_key(void);
-const ed25519_keypair_t *get_master_signing_keypair(void);
-const struct tor_cert_st *get_master_signing_key_cert(void);
+MOCK_DECL(const ed25519_keypair_t *, get_master_signing_keypair,(void));
+MOCK_DECL(const struct tor_cert_st *, get_master_signing_key_cert,(void));
 
 const ed25519_keypair_t *get_current_auth_keypair(void);
 const struct tor_cert_st *get_current_link_cert_cert(void);
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 785d114f7..ad8ab87e9 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -196,6 +196,45 @@ mock_get_onion_key(void)
   return mocked_onionkey;
 }
 
+static routerinfo_t *mocked_routerinfo = NULL;
+
+/* Returns 0 and sets ri_out to mocked_routerinfo.
+ * ri_out must not be NULL. There are no other checks. */
+static int
+mock_router_build_fresh_unsigned_routerinfo(routerinfo_t **ri_out)
+{
+  tor_assert(ri_out);
+  *ri_out = mocked_routerinfo;
+  return 0;
+}
+
+static ed25519_keypair_t *mocked_master_signing_key = NULL;
+
+/* Returns mocked_master_signing_key with no checks. */
+static const ed25519_keypair_t *
+mock_get_master_signing_keypair(void)
+{
+  return mocked_master_signing_key;
+}
+
+static struct tor_cert_st *mocked_signing_key_cert = NULL;
+
+/* Returns mocked_signing_key_cert with no checks. */
+static const struct tor_cert_st *
+mock_get_master_signing_key_cert(void)
+{
+  return mocked_signing_key_cert;
+}
+
+static curve25519_keypair_t *mocked_curve25519_onion_key = NULL;
+
+/* Returns mocked_curve25519_onion_key with no checks. */
+static const curve25519_keypair_t *
+mock_get_current_curve25519_keypair(void)
+{
+  return mocked_curve25519_onion_key;
+}
+
 /** Run unit tests for router descriptor generation logic for a RSA-only
  * router. Tor versions without ed25519 (0.2.6 and earlier) are no longer
  * officially supported, but the authorities still accept their descriptors.
@@ -372,6 +411,22 @@ test_dir_formats_rsa(void *arg)
   mocked_onionkey = pk1;
   MOCK(get_onion_key, mock_get_onion_key);
 
+  /* Fake just enough of an ORPort and DirPort to get by */
+  MOCK(get_configured_ports, mock_get_configured_ports);
+  mocked_configured_ports = smartlist_new();
+
+  memset(&orport, 0, sizeof(orport));
+  orport.type = CONN_TYPE_OR_LISTENER;
+  orport.addr.family = AF_INET;
+  orport.port = 9000;
+  smartlist_add(mocked_configured_ports, &orport);
+
+  memset(&dirport, 0, sizeof(dirport));
+  dirport.type = CONN_TYPE_DIR_LISTENER;
+  dirport.addr.family = AF_INET;
+  dirport.port = 9003;
+  smartlist_add(mocked_configured_ports, &dirport);
+
   /* Test some of the low-level static functions. */
   e1 = router_build_fresh_signed_extrainfo(r1);
   tt_assert(e1);
@@ -392,6 +447,10 @@ test_dir_formats_rsa(void *arg)
   mocked_onionkey = NULL;
   UNMOCK(get_onion_key);
 
+  UNMOCK(get_configured_ports);
+  smartlist_free(mocked_configured_ports);
+  mocked_configured_ports = NULL;
+
   /* Test that the signed ri is parseable */
   tt_assert(r1->cache_info.signed_descriptor_body);
   cp = r1->cache_info.signed_descriptor_body;
@@ -468,6 +527,7 @@ test_dir_formats_rsa_ed25519(void *arg)
   time_t now = time(NULL);
   port_cfg_t orport;
   char cert_buf[256];
+  int rv = -1;
 
   (void)arg;
   pk1 = pk_generate(0);
@@ -478,7 +538,10 @@ test_dir_formats_rsa_ed25519(void *arg)
   hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE);
 
   get_platform_str(platform, sizeof(platform));
-    /* r2 is a RSA + ed25519 descriptor, with an exit policy */
+
+  /* We can't use init_mock_ed_keys() here, because the keys are seeded */
+
+  /* r2 is a RSA + ed25519 descriptor, with an exit policy */
   ex1 = tor_malloc_zero(sizeof(addr_policy_t));
   ex2 = tor_malloc_zero(sizeof(addr_policy_t));
   ex1->policy_type = ADDR_POLICY_ACCEPT;
@@ -662,6 +725,137 @@ test_dir_formats_rsa_ed25519(void *arg)
   tt_int_op(p->prt_min,OP_EQ, 24);
   tt_int_op(p->prt_max,OP_EQ, 24);
 
+  routerinfo_free(rp2);
+
+  /* Test extrainfo creation. */
+
+  /* router_build_fresh_descriptor() requires
+   * router_build_fresh_unsigned_routerinfo(), but the implementation is
+   * too complex. Instead, we re-use r2.
+   */
+  mocked_routerinfo = r2;
+  MOCK(router_build_fresh_unsigned_routerinfo,
+       mock_router_build_fresh_unsigned_routerinfo);
+
+  /* router_build_fresh_signed_extrainfo() requires options->Nickname */
+  tor_free(options->Nickname);
+  options->Nickname = tor_strdup(r2->nickname);
+  /* router_build_fresh_signed_extrainfo() requires get_server_identity_key().
+   * Use the same one as the call to router_dump_router_to_string() above.
+   * For the second router, the keys are swapped.
+   */
+  mocked_server_identitykey = pk1;
+  MOCK(get_server_identity_key, mock_get_server_identity_key);
+  /* router_dump_and_sign_routerinfo_descriptor_body() requires
+   * get_onion_key(). Use the same one as r1.
+   */
+  mocked_onionkey = pk2;
+  MOCK(get_onion_key, mock_get_onion_key);
+
+  /* r2 uses ed25519, so we need to mock the ed key functions */
+  mocked_master_signing_key = &kp2;
+  MOCK(get_master_signing_keypair, mock_get_master_signing_keypair);
+
+  mocked_signing_key_cert = r2->cache_info.signing_key_cert;
+  MOCK(get_master_signing_key_cert, mock_get_master_signing_key_cert);
+
+  mocked_curve25519_onion_key = &r2_onion_keypair;
+  MOCK(get_current_curve25519_keypair, mock_get_current_curve25519_keypair);
+
+  /* Fake just enough of an ORPort to get by */
+  MOCK(get_configured_ports, mock_get_configured_ports);
+  mocked_configured_ports = smartlist_new();
+
+  memset(&orport, 0, sizeof(orport));
+  orport.type = CONN_TYPE_OR_LISTENER;
+  orport.addr.family = AF_INET;
+  orport.port = 9005;
+  smartlist_add(mocked_configured_ports, &orport);
+
+  /* Test the high-level interface. */
+  rv = router_build_fresh_descriptor(&r2_out, &e2);
+  if (rv < 0) {
+    /* router_build_fresh_descriptor() frees r2 on failure. */
+    r2 = NULL;
+    /* Get rid of an alias to rp2 */
+    r2_out = NULL;
+  }
+  tt_assert(rv == 0);
+  tt_assert(r2_out);
+  tt_assert(e2);
+  /* Guaranteed by mock_router_build_fresh_unsigned_routerinfo() */
+  tt_ptr_op(r2_out, OP_EQ, r2);
+  /* Get rid of an alias to r2 */
+  r2_out = NULL;
+
+  /* Now cleanup */
+  mocked_routerinfo = NULL;
+  UNMOCK(router_build_fresh_unsigned_routerinfo);
+  tor_free(options->Nickname);
+  mocked_server_identitykey = NULL;
+  UNMOCK(get_server_identity_key);
+  mocked_onionkey = NULL;
+  UNMOCK(get_onion_key);
+  mocked_master_signing_key = NULL;
+  UNMOCK(get_master_signing_keypair);
+  mocked_signing_key_cert = NULL;
+  UNMOCK(get_master_signing_key_cert);
+  mocked_curve25519_onion_key = NULL;
+  UNMOCK(get_current_curve25519_keypair);
+
+  UNMOCK(get_configured_ports);
+  smartlist_free(mocked_configured_ports);
+  mocked_configured_ports = NULL;
+
+  /* Test that the signed ri is parseable */
+  tt_assert(r2->cache_info.signed_descriptor_body);
+  cp = r2->cache_info.signed_descriptor_body;
+  rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
+  tt_assert(rp2);
+  tt_int_op(rp2->addr,OP_EQ, r2->addr);
+  tt_int_op(rp2->or_port,OP_EQ, r2->or_port);
+  tt_int_op(rp2->dir_port,OP_EQ, r2->dir_port);
+  tt_int_op(rp2->bandwidthrate,OP_EQ, r2->bandwidthrate);
+  tt_int_op(rp2->bandwidthburst,OP_EQ, r2->bandwidthburst);
+  tt_int_op(rp2->bandwidthcapacity,OP_EQ, r2->bandwidthcapacity);
+  tt_mem_op(rp2->onion_curve25519_pkey->public_key,OP_EQ,
+            r2->onion_curve25519_pkey->public_key,
+            CURVE25519_PUBKEY_LEN);
+  onion_pkey = router_get_rsa_onion_pkey(rp2->onion_pkey,
+                                         rp2->onion_pkey_len);
+  tt_int_op(crypto_pk_cmp_keys(onion_pkey, pk2), OP_EQ, 0);
+  crypto_pk_free(onion_pkey);
+  tt_int_op(crypto_pk_cmp_keys(rp2->identity_pkey, pk1), OP_EQ, 0);
+  tt_assert(rp2->supports_tunnelled_dir_requests);
+
+  tt_int_op(smartlist_len(rp2->exit_policy),OP_EQ, 2);
+
+  p = smartlist_get(rp2->exit_policy, 0);
+  tt_int_op(p->policy_type,OP_EQ, ADDR_POLICY_ACCEPT);
+  tt_assert(tor_addr_is_null(&p->addr));
+  tt_int_op(p->maskbits,OP_EQ, 0);
+  tt_int_op(p->prt_min,OP_EQ, 80);
+  tt_int_op(p->prt_max,OP_EQ, 80);
+
+  p = smartlist_get(rp2->exit_policy, 1);
+  tt_int_op(p->policy_type,OP_EQ, ADDR_POLICY_REJECT);
+  tt_assert(tor_addr_eq(&p->addr, &ex2->addr));
+  tt_int_op(p->maskbits,OP_EQ, 8);
+  tt_int_op(p->prt_min,OP_EQ, 24);
+  tt_int_op(p->prt_max,OP_EQ, 24);
+
+  routerinfo_free(rp2);
+
+  /* Test that the signed ei is parseable */
+  tt_assert(e2->cache_info.signed_descriptor_body);
+  cp = e2->cache_info.signed_descriptor_body;
+  ep2 = extrainfo_parse_entry_from_string((const char*)cp,NULL,1,NULL,NULL);
+  tt_assert(ep2);
+  tt_str_op(ep2->nickname, OP_EQ, r2->nickname);
+  /* In future tests, we could check the actual extrainfo statistics. */
+
+  extrainfo_free(ep2);
+
 #if 0
   /* Okay, now for the directories. */
   {





More information about the tor-commits mailing list