From 3ca5fe81e33ab7848c848b683bffe12e743398f3 Mon Sep 17 00:00:00 2001 From: Karsten Loesing Date: Wed, 26 Feb 2014 10:44:55 +0100 Subject: Write hashed bridge fingerprint to logs and to disk. Implements #10884. --- changes/bug10884 | 5 +++ doc/tor.1.txt | 4 +++ src/common/crypto.c | 22 ++++++++++++ src/common/crypto.h | 1 + src/or/main.c | 2 ++ src/or/router.c | 100 +++++++++++++++++++++++++++++++++++----------------- 6 files changed, 101 insertions(+), 33 deletions(-) create mode 100644 changes/bug10884 diff --git a/changes/bug10884 b/changes/bug10884 new file mode 100644 index 000000000..815d893de --- /dev/null +++ b/changes/bug10884 @@ -0,0 +1,5 @@ + o Minor features: + - Bridges write the SHA1 digest of their identity key fingerprint to + notice-level logs and to hashed-fingerprint, so that bridge + operators can look up their bridge in Globe and similar tools. + diff --git a/doc/tor.1.txt b/doc/tor.1.txt index f2960af29..dc6788935 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -2305,6 +2305,10 @@ __DataDirectory__**/keys/***:: __DataDirectory__**/fingerprint**:: Only used by servers. Holds the fingerprint of the server's identity key. +__DataDirectory__**/hashed-fingerprint**:: + Only used by bridges. Holds the hashed fingerprint of the bridge's + identity key. (That is, the hash of the hash of the identity key.) + __DataDirectory__**/approved-routers**:: Only for naming authoritative directory servers (see **NamingAuthoritativeDirectory**). This file lists nickname to identity diff --git a/src/common/crypto.c b/src/common/crypto.c index 49dc55a3e..80d835131 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1374,6 +1374,28 @@ crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out, int add_space) return 0; } +/** Given a private or public key pk, put a hashed fingerprint of + * the public key into fp_out (must have at least FINGERPRINT_LEN+1 + * bytes of space). Return 0 on success, -1 on failure. + * + * Hashed fingerprints are computed as the SHA1 digest of the SHA1 digest + * of the ASN.1 encoding of the public key, converted to hexadecimal, in + * upper case. + */ +int +crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out) +{ + char digest[DIGEST_LEN], hashed_digest[DIGEST_LEN]; + if (crypto_pk_get_digest(pk, digest)) { + return -1; + } + if (crypto_digest(hashed_digest, digest, DIGEST_LEN)) { + return -1; + } + base16_encode(fp_out, FINGERPRINT_LEN + 1, hashed_digest, DIGEST_LEN); + return 0; +} + /* symmetric crypto */ /** Return a pointer to the key set for the cipher in env. diff --git a/src/common/crypto.h b/src/common/crypto.h index 3666d5f9a..4f0f1c10c 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -182,6 +182,7 @@ crypto_pk_t *crypto_pk_asn1_decode(const char *str, size_t len); int crypto_pk_get_digest(crypto_pk_t *pk, char *digest_out); int crypto_pk_get_all_digests(crypto_pk_t *pk, digests_t *digests_out); int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out,int add_space); +int crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out); /* symmetric crypto */ const char *crypto_cipher_get_key(crypto_cipher_t *env); diff --git a/src/or/main.c b/src/or/main.c index 5404e962c..b0529cde8 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2764,6 +2764,8 @@ sandbox_init_filter(void) get_datadir_fname2("keys", "secret_id_key.tmp"), 1, get_datadir_fname("fingerprint"), 1, get_datadir_fname("fingerprint.tmp"), 1, + get_datadir_fname("hashed-fingerprint"), 1, + get_datadir_fname("hashed-fingerprint.tmp"), 1, get_datadir_fname("cached-consensus"), 1, get_datadir_fname("cached-consensus.tmp"), 1, "/etc/resolv.conf", 0, diff --git a/src/or/router.c b/src/or/router.c index c22f4c367..b7d96ead2 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -684,6 +684,68 @@ router_initialize_tls_context(void) (unsigned int)lifetime); } +/** Compute fingerprint (or hashed fingerprint if hashed is 1) and write + * it to 'fingerprint' (or 'hashed-fingerprint'). Return 0 on success, or + * -1 if Tor should die, + */ +static int +router_write_fingerprint(int hashed) +{ + char *keydir, *cp; + const char *fname = hashed ? "hashed-fingerprint" : + "fingerprint"; + char fingerprint[FINGERPRINT_LEN+1]; + const or_options_t *options = get_options(); + /*nicknamefp\n\0 */ + char fingerprint_line[MAX_NICKNAME_LEN+FINGERPRINT_LEN+3]; + keydir = get_datadir_fname(fname); + log_info(LD_GENERAL,"Dumping %sfingerprint to \"%s\"...", + hashed ? "hashed " : "", keydir); + if (!hashed) { + if (crypto_pk_get_fingerprint(get_server_identity_key(), + fingerprint, 0) < 0) { + log_err(LD_GENERAL,"Error computing fingerprint"); + tor_free(keydir); + return -1; + } + } else { + if (crypto_pk_get_hashed_fingerprint(get_server_identity_key(), + fingerprint) < 0) { + log_err(LD_GENERAL,"Error computing hashed fingerprint"); + tor_free(keydir); + return -1; + } + } + tor_assert(strlen(options->Nickname) <= MAX_NICKNAME_LEN); + if (tor_snprintf(fingerprint_line, sizeof(fingerprint_line), + "%s %s\n",options->Nickname, fingerprint) < 0) { + log_err(LD_GENERAL,"Error writing %sfingerprint line", + hashed ? "hashed " : ""); + tor_free(keydir); + return -1; + } + /* Check whether we need to write the (hashed-)fingerprint file. */ + cp = NULL; + if (file_status(keydir) == FN_FILE) + cp = read_file_to_str(keydir, 0, NULL); + if (!cp || strcmp(cp, fingerprint_line)) { + if (write_str_to_file(keydir, fingerprint_line, 0)) { + log_err(LD_FS, "Error writing %sfingerprint line to file", + hashed ? "hashed " : ""); + tor_free(keydir); + tor_free(cp); + return -1; + } + } + tor_free(cp); + tor_free(keydir); + + log_notice(LD_GENERAL, "Your Tor %s identity key fingerprint is '%s %s'", + hashed ? "bridge's hashed" : "server's", options->Nickname, + fingerprint); + return 0; +} + /** Initialize all OR private keys, and the TLS context, as necessary. * On OPs, this only initializes the tls context. Return 0 on success, * or -1 if Tor should die. @@ -692,14 +754,10 @@ int init_keys(void) { char *keydir; - char fingerprint[FINGERPRINT_LEN+1]; - /*nicknamefp\n\0 */ - char fingerprint_line[MAX_NICKNAME_LEN+FINGERPRINT_LEN+3]; const char *mydesc; crypto_pk_t *prkey; char digest[DIGEST_LEN]; char v3_digest[DIGEST_LEN]; - char *cp; const or_options_t *options = get_options(); dirinfo_type_t type; time_t now = time(NULL); @@ -889,40 +947,16 @@ 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_server_identity_key(), - fingerprint, 0) < 0) { - log_err(LD_GENERAL,"Error computing fingerprint"); - tor_free(keydir); + /* 5. Dump fingerprint and possibly hashed fingerprint to files. */ + if (router_write_fingerprint(0)) { + log_err(LD_FS, "Error writing fingerprint to file"); return -1; } - tor_assert(strlen(options->Nickname) <= MAX_NICKNAME_LEN); - if (tor_snprintf(fingerprint_line, sizeof(fingerprint_line), - "%s %s\n",options->Nickname, fingerprint) < 0) { - log_err(LD_GENERAL,"Error writing fingerprint line"); - tor_free(keydir); + if (!public_server_mode(options) && router_write_fingerprint(1)) { + log_err(LD_FS, "Error writing hashed fingerprint to file"); return -1; } - /* Check whether we need to write the fingerprint file. */ - cp = NULL; - if (file_status(keydir) == FN_FILE) - cp = read_file_to_str(keydir, 0, NULL); - if (!cp || strcmp(cp, fingerprint_line)) { - if (write_str_to_file(keydir, fingerprint_line, 0)) { - log_err(LD_FS, "Error writing fingerprint line to file"); - tor_free(keydir); - tor_free(cp); - return -1; - } - } - tor_free(cp); - tor_free(keydir); - log_notice(LD_GENERAL, - "Your Tor server's identity key fingerprint is '%s %s'", - options->Nickname, fingerprint); if (!authdir_mode(options)) return 0; /* 6. [authdirserver only] load approved-routers file */ -- cgit v1.2.3