mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
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:
committed by
Christian Decker
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)
|
static char *opt_set_hsm_password(struct lightningd *ld)
|
||||||
{
|
{
|
||||||
struct termios current_term, temp_term;
|
struct termios current_term, temp_term;
|
||||||
char *passwd = NULL;
|
char *passwd = NULL, *passwd_confirmation = NULL;
|
||||||
size_t passwd_size = 0;
|
size_t passwd_size = 0;
|
||||||
u8 salt[16] = "c-lightning\0\0\0\0\0";
|
u8 salt[16] = "c-lightning\0\0\0\0\0";
|
||||||
ld->encrypted_hsm = true;
|
ld->encrypted_hsm = true;
|
||||||
@@ -408,12 +408,18 @@ static char *opt_set_hsm_password(struct lightningd *ld)
|
|||||||
return "Could not disable password echoing.";
|
return "Could not disable password echoing.";
|
||||||
printf("The hsm_secret is encrypted with a password. In order to "
|
printf("The hsm_secret is encrypted with a password. In order to "
|
||||||
"decrypt it and start the node you must provide the password.\n");
|
"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
|
/* If we don't flush we might end up being buffered and we might seem
|
||||||
* to hang while we wait for the password. */
|
* to hang while we wait for the password. */
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
if (getline(&passwd, &passwd_size, stdin) < 0)
|
if (getline(&passwd, &passwd_size, stdin) < 0)
|
||||||
return "Could not read password from stdin.";
|
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')
|
if (passwd[strlen(passwd) - 1] == '\n')
|
||||||
passwd[strlen(passwd) - 1] = '\0';
|
passwd[strlen(passwd) - 1] = '\0';
|
||||||
if (tcsetattr(fileno(stdin), TCSAFLUSH, ¤t_term) != 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)
|
crypto_pwhash_ALG_ARGON2ID13) != 0)
|
||||||
return "Could not derive a key from the password.";
|
return "Could not derive a key from the password.";
|
||||||
free(passwd);
|
free(passwd);
|
||||||
|
free(passwd_confirmation);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -956,8 +956,9 @@ def test_hsm_secret_encryption(node_factory):
|
|||||||
l1.stop()
|
l1.stop()
|
||||||
l1.daemon.opts.update({"encrypted-hsm": None})
|
l1.daemon.opts.update({"encrypted-hsm": None})
|
||||||
l1.daemon.start(stdin=slave_fd, wait_for_initialized=False)
|
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"))
|
os.write(master_fd, password.encode("utf-8"))
|
||||||
l1.daemon.wait_for_log("Server started with public key")
|
l1.daemon.wait_for_log("Server started with public key")
|
||||||
id = l1.rpc.getinfo()["id"]
|
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.opts.update({"encrypted-hsm": None})
|
||||||
l1.daemon.start(stdin=slave_fd, stderr=subprocess.STDOUT,
|
l1.daemon.start(stdin=slave_fd, stderr=subprocess.STDOUT,
|
||||||
wait_for_initialized=False)
|
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"))
|
os.write(master_fd, password[2:].encode("utf-8"))
|
||||||
assert(l1.daemon.proc.wait() == 1)
|
assert(l1.daemon.proc.wait() == 1)
|
||||||
assert(l1.daemon.is_in_log("Wrong password for encrypted hsm_secret."))
|
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.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'The hsm_secret is encrypted')
|
||||||
os.write(master_fd, password.encode("utf-8"))
|
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")
|
l1.daemon.wait_for_log("Server started with public key")
|
||||||
assert id == l1.rpc.getinfo()["id"]
|
assert id == l1.rpc.getinfo()["id"]
|
||||||
|
|
||||||
@@ -1005,7 +1010,9 @@ def test_hsmtool_secret_decryption(node_factory):
|
|||||||
l1.stop()
|
l1.stop()
|
||||||
l1.daemon.opts.update({"encrypted-hsm": None})
|
l1.daemon.opts.update({"encrypted-hsm": None})
|
||||||
l1.daemon.start(stdin=slave_fd, wait_for_initialized=False)
|
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"))
|
os.write(master_fd, password.encode("utf-8"))
|
||||||
l1.daemon.wait_for_log("Server started with public key")
|
l1.daemon.wait_for_log("Server started with public key")
|
||||||
node_id = l1.rpc.getinfo()["id"]
|
node_id = l1.rpc.getinfo()["id"]
|
||||||
@@ -1038,6 +1045,8 @@ def test_hsmtool_secret_decryption(node_factory):
|
|||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
hsmtool.wait_for_log(r"Enter hsm_secret password:")
|
hsmtool.wait_for_log(r"Enter hsm_secret password:")
|
||||||
os.write(master_fd, password.encode("utf-8"))
|
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
|
assert hsmtool.proc.wait(5) == 0
|
||||||
# Now we need to pass the encrypted-hsm startup option
|
# Now we need to pass the encrypted-hsm startup option
|
||||||
l1.stop()
|
l1.stop()
|
||||||
@@ -1051,6 +1060,8 @@ def test_hsmtool_secret_decryption(node_factory):
|
|||||||
|
|
||||||
l1.daemon.wait_for_log(r'The hsm_secret is encrypted')
|
l1.daemon.wait_for_log(r'The hsm_secret is encrypted')
|
||||||
os.write(master_fd, password.encode("utf-8"))
|
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")
|
l1.daemon.wait_for_log("Server started with public key")
|
||||||
print(node_id, l1.rpc.getinfo()["id"])
|
print(node_id, l1.rpc.getinfo()["id"])
|
||||||
assert 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;
|
int fd;
|
||||||
struct secret key, hsm_secret;
|
struct secret key, hsm_secret;
|
||||||
char *passwd;
|
char *passwd, *passwd_confirmation;
|
||||||
u8 salt[16] = "c-lightning\0\0\0\0\0";
|
u8 salt[16] = "c-lightning\0\0\0\0\0";
|
||||||
crypto_secretstream_xchacha20poly1305_state crypto_state;
|
crypto_secretstream_xchacha20poly1305_state crypto_state;
|
||||||
u8 header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
|
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");
|
errx(ERROR_USAGE, "hsm_secret is already encrypted");
|
||||||
|
|
||||||
printf("Enter hsm_secret password:\n");
|
printf("Enter hsm_secret password:\n");
|
||||||
/* TODO: make the user double check the password. */
|
|
||||||
passwd = read_stdin_pass();
|
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);
|
get_hsm_secret(&hsm_secret, hsm_secret_path);
|
||||||
|
|
||||||
dir = path_dirname(NULL, 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. */
|
/* Once the encryption key derived, we don't need it anymore. */
|
||||||
if (passwd)
|
if (passwd)
|
||||||
free(passwd);
|
free(passwd);
|
||||||
|
if (passwd_confirmation)
|
||||||
|
free(passwd_confirmation);
|
||||||
|
|
||||||
/* Create a backup file, "just in case". */
|
/* Create a backup file, "just in case". */
|
||||||
rename(hsm_secret_path, backup);
|
rename(hsm_secret_path, backup);
|
||||||
|
|||||||
Reference in New Issue
Block a user