Merge remote-tracking branch 'asn/bug21334_v3'

This commit is contained in:
Nick Mathewson 2017-03-13 16:18:55 -04:00
commit 43dd9bf0fc
5 changed files with 814 additions and 300 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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,

View File

@ -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);
}

View File

@ -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
};