1818#include <common/hsm_secret.h>
1919#include <common/memleak.h>
2020#include <common/status.h>
21+ #include <hsmd/libhsmd.h>
2122#include <common/status_wiregen.h>
2223#include <common/subdaemon.h>
2324#include <errno.h>
3031#include <sys/stat.h>
3132#include <wally_bip39.h>
3233#include <wally_bip32.h>
34+ #include <wally_core.h>
3335#include <wire/wire_io.h>
3436
3537/*~ Each subdaemon is started with stdin connected to lightningd (for status
3941#define REQ_FD 3
4042
4143/* Temporary storage for the secret until we pass it to `hsmd_init` */
42- struct hsm_secret hsm_secret ;
44+ struct hsm_secret hsm_secret = { . secret_data = NULL , . secret_len = 0 , . mnemonic = NULL , . type = HSM_SECRET_INVALID } ;
4345
4446/*~ We keep track of clients, but there's not much to keep. */
4547struct client {
@@ -368,8 +370,12 @@ static void create_hsm(int fd, const char *passphrase)
368370 }
369371 status_debug ("HSM: Derived BIP32 seed from mnemonic" );
370372
371- /* Use first 32 bytes for hsm_secret */
372- memcpy (& hsm_secret .secret , bip32_seed , sizeof (hsm_secret .secret ));
373+ /* Store the full BIP32 seed */
374+ hsm_secret .secret_data = tal_dup_arr (tmpctx , u8 , bip32_seed , bip32_seed_len , 0 );
375+ hsm_secret .secret_len = bip32_seed_len ;
376+
377+ /* Set the type based on whether passphrase was used */
378+ hsm_secret .type = passphrase ? HSM_SECRET_MNEMONIC_WITH_PASS : HSM_SECRET_MNEMONIC_NO_PASS ;
373379
374380 /* Write the hsm_secret data to file */
375381 if (!write_all (fd , hsm_secret_data , hsm_secret_len )) {
@@ -471,8 +477,19 @@ static void load_hsm(const char *passphrase)
471477 "Failed to load hsm_secret: %s" , hsm_secret_error_str (err ));
472478 }
473479
474- /* Copy the extracted secret to our global hsm_secret */
475- memcpy (& hsm_secret , & hsms -> secret , sizeof (hsm_secret ));
480+ /* Deep copy the extracted secret to our global hsm_secret */
481+ hsm_secret = * hsms ; /* Copy the basic fields */
482+
483+ /* Deep copy the secret data if it exists */
484+ if (hsms -> secret_data ) {
485+ hsm_secret .secret_data = tal_dup_arr (NULL , u8 , hsms -> secret_data , hsms -> secret_len , 0 );
486+ hsm_secret .secret_len = hsms -> secret_len ;
487+ }
488+
489+ /* Deep copy the mnemonic if it exists */
490+ if (hsms -> mnemonic ) {
491+ hsm_secret .mnemonic = tal_strdup (NULL , hsms -> mnemonic );
492+ }
476493}
477494
478495/*~ We have a pre-init call in developer mode, to set dev flags */
@@ -551,7 +568,9 @@ static struct io_plan *init_hsm(struct io_conn *conn,
551568 hsm_passphrase = (const char * )tlvs -> hsm_passphrase ;
552569
553570 /*~ Don't swap this. */
554- sodium_mlock (hsm_secret .secret .data , sizeof (hsm_secret .secret .data ));
571+ if (hsm_secret .secret_data && hsm_secret .secret_len > 0 ) {
572+ sodium_mlock (hsm_secret .secret_data , hsm_secret .secret_len );
573+ }
555574
556575 if (!developer ) {
557576 assert (!dev_force_privkey );
@@ -571,9 +590,7 @@ static struct io_plan *init_hsm(struct io_conn *conn,
571590
572591 /* This was tallocated off NULL, and memleak complains if we don't free it */
573592 tal_free (tlvs );
574- return req_reply (conn , c , hsmd_init (hsm_secret_bytes (& hsm_secret ),
575- hsm_secret_size (& hsm_secret ),
576- hsmd_mutual_version ,
593+ return req_reply (conn , c , hsmd_init (hsm_secret .secret_data , hsm_secret .secret_len , hsmd_mutual_version ,
577594 bip32_key_version ));
578595}
579596
@@ -657,6 +674,11 @@ static struct io_plan *handle_memleak(struct io_conn *conn,
657674
658675 memleak_ptr (memtable , dev_force_privkey );
659676 memleak_ptr (memtable , dev_force_bip32_seed );
677+
678+ /* Question for Rusty/ Reviewer: Is this a suss pattern? */
679+ memleak_ptr (memtable , hsm_secret .secret_data );
680+ memleak_ptr (memtable , hsm_secret .mnemonic );
681+ memleak_ptr (memtable , get_secretstuff_bip32_seed ());
660682
661683 found_leak = dump_memleak (memtable , memleak_status_broken , NULL );
662684 reply = towire_hsmd_dev_memleak_reply (NULL , found_leak );
@@ -715,7 +737,8 @@ static struct io_plan *handle_derive_bip86_key(struct io_conn *conn,
715737 return bad_req (conn , c , msg_in );
716738
717739 /* Check if we have a mnemonic-based HSM secret */
718- if (hsm_secret_size (& hsm_secret ) != 64 ) {
740+ if (hsm_secret .type != HSM_SECRET_MNEMONIC_NO_PASS &&
741+ hsm_secret .type != HSM_SECRET_MNEMONIC_WITH_PASS ) {
719742 return bad_req_fmt (conn , c , msg_in ,
720743 "BIP86 derivation requires mnemonic-based HSM secret" );
721744 }
@@ -743,7 +766,8 @@ static struct io_plan *handle_check_bip86_pubkey(struct io_conn *conn,
743766 return bad_req (conn , c , msg_in );
744767
745768 /* Check if we have a mnemonic-based HSM secret */
746- if (hsm_secret_size (& hsm_secret ) != 64 ) {
769+ if (hsm_secret .type != HSM_SECRET_MNEMONIC_NO_PASS &&
770+ hsm_secret .type != HSM_SECRET_MNEMONIC_WITH_PASS ) {
747771 return bad_req_fmt (conn , c , msg_in ,
748772 "BIP86 derivation requires mnemonic-based HSM secret" );
749773 }
@@ -793,6 +817,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
793817 if (developer )
794818 return handle_memleak (conn , c , c -> msg_in );
795819 /* fall thru */
820+
796821 case WIRE_HSMD_DERIVE_BIP86_KEY :
797822 return handle_derive_bip86_key (conn , c , c -> msg_in );
798823 case WIRE_HSMD_CHECK_BIP86_PUBKEY :
@@ -882,8 +907,8 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
882907 case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY :
883908 case WIRE_HSMD_PREAPPROVE_INVOICE_CHECK_REPLY :
884909 case WIRE_HSMD_PREAPPROVE_KEYSEND_CHECK_REPLY :
885- case WIRE_HSMD_CHECK_PUBKEY_REPLY :
886910 case WIRE_HSMD_DERIVE_BIP86_KEY_REPLY :
911+ case WIRE_HSMD_CHECK_PUBKEY_REPLY :
887912 case WIRE_HSMD_CHECK_BIP86_PUBKEY_REPLY :
888913 case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY :
889914 case WIRE_HSMD_SIGN_HTLC_TX_MINGLE_REPLY :
0 commit comments