Browse Source

lightningd: regroup hsm_secret password input logic

Signed-off-by: Antoine Poinsot <darosior@protonmail.com>
ppa
Antoine Poinsot 4 years ago
committed by Christian Decker
parent
commit
a441485a35
  1. 38
      common/hsm_encryption.c
  2. 7
      common/hsm_encryption.h
  3. 19
      lightningd/options.c
  4. 80
      tools/hsmtool.c

38
common/hsm_encryption.c

@ -1,6 +1,8 @@
#include <ccan/tal/str/str.h>
#include <common/hsm_encryption.h>
#include <sodium.h>
#include <sodium/utils.h>
#include <termios.h>
char *hsm_secret_encryption_key(const char *pass, struct secret *key)
@ -36,3 +38,39 @@ void discard_key(struct secret *key TAKES)
if (taken(key))
tal_free(key);
}
char *read_stdin_pass(char **reason)
{
struct termios current_term, temp_term;
char *passwd = NULL;
size_t passwd_size = 0;
/* Set a temporary term, same as current but with ECHO disabled. */
if (tcgetattr(fileno(stdin), &current_term) != 0) {
*reason = "Could not get current terminal options.";
return NULL;
}
temp_term = current_term;
temp_term.c_lflag &= ~ECHO;
if (tcsetattr(fileno(stdin), TCSAFLUSH, &temp_term) != 0) {
*reason = "Could not disable pass echoing.";
return NULL;
}
/* Read the password, do not take the newline character into account. */
if (getline(&passwd, &passwd_size, stdin) < 0) {
*reason = "Could not read pass from stdin.";
return NULL;
}
if (passwd[strlen(passwd) - 1] == '\n')
passwd[strlen(passwd) - 1] = '\0';
/* Restore the original terminal */
if (tcsetattr(fileno(stdin), TCSAFLUSH, &current_term) != 0) {
*reason = "Could not restore terminal options.";
free(passwd);
return NULL;
}
return passwd;
}

7
common/hsm_encryption.h

@ -19,4 +19,11 @@ char *hsm_secret_encryption_key(const char *pass, struct secret *encryption_key)
*/
void discard_key(struct secret *key TAKES);
/** Read hsm_secret encryption pass from stdin, disabling echoing.
* @reason: if NULL is returned, will point to the human-readable error.
*
* Caller must free the string as it does tal-reallocate getline's output.
*/
char *read_stdin_pass(char **reason);
#endif /* LIGHTNING_COMMON_HSM_ENCRYPTION_H */

19
lightningd/options.c

