Browse Source

prop224: Add connection and circuit identifier object

Signed-off-by: David Goulet <dgoulet@torproject.org>
David Goulet 7 years ago
parent
commit
f8dc1164ba
7 changed files with 242 additions and 7 deletions
  1. 2 0
      src/or/circuitlist.c
  2. 3 0
      src/or/connection.c
  3. 6 0
      src/or/hs_common.h
  4. 81 0
      src/or/hs_ident.c
  5. 124 0
      src/or/hs_ident.h
  6. 9 7
      src/or/include.am
  7. 17 0
      src/or/or.h

+ 2 - 0
src/or/circuitlist.c

@@ -67,6 +67,7 @@
 #include "main.h"
 #include "hs_circuitmap.h"
 #include "hs_common.h"
+#include "hs_ident.h"
 #include "networkstatus.h"
 #include "nodelist.h"
 #include "onion.h"
@@ -957,6 +958,7 @@ circuit_free(circuit_t *circ)
 
     crypto_pk_free(ocirc->intro_key);
     rend_data_free(ocirc->rend_data);
+    hs_ident_circuit_free(ocirc->hs_ident);
 
     tor_free(ocirc->dest_address);
     if (ocirc->socks_username) {

+ 3 - 0
src/or/connection.c

@@ -84,6 +84,7 @@
 #include "geoip.h"
 #include "main.h"
 #include "hs_common.h"
+#include "hs_ident.h"
 #include "nodelist.h"
 #include "policies.h"
 #include "reasons.h"
@@ -605,6 +606,7 @@ connection_free_(connection_t *conn)
   }
   if (CONN_IS_EDGE(conn)) {
     rend_data_free(TO_EDGE_CONN(conn)->rend_data);
+    hs_ident_edge_conn_free(TO_EDGE_CONN(conn)->hs_ident);
   }
   if (conn->type == CONN_TYPE_CONTROL) {
     control_connection_t *control_conn = TO_CONTROL_CONN(conn);
@@ -636,6 +638,7 @@ connection_free_(connection_t *conn)
     }
 
     rend_data_free(dir_conn->rend_data);
