diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index 18c79e0c47..0038fdfa50 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -1181,6 +1181,19 @@ can_client_refetch_desc(const ed25519_public_key_t *identity_pk, return 0; } +/* Return the client auth in the map using the service identity public key. + * Return NULL if it does not exist in the map. */ +static hs_client_service_authorization_t * +find_client_auth(const ed25519_public_key_t *service_identity_pk) +{ + /* If the map is not allocated, we can assume that we do not have any client + * auth information. */ + if (!client_auths) { + return NULL; + } + return digest256map_get(client_auths, service_identity_pk->pubkey); +} + /* ========== */ /* Public API */ /* ========== */ @@ -1219,11 +1232,19 @@ hs_client_decode_descriptor(const char *desc_str, int ret; uint8_t subcredential[DIGEST256_LEN]; ed25519_public_key_t blinded_pubkey; + hs_client_service_authorization_t *client_auth = NULL; + curve25519_secret_key_t *client_sk = NULL; tor_assert(desc_str); tor_assert(service_identity_pk); tor_assert(desc); + /* Check if we have a client authorization for this service in the map. */ + client_auth = find_client_auth(service_identity_pk); + if (client_auth) { + client_sk = &client_auth->enc_seckey; + } + /* Create subcredential for this HS so that we can decrypt */ { uint64_t current_time_period = hs_get_time_period_num(0); @@ -1233,7 +1254,7 @@ hs_client_decode_descriptor(const char *desc_str, } /* Parse descriptor */ - ret = hs_desc_decode_descriptor(desc_str, subcredential, desc); + ret = hs_desc_decode_descriptor(desc_str, subcredential, client_sk, desc); memwipe(subcredential, 0, sizeof(subcredential)); if (ret < 0) { log_warn(LD_GENERAL, "Could not parse received descriptor as client."); diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c index 4eb06c8270..bb2cc1984b 100644 --- a/src/feature/hs/hs_descriptor.c +++ b/src/feature/hs/hs_descriptor.c @@ -1421,10 +1421,11 @@ encrypted_data_length_is_valid(size_t len) } /** Decrypt an encrypted descriptor layer at encrypted_blob of size - * encrypted_blob_size. Use the descriptor object desc to - * generate the right decryption keys; set decrypted_out to the - * plaintext. If is_superencrypted_layer is set, this is the outter - * encrypted layer of the descriptor. + * encrypted_blob_size. The descriptor cookie is optional. Use + * the descriptor object desc and descriptor_cookie + * to generate the right decryption keys; set decrypted_out to + * the plaintext. If is_superencrypted_layer is set, this is + * the outter encrypted layer of the descriptor. * * On any error case, including an empty output, return 0 and set * *decrypted_out to NULL. @@ -1433,11 +1434,14 @@ 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, char **decrypted_out)) { uint8_t *decrypted = NULL; uint8_t secret_key[HS_DESC_ENCRYPTED_KEY_LEN], secret_iv[CIPHER_IV_LEN]; + uint8_t *secret_data = NULL; + size_t secret_data_len = 0; uint8_t mac_key[DIGEST256_LEN], our_mac[DIGEST256_LEN]; const uint8_t *salt, *encrypted, *desc_mac; size_t encrypted_len, result_len = 0; @@ -1464,13 +1468,14 @@ decrypt_desc_layer,(const hs_descriptor_t *desc, /* And last comes the MAC. */ desc_mac = encrypted_blob + encrypted_blob_size - DIGEST256_LEN; + /* Build secret data to be used in the decryption. */ + secret_data_len = build_secret_data(&desc->plaintext_data.blinded_pubkey, + descriptor_cookie, + &secret_data); + /* KDF construction resulting in a key from which the secret key, IV and MAC * key are extracted which is what we need for the decryption. */ - /* XXX: I will put only blinded pubkey for now. I will also put the - * descriptor cookie when I implement the descriptor decryption with - * client auth. */ - build_secret_key_iv_mac(desc, desc->plaintext_data.blinded_pubkey.pubkey, - ED25519_PUBKEY_LEN, + build_secret_key_iv_mac(desc, secret_data, secret_data_len, salt, HS_DESC_ENCRYPTED_SALT_LEN, secret_key, sizeof(secret_key), secret_iv, sizeof(secret_iv), @@ -1531,167 +1536,82 @@ decrypt_desc_layer,(const hs_descriptor_t *desc, result_len = 0; done: + memwipe(secret_data, 0, secret_data_len); memwipe(secret_key, 0, sizeof(secret_key)); memwipe(secret_iv, 0, sizeof(secret_iv)); + tor_free(secret_data); return result_len; } -/* Basic validation that the superencrypted client auth portion of the - * descriptor is well-formed and recognized. Return True if so, otherwise - * return False. */ -static int -superencrypted_auth_data_is_valid(smartlist_t *tokens) -{ - /* XXX: This is just basic validation for now. When we implement client auth, - we can refactor this function so that it actually parses and saves the - data. */ - - { /* verify desc auth type */ - const directory_token_t *tok; - tok = find_by_keyword(tokens, R3_DESC_AUTH_TYPE); - tor_assert(tok->n_args >= 1); - if (strcmp(tok->args[0], "x25519")) { - log_warn(LD_DIR, "Unrecognized desc auth type"); - return 0; - } - } - - { /* verify desc auth key */ - const directory_token_t *tok; - curve25519_public_key_t k; - tok = find_by_keyword(tokens, R3_DESC_AUTH_KEY); - tor_assert(tok->n_args >= 1); - if (curve25519_public_from_base64(&k, tok->args[0]) < 0) { - log_warn(LD_DIR, "Bogus desc auth key in HS desc"); - return 0; - } - } - - /* verify desc auth client items */ - SMARTLIST_FOREACH_BEGIN(tokens, const directory_token_t *, tok) { - if (tok->tp == R3_DESC_AUTH_CLIENT) { - tor_assert(tok->n_args >= 3); - } - } SMARTLIST_FOREACH_END(tok); - - return 1; -} - -/* Parse message, the plaintext of the superencrypted portion of an HS - * descriptor. Set encrypted_out to the encrypted blob, and return its - * size */ -STATIC size_t -decode_superencrypted(const char *message, size_t message_len, - uint8_t **encrypted_out) -{ - int retval = 0; - memarea_t *area = NULL; - smartlist_t *tokens = NULL; - - area = memarea_new(); - tokens = smartlist_new(); - if (tokenize_string(area, message, message + message_len, tokens, - hs_desc_superencrypted_v3_token_table, 0) < 0) { - log_warn(LD_REND, "Superencrypted portion is not parseable"); - goto err; - } - - /* Do some rudimentary validation of the authentication data */ - if (!superencrypted_auth_data_is_valid(tokens)) { - log_warn(LD_REND, "Invalid auth data"); - goto err; - } - - /* Extract the encrypted data section. */ - { - const directory_token_t *tok; - tok = find_by_keyword(tokens, R3_ENCRYPTED); - tor_assert(tok->object_body); - if (strcmp(tok->object_type, "MESSAGE") != 0) { - log_warn(LD_REND, "Desc superencrypted data section is invalid"); - goto err; - } - /* Make sure the length of the encrypted blob is valid. */ - if (!encrypted_data_length_is_valid(tok->object_size)) { - goto err; - } - - /* Copy the encrypted blob to the descriptor object so we can handle it - * latter if needed. */ - tor_assert(tok->object_size <= INT_MAX); - *encrypted_out = tor_memdup(tok->object_body, tok->object_size); - retval = (int) tok->object_size; - } - - err: - SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); - smartlist_free(tokens); - if (area) { - memarea_drop_all(area); - } - - return retval; -} - -/* Decrypt both the superencrypted and the encrypted section of the descriptor - * using the given descriptor object desc. A newly allocated NUL - * terminated string is put in decrypted_out which contains the inner encrypted - * layer of the descriptor. Return the length of decrypted_out on success else - * 0 is returned and decrypted_out is set to NULL. */ +/* Decrypt the superencrypted section of the descriptor using the given + * descriptor object desc. 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 + * returned and decrypted_out is set to NULL. */ static size_t -desc_decrypt_all(const hs_descriptor_t *desc, char **decrypted_out) +desc_decrypt_superencrypted(const hs_descriptor_t *desc, char **decrypted_out) { - size_t decrypted_len = 0; - size_t encrypted_len = 0; size_t superencrypted_len = 0; char *superencrypted_plaintext = NULL; - uint8_t *encrypted_blob = NULL; - /** Function logic: This function takes us from the descriptor header to the - * inner encrypted layer, by decrypting and decoding the middle descriptor - * layer. In the end we return the contents of the inner encrypted layer to - * our caller. */ + tor_assert(desc); + tor_assert(decrypted_out); - /* 1. Decrypt middle layer of descriptor */ superencrypted_len = decrypt_desc_layer(desc, desc->plaintext_data.superencrypted_blob, desc->plaintext_data.superencrypted_blob_size, - 1, - &superencrypted_plaintext); + NULL, 1, &superencrypted_plaintext); + if (!superencrypted_len) { log_warn(LD_REND, "Decrypting superencrypted desc failed."); - goto err; + goto done; } tor_assert(superencrypted_plaintext); - /* 2. Parse "superencrypted" */ - encrypted_len = decode_superencrypted(superencrypted_plaintext, - superencrypted_len, - &encrypted_blob); + done: + /* In case of error, superencrypted_plaintext is already NULL, so the + * following line makes sense. */ + *decrypted_out = superencrypted_plaintext; + /* This makes sense too, because, in case of error, this is zero. */ + return superencrypted_len; +} + +/* Decrypt the encrypted section of the descriptor using the given descriptor + * object desc. 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 + * decrypted_out is set to NULL. */ +static size_t +desc_decrypt_encrypted(const hs_descriptor_t *desc, + const curve25519_secret_key_t *client_sk, + char **decrypted_out) +{ + size_t encrypted_len = 0; + char *encrypted_plaintext = NULL; + + tor_assert(desc); + tor_assert(decrypted_out); + + /* XXX: We need to decrypt the descriptor properly when the client auth + * is enabled. */ + (void) client_sk; + + encrypted_len = decrypt_desc_layer(desc, + desc->superencrypted_data.encrypted_blob, + desc->superencrypted_data.encrypted_blob_size, + NULL, 0, &encrypted_plaintext); if (!encrypted_len) { log_warn(LD_REND, "Decrypting encrypted desc failed."); goto err; } - tor_assert(encrypted_blob); - - /* 3. Decrypt "encrypted" and set decrypted_out */ - char *decrypted_desc; - decrypted_len = decrypt_desc_layer(desc, - encrypted_blob, encrypted_len, - 0, &decrypted_desc); - if (!decrypted_len) { - log_warn(LD_REND, "Decrypting encrypted desc failed."); - goto err; - } - tor_assert(decrypted_desc); - - *decrypted_out = decrypted_desc; + tor_assert(encrypted_plaintext); err: - tor_free(superencrypted_plaintext); - tor_free(encrypted_blob); - - return decrypted_len; + /* In case of error, encrypted_plaintext is already NULL, so the + * following line makes sense. */ + *decrypted_out = encrypted_plaintext; + /* This makes sense too, because, in case of error, this is zero. */ + return encrypted_len; } /* Given the token tok for an intro point legacy key, the list of tokens, the @@ -2118,19 +2038,19 @@ desc_decode_plaintext_v3(smartlist_t *tokens, goto err; } - /* Extract the encrypted data section. */ + /* Extract the superencrypted data section. */ tok = find_by_keyword(tokens, R3_SUPERENCRYPTED); tor_assert(tok->object_body); if (strcmp(tok->object_type, "MESSAGE") != 0) { - log_warn(LD_REND, "Service descriptor encrypted data section is invalid"); + log_warn(LD_REND, "Desc superencrypted data section is invalid"); goto err; } - /* Make sure the length of the encrypted blob is valid. */ + /* Make sure the length of the superencrypted blob is valid. */ if (!encrypted_data_length_is_valid(tok->object_size)) { goto err; } - /* Copy the encrypted blob to the descriptor object so we can handle it + /* Copy the superencrypted blob to the descriptor object so we can handle it * latter if needed. */ desc->superencrypted_blob = tor_memdup(tok->object_body, tok->object_size); desc->superencrypted_blob_size = tok->object_size; @@ -2150,14 +2070,117 @@ desc_decode_plaintext_v3(smartlist_t *tokens, return -1; } +/* 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 +desc_decode_superencrypted_v3(const hs_descriptor_t *desc, + hs_desc_superencrypted_data_t * + desc_superencrypted_out) +{ + int ret = -1; + char *message = NULL; + size_t message_len; + memarea_t *area = NULL; + directory_token_t *tok; + smartlist_t *tokens = NULL; + /* Rename the parameter because it is too long. */ + hs_desc_superencrypted_data_t *superencrypted = desc_superencrypted_out; + + tor_assert(desc); + tor_assert(desc_superencrypted_out); + + /* Decrypt the superencrypted data that is located in the plaintext section + * in the descriptor as a blob of bytes. */ + message_len = desc_decrypt_superencrypted(desc, &message); + if (!message_len) { + log_warn(LD_REND, "Service descriptor decryption failed."); + goto err; + } + tor_assert(message); + + area = memarea_new(); + tokens = smartlist_new(); + if (tokenize_string(area, message, message + message_len, + tokens, hs_desc_superencrypted_v3_token_table, 0) < 0) { + log_warn(LD_REND, "Superencrypted service descriptor is not parseable."); + goto err; + } + + /* Verify desc auth type */ + tok = find_by_keyword(tokens, R3_DESC_AUTH_TYPE); + tor_assert(tok->n_args >= 1); + if (strcmp(tok->args[0], "x25519")) { + log_warn(LD_DIR, "Unrecognized desc auth type"); + goto err; + } + + /* Extract desc auth ephemeral key */ + tok = find_by_keyword(tokens, R3_DESC_AUTH_KEY); + tor_assert(tok->n_args >= 1); + if (curve25519_public_from_base64(&superencrypted->auth_ephemeral_pubkey, + tok->args[0]) < 0) { + log_warn(LD_DIR, "Bogus desc auth ephemeral key in HS desc"); + goto err; + } + + /* Extract desc auth client items */ + SMARTLIST_FOREACH_BEGIN(tokens, const directory_token_t *, token) { + if (token->tp == R3_DESC_AUTH_CLIENT) { + tor_assert(token->n_args >= 3); + /* XXX: Extract each auth client. */ + } + } SMARTLIST_FOREACH_END(token); + + /* Extract the encrypted data section. */ + tok = find_by_keyword(tokens, R3_ENCRYPTED); + tor_assert(tok->object_body); + if (strcmp(tok->object_type, "MESSAGE") != 0) { + log_warn(LD_REND, "Desc encrypted data section is invalid"); + goto err; + } + /* Make sure the length of the encrypted blob is valid. */ + if (!encrypted_data_length_is_valid(tok->object_size)) { + goto err; + } + + /* Copy the encrypted blob to the descriptor object so we can handle it + * latter if needed. */ + tor_assert(tok->object_size <= INT_MAX); + superencrypted->encrypted_blob = tor_memdup(tok->object_body, + tok->object_size); + superencrypted->encrypted_blob_size = tok->object_size; + + ret = 0; + goto done; + + err: + tor_assert(ret < 0); + desc_superencrypted_data_free_contents(desc_superencrypted_out); + + done: + if (tokens) { + SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); + smartlist_free(tokens); + } + if (area) { + memarea_drop_all(area); + } + if (message) { + tor_free(message); + } + 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 desc_decode_encrypted_v3(const hs_descriptor_t *desc, + const curve25519_secret_key_t *client_sk, hs_desc_encrypted_data_t *desc_encrypted_out) { - int result = -1; + int ret = -1; char *message = NULL; size_t message_len; memarea_t *area = NULL; @@ -2167,9 +2190,9 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc, tor_assert(desc); tor_assert(desc_encrypted_out); - /* Decrypt the superencrypted data that is located in the plaintext section + /* Decrypt the encrypted data that is located in the superencrypted section * in the descriptor as a blob of bytes. */ - message_len = desc_decrypt_all(desc, &message); + message_len = desc_decrypt_encrypted(desc, client_sk, &message); if (!message_len) { log_warn(LD_REND, "Service descriptor decryption failed."); goto err; @@ -2228,11 +2251,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. */ - result = 0; + ret = 0; goto done; err: - tor_assert(result < 0); + tor_assert(ret < 0); desc_encrypted_data_free_contents(desc_encrypted_out); done: @@ -2246,7 +2269,7 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc, if (message) { tor_free(message); } - return result; + return ret; } /* Table of encrypted decode function version specific. The function are @@ -2254,6 +2277,7 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc, static int (*decode_encrypted_handlers[])( const hs_descriptor_t *desc, + const curve25519_secret_key_t *client_sk, hs_desc_encrypted_data_t *desc_encrypted) = { /* v0 */ NULL, /* v1 */ NULL, /* v2 */ NULL, @@ -2265,6 +2289,7 @@ static int * negative value on error. */ int hs_desc_decode_encrypted(const hs_descriptor_t *desc, + const curve25519_secret_key_t *client_sk, hs_desc_encrypted_data_t *desc_encrypted) { int ret; @@ -2275,9 +2300,9 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc, version = desc->plaintext_data.version; tor_assert(desc_encrypted); /* Calling this function without an encrypted blob to parse is a code flow - * error. The plaintext parsing should never succeed in the first place + * error. The superencrypted parsing should never succeed in the first place * without an encrypted section. */ - tor_assert(desc->plaintext_data.superencrypted_blob); + tor_assert(desc->superencrypted_data.encrypted_blob); /* 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))) { @@ -2290,7 +2315,58 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc, tor_assert(decode_encrypted_handlers[version]); /* Run the version specific plaintext decoder. */ - ret = decode_encrypted_handlers[version](desc, desc_encrypted); + ret = decode_encrypted_handlers[version](desc, client_sk, desc_encrypted); + if (ret < 0) { + goto err; + } + + err: + return ret; +} + +/* 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 + (*decode_superencrypted_handlers[])( + const hs_descriptor_t *desc, + hs_desc_superencrypted_data_t *desc_superencrypted) = +{ + /* v0 */ NULL, /* v1 */ NULL, /* v2 */ NULL, + 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 +hs_desc_decode_superencrypted(const hs_descriptor_t *desc, + hs_desc_superencrypted_data_t * + desc_superencrypted) +{ + int ret; + uint32_t version; + + tor_assert(desc); + /* Ease our life a bit. */ + version = desc->plaintext_data.version; + tor_assert(desc_superencrypted); + /* Calling this function without an superencrypted blob to parse is + * a code flow error. The plaintext parsing should never succeed in + * the first place without an superencrypted section. */ + tor_assert(desc->plaintext_data.superencrypted_blob); + /* 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 + * never happened else we forgot to add it but we bumped the version. */ + tor_assert(ARRAY_LENGTH(decode_superencrypted_handlers) >= version); + tor_assert(decode_superencrypted_handlers[version]); + + /* Run the version specific plaintext decoder. */ + ret = decode_superencrypted_handlers[version](desc, desc_superencrypted); if (ret < 0) { goto err; } @@ -2387,12 +2463,15 @@ hs_desc_decode_plaintext(const char *encoded, /* Fully decode an encoded descriptor and set a newly allocated descriptor * object in desc_out. Subcredentials are used if not NULL else it's ignored. + * 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_descriptor(const char *encoded, const uint8_t *subcredential, + const curve25519_secret_key_t *client_sk, hs_descriptor_t **desc_out) { int ret = -1; @@ -2415,7 +2494,12 @@ hs_desc_decode_descriptor(const char *encoded, goto err; } - ret = hs_desc_decode_encrypted(desc, &desc->encrypted_data); + ret = hs_desc_decode_superencrypted(desc, &desc->superencrypted_data); + if (ret < 0) { + goto err; + } + + ret = hs_desc_decode_encrypted(desc, client_sk, &desc->encrypted_data); if (ret < 0) { goto err; } diff --git a/src/feature/hs/hs_descriptor.h b/src/feature/hs/hs_descriptor.h index 8700164323..64a5a8f7f1 100644 --- a/src/feature/hs/hs_descriptor.h +++ b/src/feature/hs/hs_descriptor.h @@ -277,10 +277,14 @@ MOCK_DECL(int, int hs_desc_decode_descriptor(const char *encoded, const uint8_t *subcredential, + const curve25519_secret_key_t *client_sk, hs_descriptor_t **desc_out); int hs_desc_decode_plaintext(const char *encoded, hs_desc_plaintext_data_t *plaintext); +int hs_desc_decode_superencrypted(const hs_descriptor_t *desc, + hs_desc_superencrypted_data_t *desc_out); int hs_desc_decode_encrypted(const hs_descriptor_t *desc, + const curve25519_secret_key_t *client_sk, hs_desc_encrypted_data_t *desc_out); size_t hs_desc_obj_size(const hs_descriptor_t *data); @@ -324,13 +328,12 @@ STATIC int cert_is_valid(tor_cert_t *cert, uint8_t type, 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 size_t decode_superencrypted(const char *message, size_t message_len, - uint8_t **encrypted_out); STATIC void desc_plaintext_data_free_contents(hs_desc_plaintext_data_t *desc); MOCK_DECL(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, char **decrypted_out)); diff --git a/src/test/fuzz/fuzz_hsdescv3.c b/src/test/fuzz/fuzz_hsdescv3.c index 4ec8db0a87..b332973b39 100644 --- a/src/test/fuzz/fuzz_hsdescv3.c +++ b/src/test/fuzz/fuzz_hsdescv3.c @@ -38,11 +38,13 @@ static size_t mock_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, char **decrypted_out) { (void)is_superencrypted_layer; (void)desc; + (void)descriptor_cookie; const size_t overhead = HS_DESC_ENCRYPTED_SALT_LEN + DIGEST256_LEN; if (encrypted_blob_size < overhead) return 0; @@ -84,7 +86,7 @@ fuzz_main(const uint8_t *data, size_t sz) char *fuzzing_data = tor_memdup_nulterm(data, sz); memset(subcredential, 'A', sizeof(subcredential)); - hs_desc_decode_descriptor(fuzzing_data, subcredential, &desc); + hs_desc_decode_descriptor(fuzzing_data, subcredential, NULL, &desc); if (desc) { log_debug(LD_GENERAL, "Decoding okay"); hs_descriptor_free(desc); diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c index 33bb00e6e1..728bb4a2f5 100644 --- a/src/test/test_hs_cache.c +++ b/src/test/test_hs_cache.c @@ -390,7 +390,7 @@ test_hsdir_revision_counter_check(void *arg) received_desc_str = helper_fetch_desc_from_hsdir(blinded_key); retval = hs_desc_decode_descriptor(received_desc_str, - subcredential, &received_desc); + subcredential, NULL, &received_desc); tt_int_op(retval, OP_EQ, 0); tt_assert(received_desc); @@ -423,7 +423,7 @@ test_hsdir_revision_counter_check(void *arg) received_desc_str = helper_fetch_desc_from_hsdir(blinded_key); retval = hs_desc_decode_descriptor(received_desc_str, - subcredential, &received_desc); + subcredential, NULL, &received_desc); tt_int_op(retval, OP_EQ, 0); tt_assert(received_desc); diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c index 78cd9fa476..e003ea5ff1 100644 --- a/src/test/test_hs_descriptor.c +++ b/src/test/test_hs_descriptor.c @@ -347,14 +347,15 @@ test_decode_descriptor(void *arg) subcredential); /* Give some bad stuff to the decoding function. */ - ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential, &decoded); + ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential, + NULL, &decoded); tt_int_op(ret, OP_EQ, -1); ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded); tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); - ret = hs_desc_decode_descriptor(encoded, subcredential, &decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded); tt_int_op(ret, OP_EQ, 0); tt_assert(decoded); @@ -375,7 +376,7 @@ test_decode_descriptor(void *arg) tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); hs_descriptor_free(decoded); - ret = hs_desc_decode_descriptor(encoded, subcredential, &decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded); tt_int_op(ret, OP_EQ, 0); tt_assert(decoded); } @@ -850,103 +851,6 @@ test_build_authorized_client(void *arg) UNMOCK(crypto_strongest_rand); } -/* bad desc auth type */ -static 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 */ -static 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 */ -static 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"; - -static 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"; - -static 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; - size_t 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_u64_op(retval, OP_EQ, 0); - tt_ptr_op(encrypted_out, OP_EQ, NULL); - 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_u64_op(retval, OP_EQ, 0); - tt_ptr_op(encrypted_out, OP_EQ, NULL); - 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_u64_op(retval, OP_EQ, 0); - tt_ptr_op(encrypted_out, OP_EQ, NULL); - 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_u64_op(retval, OP_EQ, 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, @@ -980,8 +884,5 @@ struct testcase_t hs_descriptor[] = { { "build_authorized_client", test_build_authorized_client, TT_FORK, NULL, NULL }, - { "parse_hs_desc_superencrypted", test_parse_hs_desc_superencrypted, - TT_FORK, NULL, NULL }, - END_OF_TESTCASES };