@ -389,8 +389,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, *passwd_confirmation = NULL, *err;
size_t passwd_size = 0;
char *passwd, *passwd_confirmation, *err;
/* Get the password from stdin, but don't echo it. */
if (tcgetattr(fileno(stdin), &current_term) != 0)
@ -405,18 +404,14 @@ static char *opt_set_hsm_password(struct lightningd *ld)
/* 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.";
passwd = read_stdin_pass(&err);
if (!passwd)
return err;
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, &current_term) != 0)
return "Could not restore terminal options.";
passwd_confirmation = read_stdin_pass(&err);
if (!passwd_confirmation)
return err;
printf("\n");
ld->config.keypass = tal(NULL, struct secret);

80
tools/hsmtool.c

@ -21,7 +21,6 @@
#include <limits.h>
#include <sodium.h>
#include <sys/stat.h>
#include <termios.h>
#include <unistd.h>
#include <wally_bip39.h>
@ -168,46 +167,21 @@ static bool hsm_secret_is_encrypted(const char *hsm_secret_path)
return st.st_size > 32;
}
/* Read a pass from stdin, disabling echoing as done in lightning/options for the
* --encrypted-hsm startup option.
* Caller must free the returned string. */
static char *read_stdin_pass(void)
{
struct termios current_term, temp_term;
char *passwd = NULL;
size_t passwd_size = 0;
if (tcgetattr(fileno(stdin), &current_term) != 0)
errx(ERROR_TERM, "Could not get current terminal options.");
temp_term = current_term;
temp_term.c_lflag &= ~ECHO;
if (tcsetattr(fileno(stdin), TCSAFLUSH, &temp_term) != 0)
errx(ERROR_TERM, "Could not disable pass echoing.");
/* 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)
errx(ERROR_TERM, "Could not read pass from stdin.");
if (passwd[strlen(passwd) - 1] == '\n')
passwd[strlen(passwd) - 1] = '\0';
if (tcsetattr(fileno(stdin), TCSAFLUSH, &current_term) != 0)
errx(ERROR_TERM, "Could not restore terminal options.");
return passwd;
}
static int decrypt_hsm(const char *hsm_secret_path)
{
int fd;
struct secret hsm_secret;
char *passwd;
char *passwd, *err;
const char *dir, *backup;
/* This checks the file existence, too. */
if (!hsm_secret_is_encrypted(hsm_secret_path))
errx(ERROR_USAGE, "hsm_secret is not encrypted");
printf("Enter hsm_secret password:\n");
passwd = read_stdin_pass();
fflush(stdout);
passwd = read_stdin_pass(&err);
if (!passwd)
errx(ERROR_TERM, "%s", err);
if (sodium_init() == -1)
errx(ERROR_LIBSODIUM,
@ -265,9 +239,15 @@ static int encrypt_hsm(const char *hsm_secret_path)
errx(ERROR_USAGE, "hsm_secret is already encrypted");
printf("Enter hsm_secret password:\n");
passwd = read_stdin_pass();
fflush(stdout);
passwd = read_stdin_pass(&err);
if (!passwd)
errx(ERROR_TERM, "%s", err);
printf("Confirm hsm_secret password:\n");
passwd_confirmation = read_stdin_pass();
fflush(stdout);
passwd_confirmation = read_stdin_pass(&err);
if (!passwd_confirmation)
errx(ERROR_TERM, "%s", err);
if (!streq(passwd, passwd_confirmation))
errx(ERROR_USAGE, "Passwords confirmation mismatch.");
get_hsm_secret(&hsm_secret, hsm_secret_path);
@ -295,10 +275,8 @@ static int encrypt_hsm(const char *hsm_secret_path)
errx(ERROR_LIBSODIUM, "Could not encrypt the seed.");
/* Once the encryption key derived, we don't need it anymore. */
if (passwd)
free(passwd);
if (passwd_confirmation)
free(passwd_confirmation);
free(passwd);
free(passwd_confirmation);
/* Create a backup file, "just in case". */
rename(hsm_secret_path, backup);
@ -335,7 +313,7 @@ static int dump_commitments_infos(struct node_id *node_id, u64 channel_id,
struct sha256 shaseed;
struct secret hsm_secret, channel_seed, per_commitment_secret;
struct pubkey per_commitment_point;
char *passwd;
char *passwd, *err;
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN);
@ -343,7 +321,10 @@ static int dump_commitments_infos(struct node_id *node_id, u64 channel_id,
/* This checks the file existence, too. */
if (hsm_secret_is_encrypted(hsm_secret_path)) {
printf("Enter hsm_secret password:\n");
passwd = read_stdin_pass();
fflush(stdout);
passwd = read_stdin_pass(&err);
if (!passwd)
errx(ERROR_TERM, "%s", err);
get_encrypted_hsm_secret(&hsm_secret, hsm_secret_path, passwd);
free(passwd);
} else
@ -388,7 +369,7 @@ static int guess_to_remote(const char *address, struct node_id *node_id,
u64 tries, char *hsm_secret_path)
{
struct secret hsm_secret, channel_seed, basepoint_secret;
char *passwd;
char *passwd, *err;
struct pubkey basepoint;
struct ripemd160 pubkeyhash;
/* We only support P2WPKH, hence 20. */
@ -410,7 +391,10 @@ static int guess_to_remote(const char *address, struct node_id *node_id,
/* This checks the file existence, too. */
if (hsm_secret_is_encrypted(hsm_secret_path)) {
printf("Enter hsm_secret password:\n");
passwd = read_stdin_pass();
fflush(stdout);
passwd = read_stdin_pass(&err);
if (!passwd)
errx(ERROR_TERM, "%s", err);
get_encrypted_hsm_secret(&hsm_secret, hsm_secret_path, passwd);
free(passwd);
} else
@ -512,14 +496,17 @@ static void read_mnemonic(char *mnemonic) {
static int generate_hsm(const char *hsm_secret_path)
{
char mnemonic[BIP39_WORDLIST_LEN];
char *passphrase;
char *passphrase, *err;
read_mnemonic(mnemonic);
printf("Warning: remember that different passphrases yield different "
"bitcoin wallets.\n");
printf("If left empty, no password is used (echo is disabled).\n");
printf("Enter your passphrase: \n");
passphrase = read_stdin_pass();
fflush(stdout);
passphrase = read_stdin_pass(&err);
if (!passphrase)
errx(ERROR_TERM, "%s", err);
if (strlen(passphrase) == 0) {
free(passphrase);
passphrase = NULL;
@ -558,7 +545,7 @@ static int dumponchaindescriptors(const char *hsm_secret_path, const char *old_p
const bool is_testnet)
{
struct secret hsm_secret;
char *passwd;
char *passwd, *err;
u8 bip32_seed[BIP32_ENTROPY_LEN_256];
u32 salt = 0;
u32 version = is_testnet ?
@ -570,7 +557,10 @@ static int dumponchaindescriptors(const char *hsm_secret_path, const char *old_p
/* This checks the file existence, too. */
if (hsm_secret_is_encrypted(hsm_secret_path)) {
printf("Enter hsm_secret password:\n");
passwd = read_stdin_pass();
fflush(stdout);
passwd = read_stdin_pass(&err);
if (!passwd)
errx(ERROR_TERM, "%s", err);
get_encrypted_hsm_secret(&hsm_secret, hsm_secret_path, passwd);
free(passwd);
} else

Loading…
Cancel
Save