diff options
Diffstat (limited to 'src/or/router.c')
-rw-r--r-- | src/or/router.c | 242 |
1 files changed, 222 insertions, 20 deletions
diff --git a/src/or/router.c b/src/or/router.c index 24b7c750f6..6532f97d24 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -26,9 +26,11 @@ #include "relay.h" #include "rephist.h" #include "router.h" +#include "routerkeys.h" #include "routerlist.h" #include "routerparse.h" #include "statefile.h" +#include "torcert.h" #include "transports.h" #include "routerset.h" @@ -204,6 +206,8 @@ set_server_identity_key(crypto_pk_t *k) static void assert_identity_keys_ok(void) { + if (1) + return; tor_assert(client_identitykey); if (public_server_mode(get_options())) { /* assert that we have set the client and server keys to be equal */ @@ -863,6 +867,10 @@ init_keys(void) set_client_identity_key(prkey); } + /* 1d. Load all ed25519 keys */ + if (load_ed_keys(options,now) < 0) + return -1; + /* 2. Read onion key. Make it if none is found. */ keydir = get_datadir_fname2("keys", "secret_onion_key"); log_info(LD_GENERAL,"Reading/making onion key \"%s\"...",keydir); @@ -928,6 +936,13 @@ init_keys(void) return -1; } + /* 3b. Get an ed25519 link certificate. Note that we need to do this + * after we set up the TLS context */ + if (generate_ed_link_cert(options, now) < 0) { + log_err(LD_GENERAL,"Couldn't make link cert"); + return -1; + } + /* 4. Build our router descriptor. */ /* Must be called after keys are initialized. */ mydesc = router_get_my_descriptor(); @@ -1872,6 +1887,8 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) routerinfo_free(ri); return -1; } + ri->signing_key_cert = tor_cert_dup(get_master_signing_key_cert()); + get_platform_str(platform, sizeof(platform)); ri->platform = tor_strdup(platform); @@ -1962,10 +1979,12 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) ei->cache_info.is_extrainfo = 1; strlcpy(ei->nickname, get_options()->Nickname, sizeof(ei->nickname)); ei->cache_info.published_on = ri->cache_info.published_on; + ei->signing_key_cert = tor_cert_dup(get_master_signing_key_cert()); memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest, DIGEST_LEN); if (extrainfo_dump_to_string(&ei->cache_info.signed_descriptor_body, - ei, get_server_identity_key()) < 0) { + ei, get_server_identity_key(), + get_master_signing_keypair()) < 0) { log_warn(LD_BUG, "Couldn't generate extra-info descriptor."); extrainfo_free(ei); ei = NULL; @@ -1975,6 +1994,10 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) router_get_extrainfo_hash(ei->cache_info.signed_descriptor_body, ei->cache_info.signed_descriptor_len, ei->cache_info.signed_descriptor_digest); + crypto_digest256((char*) ei->digest256, + ei->cache_info.signed_descriptor_body, + ei->cache_info.signed_descriptor_len, + DIGEST_SHA256); } /* Now finish the router descriptor. */ @@ -1982,12 +2005,18 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) memcpy(ri->cache_info.extra_info_digest, ei->cache_info.signed_descriptor_digest, DIGEST_LEN); + memcpy(ri->extra_info_digest256, + ei->digest256, + DIGEST256_LEN); } else { /* ri was allocated with tor_malloc_zero, so there is no need to * zero ri->cache_info.extra_info_digest here. */ } - if (! (ri->cache_info.signed_descriptor_body = router_dump_router_to_string( - ri, get_server_identity_key()))) { + if (! (ri->cache_info.signed_descriptor_body = + router_dump_router_to_string(ri, get_server_identity_key(), + get_onion_key(), + get_current_curve25519_keypair(), + get_master_signing_keypair())) ) { log_warn(LD_BUG, "Couldn't generate router descriptor."); routerinfo_free(ri); extrainfo_free(ei); @@ -2328,22 +2357,28 @@ get_platform_str(char *platform, size_t len) */ char * router_dump_router_to_string(routerinfo_t *router, - crypto_pk_t *ident_key) + const crypto_pk_t *ident_key, + const crypto_pk_t *tap_key, + const curve25519_keypair_t *ntor_keypair, + const ed25519_keypair_t *signing_keypair) { char *address = NULL; char *onion_pkey = NULL; /* Onion key, PEM-encoded. */ char *identity_pkey = NULL; /* Identity key, PEM-encoded. */ - char digest[DIGEST_LEN]; + char digest[DIGEST256_LEN]; char published[ISO_TIME_LEN+1]; char fingerprint[FINGERPRINT_LEN+1]; - int has_extra_info_digest; - char extra_info_digest[HEX_DIGEST_LEN+1]; + char *extra_info_line = NULL; size_t onion_pkeylen, identity_pkeylen; char *family_line = NULL; char *extra_or_address = NULL; const or_options_t *options = get_options(); smartlist_t *chunks = NULL; char *output = NULL; + const int emit_ed_sigs = signing_keypair && router->signing_key_cert; + char *ed_cert_line = NULL; + char *rsa_tap_cc_line = NULL; + char *ntor_cc_line = NULL; /* Make sure the identity key matches the one in the routerinfo. */ if (!crypto_pk_eq_keys(ident_key, router->identity_pkey)) { @@ -2351,6 +2386,16 @@ router_dump_router_to_string(routerinfo_t *router, "match router's public key!"); goto err; } + if (emit_ed_sigs) { + if (!router->signing_key_cert->signing_key_included || + !ed25519_pubkey_eq(&router->signing_key_cert->signed_key, + &signing_keypair->pubkey)) { + log_warn(LD_BUG, "Tried to sign a router descriptor with a mismatched " + "ed25519 key chain %d", + router->signing_key_cert->signing_key_included); + goto err; + } + } /* record our fingerprint, so we can include it in the descriptor */ if (crypto_pk_get_fingerprint(router->identity_pkey, fingerprint, 1)<0) { @@ -2358,6 +2403,22 @@ router_dump_router_to_string(routerinfo_t *router, goto err; } + if (emit_ed_sigs) { + /* Encode ed25519 signing cert */ + char ed_cert_base64[256]; + if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64), + (const char*)router->signing_key_cert->encoded, + router->signing_key_cert->encoded_len, + BASE64_ENCODE_MULTILINE) < 0) { + log_err(LD_BUG,"Couldn't base64-encode signing key certificate!"); + goto err; + } + tor_asprintf(&ed_cert_line, "identity-ed25519\n" + "-----BEGIN ED25519 CERT-----\n" + "%s" + "-----END ED25519 CERT-----\n", ed_cert_base64); + } + /* PEM-encode the onion key */ if (crypto_pk_write_public_key_to_string(router->onion_pkey, &onion_pkey,&onion_pkeylen)<0) { @@ -2372,6 +2433,69 @@ router_dump_router_to_string(routerinfo_t *router, goto err; } + /* Cross-certify with RSA key */ + if (tap_key && router->signing_key_cert && + router->signing_key_cert->signing_key_included) { + char buf[256]; + int tap_cc_len = 0; + uint8_t *tap_cc = + make_tap_onion_key_crosscert(tap_key, + &router->signing_key_cert->signing_key, + router->identity_pkey, + &tap_cc_len); + if (!tap_cc) { + log_warn(LD_BUG,"make_tap_onion_key_crosscert failed!"); + goto err; + } + + if (base64_encode(buf, sizeof(buf), (const char*)tap_cc, tap_cc_len, + BASE64_ENCODE_MULTILINE) < 0) { + log_warn(LD_BUG,"base64_encode(rsa_crosscert) failed!"); + tor_free(tap_cc); + goto err; + } + tor_free(tap_cc); + + tor_asprintf(&rsa_tap_cc_line, + "onion-key-crosscert\n" + "-----BEGIN CROSSCERT-----\n" + "%s" + "-----END CROSSCERT-----\n", buf); + } + + /* Cross-certify with onion keys */ + if (ntor_keypair && router->signing_key_cert && + router->signing_key_cert->signing_key_included) { + int sign = 0; + char buf[256]; + /* XXXX Base the expiration date on the actual onion key expiration time?*/ + tor_cert_t *cert = + make_ntor_onion_key_crosscert(ntor_keypair, + &router->signing_key_cert->signing_key, + router->cache_info.published_on, + MIN_ONION_KEY_LIFETIME, &sign); + if (!cert) { + log_warn(LD_BUG,"make_ntor_onion_key_crosscert failed!"); + goto err; + } + tor_assert(sign == 0 || sign == 1); + + if (base64_encode(buf, sizeof(buf), + (const char*)cert->encoded, cert->encoded_len, + BASE64_ENCODE_MULTILINE)<0) { + log_warn(LD_BUG,"base64_encode(ntor_crosscert) failed!"); + tor_cert_free(cert); + goto err; + } + tor_cert_free(cert); + + tor_asprintf(&ntor_cc_line, + "ntor-onion-key-crosscert %d\n" + "-----BEGIN ED25519 CERT-----\n" + "%s" + "-----END ED25519 CERT-----\n", sign, buf); + } + /* Encode the publication time. */ format_iso_time(published, router->cache_info.published_on); @@ -2384,12 +2508,19 @@ router_dump_router_to_string(routerinfo_t *router, family_line = tor_strdup(""); } - has_extra_info_digest = - ! tor_digest_is_zero(router->cache_info.extra_info_digest); - - if (has_extra_info_digest) { + if (!tor_digest_is_zero(router->cache_info.extra_info_digest)) { + char extra_info_digest[HEX_DIGEST_LEN+1]; base16_encode(extra_info_digest, sizeof(extra_info_digest), router->cache_info.extra_info_digest, DIGEST_LEN); + if (!tor_digest256_is_zero(router->extra_info_digest256)) { + char d256_64[BASE64_DIGEST256_LEN+1]; + digest256_to_base64(d256_64, router->extra_info_digest256); + tor_asprintf(&extra_info_line, "extra-info-digest %s %s\n", + extra_info_digest, d256_64); + } else { + tor_asprintf(&extra_info_line, "extra-info-digest %s\n", + extra_info_digest); + } } if (router->ipv6_orport && @@ -2411,20 +2542,23 @@ router_dump_router_to_string(routerinfo_t *router, smartlist_add_asprintf(chunks, "router %s %s %d 0 %d\n" "%s" + "%s" "platform %s\n" "protocols Link 1 2 Circuit 1\n" "published %s\n" "fingerprint %s\n" "uptime %ld\n" "bandwidth %d %d %d\n" - "%s%s%s%s" + "%s%s" "onion-key\n%s" "signing-key\n%s" + "%s%s" "%s%s%s%s", router->nickname, address, router->or_port, decide_to_advertise_dirport(options, router->dir_port), + ed_cert_line ? ed_cert_line : "", extra_or_address ? extra_or_address : "", router->platform, published, @@ -2433,12 +2567,12 @@ router_dump_router_to_string(routerinfo_t *router, (int) router->bandwidthrate, (int) router->bandwidthburst, (int) router->bandwidthcapacity, - has_extra_info_digest ? "extra-info-digest " : "", - has_extra_info_digest ? extra_info_digest : "", - has_extra_info_digest ? "\n" : "", + extra_info_line ? extra_info_line : "", (options->DownloadExtraInfo || options->V3AuthoritativeDir) ? "caches-extra-info\n" : "", onion_pkey, identity_pkey, + rsa_tap_cc_line ? rsa_tap_cc_line : "", + ntor_cc_line ? ntor_cc_line : "", family_line, we_are_hibernating() ? "hibernating 1\n" : "", options->HidServDirectoryV2 ? "hidden-service-dir\n" : "", @@ -2481,7 +2615,24 @@ router_dump_router_to_string(routerinfo_t *router, tor_free(p6); } - /* Sign the descriptor */ + /* Sign the descriptor with Ed25519 */ + if (emit_ed_sigs) { + smartlist_add(chunks, tor_strdup("router-sig-ed25519 ")); + crypto_digest_smartlist_prefix(digest, DIGEST256_LEN, + ED_DESC_SIGNATURE_PREFIX, + chunks, "", DIGEST_SHA256); + ed25519_signature_t sig; + char buf[ED25519_SIG_BASE64_LEN+1]; + if (ed25519_sign(&sig, (const uint8_t*)digest, DIGEST256_LEN, + signing_keypair) < 0) + goto err; + if (ed25519_signature_to_base64(buf, &sig) < 0) + goto err; + + smartlist_add_asprintf(chunks, "%s\n", buf); + } + + /* Sign the descriptor with RSA */ smartlist_add(chunks, tor_strdup("router-signature\n")); crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1); @@ -2533,6 +2684,10 @@ router_dump_router_to_string(routerinfo_t *router, tor_free(onion_pkey); tor_free(identity_pkey); tor_free(extra_or_address); + tor_free(ed_cert_line); + tor_free(rsa_tap_cc_line); + tor_free(ntor_cc_line); + tor_free(extra_info_line); return output; } @@ -2676,7 +2831,8 @@ load_stats_file(const char *filename, const char *end_line, time_t now, * success, negative on failure. */ int extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, - crypto_pk_t *ident_key) + crypto_pk_t *ident_key, + const ed25519_keypair_t *signing_keypair) { const or_options_t *options = get_options(); char identity[HEX_DIGEST_LEN+1]; @@ -2686,18 +2842,45 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, int result; static int write_stats_to_extrainfo = 1; char sig[DIROBJ_MAX_SIG_LEN+1]; - char *s, *pre, *contents, *cp, *s_dup = NULL; + char *s = NULL, *pre, *contents, *cp, *s_dup = NULL; time_t now = time(NULL); smartlist_t *chunks = smartlist_new(); extrainfo_t *ei_tmp = NULL; + const int emit_ed_sigs = signing_keypair && extrainfo->signing_key_cert; + char *ed_cert_line = NULL; base16_encode(identity, sizeof(identity), extrainfo->cache_info.identity_digest, DIGEST_LEN); format_iso_time(published, extrainfo->cache_info.published_on); bandwidth_usage = rep_hist_get_bandwidth_lines(); + if (emit_ed_sigs) { + if (!extrainfo->signing_key_cert->signing_key_included || + !ed25519_pubkey_eq(&extrainfo->signing_key_cert->signed_key, + &signing_keypair->pubkey)) { + log_warn(LD_BUG, "Tried to sign a extrainfo descriptor with a " + "mismatched ed25519 key chain %d", + extrainfo->signing_key_cert->signing_key_included); + goto err; + } + char ed_cert_base64[256]; + if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64), + (const char*)extrainfo->signing_key_cert->encoded, + extrainfo->signing_key_cert->encoded_len, + BASE64_ENCODE_MULTILINE) < 0) { + log_err(LD_BUG,"Couldn't base64-encode signing key certificate!"); + goto err; + } + tor_asprintf(&ed_cert_line, "identity-ed25519\n" + "-----BEGIN ED25519 CERT-----\n" + "%s" + "-----END ED25519 CERT-----\n", ed_cert_base64); + } else { + ed_cert_line = tor_strdup(""); + } - tor_asprintf(&pre, "extra-info %s %s\npublished %s\n%s", + tor_asprintf(&pre, "extra-info %s %s\n%spublished %s\n%s", extrainfo->nickname, identity, + ed_cert_line, published, bandwidth_usage); tor_free(bandwidth_usage); smartlist_add(chunks, pre); @@ -2757,6 +2940,23 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, } } + if (emit_ed_sigs) { + char digest[DIGEST256_LEN]; + smartlist_add(chunks, tor_strdup("router-sig-ed25519 ")); + crypto_digest_smartlist_prefix(digest, DIGEST256_LEN, + ED_DESC_SIGNATURE_PREFIX, + chunks, "", DIGEST_SHA256); + ed25519_signature_t sig; + char buf[ED25519_SIG_BASE64_LEN+1]; + if (ed25519_sign(&sig, (const uint8_t*)digest, DIGEST256_LEN, + signing_keypair) < 0) + goto err; + if (ed25519_signature_to_base64(buf, &sig) < 0) + goto err; + + smartlist_add_asprintf(chunks, "%s\n", buf); + } + smartlist_add(chunks, tor_strdup("router-signature\n")); s = smartlist_join_strings(chunks, "", 0, NULL); @@ -2805,7 +3005,8 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, "adding statistics to this or any future " "extra-info descriptors."); write_stats_to_extrainfo = 0; - result = extrainfo_dump_to_string(s_out, extrainfo, ident_key); + result = extrainfo_dump_to_string(s_out, extrainfo, ident_key, + signing_keypair); goto done; } else { log_warn(LD_BUG, "We just generated an extrainfo descriptor we " @@ -2827,6 +3028,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); smartlist_free(chunks); tor_free(s_dup); + tor_free(ed_cert_line); extrainfo_free(ei_tmp); return result; |