[tor-commits] [tor/master] prop224: Add code that generates ESTABLISH_INTRO cells.

nickm at torproject.org nickm at torproject.org
Wed Dec 14 21:05:47 UTC 2016


commit c4c90d56b543887ee9bee6553725151b09891d8e
Author: George Kadianakis <desnacked at riseup.net>
Date:   Mon Sep 5 18:58:19 2016 +0300

    prop224: Add code that generates ESTABLISH_INTRO cells.
    
    Currently unused. It will only be used for creating ESTABLISH_INTRO
    cells in unittests :)
---
 src/or/hs_common.h  |   7 ++-
 src/or/hs_service.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/or/hs_service.h |  31 ++++++++++
 3 files changed, 212 insertions(+), 1 deletion(-)

diff --git a/src/or/hs_common.h b/src/or/hs_common.h
index 2502f35..55710b7 100644
--- a/src/or/hs_common.h
+++ b/src/or/hs_common.h
@@ -17,6 +17,12 @@
 /* Version 3 of the protocol (prop224). */
 #define HS_VERSION_THREE 3
 
+/* Denotes ed25519 authentication key on ESTABLISH_INTRO cell. */
+#define AUTH_KEY_ED25519 0x02
+
+/* String prefix for the signature of ESTABLISH_INTRO */
+#define ESTABLISH_INTRO_SIG_PREFIX "Tor establish-intro cell v1"
+
 void rend_data_free(rend_data_t *data);
 rend_data_t *rend_data_dup(const rend_data_t *data);
 rend_data_t *rend_data_client_create(const char *onion_address,
@@ -36,4 +42,3 @@ const uint8_t *rend_data_get_pk_digest(const rend_data_t *rend_data,
 int hs_v3_protocol_is_enabled(void);
 
 #endif /* TOR_HS_COMMON_H */
-
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
new file mode 100644
index 0000000..69f83cf
--- /dev/null
+++ b/src/or/hs_service.c
@@ -0,0 +1,175 @@
+/* Copyright (c) 2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file hs_service.c
+ * \brief Implement next generation hidden service functionality
+ **/
+
+#define HS_SERVICE_PRIVATE
+
+#include "or.h"
+#include "relay.h"
+#include "rendservice.h"
+#include "circuitlist.h"
+#include "circpathbias.h"
+
+#include "hs_service.h"
+#include "hs_common.h"
+
+#include "hs/cell_establish_intro.h"
+#include "hs/cell_common.h"
+
+/* XXX We don't currently use these functions, apart from generating unittest
+   data. When we start implementing the service-side support for prop224 we
+   should revisit these functions and use them. For now we mark them as
+   unittest-only code: */
+#ifdef TOR_UNIT_TESTS
+
+/** Given an ESTABLISH_INTRO <b>cell</b>, encode it and place its payload in
+ *  <b>buf_out</b> which has size <b>buf_out_len</b>. Return the number of
+ *  bytes written, or a negative integer if there was an error. */
+STATIC ssize_t
+get_establish_intro_payload(uint8_t *buf_out, size_t buf_out_len,
+                            const hs_cell_establish_intro_t *cell)
+{
+  ssize_t bytes_used = 0;
+
+  if (buf_out_len < RELAY_PAYLOAD_SIZE) {
+    return -1;
+  }
+
+  bytes_used = hs_cell_establish_intro_encode(buf_out, buf_out_len,
+                                              cell);
+  return bytes_used;
+}
+
+/* Set the cell extensions of <b>cell</b>. */
+static void
+set_cell_extensions(hs_cell_establish_intro_t *cell)
+{
+  cell_extension_t *cell_extensions = cell_extension_new();
+
+  /* For now, we don't use extensions at all. */
+  cell_extensions->num = 0; /* It's already zeroed, but be explicit. */
+  hs_cell_establish_intro_set_extensions(cell, cell_extensions);
+}
+
+/** Given the circuit handshake info in <b>circuit_key_material</b>, create and
+ *  return an ESTABLISH_INTRO cell. Return NULL if something went wrong.  The
+ *  returned cell is allocated on the heap and it's the responsibility of the
+ *  caller to free it. */
+STATIC hs_cell_establish_intro_t *
+generate_establish_intro_cell(const char *circuit_key_material,
+                              size_t circuit_key_material_len)
+{
+  hs_cell_establish_intro_t *cell = NULL;
+  ssize_t encoded_len;
+
+  log_warn(LD_GENERAL,
+           "Generating ESTABLISH_INTRO cell (key_material_len: %u)",
+           (unsigned) circuit_key_material_len);
+
+  /* Generate short-term keypair for use in ESTABLISH_INTRO */
+  ed25519_keypair_t key_struct;
+  if (ed25519_keypair_generate(&key_struct, 0) < 0) {
+    goto err;
+  }
+
+  cell = hs_cell_establish_intro_new();
+
+  /* Set AUTH_KEY_TYPE: 2 means ed25519 */
+  hs_cell_establish_intro_set_auth_key_type(cell, AUTH_KEY_ED25519);
+
+  /* Set AUTH_KEY_LEN field */
+  /* Must also set byte-length of AUTH_KEY to match */
+  int auth_key_len = ED25519_PUBKEY_LEN;
+  hs_cell_establish_intro_set_auth_key_len(cell, auth_key_len);
+  hs_cell_establish_intro_setlen_auth_key(cell, auth_key_len);
+
+  /* Set AUTH_KEY field */
+  uint8_t *auth_key_ptr = hs_cell_establish_intro_getarray_auth_key(cell);
+  memcpy(auth_key_ptr, key_struct.pubkey.pubkey, auth_key_len);
+
+  /* No cell extensions needed */
+  set_cell_extensions(cell);
+
+  /* Set signature size.
+     We need to do this up here, because _encode() needs it and we need to call
+     _encode() to calculate the MAC and signature.
+  */
+  int sig_len = ED25519_SIG_LEN;
+  hs_cell_establish_intro_set_sig_len(cell, sig_len);
+  hs_cell_establish_intro_setlen_sig(cell, sig_len);
+
+  /* XXX How to make this process easier and nicer? */
+
+  /* Calculate the cell MAC (aka HANDSHAKE_AUTH). */
+  {
+    /* To calculate HANDSHAKE_AUTH, we dump the cell in bytes, and then derive
+       the MAC from it. */
+    uint8_t cell_bytes_tmp[RELAY_PAYLOAD_SIZE] = {0};
+    char mac[TRUNNEL_SHA3_256_LEN];
+
+    encoded_len = hs_cell_establish_intro_encode(cell_bytes_tmp,
+                                                 sizeof(cell_bytes_tmp),
+                                                 cell);
+    if (encoded_len < 0) {
+      log_warn(LD_OR, "Unable to pre-encode ESTABLISH_INTRO cell.");
+      goto err;
+    }
+
+    /* sanity check */
+    tor_assert(encoded_len > ED25519_SIG_LEN + 2 + TRUNNEL_SHA3_256_LEN);
+
+    /* Calculate MAC of all fields before HANDSHAKE_AUTH */
+    crypto_mac_sha3_256(mac, sizeof(mac),
+                        circuit_key_material, circuit_key_material_len,
+                        (const char*)cell_bytes_tmp,
+                        encoded_len - (ED25519_SIG_LEN + 2 + TRUNNEL_SHA3_256_LEN));
+    /* Write the MAC to the cell */
+    uint8_t *handshake_ptr =
+      hs_cell_establish_intro_getarray_handshake_mac(cell);
+    memcpy(handshake_ptr, mac, sizeof(mac));
+  }
+
+  /* Calculate the cell signature */
+  {
+    /* To calculate the sig we follow the same procedure as above. We first
+       dump the cell up to the sig, and then calculate the sig */
+    uint8_t cell_bytes_tmp[RELAY_PAYLOAD_SIZE] = {0};
+    ed25519_signature_t sig;
+
+    encoded_len = hs_cell_establish_intro_encode(cell_bytes_tmp,
+                                                 sizeof(cell_bytes_tmp),
+                                                 cell);
+    if (encoded_len < 0) {
+      log_warn(LD_OR, "Unable to pre-encode ESTABLISH_INTRO cell (2).");
+      goto err;
+    }
+
+    tor_assert(encoded_len > ED25519_SIG_LEN);
+
+    if (ed25519_sign_prefixed(&sig,
+                              (uint8_t*) cell_bytes_tmp,
+                              encoded_len - ED25519_SIG_LEN,
+                              ESTABLISH_INTRO_SIG_PREFIX,
+                              &key_struct)) {
+      log_warn(LD_BUG, "Unable to gen signature for ESTABLISH_INTRO cell.");
+      goto err;
+    }
+
+    /* And write the signature to the cell */
+    uint8_t *sig_ptr = hs_cell_establish_intro_getarray_sig(cell);
+    memcpy(sig_ptr, sig.sig, sig_len);
+  }
+
+  /* We are done! Return the cell! */
+  return cell;
+
+ err:
+  hs_cell_establish_intro_free(cell);
+  return NULL;
+}
+
+#endif /* TOR_UNIT_TESTS */
diff --git a/src/or/hs_service.h b/src/or/hs_service.h
new file mode 100644
index 0000000..4a76007
--- /dev/null
+++ b/src/or/hs_service.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file hs_service.h
+ * \brief Header file for hs_service.c.
+ **/
+
+#ifndef TOR_HS_SERVICE_H
+#define TOR_HS_SERVICE_H
+
+#include "or.h"
+#include "hs/cell_establish_intro.h"
+
+#ifdef HS_SERVICE_PRIVATE
+
+#ifdef TOR_UNIT_TESTS
+
+STATIC hs_cell_establish_intro_t *
+generate_establish_intro_cell(const char *circuit_key_material,
+                              size_t circuit_key_material_len);
+
+STATIC ssize_t
+get_establish_intro_payload(uint8_t *buf, size_t buf_len,
+                            const hs_cell_establish_intro_t *cell);
+
+#endif /* TOR_UNIT_TESTS */
+
+#endif /* HS_SERVICE_PRIVATE */
+
+#endif /* TOR_HS_SERVICE_H */





More information about the tor-commits mailing list