mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
hsmd: group hsm_secret encryption
Signed-off-by: Antoine Poinsot <darosior@protonmail.com>
This commit is contained in:
parent
a441485a35
commit
c6bc22b0f5
4 changed files with 56 additions and 36 deletions
|
@ -1,10 +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)
|
||||
{
|
||||
u8 salt[16] = "c-lightning\0\0\0\0\0";
|
||||
|
@ -31,6 +29,26 @@ char *hsm_secret_encryption_key(const char *pass, struct secret *key)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool encrypt_hsm_secret(const struct secret *encryption_key,
|
||||
const struct secret *hsm_secret,
|
||||
struct encrypted_hsm_secret *output)
|
||||
{
|
||||
crypto_secretstream_xchacha20poly1305_state crypto_state;
|
||||
|
||||
if (crypto_secretstream_xchacha20poly1305_init_push(&crypto_state, output->data,
|
||||
encryption_key->data) != 0)
|
||||
return false;
|
||||
if (crypto_secretstream_xchacha20poly1305_push(&crypto_state,
|
||||
output->data + HS_HEADER_LEN,
|
||||
NULL, hsm_secret->data,
|
||||
sizeof(hsm_secret->data),
|
||||
/* Additional data and tag */
|
||||
NULL, 0, 0))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void discard_key(struct secret *key TAKES)
|
||||
{
|
||||
/* sodium_munlock() also zeroes the memory. */
|
||||
|
|
|
@ -4,7 +4,20 @@
|
|||
#include <bitcoin/privkey.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <sodium.h>
|
||||
|
||||
/* Length of the encrypted hsm secret header. */
|
||||
#define HS_HEADER_LEN crypto_secretstream_xchacha20poly1305_HEADERBYTES
|
||||
/* From libsodium: "The ciphertext length is guaranteed to always be message
|
||||
* length + ABYTES" */
|
||||
#define HS_CIPHERTEXT_LEN \
|
||||
(sizeof(struct secret) + crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||
/* Total length of an encrypted hsm_secret */
|
||||
#define ENCRYPTED_HSM_SECRET_LEN (HS_HEADER_LEN + HS_CIPHERTEXT_LEN)
|
||||
|
||||
struct encrypted_hsm_secret {
|
||||
u8 data[ENCRYPTED_HSM_SECRET_LEN];
|
||||
};
|
||||
|
||||
/** Derive the hsm_secret encryption key from a passphrase.
|
||||
* @pass: the passphrase string.
|
||||
|
@ -14,6 +27,17 @@
|
|||
*/
|
||||
char *hsm_secret_encryption_key(const char *pass, struct secret *encryption_key);
|
||||
|
||||
/** Encrypt the hsm_secret using a previously derived encryption key.
|
||||
* @encryption_key: the key derived from the passphrase.
|
||||
* @hsm_secret: the plaintext hsm_secret to encrypt.
|
||||
* @output: the resulting encrypted hsm_secret.
|
||||
*
|
||||
* Return false on encryption failure.
|
||||
*/
|
||||
bool encrypt_hsm_secret(const struct secret *encryption_key,
|
||||
const struct secret *hsm_secret,
|
||||
struct encrypted_hsm_secret *output);
|
||||
|
||||
/** Unlock and zeroize the encryption key memory after use.
|
||||
* @key: the encryption key. If taken, it will be tal_free'd
|
||||
*/
|
||||
|
|
26
hsmd/hsmd.c
26
hsmd/hsmd.c
|
@ -563,28 +563,16 @@ static void bitcoin_key(struct privkey *privkey, struct pubkey *pubkey,
|
|||
*/
|
||||
static void create_encrypted_hsm(int fd, const struct secret *encryption_key)
|
||||
{
|
||||
crypto_secretstream_xchacha20poly1305_state crypto_state;
|
||||
u8 header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
|
||||
/* The cipher size is static with xchacha20poly1305 */
|
||||
u8 cipher[sizeof(struct secret) + crypto_secretstream_xchacha20poly1305_ABYTES];
|
||||
struct encrypted_hsm_secret cipher;
|
||||
|
||||
crypto_secretstream_xchacha20poly1305_init_push(&crypto_state, header,
|
||||
encryption_key->data);
|
||||
crypto_secretstream_xchacha20poly1305_push(&crypto_state, cipher,
|
||||
NULL,
|
||||
secretstuff.hsm_secret.data,
|
||||
sizeof(secretstuff.hsm_secret.data),
|
||||
/* Additional data and tag */
|
||||
NULL, 0, 0);
|
||||
if (!write_all(fd, header, sizeof(header))) {
|
||||
if (!encrypt_hsm_secret(encryption_key, &secretstuff.hsm_secret,
|
||||
&cipher))
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Encrypting hsm_secret");
|
||||
if (!write_all(fd, cipher.data, ENCRYPTED_HSM_SECRET_LEN)) {
|
||||
unlink_noerr("hsm_secret");
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Writing header of encrypted secret: %s", strerror(errno));
|
||||
}
|
||||
if (!write_all(fd, cipher, sizeof(cipher))) {
|
||||
unlink_noerr("hsm_secret");
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Writing encrypted secret: %s", strerror(errno));
|
||||
"Writing encrypted hsm_secret: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -227,11 +227,8 @@ static int encrypt_hsm(const char *hsm_secret_path)
|
|||
{
|
||||
int fd;
|
||||
struct secret key, hsm_secret;
|
||||
struct encrypted_hsm_secret encrypted_hsm_secret;
|
||||
char *passwd, *passwd_confirmation, *err;
|
||||
crypto_secretstream_xchacha20poly1305_state crypto_state;
|
||||
u8 header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
|
||||
/* The cipher size is static with xchacha20poly1305. */
|
||||
u8 cipher[sizeof(struct secret) + crypto_secretstream_xchacha20poly1305_ABYTES];
|
||||
const char *dir, *backup;
|
||||
|
||||
/* This checks the file existence, too. */
|
||||
|
@ -264,15 +261,8 @@ static int encrypt_hsm(const char *hsm_secret_path)
|
|||
err = hsm_secret_encryption_key(passwd, &key);
|
||||
if (err)
|
||||
errx(ERROR_LIBSODIUM, "%s", err);
|
||||
if (crypto_secretstream_xchacha20poly1305_init_push(&crypto_state, header,
|
||||
key.data) != 0)
|
||||
errx(ERROR_LIBSODIUM, "Could not initialize the crypto state");
|
||||
discard_key(&key);
|
||||
if (crypto_secretstream_xchacha20poly1305_push(&crypto_state, cipher,
|
||||
NULL, hsm_secret.data,
|
||||
sizeof(hsm_secret.data),
|
||||
NULL, 0, 0) != 0)
|
||||
errx(ERROR_LIBSODIUM, "Could not encrypt the seed.");
|
||||
if (!encrypt_hsm_secret(&key, &hsm_secret, &encrypted_hsm_secret))
|
||||
errx(ERROR_LIBSODIUM, "Could not encrypt the hsm_secret seed.");
|
||||
|
||||
/* Once the encryption key derived, we don't need it anymore. */
|
||||
free(passwd);
|
||||
|
@ -285,8 +275,8 @@ static int encrypt_hsm(const char *hsm_secret_path)
|
|||
errx(ERROR_HSM_FILE, "Could not open new hsm_secret");
|
||||
|
||||
/* Write the encrypted hsm_secret. */
|
||||
if (!write_all(fd, header, sizeof(header))
|
||||
|| !write_all(fd, cipher, sizeof(cipher))) {
|
||||
if (!write_all(fd, encrypted_hsm_secret.data,
|
||||
sizeof(encrypted_hsm_secret.data))) {
|
||||
unlink_noerr(hsm_secret_path);
|
||||
close(fd);
|
||||
rename(backup, hsm_secret_path);
|
||||
|
|
Loading…
Add table
Reference in a new issue