Browse Source

hsmd: group hsm_secret encryption

Signed-off-by: Antoine Poinsot <darosior@protonmail.com>
ppa
Antoine Poinsot 4 years ago
committed by Christian Decker
parent
commit
c6bc22b0f5
  1. 22
      common/hsm_encryption.c
  2. 24
      common/hsm_encryption.h
  3. 24
      hsmd/hsmd.c
  4. 20
      tools/hsmtool.c

22
common/hsm_encryption.c

@ -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. */

24
common/hsm_encryption.h

@ -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
*/

24
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))) {
unlink_noerr("hsm_secret");
if (!encrypt_hsm_secret(encryption_key, &secretstuff.hsm_secret,
&cipher))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Writing header of encrypted secret: %s", strerror(errno));
}
if (!write_all(fd, cipher, sizeof(cipher))) {
"Encrypting hsm_secret");
if (!write_all(fd, cipher.data, ENCRYPTED_HSM_SECRET_LEN)) {
unlink_noerr("hsm_secret");
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Writing encrypted secret: %s", strerror(errno));
"Writing encrypted hsm_secret: %s", strerror(errno));
}
}

20
tools/hsmtool.c

@ -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…
Cancel
Save