From 0ba4e0895ae2395a528aacd1625715a7ffc29211 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 1 Sep 2015 10:22:24 -0400 Subject: [PATCH 1/2] 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."); From d70b1b4da13d30f16ba0604103a1ebe915a2a20a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 2 Sep 2015 11:49:28 -0400 Subject: [PATCH 2/2] Never ever try to load the secret key if offline_master is set (Not even if we can't find the public key.) --- src/or/routerkeys.c | 18 ++++++++++++++---- src/or/routerkeys.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/or/routerkeys.c b/src/or/routerkeys.c index 283effa2fd..d65b62991b 100644 --- a/src/or/routerkeys.c +++ b/src/or/routerkeys.c @@ -237,8 +237,12 @@ write_secret_key(const ed25519_secret_key_t *key, int encrypted, * If INIT_ED_KEY_MISSING_SECRET_OK is set in flags, and we find a * public key file but no secret key file, return successfully anyway. * - * If INIT_ED_KEY_OMIT_SECRET is set in flags, do not even try to - * load or return a secret key (but create and save one if needed). + * If INIT_ED_KEY_OMIT_SECRET is set in flags, do not try to load a + * secret key unless no public key is found. Do not return a secret key. (but + * create and save one if needed). + * + * If INIT_ED_KEY_NO_LOAD_SECRET is set in flags, don't try to load + * a secret key, no matter what. * * If INIT_ED_KEY_TRY_ENCRYPTED is set, we look for an encrypted secret key * and consider encrypting any new secret key. @@ -269,7 +273,8 @@ ed_key_init_from_file(const char *fname, uint32_t flags, const int encrypt_key = !! (flags & INIT_ED_KEY_TRY_ENCRYPTED); const int norepair = !! (flags & INIT_ED_KEY_NO_REPAIR); const int split = !! (flags & INIT_ED_KEY_SPLIT); - const int omit_secret = !! (flags & INIT_ED_KEY_OMIT_SECRET); + const int omit_secret = !! (flags & INIT_ED_KEY_OMIT_SECRET); + const int offline_secret = !! (flags & INIT_ED_KEY_OFFLINE_SECRET); /* we don't support setting both of these flags at once. */ tor_assert((flags & (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT)) != @@ -289,7 +294,10 @@ ed_key_init_from_file(const char *fname, uint32_t flags, /* Try to read the secret key. */ int have_secret = 0; - if (try_to_load && (!omit_secret || file_status(public_fname)==FN_NOENT )) { + int load_secret = try_to_load && + !offline_secret && + (!omit_secret || file_status(public_fname)==FN_NOENT); + if (load_secret) { int rv = ed25519_seckey_read_from_file(&keypair->seckey, &got_tag, secret_fname); if (rv == 0) { @@ -717,6 +725,8 @@ load_ed_keys(const or_options_t *options, time_t now) flags |= INIT_ED_KEY_MISSING_SECRET_OK; if (! want_new_signing_key || offline_master) flags |= INIT_ED_KEY_OMIT_SECRET; + if (offline_master) + flags |= INIT_ED_KEY_OFFLINE_SECRET; if (options->command == CMD_KEYGEN) flags |= INIT_ED_KEY_TRY_ENCRYPTED; diff --git a/src/or/routerkeys.h b/src/or/routerkeys.h index b4e73aa33f..b396779bd2 100644 --- a/src/or/routerkeys.h +++ b/src/or/routerkeys.h @@ -17,6 +17,7 @@ #define INIT_ED_KEY_TRY_ENCRYPTED (1u<<8) #define INIT_ED_KEY_NO_REPAIR (1u<<9) #define INIT_ED_KEY_SUGGEST_KEYGEN (1u<<10) +#define INIT_ED_KEY_OFFLINE_SECRET (1u<<11) struct tor_cert_st; ed25519_keypair_t *ed_key_init_from_file(const char *fname, uint32_t flags,