mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
hs-v3: Add a series of decoding error code
This commit introduces the hs_desc_decode_status_t enum which aims at having more fine grained error code when decoding a descriptor. This will be useful in later commits when we support keeping a descriptor that can't be decrypted due to missing or bad client authorization creds. No behavior change. Part of #30382. Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
8e0d9189c5
commit
52bf54ecd4
@ -1320,7 +1320,7 @@ hs_client_decode_descriptor(const char *desc_str,
|
||||
ret = hs_desc_decode_descriptor(desc_str, subcredential,
|
||||
client_auht_sk, desc);
|
||||
memwipe(subcredential, 0, sizeof(subcredential));
|
||||
if (ret < 0) {
|
||||
if (ret != HS_DESC_DECODE_OK) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -2038,7 +2038,7 @@ desc_sig_is_valid(const char *b64_sig,
|
||||
* 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 +2128,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
|
||||
* 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 +2226,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:
|
||||
@ -2250,14 +2248,13 @@ desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
|
||||
}
|
||||
|
||||
/** 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
|
||||
* 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;
|
||||
@ -2343,11 +2340,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:
|
||||
@ -2366,7 +2363,7 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
|
||||
|
||||
/** 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,
|
||||
@ -2379,12 +2376,12 @@ static int
|
||||
/** 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);
|
||||
@ -2398,7 +2395,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
|
||||
@ -2419,7 +2415,7 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc,
|
||||
|
||||
/** 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,14 +2425,13 @@ static int
|
||||
};
|
||||
|
||||
/** 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
|
||||
* 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);
|
||||
@ -2450,7 +2445,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
|
||||
@ -2470,7 +2464,7 @@ hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
|
||||
|
||||
/** 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,12 +2476,12 @@ static int
|
||||
};
|
||||
|
||||
/** Fully decode the given descriptor plaintext and store the data in the
|
||||
* plaintext data object. Returns 0 on success else a negative value. */
|
||||
int
|
||||
* 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;
|
||||
@ -2537,11 +2531,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) {
|
||||
@ -2560,13 +2554,13 @@ hs_desc_decode_plaintext(const char *encoded,
|
||||
*
|
||||
* 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 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);
|
||||
@ -2583,17 +2577,17 @@ hs_desc_decode_descriptor(const char *encoded,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2672,7 +2666,8 @@ hs_desc_encode_descriptor,(const hs_descriptor_t *desc,
|
||||
if (!descriptor_cookie) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,15 @@ typedef enum {
|
||||
HS_DESC_AUTH_ED25519 = 1
|
||||
} hs_desc_auth_type_t;
|
||||
|
||||
/** Error code when decoding a descriptor. */
|
||||
typedef enum {
|
||||
HS_DESC_DECODE_ENCRYPTED_ERROR = -4,
|
||||
HS_DESC_DECODE_SUPERENC_ERROR = -3,
|
||||
HS_DESC_DECODE_PLAINTEXT_ERROR = -2,
|
||||
HS_DESC_DECODE_GENERIC_ERROR = -1,
|
||||
HS_DESC_DECODE_OK = 0,
|
||||
} hs_desc_decode_status_t;
|
||||
|
||||
/** Introduction point information located in a descriptor. */
|
||||
typedef struct hs_desc_intro_point_t {
|
||||
/** Link specifier(s) which details how to extend to the relay. This list
|
||||
|
@ -411,7 +411,7 @@ test_hsdir_revision_counter_check(void *arg)
|
||||
|
||||
retval = hs_desc_decode_descriptor(received_desc_str,
|
||||
subcredential, NULL, &received_desc);
|
||||
tt_int_op(retval, OP_EQ, 0);
|
||||
tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
|
||||
tt_assert(received_desc);
|
||||
|
||||
/* Check that the revision counter is correct */
|
||||
@ -444,7 +444,7 @@ test_hsdir_revision_counter_check(void *arg)
|
||||
|
||||
retval = hs_desc_decode_descriptor(received_desc_str,
|
||||
subcredential, NULL, &received_desc);
|
||||
tt_int_op(retval, OP_EQ, 0);
|
||||
tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
|
||||
tt_assert(received_desc);
|
||||
|
||||
/* Check that the revision counter is the latest */
|
||||
|
@ -235,14 +235,14 @@ test_decode_descriptor(void *arg)
|
||||
/* Give some bad stuff to the decoding function. */
|
||||
ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential,
|
||||
NULL, &decoded);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
|
||||
|
||||
ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
|
||||
tt_assert(encoded);
|
||||
|
||||
ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
|
||||
tt_assert(decoded);
|
||||
|
||||
hs_helper_desc_equal(desc, decoded);
|
||||
@ -263,7 +263,7 @@ test_decode_descriptor(void *arg)
|
||||
tt_assert(encoded);
|
||||
hs_descriptor_free(decoded);
|
||||
ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
|
||||
tt_assert(decoded);
|
||||
}
|
||||
|
||||
@ -317,21 +317,21 @@ test_decode_descriptor(void *arg)
|
||||
hs_descriptor_free(decoded);
|
||||
ret = hs_desc_decode_descriptor(encoded, subcredential,
|
||||
NULL, &decoded);
|
||||
tt_int_op(ret, OP_LT, 0);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_ENCRYPTED_ERROR);
|
||||
tt_assert(!decoded);
|
||||
|
||||
/* If we have an invalid client secret key, the decoding must fail. */
|
||||
hs_descriptor_free(decoded);
|
||||
ret = hs_desc_decode_descriptor(encoded, subcredential,
|
||||
&invalid_client_kp.seckey, &decoded);
|
||||
tt_int_op(ret, OP_LT, 0);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_ENCRYPTED_ERROR);
|
||||
tt_assert(!decoded);
|
||||
|
||||
/* If we have the client secret key, the decoding must succeed and the
|
||||
* decoded descriptor must be correct. */
|
||||
ret = hs_desc_decode_descriptor(encoded, subcredential,
|
||||
&client_kp.seckey, &decoded);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
|
||||
tt_assert(decoded);
|
||||
|
||||
hs_helper_desc_equal(desc, decoded);
|
||||
@ -567,7 +567,7 @@ test_decode_bad_signature(void *arg)
|
||||
|
||||
setup_full_capture_of_logs(LOG_WARN);
|
||||
ret = hs_desc_decode_plaintext(HS_DESC_BAD_SIG, &desc_plaintext);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
|
||||
expect_log_msg_containing("Malformed signature line. Rejecting.");
|
||||
teardown_capture_of_logs();
|
||||
|
||||
@ -607,14 +607,14 @@ test_decode_plaintext(void *arg)
|
||||
tor_asprintf(&plaintext, template, bad_value, "180", "42", "MESSAGE");
|
||||
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
|
||||
tor_free(plaintext);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
|
||||
}
|
||||
|
||||
/* Missing fields. */
|
||||
{
|
||||
const char *plaintext = "hs-descriptor 3\n";
|
||||
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
|
||||
}
|
||||
|
||||
/* Max length. */
|
||||
@ -627,7 +627,7 @@ test_decode_plaintext(void *arg)
|
||||
plaintext[big - 1] = '\0';
|
||||
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
|
||||
tor_free(plaintext);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
|
||||
}
|
||||
|
||||
/* Bad lifetime value. */
|
||||
@ -636,7 +636,7 @@ test_decode_plaintext(void *arg)
|
||||
tor_asprintf(&plaintext, template, "3", bad_value, "42", "MESSAGE");
|
||||
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
|
||||
tor_free(plaintext);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
|
||||
}
|
||||
|
||||
/* Huge lifetime value. */
|
||||
@ -645,7 +645,7 @@ test_decode_plaintext(void *arg)
|
||||
tor_asprintf(&plaintext, template, "3", "7181615", "42", "MESSAGE");
|
||||
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
|
||||
tor_free(plaintext);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
|
||||
}
|
||||
|
||||
/* Invalid encrypted section. */
|
||||
@ -654,7 +654,7 @@ test_decode_plaintext(void *arg)
|
||||
tor_asprintf(&plaintext, template, "3", "180", "42", bad_value);
|
||||
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
|
||||
tor_free(plaintext);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
|
||||
}
|
||||
|
||||
/* Invalid revision counter. */
|
||||
@ -663,7 +663,7 @@ test_decode_plaintext(void *arg)
|
||||
tor_asprintf(&plaintext, template, "3", "180", bad_value, "MESSAGE");
|
||||
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
|
||||
tor_free(plaintext);
|
||||
tt_int_op(ret, OP_EQ, -1);
|
||||
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
|
||||
}
|
||||
|
||||
done:
|
||||
|
Loading…
Reference in New Issue
Block a user