From 0ba4e0895ae2395a528aacd1625715a7ffc29211 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 1 Sep 2015 10:22:24 -0400 Subject: [PATCH] Add "OfflineMasterKey" option When this is set, and Tor is running as a relay, it will not generate or load its secret identity key. You can manage the secret identity key with --keygen. Implements ticket 16944. --- changes/feature16944 | 5 +++++ doc/tor.1.txt | 5 +++++ src/or/config.c | 1 + src/or/or.h | 5 +++++ src/or/routerkeys.c | 32 ++++++++++++++++++++++++++------ 5 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 changes/feature16944 diff --git a/changes/feature16944 b/changes/feature16944 new file mode 100644 index 0000000000..1728beff7f --- /dev/null +++ b/changes/feature16944 @@ -0,0 +1,5 @@ + o Minor features (relay, ed25519): + - Add a new OfflineMasterKey option to tell Tor never to try + loading or generating a secret ed25519 identity key. You can use + this in combination with tor --keygen to manage offline and/or + encrypted ed25519 keys. Implements ticket 16944. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index af99570bd4..e34b19ed66 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1877,6 +1877,11 @@ is non-zero): configures their lifetime. (Default: 30 days) +[[OfflineMasterKey]] **OfflineMasterKey** **0**|**1**:: + If non-zero, the Tor relay will never generate or load its master secret + key. Instead, you'll have to use "tor --keygen" to manage the master + secret key. (Default: 0) + DIRECTORY SERVER OPTIONS ------------------------ diff --git a/src/or/config.c b/src/or/config.c index 6e782de0e0..3b8bf55875 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -333,6 +333,7 @@ static config_var_t option_vars_[] = { V(NumCPUs, UINT, "0"), V(NumDirectoryGuards, UINT, "0"), V(NumEntryGuards, UINT, "0"), + V(OfflineMasterKey, BOOL, "0"), V(ORListenAddress, LINELIST, NULL), VPORT(ORPort, LINELIST, NULL), V(OutboundBindAddress, LINELIST, NULL), diff --git a/src/or/or.h b/src/or/or.h index 8c40f1ab67..b753f7c11e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4295,6 +4295,10 @@ typedef struct { /** How long before auth keys expire will we try to make a new one? */ int TestingAuthKeySlop; + /** Force use of offline master key features: never generate a master + * ed25519 identity key except from tor --keygen */ + int OfflineMasterKey; + enum { FORCE_PASSPHRASE_AUTO=0, FORCE_PASSPHRASE_ON, @@ -4302,6 +4306,7 @@ typedef struct { } keygen_force_passphrase; int use_keygen_passphrase_fd; int keygen_passphrase_fd; + } or_options_t; /** Persistent state for an onion router, as saved to disk. */ diff --git a/src/or/routerkeys.c b/src/or/routerkeys.c index 50659fcb69..283effa2fd 100644 --- a/src/or/routerkeys.c +++ b/src/or/routerkeys.c @@ -668,6 +668,9 @@ load_ed_keys(const or_options_t *options, time_t now) use_signing = sign; } + const int offline_master = + options->OfflineMasterKey && options->command != CMD_KEYGEN; + const int need_new_signing_key = NULL == use_signing || EXPIRES_SOON(check_signing_cert, 0) || @@ -676,29 +679,43 @@ load_ed_keys(const or_options_t *options, time_t now) need_new_signing_key || EXPIRES_SOON(check_signing_cert, options->TestingSigningKeySlop); + /* We can only create a master key if we haven't been told that the + * master key will always be offline. Also, if we have a signing key, + * then we shouldn't make a new master ID key. */ + const int can_make_master_id_key = !offline_master && + NULL == use_signing; + if (need_new_signing_key) { log_notice(LD_OR, "It looks like I need to generate and sign a new " "medium-term signing key, because %s. To do that, I need to " - "load (or create) the permanent master identity key.", + "load%s the permanent master identity key.", (NULL == use_signing) ? "I don't have one" : EXPIRES_SOON(check_signing_cert, 0) ? "the one I have is expired" : - "you asked me to make one with --keygen"); - } else if (want_new_signing_key) { + "you asked me to make one with --keygen", + can_make_master_id_key ? " (or create)" : ""); + } else if (want_new_signing_key && !offline_master) { log_notice(LD_OR, "It looks like I should try to generate and sign a " "new medium-term signing key, because the one I have is " "going to expire soon. To do that, I'm going to have to try to " "load the permanent master identity key."); + } else if (want_new_signing_key) { + log_notice(LD_OR, "It looks like I should try to generate and sign a " + "new medium-term signing key, because the one I have is " + "going to expire soon. But OfflineMasterKey is set, so I " + "won't try to load a permanent master identity key is set. " + "You will need to use 'tor --keygen' make a new signing key " + "and certificate."); } { uint32_t flags = (INIT_ED_KEY_SPLIT| INIT_ED_KEY_EXTRA_STRONG|INIT_ED_KEY_NO_REPAIR); - if (! use_signing) + if (can_make_master_id_key) flags |= INIT_ED_KEY_CREATE; if (! need_new_signing_key) flags |= INIT_ED_KEY_MISSING_SECRET_OK; - if (! want_new_signing_key) + if (! want_new_signing_key || offline_master) flags |= INIT_ED_KEY_OMIT_SECRET; if (options->command == CMD_KEYGEN) flags |= INIT_ED_KEY_TRY_ENCRYPTED; @@ -724,7 +741,10 @@ load_ed_keys(const or_options_t *options, time_t now) tor_free(fname); if (!id) { if (need_new_signing_key) { - FAIL("Missing identity key"); + if (offline_master) + FAIL("Can't load master identity key; OfflineMasterKey is set."); + else + FAIL("Missing identity key"); } else { log_warn(LD_OR, "Master public key was absent; inferring from " "public key in signing certificate and saving to disk.");