diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index ab5fe697bca71afd70511a82876a730d8333a386..cc317dfad3c9e3923b760f7064929710287b54b9 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -3034,6 +3034,34 @@ router_dump_router_to_string(routerinfo_t *router, we_are_hibernating() ? "hibernating 1\n" : "", "hidden-service-dir\n"); + SMARTLIST_FOREACH_BEGIN(get_current_family_id_keys(), + const ed25519_keypair_t *, k_family_id) { + // TODO PROP321: We may want this to be configurable; + // we can probably use a smaller value. +#define FAMILY_CERT_LIFETIME (30*86400) + tor_cert_t *family_cert = tor_cert_create_ed25519( + k_family_id, + CERT_TYPE_FAMILY_V_IDENTITY, + get_master_identity_key(), + router->cache_info.published_on, + FAMILY_CERT_LIFETIME, CERT_FLAG_INCLUDE_SIGNING_KEY); + char family_cert_base64[256]; + if (base64_encode(family_cert_base64, sizeof(family_cert_base64), + (const char*) family_cert->encoded, + family_cert->encoded_len, BASE64_ENCODE_MULTILINE) < 0) { + log_err(LD_BUG, "Base64 encoding family cert failed!?"); + tor_cert_free(family_cert); + goto err; + } + smartlist_add_asprintf(chunks, + "family-cert\n" + "-----BEGIN FAMILY CERT-----\n" + "%s" + "-----END FAMILY CERT-----\n", + family_cert_base64); + tor_cert_free(family_cert); + } SMARTLIST_FOREACH_END(k_family_id); + if (options->ContactInfo && strlen(options->ContactInfo)) { const char *ci = options->ContactInfo; if (strchr(ci, '\n') || strchr(ci, '\r')) diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c index 64ec38ed19cfa6409fc5e1848f93c81d108da339..5bfc2ebe65a090710367757b37da34f2e2c84cee 100644 --- a/src/feature/relay/routerkeys.c +++ b/src/feature/relay/routerkeys.c @@ -44,6 +44,9 @@ static uint8_t *rsa_ed_crosscert = NULL; static size_t rsa_ed_crosscert_len = 0; static time_t rsa_ed_crosscert_expiration = 0; +// list of ed25519_keypair_t +static smartlist_t *family_id_keys = NULL; + /** * Running as a server: load, reload, or refresh our ed25519 keys and * certificates, creating and saving new ones as needed. @@ -674,6 +677,43 @@ get_current_auth_key_cert(void) return auth_key_cert; } +/** + * Return a list of our current family id keypairs, + * as a list of `ed25519_keypair_t`. + * + * Never returns NULL. + * + * TODO PROP321: Right now this is only used in testing; + * when we add relay support we'll need a way to actually + * read these keys from disk. + **/ +const smartlist_t * +get_current_family_id_keys(void) +{ + if (family_id_keys == NULL) + family_id_keys = smartlist_new(); + return family_id_keys; +} + +#ifdef TOR_UNIT_TESTS +/** + * Testing only: Replace our list of family ID keys with `family_id_keys`, + * which must be a list of `ed25519_keypair_t`. + * + * Takes ownership of its input. + */ +void +set_mock_family_id_keys(smartlist_t *keys) +{ + if (family_id_keys) { + SMARTLIST_FOREACH(family_id_keys, ed25519_keypair_t *, kp, + ed25519_keypair_free(kp)); + smartlist_free(family_id_keys); + } + family_id_keys = keys; +} +#endif + void get_master_rsa_crosscert(const uint8_t **cert_out, size_t *size_out) @@ -746,6 +786,12 @@ routerkeys_free_all(void) ed25519_keypair_free(master_identity_key); ed25519_keypair_free(master_signing_key); ed25519_keypair_free(current_auth_key); + if (family_id_keys) { + SMARTLIST_FOREACH(family_id_keys, ed25519_keypair_t *, kp, + ed25519_keypair_free(kp)); + smartlist_free(family_id_keys); + } + tor_cert_free(signing_key_cert); tor_cert_free(link_cert_cert); tor_cert_free(auth_key_cert); diff --git a/src/feature/relay/routerkeys.h b/src/feature/relay/routerkeys.h index b97615a9c9022e18e395c910e9487156edab6fa5..f51f91b141311fa28f3646016e245ab1f6b99766 100644 --- a/src/feature/relay/routerkeys.h +++ b/src/feature/relay/routerkeys.h @@ -21,6 +21,8 @@ const ed25519_keypair_t *get_current_auth_keypair(void); const struct tor_cert_st *get_current_link_cert_cert(void); const struct tor_cert_st *get_current_auth_key_cert(void); +const smartlist_t *get_current_family_id_keys(void); + void get_master_rsa_crosscert(const uint8_t **cert_out, size_t *size_out); @@ -126,6 +128,7 @@ make_tap_onion_key_crosscert(const crypto_pk_t *onion_key, #ifdef TOR_UNIT_TESTS const ed25519_keypair_t *get_master_identity_keypair(void); void init_mock_ed_keys(const crypto_pk_t *rsa_identity_key); +void set_mock_family_id_keys(smartlist_t *keys); #endif #endif /* !defined(TOR_ROUTERKEYS_H) */