commit 9052530bdde9f03da883dfb70fe261ea7d0e1b4d
Author: David Goulet <dgou...@torproject.org>
Date:   Mon Feb 6 12:26:36 2017 -0500

    prop224: API for the creation of blinded keys
    
    Add a function for both the client and service side that is building a 
blinded
    key from a keypair (service) and from a public key (client). Those two
    functions uses the current time period information to build the key.
    
    Signed-off-by: David Goulet <dgou...@torproject.org>
---
 src/or/hs_common.c         | 110 +++++++++++++++++++++++++++++++++++++++++++--
 src/or/hs_common.h         |  27 ++++++++++-
 src/test/test_hs_service.c |   6 +--
 3 files changed, 136 insertions(+), 7 deletions(-)

diff --git a/src/or/hs_common.c b/src/or/hs_common.c
index f6adad30c..9d42c8f10 100644
--- a/src/or/hs_common.c
+++ b/src/or/hs_common.c
@@ -20,6 +20,14 @@
 #include "hs_service.h"
 #include "rendcommon.h"
 
+/* Ed25519 Basepoint value. Taken from section 5 of
+ * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03 */
+static const char *str_ed25519_basepoint =
+  "(15112221349535400772501151409588531511"
+  "454012693041857206046113283949847762202, "
+  "463168356949264781694283940034751631413"
+  "07993866256225615783033603165251855960)";
+
 /* Allocate and return a string containing the path to filename in directory.
  * This function will never return NULL. The caller must free this path. */
 char *
@@ -83,8 +91,8 @@ get_time_period_length(void)
 }
 
 /** Get the HS time period number at time <b>now</b> */
