mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Merge branch 'ticket21871_031_03_squashed'
This commit is contained in:
commit
6390a0c3b6
@ -79,7 +79,9 @@
|
|||||||
#define str_intro_point "introduction-point"
|
#define str_intro_point "introduction-point"
|
||||||
#define str_ip_auth_key "auth-key"
|
#define str_ip_auth_key "auth-key"
|
||||||
#define str_ip_enc_key "enc-key"
|
#define str_ip_enc_key "enc-key"
|
||||||
#define str_ip_enc_key_cert "enc-key-certification"
|
#define str_ip_enc_key_cert "enc-key-cert"
|
||||||
|
#define str_ip_legacy_key "legacy-key"
|
||||||
|
#define str_ip_legacy_key_cert "legacy-key-cert"
|
||||||
#define str_intro_point_start "\n" str_intro_point " "
|
#define str_intro_point_start "\n" str_intro_point " "
|
||||||
/* Constant string value for the construction to encrypt the encrypted data
|
/* Constant string value for the construction to encrypt the encrypted data
|
||||||
* section. */
|
* section. */
|
||||||
@ -134,9 +136,10 @@ static token_rule_t hs_desc_encrypted_v3_token_table[] = {
|
|||||||
static token_rule_t hs_desc_intro_point_v3_token_table[] = {
|
static token_rule_t hs_desc_intro_point_v3_token_table[] = {
|
||||||
T1_START(str_intro_point, R3_INTRODUCTION_POINT, EQ(1), NO_OBJ),
|
T1_START(str_intro_point, R3_INTRODUCTION_POINT, EQ(1), NO_OBJ),
|
||||||
T1(str_ip_auth_key, R3_INTRO_AUTH_KEY, NO_ARGS, NEED_OBJ),
|
T1(str_ip_auth_key, R3_INTRO_AUTH_KEY, NO_ARGS, NEED_OBJ),
|
||||||
T1(str_ip_enc_key, R3_INTRO_ENC_KEY, ARGS, OBJ_OK),
|
T1(str_ip_enc_key, R3_INTRO_ENC_KEY, GE(2), OBJ_OK),
|
||||||
T1_END(str_ip_enc_key_cert, R3_INTRO_ENC_KEY_CERTIFICATION,
|
T1(str_ip_enc_key_cert, R3_INTRO_ENC_KEY_CERT, ARGS, OBJ_OK),
|
||||||
NO_ARGS, NEED_OBJ),
|
T01(str_ip_legacy_key, R3_INTRO_LEGACY_KEY, ARGS, NEED_KEY_1024),
|
||||||
|
T01(str_ip_legacy_key_cert, R3_INTRO_LEGACY_KEY_CERT, ARGS, OBJ_OK),
|
||||||
END_OF_TABLE
|
END_OF_TABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -153,8 +156,12 @@ desc_intro_point_free(hs_desc_intro_point_t *ip)
|
|||||||
smartlist_free(ip->link_specifiers);
|
smartlist_free(ip->link_specifiers);
|
||||||
}
|
}
|
||||||
tor_cert_free(ip->auth_key_cert);
|
tor_cert_free(ip->auth_key_cert);
|
||||||
if (ip->enc_key_type == HS_DESC_KEY_TYPE_LEGACY) {
|
tor_cert_free(ip->enc_key_cert);
|
||||||
crypto_pk_free(ip->enc_key.legacy);
|
if (ip->legacy.key) {
|
||||||
|
crypto_pk_free(ip->legacy.key);
|
||||||
|
}
|
||||||
|
if (ip->legacy.cert.encoded) {
|
||||||
|
tor_free(ip->legacy.cert.encoded);
|
||||||
}
|
}
|
||||||
tor_free(ip);
|
tor_free(ip);
|
||||||
}
|
}
|
||||||
@ -406,101 +413,68 @@ encode_link_specifiers(const smartlist_t *specs)
|
|||||||
return encoded_b64;
|
return encoded_b64;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Encode an introduction point encryption key and return a newly allocated
|
/* Encode an introduction point legacy key and certificate. Return a newly
|
||||||
* string with it. On failure, return NULL. */
|
* allocated string with it. On failure, return NULL. */
|
||||||
static char *
|
static char *
|
||||||
encode_enc_key(const ed25519_public_key_t *sig_key,
|
encode_legacy_key(const hs_desc_intro_point_t *ip)
|
||||||
const hs_desc_intro_point_t *ip)
|
|
||||||
{
|
{
|
||||||
char *encoded = NULL;
|
char *key_str, b64_cert[256], *encoded = NULL;
|
||||||
time_t now = time(NULL);
|
size_t key_str_len;
|
||||||
|
|
||||||
tor_assert(sig_key);
|
|
||||||
tor_assert(ip);
|
tor_assert(ip);
|
||||||
|
|
||||||
switch (ip->enc_key_type) {
|
/* Encode cross cert. */
|
||||||
case HS_DESC_KEY_TYPE_LEGACY:
|
if (base64_encode(b64_cert, sizeof(b64_cert),
|
||||||
{
|
(const char *) ip->legacy.cert.encoded,
|
||||||
char *key_str, b64_cert[256];
|
ip->legacy.cert.len, BASE64_ENCODE_MULTILINE) < 0) {
|
||||||
ssize_t cert_len;
|
log_warn(LD_REND, "Unable to encode legacy crosscert.");
|
||||||
size_t key_str_len;
|
goto done;
|
||||||
uint8_t *cert_data = NULL;
|
|
||||||
|
|
||||||
/* Create cross certification cert. */
|
|
||||||
cert_len = tor_make_rsa_ed25519_crosscert(sig_key, ip->enc_key.legacy,
|
|
||||||
now + HS_DESC_CERT_LIFETIME,
|
|
||||||
&cert_data);
|
|
||||||
if (cert_len < 0) {
|
|
||||||
log_warn(LD_REND, "Unable to create legacy crosscert.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
/* Encode cross cert. */
|
|
||||||
if (base64_encode(b64_cert, sizeof(b64_cert), (const char *) cert_data,
|
|
||||||
cert_len, BASE64_ENCODE_MULTILINE) < 0) {
|
|
||||||
tor_free(cert_data);
|
|
||||||
log_warn(LD_REND, "Unable to encode legacy crosscert.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
tor_free(cert_data);
|
|
||||||
/* Convert the encryption key to a string. */
|
|
||||||
if (crypto_pk_write_public_key_to_string(ip->enc_key.legacy, &key_str,
|
|
||||||
&key_str_len) < 0) {
|
|
||||||
log_warn(LD_REND, "Unable to encode legacy encryption key.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
tor_asprintf(&encoded,
|
|
||||||
"%s legacy\n%s" /* Newline is added by the call above. */
|
|
||||||
"%s\n"
|
|
||||||
"-----BEGIN CROSSCERT-----\n"
|
|
||||||
"%s"
|
|
||||||
"-----END CROSSCERT-----",
|
|
||||||
str_ip_enc_key, key_str,
|
|
||||||
str_ip_enc_key_cert, b64_cert);
|
|
||||||
tor_free(key_str);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case HS_DESC_KEY_TYPE_CURVE25519:
|
/* Convert the encryption key to PEM format NUL terminated. */
|
||||||
{
|
if (crypto_pk_write_public_key_to_string(ip->legacy.key, &key_str,
|
||||||
int signbit, ret;
|
&key_str_len) < 0) {
|
||||||
char *encoded_cert, key_fp_b64[CURVE25519_BASE64_PADDED_LEN + 1];
|
log_warn(LD_REND, "Unable to encode legacy encryption key.");
|
||||||
ed25519_keypair_t curve_kp;
|
goto done;
|
||||||
|
|
||||||
if (ed25519_keypair_from_curve25519_keypair(&curve_kp, &signbit,
|
|
||||||
&ip->enc_key.curve25519)) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
tor_cert_t *cross_cert = tor_cert_create(&curve_kp,
|
|
||||||
CERT_TYPE_CROSS_HS_IP_KEYS,
|
|
||||||
sig_key, now,
|
|
||||||
HS_DESC_CERT_LIFETIME,
|
|
||||||
CERT_FLAG_INCLUDE_SIGNING_KEY);
|
|
||||||
memwipe(&curve_kp, 0, sizeof(curve_kp));
|
|
||||||
if (!cross_cert) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
ret = tor_cert_encode_ed22519(cross_cert, &encoded_cert);
|
|
||||||
tor_cert_free(cross_cert);
|
|
||||||
if (ret) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (curve25519_public_to_base64(key_fp_b64,
|
|
||||||
&ip->enc_key.curve25519.pubkey) < 0) {
|
|
||||||
tor_free(encoded_cert);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
tor_asprintf(&encoded,
|
|
||||||
"%s ntor %s\n"
|
|
||||||
"%s\n%s",
|
|
||||||
str_ip_enc_key, key_fp_b64,
|
|
||||||
str_ip_enc_key_cert, encoded_cert);
|
|
||||||
tor_free(encoded_cert);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
tor_assert(0);
|
|
||||||
}
|
}
|
||||||
|
tor_asprintf(&encoded,
|
||||||
|
"%s \n%s" /* Newline is added by the call above. */
|
||||||
|
"%s\n"
|
||||||
|
"-----BEGIN CROSSCERT-----\n"
|
||||||
|
"%s"
|
||||||
|
"-----END CROSSCERT-----",
|
||||||
|
str_ip_legacy_key, key_str,
|
||||||
|
str_ip_legacy_key_cert, b64_cert);
|
||||||
|
tor_free(key_str);
|
||||||
|
|
||||||
err:
|
done:
|
||||||
|
return encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
char *encoded = NULL, *encoded_cert;
|
||||||
|
char key_b64[CURVE25519_BASE64_PADDED_LEN + 1];
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (tor_cert_encode_ed22519(ip->enc_key_cert, &encoded_cert) < 0) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
tor_asprintf(&encoded,
|
||||||
|
"%s ntor %s\n"
|
||||||
|
"%s\n%s",
|
||||||
|
str_ip_enc_key, key_b64,
|
||||||
|
str_ip_enc_key_cert, encoded_cert);
|
||||||
|
tor_free(encoded_cert);
|
||||||
|
|
||||||
|
done:
|
||||||
return encoded;
|
return encoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,7 +509,7 @@ encode_intro_point(const ed25519_public_key_t *sig_key,
|
|||||||
|
|
||||||
/* Encryption key encoding. */
|
/* Encryption key encoding. */
|
||||||
{
|
{
|
||||||
char *encoded_enc_key = encode_enc_key(sig_key, ip);
|
char *encoded_enc_key = encode_enc_key(ip);
|
||||||
if (encoded_enc_key == NULL) {
|
if (encoded_enc_key == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -543,6 +517,18 @@ encode_intro_point(const ed25519_public_key_t *sig_key,
|
|||||||
tor_free(encoded_enc_key);
|
tor_free(encoded_enc_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Legacy key if any. */
|
||||||
|
if (ip->legacy.key != NULL) {
|
||||||
|
/* Strong requirement else the IP creation was badly done. */
|
||||||
|
tor_assert(ip->legacy.cert.encoded);
|
||||||
|
char *encoded_legacy_key = encode_legacy_key(ip);
|
||||||
|
if (encoded_legacy_key == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
smartlist_add_asprintf(lines, "%s", encoded_legacy_key);
|
||||||
|
tor_free(encoded_legacy_key);
|
||||||
|
}
|
||||||
|
|
||||||
/* Join them all in one blob of text. */
|
/* Join them all in one blob of text. */
|
||||||
encoded_ip = smartlist_join_strings(lines, "\n", 1, NULL);
|
encoded_ip = smartlist_join_strings(lines, "\n", 1, NULL);
|
||||||
|
|
||||||
@ -1581,6 +1567,64 @@ desc_decrypt_all(const hs_descriptor_t *desc, char **decrypted_out)
|
|||||||
return decrypted_len;
|
return decrypted_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
static int
|
||||||
|
decode_intro_legacy_key(const directory_token_t *tok,
|
||||||
|
smartlist_t *tokens,
|
||||||
|
hs_desc_intro_point_t *ip,
|
||||||
|
const hs_descriptor_t *desc)
|
||||||
|
{
|
||||||
|
tor_assert(tok);
|
||||||
|
tor_assert(tokens);
|
||||||
|
tor_assert(ip);
|
||||||
|
tor_assert(desc);
|
||||||
|
|
||||||
|
if (!crypto_pk_public_exponent_ok(tok->key)) {
|
||||||
|
log_warn(LD_REND, "Introduction point legacy key is invalid");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
ip->legacy.key = crypto_pk_dup_key(tok->key);
|
||||||
|
/* Extract the legacy cross certification cert which MUST be present if we
|
||||||
|
* have a legacy key. */
|
||||||
|
tok = find_opt_by_keyword(tokens, R3_INTRO_LEGACY_KEY_CERT);
|
||||||
|
if (!tok) {
|
||||||
|
log_warn(LD_REND, "Introduction point legacy key cert is missing");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
tor_assert(tok->object_body);
|
||||||
|
if (strcmp(tok->object_type, "CROSSCERT")) {
|
||||||
|
/* Info level because this might be an unknown field that we should
|
||||||
|
* ignore. */
|
||||||
|
log_info(LD_REND, "Introduction point legacy encryption key "
|
||||||
|
"cross-certification has an unknown format.");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* Keep a copy of the certificate. */
|
||||||
|
ip->legacy.cert.encoded = tor_memdup(tok->object_body, tok->object_size);
|
||||||
|
ip->legacy.cert.len = tok->object_size;
|
||||||
|
/* The check on the expiration date is for the entire lifetime of a
|
||||||
|
* certificate which is 24 hours. However, a descriptor has a maximum
|
||||||
|
* lifetime of 12 hours meaning we have a 12h difference between the two
|
||||||
|
* which ultimately accomodate the clock skewed client. */
|
||||||
|
if (rsa_ed25519_crosscert_check(ip->legacy.cert.encoded,
|
||||||
|
ip->legacy.cert.len, ip->legacy.key,
|
||||||
|
&desc->plaintext_data.signing_pubkey,
|
||||||
|
approx_time() - HS_DESC_CERT_LIFETIME)) {
|
||||||
|
log_warn(LD_REND, "Unable to check cross-certification on the "
|
||||||
|
"introduction point legacy encryption key.");
|
||||||
|
ip->cross_certified = 0;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success. */
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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
|
* introduction point from that section. Return a newly allocated introduction
|
||||||
* point object containing the decoded data. Return NULL if the section can't
|
* point object containing the decoded data. Return NULL if the section can't
|
||||||
@ -1591,7 +1635,6 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start)
|
|||||||
hs_desc_intro_point_t *ip = NULL;
|
hs_desc_intro_point_t *ip = NULL;
|
||||||
memarea_t *area = NULL;
|
memarea_t *area = NULL;
|
||||||
smartlist_t *tokens = NULL;
|
smartlist_t *tokens = NULL;
|
||||||
tor_cert_t *cross_cert = NULL;
|
|
||||||
const directory_token_t *tok;
|
const directory_token_t *tok;
|
||||||
|
|
||||||
tor_assert(desc);
|
tor_assert(desc);
|
||||||
@ -1625,84 +1668,67 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start)
|
|||||||
log_warn(LD_REND, "Unexpected object type for introduction auth key");
|
log_warn(LD_REND, "Unexpected object type for introduction auth key");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse cert and do some validation. */
|
/* Parse cert and do some validation. */
|
||||||
if (cert_parse_and_validate(&ip->auth_key_cert, tok->object_body,
|
if (cert_parse_and_validate(&ip->auth_key_cert, tok->object_body,
|
||||||
tok->object_size, CERT_TYPE_AUTH_HS_IP_KEY,
|
tok->object_size, CERT_TYPE_AUTH_HS_IP_KEY,
|
||||||
"introduction point auth-key") < 0) {
|
"introduction point auth-key") < 0) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
/* Validate authentication certificate with descriptor signing key. */
|
||||||
|
if (tor_cert_checksig(ip->auth_key_cert,
|
||||||
|
&desc->plaintext_data.signing_pubkey, 0) < 0) {
|
||||||
|
log_warn(LD_REND, "Invalid authentication key signature");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Exactly one "enc-key" ... */
|
/* Exactly one "enc-key" SP "ntor" SP key NL */
|
||||||
tok = find_by_keyword(tokens, R3_INTRO_ENC_KEY);
|
tok = find_by_keyword(tokens, R3_INTRO_ENC_KEY);
|
||||||
if (!strcmp(tok->args[0], "ntor")) {
|
if (!strcmp(tok->args[0], "ntor")) {
|
||||||
/* "enc-key" SP "ntor" SP key NL */
|
/* This field is using GE(2) so for possible forward compatibility, we
|
||||||
if (tok->n_args != 2 || tok->object_body) {
|
* accept more fields but must be at least 2. */
|
||||||
log_warn(LD_REND, "Introduction point ntor encryption key is invalid");
|
tor_assert(tok->n_args >= 2);
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curve25519_public_from_base64(&ip->enc_key.curve25519.pubkey,
|
if (curve25519_public_from_base64(&ip->enc_key, tok->args[1]) < 0) {
|
||||||
tok->args[1]) < 0) {
|
log_warn(LD_REND, "Introduction point ntor enc-key is invalid");
|
||||||
log_warn(LD_REND, "Introduction point ntor encryption key is invalid");
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
ip->enc_key_type = HS_DESC_KEY_TYPE_CURVE25519;
|
|
||||||
} else if (!strcmp(tok->args[0], "legacy")) {
|
|
||||||
/* "enc-key" SP "legacy" NL key NL */
|
|
||||||
if (!tok->key) {
|
|
||||||
log_warn(LD_REND, "Introduction point legacy encryption key is "
|
|
||||||
"invalid");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
ip->enc_key.legacy = crypto_pk_dup_key(tok->key);
|
|
||||||
ip->enc_key_type = HS_DESC_KEY_TYPE_LEGACY;
|
|
||||||
} else {
|
} else {
|
||||||
/* Unknown key type so we can't use that introduction point. */
|
/* Unknown key type so we can't use that introduction point. */
|
||||||
log_warn(LD_REND, "Introduction point encryption key is unrecognized.");
|
log_warn(LD_REND, "Introduction point encryption key is unrecognized.");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "enc-key-certification" NL certificate NL */
|
/* Exactly once "enc-key-cert" NL certificate NL */
|
||||||
tok = find_by_keyword(tokens, R3_INTRO_ENC_KEY_CERTIFICATION);
|
tok = find_by_keyword(tokens, R3_INTRO_ENC_KEY_CERT);
|
||||||
tor_assert(tok->object_body);
|
tor_assert(tok->object_body);
|
||||||
/* Do the cross certification. */
|
/* Do the cross certification. */
|
||||||
switch (ip->enc_key_type) {
|
if (strcmp(tok->object_type, "ED25519 CERT")) {
|
||||||
case HS_DESC_KEY_TYPE_CURVE25519:
|
|
||||||
{
|
|
||||||
if (strcmp(tok->object_type, "ED25519 CERT")) {
|
|
||||||
log_warn(LD_REND, "Introduction point ntor encryption key "
|
log_warn(LD_REND, "Introduction point ntor encryption key "
|
||||||
"cross-certification has an unknown format.");
|
"cross-certification has an unknown format.");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
if (cert_parse_and_validate(&cross_cert, tok->object_body,
|
|
||||||
tok->object_size, CERT_TYPE_CROSS_HS_IP_KEYS,
|
|
||||||
"introduction point enc-key-certification") < 0) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case HS_DESC_KEY_TYPE_LEGACY:
|
if (cert_parse_and_validate(&ip->enc_key_cert, tok->object_body,
|
||||||
if (strcmp(tok->object_type, "CROSSCERT")) {
|
tok->object_size, CERT_TYPE_CROSS_HS_IP_KEYS,
|
||||||
log_warn(LD_REND, "Introduction point legacy encryption key "
|
"introduction point enc-key-cert") < 0) {
|
||||||
"cross-certification has an unknown format.");
|
goto err;
|
||||||
goto err;
|
}
|
||||||
}
|
if (tor_cert_checksig(ip->enc_key_cert,
|
||||||
if (rsa_ed25519_crosscert_check((const uint8_t *) tok->object_body,
|
&desc->plaintext_data.signing_pubkey, 0) < 0) {
|
||||||
tok->object_size, ip->enc_key.legacy,
|
log_warn(LD_REND, "Invalid encryption key signature");
|
||||||
&desc->plaintext_data.signing_key_cert->signed_key,
|
goto err;
|
||||||
approx_time()-86400)) {
|
|
||||||
log_warn(LD_REND, "Unable to check cross-certification on the "
|
|
||||||
"introduction point legacy encryption key.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tor_assert(0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
/* It is successfully cross certified. Flag the object. */
|
/* It is successfully cross certified. Flag the object. */
|
||||||
ip->cross_certified = 1;
|
ip->cross_certified = 1;
|
||||||
|
|
||||||
|
/* Do we have a "legacy-key" SP key NL ?*/
|
||||||
|
tok = find_opt_by_keyword(tokens, R3_INTRO_LEGACY_KEY);
|
||||||
|
if (tok) {
|
||||||
|
if (decode_intro_legacy_key(tok, tokens, ip, desc) < 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Introduction point has been parsed successfully. */
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -1710,7 +1736,6 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start)
|
|||||||
ip = NULL;
|
ip = NULL;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
tor_cert_free(cross_cert);
|
|
||||||
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
|
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
|
||||||
smartlist_free(tokens);
|
smartlist_free(tokens);
|
||||||
if (area) {
|
if (area) {
|
||||||
|
@ -58,12 +58,6 @@ typedef enum {
|
|||||||
HS_DESC_AUTH_ED25519 = 1
|
HS_DESC_AUTH_ED25519 = 1
|
||||||
} hs_desc_auth_type_t;
|
} hs_desc_auth_type_t;
|
||||||
|
|
||||||
/* Type of encryption key in the descriptor. */
|
|
||||||
typedef enum {
|
|
||||||
HS_DESC_KEY_TYPE_LEGACY = 1,
|
|
||||||
HS_DESC_KEY_TYPE_CURVE25519 = 2,
|
|
||||||
} hs_desc_key_type_t;
|
|
||||||
|
|
||||||
/* Link specifier object that contains information on how to extend to the
|
/* Link specifier object that contains information on how to extend to the
|
||||||
* relay that is the address, port and handshake type. */
|
* relay that is the address, port and handshake type. */
|
||||||
typedef struct hs_desc_link_specifier_t {
|
typedef struct hs_desc_link_specifier_t {
|
||||||
@ -91,18 +85,29 @@ typedef struct hs_desc_intro_point_t {
|
|||||||
* the blinded key and in turn signs it. */
|
* the blinded key and in turn signs it. */
|
||||||
tor_cert_t *auth_key_cert;
|
tor_cert_t *auth_key_cert;
|
||||||
|
|
||||||
/* Encryption key type so we know which one to use in the union below. */
|
/* Encryption key for the "ntor" type. */
|
||||||
hs_desc_key_type_t enc_key_type;
|
curve25519_public_key_t enc_key;
|
||||||
|
|
||||||
/* Keys are mutually exclusive thus the union. */
|
/* Certificate cross certifying the descriptor signing key by the encryption
|
||||||
union {
|
* curve25519 key. This certificate contains the signing key and is of type
|
||||||
/* Encryption key used to encrypt request to hidden service. */
|
* CERT_TYPE_CROSS_HS_IP_KEYS [0B]. */
|
||||||
curve25519_keypair_t curve25519;
|
tor_cert_t *enc_key_cert;
|
||||||
|
|
||||||
/* Backward compat: RSA 1024 encryption key for legacy purposes.
|
/* (Optional): If this introduction point is a legacy one that is version <=
|
||||||
* Mutually exclusive with enc_key. */
|
* 0.2.9.x (HSIntro=3), we use this extra key for the intro point to be able
|
||||||
crypto_pk_t *legacy;
|
* to relay the cells to the service correctly. */
|
||||||
} enc_key;
|
struct {
|
||||||
|
/* RSA public key. */
|
||||||
|
crypto_pk_t *key;
|
||||||
|
|
||||||
|
/* Cross certified cert with the descriptor signing key (RSA->Ed). Because
|
||||||
|
* of the cross certification API, we need to keep the certificate binary
|
||||||
|
* blob and its length in order to properly encode it after. */
|
||||||
|
struct {
|
||||||
|
uint8_t *encoded;
|
||||||
|
size_t len;
|
||||||
|
} cert;
|
||||||
|
} legacy;
|
||||||
|
|
||||||
/* True iff the introduction point has passed the cross certification. Upon
|
/* True iff the introduction point has passed the cross certification. Upon
|
||||||
* decoding an intro point, this must be true. */
|
* decoding an intro point, this must be true. */
|
||||||
|
@ -162,7 +162,9 @@ typedef enum {
|
|||||||
R3_INTRODUCTION_POINT,
|
R3_INTRODUCTION_POINT,
|
||||||
R3_INTRO_AUTH_KEY,
|
R3_INTRO_AUTH_KEY,
|
||||||
R3_INTRO_ENC_KEY,
|
R3_INTRO_ENC_KEY,
|
||||||
R3_INTRO_ENC_KEY_CERTIFICATION,
|
R3_INTRO_ENC_KEY_CERT,
|
||||||
|
R3_INTRO_LEGACY_KEY,
|
||||||
|
R3_INTRO_LEGACY_KEY_CERT,
|
||||||
R3_DESC_AUTH_TYPE,
|
R3_DESC_AUTH_TYPE,
|
||||||
R3_DESC_AUTH_KEY,
|
R3_DESC_AUTH_KEY,
|
||||||
R3_DESC_AUTH_CLIENT,
|
R3_DESC_AUTH_CLIENT,
|
||||||
|
257
src/test/hs_test_helpers.c
Normal file
257
src/test/hs_test_helpers.c
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
/* Copyright (c) 2017, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#include "or.h"
|
||||||
|
#include "crypto_ed25519.h"
|
||||||
|
#include "test.h"
|
||||||
|
#include "torcert.h"
|
||||||
|
|
||||||
|
#include "hs_test_helpers.h"
|
||||||
|
|
||||||
|
hs_desc_intro_point_t *
|
||||||
|
hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
|
||||||
|
const char *addr, int legacy)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ed25519_keypair_t auth_kp;
|
||||||
|
hs_desc_intro_point_t *intro_point = NULL;
|
||||||
|
hs_desc_intro_point_t *ip = tor_malloc_zero(sizeof(*ip));
|
||||||
|
ip->link_specifiers = smartlist_new();
|
||||||
|
|
||||||
|
{
|
||||||
|
hs_desc_link_specifier_t *ls = tor_malloc_zero(sizeof(*ls));
|
||||||
|
if (legacy) {
|
||||||
|
ls->type = LS_LEGACY_ID;
|
||||||
|
memcpy(ls->u.legacy_id, "0299F268FCA9D55CD157976D39AE92B4B455B3A8",
|
||||||
|
DIGEST_LEN);
|
||||||
|
} else {
|
||||||
|
ls->u.ap.port = 9001;
|
||||||
|
int family = tor_addr_parse(&ls->u.ap.addr, addr);
|
||||||
|
switch (family) {
|
||||||
|
case AF_INET:
|
||||||
|
ls->type = LS_IPV4;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
ls->type = LS_IPV6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Stop the test, not suppose to have an error. */
|
||||||
|
tt_int_op(family, OP_EQ, AF_INET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
smartlist_add(ip->link_specifiers, ls);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ed25519_keypair_generate(&auth_kp, 0);
|
||||||
|
tt_int_op(ret, ==, 0);
|
||||||
|
ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY,
|
||||||
|
&auth_kp.pubkey, now,
|
||||||
|
HS_DESC_CERT_LIFETIME,
|
||||||
|
CERT_FLAG_INCLUDE_SIGNING_KEY);
|
||||||
|
tt_assert(ip->auth_key_cert);
|
||||||
|
|
||||||
|
if (legacy) {
|
||||||
|
ip->legacy.key = crypto_pk_new();
|
||||||
|
tt_assert(ip->legacy.key);
|
||||||
|
ret = crypto_pk_generate_key(ip->legacy.key);
|
||||||
|
tt_int_op(ret, ==, 0);
|
||||||
|
ssize_t cert_len = tor_make_rsa_ed25519_crosscert(
|
||||||
|
&signing_kp->pubkey, ip->legacy.key,
|
||||||
|
now + HS_DESC_CERT_LIFETIME,
|
||||||
|
&ip->legacy.cert.encoded);
|
||||||
|
tt_assert(ip->legacy.cert.encoded);
|
||||||
|
tt_u64_op(cert_len, OP_GT, 0);
|
||||||
|
ip->legacy.cert.len = cert_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encryption key. */
|
||||||
|
{
|
||||||
|
int signbit;
|
||||||
|
curve25519_keypair_t curve25519_kp;
|
||||||
|
ed25519_keypair_t ed25519_kp;
|
||||||
|
tor_cert_t *cross_cert;
|
||||||
|
|
||||||
|
ret = curve25519_keypair_generate(&curve25519_kp, 0);
|
||||||
|
tt_int_op(ret, ==, 0);
|
||||||
|
ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit,
|
||||||
|
&curve25519_kp);
|
||||||
|
cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
|
||||||
|
&ed25519_kp.pubkey, time(NULL),
|
||||||
|
HS_DESC_CERT_LIFETIME,
|
||||||
|
CERT_FLAG_INCLUDE_SIGNING_KEY);
|
||||||
|
tt_assert(cross_cert);
|
||||||
|
ip->enc_key_cert = cross_cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
intro_point = ip;
|
||||||
|
done:
|
||||||
|
return intro_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return a valid hs_descriptor_t object. If no_ip is set, no introduction
|
||||||
|
* points are added. */
|
||||||
|
static hs_descriptor_t *
|
||||||
|
hs_helper_build_hs_desc_impl(unsigned int no_ip,
|
||||||
|
const ed25519_keypair_t *signing_kp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
time_t now = time(NULL);
|
||||||
|
ed25519_keypair_t blinded_kp;
|
||||||
|
hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc));
|
||||||
|
|
||||||
|
desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX;
|
||||||
|
|
||||||
|
/* Copy only the public key into the descriptor. */
|
||||||
|
memcpy(&desc->plaintext_data.signing_pubkey, &signing_kp->pubkey,
|
||||||
|
sizeof(ed25519_public_key_t));
|
||||||
|
|
||||||
|
ret = ed25519_keypair_generate(&blinded_kp, 0);
|
||||||
|
tt_int_op(ret, ==, 0);
|
||||||
|
/* Copy only the public key into the descriptor. */
|
||||||
|
memcpy(&desc->plaintext_data.blinded_pubkey, &blinded_kp.pubkey,
|
||||||
|
sizeof(ed25519_public_key_t));
|
||||||
|
|
||||||
|
desc->plaintext_data.signing_key_cert =
|
||||||
|
tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
|
||||||
|
&signing_kp->pubkey, now, 3600,
|
||||||
|
CERT_FLAG_INCLUDE_SIGNING_KEY);
|
||||||
|
tt_assert(desc->plaintext_data.signing_key_cert);
|
||||||
|
desc->plaintext_data.revision_counter = 42;
|
||||||
|
desc->plaintext_data.lifetime_sec = 3 * 60 * 60;
|
||||||
|
|
||||||
|
/* Setup encrypted data section. */
|
||||||
|
desc->encrypted_data.create2_ntor = 1;
|
||||||
|
desc->encrypted_data.intro_auth_types = smartlist_new();
|
||||||
|
desc->encrypted_data.single_onion_service = 1;
|
||||||
|
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. */
|
||||||
|
smartlist_add(desc->encrypted_data.intro_points,
|
||||||
|
hs_helper_build_intro_point(signing_kp, now, "1.2.3.4", 0));
|
||||||
|
smartlist_add(desc->encrypted_data.intro_points,
|
||||||
|
hs_helper_build_intro_point(signing_kp, now, "[2600::1]", 0));
|
||||||
|
smartlist_add(desc->encrypted_data.intro_points,
|
||||||
|
hs_helper_build_intro_point(signing_kp, now, "3.2.1.4", 1));
|
||||||
|
smartlist_add(desc->encrypted_data.intro_points,
|
||||||
|
hs_helper_build_intro_point(signing_kp, now, "", 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
descp = desc;
|
||||||
|
done:
|
||||||
|
return descp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a descriptor with introduction points. */
|
||||||
|
hs_descriptor_t *
|
||||||
|
hs_helper_build_hs_desc_with_ip(const ed25519_keypair_t *signing_kp)
|
||||||
|
{
|
||||||
|
return hs_helper_build_hs_desc_impl(0, signing_kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a descriptor without any introduction points. */
|
||||||
|
hs_descriptor_t *
|
||||||
|
hs_helper_build_hs_desc_no_ip(const ed25519_keypair_t *signing_kp)
|
||||||
|
{
|
||||||
|
return hs_helper_build_hs_desc_impl(1, signing_kp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hs_helper_desc_equal(const hs_descriptor_t *desc1,
|
||||||
|
const hs_descriptor_t *desc2)
|
||||||
|
{
|
||||||
|
char *addr1 = NULL, *addr2 = NULL;
|
||||||
|
/* Plaintext data section. */
|
||||||
|
tt_int_op(desc1->plaintext_data.version, OP_EQ,
|
||||||
|
desc2->plaintext_data.version);
|
||||||
|
tt_uint_op(desc1->plaintext_data.lifetime_sec, OP_EQ,
|
||||||
|
desc2->plaintext_data.lifetime_sec);
|
||||||
|
tt_assert(tor_cert_eq(desc1->plaintext_data.signing_key_cert,
|
||||||
|
desc2->plaintext_data.signing_key_cert));
|
||||||
|
tt_mem_op(desc1->plaintext_data.signing_pubkey.pubkey, OP_EQ,
|
||||||
|
desc2->plaintext_data.signing_pubkey.pubkey,
|
||||||
|
ED25519_PUBKEY_LEN);
|
||||||
|
tt_mem_op(desc1->plaintext_data.blinded_pubkey.pubkey, OP_EQ,
|
||||||
|
desc2->plaintext_data.blinded_pubkey.pubkey,
|
||||||
|
ED25519_PUBKEY_LEN);
|
||||||
|
tt_u64_op(desc1->plaintext_data.revision_counter, ==,
|
||||||
|
desc2->plaintext_data.revision_counter);
|
||||||
|
|
||||||
|
/* NOTE: We can't compare the encrypted blob because when encoding the
|
||||||
|
* descriptor, the object is immutable thus we don't update it with the
|
||||||
|
* encrypted blob. As contrast to the decoding process where we populate a
|
||||||
|
* descriptor object. */
|
||||||
|
|
||||||
|
/* Encrypted data section. */
|
||||||
|
tt_uint_op(desc1->encrypted_data.create2_ntor, ==,
|
||||||
|
desc2->encrypted_data.create2_ntor);
|
||||||
|
|
||||||
|
/* Authentication type. */
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Introduction points. */
|
||||||
|
{
|
||||||
|
tt_assert(desc1->encrypted_data.intro_points);
|
||||||
|
tt_assert(desc2->encrypted_data.intro_points);
|
||||||
|
tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), ==,
|
||||||
|
smartlist_len(desc2->encrypted_data.intro_points));
|
||||||
|
for (int i=0; i < smartlist_len(desc1->encrypted_data.intro_points); i++) {
|
||||||
|
hs_desc_intro_point_t *ip1 = smartlist_get(desc1->encrypted_data
|
||||||
|
.intro_points, i),
|
||||||
|
*ip2 = smartlist_get(desc2->encrypted_data
|
||||||
|
.intro_points, i);
|
||||||
|
tt_assert(tor_cert_eq(ip1->auth_key_cert, ip2->auth_key_cert));
|
||||||
|
if (ip1->legacy.key) {
|
||||||
|
tt_int_op(crypto_pk_cmp_keys(ip1->legacy.key, ip2->legacy.key),
|
||||||
|
OP_EQ, 0);
|
||||||
|
} else {
|
||||||
|
tt_mem_op(&ip1->enc_key, OP_EQ, &ip2->enc_key, CURVE25519_PUBKEY_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
tt_int_op(smartlist_len(ip1->link_specifiers), ==,
|
||||||
|
smartlist_len(ip2->link_specifiers));
|
||||||
|
for (int j = 0; j < smartlist_len(ip1->link_specifiers); j++) {
|
||||||
|
hs_desc_link_specifier_t *ls1 = smartlist_get(ip1->link_specifiers, j),
|
||||||
|
*ls2 = smartlist_get(ip2->link_specifiers, j);
|
||||||
|
tt_int_op(ls1->type, ==, ls2->type);
|
||||||
|
switch (ls1->type) {
|
||||||
|
case LS_IPV4:
|
||||||
|
case LS_IPV6:
|
||||||
|
{
|
||||||
|
addr1 = tor_addr_to_str_dup(&ls1->u.ap.addr);
|
||||||
|
addr2 = tor_addr_to_str_dup(&ls2->u.ap.addr);
|
||||||
|
tt_str_op(addr1, OP_EQ, addr2);
|
||||||
|
tor_free(addr1);
|
||||||
|
tor_free(addr2);
|
||||||
|
tt_int_op(ls1->u.ap.port, ==, ls2->u.ap.port);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LS_LEGACY_ID:
|
||||||
|
tt_mem_op(ls1->u.legacy_id, OP_EQ, ls2->u.legacy_id,
|
||||||
|
sizeof(ls1->u.legacy_id));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unknown type, caught it and print its value. */
|
||||||
|
tt_int_op(ls1->type, OP_EQ, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
tor_free(addr1);
|
||||||
|
tor_free(addr2);
|
||||||
|
}
|
||||||
|
|
22
src/test/hs_test_helpers.h
Normal file
22
src/test/hs_test_helpers.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* Copyright (c) 2017, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#ifndef TOR_HS_TEST_HELPERS_H
|
||||||
|
#define TOR_HS_TEST_HELPERS_H
|
||||||
|
|
||||||
|
#include "ed25519_cert.h"
|
||||||
|
#include "hs_descriptor.h"
|
||||||
|
|
||||||
|
/* Set of functions to help build and test descriptors. */
|
||||||
|
hs_desc_intro_point_t *hs_helper_build_intro_point(
|
||||||
|
const ed25519_keypair_t *signing_kp, time_t now,
|
||||||
|
const char *addr, int legacy);
|
||||||
|
hs_descriptor_t *hs_helper_build_hs_desc_no_ip(
|
||||||
|
const ed25519_keypair_t *signing_kp);
|
||||||
|
hs_descriptor_t *hs_helper_build_hs_desc_with_ip(
|
||||||
|
const ed25519_keypair_t *signing_kp);
|
||||||
|
void hs_helper_desc_equal(const hs_descriptor_t *desc1,
|
||||||
|
const hs_descriptor_t *desc2);
|
||||||
|
|
||||||
|
#endif /* TOR_HS_TEST_HELPERS_H */
|
||||||
|
|
@ -69,6 +69,7 @@ src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
|
|||||||
|
|
||||||
src_test_test_SOURCES = \
|
src_test_test_SOURCES = \
|
||||||
src/test/log_test_helpers.c \
|
src/test/log_test_helpers.c \
|
||||||
|
src/test/hs_test_helpers.c \
|
||||||
src/test/rend_test_helpers.c \
|
src/test/rend_test_helpers.c \
|
||||||
src/test/test.c \
|
src/test/test.c \
|
||||||
src/test/test_accounting.c \
|
src/test/test_accounting.c \
|
||||||
|
@ -15,96 +15,10 @@
|
|||||||
#include "directory.h"
|
#include "directory.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
|
#include "hs_test_helpers.h"
|
||||||
#include "test_helpers.h"
|
#include "test_helpers.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
/* Build an intro point using a blinded key and an address. */
|
|
||||||
static hs_desc_intro_point_t *
|
|
||||||
helper_build_intro_point(const ed25519_keypair_t *blinded_kp,
|
|
||||||
const char *addr)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
ed25519_keypair_t auth_kp;
|
|
||||||
hs_desc_intro_point_t *intro_point = NULL;
|
|
||||||
hs_desc_intro_point_t *ip = tor_malloc_zero(sizeof(*ip));
|
|
||||||
ip->link_specifiers = smartlist_new();
|
|
||||||
|
|
||||||
{
|
|
||||||
hs_desc_link_specifier_t *ls = tor_malloc_zero(sizeof(*ls));
|
|
||||||
ls->u.ap.port = 9001;
|
|
||||||
int family = tor_addr_parse(&ls->u.ap.addr, addr);
|
|
||||||
switch (family) {
|
|
||||||
case AF_INET:
|
|
||||||
ls->type = LS_IPV4;
|
|
||||||
break;
|
|
||||||
case AF_INET6:
|
|
||||||
ls->type = LS_IPV6;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Stop the test, not suppose to have an error. */
|
|
||||||
tt_int_op(family, OP_EQ, AF_INET);
|
|
||||||
}
|
|
||||||
smartlist_add(ip->link_specifiers, ls);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ed25519_keypair_generate(&auth_kp, 0);
|
|
||||||
tt_int_op(ret, ==, 0);
|
|
||||||
ip->auth_key_cert = tor_cert_create(blinded_kp, CERT_TYPE_AUTH_HS_IP_KEY,
|
|
||||||
&auth_kp.pubkey, time(NULL),
|
|
||||||
HS_DESC_CERT_LIFETIME,
|
|
||||||
CERT_FLAG_INCLUDE_SIGNING_KEY);
|
|
||||||
tt_assert(ip->auth_key_cert);
|
|
||||||
|
|
||||||
ret = curve25519_keypair_generate(&ip->enc_key.curve25519, 0);
|
|
||||||
tt_int_op(ret, ==, 0);
|
|
||||||
ip->enc_key_type = HS_DESC_KEY_TYPE_CURVE25519;
|
|
||||||
intro_point = ip;
|
|
||||||
done:
|
|
||||||
return intro_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a valid hs_descriptor_t object. */
|
|
||||||
static hs_descriptor_t *
|
|
||||||
helper_build_hs_desc(uint64_t revision_counter, uint32_t lifetime,
|
|
||||||
ed25519_public_key_t *signing_pubkey)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
ed25519_keypair_t blinded_kp;
|
|
||||||
hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc));
|
|
||||||
|
|
||||||
desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX;
|
|
||||||
|
|
||||||
/* Copy only the public key into the descriptor. */
|
|
||||||
memcpy(&desc->plaintext_data.signing_pubkey, signing_pubkey,
|
|
||||||
sizeof(ed25519_public_key_t));
|
|
||||||
|
|
||||||
ret = ed25519_keypair_generate(&blinded_kp, 0);
|
|
||||||
tt_int_op(ret, ==, 0);
|
|
||||||
/* Copy only the public key into the descriptor. */
|
|
||||||
memcpy(&desc->plaintext_data.blinded_pubkey, &blinded_kp.pubkey,
|
|
||||||
sizeof(ed25519_public_key_t));
|
|
||||||
|
|
||||||
desc->plaintext_data.signing_key_cert =
|
|
||||||
tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC, signing_pubkey,
|
|
||||||
time(NULL), 3600, CERT_FLAG_INCLUDE_SIGNING_KEY);
|
|
||||||
tt_assert(desc->plaintext_data.signing_key_cert);
|
|
||||||
desc->plaintext_data.revision_counter = revision_counter;
|
|
||||||
desc->plaintext_data.lifetime_sec = lifetime;
|
|
||||||
|
|
||||||
/* Setup encrypted data section. */
|
|
||||||
desc->encrypted_data.create2_ntor = 1;
|
|
||||||
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,
|
|
||||||
helper_build_intro_point(&blinded_kp, "1.2.3.4"));
|
|
||||||
|
|
||||||
descp = desc;
|
|
||||||
done:
|
|
||||||
return descp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Static variable used to encoded the HSDir query. */
|
/* Static variable used to encoded the HSDir query. */
|
||||||
static char query_b64[256];
|
static char query_b64[256];
|
||||||
|
|
||||||
@ -141,7 +55,7 @@ test_directory(void *arg)
|
|||||||
/* Generate a valid descriptor with normal values. */
|
/* Generate a valid descriptor with normal values. */
|
||||||
ret = ed25519_keypair_generate(&signing_kp1, 0);
|
ret = ed25519_keypair_generate(&signing_kp1, 0);
|
||||||
tt_int_op(ret, ==, 0);
|
tt_int_op(ret, ==, 0);
|
||||||
desc1 = helper_build_hs_desc(42, 3 * 60 * 60, &signing_kp1.pubkey);
|
desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1);
|
||||||
tt_assert(desc1);
|
tt_assert(desc1);
|
||||||
ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str);
|
ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str);
|
||||||
tt_int_op(ret, OP_EQ, 0);
|
tt_int_op(ret, OP_EQ, 0);
|
||||||
@ -175,8 +89,10 @@ test_directory(void *arg)
|
|||||||
ret = ed25519_keypair_generate(&signing_kp_zero, 0);
|
ret = ed25519_keypair_generate(&signing_kp_zero, 0);
|
||||||
tt_int_op(ret, ==, 0);
|
tt_int_op(ret, ==, 0);
|
||||||
hs_descriptor_t *desc_zero_lifetime;
|
hs_descriptor_t *desc_zero_lifetime;
|
||||||
desc_zero_lifetime = helper_build_hs_desc(1, 0, &signing_kp_zero.pubkey);
|
desc_zero_lifetime = hs_helper_build_hs_desc_with_ip(&signing_kp_zero);
|
||||||
tt_assert(desc_zero_lifetime);
|
tt_assert(desc_zero_lifetime);
|
||||||
|
desc_zero_lifetime->plaintext_data.revision_counter = 1;
|
||||||
|
desc_zero_lifetime->plaintext_data.lifetime_sec = 0;
|
||||||
char *desc_zero_lifetime_str;
|
char *desc_zero_lifetime_str;
|
||||||
ret = hs_desc_encode_descriptor(desc_zero_lifetime, &signing_kp_zero,
|
ret = hs_desc_encode_descriptor(desc_zero_lifetime, &signing_kp_zero,
|
||||||
&desc_zero_lifetime_str);
|
&desc_zero_lifetime_str);
|
||||||
@ -262,7 +178,7 @@ test_clean_as_dir(void *arg)
|
|||||||
/* Generate a valid descriptor with values. */
|
/* Generate a valid descriptor with values. */
|
||||||
ret = ed25519_keypair_generate(&signing_kp1, 0);
|
ret = ed25519_keypair_generate(&signing_kp1, 0);
|
||||||
tt_int_op(ret, ==, 0);
|
tt_int_op(ret, ==, 0);
|
||||||
desc1 = helper_build_hs_desc(42, 3 * 60 * 60, &signing_kp1.pubkey);
|
desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1);
|
||||||
tt_assert(desc1);
|
tt_assert(desc1);
|
||||||
ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str);
|
ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str);
|
||||||
tt_int_op(ret, OP_EQ, 0);
|
tt_int_op(ret, OP_EQ, 0);
|
||||||
@ -375,7 +291,7 @@ test_upload_and_download_hs_desc(void *arg)
|
|||||||
ed25519_keypair_t signing_kp;
|
ed25519_keypair_t signing_kp;
|
||||||
retval = ed25519_keypair_generate(&signing_kp, 0);
|
retval = ed25519_keypair_generate(&signing_kp, 0);
|
||||||
tt_int_op(retval, ==, 0);
|
tt_int_op(retval, ==, 0);
|
||||||
published_desc = helper_build_hs_desc(42, 3 * 60 * 60, &signing_kp.pubkey);
|
published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
|
||||||
tt_assert(published_desc);
|
tt_assert(published_desc);
|
||||||
retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
|
retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
|
||||||
&published_desc_str);
|
&published_desc_str);
|
||||||
@ -438,8 +354,7 @@ test_hsdir_revision_counter_check(void *arg)
|
|||||||
{
|
{
|
||||||
retval = ed25519_keypair_generate(&signing_kp, 0);
|
retval = ed25519_keypair_generate(&signing_kp, 0);
|
||||||
tt_int_op(retval, ==, 0);
|
tt_int_op(retval, ==, 0);
|
||||||
published_desc = helper_build_hs_desc(1312, 3 * 60 * 60,
|
published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
|
||||||
&signing_kp.pubkey);
|
|
||||||
tt_assert(published_desc);
|
tt_assert(published_desc);
|
||||||
retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
|
retval = hs_desc_encode_descriptor(published_desc, &signing_kp,
|
||||||
&published_desc_str);
|
&published_desc_str);
|
||||||
@ -470,7 +385,7 @@ test_hsdir_revision_counter_check(void *arg)
|
|||||||
tt_assert(received_desc);
|
tt_assert(received_desc);
|
||||||
|
|
||||||
/* Check that the revision counter is correct */
|
/* Check that the revision counter is correct */
|
||||||
tt_u64_op(received_desc->plaintext_data.revision_counter, ==, 1312);
|
tt_u64_op(received_desc->plaintext_data.revision_counter, ==, 42);
|
||||||
|
|
||||||
hs_descriptor_free(received_desc);
|
hs_descriptor_free(received_desc);
|
||||||
received_desc = NULL;
|
received_desc = NULL;
|
||||||
|
@ -15,227 +15,10 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include "torcert.h"
|
#include "torcert.h"
|
||||||
|
|
||||||
|
#include "hs_test_helpers.h"
|
||||||
#include "test_helpers.h"
|
#include "test_helpers.h"
|
||||||
#include "log_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)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
ed25519_keypair_t auth_kp;
|
|
||||||
hs_desc_intro_point_t *intro_point = NULL;
|
|
||||||
hs_desc_intro_point_t *ip = tor_malloc_zero(sizeof(*ip));
|
|
||||||
ip->link_specifiers = smartlist_new();
|
|
||||||
|
|
||||||
{
|
|
||||||
hs_desc_link_specifier_t *ls = tor_malloc_zero(sizeof(*ls));
|
|
||||||
if (legacy) {
|
|
||||||
ls->type = LS_LEGACY_ID;
|
|
||||||
memcpy(ls->u.legacy_id, "0299F268FCA9D55CD157976D39AE92B4B455B3A8",
|
|
||||||
DIGEST_LEN);
|
|
||||||
} else {
|
|
||||||
ls->u.ap.port = 9001;
|
|
||||||
int family = tor_addr_parse(&ls->u.ap.addr, addr);
|
|
||||||
switch (family) {
|
|
||||||
case AF_INET:
|
|
||||||
ls->type = LS_IPV4;
|
|
||||||
break;
|
|
||||||
case AF_INET6:
|
|
||||||
ls->type = LS_IPV6;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Stop the test, not suppose to have an error. */
|
|
||||||
tt_int_op(family, OP_EQ, AF_INET);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
smartlist_add(ip->link_specifiers, ls);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ed25519_keypair_generate(&auth_kp, 0);
|
|
||||||
tt_int_op(ret, ==, 0);
|
|
||||||
ip->auth_key_cert = tor_cert_create(blinded_kp, CERT_TYPE_AUTH_HS_IP_KEY,
|
|
||||||
&auth_kp.pubkey, now,
|
|
||||||
HS_DESC_CERT_LIFETIME,
|
|
||||||
CERT_FLAG_INCLUDE_SIGNING_KEY);
|
|
||||||
tt_assert(ip->auth_key_cert);
|
|
||||||
|
|
||||||
if (legacy) {
|
|
||||||
ip->enc_key.legacy = crypto_pk_new();
|
|
||||||
ip->enc_key_type = HS_DESC_KEY_TYPE_LEGACY;
|
|
||||||
tt_assert(ip->enc_key.legacy);
|
|
||||||
ret = crypto_pk_generate_key(ip->enc_key.legacy);
|
|
||||||
tt_int_op(ret, ==, 0);
|
|
||||||
} else {
|
|
||||||
ret = curve25519_keypair_generate(&ip->enc_key.curve25519, 0);
|
|
||||||
tt_int_op(ret, ==, 0);
|
|
||||||
ip->enc_key_type = HS_DESC_KEY_TYPE_CURVE25519;
|
|
||||||
}
|
|
||||||
|
|
||||||
intro_point = ip;
|
|
||||||
done:
|
|
||||||
return intro_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a valid hs_descriptor_t object. If no_ip is set, no introduction
|
|
||||||
* points are added. */
|
|
||||||
static hs_descriptor_t *
|
|
||||||
helper_build_hs_desc(unsigned int no_ip, ed25519_public_key_t *signing_pubkey)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
time_t now = time(NULL);
|
|
||||||
ed25519_keypair_t blinded_kp;
|
|
||||||
hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc));
|
|
||||||
|
|
||||||
desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX;
|
|
||||||
|
|
||||||
/* Copy only the public key into the descriptor. */
|
|
||||||
memcpy(&desc->plaintext_data.signing_pubkey, signing_pubkey,
|
|
||||||
sizeof(ed25519_public_key_t));
|
|
||||||
|
|
||||||
ret = ed25519_keypair_generate(&blinded_kp, 0);
|
|
||||||
tt_int_op(ret, ==, 0);
|
|
||||||
/* Copy only the public key into the descriptor. */
|
|
||||||
memcpy(&desc->plaintext_data.blinded_pubkey, &blinded_kp.pubkey,
|
|
||||||
sizeof(ed25519_public_key_t));
|
|
||||||
|
|
||||||
desc->plaintext_data.signing_key_cert =
|
|
||||||
tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC, signing_pubkey,
|
|
||||||
now, 3600, CERT_FLAG_INCLUDE_SIGNING_KEY);
|
|
||||||
tt_assert(desc->plaintext_data.signing_key_cert);
|
|
||||||
desc->plaintext_data.revision_counter = 42;
|
|
||||||
desc->plaintext_data.lifetime_sec = 3 * 60 * 60;
|
|
||||||
|
|
||||||
/* Setup encrypted data section. */
|
|
||||||
desc->encrypted_data.create2_ntor = 1;
|
|
||||||
desc->encrypted_data.intro_auth_types = smartlist_new();
|
|
||||||
desc->encrypted_data.single_onion_service = 1;
|
|
||||||
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. */
|
|
||||||
smartlist_add(desc->encrypted_data.intro_points,
|
|
||||||
helper_build_intro_point(&blinded_kp, now, "1.2.3.4", 0));
|
|
||||||
smartlist_add(desc->encrypted_data.intro_points,
|
|
||||||
helper_build_intro_point(&blinded_kp, now, "[2600::1]", 0));
|
|
||||||
smartlist_add(desc->encrypted_data.intro_points,
|
|
||||||
helper_build_intro_point(&blinded_kp, now, "3.2.1.4", 1));
|
|
||||||
smartlist_add(desc->encrypted_data.intro_points,
|
|
||||||
helper_build_intro_point(&blinded_kp, now, "", 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
descp = desc;
|
|
||||||
done:
|
|
||||||
return descp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
helper_compare_hs_desc(const hs_descriptor_t *desc1,
|
|
||||||
const hs_descriptor_t *desc2)
|
|
||||||
{
|
|
||||||
char *addr1 = NULL, *addr2 = NULL;
|
|
||||||
/* Plaintext data section. */
|
|
||||||
tt_int_op(desc1->plaintext_data.version, OP_EQ,
|
|
||||||
desc2->plaintext_data.version);
|
|
||||||
tt_uint_op(desc1->plaintext_data.lifetime_sec, OP_EQ,
|
|
||||||
desc2->plaintext_data.lifetime_sec);
|
|
||||||
tt_assert(tor_cert_eq(desc1->plaintext_data.signing_key_cert,
|
|
||||||
desc2->plaintext_data.signing_key_cert));
|
|
||||||
tt_mem_op(desc1->plaintext_data.signing_pubkey.pubkey, OP_EQ,
|
|
||||||
desc2->plaintext_data.signing_pubkey.pubkey,
|
|
||||||
ED25519_PUBKEY_LEN);
|
|
||||||
tt_mem_op(desc1->plaintext_data.blinded_pubkey.pubkey, OP_EQ,
|
|
||||||
desc2->plaintext_data.blinded_pubkey.pubkey,
|
|
||||||
ED25519_PUBKEY_LEN);
|
|
||||||
tt_u64_op(desc1->plaintext_data.revision_counter, ==,
|
|
||||||
desc2->plaintext_data.revision_counter);
|
|
||||||
|
|
||||||
/* NOTE: We can't compare the encrypted blob because when encoding the
|
|
||||||
* descriptor, the object is immutable thus we don't update it with the
|
|
||||||
* encrypted blob. As contrast to the decoding process where we populate a
|
|
||||||
* descriptor object. */
|
|
||||||
|
|
||||||
/* Encrypted data section. */
|
|
||||||
tt_uint_op(desc1->encrypted_data.create2_ntor, ==,
|
|
||||||
desc2->encrypted_data.create2_ntor);
|
|
||||||
|
|
||||||
/* Authentication type. */
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Introduction points. */
|
|
||||||
{
|
|
||||||
tt_assert(desc1->encrypted_data.intro_points);
|
|
||||||
tt_assert(desc2->encrypted_data.intro_points);
|
|
||||||
tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), ==,
|
|
||||||
smartlist_len(desc2->encrypted_data.intro_points));
|
|
||||||
for (int i=0; i < smartlist_len(desc1->encrypted_data.intro_points); i++) {
|
|
||||||
hs_desc_intro_point_t *ip1 = smartlist_get(desc1->encrypted_data
|
|
||||||
.intro_points, i),
|
|
||||||
*ip2 = smartlist_get(desc2->encrypted_data
|
|
||||||
.intro_points, i);
|
|
||||||
tt_assert(tor_cert_eq(ip1->auth_key_cert, ip2->auth_key_cert));
|
|
||||||
tt_int_op(ip1->enc_key_type, OP_EQ, ip2->enc_key_type);
|
|
||||||
tt_assert(ip1->enc_key_type == HS_DESC_KEY_TYPE_LEGACY ||
|
|
||||||
ip1->enc_key_type == HS_DESC_KEY_TYPE_CURVE25519);
|
|
||||||
switch (ip1->enc_key_type) {
|
|
||||||
case HS_DESC_KEY_TYPE_LEGACY:
|
|
||||||
tt_int_op(crypto_pk_cmp_keys(ip1->enc_key.legacy, ip2->enc_key.legacy),
|
|
||||||
OP_EQ, 0);
|
|
||||||
break;
|
|
||||||
case HS_DESC_KEY_TYPE_CURVE25519:
|
|
||||||
tt_mem_op(ip1->enc_key.curve25519.pubkey.public_key, OP_EQ,
|
|
||||||
ip2->enc_key.curve25519.pubkey.public_key,
|
|
||||||
CURVE25519_PUBKEY_LEN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt_int_op(smartlist_len(ip1->link_specifiers), ==,
|
|
||||||
smartlist_len(ip2->link_specifiers));
|
|
||||||
for (int j = 0; j < smartlist_len(ip1->link_specifiers); j++) {
|
|
||||||
hs_desc_link_specifier_t *ls1 = smartlist_get(ip1->link_specifiers, j),
|
|
||||||
*ls2 = smartlist_get(ip2->link_specifiers, j);
|
|
||||||
tt_int_op(ls1->type, ==, ls2->type);
|
|
||||||
switch (ls1->type) {
|
|
||||||
case LS_IPV4:
|
|
||||||
case LS_IPV6:
|
|
||||||
{
|
|
||||||
addr1 = tor_addr_to_str_dup(&ls1->u.ap.addr);
|
|
||||||
addr2 = tor_addr_to_str_dup(&ls2->u.ap.addr);
|
|
||||||
tt_str_op(addr1, OP_EQ, addr2);
|
|
||||||
tor_free(addr1);
|
|
||||||
tor_free(addr2);
|
|
||||||
tt_int_op(ls1->u.ap.port, ==, ls2->u.ap.port);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LS_LEGACY_ID:
|
|
||||||
tt_mem_op(ls1->u.legacy_id, OP_EQ, ls2->u.legacy_id,
|
|
||||||
sizeof(ls1->u.legacy_id));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Unknown type, caught it and print its value. */
|
|
||||||
tt_int_op(ls1->type, OP_EQ, -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
tor_free(addr1);
|
|
||||||
tor_free(addr2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Test certificate encoding put in a descriptor. */
|
/* Test certificate encoding put in a descriptor. */
|
||||||
static void
|
static void
|
||||||
test_cert_encoding(void *arg)
|
test_cert_encoding(void *arg)
|
||||||
@ -494,7 +277,7 @@ test_encode_descriptor(void *arg)
|
|||||||
|
|
||||||
ret = ed25519_keypair_generate(&signing_kp, 0);
|
ret = ed25519_keypair_generate(&signing_kp, 0);
|
||||||
tt_int_op(ret, ==, 0);
|
tt_int_op(ret, ==, 0);
|
||||||
desc = helper_build_hs_desc(0, &signing_kp.pubkey);
|
desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
|
||||||
ret = hs_desc_encode_descriptor(desc, &signing_kp, &encoded);
|
ret = hs_desc_encode_descriptor(desc, &signing_kp, &encoded);
|
||||||
tt_int_op(ret, ==, 0);
|
tt_int_op(ret, ==, 0);
|
||||||
tt_assert(encoded);
|
tt_assert(encoded);
|
||||||
@ -518,7 +301,7 @@ test_decode_descriptor(void *arg)
|
|||||||
|
|
||||||
ret = ed25519_keypair_generate(&signing_kp, 0);
|
ret = ed25519_keypair_generate(&signing_kp, 0);
|
||||||
tt_int_op(ret, ==, 0);
|
tt_int_op(ret, ==, 0);
|
||||||
desc = helper_build_hs_desc(0, &signing_kp.pubkey);
|
desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
|
||||||
|
|
||||||
/* Give some bad stuff to the decoding function. */
|
/* Give some bad stuff to the decoding function. */
|
||||||
ret = hs_desc_decode_descriptor("hladfjlkjadf", NULL, &decoded);
|
ret = hs_desc_decode_descriptor("hladfjlkjadf", NULL, &decoded);
|
||||||
@ -532,14 +315,14 @@ test_decode_descriptor(void *arg)
|
|||||||
tt_int_op(ret, ==, 0);
|
tt_int_op(ret, ==, 0);
|
||||||
tt_assert(decoded);
|
tt_assert(decoded);
|
||||||
|
|
||||||
helper_compare_hs_desc(desc, decoded);
|
hs_helper_desc_equal(desc, decoded);
|
||||||
|
|
||||||
/* Decode a descriptor with _no_ introduction points. */
|
/* Decode a descriptor with _no_ introduction points. */
|
||||||
{
|
{
|
||||||
ed25519_keypair_t signing_kp_no_ip;
|
ed25519_keypair_t signing_kp_no_ip;
|
||||||
ret = ed25519_keypair_generate(&signing_kp_no_ip, 0);
|
ret = ed25519_keypair_generate(&signing_kp_no_ip, 0);
|
||||||
tt_int_op(ret, ==, 0);
|
tt_int_op(ret, ==, 0);
|
||||||
desc_no_ip = helper_build_hs_desc(1, &signing_kp_no_ip.pubkey);
|
desc_no_ip = hs_helper_build_hs_desc_no_ip(&signing_kp_no_ip);
|
||||||
tt_assert(desc_no_ip);
|
tt_assert(desc_no_ip);
|
||||||
tor_free(encoded);
|
tor_free(encoded);
|
||||||
ret = hs_desc_encode_descriptor(desc_no_ip, &signing_kp_no_ip, &encoded);
|
ret = hs_desc_encode_descriptor(desc_no_ip, &signing_kp_no_ip, &encoded);
|
||||||
@ -603,7 +386,7 @@ test_encrypted_data_len(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_decode_intro_point(void *arg)
|
test_decode_invalid_intro_point(void *arg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char *encoded_ip = NULL;
|
char *encoded_ip = NULL;
|
||||||
@ -614,9 +397,6 @@ test_decode_intro_point(void *arg)
|
|||||||
|
|
||||||
(void) arg;
|
(void) arg;
|
||||||
|
|
||||||
/* The following certificate expires in 2036. After that, one of the test
|
|
||||||
* will fail because of the expiry time. */
|
|
||||||
|
|
||||||
/* Seperate pieces of a valid encoded introduction point. */
|
/* Seperate pieces of a valid encoded introduction point. */
|
||||||
const char *intro_point =
|
const char *intro_point =
|
||||||
"introduction-point AQIUMDI5OUYyNjhGQ0E5RDU1Q0QxNTc=";
|
"introduction-point AQIUMDI5OUYyNjhGQ0E5RDU1Q0QxNTc=";
|
||||||
@ -629,60 +409,13 @@ test_decode_intro_point(void *arg)
|
|||||||
"-----END ED25519 CERT-----";
|
"-----END ED25519 CERT-----";
|
||||||
const char *enc_key =
|
const char *enc_key =
|
||||||
"enc-key ntor bpZKLsuhxP6woDQ3yVyjm5gUKSk7RjfAijT2qrzbQk0=";
|
"enc-key ntor bpZKLsuhxP6woDQ3yVyjm5gUKSk7RjfAijT2qrzbQk0=";
|
||||||
const char *enc_key_legacy =
|
|
||||||
"enc-key legacy\n"
|
|
||||||
"-----BEGIN RSA PUBLIC KEY-----\n"
|
|
||||||
"MIGJAoGBAO4bATcW8kW4h6RQQAKEgg+aXCpF4JwbcO6vGZtzXTDB+HdPVQzwqkbh\n"
|
|
||||||
"XzFM6VGArhYw4m31wcP1Z7IwULir7UMnAFd7Zi62aYfU6l+Y1yAoZ1wzu1XBaAMK\n"
|
|
||||||
"ejpwQinW9nzJn7c2f69fVke3pkhxpNdUZ+vplSA/l9iY+y+v+415AgMBAAE=\n"
|
|
||||||
"-----END RSA PUBLIC KEY-----";
|
|
||||||
const char *enc_key_cert =
|
const char *enc_key_cert =
|
||||||
"enc-key-certification\n"
|
"enc-key-cert\n"
|
||||||
"-----BEGIN ED25519 CERT-----\n"
|
"-----BEGIN ED25519 CERT-----\n"
|
||||||
"AQsACOhZAUpNvCZ1aJaaR49lS6MCdsVkhVGVrRqoj0Y2T4SzroAtAQAgBABFOcGg\n"
|
"AQsACOhZAUpNvCZ1aJaaR49lS6MCdsVkhVGVrRqoj0Y2T4SzroAtAQAgBABFOcGg\n"
|
||||||
"lbTt1DF5nKTE/gU3Fr8ZtlCIOhu1A+F5LM7fqCUupfesg0KTHwyIZOYQbJuM5/he\n"
|
"lbTt1DF5nKTE/gU3Fr8ZtlCIOhu1A+F5LM7fqCUupfesg0KTHwyIZOYQbJuM5/he\n"
|
||||||
"/jDNyLy9woPJdjkxywaY2RPUxGjLYtMQV0E8PUxWyICV+7y52fTCYaKpYQw=\n"
|
"/jDNyLy9woPJdjkxywaY2RPUxGjLYtMQV0E8PUxWyICV+7y52fTCYaKpYQw=\n"
|
||||||
"-----END ED25519 CERT-----";
|
"-----END ED25519 CERT-----";
|
||||||
const char *enc_key_cert_legacy =
|
|
||||||
"enc-key-certification\n"
|
|
||||||
"-----BEGIN CROSSCERT-----\n"
|
|
||||||
"Sk28JnVolppHj2VLowJ2xWSFUZWtGqiPRjZPhLOugC0ACOhZgFPA5egeRDUXMM1U\n"
|
|
||||||
"Fn3c7Je0gJS6mVma5FzwlgwggeriF13UZcaT71vEAN/ZJXbxOfQVGMZ0rXuFpjUq\n"
|
|
||||||
"C8CvqmZIwEUaPE1nDFtmnTcucvNS1YQl9nsjH3ejbxc+4yqps/cXh46FmXsm5yz7\n"
|
|
||||||
"NZjBM9U1fbJhlNtOvrkf70K8bLk6\n"
|
|
||||||
"-----END CROSSCERT-----";
|
|
||||||
|
|
||||||
(void) enc_key_legacy;
|
|
||||||
(void) enc_key_cert_legacy;
|
|
||||||
|
|
||||||
/* Start by testing the "decode all intro points" function. */
|
|
||||||
{
|
|
||||||
char *line;
|
|
||||||
ret = ed25519_keypair_generate(&signing_kp, 0);
|
|
||||||
tt_int_op(ret, ==, 0);
|
|
||||||
desc = helper_build_hs_desc(0, &signing_kp.pubkey);
|
|
||||||
tt_assert(desc);
|
|
||||||
/* Only try to decode an incomplete introduction point section. */
|
|
||||||
tor_asprintf(&line, "\n%s", intro_point);
|
|
||||||
ret = decode_intro_points(desc, &desc->encrypted_data, line);
|
|
||||||
tor_free(line);
|
|
||||||
tt_int_op(ret, ==, -1);
|
|
||||||
|
|
||||||
/* Decode one complete intro point. */
|
|
||||||
smartlist_t *lines = smartlist_new();
|
|
||||||
smartlist_add(lines, (char *) intro_point);
|
|
||||||
smartlist_add(lines, (char *) auth_key);
|
|
||||||
smartlist_add(lines, (char *) enc_key);
|
|
||||||
smartlist_add(lines, (char *) enc_key_cert);
|
|
||||||
encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out);
|
|
||||||
tt_assert(encoded_ip);
|
|
||||||
tor_asprintf(&line, "\n%s", encoded_ip);
|
|
||||||
tor_free(encoded_ip);
|
|
||||||
ret = decode_intro_points(desc, &desc->encrypted_data, line);
|
|
||||||
tor_free(line);
|
|
||||||
smartlist_free(lines);
|
|
||||||
tt_int_op(ret, ==, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to decode a junk string. */
|
/* Try to decode a junk string. */
|
||||||
{
|
{
|
||||||
@ -690,7 +423,7 @@ test_decode_intro_point(void *arg)
|
|||||||
desc = NULL;
|
desc = NULL;
|
||||||
ret = ed25519_keypair_generate(&signing_kp, 0);
|
ret = ed25519_keypair_generate(&signing_kp, 0);
|
||||||
tt_int_op(ret, ==, 0);
|
tt_int_op(ret, ==, 0);
|
||||||
desc = helper_build_hs_desc(0, &signing_kp.pubkey);
|
desc = hs_helper_build_hs_desc_with_ip(&signing_kp);
|
||||||
const char *junk = "this is not a descriptor";
|
const char *junk = "this is not a descriptor";
|
||||||
ip = decode_introduction_point(desc, junk);
|
ip = decode_introduction_point(desc, junk);
|
||||||
tt_assert(!ip);
|
tt_assert(!ip);
|
||||||
@ -796,7 +529,7 @@ test_decode_intro_point(void *arg)
|
|||||||
/* Invalid enc-key invalid legacy. */
|
/* Invalid enc-key invalid legacy. */
|
||||||
{
|
{
|
||||||
smartlist_t *lines = smartlist_new();
|
smartlist_t *lines = smartlist_new();
|
||||||
const char *bad_line = "enc-key legacy blah===";
|
const char *bad_line = "legacy-key blah===";
|
||||||
/* Build intro point text. */
|
/* Build intro point text. */
|
||||||
smartlist_add(lines, (char *) intro_point);
|
smartlist_add(lines, (char *) intro_point);
|
||||||
smartlist_add(lines, (char *) auth_key);
|
smartlist_add(lines, (char *) auth_key);
|
||||||
@ -810,22 +543,6 @@ test_decode_intro_point(void *arg)
|
|||||||
smartlist_free(lines);
|
smartlist_free(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Valid object. */
|
|
||||||
{
|
|
||||||
smartlist_t *lines = smartlist_new();
|
|
||||||
/* Build intro point text. */
|
|
||||||
smartlist_add(lines, (char *) intro_point);
|
|
||||||
smartlist_add(lines, (char *) auth_key);
|
|
||||||
smartlist_add(lines, (char *) enc_key);
|
|
||||||
smartlist_add(lines, (char *) enc_key_cert);
|
|
||||||
encoded_ip = smartlist_join_strings(lines, "\n", 0, &len_out);
|
|
||||||
tt_assert(encoded_ip);
|
|
||||||
ip = decode_introduction_point(desc, encoded_ip);
|
|
||||||
tt_assert(ip);
|
|
||||||
tor_free(encoded_ip);
|
|
||||||
smartlist_free(lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
hs_descriptor_free(desc);
|
hs_descriptor_free(desc);
|
||||||
desc_intro_point_free(ip);
|
desc_intro_point_free(ip);
|
||||||
@ -1117,7 +834,7 @@ struct testcase_t hs_descriptor[] = {
|
|||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
{ "encrypted_data_len", test_encrypted_data_len, TT_FORK,
|
{ "encrypted_data_len", test_encrypted_data_len, TT_FORK,
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
{ "decode_intro_point", test_decode_intro_point, TT_FORK,
|
{ "decode_invalid_intro_point", test_decode_invalid_intro_point, TT_FORK,
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
{ "decode_plaintext", test_decode_plaintext, TT_FORK,
|
{ "decode_plaintext", test_decode_plaintext, TT_FORK,
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
|
Loading…
Reference in New Issue
Block a user