diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-05-31 18:33:38 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-05-31 18:45:35 -0400 |
commit | a9be768959c189846178723d5fe44d3b59b0d983 (patch) | |
tree | 34a4e674f22dd522d339b6c064b075f7db75cd29 /src/or/routerkeys.c | |
parent | 5b33d95a3dfe943625d78983bb53be2901a51150 (diff) | |
download | tor-a9be768959c189846178723d5fe44d3b59b0d983.tar.gz tor-a9be768959c189846178723d5fe44d3b59b0d983.zip |
Bugfix: Regenerate more certificates when appropriate
Previously we could sometimes change our signing key, but not
regenerate the certificates (signing->link and signing->auth) that
were signed with it. Also, we would regularly replace our TLS x.509
link certificate (by rotating our TLS context) but not replace our
signing->link ed25519 certificate. In both cases, the resulting
inconsistency would make other relays reject our link handshakes.
Fixes two cases of bug 22460; bugfix on 0.3.0.1-alpha.
Diffstat (limited to 'src/or/routerkeys.c')
-rw-r--r-- | src/or/routerkeys.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/src/or/routerkeys.c b/src/or/routerkeys.c index 6259e3f5a0..1f0f82a184 100644 --- a/src/or/routerkeys.c +++ b/src/or/routerkeys.c @@ -672,6 +672,9 @@ static size_t rsa_ed_crosscert_len = 0; /** * Running as a server: load, reload, or refresh our ed25519 keys and * certificates, creating and saving new ones as needed. + * + * Return -1 on failure; 0 on success if the signing key was not replaced; + * and 1 on success if the signing key was replaced. */ int load_ed_keys(const or_options_t *options, time_t now) @@ -684,6 +687,7 @@ load_ed_keys(const or_options_t *options, time_t now) const tor_cert_t *check_signing_cert = NULL; tor_cert_t *sign_cert = NULL; tor_cert_t *auth_cert = NULL; + int signing_key_changed = 0; #define FAIL(msg) do { \ log_warn(LD_OR, (msg)); \ @@ -719,7 +723,23 @@ load_ed_keys(const or_options_t *options, time_t now) use_signing = sign; } + if (use_signing) { + /* We loaded a signing key with its certificate. */ + if (! master_signing_key) { + /* We didn't know one before! */ + signing_key_changed = 1; + } else if (! ed25519_pubkey_eq(&use_signing->pubkey, + &master_signing_key->pubkey) || + ! tor_memeq(use_signing->seckey.seckey, + master_signing_key->seckey.seckey, + ED25519_SECKEY_LEN)) { + /* We loaded a different signing key than the one we knew before. */ + signing_key_changed = 1; + } + } + if (!use_signing && master_signing_key) { + /* We couldn't load a signing key, but we already had one loaded */ check_signing_cert = signing_key_cert; use_signing = master_signing_key; } @@ -879,6 +899,7 @@ load_ed_keys(const or_options_t *options, time_t now) if (!sign) FAIL("Missing signing key"); use_signing = sign; + signing_key_changed = 1; tor_assert(sign_cert->signing_key_included); tor_assert(ed25519_pubkey_eq(&sign_cert->signing_key, &id->pubkey)); @@ -910,6 +931,7 @@ load_ed_keys(const or_options_t *options, time_t now) } if (!current_auth_key || + signing_key_changed || EXPIRES_SOON(auth_key_cert, options->TestingAuthKeySlop)) { auth = ed_key_new(use_signing, INIT_ED_KEY_NEEDCERT, now, @@ -937,7 +959,7 @@ load_ed_keys(const or_options_t *options, time_t now) SET_CERT(auth_key_cert, auth_cert); } - return 0; + return signing_key_changed; err: ed25519_keypair_free(id); ed25519_keypair_free(sign); @@ -951,16 +973,18 @@ load_ed_keys(const or_options_t *options, time_t now) * Retrieve our currently-in-use Ed25519 link certificate and id certificate, * and, if they would expire soon (based on the time <b>now</b>, generate new * certificates (without embedding the public part of the signing key inside). + * If <b>force</b> is true, always generate a new certificate. * - * The signed_key from the expiring certificate will be used to sign the new - * key within newly generated X509 certificate. + * The signed_key from the current id->signing certificate will be used to + * sign the new key within newly generated X509 certificate. * * Returns -1 upon error. Otherwise, returns 0 upon success (either when the * current certificate is still valid, or when a new certificate was * successfully generated). */ int -generate_ed_link_cert(const or_options_t *options, time_t now) +generate_ed_link_cert(const or_options_t *options, time_t now, + int force) { const tor_x509_cert_t *link_ = NULL, *id = NULL; tor_cert_t *link_cert = NULL; @@ -972,7 +996,8 @@ generate_ed_link_cert(const or_options_t *options, time_t now) const common_digests_t *digests = tor_x509_cert_get_cert_digests(link_); - if (link_cert_cert && + if (force == 0 && + link_cert_cert && ! EXPIRES_SOON(link_cert_cert, options->TestingLinkKeySlop) && fast_memeq(digests->d[DIGEST_SHA256], link_cert_cert->signed_key.pubkey, DIGEST256_LEN)) { @@ -1073,7 +1098,7 @@ init_mock_ed_keys(const crypto_pk_t *rsa_identity_key) MAKECERT(auth_key_cert, master_signing_key, current_auth_key, CERT_TYPE_SIGNING_AUTH, 0); - if (generate_ed_link_cert(get_options(), time(NULL)) < 0) { + if (generate_ed_link_cert(get_options(), time(NULL), 0) < 0) { log_warn(LD_BUG, "Couldn't make link certificate"); goto err; } |