diff --git a/changes/ticket30642 b/changes/ticket30642 new file mode 100644 index 0000000000..13941b2ac5 --- /dev/null +++ b/changes/ticket30642 @@ -0,0 +1,4 @@ + o Minor features (ed25519, relay): + - Save a relay's base64-encoded ed25519 identity key to the data + directory in a file named fingerprint-ed25519. Closes ticket 30642. + Patch by Neel Chauhan. diff --git a/src/app/main/main.c b/src/app/main/main.c index 32c34ea821..e6fa789a7d 100644 --- a/src/app/main/main.c +++ b/src/app/main/main.c @@ -1053,12 +1053,14 @@ sandbox_init_filter(void) OPEN_DATADIR("approved-routers"); OPEN_DATADIR_SUFFIX("fingerprint", ".tmp"); + OPEN_DATADIR_SUFFIX("fingerprint-ed25519", ".tmp"); OPEN_DATADIR_SUFFIX("hashed-fingerprint", ".tmp"); OPEN_DATADIR_SUFFIX("router-stability", ".tmp"); OPEN("/etc/resolv.conf"); RENAME_SUFFIX("fingerprint", ".tmp"); + RENAME_SUFFIX("fingerprint-ed25519", ".tmp"); RENAME_KEYDIR_SUFFIX("secret_onion_key_ntor", ".tmp"); RENAME_KEYDIR_SUFFIX("secret_id_key", ".tmp"); diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index 1691ac5f48..dfe9c9a823 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -831,30 +831,37 @@ router_initialize_tls_context(void) * -1 if Tor should die, */ STATIC int -router_write_fingerprint(int hashed) +router_write_fingerprint(int hashed, int ed25519_identity) { char *keydir = NULL, *cp = NULL; const char *fname = hashed ? "hashed-fingerprint" : - "fingerprint"; + (ed25519_identity ? "fingerprint-ed25519" : + "fingerprint"); char fingerprint[FINGERPRINT_LEN+1]; const or_options_t *options = get_options(); char *fingerprint_line = NULL; int result = -1; 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"); - goto done; - } - } else { - if (crypto_pk_get_hashed_fingerprint(get_server_identity_key(), - fingerprint) < 0) { - log_err(LD_GENERAL,"Error computing hashed fingerprint"); - goto done; + log_info(LD_GENERAL,"Dumping %s%s to \"%s\"...", hashed ? "hashed " : "", + ed25519_identity ? "ed25519 identity" : "fingerprint", keydir); + + if (ed25519_identity) { /* ed25519 identity */ + digest256_to_base64(fingerprint, (const char *) + get_master_identity_key()->pubkey); + } else { /* RSA identity */ + if (!hashed) { + if (crypto_pk_get_fingerprint(get_server_identity_key(), + fingerprint, 0) < 0) { + log_err(LD_GENERAL,"Error computing fingerprint"); + goto done; + } + } else { + if (crypto_pk_get_hashed_fingerprint(get_server_identity_key(), + fingerprint) < 0) { + log_err(LD_GENERAL,"Error computing hashed fingerprint"); + goto done; + } } } @@ -865,15 +872,17 @@ router_write_fingerprint(int hashed) cp = read_file_to_str(keydir, RFTS_IGNORE_MISSING, 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 " : ""); + log_err(LD_FS, "Error writing %s%s line to file", + hashed ? "hashed " : "", + ed25519_identity ? "ed25519 identity" : "fingerprint"); goto done; } } - log_notice(LD_GENERAL, "Your Tor %s identity key fingerprint is '%s %s'", - hashed ? "bridge's hashed" : "server's", options->Nickname, - fingerprint); + log_notice(LD_GENERAL, "Your Tor %s identity key %s fingerprint is '%s %s'", + hashed ? "bridge's hashed" : "server's", + ed25519_identity ? "ed25519" : "", + options->Nickname, fingerprint); result = 0; done: @@ -1109,15 +1118,20 @@ init_keys(void) } } - /* 5. Dump fingerprint and possibly hashed fingerprint to files. */ - if (router_write_fingerprint(0)) { + /* 5. Dump fingerprint, ed25519 identity and possibly hashed fingerprint + * to files. */ + if (router_write_fingerprint(0, 0)) { log_err(LD_FS, "Error writing fingerprint to file"); return -1; } - if (!public_server_mode(options) && router_write_fingerprint(1)) { + if (!public_server_mode(options) && router_write_fingerprint(1, 0)) { log_err(LD_FS, "Error writing hashed fingerprint to file"); return -1; } + if (router_write_fingerprint(0, 1)) { + log_err(LD_FS, "Error writing ed25519 identity to file"); + return -1; + } if (!authdir_mode(options)) return 0; diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h index 50790a73dd..b7d99a1016 100644 --- a/src/feature/relay/router.h +++ b/src/feature/relay/router.h @@ -124,7 +124,7 @@ void router_free_all(void); #ifdef ROUTER_PRIVATE /* Used only by router.c and the unit tests */ STATIC void get_platform_str(char *platform, size_t len); -STATIC int router_write_fingerprint(int hashed); +STATIC int router_write_fingerprint(int hashed, int ed25519_identity); STATIC smartlist_t *get_my_declared_family(const or_options_t *options); #ifdef TOR_UNIT_TESTS diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c index fc437dccc0..bafc886bc6 100644 --- a/src/test/test_routerkeys.c +++ b/src/test/test_routerkeys.c @@ -51,7 +51,7 @@ test_routerkeys_write_fingerprint(void *arg) tt_int_op(crypto_pk_cmp_keys(get_server_identity_key(),key),OP_EQ,0); /* Write fingerprint file */ - tt_int_op(0, OP_EQ, router_write_fingerprint(0)); + tt_int_op(0, OP_EQ, router_write_fingerprint(0, 0)); cp = read_file_to_str(get_fname("write_fingerprint/fingerprint"), 0, NULL); crypto_pk_get_fingerprint(key, fp, 0); @@ -61,7 +61,7 @@ test_routerkeys_write_fingerprint(void *arg) tor_free(cp2); /* Write hashed-fingerprint file */ - tt_int_op(0, OP_EQ, router_write_fingerprint(1)); + tt_int_op(0, OP_EQ, router_write_fingerprint(1, 0)); cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), 0, NULL); crypto_pk_get_hashed_fingerprint(key, fp); @@ -73,7 +73,7 @@ test_routerkeys_write_fingerprint(void *arg) /* Replace outdated file */ write_str_to_file(get_fname("write_fingerprint/hashed-fingerprint"), "junk goes here", 0); - tt_int_op(0, OP_EQ, router_write_fingerprint(1)); + tt_int_op(0, OP_EQ, router_write_fingerprint(1, 0)); cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), 0, NULL); crypto_pk_get_hashed_fingerprint(key, fp); @@ -89,6 +89,52 @@ test_routerkeys_write_fingerprint(void *arg) tor_free(cp2); } +static void +test_routerkeys_write_ed25519_identity(void *arg) +{ + crypto_pk_t *key = pk_generate(2); + or_options_t *options = get_options_mutable(); + time_t now = time(NULL); + const char *ddir = get_fname("write_fingerprint"); + char *cp = NULL, *cp2 = NULL; + char ed25519_id[BASE64_DIGEST256_LEN + 1]; + + (void) arg; + + tt_assert(key); + + options->ORPort_set = 1; /* So that we can get the server ID key */ + tor_free(options->DataDirectory); + options->DataDirectory = tor_strdup(ddir); + options->Nickname = tor_strdup("haflinger"); + set_server_identity_key(key); + set_client_identity_key(crypto_pk_dup_key(key)); + + load_ed_keys(options, now); + generate_ed_link_cert(options, now, 0); + tt_assert(get_master_identity_key()); + + tt_int_op(0, OP_EQ, check_private_dir(ddir, CPD_CREATE, NULL)); + + /* Write fingerprint file */ + tt_int_op(0, OP_EQ, router_write_fingerprint(0, 1)); + cp = read_file_to_str(get_fname("write_fingerprint/fingerprint-ed25519"), + 0, NULL); + digest256_to_base64(ed25519_id, + (const char *) get_master_identity_key()->pubkey); + tor_asprintf(&cp2, "haflinger %s\n", ed25519_id); + tt_str_op(cp, OP_EQ, cp2); + tor_free(cp); + tor_free(cp2); + + done: + crypto_pk_free(key); + set_client_identity_key(NULL); + tor_free(cp); + tor_free(cp2); + routerkeys_free_all(); +} + static void test_routerkeys_ed_certs(void *args) { @@ -695,6 +741,7 @@ test_routerkeys_rsa_ed_crosscert(void *arg) struct testcase_t routerkeys_tests[] = { TEST(write_fingerprint, TT_FORK), + TEST(write_ed25519_identity, TT_FORK), TEST(ed_certs, TT_FORK), TEST(ed_key_create, TT_FORK), TEST(ed_key_init_basic, TT_FORK),