utils: add a generic mlock function with a destructor
Introduces a generic utility function to replace the repeated pattern of sodium_mlock() + tal_add_destructor()
This commit is contained in:
committed by
Rusty Russell
parent
310405761a
commit
463712f3b7
@@ -28,11 +28,6 @@
|
||||
#define PASSPHRASE_HASH_LEN 32
|
||||
#define HSM_SECRET_PLAIN_SIZE 32
|
||||
|
||||
void destroy_secret(struct secret *secret)
|
||||
{
|
||||
sodium_munlock(secret->data, sizeof(secret->data));
|
||||
}
|
||||
|
||||
/* Helper function to validate a mnemonic string */
|
||||
static bool validate_mnemonic(const char *mnemonic, enum hsm_secret_error *err)
|
||||
{
|
||||
@@ -70,9 +65,7 @@ struct secret *get_encryption_key(const tal_t *ctx, const char *passphrase)
|
||||
}
|
||||
|
||||
/* Don't swap the encryption key ! */
|
||||
if (sodium_mlock(secret->data, sizeof(secret->data)) != 0)
|
||||
return tal_free(secret);
|
||||
tal_add_destructor(secret, destroy_secret);
|
||||
mlock_tal_memory(secret);
|
||||
|
||||
/* Now derive the key. */
|
||||
if (crypto_pwhash(secret->data, sizeof(secret->data), passphrase, strlen(passphrase), salt,
|
||||
@@ -254,10 +247,6 @@ static struct hsm_secret *extract_encrypted_secret(const tal_t *ctx,
|
||||
/* Attempt decryption */
|
||||
struct secret temp_secret;
|
||||
decrypt_success = decrypt_hsm_secret(encryption_key, hsm_secret, &temp_secret);
|
||||
|
||||
/* Clear encryption key immediately after use */
|
||||
destroy_secret(encryption_key);
|
||||
|
||||
if (!decrypt_success) {
|
||||
*err = HSM_SECRET_ERR_WRONG_PASSPHRASE;
|
||||
return tal_free(hsms);
|
||||
@@ -389,11 +378,6 @@ bool encrypt_legacy_hsm_secret(const struct secret *encryption_key,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void destroy_passphrase(char *passphrase)
|
||||
{
|
||||
sodium_munlock(passphrase, tal_bytelen(passphrase));
|
||||
}
|
||||
|
||||
/* Disable terminal echo if needed */
|
||||
static bool disable_echo(struct termios *saved_term)
|
||||
{
|
||||
@@ -457,11 +441,7 @@ const char *read_stdin_pass(const tal_t *ctx, enum hsm_secret_error *err)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Memory locking is mandatory: failure means we're on an insecure system */
|
||||
if (sodium_mlock(input, tal_bytelen(input)) != 0)
|
||||
abort();
|
||||
|
||||
tal_add_destructor(input, destroy_passphrase);
|
||||
mlock_tal_memory(input);
|
||||
|
||||
if (echo_disabled)
|
||||
restore_echo(&saved_term);
|
||||
|
||||
@@ -158,12 +158,6 @@ bool derive_seed_hash(const char *mnemonic, const char *passphrase, struct sha25
|
||||
*/
|
||||
int is_legacy_hsm_secret_encrypted(const char *path);
|
||||
|
||||
/**
|
||||
* Zero and unlock a secret's memory.
|
||||
* @secret - the secret to destroy
|
||||
*/
|
||||
void destroy_secret(struct secret *secret);
|
||||
|
||||
/**
|
||||
* Convert hsm_secret_type enum to human-readable string.
|
||||
* @type - the hsm_secret_type to convert
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <common/utils.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <sodium.h>
|
||||
|
||||
const tal_t *wally_tal_ctx = NULL;
|
||||
secp256k1_context *secp256k1_ctx;
|
||||
@@ -92,6 +93,18 @@ u8 *tal_hexdata(const tal_t *ctx, const void *str, size_t len)
|
||||
return data;
|
||||
}
|
||||
|
||||
static void destroy_munlock(const tal_t *ptr)
|
||||
{
|
||||
sodium_munlock((void *)ptr, tal_bytelen(ptr));
|
||||
}
|
||||
|
||||
void mlock_tal_memory(const tal_t *ptr)
|
||||
{
|
||||
if (sodium_mlock((void *)ptr, tal_bytelen(ptr)) != 0)
|
||||
abort();
|
||||
tal_add_destructor(ptr, destroy_munlock);
|
||||
}
|
||||
|
||||
bool tal_arr_eq_(const void *a, const void *b, size_t unused)
|
||||
{
|
||||
return memeq(a, tal_bytelen(a), b, tal_bytelen(b));
|
||||
|
||||
@@ -53,6 +53,16 @@ char *tal_hex(const tal_t *ctx, const tal_t *data);
|
||||
/* Allocate and fill a buffer with the data of this hex string. */
|
||||
u8 *tal_hexdata(const tal_t *ctx, const void *str, size_t len);
|
||||
|
||||
/**
|
||||
* mlock_tal_memory - lock a tal-allocated memory with sodium_mlock.
|
||||
* @ptr - the tal-allocated memory to lock
|
||||
*
|
||||
* This is a generic function to replace the pattern of sodium_mlock + tal_add_destructor.
|
||||
*
|
||||
* Aborts on failure (memory locking is mandatory for security).
|
||||
*/
|
||||
void mlock_tal_memory(const tal_t *ptr);
|
||||
|
||||
/* Note: p is never a complex expression, otherwise this multi-evaluates! */
|
||||
#define tal_arr_expand(p, s) \
|
||||
do { \
|
||||
|
||||
@@ -455,7 +455,7 @@ static void load_hsm(const char *passphrase)
|
||||
hsm_secret->mnemonic = tal_steal(hsm_secret, hsms->mnemonic);
|
||||
|
||||
/*~ Don't swap this secret data to disk for security. */
|
||||
sodium_mlock(hsm_secret->secret_data, tal_bytelen(hsm_secret->secret_data));
|
||||
mlock_tal_memory(hsm_secret->secret_data);
|
||||
}
|
||||
|
||||
/*~ We have a pre-init call in developer mode, to set dev flags */
|
||||
|
||||
@@ -2477,7 +2477,7 @@ u8 *hsmd_init(const u8 *secret_data, size_t secret_len, const u64 hsmd_version,
|
||||
|
||||
/*~ Store the secret (32 or 64 bytes) - use NULL context for persistence */
|
||||
secretstuff.bip32_seed = notleak(tal_dup_arr(NULL, u8, secret_data, secret_len, 0));
|
||||
sodium_mlock(secretstuff.bip32_seed, tal_bytelen(secretstuff.bip32_seed));
|
||||
mlock_tal_memory(secretstuff.bip32_seed);
|
||||
|
||||
assert(bip32_key_version.bip32_pubkey_version == BIP32_VER_MAIN_PUBLIC
|
||||
|| bip32_key_version.bip32_pubkey_version == BIP32_VER_TEST_PUBLIC);
|
||||
|
||||
@@ -223,9 +223,6 @@ static void encrypt_hsm(const char *hsm_secret_path)
|
||||
if (!encrypt_legacy_hsm_secret(encryption_key, &legacy_secret, encrypted_hsm_secret))
|
||||
errx(ERROR_LIBSODIUM, "Could not encrypt the hsm_secret seed.");
|
||||
|
||||
/* Securely discard the encryption key */
|
||||
destroy_secret(encryption_key);
|
||||
|
||||
/* Create a backup file, "just in case". */
|
||||
rename(hsm_secret_path, backup);
|
||||
fd = open(hsm_secret_path, O_CREAT|O_EXCL|O_WRONLY, 0400);
|
||||
|
||||
Reference in New Issue
Block a user