lightning: confirm password on hsm_secret encryption
Changelog-changed: lightningd: the `--encrypted-hsm` now asks you to confirm your password when first set Changelog-changed: hsmtool: the `encrypt` now asks you to confirm your password Signed-off-by: Antoine Poinsot <darosior@protonmail.com>
This commit is contained in:
parent
38204f9b6d
commit
56c223886c
|
@ -388,7 +388,7 @@ static char *opt_important_plugin(const char *arg, struct lightningd *ld)
|
|||
static char *opt_set_hsm_password(struct lightningd *ld)
|
||||
{
|
||||
struct termios current_term, temp_term;
|
||||
char *passwd = NULL;
|
||||
char *passwd = NULL, *passwd_confirmation = NULL;
|
||||
size_t passwd_size = 0;
|
||||
u8 salt[16] = "c-lightning\0\0\0\0\0";
|
||||
ld->encrypted_hsm = true;
|
||||
|
@ -408,12 +408,18 @@ static char *opt_set_hsm_password(struct lightningd *ld)
|
|||
return "Could not disable password echoing.";
|
||||
printf("The hsm_secret is encrypted with a password. In order to "
|
||||
"decrypt it and start the node you must provide the password.\n");
|
||||
printf("Enter hsm_secret password: ");
|
||||
printf("Enter hsm_secret password:\n");
|
||||
/* If we don't flush we might end up being buffered and we might seem
|
||||
* to hang while we wait for the password. */
|
||||
fflush(stdout);
|
||||
if (getline(&passwd, &passwd_size, stdin) < 0)
|
||||
return "Could not read password from stdin.";
|
||||
printf("Confirm hsm_secret password:\n");
|
||||
fflush(stdout);
|
||||
if (getline(&passwd_confirmation, &passwd_size, stdin) < 0)
|
||||
return "Could not read password confirmation from stdin.";
|
||||
if (!streq(passwd, passwd_confirmation))
|
||||
return "Password confirmation mismatch.";
|
||||
if (passwd[strlen(passwd) - 1] == '\n')
|
||||
passwd[strlen(passwd) - 1] = '\0';
|
||||
if (tcsetattr(fileno(stdin), TCSAFLUSH, ¤t_term) != 0)
|
||||
|
@ -434,6 +440,7 @@ static char *opt_set_hsm_password(struct lightningd *ld)
|
|||
crypto_pwhash_ALG_ARGON2ID13) != 0)
|
||||
return "Could not derive a key from the password.";
|
||||
free(passwd);
|
||||
free(passwd_confirmation);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -956,8 +956,9 @@ def test_hsm_secret_encryption(node_factory):
|
|||
l1.stop()
|
||||
l1.daemon.opts.update({"encrypted-hsm": None})
|
||||
l1.daemon.start(stdin=slave_fd, wait_for_initialized=False)
|
||||
l1.daemon.wait_for_log(r'The hsm_secret is encrypted')
|
||||
|
||||
l1.daemon.wait_for_log(r'Enter hsm_secret password')
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
l1.daemon.wait_for_log(r'Confirm hsm_secret password')
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
l1.daemon.wait_for_log("Server started with public key")
|
||||
id = l1.rpc.getinfo()["id"]
|
||||
|
@ -972,7 +973,9 @@ def test_hsm_secret_encryption(node_factory):
|
|||
l1.daemon.opts.update({"encrypted-hsm": None})
|
||||
l1.daemon.start(stdin=slave_fd, stderr=subprocess.STDOUT,
|
||||
wait_for_initialized=False)
|
||||
l1.daemon.wait_for_log(r'The hsm_secret is encrypted')
|
||||
l1.daemon.wait_for_log(r'Enter hsm_secret password')
|
||||
os.write(master_fd, password[2:].encode("utf-8"))
|
||||
l1.daemon.wait_for_log(r'Confirm hsm_secret password')
|
||||
os.write(master_fd, password[2:].encode("utf-8"))
|
||||
assert(l1.daemon.proc.wait() == 1)
|
||||
assert(l1.daemon.is_in_log("Wrong password for encrypted hsm_secret."))
|
||||
|
@ -981,6 +984,8 @@ def test_hsm_secret_encryption(node_factory):
|
|||
l1.daemon.start(stdin=slave_fd, wait_for_initialized=False)
|
||||
l1.daemon.wait_for_log(r'The hsm_secret is encrypted')
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
l1.daemon.wait_for_log(r'Confirm hsm_secret password')
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
l1.daemon.wait_for_log("Server started with public key")
|
||||
assert id == l1.rpc.getinfo()["id"]
|
||||
|
||||
|
@ -1005,7 +1010,9 @@ def test_hsmtool_secret_decryption(node_factory):
|
|||
l1.stop()
|
||||
l1.daemon.opts.update({"encrypted-hsm": None})
|
||||
l1.daemon.start(stdin=slave_fd, wait_for_initialized=False)
|
||||
l1.daemon.wait_for_log(r'The hsm_secret is encrypted')
|
||||
l1.daemon.wait_for_log(r'Enter hsm_secret password')
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
l1.daemon.wait_for_log(r'Confirm hsm_secret password')
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
l1.daemon.wait_for_log("Server started with public key")
|
||||
node_id = l1.rpc.getinfo()["id"]
|
||||
|
@ -1038,6 +1045,8 @@ def test_hsmtool_secret_decryption(node_factory):
|
|||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
hsmtool.wait_for_log(r"Enter hsm_secret password:")
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
hsmtool.wait_for_log(r"Confirm hsm_secret password:")
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
assert hsmtool.proc.wait(5) == 0
|
||||
# Now we need to pass the encrypted-hsm startup option
|
||||
l1.stop()
|
||||
|
@ -1051,6 +1060,8 @@ def test_hsmtool_secret_decryption(node_factory):
|
|||
|
||||
l1.daemon.wait_for_log(r'The hsm_secret is encrypted')
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
l1.daemon.wait_for_log(r'Confirm hsm_secret password')
|
||||
os.write(master_fd, password.encode("utf-8"))
|
||||
l1.daemon.wait_for_log("Server started with public key")
|
||||
print(node_id, l1.rpc.getinfo()["id"])
|
||||
assert node_id == l1.rpc.getinfo()["id"]
|
||||
|
|
|
@ -253,7 +253,7 @@ static int encrypt_hsm(const char *hsm_secret_path)
|
|||
{
|
||||
int fd;
|
||||
struct secret key, hsm_secret;
|
||||
char *passwd;
|
||||
char *passwd, *passwd_confirmation;
|
||||
u8 salt[16] = "c-lightning\0\0\0\0\0";
|
||||
crypto_secretstream_xchacha20poly1305_state crypto_state;
|
||||
u8 header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
|
||||
|
@ -266,8 +266,11 @@ static int encrypt_hsm(const char *hsm_secret_path)
|
|||
errx(ERROR_USAGE, "hsm_secret is already encrypted");
|
||||
|
||||
printf("Enter hsm_secret password:\n");
|
||||
/* TODO: make the user double check the password. */
|
||||
passwd = read_stdin_pass();
|
||||
printf("Confirm hsm_secret password:\n");
|
||||
passwd_confirmation = read_stdin_pass();
|
||||
if (!streq(passwd, passwd_confirmation))
|
||||
errx(ERROR_USAGE, "Passwords confirmation mismatch.");
|
||||
get_hsm_secret(&hsm_secret, hsm_secret_path);
|
||||
|
||||
dir = path_dirname(NULL, hsm_secret_path);
|
||||
|
@ -296,6 +299,8 @@ static int encrypt_hsm(const char *hsm_secret_path)
|
|||
/* Once the encryption key derived, we don't need it anymore. */
|
||||
if (passwd)
|
||||
free(passwd);
|
||||
if (passwd_confirmation)
|
||||
free(passwd_confirmation);
|
||||
|
||||
/* Create a backup file, "just in case". */
|
||||
rename(hsm_secret_path, backup);
|
||||
|
|
Loading…
Reference in New Issue