mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
Checkpoint work on ed25519 keygen improvements.
Needs changes file, documentation, test integration, more tests.
This commit is contained in:
parent
1ccba302f7
commit
f362e7a873
@ -1912,6 +1912,8 @@ static const struct {
|
|||||||
{ "--dump-config", ARGUMENT_OPTIONAL },
|
{ "--dump-config", ARGUMENT_OPTIONAL },
|
||||||
{ "--list-fingerprint", TAKES_NO_ARGUMENT },
|
{ "--list-fingerprint", TAKES_NO_ARGUMENT },
|
||||||
{ "--keygen", TAKES_NO_ARGUMENT },
|
{ "--keygen", TAKES_NO_ARGUMENT },
|
||||||
|
{ "--no-passphrase", TAKES_NO_ARGUMENT },
|
||||||
|
{ "--passphrase-fd", ARGUMENT_NECESSARY },
|
||||||
{ "--verify-config", TAKES_NO_ARGUMENT },
|
{ "--verify-config", TAKES_NO_ARGUMENT },
|
||||||
{ "--ignore-missing-torrc", TAKES_NO_ARGUMENT },
|
{ "--ignore-missing-torrc", TAKES_NO_ARGUMENT },
|
||||||
{ "--quiet", 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,
|
retval = options_init_from_string(cf_defaults, cf, command, command_arg,
|
||||||
&errmsg);
|
&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:
|
err:
|
||||||
|
|
||||||
tor_free(cf);
|
tor_free(cf);
|
||||||
|
@ -4292,6 +4292,13 @@ typedef struct {
|
|||||||
/** How long before auth keys expire will we try to make a new one? */
|
/** How long before auth keys expire will we try to make a new one? */
|
||||||
int TestingAuthKeySlop;
|
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;
|
} or_options_t;
|
||||||
|
|
||||||
/** Persistent state for an onion router, as saved to disk. */
|
/** Persistent state for an onion router, as saved to disk. */
|
||||||
|
@ -11,6 +11,72 @@
|
|||||||
#define ENC_KEY_HEADER "Boxed Ed25519 key"
|
#define ENC_KEY_HEADER "Boxed Ed25519 key"
|
||||||
#define ENC_KEY_TAG "master"
|
#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
|
int
|
||||||
read_encrypted_secret_key(ed25519_secret_key_t *out,
|
read_encrypted_secret_key(ed25519_secret_key_t *out,
|
||||||
const char *fname)
|
const char *fname)
|
||||||
@ -41,22 +107,24 @@ read_encrypted_secret_key(ed25519_secret_key_t *out,
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ssize_t pwlen =
|
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) {
|
if (pwlen < 0) {
|
||||||
saved_errno = EINVAL;
|
saved_errno = EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int r = crypto_unpwbox(&secret, &secret_len,
|
const int r = crypto_unpwbox(&secret, &secret_len,
|
||||||
encrypted_key, encrypted_len,
|
encrypted_key, encrypted_len,
|
||||||
pwbuf, pwlen);
|
pwbuf, pwlen);
|
||||||
if (r == UNPWBOX_CORRUPTED) {
|
if (r == UNPWBOX_CORRUPTED) {
|
||||||
log_err(LD_OR, "%s is corrupted.", fname);
|
log_err(LD_OR, "%s is corrupted.", fname);
|
||||||
|
puts("E");
|
||||||
saved_errno = EINVAL;
|
saved_errno = EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
} else if (r == UNPWBOX_OKAY) {
|
} else if (r == UNPWBOX_OKAY) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, passphrase is bad, so try again till user does ctrl-c or gets
|
/* Otherwise, passphrase is bad, so try again till user does ctrl-c or gets
|
||||||
* it right. */
|
* it right. */
|
||||||
}
|
}
|
||||||
@ -87,22 +155,23 @@ write_encrypted_secret_key(const ed25519_secret_key_t *key,
|
|||||||
const char *fname)
|
const char *fname)
|
||||||
{
|
{
|
||||||
int r = -1;
|
int r = -1;
|
||||||
char pwbuf0[256], pwbuf1[256];
|
char pwbuf0[256];
|
||||||
uint8_t *encrypted_key = NULL;
|
uint8_t *encrypted_key = NULL;
|
||||||
size_t encrypted_len = 0;
|
size_t encrypted_len = 0;
|
||||||
|
|
||||||
while (1) {
|
if (do_getpass("Enter new passphrase:", pwbuf0, sizeof(pwbuf0), 1,
|
||||||
if (tor_getpass("Enter passphrase:", pwbuf0, sizeof(pwbuf0)) < 0)
|
get_options()) < 0) {
|
||||||
return -1;
|
log_warn(LD_OR, "NO/failed passphrase");
|
||||||
if (tor_getpass(" One more time:", pwbuf1, sizeof(pwbuf1)) < 0)
|
return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!strcmp(pwbuf0, pwbuf1))
|
|
||||||
break;
|
|
||||||
fprintf(stderr, "That didn't match.\n");
|
|
||||||
}
|
}
|
||||||
if (0 == strlen(pwbuf0))
|
|
||||||
return 0;
|
if (strlen(pwbuf0) == 0) {
|
||||||
|
if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_ON)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (crypto_pwbox(&encrypted_key, &encrypted_len,
|
if (crypto_pwbox(&encrypted_key, &encrypted_len,
|
||||||
key->seckey, sizeof(key->seckey),
|
key->seckey, sizeof(key->seckey),
|
||||||
pwbuf0, strlen(pwbuf0), 0) < 0) {
|
pwbuf0, strlen(pwbuf0), 0) < 0) {
|
||||||
@ -121,7 +190,6 @@ write_encrypted_secret_key(const ed25519_secret_key_t *key,
|
|||||||
tor_free(encrypted_key);
|
tor_free(encrypted_key);
|
||||||
}
|
}
|
||||||
memwipe(pwbuf0, 0, sizeof(pwbuf0));
|
memwipe(pwbuf0, 0, sizeof(pwbuf0));
|
||||||
memwipe(pwbuf1, 0, sizeof(pwbuf1));
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +202,9 @@ write_secret_key(const ed25519_secret_key_t *key, int encrypted,
|
|||||||
if (encrypted) {
|
if (encrypted) {
|
||||||
int r = write_encrypted_secret_key(key, encrypted_fname);
|
int r = write_encrypted_secret_key(key, encrypted_fname);
|
||||||
if (r != 0)
|
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);
|
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. */
|
* it, if we loaded it in the first place. */
|
||||||
memwipe(id->seckey.seckey, 0, sizeof(id->seckey));
|
memwipe(id->seckey.seckey, 0, sizeof(id->seckey));
|
||||||
|
|
||||||
|
if (options->command == CMD_KEYGEN)
|
||||||
|
goto end;
|
||||||
|
|
||||||
if (!rsa_ed_crosscert && server_mode(options)) {
|
if (!rsa_ed_crosscert && server_mode(options)) {
|
||||||
uint8_t *crosscert;
|
uint8_t *crosscert;
|
||||||
ssize_t crosscert_len = tor_make_rsa_ed25519_crosscert(&id->pubkey,
|
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. */
|
/* We've generated or loaded everything. Put them in memory. */
|
||||||
|
|
||||||
|
end:
|
||||||
if (! master_identity_key) {
|
if (! master_identity_key) {
|
||||||
SET_KEY(master_identity_key, id);
|
SET_KEY(master_identity_key, id);
|
||||||
} else {
|
} else {
|
||||||
|
332
src/test/test_keygen.sh
Executable file
332
src/test/test_keygen.sh
Executable file
@ -0,0 +1,332 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Note: some of this code is lifted from zero_length_keys.sh, and could be
|
||||||
|
# unified.
|
||||||
|
|
||||||
|
umask 077
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ $# -eq 0 ] || [ ! -f ${1} ] || [ ! -x ${1} ]; then
|
||||||
|
echo "Usage: ${0} PATH_TO_TOR [case-number]"
|
||||||
|
exit 1
|
||||||
|
elif [ $# -ge 1 ]; then
|
||||||
|
TOR_BINARY="${1}"
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ $# -ge 1 ]; then
|
||||||
|
dflt=0
|
||||||
|
else
|
||||||
|
dflt=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CASE2A=$dflt
|
||||||
|
CASE2B=$dflt
|
||||||
|
CASE3A=$dflt
|
||||||
|
CASE3B=$dflt
|
||||||
|
CASE3C=$dflt
|
||||||
|
CASE4=$dflt
|
||||||
|
CASE5=$dflt
|
||||||
|
CASE6=$dflt
|
||||||
|
CASE7=$dflt
|
||||||
|
CASE8=$dflt
|
||||||
|
CASE9=$dflt
|
||||||
|
CASE10=$dflt
|
||||||
|
|
||||||
|
if [ $# -ge 1 ]; then
|
||||||
|
eval "CASE${1}"=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
die() { echo "$1" >&2 ; exit 5; }
|
||||||
|
check_dir() { [ -d "$1" ] || die "$1 did not exist"; }
|
||||||
|
check_file() { [ -e "$1" ] || die "$1 did not exist"; }
|
||||||
|
check_no_file() { [ -e "$1" ] && die "$1 was not supposed to exist" || true; }
|
||||||
|
check_files_eq() { cmp "$1" "$2" || die "$1 and $2 did not match"; }
|
||||||
|
check_keys_eq() { check_files_eq "${SRC}/keys/${1}" "${ME}/keys/${1}"; }
|
||||||
|
|
||||||
|
DATA_DIR=`mktemp -d -t tor_keygen_tests.XXXXXX`
|
||||||
|
if [ -z "$DATA_DIR" ]; then
|
||||||
|
echo "Failure: mktemp invocation returned empty string" >&2
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
if [ ! -d "$DATA_DIR" ]; then
|
||||||
|
echo "Failure: mktemp invocation result doesn't point to directory" >&2
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
trap "rm -rf '$DATA_DIR'" 0
|
||||||
|
|
||||||
|
touch "${DATA_DIR}/empty_torrc"
|
||||||
|
|
||||||
|
TOR="${TOR_BINARY} --hush --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f ${DATA_DIR}/empty_torrc"
|
||||||
|
|
||||||
|
# Step 1: Start Tor with --list-fingerprint. Make sure everything is there.
|
||||||
|
mkdir "${DATA_DIR}/orig"
|
||||||
|
${TOR} --DataDirectory "${DATA_DIR}/orig" --list-fingerprint > /dev/null
|
||||||
|
|
||||||
|
check_dir "${DATA_DIR}/orig/keys"
|
||||||
|
check_file "${DATA_DIR}/orig/keys/ed25519_master_id_public_key"
|
||||||
|
check_file "${DATA_DIR}/orig/keys/ed25519_master_id_secret_key"
|
||||||
|
check_file "${DATA_DIR}/orig/keys/ed25519_signing_cert"
|
||||||
|
check_file "${DATA_DIR}/orig/keys/ed25519_signing_secret_key"
|
||||||
|
|
||||||
|
# Step 2: Start Tor with --keygen. Make sure everything is there.
|
||||||
|
mkdir "${DATA_DIR}/keygen"
|
||||||
|
${TOR} --DataDirectory "${DATA_DIR}/keygen" --keygen --no-passphrase
|
||||||
|
|
||||||
|
check_dir "${DATA_DIR}/keygen/keys"
|
||||||
|
check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_public_key"
|
||||||
|
check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_secret_key"
|
||||||
|
check_file "${DATA_DIR}/keygen/keys/ed25519_signing_cert"
|
||||||
|
check_file "${DATA_DIR}/keygen/keys/ed25519_signing_secret_key"
|
||||||
|
|
||||||
|
# Step 3: Start Tor with --keygen and a passphrase.
|
||||||
|
# Make sure everything is there.
|
||||||
|
mkdir "${DATA_DIR}/encrypted"
|
||||||
|
echo "passphrase" | ${TOR} --DataDirectory "${DATA_DIR}/encrypted" --keygen --passphrase-fd 0
|
||||||
|
|
||||||
|
check_dir "${DATA_DIR}/encrypted/keys"
|
||||||
|
check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_public_key"
|
||||||
|
check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_secret_key_encrypted"
|
||||||
|
check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_cert"
|
||||||
|
check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_secret_key"
|
||||||
|
|
||||||
|
|
||||||
|
echo "KEY GENERATION WAS SUCCESSFUL."
|
||||||
|
|
||||||
|
#
|
||||||
|
# The "case X" numbers below come from s7r's email on
|
||||||
|
# https://lists.torproject.org/pipermail/tor-dev/2015-August/009204.html
|
||||||
|
|
||||||
|
|
||||||
|
# Case 2a: Missing secret key, public key exists, start tor.
|
||||||
|
|
||||||
|
if [ "$CASE2A" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case2a"
|
||||||
|
SRC="${DATA_DIR}/orig"
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint && die "Somehow succeeded when missing secret key, certs" || true
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
|
||||||
|
|
||||||
|
echo "==== Case 2A ok"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 2b: Encrypted secret key, public key exists, start tor.
|
||||||
|
|
||||||
|
if [ "$CASE2B" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case2b"
|
||||||
|
SRC="${DATA_DIR}/encrypted"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint && dir "Somehow succeeded with encrypted secret key, missing certs"
|
||||||
|
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted"
|
||||||
|
|
||||||
|
echo "==== Case 2B ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 3a: Start Tor with only master key.
|
||||||
|
|
||||||
|
if [ "$CASE3A" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case3a"
|
||||||
|
SRC="${DATA_DIR}/orig"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint || die "Tor failed when starting with only master key"
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key"
|
||||||
|
check_file "${ME}/keys/ed25519_signing_cert"
|
||||||
|
check_file "${ME}/keys/ed25519_signing_secret_key"
|
||||||
|
|
||||||
|
echo "==== Case 3A ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 3b: Call keygen with only unencrypted master key.
|
||||||
|
|
||||||
|
if [ "$CASE3B" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case3b"
|
||||||
|
SRC="${DATA_DIR}/orig"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
|
||||||
|
${TOR} --DataDirectory "${ME}" --keygen || die "Keygen failed with only master key"
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key"
|
||||||
|
check_file "${ME}/keys/ed25519_signing_cert"
|
||||||
|
check_file "${ME}/keys/ed25519_signing_secret_key"
|
||||||
|
|
||||||
|
echo "==== Case 3B ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 3c: Call keygen with only encrypted master key.
|
||||||
|
|
||||||
|
if [ "$CASE3C" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case3c"
|
||||||
|
SRC="${DATA_DIR}/encrypted"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
|
||||||
|
echo "passphrase" | ${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd 0 || die "Keygen failed with only encrypted master key"
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted"
|
||||||
|
check_file "${ME}/keys/ed25519_signing_cert"
|
||||||
|
check_file "${ME}/keys/ed25519_signing_secret_key"
|
||||||
|
|
||||||
|
echo "==== Case 3C ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 4: Make a new data directory with only an unencrypted secret key.
|
||||||
|
# Then start tor. The rest should become correct.
|
||||||
|
|
||||||
|
if [ "$CASE4" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case4"
|
||||||
|
SRC="${DATA_DIR}/orig"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint || die "Tor wouldn't start with only unencrypted secret key"
|
||||||
|
check_file "${ME}/keys/ed25519_master_id_public_key"
|
||||||
|
check_file "${ME}/keys/ed25519_master_id_signing_cert"
|
||||||
|
check_file "${ME}/keys/ed25519_master_id_signing_secret_key"
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint || die "Tor wouldn't start again after starting once with only unencrypted secret key."
|
||||||
|
|
||||||
|
echo "==== Case 4 ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 5: Make a new data directory with only an encrypted secret key.
|
||||||
|
|
||||||
|
if [ "$CASE5" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case5"
|
||||||
|
SRC="${DATA_DIR}/encrypted"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint || die "Tor wouldn't start with only encrypted secret key"
|
||||||
|
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
|
||||||
|
|
||||||
|
echo "==== Case 5 ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 6: Make a new data directory with encrypted secret key and public key
|
||||||
|
|
||||||
|
if [ "$CASE6" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case6"
|
||||||
|
SRC="${DATA_DIR}/encrypted"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint && die "Tor started with encrypted secret key and no certs" || true
|
||||||
|
check_no_file "${ME}/keys/ed25519_signing_cert"
|
||||||
|
check_no_file "${ME}/keys/ed25519_signing_secret_key"
|
||||||
|
|
||||||
|
echo "==== Case 6 ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 7: Make a new data directory with unencrypted secret key and
|
||||||
|
# certificates; missing master public.
|
||||||
|
|
||||||
|
if [ "$CASE7" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case7"
|
||||||
|
SRC="${DATA_DIR}/keygen"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
|
||||||
|
cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
|
||||||
|
cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
|
||||||
|
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint || die "Failed when starting with missing public key"
|
||||||
|
check_keys_eq ed25519_master_id_secret_key
|
||||||
|
check_keys_eq ed25519_master_id_public_key
|
||||||
|
check_keys_eq ed25519_signing_secret_key
|
||||||
|
check_keys_eq ed25519_signing_cert
|
||||||
|
|
||||||
|
echo "==== Case 7 ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 8: offline master secret key.
|
||||||
|
|
||||||
|
if [ "$CASE8" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case8"
|
||||||
|
SRC="${DATA_DIR}/keygen"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
|
||||||
|
cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
|
||||||
|
cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
|
||||||
|
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint || die "Failed when starting with offline secret key"
|
||||||
|
check_no_file "${ME}/keys/ed25519_master_id_secret_key"
|
||||||
|
check_keys_eq ed25519_master_id_public_key
|
||||||
|
check_keys_eq ed25519_signing_secret_key
|
||||||
|
check_keys_eq ed25519_signing_cert
|
||||||
|
|
||||||
|
echo "==== Case 8 ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Case 9: signing cert and secret key provided; could infer master key.
|
||||||
|
|
||||||
|
if [ "$CASE9" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case9"
|
||||||
|
SRC="${DATA_DIR}/keygen"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
|
||||||
|
cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
|
||||||
|
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint || die "Failed when starting with only signing material"
|
||||||
|
check_no_file "${ME}/keys/ed25519_master_id_secret_key"
|
||||||
|
check_keys_eq ed25519_master_id_public_key
|
||||||
|
check_keys_eq ed25519_signing_secret_key
|
||||||
|
check_keys_eq ed25519_signing_cert
|
||||||
|
|
||||||
|
echo "==== Case 9 ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Case 10: key mismatch.
|
||||||
|
|
||||||
|
if [ "$CASE10" = 1 ]; then
|
||||||
|
|
||||||
|
ME="${DATA_DIR}/case10"
|
||||||
|
SRC="${DATA_DIR}/keygen"
|
||||||
|
OTHER="${DATA_DIR}/orig"
|
||||||
|
|
||||||
|
mkdir -p "${ME}/keys"
|
||||||
|
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
|
||||||
|
cp "${OTHER}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
|
||||||
|
|
||||||
|
${TOR} --DataDirectory "${ME}" --list-fingerprint && die "Successfully started with mismatched keys!?" || true
|
||||||
|
|
||||||
|
echo "==== Case 10 ok"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Check cert-only.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user