aboutsummaryrefslogtreecommitdiff
path: root/src/feature/hs/hs_descriptor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/feature/hs/hs_descriptor.c')
-rw-r--r--src/feature/hs/hs_descriptor.c595
1 files changed, 240 insertions, 355 deletions
diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c
index f74bb97ee2..c1e6553398 100644
--- a/src/feature/hs/hs_descriptor.c
+++ b/src/feature/hs/hs_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -56,6 +56,7 @@
#define HS_DESCRIPTOR_PRIVATE
#include "core/or/or.h"
+#include "app/config/config.h"
#include "trunnel/ed25519_cert.h" /* Trunnel interface. */
#include "feature/hs/hs_descriptor.h"
#include "core/or/circuitbuild.h"
@@ -102,7 +103,7 @@
#define str_desc_auth_client "auth-client"
#define str_encrypted "encrypted"
-/* Authentication supported types. */
+/** Authentication supported types. */
static const struct {
hs_desc_auth_type_t type;
const char *identifier;
@@ -112,7 +113,7 @@ static const struct {
{ 0, NULL }
};
-/* Descriptor ruleset. */
+/** Descriptor ruleset. */
static token_rule_t hs_desc_v3_token_table[] = {
T1_START(str_hs_desc, R_HS_DESCRIPTOR, EQ(1), NO_OBJ),
T1(str_lifetime, R3_DESC_LIFETIME, EQ(1), NO_OBJ),
@@ -123,7 +124,7 @@ static token_rule_t hs_desc_v3_token_table[] = {
END_OF_TABLE
};
-/* Descriptor ruleset for the superencrypted section. */
+/** Descriptor ruleset for the superencrypted section. */
static token_rule_t hs_desc_superencrypted_v3_token_table[] = {
T1_START(str_desc_auth_type, R3_DESC_AUTH_TYPE, GE(1), NO_OBJ),
T1(str_desc_auth_key, R3_DESC_AUTH_KEY, GE(1), NO_OBJ),
@@ -132,7 +133,7 @@ static token_rule_t hs_desc_superencrypted_v3_token_table[] = {
END_OF_TABLE
};
-/* Descriptor ruleset for the encrypted section. */
+/** Descriptor ruleset for the encrypted section. */
static token_rule_t hs_desc_encrypted_v3_token_table[] = {
T1_START(str_create2_formats, R3_CREATE2_FORMATS, CONCAT_ARGS, NO_OBJ),
T01(str_intro_auth_required, R3_INTRO_AUTH_REQUIRED, GE(1), NO_OBJ),
@@ -140,7 +141,7 @@ static token_rule_t hs_desc_encrypted_v3_token_table[] = {
END_OF_TABLE
};
-/* Descriptor ruleset for the introduction points section. */
+/** Descriptor ruleset for the introduction points section. */
static token_rule_t hs_desc_intro_point_v3_token_table[] = {
T1_START(str_intro_point, R3_INTRODUCTION_POINT, EQ(1), NO_OBJ),
T1N(str_ip_onion_key, R3_INTRO_ONION_KEY, GE(2), OBJ_OK),
@@ -152,7 +153,7 @@ static token_rule_t hs_desc_intro_point_v3_token_table[] = {
END_OF_TABLE
};
-/* Using a key, salt and encrypted payload, build a MAC and put it in mac_out.
+/** Using a key, salt and encrypted payload, build a MAC and put it in mac_out.
* We use SHA3-256 for the MAC computation.
* This function can't fail. */
static void
@@ -184,7 +185,7 @@ build_mac(const uint8_t *mac_key, size_t mac_key_len,
crypto_digest_free(digest);
}
-/* Using a secret data and a given decriptor object, build the secret
+/** Using a secret data and a given decriptor object, build the secret
* input needed for the KDF.
*
* secret_input = SECRET_DATA | subcredential | INT_8(revision_counter)
@@ -211,7 +212,7 @@ build_secret_input(const hs_descriptor_t *desc,
memcpy(secret_input, secret_data, secret_data_len);
offset += secret_data_len;
/* Copy subcredential. */
- memcpy(secret_input + offset, desc->subcredential, DIGEST256_LEN);
+ memcpy(secret_input + offset, desc->subcredential.subcred, DIGEST256_LEN);
offset += DIGEST256_LEN;
/* Copy revision counter value. */
set_uint64(secret_input + offset,
@@ -224,7 +225,7 @@ build_secret_input(const hs_descriptor_t *desc,
return secret_input_len;
}
-/* Do the KDF construction and put the resulting data in key_out which is of
+/** Do the KDF construction and put the resulting data in key_out which is of
* key_out_len length. It uses SHAKE-256 as specified in the spec. */
static void
build_kdf_key(const hs_descriptor_t *desc,
@@ -269,7 +270,7 @@ build_kdf_key(const hs_descriptor_t *desc,
tor_free(secret_input);
}
-/* Using the given descriptor, secret data, and salt, run it through our
+/** Using the given descriptor, secret data, and salt, run it through our
* KDF function and then extract a secret key in key_out, the IV in iv_out
* and MAC in mac_out. This function can't fail. */
static void
@@ -308,7 +309,7 @@ build_secret_key_iv_mac(const hs_descriptor_t *desc,
/* === ENCODING === */
-/* Encode the given link specifier objects into a newly allocated string.
+/** Encode the given link specifier objects into a newly allocated string.
* This can't fail so caller can always assume a valid string being
* returned. */
STATIC char *
@@ -324,12 +325,11 @@ encode_link_specifiers(const smartlist_t *specs)
link_specifier_list_set_n_spec(lslist, smartlist_len(specs));
- SMARTLIST_FOREACH_BEGIN(specs, const hs_desc_link_specifier_t *,
+ SMARTLIST_FOREACH_BEGIN(specs, const link_specifier_t *,
spec) {
- link_specifier_t *ls = hs_desc_lspec_to_trunnel(spec);
- if (ls) {
- link_specifier_list_add_spec(lslist, ls);
- }
+ link_specifier_t *ls = link_specifier_dup(spec);
+ tor_assert(ls);
+ link_specifier_list_add_spec(lslist, ls);
} SMARTLIST_FOREACH_END(spec);
{
@@ -356,7 +356,7 @@ encode_link_specifiers(const smartlist_t *specs)
return encoded_b64;
}
-/* Encode an introduction point legacy key and certificate. Return a newly
+/** Encode an introduction point legacy key and certificate. Return a newly
* allocated string with it. On failure, return NULL. */
static char *
encode_legacy_key(const hs_desc_intro_point_t *ip)
@@ -393,7 +393,7 @@ encode_legacy_key(const hs_desc_intro_point_t *ip)
return encoded;
}
-/* Encode an introduction point encryption key and certificate. Return a newly
+/** Encode an introduction point encryption key and certificate. Return a newly
* allocated string with it. On failure, return NULL. */
static char *
encode_enc_key(const hs_desc_intro_point_t *ip)
@@ -404,9 +404,7 @@ encode_enc_key(const hs_desc_intro_point_t *ip)
tor_assert(ip);
/* Base64 encode the encryption key for the "enc-key" field. */
- if (curve25519_public_to_base64(key_b64, &ip->enc_key) < 0) {
- goto done;
- }
+ curve25519_public_to_base64(key_b64, &ip->enc_key);
if (tor_cert_encode_ed22519(ip->enc_key_cert, &encoded_cert) < 0) {
goto done;
}
@@ -421,8 +419,8 @@ encode_enc_key(const hs_desc_intro_point_t *ip)
return encoded;
}
-/* Encode an introduction point onion key. Return a newly allocated string
- * with it. On failure, return NULL. */
+/** Encode an introduction point onion key. Return a newly allocated string
+ * with it. Can not fail. */
static char *
encode_onion_key(const hs_desc_intro_point_t *ip)
{
@@ -432,16 +430,13 @@ encode_onion_key(const hs_desc_intro_point_t *ip)
tor_assert(ip);
/* Base64 encode the encryption key for the "onion-key" field. */
- if (curve25519_public_to_base64(key_b64, &ip->onion_key) < 0) {
- goto done;
- }
+ curve25519_public_to_base64(key_b64, &ip->onion_key);
tor_asprintf(&encoded, "%s ntor %s", str_ip_onion_key, key_b64);
- done:
return encoded;
}
-/* Encode an introduction point object and return a newly allocated string
+/** Encode an introduction point object and return a newly allocated string
* with it. On failure, return NULL. */
static char *
encode_intro_point(const ed25519_public_key_t *sig_key,
@@ -511,7 +506,7 @@ encode_intro_point(const ed25519_public_key_t *sig_key,
return encoded_ip;
}
-/* Given a source length, return the new size including padding for the
+/** Given a source length, return the new size including padding for the
* plaintext encryption. */
static size_t
compute_padded_plaintext_length(size_t plaintext_len)
@@ -531,7 +526,7 @@ compute_padded_plaintext_length(size_t plaintext_len)
return plaintext_padded_len;
}
-/* Given a buffer, pad it up to the encrypted section padding requirement. Set
+/** Given a buffer, pad it up to the encrypted section padding requirement. Set
* the newly allocated string in padded_out and return the length of the
* padded buffer. */
STATIC size_t
@@ -554,7 +549,7 @@ build_plaintext_padding(const char *plaintext, size_t plaintext_len,
return padded_len;
}
-/* Using a key, IV and plaintext data of length plaintext_len, create the
+/** Using a key, IV and plaintext data of length plaintext_len, create the
* encrypted section by encrypting it and setting encrypted_out with the
* data. Return size of the encrypted data buffer. */
static size_t
@@ -599,7 +594,7 @@ build_encrypted(const uint8_t *key, const uint8_t *iv, const char *plaintext,
return encrypted_len;
}
-/* Encrypt the given <b>plaintext</b> buffer using <b>desc</b> and
+/** Encrypt the given <b>plaintext</b> buffer using <b>desc</b> and
* <b>secret_data</b> to get the keys. Set encrypted_out with the encrypted
* data and return the length of it. <b>is_superencrypted_layer</b> is set
* if this is the outer encrypted layer of the descriptor. */
@@ -669,7 +664,7 @@ encrypt_descriptor_data(const hs_descriptor_t *desc,
return final_blob_len;
}
-/* Create and return a string containing a client-auth entry. It's the
+/** Create and return a string containing a client-auth entry. It's the
* responsibility of the caller to free the returned string. This function
* will never fail. */
static char *
@@ -684,7 +679,7 @@ get_auth_client_str(const hs_desc_authorized_client_t *client)
char encrypted_cookie_b64[HS_DESC_ENCRYPED_COOKIE_LEN * 2];
#define ASSERT_AND_BASE64(field) STMT_BEGIN \
- tor_assert(!tor_mem_is_zero((char *) client->field, \
+ tor_assert(!fast_mem_is_zero((char *) client->field, \
sizeof(client->field))); \
ret = base64_encode_nopad(field##_b64, sizeof(field##_b64), \
client->field, sizeof(client->field)); \
@@ -739,7 +734,7 @@ get_all_auth_client_lines(const hs_descriptor_t *desc)
return auth_client_lines_str;
}
-/* Create the inner layer of the descriptor (which includes the intro points,
+/** Create the inner layer of the descriptor (which includes the intro points,
* etc.). Return a newly-allocated string with the layer plaintext, or NULL if
* an error occurred. It's the responsibility of the caller to free the
* returned string. */
@@ -795,11 +790,11 @@ get_inner_encrypted_layer_plaintext(const hs_descriptor_t *desc)
return encoded_str;
}
-/* Create the middle layer of the descriptor, which includes the client auth
+/** Create the middle layer of the descriptor, which includes the client auth
* data and the encrypted inner layer (provided as a base64 string at
* <b>layer2_b64_ciphertext</b>). Return a newly-allocated string with the
- * layer plaintext, or NULL if an error occurred. It's the responsibility of
- * the caller to free the returned string. */
+ * layer plaintext. It's the responsibility of the caller to free the returned
+ * string. Can not fail. */
static char *
get_outer_encrypted_layer_plaintext(const hs_descriptor_t *desc,
const char *layer2_b64_ciphertext)
@@ -815,13 +810,10 @@ get_outer_encrypted_layer_plaintext(const hs_descriptor_t *desc,
const curve25519_public_key_t *ephemeral_pubkey;
ephemeral_pubkey = &desc->superencrypted_data.auth_ephemeral_pubkey;
- tor_assert(!tor_mem_is_zero((char *) ephemeral_pubkey->public_key,
+ tor_assert(!fast_mem_is_zero((char *) ephemeral_pubkey->public_key,
CURVE25519_PUBKEY_LEN));
- if (curve25519_public_to_base64(ephemeral_key_base64,
- ephemeral_pubkey) < 0) {
- goto done;
- }
+ curve25519_public_to_base64(ephemeral_key_base64, ephemeral_pubkey);
smartlist_add_asprintf(lines, "%s %s\n",
str_desc_auth_key, ephemeral_key_base64);
@@ -846,7 +838,6 @@ get_outer_encrypted_layer_plaintext(const hs_descriptor_t *desc,
layer1_str = smartlist_join_strings(lines, "", 0, NULL);
- done:
/* We need to memwipe all lines because it contains the ephemeral key */
SMARTLIST_FOREACH(lines, char *, a, memwipe(a, 0, strlen(a)));
SMARTLIST_FOREACH(lines, char *, a, tor_free(a));
@@ -855,7 +846,7 @@ get_outer_encrypted_layer_plaintext(const hs_descriptor_t *desc,
return layer1_str;
}
-/* Encrypt <b>encoded_str</b> into an encrypted blob and then base64 it before
+/** Encrypt <b>encoded_str</b> into an encrypted blob and then base64 it before
* returning it. <b>desc</b> is provided to derive the encryption
* keys. <b>secret_data</b> is also proved to derive the encryption keys.
* <b>is_superencrypted_layer</b> is set if <b>encoded_str</b> is the
@@ -888,7 +879,7 @@ encrypt_desc_data_and_base64(const hs_descriptor_t *desc,
return enc_b64;
}
-/* Generate the secret data which is used to encrypt/decrypt the descriptor.
+/** Generate the secret data which is used to encrypt/decrypt the descriptor.
*
* SECRET_DATA = blinded-public-key
* SECRET_DATA = blinded-public-key | descriptor_cookie
@@ -935,7 +926,7 @@ build_secret_data(const ed25519_public_key_t *blinded_pubkey,
return secret_data_len;
}
-/* Generate and encode the superencrypted portion of <b>desc</b>. This also
+/** Generate and encode the superencrypted portion of <b>desc</b>. This also
* involves generating the encrypted portion of the descriptor, and performing
* the superencryption. A newly allocated NUL-terminated string pointer
* containing the encrypted encoded blob is put in encrypted_blob_out. Return 0
@@ -1009,7 +1000,7 @@ encode_superencrypted_data(const hs_descriptor_t *desc,
return ret;
}
-/* Encode a v3 HS descriptor. Return 0 on success and set encoded_out to the
+/** Encode a v3 HS descriptor. Return 0 on success and set encoded_out to the
* newly allocated string of the encoded descriptor. On error, -1 is returned
* and encoded_out is untouched. */
static int
@@ -1028,10 +1019,6 @@ desc_encode_v3(const hs_descriptor_t *desc,
tor_assert(encoded_out);
tor_assert(desc->plaintext_data.version == 3);
- if (BUG(desc->subcredential == NULL)) {
- goto err;
- }
-
/* Build the non-encrypted values. */
{
char *encoded_cert;
@@ -1092,11 +1079,7 @@ desc_encode_v3(const hs_descriptor_t *desc,
tor_free(encoded_str);
goto err;
}
- if (ed25519_signature_to_base64(ed_sig_b64, &sig) < 0) {
- log_warn(LD_BUG, "Can't base64 encode descriptor signature!");
- tor_free(encoded_str);
- goto err;
- }
+ ed25519_signature_to_base64(ed_sig_b64, &sig);
/* Create the signature line. */
smartlist_add_asprintf(lines, "%s %s", str_signature, ed_sig_b64);
}
@@ -1125,7 +1108,7 @@ desc_encode_v3(const hs_descriptor_t *desc,
/* === DECODING === */
-/* Given the token tok for an auth client, decode it as
+/** Given the token tok for an auth client, decode it as
* hs_desc_authorized_client_t. tok->args MUST contain at least 3 elements
* Return 0 on success else -1 on failure. */
static int
@@ -1161,7 +1144,7 @@ decode_auth_client(const directory_token_t *tok,
return ret;
}
-/* Given an encoded string of the link specifiers, return a newly allocated
+/** Given an encoded string of the link specifiers, return a newly allocated
* list of decoded link specifiers. Return NULL on error. */
STATIC smartlist_t *
decode_link_specifiers(const char *encoded)
@@ -1190,52 +1173,22 @@ decode_link_specifiers(const char *encoded)
results = smartlist_new();
for (i = 0; i < link_specifier_list_getlen_spec(specs); i++) {
- hs_desc_link_specifier_t *hs_spec;
link_specifier_t *ls = link_specifier_list_get_spec(specs, i);
- tor_assert(ls);
-
- hs_spec = tor_malloc_zero(sizeof(*hs_spec));
- hs_spec->type = link_specifier_get_ls_type(ls);
- switch (hs_spec->type) {
- case LS_IPV4:
- tor_addr_from_ipv4h(&hs_spec->u.ap.addr,
- link_specifier_get_un_ipv4_addr(ls));
- hs_spec->u.ap.port = link_specifier_get_un_ipv4_port(ls);
- break;
- case LS_IPV6:
- tor_addr_from_ipv6_bytes(&hs_spec->u.ap.addr, (const char *)
- link_specifier_getarray_un_ipv6_addr(ls));
- hs_spec->u.ap.port = link_specifier_get_un_ipv6_port(ls);
- break;
- case LS_LEGACY_ID:
- /* Both are known at compile time so let's make sure they are the same
- * else we can copy memory out of bound. */
- tor_assert(link_specifier_getlen_un_legacy_id(ls) ==
- sizeof(hs_spec->u.legacy_id));
- memcpy(hs_spec->u.legacy_id, link_specifier_getarray_un_legacy_id(ls),
- sizeof(hs_spec->u.legacy_id));
- break;
- case LS_ED25519_ID:
- /* Both are known at compile time so let's make sure they are the same
- * else we can copy memory out of bound. */
- tor_assert(link_specifier_getlen_un_ed25519_id(ls) ==
- sizeof(hs_spec->u.ed25519_id));
- memcpy(hs_spec->u.ed25519_id,
- link_specifier_getconstarray_un_ed25519_id(ls),
- sizeof(hs_spec->u.ed25519_id));
- break;
- default:
- tor_free(hs_spec);
+ if (BUG(!ls)) {
goto err;
}
-
- smartlist_add(results, hs_spec);
+ link_specifier_t *ls_dup = link_specifier_dup(ls);
+ if (BUG(!ls_dup)) {
+ goto err;
+ }
+ smartlist_add(results, ls_dup);
}
goto done;
err:
if (results) {
- SMARTLIST_FOREACH(results, hs_desc_link_specifier_t *, s, tor_free(s));
+ SMARTLIST_FOREACH(results, link_specifier_t *, s,
+ link_specifier_free(s));
smartlist_free(results);
results = NULL;
}
@@ -1245,7 +1198,7 @@ decode_link_specifiers(const char *encoded)
return results;
}
-/* Given a list of authentication types, decode it and put it in the encrypted
+/** Given a list of authentication types, decode it and put it in the encrypted
* data section. Return 1 if we at least know one of the type or 0 if we know
* none of them. */
static int
@@ -1273,7 +1226,7 @@ decode_auth_type(hs_desc_encrypted_data_t *desc, const char *list)
return match;
}
-/* Parse a space-delimited list of integers representing CREATE2 formats into
+/** Parse a space-delimited list of integers representing CREATE2 formats into
* the bitfield in hs_desc_encrypted_data_t. Ignore unrecognized values. */
static void
decode_create2_list(hs_desc_encrypted_data_t *desc, const char *list)
@@ -1307,7 +1260,7 @@ decode_create2_list(hs_desc_encrypted_data_t *desc, const char *list)
smartlist_free(tokens);
}
-/* Given a certificate, validate the certificate for certain conditions which
+/** Given a certificate, validate the certificate for certain conditions which
* are if the given type matches the cert's one, if the signing key is
* included and if the that key was actually used to sign the certificate.
*
@@ -1331,11 +1284,20 @@ cert_is_valid(tor_cert_t *cert, uint8_t type, const char *log_obj_type)
log_warn(LD_REND, "Signing key is NOT included for %s.", log_obj_type);
goto err;
}
+
/* The following will not only check if the signature matches but also the
* expiration date and overall validity. */
if (tor_cert_checksig(cert, &cert->signing_key, approx_time()) < 0) {
- log_warn(LD_REND, "Invalid signature for %s: %s", log_obj_type,
- tor_cert_describe_signature_status(cert));
+ if (cert->cert_expired) {
+ char expiration_str[ISO_TIME_LEN+1];
+ format_iso_time(expiration_str, cert->valid_until);
+ log_fn(LOG_PROTOCOL_WARN, LD_REND, "Invalid signature for %s: %s (%s)",
+ log_obj_type, tor_cert_describe_signature_status(cert),
+ expiration_str);
+ } else {
+ log_warn(LD_REND, "Invalid signature for %s: %s",
+ log_obj_type, tor_cert_describe_signature_status(cert));
+ }
goto err;
}
@@ -1344,7 +1306,7 @@ cert_is_valid(tor_cert_t *cert, uint8_t type, const char *log_obj_type)
return 0;
}
-/* Given some binary data, try to parse it to get a certificate object. If we
+/** Given some binary data, try to parse it to get a certificate object. If we
* have a valid cert, validate it using the given wanted type. On error, print
* a log using the err_msg has the certificate identifier adding semantic to
* the log and cert_out is set to NULL. On success, 0 is returned and cert_out
@@ -1381,7 +1343,7 @@ cert_parse_and_validate(tor_cert_t **cert_out, const char *data,
return -1;
}
-/* Return true iff the given length of the encrypted data of a descriptor
+/** Return true iff the given length of the encrypted data of a descriptor
* passes validation. */
STATIC int
encrypted_data_length_is_valid(size_t len)
@@ -1400,7 +1362,50 @@ encrypted_data_length_is_valid(size_t len)
return 0;
}
-/* Decrypt the descriptor cookie given the descriptor, the auth client,
+/** Build the KEYS component for the authorized client computation. The format
+ * of the construction is:
+ *
+ * SECRET_SEED = x25519(sk, pk)
+ * KEYS = KDF(subcredential | SECRET_SEED, 40)
+ *
+ * Set the <b>keys_out</b> argument to point to the buffer containing the KEYS,
+ * and return the buffer's length. The caller should wipe and free its content
+ * once done with it. This function can't fail. */
+static size_t
+build_descriptor_cookie_keys(const hs_subcredential_t *subcredential,
+ const curve25519_secret_key_t *sk,
+ const curve25519_public_key_t *pk,
+ uint8_t **keys_out)
+{
+ uint8_t secret_seed[CURVE25519_OUTPUT_LEN];
+ uint8_t *keystream;
+ size_t keystream_len = HS_DESC_CLIENT_ID_LEN + HS_DESC_COOKIE_KEY_LEN;
+ crypto_xof_t *xof;
+
+ tor_assert(subcredential);
+ tor_assert(sk);
+ tor_assert(pk);
+ tor_assert(keys_out);
+
+ keystream = tor_malloc_zero(keystream_len);
+
+ /* Calculate x25519(sk, pk) to get the secret seed. */
+ curve25519_handshake(secret_seed, sk, pk);
+
+ /* Calculate KEYS = KDF(subcredential | SECRET_SEED, 40) */
+ xof = crypto_xof_new();
+ crypto_xof_add_bytes(xof, subcredential->subcred, SUBCRED_LEN);
+ crypto_xof_add_bytes(xof, secret_seed, sizeof(secret_seed));
+ crypto_xof_squeeze_bytes(xof, keystream, keystream_len);
+ crypto_xof_free(xof);
+
+ memwipe(secret_seed, 0, sizeof(secret_seed));
+
+ *keys_out = keystream;
+ return keystream_len;
+}
+
+/** Decrypt the descriptor cookie given the descriptor, the auth client,
* and the client secret key. On sucess, return 0 and a newly allocated
* descriptor cookie descriptor_cookie_out. On error or if the client id
* is invalid, return -1 and descriptor_cookie_out is set to
@@ -1412,33 +1417,34 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
uint8_t **descriptor_cookie_out)
{
int ret = -1;
- uint8_t secret_seed[CURVE25519_OUTPUT_LEN];
- uint8_t keystream[HS_DESC_CLIENT_ID_LEN + HS_DESC_COOKIE_KEY_LEN];
- uint8_t *cookie_key = NULL;
+ uint8_t *keystream = NULL;
+ size_t keystream_length = 0;
uint8_t *descriptor_cookie = NULL;
+ const uint8_t *cookie_key = NULL;
crypto_cipher_t *cipher = NULL;
- crypto_xof_t *xof = NULL;
tor_assert(desc);
tor_assert(client);
tor_assert(client_auth_sk);
- tor_assert(!tor_mem_is_zero(
+ tor_assert(!fast_mem_is_zero(
(char *) &desc->superencrypted_data.auth_ephemeral_pubkey,
sizeof(desc->superencrypted_data.auth_ephemeral_pubkey)));
- tor_assert(!tor_mem_is_zero((char *) client_auth_sk,
- sizeof(*client_auth_sk)));
- tor_assert(!tor_mem_is_zero((char *) desc->subcredential, DIGEST256_LEN));
+ tor_assert(!fast_mem_is_zero((char *) desc->subcredential.subcred,
+ DIGEST256_LEN));
- /* Calculate x25519(client_x, hs_Y) */
- curve25519_handshake(secret_seed, client_auth_sk,
- &desc->superencrypted_data.auth_ephemeral_pubkey);
+ /* Catch potential code-flow cases of an unitialized private key sneaking
+ * into this function. */
+ if (BUG(fast_mem_is_zero((char *)client_auth_sk, sizeof(*client_auth_sk)))) {
+ goto done;
+ }
- /* Calculate KEYS = KDF(subcredential | SECRET_SEED, 40) */
- xof = crypto_xof_new();
- crypto_xof_add_bytes(xof, desc->subcredential, DIGEST256_LEN);
- crypto_xof_add_bytes(xof, secret_seed, sizeof(secret_seed));
- crypto_xof_squeeze_bytes(xof, keystream, sizeof(keystream));
- crypto_xof_free(xof);
+ /* Get the KEYS component to derive the CLIENT-ID and COOKIE-KEY. */
+ keystream_length =
+ build_descriptor_cookie_keys(&desc->subcredential,
+ client_auth_sk,
+ &desc->superencrypted_data.auth_ephemeral_pubkey,
+ &keystream);
+ tor_assert(keystream_length > 0);
/* If the client id of auth client is not the same as the calculcated
* client id, it means that this auth client is invaild according to the
@@ -1464,8 +1470,8 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
if (cipher) {
crypto_cipher_free(cipher);
}
- memwipe(secret_seed, 0, sizeof(secret_seed));
- memwipe(keystream, 0, sizeof(keystream));
+ memwipe(keystream, 0, keystream_length);
+ tor_free(keystream);
return ret;
}
@@ -1481,10 +1487,8 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
*/
MOCK_IMPL(STATIC size_t,
decrypt_desc_layer,(const hs_descriptor_t *desc,
- const uint8_t *encrypted_blob,
- size_t encrypted_blob_size,
const uint8_t *descriptor_cookie,
- int is_superencrypted_layer,
+ bool is_superencrypted_layer,
char **decrypted_out))
{
uint8_t *decrypted = NULL;
@@ -1494,6 +1498,12 @@ decrypt_desc_layer,(const hs_descriptor_t *desc,
uint8_t mac_key[DIGEST256_LEN], our_mac[DIGEST256_LEN];
const uint8_t *salt, *encrypted, *desc_mac;
size_t encrypted_len, result_len = 0;
+ const uint8_t *encrypted_blob = (is_superencrypted_layer)
+ ? desc->plaintext_data.superencrypted_blob
+ : desc->superencrypted_data.encrypted_blob;
+ size_t encrypted_blob_size = (is_superencrypted_layer)
+ ? desc->plaintext_data.superencrypted_blob_size
+ : desc->superencrypted_data.encrypted_blob_size;
tor_assert(decrypted_out);
tor_assert(desc);
@@ -1592,7 +1602,7 @@ decrypt_desc_layer,(const hs_descriptor_t *desc,
return result_len;
}
-/* Decrypt the superencrypted section of the descriptor using the given
+/** Decrypt the superencrypted section of the descriptor using the given
* descriptor object <b>desc</b>. A newly allocated NUL terminated string is
* put in decrypted_out which contains the superencrypted layer of the
* descriptor. Return the length of decrypted_out on success else 0 is
@@ -1607,9 +1617,8 @@ desc_decrypt_superencrypted(const hs_descriptor_t *desc, char **decrypted_out)
tor_assert(decrypted_out);
superencrypted_len = decrypt_desc_layer(desc,
- desc->plaintext_data.superencrypted_blob,
- desc->plaintext_data.superencrypted_blob_size,
- NULL, 1, &superencrypted_plaintext);
+ NULL,
+ true, &superencrypted_plaintext);
if (!superencrypted_len) {
log_warn(LD_REND, "Decrypting superencrypted desc failed.");
@@ -1625,7 +1634,7 @@ desc_decrypt_superencrypted(const hs_descriptor_t *desc, char **decrypted_out)
return superencrypted_len;
}
-/* Decrypt the encrypted section of the descriptor using the given descriptor
+/** Decrypt the encrypted section of the descriptor using the given descriptor
* object <b>desc</b>. A newly allocated NUL terminated string is put in
* decrypted_out which contains the encrypted layer of the descriptor.
* Return the length of decrypted_out on success else 0 is returned and
@@ -1658,9 +1667,9 @@ desc_decrypt_encrypted(const hs_descriptor_t *desc,
}
encrypted_len = decrypt_desc_layer(desc,
- desc->superencrypted_data.encrypted_blob,
- desc->superencrypted_data.encrypted_blob_size,
- descriptor_cookie, 0, &encrypted_plaintext);
+ descriptor_cookie,
+ false, &encrypted_plaintext);
+
if (!encrypted_len) {
goto err;
}
@@ -1678,7 +1687,7 @@ desc_decrypt_encrypted(const hs_descriptor_t *desc,
return encrypted_len;
}
-/* Given the token tok for an intro point legacy key, the list of tokens, the
+/** Given the token tok for an intro point legacy key, the list of tokens, the
* introduction point ip being decoded and the descriptor desc from which it
* comes from, decode the legacy key and set the intro point object. Return 0
* on success else -1 on failure. */
@@ -1736,7 +1745,7 @@ decode_intro_legacy_key(const directory_token_t *tok,
return -1;
}
-/* Dig into the descriptor <b>tokens</b> to find the onion key we should use
+/** Dig into the descriptor <b>tokens</b> to find the onion key we should use
* for this intro point, and set it into <b>onion_key_out</b>. Return 0 if it
* was found and well-formed, otherwise return -1 in case of errors. */
static int
@@ -1780,7 +1789,7 @@ set_intro_point_onion_key(curve25519_public_key_t *onion_key_out,
return retval;
}
-/* Given the start of a section and the end of it, decode a single
+/** Given the start of a section and the end of it, decode a single
* introduction point from that section. Return a newly allocated introduction
* point object containing the decoded data. Return NULL if the section can't
* be decoded. */
@@ -1909,7 +1918,7 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start)
return ip;
}
-/* Given a descriptor string at <b>data</b>, decode all possible introduction
+/** Given a descriptor string at <b>data</b>, decode all possible introduction
* points that we can find. Add the introduction point object to desc_enc as we
* find them. This function can't fail and it is possible that zero
* introduction points can be decoded. */
@@ -1972,7 +1981,8 @@ decode_intro_points(const hs_descriptor_t *desc,
SMARTLIST_FOREACH(intro_points, char *, a, tor_free(a));
smartlist_free(intro_points);
}
-/* Return 1 iff the given base64 encoded signature in b64_sig from the encoded
+
+/** Return 1 iff the given base64 encoded signature in b64_sig from the encoded
* descriptor in encoded_desc validates the descriptor content. */
STATIC int
desc_sig_is_valid(const char *b64_sig,
@@ -2031,14 +2041,14 @@ desc_sig_is_valid(const char *b64_sig,
return ret;
}
-/* Decode descriptor plaintext data for version 3. Given a list of tokens, an
+/** Decode descriptor plaintext data for version 3. Given a list of tokens, an
* allocated plaintext object that will be populated and the encoded
* descriptor with its length. The last one is needed for signature
* verification. Unknown tokens are simply ignored so this won't error on
* unknowns but requires that all v3 token be present and valid.
*
* Return 0 on success else a negative value. */
-static int
+static hs_desc_decode_status_t
desc_decode_plaintext_v3(smartlist_t *tokens,
hs_desc_plaintext_data_t *desc,
const char *encoded_desc, size_t encoded_len)
@@ -2128,21 +2138,19 @@ desc_decode_plaintext_v3(smartlist_t *tokens,
goto err;
}
- return 0;
-
+ return HS_DESC_DECODE_OK;
err:
- return -1;
+ return HS_DESC_DECODE_PLAINTEXT_ERROR;
}
-/* Decode the version 3 superencrypted section of the given descriptor desc.
- * The desc_superencrypted_out will be populated with the decoded data.
- * Return 0 on success else -1. */
-static int
+/** Decode the version 3 superencrypted section of the given descriptor desc.
+ * The desc_superencrypted_out will be populated with the decoded data. */
+static hs_desc_decode_status_t
desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
hs_desc_superencrypted_data_t *
desc_superencrypted_out)
{
- int ret = -1;
+ int ret = HS_DESC_DECODE_SUPERENC_ERROR;
char *message = NULL;
size_t message_len;
memarea_t *area = NULL;
@@ -2228,11 +2236,11 @@ desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
tok->object_size);
superencrypted->encrypted_blob_size = tok->object_size;
- ret = 0;
+ ret = HS_DESC_DECODE_OK;
goto done;
err:
- tor_assert(ret < 0);
+ tor_assert(ret < HS_DESC_DECODE_OK);
hs_desc_superencrypted_data_free_contents(desc_superencrypted_out);
done:
@@ -2249,15 +2257,14 @@ desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
return ret;
}
-/* Decode the version 3 encrypted section of the given descriptor desc. The
- * desc_encrypted_out will be populated with the decoded data. Return 0 on
- * success else -1. */
-static int
+/** Decode the version 3 encrypted section of the given descriptor desc. The
+ * desc_encrypted_out will be populated with the decoded data. */
+static hs_desc_decode_status_t
desc_decode_encrypted_v3(const hs_descriptor_t *desc,
const curve25519_secret_key_t *client_auth_sk,
hs_desc_encrypted_data_t *desc_encrypted_out)
{
- int ret = -1;
+ int ret = HS_DESC_DECODE_ENCRYPTED_ERROR;
char *message = NULL;
size_t message_len;
memarea_t *area = NULL;
@@ -2280,12 +2287,14 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
* authorization is failing. */
log_warn(LD_REND, "Client authorization for requested onion address "
"is invalid. Can't decrypt the descriptor.");
+ ret = HS_DESC_DECODE_BAD_CLIENT_AUTH;
} else {
/* Inform at notice level that the onion address requested can't be
* reached without client authorization most likely. */
log_notice(LD_REND, "Fail to decrypt descriptor for requested onion "
"address. It is likely requiring client "
"authorization.");
+ ret = HS_DESC_DECODE_NEED_CLIENT_AUTH;
}
goto err;
}
@@ -2344,11 +2353,11 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
/* NOTE: Unknown fields are allowed because this function could be used to
* decode other descriptor version. */
- ret = 0;
+ ret = HS_DESC_DECODE_OK;
goto done;
err:
- tor_assert(ret < 0);
+ tor_assert(ret < HS_DESC_DECODE_OK);
hs_desc_encrypted_data_free_contents(desc_encrypted_out);
done:
@@ -2365,9 +2374,9 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
return ret;
}
-/* Table of encrypted decode function version specific. The function are
+/** Table of encrypted decode function version specific. The function are
* indexed by the version number so v3 callback is at index 3 in the array. */
-static int
+static hs_desc_decode_status_t
(*decode_encrypted_handlers[])(
const hs_descriptor_t *desc,
const curve25519_secret_key_t *client_auth_sk,
@@ -2377,15 +2386,15 @@ static int
desc_decode_encrypted_v3,
};
-/* Decode the encrypted data section of the given descriptor and store the
+/** Decode the encrypted data section of the given descriptor and store the
* data in the given encrypted data object. Return 0 on success else a
* negative value on error. */
-int
+hs_desc_decode_status_t
hs_desc_decode_encrypted(const hs_descriptor_t *desc,
const curve25519_secret_key_t *client_auth_sk,
hs_desc_encrypted_data_t *desc_encrypted)
{
- int ret;
+ int ret = HS_DESC_DECODE_ENCRYPTED_ERROR;
uint32_t version;
tor_assert(desc);
@@ -2399,7 +2408,6 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc,
/* Let's make sure we have a supported version as well. By correctly parsing
* the plaintext, this should not fail. */
if (BUG(!hs_desc_is_supported_version(version))) {
- ret = -1;
goto err;
}
/* Extra precaution. Having no handler for the supported version should
@@ -2418,9 +2426,9 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc,
return ret;
}
-/* Table of superencrypted decode function version specific. The function are
+/** Table of superencrypted decode function version specific. The function are
* indexed by the version number so v3 callback is at index 3 in the array. */
-static int
+static hs_desc_decode_status_t
(*decode_superencrypted_handlers[])(
const hs_descriptor_t *desc,
hs_desc_superencrypted_data_t *desc_superencrypted) =
@@ -2429,15 +2437,14 @@ static int
desc_decode_superencrypted_v3,
};
-/* Decode the superencrypted data section of the given descriptor and store the
- * data in the given superencrypted data object. Return 0 on success else a
- * negative value on error. */
-int
+/** Decode the superencrypted data section of the given descriptor and store
+ * the data in the given superencrypted data object. */
+hs_desc_decode_status_t
hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
hs_desc_superencrypted_data_t *
desc_superencrypted)
{
- int ret;
+ int ret = HS_DESC_DECODE_SUPERENC_ERROR;
uint32_t version;
tor_assert(desc);
@@ -2451,7 +2458,6 @@ hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
/* Let's make sure we have a supported version as well. By correctly parsing
* the plaintext, this should not fail. */
if (BUG(!hs_desc_is_supported_version(version))) {
- ret = -1;
goto err;
}
/* Extra precaution. Having no handler for the supported version should
@@ -2469,9 +2475,9 @@ hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
return ret;
}
-/* Table of plaintext decode function version specific. The function are
+/** Table of plaintext decode function version specific. The function are
* indexed by the version number so v3 callback is at index 3 in the array. */
-static int
+static hs_desc_decode_status_t
(*decode_plaintext_handlers[])(
smartlist_t *tokens,
hs_desc_plaintext_data_t *desc,
@@ -2482,13 +2488,13 @@ static int
desc_decode_plaintext_v3,
};
-/* Fully decode the given descriptor plaintext and store the data in the
- * plaintext data object. Returns 0 on success else a negative value. */
-int
+/** Fully decode the given descriptor plaintext and store the data in the
+ * plaintext data object. */
+hs_desc_decode_status_t
hs_desc_decode_plaintext(const char *encoded,
hs_desc_plaintext_data_t *plaintext)
{
- int ok = 0, ret = -1;
+ int ok = 0, ret = HS_DESC_DECODE_PLAINTEXT_ERROR;
memarea_t *area = NULL;
smartlist_t *tokens = NULL;
size_t encoded_len;
@@ -2538,11 +2544,11 @@ hs_desc_decode_plaintext(const char *encoded,
/* Run the version specific plaintext decoder. */
ret = decode_plaintext_handlers[plaintext->version](tokens, plaintext,
encoded, encoded_len);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
/* Success. Descriptor has been populated with the data. */
- ret = 0;
+ ret = HS_DESC_DECODE_OK;
err:
if (tokens) {
@@ -2555,19 +2561,19 @@ hs_desc_decode_plaintext(const char *encoded,
return ret;
}
-/* Fully decode an encoded descriptor and set a newly allocated descriptor
+/** Fully decode an encoded descriptor and set a newly allocated descriptor
* object in desc_out. Client secret key is used to decrypt the "encrypted"
* section if not NULL else it's ignored.
*
* Return 0 on success. A negative value is returned on error and desc_out is
* set to NULL. */
-int
+hs_desc_decode_status_t
hs_desc_decode_descriptor(const char *encoded,
- const uint8_t *subcredential,
+ const hs_subcredential_t *subcredential,
const curve25519_secret_key_t *client_auth_sk,
hs_descriptor_t **desc_out)
{
- int ret = -1;
+ hs_desc_decode_status_t ret = HS_DESC_DECODE_GENERIC_ERROR;
hs_descriptor_t *desc;
tor_assert(encoded);
@@ -2576,25 +2582,25 @@ hs_desc_decode_descriptor(const char *encoded,
/* Subcredentials are not optional. */
if (BUG(!subcredential ||
- tor_mem_is_zero((char*)subcredential, DIGEST256_LEN))) {
+ fast_mem_is_zero((char*)subcredential, DIGEST256_LEN))) {
log_warn(LD_GENERAL, "Tried to decrypt without subcred. Impossible!");
goto err;
}
- memcpy(desc->subcredential, subcredential, sizeof(desc->subcredential));
+ memcpy(&desc->subcredential, subcredential, sizeof(desc->subcredential));
ret = hs_desc_decode_plaintext(encoded, &desc->plaintext_data);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
ret = hs_desc_decode_superencrypted(desc, &desc->superencrypted_data);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
ret = hs_desc_decode_encrypted(desc, client_auth_sk, &desc->encrypted_data);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
@@ -2615,7 +2621,7 @@ hs_desc_decode_descriptor(const char *encoded,
return ret;
}
-/* Table of encode function version specific. The functions are indexed by the
+/** Table of encode function version specific. The functions are indexed by the
* version number so v3 callback is at index 3 in the array. */
static int
(*encode_handlers[])(
@@ -2628,7 +2634,7 @@ static int
desc_encode_v3,
};
-/* Encode the given descriptor desc including signing with the given key pair
+/** Encode the given descriptor desc including signing with the given key pair
* signing_kp and encrypting with the given descriptor cookie.
*
* If the client authorization is enabled, descriptor_cookie must be the same
@@ -2671,9 +2677,10 @@ hs_desc_encode_descriptor,(const hs_descriptor_t *desc,
* symmetric only if the client auth is disabled. That is, the descriptor
* cookie will be NULL. */
if (!descriptor_cookie) {
- ret = hs_desc_decode_descriptor(*encoded_out, desc->subcredential,
+ ret = hs_desc_decode_descriptor(*encoded_out, &desc->subcredential,
NULL, NULL);
- if (BUG(ret < 0)) {
+ if (BUG(ret != HS_DESC_DECODE_OK)) {
+ ret = -1;
goto err;
}
}
@@ -2685,7 +2692,7 @@ hs_desc_encode_descriptor,(const hs_descriptor_t *desc,
return ret;
}
-/* Free the content of the plaintext section of a descriptor. */
+/** Free the content of the plaintext section of a descriptor. */
void
hs_desc_plaintext_data_free_contents(hs_desc_plaintext_data_t *desc)
{
@@ -2701,7 +2708,7 @@ hs_desc_plaintext_data_free_contents(hs_desc_plaintext_data_t *desc)
memwipe(desc, 0, sizeof(*desc));
}
-/* Free the content of the superencrypted section of a descriptor. */
+/** Free the content of the superencrypted section of a descriptor. */
void
hs_desc_superencrypted_data_free_contents(hs_desc_superencrypted_data_t *desc)
{
@@ -2721,7 +2728,7 @@ hs_desc_superencrypted_data_free_contents(hs_desc_superencrypted_data_t *desc)
memwipe(desc, 0, sizeof(*desc));
}
-/* Free the content of the encrypted section of a descriptor. */
+/** Free the content of the encrypted section of a descriptor. */
void
hs_desc_encrypted_data_free_contents(hs_desc_encrypted_data_t *desc)
{
@@ -2741,7 +2748,7 @@ hs_desc_encrypted_data_free_contents(hs_desc_encrypted_data_t *desc)
memwipe(desc, 0, sizeof(*desc));
}
-/* Free the descriptor plaintext data object. */
+/** Free the descriptor plaintext data object. */
void
hs_desc_plaintext_data_free_(hs_desc_plaintext_data_t *desc)
{
@@ -2749,7 +2756,7 @@ hs_desc_plaintext_data_free_(hs_desc_plaintext_data_t *desc)
tor_free(desc);
}
-/* Free the descriptor plaintext data object. */
+/** Free the descriptor plaintext data object. */
void
hs_desc_superencrypted_data_free_(hs_desc_superencrypted_data_t *desc)
{
@@ -2757,7 +2764,7 @@ hs_desc_superencrypted_data_free_(hs_desc_superencrypted_data_t *desc)
tor_free(desc);
}
-/* Free the descriptor encrypted data object. */
+/** Free the descriptor encrypted data object. */
void
hs_desc_encrypted_data_free_(hs_desc_encrypted_data_t *desc)
{
@@ -2765,7 +2772,7 @@ hs_desc_encrypted_data_free_(hs_desc_encrypted_data_t *desc)
tor_free(desc);
}
-/* Free the given descriptor object. */
+/** Free the given descriptor object. */
void
hs_descriptor_free_(hs_descriptor_t *desc)
{
@@ -2779,7 +2786,7 @@ hs_descriptor_free_(hs_descriptor_t *desc)
tor_free(desc);
}
-/* Return the size in bytes of the given plaintext data object. A sizeof() is
+/** Return the size in bytes of the given plaintext data object. A sizeof() is
* not enough because the object contains pointers and the encrypted blob.
* This is particularly useful for our OOM subsystem that tracks the HSDir
* cache size for instance. */
@@ -2791,7 +2798,7 @@ hs_desc_plaintext_obj_size(const hs_desc_plaintext_data_t *data)
data->superencrypted_blob_size);
}
-/* Return the size in bytes of the given encrypted data object. Used by OOM
+/** Return the size in bytes of the given encrypted data object. Used by OOM
* subsystem. */
static size_t
hs_desc_encrypted_obj_size(const hs_desc_encrypted_data_t *data)
@@ -2811,18 +2818,20 @@ hs_desc_encrypted_obj_size(const hs_desc_encrypted_data_t *data)
return sizeof(*data) + intro_size;
}
-/* Return the size in bytes of the given descriptor object. Used by OOM
+/** Return the size in bytes of the given descriptor object. Used by OOM
* subsystem. */
size_t
hs_desc_obj_size(const hs_descriptor_t *data)
{
- tor_assert(data);
+ if (data == NULL) {
+ return 0;
+ }
return (hs_desc_plaintext_obj_size(&data->plaintext_data) +
hs_desc_encrypted_obj_size(&data->encrypted_data) +
sizeof(data->subcredential));
}
-/* Return a newly allocated descriptor intro point. */
+/** Return a newly allocated descriptor intro point. */
hs_desc_intro_point_t *
hs_desc_intro_point_new(void)
{
@@ -2831,7 +2840,7 @@ hs_desc_intro_point_new(void)
return ip;
}
-/* Free a descriptor intro point object. */
+/** Free a descriptor intro point object. */
void
hs_desc_intro_point_free_(hs_desc_intro_point_t *ip)
{
@@ -2839,8 +2848,8 @@ hs_desc_intro_point_free_(hs_desc_intro_point_t *ip)
return;
}
if (ip->link_specifiers) {
- SMARTLIST_FOREACH(ip->link_specifiers, hs_desc_link_specifier_t *,
- ls, hs_desc_link_specifier_free(ls));
+ SMARTLIST_FOREACH(ip->link_specifiers, link_specifier_t *,
+ ls, link_specifier_free(ls));
smartlist_free(ip->link_specifiers);
}
tor_cert_free(ip->auth_key_cert);
@@ -2850,7 +2859,7 @@ hs_desc_intro_point_free_(hs_desc_intro_point_t *ip)
tor_free(ip);
}
-/* Allocate and build a new fake client info for the descriptor. Return a
+/** Allocate and build a new fake client info for the descriptor. Return a
* newly allocated object. This can't fail. */
hs_desc_authorized_client_t *
hs_desc_build_fake_authorized_client(void)
@@ -2868,49 +2877,44 @@ hs_desc_build_fake_authorized_client(void)
return client_auth;
}
-/* Using the service's subcredential, client public key, auth ephemeral secret
+/** Using the service's subcredential, client public key, auth ephemeral secret
* key, and descriptor cookie, build the auth client so we can then encode the
* descriptor for publication. client_out must be already allocated. */
void
-hs_desc_build_authorized_client(const uint8_t *subcredential,
+hs_desc_build_authorized_client(const hs_subcredential_t *subcredential,
const curve25519_public_key_t *client_auth_pk,
const curve25519_secret_key_t *
auth_ephemeral_sk,
const uint8_t *descriptor_cookie,
hs_desc_authorized_client_t *client_out)
{
- uint8_t secret_seed[CURVE25519_OUTPUT_LEN];
- uint8_t keystream[HS_DESC_CLIENT_ID_LEN + HS_DESC_COOKIE_KEY_LEN];
- uint8_t *cookie_key;
+ uint8_t *keystream = NULL;
+ size_t keystream_length = 0;
+ const uint8_t *cookie_key;
crypto_cipher_t *cipher;
- crypto_xof_t *xof;
tor_assert(client_auth_pk);
tor_assert(auth_ephemeral_sk);
tor_assert(descriptor_cookie);
tor_assert(client_out);
tor_assert(subcredential);
- tor_assert(!tor_mem_is_zero((char *) auth_ephemeral_sk,
+ tor_assert(!fast_mem_is_zero((char *) auth_ephemeral_sk,
sizeof(*auth_ephemeral_sk)));
- tor_assert(!tor_mem_is_zero((char *) client_auth_pk,
+ tor_assert(!fast_mem_is_zero((char *) client_auth_pk,
sizeof(*client_auth_pk)));
- tor_assert(!tor_mem_is_zero((char *) descriptor_cookie,
+ tor_assert(!fast_mem_is_zero((char *) descriptor_cookie,
HS_DESC_DESCRIPTOR_COOKIE_LEN));
- tor_assert(!tor_mem_is_zero((char *) subcredential,
+ tor_assert(!fast_mem_is_zero((char *) subcredential,
DIGEST256_LEN));
- /* Calculate x25519(hs_y, client_X) */
- curve25519_handshake(secret_seed,
- auth_ephemeral_sk,
- client_auth_pk);
-
- /* Calculate KEYS = KDF(subcredential | SECRET_SEED, 40) */
- xof = crypto_xof_new();
- crypto_xof_add_bytes(xof, subcredential, DIGEST256_LEN);
- crypto_xof_add_bytes(xof, secret_seed, sizeof(secret_seed));
- crypto_xof_squeeze_bytes(xof, keystream, sizeof(keystream));
- crypto_xof_free(xof);
+ /* Get the KEYS part so we can derive the CLIENT-ID and COOKIE-KEY. */
+ keystream_length =
+ build_descriptor_cookie_keys(subcredential,
+ auth_ephemeral_sk, client_auth_pk,
+ &keystream);
+ tor_assert(keystream_length > 0);
+ /* Extract the CLIENT-ID and COOKIE-KEY from the KEYS. */
memcpy(client_out->client_id, keystream, HS_DESC_CLIENT_ID_LEN);
cookie_key = keystream + HS_DESC_CLIENT_ID_LEN;
@@ -2925,83 +2929,20 @@ hs_desc_build_authorized_client(const uint8_t *subcredential,
(const char *) descriptor_cookie,
HS_DESC_DESCRIPTOR_COOKIE_LEN);
- memwipe(secret_seed, 0, sizeof(secret_seed));
- memwipe(keystream, 0, sizeof(keystream));
+ memwipe(keystream, 0, keystream_length);
+ tor_free(keystream);
crypto_cipher_free(cipher);
}
-/* Free an authoriezd client object. */
+/** Free an authoriezd client object. */
void
hs_desc_authorized_client_free_(hs_desc_authorized_client_t *client)
{
tor_free(client);
}
-/* Free the given descriptor link specifier. */
-void
-hs_desc_link_specifier_free_(hs_desc_link_specifier_t *ls)
-{
- if (ls == NULL) {
- return;
- }
- tor_free(ls);
-}
-
-/* Return a newly allocated descriptor link specifier using the given extend
- * info and requested type. Return NULL on error. */
-hs_desc_link_specifier_t *
-hs_desc_link_specifier_new(const extend_info_t *info, uint8_t type)
-{
- hs_desc_link_specifier_t *ls = NULL;
-
- tor_assert(info);
-
- ls = tor_malloc_zero(sizeof(*ls));
- ls->type = type;
- switch (ls->type) {
- case LS_IPV4:
- if (info->addr.family != AF_INET) {
- goto err;
- }
- tor_addr_copy(&ls->u.ap.addr, &info->addr);
- ls->u.ap.port = info->port;
- break;
- case LS_IPV6:
- if (info->addr.family != AF_INET6) {
- goto err;
- }
- tor_addr_copy(&ls->u.ap.addr, &info->addr);
- ls->u.ap.port = info->port;
- break;
- case LS_LEGACY_ID:
- /* Bug out if the identity digest is not set */
- if (BUG(tor_mem_is_zero(info->identity_digest,
- sizeof(info->identity_digest)))) {
- goto err;
- }
- memcpy(ls->u.legacy_id, info->identity_digest, sizeof(ls->u.legacy_id));
- break;
- case LS_ED25519_ID:
- /* ed25519 keys are optional for intro points */
- if (ed25519_public_key_is_zero(&info->ed_identity)) {
- goto err;
- }
- memcpy(ls->u.ed25519_id, info->ed_identity.pubkey,
- sizeof(ls->u.ed25519_id));
- break;
- default:
- /* Unknown type is code flow error. */
- tor_assert(0);
- }
-
- return ls;
- err:
- tor_free(ls);
- return NULL;
-}
-
-/* From the given descriptor, remove and free every introduction point. */
+/** From the given descriptor, remove and free every introduction point. */
void
hs_descriptor_clear_intro_points(hs_descriptor_t *desc)
{
@@ -3016,59 +2957,3 @@ hs_descriptor_clear_intro_points(hs_descriptor_t *desc)
smartlist_clear(ips);
}
}
-
-/* From a descriptor link specifier object spec, returned a newly allocated
- * link specifier object that is the encoded representation of spec. Return
- * NULL on error. */
-link_specifier_t *
-hs_desc_lspec_to_trunnel(const hs_desc_link_specifier_t *spec)
-{
- tor_assert(spec);
-
- link_specifier_t *ls = link_specifier_new();
- link_specifier_set_ls_type(ls, spec->type);
-
- switch (spec->type) {
- case LS_IPV4:
- link_specifier_set_un_ipv4_addr(ls,
- tor_addr_to_ipv4h(&spec->u.ap.addr));
- link_specifier_set_un_ipv4_port(ls, spec->u.ap.port);
- /* Four bytes IPv4 and two bytes port. */
- link_specifier_set_ls_len(ls, sizeof(spec->u.ap.addr.addr.in_addr) +
- sizeof(spec->u.ap.port));
- break;
- case LS_IPV6:
- {
- size_t addr_len = link_specifier_getlen_un_ipv6_addr(ls);
- const uint8_t *in6_addr = tor_addr_to_in6_addr8(&spec->u.ap.addr);
- uint8_t *ipv6_array = link_specifier_getarray_un_ipv6_addr(ls);
- memcpy(ipv6_array, in6_addr, addr_len);
- link_specifier_set_un_ipv6_port(ls, spec->u.ap.port);
- /* Sixteen bytes IPv6 and two bytes port. */
- link_specifier_set_ls_len(ls, addr_len + sizeof(spec->u.ap.port));
- break;
- }
- case LS_LEGACY_ID:
- {
- size_t legacy_id_len = link_specifier_getlen_un_legacy_id(ls);
- uint8_t *legacy_id_array = link_specifier_getarray_un_legacy_id(ls);
- memcpy(legacy_id_array, spec->u.legacy_id, legacy_id_len);
- link_specifier_set_ls_len(ls, legacy_id_len);
- break;
- }
- case LS_ED25519_ID:
- {
- size_t ed25519_id_len = link_specifier_getlen_un_ed25519_id(ls);
- uint8_t *ed25519_id_array = link_specifier_getarray_un_ed25519_id(ls);
- memcpy(ed25519_id_array, spec->u.ed25519_id, ed25519_id_len);
- link_specifier_set_ls_len(ls, ed25519_id_len);
- break;
- }
- default:
- tor_assert_nonfatal_unreached();
- link_specifier_free(ls);
- ls = NULL;
- }
-
- return ls;
-}