diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 09f310a3df..b2ce7220eb 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1007,6 +1007,9 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, started_here ? conn->_base.address : safe_str_client(conn->_base.address); const char *conn_type = started_here ? "outgoing" : "incoming"; + crypto_pk_env_t *our_identity = + started_here ? get_client_identity_key() : + get_server_identity_key(); int has_cert = 0, has_identity=0; check_no_tls_errors(); @@ -1044,7 +1047,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, if (identity_rcvd) { has_identity = 1; crypto_pk_get_digest(identity_rcvd, digest_rcvd_out); - if (crypto_pk_cmp_keys(get_identity_key(), identity_rcvd)<0) { + if (crypto_pk_cmp_keys(our_identity, identity_rcvd)<0) { conn->circ_id_type = CIRC_ID_TYPE_LOWER; } else { conn->circ_id_type = CIRC_ID_TYPE_HIGHER; diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 8ae03424a2..d436b6e597 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1552,7 +1552,8 @@ dirserv_regenerate_directory(void) { char *new_directory=NULL; - if (dirserv_dump_directory_to_string(&new_directory, get_identity_key())) { + if (dirserv_dump_directory_to_string(&new_directory, + get_server_identity_key())) { log_warn(LD_BUG, "Error creating directory."); tor_free(new_directory); return NULL; @@ -1582,7 +1583,7 @@ generate_runningrouters(void) char digest[DIGEST_LEN]; char published[ISO_TIME_LEN+1]; size_t len; - crypto_pk_env_t *private_key = get_identity_key(); + crypto_pk_env_t *private_key = get_server_identity_key(); char *identity_pkey; /* Identity key, DER64-encoded. */ size_t identity_pkey_len; @@ -2710,7 +2711,7 @@ generate_v2_networkstatus_opinion(void) smartlist_t *routers = NULL; digestmap_t *omit_as_sybil = NULL; - private_key = get_identity_key(); + private_key = get_server_identity_key(); if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); diff --git a/src/or/hibernate.c b/src/or/hibernate.c index 3c6a3fa033..e9be5930d1 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -522,7 +522,7 @@ accounting_set_wakeup_time(void) uint64_t time_to_exhaust_bw; int time_to_consider; - if (! identity_key_is_set()) { + if (! server_identity_key_is_set()) { if (init_keys() < 0) { log_err(LD_BUG, "Error initializing keys"); tor_assert(0); @@ -530,7 +530,7 @@ accounting_set_wakeup_time(void) } format_iso_time(buf, interval_start_time); - crypto_pk_get_digest(get_identity_key(), digest); + crypto_pk_get_digest(get_server_identity_key(), digest); d_env = crypto_new_digest_env(); crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); diff --git a/src/or/main.c b/src/or/main.c index 01c27f0efd..927e931b9a 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -932,8 +932,8 @@ run_scheduled_events(time_t now) if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME < now) { log_info(LD_GENERAL,"Rotating tls context."); if (tor_tls_context_init(public_server_mode(options), - get_identity_key(), - is_server ? get_identity_key() : NULL, + get_client_identity_key(), + is_server ? get_server_identity_key() : NULL, MAX_SSL_KEY_LIFETIME) < 0) { log_warn(LD_BUG, "Error reinitializing TLS context"); /* XXX is it a bug here, that we just keep going? -RD */ @@ -1466,7 +1466,7 @@ do_main_loop(void) /* load the private keys, if we're supposed to have them, and set up the * TLS context. */ - if (! identity_key_is_set()) { + if (! client_identity_key_is_set()) { if (init_keys() < 0) { log_err(LD_BUG,"Error initializing keys; exiting"); return -1; @@ -2102,7 +2102,7 @@ do_list_fingerprint(void) log_err(LD_BUG,"Error initializing keys; can't display fingerprint"); return -1; } - if (!(k = get_identity_key())) { + if (!(k = get_server_identity_key())) { log_err(LD_GENERAL,"Error: missing identity key."); return -1; } diff --git a/src/or/router.c b/src/or/router.c index c59e4b2ca0..a256970f90 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -49,11 +49,15 @@ static crypto_pk_env_t *onionkey=NULL; /** Previous private onionskin decryption key: used to decode CREATE cells * generated by clients that have an older version of our descriptor. */ static crypto_pk_env_t *lastonionkey=NULL; -/** Private "identity key": used to sign directory info and TLS +/** Private server "identity key": used to sign directory info and TLS * certificates. Never changes. */ -static crypto_pk_env_t *identitykey=NULL; -/** Digest of identitykey. */ -static char identitykey_digest[DIGEST_LEN]; +static crypto_pk_env_t *server_identitykey=NULL; +/** Digest of server_identitykey. */ +static char server_identitykey_digest[DIGEST_LEN]; +/** Private client "identity key": used to sign bridges' and clients' + * outbound TLS certificates. Regenerated on startup and on IP address + * change. */ +static crypto_pk_env_t *client_identitykey=NULL; /** Signing key used for v3 directory material; only set for authorities. */ static crypto_pk_env_t *authority_signing_key = NULL; /** Key certificate to authenticate v3 directory material; only set for @@ -123,31 +127,57 @@ get_onion_key_set_at(void) return onionkey_set_at; } -/** Set the current identity key to k. +/** Set the current server identity key to k. */ void -set_identity_key(crypto_pk_env_t *k) +set_server_identity_key(crypto_pk_env_t *k) { - crypto_free_pk_env(identitykey); - identitykey = k; - crypto_pk_get_digest(identitykey, identitykey_digest); + crypto_free_pk_env(server_identitykey); + server_identitykey = k; + crypto_pk_get_digest(server_identitykey, server_identitykey_digest); } -/** Returns the current identity key; requires that the identity key has been - * set. +/** Returns the current server identity key; requires that the key has + * been set. */ crypto_pk_env_t * -get_identity_key(void) +get_server_identity_key(void) { - tor_assert(identitykey); - return identitykey; + tor_assert(server_identitykey); + return server_identitykey; } -/** Return true iff the identity key has been set. */ +/** Return true iff the server identity key has been set. */ int -identity_key_is_set(void) +server_identity_key_is_set(void) { - return identitykey != NULL; + return server_identitykey != NULL; +} + +/** Set the current client identity key to k. + */ +void +set_client_identity_key(crypto_pk_env_t *k) +{ + crypto_free_pk_env(client_identitykey); + client_identitykey = k; +} + +/** Returns the current client identity key; requires that the key has + * been set. + */ +crypto_pk_env_t * +get_client_identity_key(void) +{ + tor_assert(client_identitykey); + return client_identitykey; +} + +/** Return true iff the client identity key has been set. */ +int +client_identity_key_is_set(void) +{ + return client_identitykey != NULL; } /** Return the key certificate for this v3 (voting) authority, or NULL @@ -470,10 +500,10 @@ init_keys(void) crypto_free_pk_env(prkey); return -1; } - set_identity_key(prkey); + set_client_identity_key(prkey); /* Create a TLS context. */ if (tor_tls_context_init(0, - get_identity_key(), + get_client_identity_key(), NULL, MAX_SSL_KEY_LIFETIME) < 0) { log_err(LD_GENERAL,"Error creating TLS context for Tor client."); @@ -510,13 +540,28 @@ init_keys(void) } } - /* 1. Read identity key. Make it if none is found. */ + /* 1b. Read identity key. Make it if none is found. */ keydir = get_datadir_fname2("keys", "secret_id_key"); log_info(LD_GENERAL,"Reading/making identity key \"%s\"...",keydir); prkey = init_key_from_file(keydir, 1, LOG_ERR); tor_free(keydir); if (!prkey) return -1; - set_identity_key(prkey); + set_server_identity_key(prkey); + + /* 1c. If we are configured as a bridge, generate a client key; + * otherwise, set the server identity key as our client identity + * key. */ + if (public_server_mode(options)) { + set_client_identity_key(prkey); /* set above */ + } else { + if (!(prkey = crypto_new_pk_env())) + return -1; + if (crypto_pk_generate_key(prkey)) { + crypto_free_pk_env(prkey); + return -1; + } + set_client_identity_key(prkey); + } /* 2. Read onion key. Make it if none is found. */ keydir = get_datadir_fname2("keys", "secret_onion_key"); @@ -554,8 +599,8 @@ init_keys(void) /* 3. Initialize link key and TLS context. */ if (tor_tls_context_init(public_server_mode(options), - get_identity_key(), - get_identity_key(), + get_client_identity_key(), + get_server_identity_key(), MAX_SSL_KEY_LIFETIME) < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); return -1; @@ -567,7 +612,8 @@ init_keys(void) const char *m = NULL; routerinfo_t *ri; /* We need to add our own fingerprint so it gets recognized. */ - if (dirserv_add_own_fingerprint(options->Nickname, get_identity_key())) { + if (dirserv_add_own_fingerprint(options->Nickname, + get_server_identity_key())) { log_err(LD_GENERAL,"Error adding own fingerprint to approved set"); return -1; } @@ -588,7 +634,8 @@ init_keys(void) /* 5. Dump fingerprint to 'fingerprint' */ keydir = get_datadir_fname("fingerprint"); log_info(LD_GENERAL,"Dumping fingerprint to \"%s\"...",keydir); - if (crypto_pk_get_fingerprint(get_identity_key(), fingerprint, 0)<0) { + if (crypto_pk_get_fingerprint(get_server_identity_key(), + fingerprint, 0) < 0) { log_err(LD_GENERAL,"Error computing fingerprint"); tor_free(keydir); return -1; @@ -626,7 +673,7 @@ init_keys(void) return -1; } /* 6b. [authdirserver only] add own key to approved directories. */ - crypto_pk_get_digest(get_identity_key(), digest); + crypto_pk_get_digest(get_server_identity_key(), digest); type = ((options->V1AuthoritativeDir ? V1_AUTHORITY : NO_AUTHORITY) | (options->V2AuthoritativeDir ? V2_AUTHORITY : NO_AUTHORITY) | (options->V3AuthoritativeDir ? V3_AUTHORITY : NO_AUTHORITY) | @@ -1178,11 +1225,12 @@ router_my_exit_policy_is_reject_star(void) } /** Return true iff I'm a server and digest is equal to - * my identity digest. */ + * my server identity key digest. */ int router_digest_is_me(const char *digest) { - return identitykey && !memcmp(identitykey_digest, digest, DIGEST_LEN); + return (server_identitykey && + !memcmp(server_identitykey_digest, digest, DIGEST_LEN)); } /** Return true iff I'm a server and digest is equal to @@ -1325,7 +1373,7 @@ router_rebuild_descriptor(int force) ri->cache_info.published_on = time(NULL); ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from * main thread */ - ri->identity_pkey = crypto_pk_dup_key(get_identity_key()); + ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key()); if (crypto_pk_get_digest(ri->identity_pkey, ri->cache_info.identity_digest)<0) { routerinfo_free(ri); @@ -1420,7 +1468,8 @@ router_rebuild_descriptor(int force) ei_size = options->ExtraInfoStatistics ? MAX_EXTRAINFO_UPLOAD_SIZE : 8192; ei->cache_info.signed_descriptor_body = tor_malloc(ei_size); if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body, - ei_size, ei, get_identity_key()) < 0) { + ei_size, ei, + get_server_identity_key()) < 0) { log_warn(LD_BUG, "Couldn't generate extra-info descriptor."); routerinfo_free(ri); extrainfo_free(ei); @@ -1437,7 +1486,7 @@ router_rebuild_descriptor(int force) DIGEST_LEN); ri->cache_info.signed_descriptor_body = tor_malloc(8192); if (router_dump_router_to_string(ri->cache_info.signed_descriptor_body, 8192, - ri, get_identity_key())<0) { + ri, get_server_identity_key()) < 0) { log_warn(LD_BUG, "Couldn't generate router descriptor."); routerinfo_free(ri); extrainfo_free(ei); @@ -2186,7 +2235,8 @@ router_free_all(void) { crypto_free_pk_env(onionkey); crypto_free_pk_env(lastonionkey); - crypto_free_pk_env(identitykey); + crypto_free_pk_env(server_identitykey); + crypto_free_pk_env(client_identitykey); tor_mutex_free(key_lock); routerinfo_free(desc_routerinfo); extrainfo_free(desc_extrainfo); diff --git a/src/or/router.h b/src/or/router.h index 4107c717c3..125fa653d6 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -14,9 +14,12 @@ crypto_pk_env_t *get_onion_key(void); time_t get_onion_key_set_at(void); -void set_identity_key(crypto_pk_env_t *k); -crypto_pk_env_t *get_identity_key(void); -int identity_key_is_set(void); +void set_server_identity_key(crypto_pk_env_t *k); +crypto_pk_env_t *get_server_identity_key(void); +int server_identity_key_is_set(void); +void set_client_identity_key(crypto_pk_env_t *k); +crypto_pk_env_t *get_client_identity_key(void); +int client_identity_key_is_set(void); authority_cert_t *get_my_v3_authority_cert(void); crypto_pk_env_t *get_my_v3_authority_signing_key(void); authority_cert_t *get_my_v3_legacy_cert(void);