diff options
author | David Goulet <dgoulet@torproject.org> | 2017-02-06 12:26:36 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-08-08 20:29:33 -0400 |
commit | 9052530bdde9f03da883dfb70fe261ea7d0e1b4d (patch) | |
tree | 1e96d47b71da1cd4809a925d95aeecc723c72866 | |
parent | 44e3255c4df78828110cec360031a616c6d8d0fa (diff) | |
download | tor-9052530bdde9f03da883dfb70fe261ea7d0e1b4d.tar.gz tor-9052530bdde9f03da883dfb70fe261ea7d0e1b4d.zip |
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 <dgoulet@torproject.org>
-rw-r--r-- | src/or/hs_common.c | 110 | ||||
-rw-r--r-- | src/or/hs_common.h | 27 | ||||
-rw-r--r-- | 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 f6adad30cc..9d42c8f105 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 a6c9994ef9..ae9c4e36a5 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 4a7cb81140..174d07f488 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 */ |