mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
Merge remote-tracking branch 'asn/bug21334_v3'
This commit is contained in:
commit
43dd9bf0fc
File diff suppressed because it is too large
Load Diff
@ -41,24 +41,11 @@
|
||||
* the secret IV and MAC key length which is the length of H() output. */
|
||||
#define HS_DESC_ENCRYPTED_KDF_OUTPUT_LEN \
|
||||
CIPHER256_KEY_LEN + CIPHER_IV_LEN + DIGEST256_LEN
|
||||
/* We need to pad the plaintext version of the encrypted data section before
|
||||
* encryption and it has to be a multiple of this value. */
|
||||
#define HS_DESC_PLAINTEXT_PADDING_MULTIPLE 128
|
||||
/* XXX: Let's make sure this makes sense as an upper limit for the padded
|
||||
* plaintext section. Then we should enforce it as now only an assert will be
|
||||
* triggered if we are above it. */
|
||||
/* Once padded, this is the maximum length in bytes for the plaintext. */
|
||||
#define HS_DESC_PADDED_PLAINTEXT_MAX_LEN 8192
|
||||
/* Minimum length in bytes of the encrypted portion of the descriptor. */
|
||||
#define HS_DESC_ENCRYPTED_MIN_LEN \
|
||||
HS_DESC_ENCRYPTED_SALT_LEN + \
|
||||
HS_DESC_PLAINTEXT_PADDING_MULTIPLE + DIGEST256_LEN
|
||||
/* Pad plaintext of superencrypted data section before encryption so that its
|
||||
* length is a multiple of this value. */
|
||||
#define HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE 10000
|
||||
/* Maximum length in bytes of a full hidden service descriptor. */
|
||||
#define HS_DESC_MAX_LEN 50000 /* 50kb max size */
|
||||
/* The minimum amount of fields a descriptor should contain. The parsing of
|
||||
* the fields are version specific so the only required field, as a generic
|
||||
* view of a descriptor, is 1 that is the version field. */
|
||||
#define HS_DESC_PLAINTEXT_MIN_FIELDS 1
|
||||
|
||||
/* Key length for the descriptor symmetric encryption. As specified in the
|
||||
* protocol, we use AES-256 for the encrypted section of the descriptor. The
|
||||
@ -68,8 +55,7 @@
|
||||
|
||||
/* Type of authentication in the descriptor. */
|
||||
typedef enum {
|
||||
HS_DESC_AUTH_PASSWORD = 1,
|
||||
HS_DESC_AUTH_ED25519 = 2,
|
||||
HS_DESC_AUTH_ED25519 = 1
|
||||
} hs_desc_auth_type_t;
|
||||
|
||||
/* Type of encryption key in the descriptor. */
|
||||
@ -132,7 +118,7 @@ typedef struct hs_desc_encrypted_data_t {
|
||||
|
||||
/* A list of authentication types that a client must at least support one
|
||||
* in order to contact the service. Contains NULL terminated strings. */
|
||||
smartlist_t *auth_types;
|
||||
smartlist_t *intro_auth_types;
|
||||
|
||||
/* Is this descriptor a single onion service? */
|
||||
unsigned int single_onion_service : 1;
|
||||
@ -167,11 +153,11 @@ typedef struct hs_desc_plaintext_data_t {
|
||||
* has changed. Spec specifies this as a 8 bytes positive integer. */
|
||||
uint64_t revision_counter;
|
||||
|
||||
/* Decoding only: The base64-decoded encrypted blob from the descriptor */
|
||||
uint8_t *encrypted_blob;
|
||||
/* Decoding only: The b64-decoded superencrypted blob from the descriptor */
|
||||
uint8_t *superencrypted_blob;
|
||||
|
||||
/* Decoding only: Size of the encrypted_blob */
|
||||
size_t encrypted_blob_size;
|
||||
/* Decoding only: Size of the superencrypted_blob */
|
||||
size_t superencrypted_blob_size;
|
||||
} hs_desc_plaintext_data_t;
|
||||
|
||||
/* Service descriptor in its decoded form. */
|
||||
@ -242,6 +228,8 @@ STATIC int desc_sig_is_valid(const char *b64_sig,
|
||||
const ed25519_public_key_t *signing_pubkey,
|
||||
const char *encoded_desc, size_t encoded_len);
|
||||
STATIC void desc_intro_point_free(hs_desc_intro_point_t *ip);
|
||||
STATIC size_t decode_superencrypted(const char *message, size_t message_len,
|
||||
uint8_t **encrypted_out);
|
||||
#endif /* HS_DESCRIPTOR_PRIVATE */
|
||||
|
||||
#endif /* TOR_HS_DESCRIPTOR_H */
|
||||
|
@ -157,12 +157,16 @@ typedef enum {
|
||||
R3_SUPERENCRYPTED,
|
||||
R3_SIGNATURE,
|
||||
R3_CREATE2_FORMATS,
|
||||
R3_AUTHENTICATION_REQUIRED,
|
||||
R3_INTRO_AUTH_REQUIRED,
|
||||
R3_SINGLE_ONION_SERVICE,
|
||||
R3_INTRODUCTION_POINT,
|
||||
R3_INTRO_AUTH_KEY,
|
||||
R3_INTRO_ENC_KEY,
|
||||
R3_INTRO_ENC_KEY_CERTIFICATION,
|
||||
R3_DESC_AUTH_TYPE,
|
||||
R3_DESC_AUTH_KEY,
|
||||
R3_DESC_AUTH_CLIENT,
|
||||
R3_ENCRYPTED,
|
||||
|
||||
R_IPO_IDENTIFIER,
|
||||
R_IPO_IP_ADDRESS,
|
||||
|
@ -93,8 +93,8 @@ helper_build_hs_desc(uint64_t revision_counter, uint32_t lifetime,
|
||||
|
||||
/* Setup encrypted data section. */
|
||||
desc->encrypted_data.create2_ntor = 1;
|
||||
desc->encrypted_data.auth_types = smartlist_new();
|
||||
smartlist_add(desc->encrypted_data.auth_types, tor_strdup("ed25519"));
|
||||
desc->encrypted_data.intro_auth_types = smartlist_new();
|
||||
smartlist_add(desc->encrypted_data.intro_auth_types, tor_strdup("ed25519"));
|
||||
desc->encrypted_data.intro_points = smartlist_new();
|
||||
/* Add an intro point. */
|
||||
smartlist_add(desc->encrypted_data.intro_points,
|
||||
@ -333,7 +333,7 @@ helper_fetch_desc_from_hsdir(const ed25519_public_key_t *blinded_key)
|
||||
size_t body_used = 0;
|
||||
|
||||
fetch_from_buf_http(TO_CONN(conn)->outbuf, &headers, MAX_HEADERS_SIZE,
|
||||
&received_desc, &body_used, 10000, 0);
|
||||
&received_desc, &body_used, HS_DESC_MAX_LEN, 0);
|
||||
tor_free(headers);
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include "test.h"
|
||||
#include "torcert.h"
|
||||
|
||||
#include "test_helpers.h"
|
||||
#include "log_test_helpers.h"
|
||||
|
||||
static hs_desc_intro_point_t *
|
||||
helper_build_intro_point(const ed25519_keypair_t *blinded_kp, time_t now,
|
||||
const char *addr, int legacy)
|
||||
@ -105,9 +108,9 @@ helper_build_hs_desc(unsigned int no_ip, ed25519_public_key_t *signing_pubkey)
|
||||
|
||||
/* Setup encrypted data section. */
|
||||
desc->encrypted_data.create2_ntor = 1;
|
||||
desc->encrypted_data.auth_types = smartlist_new();
|
||||
desc->encrypted_data.intro_auth_types = smartlist_new();
|
||||
desc->encrypted_data.single_onion_service = 1;
|
||||
smartlist_add(desc->encrypted_data.auth_types, tor_strdup("ed25519"));
|
||||
smartlist_add(desc->encrypted_data.intro_auth_types, tor_strdup("ed25519"));
|
||||
desc->encrypted_data.intro_points = smartlist_new();
|
||||
if (!no_ip) {
|
||||
/* Add four intro points. */
|
||||
@ -157,14 +160,17 @@ helper_compare_hs_desc(const hs_descriptor_t *desc1,
|
||||
desc2->encrypted_data.create2_ntor);
|
||||
|
||||
/* Authentication type. */
|
||||
tt_int_op(!!desc1->encrypted_data.auth_types, ==,
|
||||
!!desc2->encrypted_data.auth_types);
|
||||
if (desc1->encrypted_data.auth_types && desc2->encrypted_data.auth_types) {
|
||||
tt_int_op(smartlist_len(desc1->encrypted_data.auth_types), ==,
|
||||
smartlist_len(desc2->encrypted_data.auth_types));
|
||||
for (int i = 0; i < smartlist_len(desc1->encrypted_data.auth_types); i++) {
|
||||
tt_str_op(smartlist_get(desc1->encrypted_data.auth_types, i), OP_EQ,
|
||||
smartlist_get(desc2->encrypted_data.auth_types, i));
|
||||
tt_int_op(!!desc1->encrypted_data.intro_auth_types, ==,
|
||||
!!desc2->encrypted_data.intro_auth_types);
|
||||
if (desc1->encrypted_data.intro_auth_types &&
|
||||
desc2->encrypted_data.intro_auth_types) {
|
||||
tt_int_op(smartlist_len(desc1->encrypted_data.intro_auth_types), ==,
|
||||
smartlist_len(desc2->encrypted_data.intro_auth_types));
|
||||
for (int i = 0;
|
||||
i < smartlist_len(desc1->encrypted_data.intro_auth_types);
|
||||
i++) {
|
||||
tt_str_op(smartlist_get(desc1->encrypted_data.intro_auth_types, i),OP_EQ,
|
||||
smartlist_get(desc2->encrypted_data.intro_auth_types, i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,13 +317,13 @@ test_descriptor_padding(void *arg)
|
||||
/* Example: if l = 129, the ceiled division gives 2 and then multiplied by 128
|
||||
* to give 256. With l = 127, ceiled division gives 1 then times 128. */
|
||||
#define PADDING_EXPECTED_LEN(l) \
|
||||
CEIL_DIV(l, HS_DESC_PLAINTEXT_PADDING_MULTIPLE) * \
|
||||
HS_DESC_PLAINTEXT_PADDING_MULTIPLE
|
||||
CEIL_DIV(l, HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE) * \
|
||||
HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE
|
||||
|
||||
(void) arg;
|
||||
|
||||
{ /* test #1: no padding */
|
||||
plaintext_len = HS_DESC_PLAINTEXT_PADDING_MULTIPLE;
|
||||
plaintext_len = HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE;
|
||||
plaintext = tor_malloc(plaintext_len);
|
||||
padded_len = build_plaintext_padding(plaintext, plaintext_len,
|
||||
&padded_plaintext);
|
||||
@ -333,7 +339,7 @@ test_descriptor_padding(void *arg)
|
||||
}
|
||||
|
||||
{ /* test #2: one byte padding? */
|
||||
plaintext_len = HS_DESC_PLAINTEXT_PADDING_MULTIPLE - 1;
|
||||
plaintext_len = HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE - 1;
|
||||
plaintext = tor_malloc(plaintext_len);
|
||||
padded_plaintext = NULL;
|
||||
padded_len = build_plaintext_padding(plaintext, plaintext_len,
|
||||
@ -350,7 +356,7 @@ test_descriptor_padding(void *arg)
|
||||
}
|
||||
|
||||
{ /* test #3: Lots more bytes of padding? */
|
||||
plaintext_len = HS_DESC_PLAINTEXT_PADDING_MULTIPLE + 1;
|
||||
plaintext_len = HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE + 1;
|
||||
plaintext = tor_malloc(plaintext_len);
|
||||
padded_plaintext = NULL;
|
||||
padded_len = build_plaintext_padding(plaintext, plaintext_len,
|
||||
@ -587,19 +593,11 @@ test_encrypted_data_len(void *arg)
|
||||
/* No length, error. */
|
||||
ret = encrypted_data_length_is_valid(0);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
/* Not a multiple of our encryption algorithm (thus no padding). It's
|
||||
* suppose to be aligned on HS_DESC_PLAINTEXT_PADDING_MULTIPLE. */
|
||||
value = HS_DESC_PLAINTEXT_PADDING_MULTIPLE * 10 - 1;
|
||||
ret = encrypted_data_length_is_valid(value);
|
||||
tt_int_op(ret, OP_EQ, 0);
|
||||
/* Valid value. */
|
||||
value = HS_DESC_PADDED_PLAINTEXT_MAX_LEN + HS_DESC_ENCRYPTED_SALT_LEN +
|
||||
DIGEST256_LEN;
|
||||
value = HS_DESC_ENCRYPTED_SALT_LEN + DIGEST256_LEN + 1;
|
||||
ret = encrypted_data_length_is_valid(value);
|
||||
tt_int_op(ret, OP_EQ, 1);
|
||||
|
||||
/* XXX: Test maximum possible size. */
|
||||
|
||||
done:
|
||||
;
|
||||
}
|
||||
@ -1006,6 +1004,103 @@ test_desc_signature(void *arg)
|
||||
tor_free(data);
|
||||
}
|
||||
|
||||
/* bad desc auth type */
|
||||
const char bad_superencrypted_text1[] = "desc-auth-type scoobysnack\n"
|
||||
"desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n"
|
||||
"auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n"
|
||||
"encrypted\n"
|
||||
"-----BEGIN MESSAGE-----\n"
|
||||
"YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC"
|
||||
"BiYWQgYXQgYWxs\n"
|
||||
"-----END MESSAGE-----\n";
|
||||
|
||||
/* bad ephemeral key */
|
||||
const char bad_superencrypted_text2[] = "desc-auth-type x25519\n"
|
||||
"desc-auth-ephemeral-key differentalphabet\n"
|
||||
"auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n"
|
||||
"encrypted\n"
|
||||
"-----BEGIN MESSAGE-----\n"
|
||||
"YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC"
|
||||
"BiYWQgYXQgYWxs\n"
|
||||
"-----END MESSAGE-----\n";
|
||||
|
||||
/* bad encrypted msg */
|
||||
const char bad_superencrypted_text3[] = "desc-auth-type x25519\n"
|
||||
"desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n"
|
||||
"auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n"
|
||||
"encrypted\n"
|
||||
"-----BEGIN MESSAGE-----\n"
|
||||
"SO SMALL NOT GOOD\n"
|
||||
"-----END MESSAGE-----\n";
|
||||
|
||||
const char correct_superencrypted_text[] = "desc-auth-type x25519\n"
|
||||
"desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n"
|
||||
"auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n"
|
||||
"auth-client Od09Qu636Qo /PKLzqewAdS/+0+vZC+MvQ dpw4NFo13zDnuPz45rxrOg\n"
|
||||
"auth-client JRr840iGYN0 8s8cxYqF7Lx23+NducC4Qg zAafl4wPLURkuEjJreZq1g\n"
|
||||
"encrypted\n"
|
||||
"-----BEGIN MESSAGE-----\n"
|
||||
"YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC"
|
||||
"BiYWQgYXQgYWxs\n"
|
||||
"-----END MESSAGE-----\n";
|
||||
|
||||
const char correct_encrypted_plaintext[] = "being on mountains, "
|
||||
"thinking about computers, is not bad at all";
|
||||
|
||||
static void
|
||||
test_parse_hs_desc_superencrypted(void *arg)
|
||||
{
|
||||
(void) arg;
|
||||
int retval;
|
||||
uint8_t *encrypted_out = NULL;
|
||||
|
||||
{
|
||||
setup_full_capture_of_logs(LOG_WARN);
|
||||
retval = decode_superencrypted(bad_superencrypted_text1,
|
||||
strlen(bad_superencrypted_text1),
|
||||
&encrypted_out);
|
||||
tt_int_op(retval, ==, 0);
|
||||
tt_assert(!encrypted_out);
|
||||
expect_log_msg_containing("Unrecognized desc auth type");
|
||||
teardown_capture_of_logs();
|
||||
}
|
||||
|
||||
{
|
||||
setup_full_capture_of_logs(LOG_WARN);
|
||||
retval = decode_superencrypted(bad_superencrypted_text2,
|
||||
strlen(bad_superencrypted_text2),
|
||||
&encrypted_out);
|
||||
tt_int_op(retval, ==, 0);
|
||||
tt_assert(!encrypted_out);
|
||||
expect_log_msg_containing("Bogus desc auth key in HS desc");
|
||||
teardown_capture_of_logs();
|
||||
}
|
||||
|
||||
{
|
||||
setup_full_capture_of_logs(LOG_WARN);
|
||||
retval = decode_superencrypted(bad_superencrypted_text3,
|
||||
strlen(bad_superencrypted_text3),
|
||||
&encrypted_out);
|
||||
tt_int_op(retval, ==, 0);
|
||||
tt_assert(!encrypted_out);
|
||||
expect_log_msg_containing("Length of descriptor\'s encrypted data "
|
||||
"is too small.");
|
||||
teardown_capture_of_logs();
|
||||
}
|
||||
|
||||
/* Now finally the good one */
|
||||
retval = decode_superencrypted(correct_superencrypted_text,
|
||||
strlen(correct_superencrypted_text),
|
||||
&encrypted_out);
|
||||
|
||||
tt_int_op(retval, ==, strlen(correct_encrypted_plaintext));
|
||||
tt_mem_op(encrypted_out, OP_EQ, correct_encrypted_plaintext,
|
||||
strlen(correct_encrypted_plaintext));
|
||||
|
||||
done:
|
||||
tor_free(encrypted_out);
|
||||
}
|
||||
|
||||
struct testcase_t hs_descriptor[] = {
|
||||
/* Encoding tests. */
|
||||
{ "cert_encoding", test_cert_encoding, TT_FORK,
|
||||
@ -1035,6 +1130,9 @@ struct testcase_t hs_descriptor[] = {
|
||||
{ "desc_signature", test_desc_signature, TT_FORK,
|
||||
NULL, NULL },
|
||||
|
||||
{ "parse_hs_desc_superencrypted", test_parse_hs_desc_superencrypted,
|
||||
TT_FORK, NULL, NULL },
|
||||
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user