-STATIC uint64_t
-get_time_period_num(time_t now)
+uint64_t
+hs_get_time_period_num(time_t now)
 {
   uint64_t time_period_num;
   uint64_t time_period_length = get_time_period_length();
@@ -105,7 +113,7 @@ get_time_period_num(time_t now)
 uint64_t
 hs_get_next_time_period_num(time_t now)
 {
-  return get_time_period_num(now) + 1;
+  return hs_get_time_period_num(now) + 1;
 }
 
 /* Create a new rend_data_t for a specific given <b>version</b>.
@@ -360,6 +368,56 @@ rend_data_get_pk_digest(const rend_data_t *rend_data, 
size_t *len_out)
   }
 }
 
+/* When creating a blinded key, we need a parameter which construction is as
+ * follow: H(pubkey | [secret] | ed25519-basepoint | nonce).
+ *
+ * The nonce has a pre-defined format which uses the time period number
+ * period_num and the start of the period in second start_time_period.
+ *
+ * The secret of size secret_len is optional meaning that it can be NULL and
+ * thus will be ignored for the param construction.
+ *
+ * The result is put in param_out. */
+static void
+build_blinded_key_param(const ed25519_public_key_t *pubkey,
+                        const uint8_t *secret, size_t secret_len,
+                        uint64_t period_num, uint64_t start_time_period,
+                        uint8_t *param_out)
+{
+  size_t offset = 0;
+  uint8_t nonce[HS_KEYBLIND_NONCE_LEN];
+  crypto_digest_t *digest;
+
+  tor_assert(pubkey);
+  tor_assert(param_out);
+
+  /* Create the nonce N. The construction is as follow:
+   *    N = "key-blind" || INT_8(period_num) || INT_8(start_period_sec) */
+  memcpy(nonce, HS_KEYBLIND_NONCE_PREFIX, HS_KEYBLIND_NONCE_PREFIX_LEN);
+  offset += HS_KEYBLIND_NONCE_PREFIX_LEN;
+  set_uint64(nonce + offset, period_num);
+  offset += sizeof(uint64_t);
+  set_uint64(nonce + offset, start_time_period);
+  offset += sizeof(uint64_t);
+  tor_assert(offset == HS_KEYBLIND_NONCE_LEN);
+
+  /* Generate the parameter h and the construction is as follow:
+   *    h = H(pubkey | [secret] | ed25519-basepoint | nonce) */
+  digest = crypto_digest256_new(DIGEST_SHA3_256);
+  crypto_digest_add_bytes(digest, (char *) pubkey, ED25519_PUBKEY_LEN);
+  /* Optional secret. */
+  if (secret) {
+    crypto_digest_add_bytes(digest, (char *) secret, secret_len);
+  }
+  crypto_digest_add_bytes(digest, str_ed25519_basepoint,
+                          strlen(str_ed25519_basepoint));
+  crypto_digest_add_bytes(digest, (char *) nonce, sizeof(nonce));
+
+  /* Extract digest and put it in the param. */
+  crypto_digest_get_digest(digest, (char *) param_out, DIGEST256_LEN);
+  crypto_digest_free(digest);
+}
+
 /* Using an ed25519 public key and version to build the checksum of an
  * address. Put in checksum_out. Format is:
  *    SHA3-256(".onion checksum" || PUBKEY || VERSION)
@@ -559,6 +617,52 @@ hs_link_specifier_dup(const link_specifier_t *lspec)
   return dup;
 }
 
+/* From a given ed25519 public key pk and an optional secret, compute a
+ * blinded public key and put it in blinded_pk_out. This is only useful to
+ * the client side because the client only has access to the identity public
+ * key of the service. */
+void
+hs_build_blinded_pubkey(const ed25519_public_key_t *pk,
+                        const uint8_t *secret, size_t secret_len,
+                        uint64_t time_period_num,
+                        ed25519_public_key_t *blinded_pk_out)
+{
+  /* Our blinding key API requires a 32 bytes parameter. */
+  uint8_t param[DIGEST256_LEN];
+
+  tor_assert(pk);
+  tor_assert(blinded_pk_out);
+  tor_assert(!tor_mem_is_zero((char *) pk, ED25519_PUBKEY_LEN));
+
+  build_blinded_key_param(pk, secret, secret_len,
+                          time_period_num, get_time_period_length(), param);
+  ed25519_public_blind(blinded_pk_out, pk, param);
+}
+
+/* From a given ed25519 keypair kp and an optional secret, compute a blinded
+ * keypair for the current time period and put it in blinded_kp_out. This is
+ * only useful by the service side because the client doesn't have access to
+ * the identity secret key. */
+void
+hs_build_blinded_keypair(const ed25519_keypair_t *kp,
+                         const uint8_t *secret, size_t secret_len,
+                         uint64_t time_period_num,
+                         ed25519_keypair_t *blinded_kp_out)
+{
+  /* Our blinding key API requires a 32 bytes parameter. */
+  uint8_t param[DIGEST256_LEN];
+
+  tor_assert(kp);
+  tor_assert(blinded_kp_out);
+  /* Extra safety. A zeroed key is bad. */
+  tor_assert(!tor_mem_is_zero((char *) &kp->pubkey, ED25519_PUBKEY_LEN));
+  tor_assert(!tor_mem_is_zero((char *) &kp->seckey, ED25519_SECKEY_LEN));
+
+  build_blinded_key_param(&kp->pubkey, secret, secret_len,
+                          time_period_num, get_time_period_length(), param);
+  ed25519_keypair_blind(blinded_kp_out, kp, param);
+}
+
 /* Initialize the entire HS subsytem. This is called in tor_init() before any
  * torrc options are loaded. Only for >= v3. */
 void
diff --git a/src/or/hs_common.h b/src/or/hs_common.h
index a6c9994ef..ae9c4e36a 100644
--- a/src/or/hs_common.h
+++ b/src/or/hs_common.h
@@ -79,6 +79,22 @@
 #define HS_SERVICE_ADDR_LEN_BASE32 \
   (CEIL_DIV(HS_SERVICE_ADDR_LEN * 8, 5))
 
+/* The default HS time period length */
+#define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */
+/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+#define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */
+/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+#define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */
+/* The time period rotation offset as seen in prop224 section [TIME-PERIODS] */
+#define HS_TIME_PERIOD_ROTATION_OFFSET (12 * 60) /* minutes */
+
+/* Keyblinding parameter construction is as follow:
+ *    "key-blind" || INT_8(period_num) || INT_8(start_period_sec) */
+#define HS_KEYBLIND_NONCE_PREFIX "key-blind"
+#define HS_KEYBLIND_NONCE_PREFIX_LEN (sizeof(HS_KEYBLIND_NONCE_PREFIX) - 1)
+#define HS_KEYBLIND_NONCE_LEN \
+  (HS_KEYBLIND_NONCE_PREFIX_LEN + sizeof(uint64_t) + sizeof(uint64_t))
+
 /* Type of authentication key used by an introduction point. */
 typedef enum {
   HS_AUTH_KEY_TYPE_LEGACY  = 1,
@@ -98,6 +114,15 @@ int hs_address_is_valid(const char *address);
 int hs_parse_address(const char *address, ed25519_public_key_t *key_out,
                      uint8_t *checksum_out, uint8_t *version_out);
 
+void hs_build_blinded_pubkey(const ed25519_public_key_t *pubkey,
+                             const uint8_t *secret, size_t secret_len,
+                             uint64_t time_period_num,
+                             ed25519_public_key_t *pubkey_out);
+void hs_build_blinded_keypair(const ed25519_keypair_t *kp,
+                              const uint8_t *secret, size_t secret_len,
+                              uint64_t time_period_num,
+                              ed25519_keypair_t *kp_out);
+
 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,
@@ -114,6 +139,7 @@ const char *rend_data_get_desc_id(const rend_data_t 
*rend_data,
 const uint8_t *rend_data_get_pk_digest(const rend_data_t *rend_data,
                                        size_t *len_out);
 
+uint64_t hs_get_time_period_num(time_t now);
 uint64_t hs_get_next_time_period_num(time_t now);
 
 link_specifier_t *hs_link_specifier_dup(const link_specifier_t *lspec);
@@ -123,7 +149,6 @@ link_specifier_t *hs_link_specifier_dup(const 
link_specifier_t *lspec);
 #ifdef TOR_UNIT_TESTS
 
 STATIC uint64_t get_time_period_length(void);
-STATIC uint64_t get_time_period_num(time_t now);
 
 #endif /* TOR_UNIT_TESTS */
 
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 4a7cb8114..174d07f48 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -330,18 +330,18 @@ test_time_period(void *arg)
   tt_int_op(retval, ==, 0);
 
   /* Check that the time period number is right */
-  tn = get_time_period_num(fake_time);
+  tn = hs_get_time_period_num(fake_time);
   tt_u64_op(tn, ==, 16903);
 
   /* Increase current time to 11:59:59 UTC and check that the time period
      number is still the same */
   fake_time += 3599;
-  tn = get_time_period_num(fake_time);
+  tn = hs_get_time_period_num(fake_time);
   tt_u64_op(tn, ==, 16903);
 
   /* Now take time to 12:00:00 UTC and check that the time period rotated */
   fake_time += 1;
-  tn = get_time_period_num(fake_time);
+  tn = hs_get_time_period_num(fake_time);
   tt_u64_op(tn, ==, 16904);
 
   /* Now also check our hs_get_next_time_period_num() function */



_______________________________________________
tor-commits mailing list
tor-commits@lists.torproject.org
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to