+    hs_ident_dir_conn_free(dir_conn->hs_ident);
     if (dir_conn->guard_state) {
       /* Cancel before freeing, if it's still there. */
       entry_guard_cancel(&dir_conn->guard_state);

+ 6 - 0
src/or/hs_common.h

@@ -49,6 +49,12 @@
 /* The time period rotation offset as seen in prop224 section [TIME-PERIODS] */
 #define HS_TIME_PERIOD_ROTATION_OFFSET (12 * 60) /* minutes */
 
+/* Type of authentication key used by an introduction point. */
+typedef enum {
+  HS_AUTH_KEY_TYPE_LEGACY  = 1,
+  HS_AUTH_KEY_TYPE_ED25519 = 2,
+} hs_auth_key_type_t;
+
 int hs_check_service_private_dir(const char *username, const char *path,
                                  unsigned int dir_group_readable,
                                  unsigned int create);

+ 81 - 0
src/or/hs_ident.c

@@ -0,0 +1,81 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file hs_ident.c
+ * \brief Contains circuit and connection identifier code for the whole HS
+ *        subsytem.
+ **/
+
+#include "hs_ident.h"
+
+/* Return a newly allocated circuit identifier. The given public key is copied
+ * identity_pk into the identifier. */
+hs_ident_circuit_t *
+hs_ident_circuit_new(const ed25519_public_key_t *identity_pk,
+                     hs_ident_circuit_type_t circuit_type)
+{
+  tor_assert(circuit_type == HS_IDENT_CIRCUIT_INTRO ||
+             circuit_type == HS_IDENT_CIRCUIT_RENDEZVOUS);
+  hs_ident_circuit_t *ident = tor_malloc_zero(sizeof(*ident));
+  ed25519_pubkey_copy(&ident->identity_pk, identity_pk);
+  ident->circuit_type = circuit_type;
+  return ident;
+}
+
+/* Free the given circuit identifier. */
+void
+hs_ident_circuit_free(hs_ident_circuit_t *ident)
+{
+  if (ident == NULL) {
+    return;
+  }
+  if (ident->auth_key_type == HS_AUTH_KEY_TYPE_LEGACY) {
+    crypto_pk_free(ident->auth_rsa_pk);
+  }
+  memwipe(ident, 0, sizeof(hs_ident_circuit_t));
+  tor_free(ident);
+}
+
+/* For a given directory connection identifier src, return a newly allocated
+ * copy of it. This can't fail. */
+hs_ident_dir_conn_t *
+hs_ident_dir_conn_dup(const hs_ident_dir_conn_t *src)
+{
+  hs_ident_dir_conn_t *ident = tor_malloc_zero(sizeof(*ident));
+  memcpy(ident, src, sizeof(*ident));
+  return ident;
+}
+
+/* Free the given directory connection identifier. */
+void
+hs_ident_dir_conn_free(hs_ident_dir_conn_t *ident)
+{
+  if (ident == NULL) {
+    return;
+  }
+  memwipe(ident, 0, sizeof(hs_ident_dir_conn_t));
+  tor_free(ident);
+}
+
+/* Return a newly allocated edge connection identifier. The given public key
+ * identity_pk is copied into the identifier. */
+hs_ident_edge_conn_t *
+hs_ident_edge_conn_new(const ed25519_public_key_t *identity_pk)
+{
+  hs_ident_edge_conn_t *ident = tor_malloc_zero(sizeof(*ident));
+  ed25519_pubkey_copy(&ident->identity_pk, identity_pk);
+  return ident;
+}
+
+/* Free the given edge connection identifier. */
+void
+hs_ident_edge_conn_free(hs_ident_edge_conn_t *ident)
+{
+  if (ident == NULL) {
+    return;
+  }
+  memwipe(ident, 0, sizeof(hs_ident_edge_conn_t));
+  tor_free(ident);
+}
+

+ 124 - 0
src/or/hs_ident.h

@@ -0,0 +1,124 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file hs_ident.h
+ * \brief Header file containing circuit and connection identifier data for
+ *        the whole HS subsytem.
+ *
+ * \details
+ * This interface is used to uniquely identify a hidden service on a circuit
+ * or connection using the service identity public key. Once the circuit or
+ * connection subsystem calls in the hidden service one, we use those
+ * identifiers to lookup the corresponding objects like service, intro point
+ * and descriptor.
+ *
+ * Furthermore, the circuit identifier holds cryptographic material needed for
+ * the e2e encryption on the rendezvous circuit which is set once the
+ * rendezvous circuit has opened and ready to be used.
+ **/
+
+#ifndef TOR_HS_IDENT_H
+#define TOR_HS_IDENT_H
+
+#include "crypto.h"
+#include "crypto_ed25519.h"
+
+#include "hs_common.h"
+
+/* Length of the rendezvous cookie that is used to connect circuits at the
+ * rendezvous point. */
+#define HS_REND_COOKIE_LEN DIGEST_LEN
+
+/* Type of circuit an hs_ident_t object is associated with. */
+typedef enum {
+  HS_IDENT_CIRCUIT_INTRO      = 1,
+  HS_IDENT_CIRCUIT_RENDEZVOUS = 2,
+} hs_ident_circuit_type_t;
+
+/* Client and service side circuit identifier that is used for hidden service
+ * circuit establishment. Not all fields contain data, it depends on the
+ * circuit purpose. This is attached to an origin_circuit_t. All fields are
+ * used by both client and service. */
+typedef struct hs_ident_circuit_t {
+  /* (All circuit) The public key used to uniquely identify the service. It is
+   * the one found in the onion address. */
+  ed25519_public_key_t identity_pk;
+
+  /* (All circuit) The type of circuit this identifier is attached to.
+   * Accessors of the fields in this object assert non fatal on this circuit
+   * type. In other words, if a rendezvous field is being accessed, the
+   * circuit type MUST BE of type HS_IDENT_CIRCUIT_RENDEZVOUS. This value is
+   * set when an object is initialized in its constructor. */
+  hs_ident_circuit_type_t circuit_type;
+
+  /* (Only intro point circuit) Which type of authentication key this
+   * circuit identifier is using. */
+  hs_auth_key_type_t auth_key_type;
+
+  /* (Only intro point circuit) Introduction point authentication key. In
+   * legacy mode, we use an RSA key else an ed25519 public key. */
+  crypto_pk_t *auth_rsa_pk;
+  ed25519_public_key_t auth_ed25519_pk;
+
+  /* (Only rendezvous circuit) Rendezvous cookie sent from the client to the
+   * service with an INTRODUCE1 cell and used by the service in an
+   * RENDEZVOUS1 cell. */
+  uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN];
+
+  /* (Only rendezvous circuit) The HANDSHAKE_INFO needed in the RENDEZVOUS1
+   * cell of the service. The construction is as follows:
+   *    SERVER_PK   [32 bytes]
+   *    AUTH_MAC    [32 bytes]
+   */
+  uint8_t rendezvous_handshake_info[CURVE25519_PUBKEY_LEN + DIGEST256_LEN];
+
+  /* (Only rendezvous circuit) The NTOR_KEY_SEED needed for key derivation for
+   * the e2e encryption with the client on the circuit. */
+  uint8_t rendezvous_ntor_key_seed[DIGEST256_LEN];
+
+  /* (Only rendezvous circuit) Number of streams associated with this
+   * rendezvous circuit. We track this because there is a check on a maximum
+   * value. */
+  uint64_t num_rdv_streams;
+} hs_ident_circuit_t;
+
+/* Client and service side directory connection identifier used for a
+ * directory connection to identify which service is being queried. This is
+ * attached to a dir_connection_t. */
+typedef struct hs_ident_dir_conn_t {
+  /* The public key used to uniquely identify the service. It is the one found
+   * in the onion address. */
+  ed25519_public_key_t identity_pk;
+
+  /* XXX: Client authorization. */
+} hs_ident_dir_conn_t;
+
+/* Client and service side edge connection identifier used for an edge
+ * connection to identify which service is being queried. This is attached to
+ * a edge_connection_t. */
+typedef struct hs_ident_edge_conn_t {
+  /* The public key used to uniquely identify the service. It is the one found
+   * in the onion address. */
+  ed25519_public_key_t identity_pk;
+
+  /* XXX: Client authorization. */
+} hs_ident_edge_conn_t;
+
+/* Circuit identifier API. */
+hs_ident_circuit_t *hs_ident_circuit_new(
+                             const ed25519_public_key_t *identity_pk,
+                             hs_ident_circuit_type_t circuit_type);
+void hs_ident_circuit_free(hs_ident_circuit_t *ident);
+
+/* Directory connection identifier API. */
+hs_ident_dir_conn_t *hs_ident_dir_conn_dup(const hs_ident_dir_conn_t *src);
+void hs_ident_dir_conn_free(hs_ident_dir_conn_t *ident);
+
+/* Edge connection identifier API. */
+hs_ident_edge_conn_t *hs_ident_edge_conn_new(
+                                    const ed25519_public_key_t *identity_pk);
+void hs_ident_edge_conn_free(hs_ident_edge_conn_t *ident);
+
+#endif /* TOR_HS_IDENT_H */
+

