diff options
author | Nick Mathewson <nickm@torproject.org> | 2015-08-05 21:09:21 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-08-19 13:36:49 -0400 |
commit | f362e7a873f4a582e01371f001665eaaf0382434 (patch) | |
tree | 4d7c0d1b6b712c65c5f1dffa5c2b1d1b1578f76a /src/or | |
parent | 1ccba302f77315b459540cda2168c813e0d24371 (diff) | |
download | tor-f362e7a873f4a582e01371f001665eaaf0382434.tar.gz tor-f362e7a873f4a582e01371f001665eaaf0382434.zip |
Checkpoint work on ed25519 keygen improvements.
Needs changes file, documentation, test integration, more tests.
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/config.c | 39 | ||||
-rw-r--r-- | src/or/or.h | 7 | ||||
-rw-r--r-- | src/or/routerkeys.c | 104 |
3 files changed, 135 insertions, 15 deletions
diff --git a/src/or/config.c b/src/or/config.c index 618c941fb4..d22452bfd4 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1912,6 +1912,8 @@ static const struct { { "--dump-config", ARGUMENT_OPTIONAL }, { "--list-fingerprint", TAKES_NO_ARGUMENT }, { "--keygen", TAKES_NO_ARGUMENT }, + { "--no-passphrase", TAKES_NO_ARGUMENT }, + { "--passphrase-fd", ARGUMENT_NECESSARY }, { "--verify-config", TAKES_NO_ARGUMENT }, { "--ignore-missing-torrc", TAKES_NO_ARGUMENT }, { "--quiet", TAKES_NO_ARGUMENT }, @@ -4492,6 +4494,43 @@ options_init_from_torrc(int argc, char **argv) retval = options_init_from_string(cf_defaults, cf, command, command_arg, &errmsg); + if (retval < 0) + goto err; + + if (config_line_find(cmdline_only_options, "--no-passphrase")) { + if (command == CMD_KEYGEN) { + get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_OFF; + } else { + log_err(LD_CONFIG, "--no-passphrase specified without --keygen!"); + exit(1); + } + } + + { + const config_line_t *fd_line = config_line_find(cmdline_only_options, + "--passphrase-fd"); + if (fd_line) { + if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) { + log_err(LD_CONFIG, "--no-passphrase specified with --passphrase-fd!"); + exit(1); + } else if (command != CMD_KEYGEN) { + log_err(LD_CONFIG, "--passphrase-fd specified without --keygen!"); + exit(1); + } else { + const char *v = fd_line->value; + int ok = 1; + long fd = tor_parse_long(v, 10, 0, INT_MAX, &ok, NULL); + if (fd < 0 || ok == 0) { + log_err(LD_CONFIG, "Invalid --passphrase-fd value %s", escaped(v)); + exit(1); + } + get_options_mutable()->keygen_passphrase_fd = (int)fd; + get_options_mutable()->use_keygen_passphrase_fd = 1; + get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_ON; + } + } + } + err: tor_free(cf); diff --git a/src/or/or.h b/src/or/or.h index f6aee13f5b..96e69bc9ba 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4292,6 +4292,13 @@ typedef struct { /** How long before auth keys expire will we try to make a new one? */ int TestingAuthKeySlop; + enum { + FORCE_PASSPHRASE_AUTO=0, + FORCE_PASSPHRASE_ON, + FORCE_PASSPHRASE_OFF + } 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 47a6c89534..b15d31bc61 100644 --- a/src/or/routerkeys.c +++ b/src/or/routerkeys.c @@ -11,6 +11,72 @@ #define ENC_KEY_HEADER "Boxed Ed25519 key" #define ENC_KEY_TAG "master" +static ssize_t +do_getpass(const char *prompt, char *buf, size_t buflen, + int twice, const or_options_t *options) +{ + if (options->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) { + tor_assert(buflen); + buf[0] = 0; + return 0; + } + + char *prompt2 = NULL; + char *buf2 = NULL; + int fd = -1; + ssize_t length = -1; + + if (options->use_keygen_passphrase_fd) { + twice = 0; + fd = options->keygen_passphrase_fd; + length = read_all(fd, buf, buflen-1, 0); + if (length >= 0) + buf[length] = 0; + goto done_reading; + } + + if (twice) { + const char msg[] = "One more time:"; + size_t p2len = strlen(prompt) + 1; + if (p2len < sizeof(msg)) + p2len = sizeof(msg); + prompt2 = tor_malloc(strlen(prompt)+1); + memset(prompt2, ' ', p2len); + memcpy(prompt2 + p2len - sizeof(msg), msg, sizeof(msg)); + + buf2 = tor_malloc_zero(buflen); + } + + while (1) { + length = tor_getpass(prompt, buf, buflen); + if (length < 0) + goto done_reading; + + if (! twice) + break; + + ssize_t length2 = tor_getpass(prompt2, buf2, buflen); + + if (length != length2 || tor_memneq(buf, buf2, length)) { + fprintf(stderr, "That didn't match.\n"); + } else { + break; + } + } + + done_reading: + if (twice) { + tor_free(prompt2); + memwipe(buf2, 0, buflen); + tor_free(buf2); + } + + if (options->keygen_force_passphrase == FORCE_PASSPHRASE_ON && length == 0) + return -1; + + return length; +} + int read_encrypted_secret_key(ed25519_secret_key_t *out, const char *fname) @@ -41,22 +107,24 @@ read_encrypted_secret_key(ed25519_secret_key_t *out, while (1) { ssize_t pwlen = - tor_getpass("Enter pasphrase for master key:", pwbuf, sizeof(pwbuf)); + do_getpass("Enter pasphrase for master key:", pwbuf, sizeof(pwbuf), 0, + get_options()); if (pwlen < 0) { saved_errno = EINVAL; goto done; } - const int r = crypto_unpwbox(&secret, &secret_len, encrypted_key, encrypted_len, pwbuf, pwlen); if (r == UNPWBOX_CORRUPTED) { log_err(LD_OR, "%s is corrupted.", fname); + puts("E"); saved_errno = EINVAL; goto done; } else if (r == UNPWBOX_OKAY) { break; } + /* Otherwise, passphrase is bad, so try again till user does ctrl-c or gets * it right. */ } @@ -87,22 +155,23 @@ write_encrypted_secret_key(const ed25519_secret_key_t *key, const char *fname) { int r = -1; - char pwbuf0[256], pwbuf1[256]; + char pwbuf0[256]; uint8_t *encrypted_key = NULL; size_t encrypted_len = 0; - while (1) { - if (tor_getpass("Enter passphrase:", pwbuf0, sizeof(pwbuf0)) < 0) - return -1; - if (tor_getpass(" One more time:", pwbuf1, sizeof(pwbuf1)) < 0) - return -1; + if (do_getpass("Enter new passphrase:", pwbuf0, sizeof(pwbuf0), 1, + get_options()) < 0) { + log_warn(LD_OR, "NO/failed passphrase"); + return -1; + } - if (!strcmp(pwbuf0, pwbuf1)) - break; - fprintf(stderr, "That didn't match.\n"); + if (strlen(pwbuf0) == 0) { + if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_ON) + return -1; + else + return 0; } - if (0 == strlen(pwbuf0)) - return 0; + if (crypto_pwbox(&encrypted_key, &encrypted_len, key->seckey, sizeof(key->seckey), pwbuf0, strlen(pwbuf0), 0) < 0) { @@ -121,7 +190,6 @@ write_encrypted_secret_key(const ed25519_secret_key_t *key, tor_free(encrypted_key); } memwipe(pwbuf0, 0, sizeof(pwbuf0)); - memwipe(pwbuf1, 0, sizeof(pwbuf1)); return r; } @@ -134,7 +202,9 @@ write_secret_key(const ed25519_secret_key_t *key, int encrypted, if (encrypted) { int r = write_encrypted_secret_key(key, encrypted_fname); if (r != 0) - return r; + return r; /* Either succeeded or failed unrecoverably */ + + fprintf(stderr, "Not encrypting the secret key.\n"); } return ed25519_seckey_write_to_file(key, fname, fname_tag); } @@ -628,6 +698,9 @@ load_ed_keys(const or_options_t *options, time_t now) * it, if we loaded it in the first place. */ memwipe(id->seckey.seckey, 0, sizeof(id->seckey)); + if (options->command == CMD_KEYGEN) + goto end; + if (!rsa_ed_crosscert && server_mode(options)) { uint8_t *crosscert; ssize_t crosscert_len = tor_make_rsa_ed25519_crosscert(&id->pubkey, @@ -651,6 +724,7 @@ load_ed_keys(const or_options_t *options, time_t now) /* We've generated or loaded everything. Put them in memory. */ + end: if (! master_identity_key) { SET_KEY(master_identity_key, id); } else { |