mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
hsm: return BIP32 public seed on initialization.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
fddb38126d
commit
891a915e0f
@ -107,7 +107,7 @@ check-makefile: check-lightningd-makefile
|
||||
check-lightningd-makefile:
|
||||
@for f in lightningd/*.h lightningd/*/*.h; do if ! echo $(LIGHTNINGD_HEADERS_NOGEN) $(LIGHTNINGD_HEADERS_GEN) "" | grep -q "$$f "; then echo $$f not mentioned in LIGHTNINGD_HEADERS_NOGEN or LIGHTNINGD_HEADERS_GEN >&2; exit 1; fi; done
|
||||
|
||||
lightningd/lightningd: $(LIGHTNINGD_OBJS) $(LIGHTNINGD_OLD_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_JSMN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(CCAN_OBJS) $(LIGHTNINGD_HSM_CONTROL_OBJS) $(LIGHTNINGD_HANDSHAKE_CONTROL_OBJS) $(LIGHTNINGD_GOSSIP_CONTROL_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a libsodium.a
|
||||
lightningd/lightningd: $(LIGHTNINGD_OBJS) $(LIGHTNINGD_OLD_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_JSMN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(CCAN_OBJS) $(LIGHTNINGD_HSM_CONTROL_OBJS) $(LIGHTNINGD_HANDSHAKE_CONTROL_OBJS) $(LIGHTNINGD_GOSSIP_CONTROL_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a libsodium.a libwallycore.a
|
||||
|
||||
clean: lightningd-clean
|
||||
|
||||
|
@ -37,9 +37,11 @@ $(LIGHTNINGD_HSM_OBJS) $(LIGHTNINGD_HSM_CLIENT_OBJS): $(LIGHTNINGD_HEADERS)
|
||||
|
||||
$(LIGHTNINGD_HSM_CONTROL_OBJS) : $(LIGHTNINGD_HSM_CONTROL_HEADERS)
|
||||
|
||||
$(LIGHTNINGD_HSM_OBJS): $(CORE_TX_HEADERS)
|
||||
|
||||
lightningd/hsm-all: lightningd/lightningd_hsm $(LIGHTNINGD_HSM_CLIENT_OBJS)
|
||||
|
||||
lightningd/lightningd_hsm: $(LIGHTNINGD_HSM_OBJS) $(CORE_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(CCAN_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a libsodium.a libwallycore.a
|
||||
lightningd/lightningd_hsm: $(LIGHTNINGD_HSM_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(CCAN_OBJS) $(LIBBASE58_OBJS) lightningd/utxo.o libsecp256k1.a libsodium.a libwallycore.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
lightningd/hsm/gen_hsm_client_wire.h: $(WIRE_GEN) lightningd/hsm/hsm_client_wire_csv
|
||||
|
@ -135,14 +135,25 @@ static u8 *handle_ecdh(struct client *c, const void *data)
|
||||
static u8 *init_response(struct conn_info *control)
|
||||
{
|
||||
struct pubkey node_id;
|
||||
u8 *serialized_extkey = tal_arr(control, u8, BIP32_SERIALIZED_LEN), *msg;
|
||||
|
||||
node_key(NULL, &node_id);
|
||||
return towire_hsmctl_init_response(control, &node_id);
|
||||
if (bip32_key_serialize(&secretstuff.bip32, BIP32_FLAG_KEY_PUBLIC,
|
||||
serialized_extkey, tal_len(serialized_extkey))
|
||||
!= WALLY_OK)
|
||||
status_failed(WIRE_HSMSTATUS_KEY_FAILED,
|
||||
"Can't serialize bip32 public key");
|
||||
|
||||
msg = towire_hsmctl_init_response(control, &node_id, serialized_extkey);
|
||||
tal_free(serialized_extkey);
|
||||
return msg;
|
||||
}
|
||||
|
||||
static void populate_secretstuff(void)
|
||||
{
|
||||
u8 bip32_seed[BIP32_ENTROPY_LEN_256];
|
||||
u32 salt = 0;
|
||||
struct ext_key master_extkey, child_extkey;
|
||||
|
||||
/* Fill in the BIP32 tree for bitcoin addresses. */
|
||||
do {
|
||||
@ -154,7 +165,79 @@ static void populate_secretstuff(void)
|
||||
salt++;
|
||||
} while (bip32_key_from_seed(bip32_seed, sizeof(bip32_seed),
|
||||
BIP32_VER_TEST_PRIVATE,
|
||||
0, &secretstuff.bip32) != WALLY_OK);
|
||||
0, &master_extkey) != WALLY_OK);
|
||||
|
||||
/* BIP 32:
|
||||
*
|
||||
* The default wallet layout
|
||||
*
|
||||
* An HDW is organized as several 'accounts'. Accounts are numbered,
|
||||
* the default account ("") being number 0. Clients are not required
|
||||
* to support more than one account - if not, they only use the
|
||||
* default account.
|
||||
*
|
||||
* Each account is composed of two keypair chains: an internal and an
|
||||
* external one. The external keychain is used to generate new public
|
||||
* addresses, while the internal keychain is used for all other
|
||||
* operations (change addresses, generation addresses, ..., anything
|
||||
* that doesn't need to be communicated). Clients that do not support
|
||||
* separate keychains for these should use the external one for
|
||||
* everything.
|
||||
*
|
||||
* - m/iH/0/k corresponds to the k'th keypair of the external chain of account number i of the HDW derived from master m.
|
||||
*/
|
||||
/* Hence child 0, then child 0 again to get extkey to derive from. */
|
||||
if (bip32_key_from_parent(&master_extkey, 0, BIP32_FLAG_KEY_PRIVATE,
|
||||
&child_extkey) != WALLY_OK)
|
||||
status_failed(WIRE_HSMSTATUS_KEY_FAILED,
|
||||
"Can't derive child bip32 key");
|
||||
|
||||
if (bip32_key_from_parent(&child_extkey, 0, BIP32_FLAG_KEY_PRIVATE,
|
||||
&secretstuff.bip32) != WALLY_OK)
|
||||
status_failed(WIRE_HSMSTATUS_KEY_FAILED,
|
||||
"Can't derive private bip32 key");
|
||||
}
|
||||
|
||||
static inline void bitcoin_pubkey(struct pubkey *pubkey, u32 index)
|
||||
{
|
||||
struct ext_key ext;
|
||||
|
||||
if (index >= BIP32_INITIAL_HARDENED_CHILD)
|
||||
status_failed(WIRE_HSMSTATUS_KEY_FAILED,
|
||||
"Index %u too great", index);
|
||||
|
||||
if (bip32_key_from_parent(&secretstuff.bip32, index,
|
||||
BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK)
|
||||
status_failed(WIRE_HSMSTATUS_KEY_FAILED,
|
||||
"BIP32 of %u failed", index);
|
||||
|
||||
if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey->pubkey,
|
||||
ext.pub_key, sizeof(ext.pub_key)))
|
||||
status_failed(WIRE_HSMSTATUS_KEY_FAILED,
|
||||
"Parse of BIP32 child %u pubkey failed", index);
|
||||
}
|
||||
|
||||
static inline void bitcoin_keypair(struct privkey *privkey,
|
||||
struct pubkey *pubkey,
|
||||
u32 index)
|
||||
{
|
||||
struct ext_key ext;
|
||||
|
||||
if (index >= BIP32_INITIAL_HARDENED_CHILD)
|
||||
status_failed(WIRE_HSMSTATUS_KEY_FAILED,
|
||||
"Index %u too great", index);
|
||||
|
||||
if (bip32_key_from_parent(&secretstuff.bip32, index,
|
||||
BIP32_FLAG_KEY_PRIVATE, &ext) != WALLY_OK)
|
||||
status_failed(WIRE_HSMSTATUS_KEY_FAILED,
|
||||
"BIP32 of %u failed", index);
|
||||
|
||||
/* libwally says: The private key with prefix byte 0 */
|
||||
memcpy(privkey->secret, ext.priv_key+1, 32);
|
||||
if (!secp256k1_ec_pubkey_create(secp256k1_ctx, &pubkey->pubkey,
|
||||
privkey->secret))
|
||||
status_failed(WIRE_HSMSTATUS_KEY_FAILED,
|
||||
"BIP32 pubkey %u create failed", index);
|
||||
}
|
||||
|
||||
static u8 *create_new_hsm(struct conn_info *control)
|
||||
|
@ -4,6 +4,8 @@ hsmctl_init_load,2
|
||||
|
||||
hsmctl_init_response,100
|
||||
hsmctl_init_response,0,node_id,33
|
||||
hsmctl_init_response,33,bip32_len,2
|
||||
hsmctl_init_response,35,bip32_seed,bip32_len*1,u8
|
||||
|
||||
# ECDH returns an fd.
|
||||
hsmctl_hsmfd_ecdh,3
|
||||
|
@ -3,6 +3,7 @@ hsmstatus_init_failed,0x8000
|
||||
hsmstatus_writemsg_failed,0x8001
|
||||
hsmstatus_bad_request,0x8002
|
||||
hsmstatus_fd_failed,0x8003
|
||||
hsmstatus_key_failed,0x8004
|
||||
|
||||
# Clients should not give a bad request but not the HSM's decision to crash.
|
||||
hsmstatus_client_bad_request,1
|
||||
|
@ -9,14 +9,23 @@
|
||||
#include <inttypes.h>
|
||||
#include <lightningd/hsm/gen_hsm_control_wire.h>
|
||||
#include <lightningd/hsm/gen_hsm_status_wire.h>
|
||||
#include <wally_bip32.h>
|
||||
|
||||
static void hsm_init_done(struct subdaemon *hsm, const u8 *msg,
|
||||
struct lightningd *ld)
|
||||
{
|
||||
if (!fromwire_hsmctl_init_response(msg, NULL, &ld->dstate.id))
|
||||
u8 *serialized_extkey;
|
||||
|
||||
if (!fromwire_hsmctl_init_response(hsm, msg, NULL, &ld->dstate.id,
|
||||
&serialized_extkey))
|
||||
errx(1, "HSM did not give init response");
|
||||
|
||||
log_info_struct(ld->log, "Our ID: %s", struct pubkey, &ld->dstate.id);
|
||||
ld->bip32_base = tal(ld, struct ext_key);
|
||||
if (bip32_key_unserialize(serialized_extkey, tal_len(serialized_extkey),
|
||||
ld->bip32_base) != WALLY_OK)
|
||||
errx(1, "HSM did not give unserializable BIP32 extkey");
|
||||
|
||||
io_break(ld->hsm);
|
||||
}
|
||||
|
||||
@ -57,6 +66,7 @@ static enum subdaemon_status hsm_status(struct subdaemon *hsm, const u8 *msg,
|
||||
case WIRE_HSMSTATUS_WRITEMSG_FAILED:
|
||||
case WIRE_HSMSTATUS_BAD_REQUEST:
|
||||
case WIRE_HSMSTATUS_FD_FAILED:
|
||||
case WIRE_HSMSTATUS_KEY_FAILED:
|
||||
break;
|
||||
}
|
||||
return STATUS_COMPLETE;
|
||||
|
@ -30,6 +30,9 @@ struct lightningd {
|
||||
|
||||
/* All peers we're tracking. */
|
||||
struct list_head peers;
|
||||
|
||||
/* Public base for bip32 keys. */
|
||||
struct ext_key *bip32_base;
|
||||
};
|
||||
|
||||
/* FIXME */
|
||||
|
Loading…
Reference in New Issue
Block a user