+ 9 - 7
src/or/include.am

@@ -50,16 +50,17 @@ LIBTOR_A_SOURCES = \
 	src/or/dnsserv.c				\
 	src/or/fp_pair.c				\
 	src/or/geoip.c					\
-	src/or/hs_intropoint.c          \
-	src/or/hs_circuitmap.c          \
-	src/or/hs_ntor.c                \
-	src/or/hs_service.c             \
-	src/or/entrynodes.c				\
-	src/or/ext_orport.c				\
-	src/or/hibernate.c				\
 	src/or/hs_cache.c				\
+	src/or/hs_circuitmap.c				\
 	src/or/hs_common.c				\
 	src/or/hs_descriptor.c				\
+	src/or/hs_ident.c				\
+	src/or/hs_intropoint.c				\
+	src/or/hs_ntor.c				\
+	src/or/hs_service.c				\
+	src/or/entrynodes.c				\
+	src/or/ext_orport.c				\
+	src/or/hibernate.c				\
 	src/or/keypin.c					\
 	src/or/main.c					\
 	src/or/microdesc.c				\
@@ -182,6 +183,7 @@ ORHEADERS = \
 	src/or/hs_cache.h				\
 	src/or/hs_common.h				\
 	src/or/hs_descriptor.h				\
+	src/or/hs_ident.h				\
 	src/or/hs_intropoint.h          \
 	src/or/hs_circuitmap.h          \
 	src/or/hs_ntor.h                \

+ 17 - 0
src/or/or.h

@@ -846,6 +846,11 @@ rend_data_v2_t *TO_REND_DATA_V2(const rend_data_t *d)
   return DOWNCAST(rend_data_v2_t, d);
 }
 
+/* Stub because we can't include hs_ident.h. */
+typedef struct hs_ident_edge_conn_t hs_ident_edge_conn_t;
+typedef struct hs_ident_dir_conn_t hs_ident_dir_conn_t;
+typedef struct hs_ident_circuit_t hs_ident_circuit_t;
+
 /** Time interval for tracking replays of DH public keys received in
  * INTRODUCE2 cells.  Used only to avoid launching multiple
  * simultaneous attempts to connect to the same rendezvous point. */
@@ -1633,6 +1638,10 @@ typedef struct edge_connection_t {
    * an exit)? */
   rend_data_t *rend_data;
 
+  /* Hidden service connection identifier that is which service is being
+   * queried? */
+  hs_ident_edge_conn_t *hs_ident;
+
   uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
                          * connection.  Exit connections only. */
   uint32_t begincell_flags; /** Flags sent or received in the BEGIN cell
@@ -1783,6 +1792,10 @@ typedef struct dir_connection_t {
   /** What rendezvous service are we querying for? */
   rend_data_t *rend_data;
 
+  /* Hidden service connection identifier that is which service is being
+   * queried? */
+  hs_ident_dir_conn_t *hs_ident;
+
   /** If this is a one-hop connection, tracks the state of the directory guard
    * for this connection (if any). */
   struct circuit_guard_state_t *guard_state;
@@ -3186,6 +3199,10 @@ typedef struct origin_circuit_t {
   /** Holds all rendezvous data on either client or service side. */
   rend_data_t *rend_data;
 
+  /** Holds hidden service identifier on either client or service side. This
+   * is for both introduction and rendezvous circuit. */
+  hs_ident_circuit_t *hs_ident;
+
   /** Holds the data that the entry guard system uses to track the
    * status of the guard this circuit is using, and thereby to determine
    * whether this circuit can be used. */