rgb-cln/hsmd/hsmd.c

1898 lines
65 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*~ Welcome to the hsm daemon: keeper of our secrets!
*
* This is a separate daemon which keeps a root secret from which all others
* are generated. It starts with one client: lightningd, which can ask for
* new sockets for other clients. Each client has a simple capability map
* which indicates what it's allowed to ask for. We're entirely driven
* by request, response.
*/
#include <bitcoin/address.h>
#include <bitcoin/privkey.h>
#include <bitcoin/pubkey.h>
#include <bitcoin/script.h>
#include <bitcoin/tx.h>
#include <ccan/array_size/array_size.h>
#include <ccan/cast/cast.h>
#include <ccan/container_of/container_of.h>
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
#include <ccan/endian/endian.h>
#include <ccan/fdpass/fdpass.h>
#include <ccan/intmap/intmap.h>
#include <ccan/io/fdpass/fdpass.h>
#include <ccan/io/io.h>
#include <ccan/noerr/noerr.h>
#include <ccan/ptrint/ptrint.h>
#include <ccan/read_write_all/read_write_all.h>
#include <ccan/take/take.h>
#include <ccan/tal/str/str.h>
#include <common/daemon_conn.h>
#include <common/derive_basepoints.h>
#include <common/funding_tx.h>
#include <common/hash_u5.h>
#include <common/key_derive.h>
#include <common/memleak.h>
#include <common/node_id.h>
#include <common/status.h>
#include <common/subdaemon.h>
#include <common/type_to_string.h>
#include <common/utils.h>
#include <common/version.h>
#include <common/withdraw_tx.h>
#include <errno.h>
#include <fcntl.h>
#include <hsmd/capabilities.h>
/*~ All gen_ files are autogenerated; in this case by tools/generate-wire.py */
#include <hsmd/gen_hsm_wire.h>
#include <inttypes.h>
#include <secp256k1_ecdh.h>
#include <sodium/randombytes.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <wally_bip32.h>
#include <wire/gen_peer_wire.h>
#include <wire/wire_io.h>
/*~ Each subdaemon is started with stdin connected to lightningd (for status
* messages), and stderr untouched (for emergency printing). File descriptors
* 3 and beyond are set up on other sockets: for hsmd, fd 3 is the request
* stream from lightningd. */
#define REQ_FD 3
/*~ Nobody will ever find it here! hsm_secret is our root secret, the bip32
* tree is derived from that, and cached here. */
static struct {
struct secret hsm_secret;
struct ext_key bip32;
} secretstuff;
/* Version codes for BIP32 extended keys in libwally-core.
* It's not suitable to add this struct into client struct,
* so set it static.*/
static struct bip32_key_version bip32_key_version;
#if DEVELOPER
/* If they specify --dev-force-privkey it ends up in here. */
static struct privkey *dev_force_privkey;
/* If they specify --dev-force-bip32-seed it ends up in here. */
static struct secret *dev_force_bip32_seed;
#endif
/*~ We keep track of clients, but there's not much to keep. */
struct client {
/* The ccan/io async io connection for this client: it closes, we die. */
struct io_conn *conn;
/*~ io_read_wire needs a pointer to store incoming messages until
* it has the complete thing; this is it. */
u8 *msg_in;
/*~ Useful for logging, but also used to derive the per-channel seed. */
struct node_id id;
/*~ This is a unique value handed to us from lightningd, used for
* per-channel seed generation (a single id may have multiple channels
* over time).
*
* It's actually zero for the initial lightningd client connection and
* the ones for gossipd and connectd, which don't have channels
* associated. */
u64 dbid;
/* What is this client allowed to ask for? */
u64 capabilities;
/* Params to apply to all transactions for this client */
const struct chainparams *chainparams;
};
/*~ We keep a map of nonzero dbid -> clients, mainly for leak detection.
* This is ccan/uintmap, which maps u64 to some (non-NULL) pointer.
* I really dislike these kinds of declaration-via-magic macro things, as
* tags can't find them without special hacks, but the payoff here is that
* the map is typesafe: the compiler won't let you put anything in but a
* struct client pointer. */
static UINTMAP(struct client *) clients;
/*~ Plus the three zero-dbid clients: master, gossipd and connnectd. */
static struct client *dbid_zero_clients[3];
static size_t num_dbid_zero_clients;
/*~ We need this deep inside bad_req_fmt, and for memleak, so we make it a
* global. */
static struct daemon_conn *status_conn;
/* This is used for various assertions and error cases. */
static bool is_lightningd(const struct client *client)
{
return client == dbid_zero_clients[0];
}
/* FIXME: This is used by debug.c. Doesn't apply to us, but lets us link. */
extern void dev_disconnect_init(int fd);
void dev_disconnect_init(int fd UNUSED) { }
/* Pre-declare this, due to mutual recursion */
static struct io_plan *handle_client(struct io_conn *conn, struct client *c);
/*~ ccan/compiler.h defines PRINTF_FMT as the gcc compiler hint so it will
* check that fmt and other trailing arguments really are the correct type.
*
* This is a convenient helper to tell lightningd we've received a bad request
* and closes the client connection. This should never happen, of course, but
* we definitely want to log if it does.
*/
static PRINTF_FMT(4,5)
struct io_plan *bad_req_fmt(struct io_conn *conn,
struct client *c,
const u8 *msg_in,
const char *fmt, ...)
{
va_list ap;
char *str;
va_start(ap, fmt);
str = tal_fmt(tmpctx, fmt, ap);
va_end(ap);
/*~ If the client was actually lightningd, it's Game Over; we actually
* fail in this case, and it will too. */
if (is_lightningd(c)) {
status_broken("%s", str);
master_badmsg(fromwire_peektype(msg_in), msg_in);
}
/*~ Nobody should give us bad requests; it's a sign something is broken */
status_broken("%s: %s", type_to_string(tmpctx, struct node_id, &c->id), str);
/*~ Note the use of NULL as the ctx arg to towire_hsmstatus_: only
* use NULL as the allocation when we're about to immediately free it
* or hand it off with take(), as here. That makes it clear we don't
* expect it to linger, and in fact our memleak detection will
* complain if it does (unlike using the deliberately-transient
* tmpctx). */
daemon_conn_send(status_conn,
take(towire_hsmstatus_client_bad_request(NULL,
&c->id,
str,
msg_in)));
/*~ The way ccan/io works is that you return the "plan" for what to do
* next (eg. io_read). io_close() is special: it means to close the
* connection. */
return io_close(conn);
}
/* Convenience wrapper for when we simply can't parse. */
static struct io_plan *bad_req(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
return bad_req_fmt(conn, c, msg_in, "could not parse request");
}
/*~ This plan simply says: read the next packet into 'c->msg_in' (parent 'c'),
* and then call handle_client with argument 'c' */
static struct io_plan *client_read_next(struct io_conn *conn, struct client *c)
{
return io_read_wire(conn, c, &c->msg_in, handle_client, c);
}
/*~ This is the destructor on our client: we may call it manually, but
* generally it's called because the io_conn associated with the client is
* closed by the other end. */
static void destroy_client(struct client *c)
{
if (!uintmap_del(&clients, c->dbid))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed to remove client dbid %"PRIu64, c->dbid);
}
static struct client *new_client(const tal_t *ctx,
const struct chainparams *chainparams,
const struct node_id *id,
u64 dbid,
const u64 capabilities,
int fd)
{
struct client *c = tal(ctx, struct client);
/*~ All-zero pubkey is used for the initial master connection */
if (id) {
c->id = *id;
if (!node_id_valid(id))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Invalid node id %s",
type_to_string(tmpctx, struct node_id,
id));
} else {
memset(&c->id, 0, sizeof(c->id));
}
c->dbid = dbid;
c->capabilities = capabilities;
c->chainparams = chainparams;
/*~ This is the core of ccan/io: the connection creation calls a
* callback which returns the initial plan to execute: in our case,
* read a message.*/
c->conn = io_new_conn(ctx, fd, client_read_next, c);
/*~ tal_steal() moves a pointer to a new parent. At this point, the
* hierarchy is:
*
* ctx -> c
* ctx -> c->conn
*
* We want to the c->conn to own 'c', so that if the io_conn closes,
* the client is freed:
*
* ctx -> c->conn -> c.
*/
tal_steal(c->conn, c);
/* We put the special zero-db HSM connections into an array, the rest
* go into the map. */
if (dbid == 0) {
assert(num_dbid_zero_clients < ARRAY_SIZE(dbid_zero_clients));
dbid_zero_clients[num_dbid_zero_clients++] = c;
} else {
struct client *old_client = uintmap_get(&clients, dbid);
/* Close conn and free any old client of this dbid. */
if (old_client)
io_close(old_client->conn);
if (!uintmap_add(&clients, dbid, c))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed inserting dbid %"PRIu64, dbid);
tal_add_destructor(c, destroy_client);
}
return c;
}
/* This is the common pattern for the tail of each handler in this file. */
static struct io_plan *req_reply(struct io_conn *conn,
struct client *c,
const u8 *msg_out TAKES)
{
/*~ Write this out, then read the next one. This works perfectly for
* a simple request/response system like this.
*
* Internally, the ccan/io subsystem gathers all the file descriptors,
* figures out which want to write and read, asks the OS which ones
* are available, and for those file descriptors, tries to do the
* reads/writes we've asked it. It handles retry in the case where a
* read or write is done partially.
*
* Since the OS does buffering internally (on my system, over 100k
* worth) writes will normally succeed immediately. However, if the
* client is slow or malicious, and doesn't read from the socket as
* fast as we're writing, eventually the socket buffer will fill up;
* we don't care, because ccan/io will wait until there's room to
* write this reply before it will read again. The client just hurts
* themselves, and there's no Denial of Service on us.
*
* If we were to queue outgoing messages ourselves, we *would* have to
* consider such scenarios; this is why our daemons generally avoid
* buffering from untrusted parties. */
return io_write_wire(conn, msg_out, client_read_next, c);
}
/*~ This returns the secret and/or public key for this node. */
static void node_key(struct privkey *node_privkey, struct pubkey *node_id)
{
u32 salt = 0;
struct privkey unused_s;
struct pubkey unused_k;
/* If caller specifies NULL, they don't want the results. */
if (node_privkey == NULL)
node_privkey = &unused_s;
else if (node_id == NULL)
node_id = &unused_k;
/*~ So, there is apparently a 1 in 2^127 chance that a random value is
* not a valid private key, so this never actually loops. */
do {
/*~ ccan/crypto/hkdf_sha256 implements RFC5869 "Hardened Key
* Derivation Functions". That means that if a derived key
* leaks somehow, the other keys are not compromised. */
hkdf_sha256(node_privkey, sizeof(*node_privkey),
&salt, sizeof(salt),
&secretstuff.hsm_secret,
sizeof(secretstuff.hsm_secret),
"nodeid", 6);
salt++;
} while (!secp256k1_ec_pubkey_create(secp256k1_ctx, &node_id->pubkey,
node_privkey->secret.data));
#if DEVELOPER
/* In DEVELOPER mode, we can override with --dev-force-privkey */
if (dev_force_privkey) {
*node_privkey = *dev_force_privkey;
if (!secp256k1_ec_pubkey_create(secp256k1_ctx, &node_id->pubkey,
node_privkey->secret.data))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Failed to derive pubkey for dev_force_privkey");
}
#endif
}
/*~ This secret is the basis for all per-channel secrets: the per-channel seeds
* will be generated by mixing in the dbid and the peer node_id. */
static void hsm_channel_secret_base(struct secret *channel_seed_base)
{
hkdf_sha256(channel_seed_base, sizeof(struct secret), NULL, 0,
&secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret),
/*~ Initially, we didn't support multiple channels per
* peer at all: a channel had to be completely forgotten
* before another could exist. That was slightly relaxed,
* but the phrase "peer seed" is wired into the seed
* generation here, so we need to keep it that way for
* existing clients, rather than using "channel seed". */
"peer seed", strlen("peer seed"));
}
/*~ This gets the seed for this particular channel. */
static void get_channel_seed(const struct node_id *peer_id, u64 dbid,
struct secret *channel_seed)
{
struct secret channel_base;
u8 input[sizeof(peer_id->k) + sizeof(dbid)];
/*~ Again, "per-peer" should be "per-channel", but Hysterical Raisins */
const char *info = "per-peer seed";
/*~ We use the DER encoding of the pubkey, because it's platform
* independent. Since the dbid is unique, however, it's completely
* unnecessary, but again, existing users can't be broken. */
/* FIXME: lnd has a nicer BIP32 method for deriving secrets which we
* should migrate to. */
hsm_channel_secret_base(&channel_base);
memcpy(input, peer_id->k, sizeof(peer_id->k));
BUILD_ASSERT(sizeof(peer_id->k) == PUBKEY_CMPR_LEN);
/*~ For all that talk about platform-independence, note that this
* field is endian-dependent! But let's face it, little-endian won.
* In related news, we don't support EBCDIC or middle-endian. */
memcpy(input + PUBKEY_CMPR_LEN, &dbid, sizeof(dbid));
hkdf_sha256(channel_seed, sizeof(*channel_seed),
input, sizeof(input),
&channel_base, sizeof(channel_base),
info, strlen(info));
}
/*~ Called at startup to derive the bip32 field. */
static void populate_secretstuff(void)
{
u8 bip32_seed[BIP32_ENTROPY_LEN_256];
u32 salt = 0;
struct ext_key master_extkey, child_extkey;
assert(bip32_key_version.bip32_pubkey_version == BIP32_VER_MAIN_PUBLIC
|| bip32_key_version.bip32_pubkey_version == BIP32_VER_TEST_PUBLIC);
assert(bip32_key_version.bip32_privkey_version == BIP32_VER_MAIN_PRIVATE
|| bip32_key_version.bip32_privkey_version == BIP32_VER_TEST_PRIVATE);
/* Fill in the BIP32 tree for bitcoin addresses. */
/* In libwally-core, the version BIP32_VER_TEST_PRIVATE is for testnet/regtest,
* and BIP32_VER_MAIN_PRIVATE is for mainnet. For litecoin, we also set it like
* bitcoin else.*/
do {
hkdf_sha256(bip32_seed, sizeof(bip32_seed),
&salt, sizeof(salt),
&secretstuff.hsm_secret,
sizeof(secretstuff.hsm_secret),
"bip32 seed", strlen("bip32 seed"));
salt++;
} while (bip32_key_from_seed(bip32_seed, sizeof(bip32_seed),
bip32_key_version.bip32_privkey_version,
0, &master_extkey) != WALLY_OK);
#if DEVELOPER
/* In DEVELOPER mode, we can override with --dev-force-bip32-seed */
if (dev_force_bip32_seed) {
if (bip32_key_from_seed(dev_force_bip32_seed->data,
sizeof(dev_force_bip32_seed->data),
bip32_key_version.bip32_privkey_version,
0, &master_extkey) != WALLY_OK)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't derive bip32 master key");
}
#endif /* DEVELOPER */
/* 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() is a helper which exits and sends lightningd
* a message about what happened. For hsmd, that's fatal to
* lightningd. */
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't derive child bip32 key");
if (bip32_key_from_parent(&child_extkey, 0, BIP32_FLAG_KEY_PRIVATE,
&secretstuff.bip32) != WALLY_OK)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Can't derive private bip32 key");
}
/*~ Get the keys for this given BIP32 index: if privkey is NULL, we
* don't fill it in. */
static void bitcoin_key(struct privkey *privkey, struct pubkey *pubkey,
u32 index)
{
struct ext_key ext;
struct privkey unused_priv;
if (privkey == NULL)
privkey = &unused_priv;
if (index >= BIP32_INITIAL_HARDENED_CHILD)
status_failed(STATUS_FAIL_MASTER_IO,
"Index %u too great", index);
/*~ This uses libwally, which doesn't dovetail directly with
* libsecp256k1 even though it, too, uses it internally. */
if (bip32_key_from_parent(&secretstuff.bip32, index,
BIP32_FLAG_KEY_PRIVATE, &ext) != WALLY_OK)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"BIP32 of %u failed", index);
/* libwally says: The private key with prefix byte 0; remove it
* for libsecp256k1. */
memcpy(privkey->secret.data, ext.priv_key+1, 32);
if (!secp256k1_ec_pubkey_create(secp256k1_ctx, &pubkey->pubkey,
privkey->secret.data))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"BIP32 pubkey %u create failed", index);
}
/*~ We store our root secret in a "hsm_secret" file (like all of c-lightning,
* we run in the user's .lightning directory). */
static void maybe_create_new_hsm(void)
{
/*~ Note that this is opened for write-only, even though the permissions
* are set to read-only. That's perfectly valid! */
int fd = open("hsm_secret", O_CREAT|O_EXCL|O_WRONLY, 0400);
if (fd < 0) {
/* If this is not the first time we've run, it will exist. */
if (errno == EEXIST)
return;
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"creating: %s", strerror(errno));
}
/*~ This is libsodium's cryptographic randomness routine: we assume
* it's doing a good job. */
randombytes_buf(&secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret));
/*~ ccan/read_write_all has a more convenient return than write() where
* we'd have to check the return value == the length we gave: write()
* can return short on normal files if we run out of disk space. */
if (!write_all(fd, &secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret))) {
/* ccan/noerr contains useful routines like this, which don't
* clobber errno, so we can use it in our error report. */
unlink_noerr("hsm_secret");
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"writing: %s", strerror(errno));
}
/*~ fsync (mostly!) ensures that the file has reached the disk. */
if (fsync(fd) != 0) {
unlink_noerr("hsm_secret");
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"fsync: %s", strerror(errno));
}
/*~ This should never fail if fsync succeeded. But paranoia good, and
* bugs exist. */
if (close(fd) != 0) {
unlink_noerr("hsm_secret");
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"closing: %s", strerror(errno));
}
/*~ We actually need to sync the *directory itself* to make sure the
* file exists! You're only allowed to open directories read-only in
* modern Unix though. */
fd = open(".", O_RDONLY);
if (fd < 0) {
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"opening: %s", strerror(errno));
}
if (fsync(fd) != 0) {
unlink_noerr("hsm_secret");
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"fsyncdir: %s", strerror(errno));
}
close(fd);
/*~ status_unusual() is good for things which are interesting and
* definitely won't spam the logs. Only status_broken() is higher;
* status_info() is lower, then status_debug() and finally
* status_io(). */
status_unusual("HSM: created new hsm_secret file");
}
/*~ We always load the HSM file, even if we just created it above. This
* both unifies the code paths, and provides a nice sanity check that the
* file contents are as they will be for future invocations. */
static void load_hsm(void)
{
int fd = open("hsm_secret", O_RDONLY);
if (fd < 0)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"opening: %s", strerror(errno));
if (!read_all(fd, &secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret)))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"reading: %s", strerror(errno));
close(fd);
populate_secretstuff();
}
/*~ This is the response to lightningd's HSM_INIT request, which is the first
* thing it sends. */
static struct io_plan *init_hsm(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct node_id node_id;
struct pubkey key;
struct privkey *privkey;
struct secret *seed;
struct secrets *secrets;
struct sha256 *shaseed;
struct bitcoin_blkid chain_hash;
/* This must be lightningd. */
assert(is_lightningd(c));
/*~ The fromwire_* routines are autogenerated, based on the message
* definitions in hsm_client_wire.csv. The format of those files is
* an extension of the simple comma-separated format output by the
* BOLT tools/extract-formats.py tool. */
if (!fromwire_hsm_init(NULL, msg_in, &bip32_key_version, &chain_hash,
&privkey, &seed, &secrets, &shaseed))
return bad_req(conn, c, msg_in);
#if DEVELOPER
dev_force_privkey = privkey;
dev_force_bip32_seed = seed;
dev_force_channel_secrets = secrets;
dev_force_channel_secrets_shaseed = shaseed;
#endif
/* Once we have read the init message we know which params the master
* will use */
c->chainparams = chainparams_by_chainhash(&chain_hash);
maybe_create_new_hsm();
load_hsm();
/*~ We tell lightning our node id and (public) bip32 seed. */
node_key(NULL, &key);
node_id_from_pubkey(&node_id, &key);
/*~ Note: marshalling a bip32 tree only marshals the public side,
* not the secrets! So we're not actually handing them out here!
*/
return req_reply(conn, c,
take(towire_hsm_init_reply(NULL, &node_id,
&secretstuff.bip32)));
}
/*~ The client has asked us to extract the shared secret from an EC Diffie
* Hellman token. This doesn't leak any information, but requires the private
* key, so the hsmd performs it. It's used to set up an encryption key for the
* connection handshaking (BOLT #8) and for the onion wrapping (BOLT #4). */
static struct io_plan *handle_ecdh(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct privkey privkey;
struct pubkey point;
struct secret ss;
if (!fromwire_hsm_ecdh_req(msg_in, &point))
return bad_req(conn, c, msg_in);
/*~ We simply use the secp256k1_ecdh function: if ss.data is invalid,
* we kill them for bad randomness (~1 in 2^127 if ss.data is random) */
node_key(&privkey, NULL);
if (secp256k1_ecdh(secp256k1_ctx, ss.data, &point.pubkey,
privkey.secret.data, NULL, NULL) != 1) {
return bad_req_fmt(conn, c, msg_in, "secp256k1_ecdh fail");
}
/*~ In the normal case, we return the shared secret, and then read
* the next msg. */
return req_reply(conn, c, take(towire_hsm_ecdh_resp(NULL, &ss)));
}
/*~ The specific routine to sign the channel_announcement message. This is
* defined in BOLT #7, and requires *two* signatures: one from this node's key
* (to prove it's from us), and one from the bitcoin key used to create the
* funding transaction (to prove we own the output). */
static struct io_plan *handle_cannouncement_sig(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
/*~ Our autogeneration code doesn't define field offsets, so we just
* copy this from the spec itself.
*
* Note that 'check-source' will actually find and check this quote
* against the spec (if available); whitespace is ignored and
* "..." means some content is skipped, but it works remarkably well to
* track spec changes. */
/* BOLT #7:
*
* - MUST compute the double-SHA256 hash `h` of the message, beginning
* at offset 256, up to the end of the message.
* - Note: the hash skips the 4 signatures but hashes the rest of the
* message, including any future fields appended to the end.
*/
/* First type bytes are the msg type */
size_t offset = 2 + 256;
struct privkey node_pkey;
secp256k1_ecdsa_signature node_sig, bitcoin_sig;
struct sha256_double hash;
u8 *reply;
u8 *ca;
struct pubkey funding_pubkey;
struct privkey funding_privkey;
struct secret channel_seed;
/*~ You'll find FIXMEs like this scattered through the code.
* Sometimes they suggest simple improvements which someone like
* yourself should go ahead an implement. Sometimes they're deceptive
* quagmires which will cause you nothing but grief. You decide! */
/*~ Christian uses TODO(cdecker) or FIXME(cdecker), but I'm sure he won't
* mind if you fix this for him! */
/* FIXME: We should cache these. */
get_channel_seed(&c->id, c->dbid, &channel_seed);
derive_funding_key(&channel_seed, &funding_pubkey, &funding_privkey);
/*~ fromwire_ routines which need to do allocation take a tal context
* as their first field; tmpctx is good here since we won't need it
* after this function. */
if (!fromwire_hsm_cannouncement_sig_req(tmpctx, msg_in, &ca))
return bad_req(conn, c, msg_in);
if (tal_count(ca) < offset)
return bad_req_fmt(conn, c, msg_in,
"bad cannounce length %zu",
tal_count(ca));
if (fromwire_peektype(ca) != WIRE_CHANNEL_ANNOUNCEMENT)
return bad_req_fmt(conn, c, msg_in,
"Invalid channel announcement");
node_key(&node_pkey, NULL);
sha256_double(&hash, ca + offset, tal_count(ca) - offset);
sign_hash(&node_pkey, &hash, &node_sig);
sign_hash(&funding_privkey, &hash, &bitcoin_sig);
reply = towire_hsm_cannouncement_sig_reply(NULL, &node_sig,
&bitcoin_sig);
return req_reply(conn, c, take(reply));
}
/*~ The specific routine to sign the channel_update message. */
static struct io_plan *handle_channel_update_sig(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
/* BOLT #7:
*
* - MUST set `signature` to the signature of the double-SHA256 of the
* entire remaining packet after `signature`, using its own
* `node_id`.
*/
/* 2 bytes msg type + 64 bytes signature */
size_t offset = 66;
struct privkey node_pkey;
struct sha256_double hash;
secp256k1_ecdsa_signature sig;
struct short_channel_id scid;
u32 timestamp, fee_base_msat, fee_proportional_mill;
struct amount_msat htlc_minimum, htlc_maximum;
u8 message_flags, channel_flags;
u16 cltv_expiry_delta;
struct bitcoin_blkid chain_hash;
u8 *cu;
if (!fromwire_hsm_cupdate_sig_req(tmpctx, msg_in, &cu))
return bad_req(conn, c, msg_in);
if (!fromwire_channel_update_option_channel_htlc_max(cu, &sig,
&chain_hash, &scid, &timestamp, &message_flags,
&channel_flags, &cltv_expiry_delta,
&htlc_minimum, &fee_base_msat,
&fee_proportional_mill, &htlc_maximum)) {
return bad_req_fmt(conn, c, msg_in, "Bad inner channel_update");
}
if (tal_count(cu) < offset)
return bad_req_fmt(conn, c, msg_in,
"inner channel_update too short");
node_key(&node_pkey, NULL);
sha256_double(&hash, cu + offset, tal_count(cu) - offset);
sign_hash(&node_pkey, &hash, &sig);
cu = towire_channel_update_option_channel_htlc_max(tmpctx, &sig, &chain_hash,
&scid, timestamp, message_flags, channel_flags,
cltv_expiry_delta, htlc_minimum,
fee_base_msat, fee_proportional_mill,
htlc_maximum);
return req_reply(conn, c, take(towire_hsm_cupdate_sig_reply(NULL, cu)));
}
/*~ This gets the basepoints for a channel; it's not private information really
* (we tell the peer this to establish a channel, as it sets up the keys used
* for each transaction).
*
* Note that this is asked by lightningd, so it tells us what channels it wants.
*/
static struct io_plan *handle_get_channel_basepoints(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct node_id peer_id;
u64 dbid;
struct secret seed;
struct basepoints basepoints;
struct pubkey funding_pubkey;
if (!fromwire_hsm_get_channel_basepoints(msg_in, &peer_id, &dbid))
return bad_req(conn, c, msg_in);
get_channel_seed(&peer_id, dbid, &seed);
derive_basepoints(&seed, &funding_pubkey, &basepoints, NULL, NULL);
return req_reply(conn, c,
take(towire_hsm_get_channel_basepoints_reply(NULL,
&basepoints,
&funding_pubkey)));
}
/*~ This is another lightningd-only interface; signing a commit transaction.
* This is dangerous, since if we sign a revoked commitment tx we'll lose
* funds, thus it's only available to lightningd.
*
*
* Oh look, another FIXME! */
/* FIXME: Ensure HSM never does this twice for same dbid! */
static struct io_plan *handle_sign_commitment_tx(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct pubkey remote_funding_pubkey, local_funding_pubkey;
struct node_id peer_id;
u64 dbid;
struct amount_sat funding;
struct secret channel_seed;
struct bitcoin_tx *tx;
struct bitcoin_signature sig;
struct secrets secrets;
const u8 *funding_wscript;
if (!fromwire_hsm_sign_commitment_tx(tmpctx, msg_in,
&peer_id, &dbid,
&tx,
&remote_funding_pubkey,
&funding))
return bad_req(conn, c, msg_in);
tx->chainparams = c->chainparams;
/* Basic sanity checks. */
if (tx->wtx->num_inputs != 1)
return bad_req_fmt(conn, c, msg_in, "tx must have 1 input");
if (tx->wtx->num_outputs == 0)
return bad_req_fmt(conn, c, msg_in, "tx must have > 0 outputs");
get_channel_seed(&peer_id, dbid, &channel_seed);
derive_basepoints(&channel_seed,
&local_funding_pubkey, NULL, &secrets, NULL);
/*~ Bitcoin signatures cover the (part of) the script they're
* executing; the rules are a bit complex in general, but for
* Segregated Witness it's simply the current script. */
funding_wscript = bitcoin_redeem_2of2(tmpctx,
&local_funding_pubkey,
&remote_funding_pubkey);
/*~ Segregated Witness also added the input amount to the signing
* algorithm; it's only part of the input implicitly (it's part of the
* output it's spending), so in our 'bitcoin_tx' structure it's a
* pointer, as we don't always know it (and zero is a valid amount, so
* NULL is better to mean 'unknown' and has the nice property that
* you'll crash if you assume it's there and you're wrong.) */
tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &funding);
sign_tx_input(tx, 0, NULL, funding_wscript,
&secrets.funding_privkey,
&local_funding_pubkey,
SIGHASH_ALL,
&sig);
return req_reply(conn, c,
take(towire_hsm_sign_commitment_tx_reply(NULL, &sig)));
}
/*~ This is used by channeld to create signatures for the remote peer's
* commitment transaction. It's functionally identical to signing our own,
* but we expect to do this repeatedly as commitment transactions are
* updated.
*
* The HSM almost certainly *should* do more checks before signing!
*/
/* FIXME: make sure it meets some criteria? */
static struct io_plan *handle_sign_remote_commitment_tx(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct pubkey remote_funding_pubkey, local_funding_pubkey;
struct amount_sat funding;
struct secret channel_seed;
struct bitcoin_tx *tx;
struct bitcoin_signature sig;
struct secrets secrets;
const u8 *funding_wscript;
if (!fromwire_hsm_sign_remote_commitment_tx(tmpctx, msg_in,
&tx,
&remote_funding_pubkey,
&funding))
bad_req(conn, c, msg_in);
tx->chainparams = c->chainparams;
/* Basic sanity checks. */
if (tx->wtx->num_inputs != 1)
return bad_req_fmt(conn, c, msg_in, "tx must have 1 input");
if (tx->wtx->num_outputs == 0)
return bad_req_fmt(conn, c, msg_in, "tx must have > 0 outputs");
get_channel_seed(&c->id, c->dbid, &channel_seed);
derive_basepoints(&channel_seed,
&local_funding_pubkey, NULL, &secrets, NULL);
funding_wscript = bitcoin_redeem_2of2(tmpctx,
&local_funding_pubkey,
&remote_funding_pubkey);
/* Need input amount for signing */
tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &funding);
sign_tx_input(tx, 0, NULL, funding_wscript,
&secrets.funding_privkey,
&local_funding_pubkey,
SIGHASH_ALL,
&sig);
return req_reply(conn, c, take(towire_hsm_sign_tx_reply(NULL, &sig)));
}
/*~ This is used by channeld to create signatures for the remote peer's
* HTLC transactions. */
static struct io_plan *handle_sign_remote_htlc_tx(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct secret channel_seed;
struct bitcoin_tx *tx;
struct bitcoin_signature sig;
struct secrets secrets;
struct basepoints basepoints;
struct pubkey remote_per_commit_point;
struct amount_sat amount;
u8 *wscript;
struct privkey htlc_privkey;
struct pubkey htlc_pubkey;
if (!fromwire_hsm_sign_remote_htlc_tx(tmpctx, msg_in,
&tx, &wscript, &amount,
&remote_per_commit_point))
return bad_req(conn, c, msg_in);
tx->chainparams = c->chainparams;
get_channel_seed(&c->id, c->dbid, &channel_seed);
derive_basepoints(&channel_seed, NULL, &basepoints, &secrets, NULL);
if (!derive_simple_privkey(&secrets.htlc_basepoint_secret,
&basepoints.htlc,
&remote_per_commit_point,
&htlc_privkey))
return bad_req_fmt(conn, c, msg_in,
"Failed deriving htlc privkey");
if (!derive_simple_key(&basepoints.htlc,
&remote_per_commit_point,
&htlc_pubkey))
return bad_req_fmt(conn, c, msg_in,
"Failed deriving htlc pubkey");
/* Need input amount for signing */
tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &amount);
sign_tx_input(tx, 0, NULL, wscript, &htlc_privkey, &htlc_pubkey,
SIGHASH_ALL, &sig);
return req_reply(conn, c, take(towire_hsm_sign_tx_reply(NULL, &sig)));
}
/*~ This covers several cases where onchaind is creating a transaction which
* sends funds to our internal wallet. */
/* FIXME: Derive output address for this client, and check it here! */
static struct io_plan *handle_sign_to_us_tx(struct io_conn *conn,
struct client *c,
const u8 *msg_in,
struct bitcoin_tx *tx,
const struct privkey *privkey,
const u8 *wscript,
struct amount_sat input_sat)
{
struct bitcoin_signature sig;
struct pubkey pubkey;
if (!pubkey_from_privkey(privkey, &pubkey))
return bad_req_fmt(conn, c, msg_in, "bad pubkey_from_privkey");
if (tx->wtx->num_inputs != 1)
return bad_req_fmt(conn, c, msg_in, "bad txinput count");
tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &input_sat);
sign_tx_input(tx, 0, NULL, wscript, privkey, &pubkey, SIGHASH_ALL, &sig);
return req_reply(conn, c, take(towire_hsm_sign_tx_reply(NULL, &sig)));
}
/*~ When we send a commitment transaction onchain (unilateral close), there's
* a delay before we can spend it. onchaind does an explicit transaction to
* transfer it to the wallet so that doesn't need to remember how to spend
* this complex transaction. */
static struct io_plan *handle_sign_delayed_payment_to_us(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
u64 commit_num;
struct amount_sat input_sat;
struct secret channel_seed, basepoint_secret;
struct pubkey basepoint;
struct bitcoin_tx *tx;
struct sha256 shaseed;
struct pubkey per_commitment_point;
struct privkey privkey;
u8 *wscript;
/*~ We don't derive the wscript ourselves, but perhaps we should? */
if (!fromwire_hsm_sign_delayed_payment_to_us(tmpctx, msg_in,
&commit_num,
&tx, &wscript,
&input_sat))
return bad_req(conn, c, msg_in);
tx->chainparams = c->chainparams;
get_channel_seed(&c->id, c->dbid, &channel_seed);
/*~ ccan/crypto/shachain how we efficiently derive 2^48 ordered
* preimages from a single seed; the twist is that as the preimages
* are revealed, you can generate the previous ones yourself, needing
* to only keep log(N) of them at any time. */
if (!derive_shaseed(&channel_seed, &shaseed))
return bad_req_fmt(conn, c, msg_in, "bad derive_shaseed");
/*~ BOLT #3 describes exactly how this is used to generate the Nth
* per-commitment point. */
if (!per_commit_point(&shaseed, &per_commitment_point, commit_num))
return bad_req_fmt(conn, c, msg_in,
"bad per_commitment_point %"PRIu64,
commit_num);
/*~ ... which is combined with the basepoint to generate then N'th key.
*/
if (!derive_delayed_payment_basepoint(&channel_seed,
&basepoint,
&basepoint_secret))
return bad_req_fmt(conn, c, msg_in, "failed deriving basepoint");
if (!derive_simple_privkey(&basepoint_secret,
&basepoint,
&per_commitment_point,
&privkey))
return bad_req_fmt(conn, c, msg_in, "failed deriving privkey");
return handle_sign_to_us_tx(conn, c, msg_in,
tx, &privkey, wscript, input_sat);
}
/*~ This is used when a commitment transaction is onchain, and has an HTLC
* output paying to us (because we have the preimage); this signs that
* transaction, which lightningd will broadcast to collect the funds. */
static struct io_plan *handle_sign_remote_htlc_to_us(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct amount_sat input_sat;
struct secret channel_seed, htlc_basepoint_secret;
struct pubkey htlc_basepoint;
struct bitcoin_tx *tx;
struct pubkey remote_per_commitment_point;
struct privkey privkey;
u8 *wscript;
if (!fromwire_hsm_sign_remote_htlc_to_us(tmpctx, msg_in,
&remote_per_commitment_point,
&tx, &wscript,
&input_sat))
return bad_req(conn, c, msg_in);
tx->chainparams = c->chainparams;
get_channel_seed(&c->id, c->dbid, &channel_seed);
if (!derive_htlc_basepoint(&channel_seed, &htlc_basepoint,
&htlc_basepoint_secret))
return bad_req_fmt(conn, c, msg_in,
"Failed derive_htlc_basepoint");
if (!derive_simple_privkey(&htlc_basepoint_secret,
&htlc_basepoint,
&remote_per_commitment_point,
&privkey))
return bad_req_fmt(conn, c, msg_in,
"Failed deriving htlc privkey");
return handle_sign_to_us_tx(conn, c, msg_in,
tx, &privkey, wscript, input_sat);
}
/*~ This is used when the remote peer's commitment transaction is revoked;
* we can use the revocation secret to spend the outputs. For simplicity,
* we do them one at a time, though. */
static struct io_plan *handle_sign_penalty_to_us(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct amount_sat input_sat;
struct secret channel_seed, revocation_secret, revocation_basepoint_secret;
struct pubkey revocation_basepoint;
struct bitcoin_tx *tx;
struct pubkey point;
struct privkey privkey;
u8 *wscript;
if (!fromwire_hsm_sign_penalty_to_us(tmpctx, msg_in,
&revocation_secret,
&tx, &wscript,
&input_sat))
return bad_req(conn, c, msg_in);
tx->chainparams = c->chainparams;
if (!pubkey_from_secret(&revocation_secret, &point))
return bad_req_fmt(conn, c, msg_in, "Failed deriving pubkey");
get_channel_seed(&c->id, c->dbid, &channel_seed);
if (!derive_revocation_basepoint(&channel_seed,
&revocation_basepoint,
&revocation_basepoint_secret))
return bad_req_fmt(conn, c, msg_in,
"Failed deriving revocation basepoint");
if (!derive_revocation_privkey(&revocation_basepoint_secret,
&revocation_secret,
&revocation_basepoint,
&point,
&privkey))
return bad_req_fmt(conn, c, msg_in,
"Failed deriving revocation privkey");
return handle_sign_to_us_tx(conn, c, msg_in,
tx, &privkey, wscript, input_sat);
}
/*~ This is used when a commitment transaction is onchain, and has an HTLC
* output paying to them, which has timed out; this signs that transaction,
* which lightningd will broadcast to collect the funds. */
static struct io_plan *handle_sign_local_htlc_tx(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
u64 commit_num;
struct amount_sat input_sat;
struct secret channel_seed, htlc_basepoint_secret;
struct sha256 shaseed;
struct pubkey per_commitment_point, htlc_basepoint;
struct bitcoin_tx *tx;
u8 *wscript;
struct bitcoin_signature sig;
struct privkey htlc_privkey;
struct pubkey htlc_pubkey;
if (!fromwire_hsm_sign_local_htlc_tx(tmpctx, msg_in,
&commit_num, &tx, &wscript,
&input_sat))
return bad_req(conn, c, msg_in);
tx->chainparams = c->chainparams;
get_channel_seed(&c->id, c->dbid, &channel_seed);
if (!derive_shaseed(&channel_seed, &shaseed))
return bad_req_fmt(conn, c, msg_in, "bad derive_shaseed");
if (!per_commit_point(&shaseed, &per_commitment_point, commit_num))
return bad_req_fmt(conn, c, msg_in,
"bad per_commitment_point %"PRIu64,
commit_num);
if (!derive_htlc_basepoint(&channel_seed,
&htlc_basepoint,
&htlc_basepoint_secret))
return bad_req_fmt(conn, c, msg_in,
"Failed deriving htlc basepoint");
if (!derive_simple_privkey(&htlc_basepoint_secret,
&htlc_basepoint,
&per_commitment_point,
&htlc_privkey))
return bad_req_fmt(conn, c, msg_in,
"Failed deriving htlc privkey");
if (!pubkey_from_privkey(&htlc_privkey, &htlc_pubkey))
return bad_req_fmt(conn, c, msg_in, "bad pubkey_from_privkey");
if (tx->wtx->num_inputs != 1)
return bad_req_fmt(conn, c, msg_in, "bad txinput count");
/* FIXME: Check that output script is correct! */
tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &input_sat);
sign_tx_input(tx, 0, NULL, wscript, &htlc_privkey, &htlc_pubkey,
SIGHASH_ALL, &sig);
return req_reply(conn, c, take(towire_hsm_sign_tx_reply(NULL, &sig)));
}
/*~ This get the Nth a per-commitment point, and for N > 2, returns the
* grandparent per-commitment secret. This pattern is because after
* negotiating commitment N-1, we send them the next per-commitment point,
* and reveal the previous per-commitment secret as a promise not to spend
* the previous commitment transaction. */
static struct io_plan *handle_get_per_commitment_point(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct secret channel_seed;
struct sha256 shaseed;
struct pubkey per_commitment_point;
u64 n;
struct secret *old_secret;
if (!fromwire_hsm_get_per_commitment_point(msg_in, &n))
return bad_req(conn, c, msg_in);
get_channel_seed(&c->id, c->dbid, &channel_seed);
if (!derive_shaseed(&channel_seed, &shaseed))
return bad_req_fmt(conn, c, msg_in, "bad derive_shaseed");
if (!per_commit_point(&shaseed, &per_commitment_point, n))
return bad_req_fmt(conn, c, msg_in,
"bad per_commit_point %"PRIu64, n);
if (n >= 2) {
old_secret = tal(tmpctx, struct secret);
if (!per_commit_secret(&shaseed, old_secret, n - 2)) {
return bad_req_fmt(conn, c, msg_in,
"Cannot derive secret %"PRIu64,
n - 2);
}
} else
old_secret = NULL;
/*~ hsm_client_wire.csv marks the secret field here optional, so it only
* gets included if the parameter is non-NULL. We violate 80 columns
* pretty badly here, but it's a recommendation not a religion. */
return req_reply(conn, c,
take(towire_hsm_get_per_commitment_point_reply(NULL,
&per_commitment_point,
old_secret)));
}
/*~ This is used when the remote peer claims to have knowledge of future
* commitment states (option_data_loss_protect in the spec) which means we've
* been restored from backup or something, and may have already revealed
* secrets. We carefully check that this is true, here. */
static struct io_plan *handle_check_future_secret(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct secret channel_seed;
struct sha256 shaseed;
u64 n;
struct secret secret, suggested;
if (!fromwire_hsm_check_future_secret(msg_in, &n, &suggested))
return bad_req(conn, c, msg_in);
get_channel_seed(&c->id, c->dbid, &channel_seed);
if (!derive_shaseed(&channel_seed, &shaseed))
return bad_req_fmt(conn, c, msg_in, "bad derive_shaseed");
if (!per_commit_secret(&shaseed, &secret, n))
return bad_req_fmt(conn, c, msg_in,
"bad commit secret #%"PRIu64, n);
/*~ Note the special secret_eq_consttime: we generate foo_eq for many
* types using ccan/structeq, but not 'struct secret' because any
* comparison risks leaking information about the secret if it is
* timing dependent. */
return req_reply(conn, c,
take(towire_hsm_check_future_secret_reply(NULL,
secret_eq_consttime(&secret, &suggested))));
}
/* This is used by closingd to sign off on a mutual close tx. */
static struct io_plan *handle_sign_mutual_close_tx(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct secret channel_seed;
struct bitcoin_tx *tx;
struct pubkey remote_funding_pubkey, local_funding_pubkey;
struct bitcoin_signature sig;
struct secrets secrets;
struct amount_sat funding;
const u8 *funding_wscript;
if (!fromwire_hsm_sign_mutual_close_tx(tmpctx, msg_in,
&tx,
&remote_funding_pubkey,
&funding))
return bad_req(conn, c, msg_in);
tx->chainparams = c->chainparams;
/* FIXME: We should know dust level, decent fee range and
* balances, and final_keyindex, and thus be able to check tx
* outputs! */
get_channel_seed(&c->id, c->dbid, &channel_seed);
derive_basepoints(&channel_seed,
&local_funding_pubkey, NULL, &secrets, NULL);
funding_wscript = bitcoin_redeem_2of2(tmpctx,
&local_funding_pubkey,
&remote_funding_pubkey);
/* Need input amount for signing */
tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &funding);
sign_tx_input(tx, 0, NULL, funding_wscript,
&secrets.funding_privkey,
&local_funding_pubkey,
SIGHASH_ALL, &sig);
return req_reply(conn, c, take(towire_hsm_sign_tx_reply(NULL, &sig)));
}
/*~ Since we process requests then service them in strict order, and because
* only lightningd can request a new client fd, we can get away with a global
* here! But because we are being tricky, I set it to an invalid value when
* not in use, and sprinkle assertions around. */
static int pending_client_fd = -1;
/*~ This is the callback from below: having sent the reply, we now send the
* fd for the client end of the new socketpair. */
static struct io_plan *send_pending_client_fd(struct io_conn *conn,
struct client *master)
{
int fd = pending_client_fd;
/* This must be the master. */
assert(is_lightningd(master));
assert(fd != -1);
/* This sanity check shouldn't be necessary, but it's cheap. */
pending_client_fd = -1;
/*~There's arcane UNIX magic to send an open file descriptor over a
* UNIX domain socket. There's no great way to autogenerate this
* though; especially for the receive side, so we always pass these
* manually immediately following the message.
*
* io_send_fd()'s third parameter is whether to close the local one
* after sending; that saves us YA callback.
*/
return io_send_fd(conn, fd, true, client_read_next, master);
}
/*~ This is used by the master to create a new client connection (which
* becomes the HSM_FD for the subdaemon after forking). */
static struct io_plan *pass_client_hsmfd(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
int fds[2];
u64 dbid, capabilities;
struct node_id id;
/* This must be lightningd itself. */
assert(is_lightningd(c));
if (!fromwire_hsm_client_hsmfd(msg_in, &id, &dbid, &capabilities))
return bad_req(conn, c, msg_in);
/* socketpair is a bi-directional pipe, which is what we want. */
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0)
status_failed(STATUS_FAIL_INTERNAL_ERROR, "creating fds: %s",
strerror(errno));
status_debug("new_client: %"PRIu64, dbid);
new_client(c, c->chainparams, &id, dbid, capabilities, fds[0]);
/*~ We stash this in a global, because we need to get both the fd and
* the client pointer to the callback. The other way would be to
* create a boutique structure and hand that, but we don't need to. */
pending_client_fd = fds[1];
return io_write_wire(conn, take(towire_hsm_client_hsmfd_reply(NULL)),
send_pending_client_fd, c);
}
/*~ For almost every wallet tx we use the BIP32 seed, but not for onchain
* unilateral closes from a peer: they (may) have an output to us using a
* public key based on the channel basepoints. It's a bit spammy to spend
* those immediately just to make the wallet simpler, and we didn't appreciate
* the problem when we designed the protocol for commitment transaction keys.
*
* So we store just enough about the channel it came from (which may be
* long-gone) to regenerate the keys here. That has the added advantage that
* the secrets themselves stay within the HSM. */
static void hsm_unilateral_close_privkey(struct privkey *dst,
struct unilateral_close_info *info)
{
struct secret channel_seed;
struct basepoints basepoints;
struct secrets secrets;
get_channel_seed(&info->peer_id, info->channel_id, &channel_seed);
derive_basepoints(&channel_seed, NULL, &basepoints, &secrets, NULL);
if (!derive_simple_privkey(&secrets.payment_basepoint_secret,
&basepoints.payment, &info->commitment_point,
dst)) {
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Deriving unilateral_close_privkey");
}
}
/* This gets the bitcoin private key needed to spend from our wallet. */
static void hsm_key_for_utxo(struct privkey *privkey, struct pubkey *pubkey,
const struct utxo *utxo)
{
if (utxo->close_info != NULL) {
/* This is a their_unilateral_close/to-us output, so
* we need to derive the secret the long way */
status_debug("Unilateral close output, deriving secrets");
hsm_unilateral_close_privkey(privkey, utxo->close_info);
pubkey_from_privkey(privkey, pubkey);
status_debug("Derived public key %s from unilateral close",
type_to_string(tmpctx, struct pubkey, pubkey));
} else {
/* Simple case: just get derive via HD-derivation */
bitcoin_key(privkey, pubkey, utxo->keyindex);
}
}
/* This completes the tx by filling in the input scripts with signatures. */
static void sign_all_inputs(struct bitcoin_tx *tx, struct utxo **utxos)
{
/*~ Deep in my mind there's a continuous battle: should arrays be
* named as singular or plural? Is consistency the sign of a weak
* mind?
*
* ZmnSCPxj answers thusly: One must make peace with the fact, that
* the array itself is singular, yet its contents are plural. Do you
* name the array, or do you name its contents? Is the array itself
* the thing and the whole of the thing, or is it its contents that
* define what it is?
*
*... I'm not sure that helps! */
assert(tx->wtx->num_inputs == tal_count(utxos));
for (size_t i = 0; i < tal_count(utxos); i++) {
struct pubkey inkey;
struct privkey inprivkey;
const struct utxo *in = utxos[i];
u8 *subscript, *wscript, *script;
struct bitcoin_signature sig;
/* Figure out keys to spend this. */
hsm_key_for_utxo(&inprivkey, &inkey, in);
/* It's either a p2wpkh or p2sh (we support that so people from
* the last bitcoin era can put funds into the wallet) */
wscript = p2wpkh_scriptcode(tmpctx, &inkey);
if (in->is_p2sh) {
/* For P2SH-wrapped Segwit, the (implied) redeemScript
* is defined in BIP141 */
subscript = bitcoin_redeem_p2sh_p2wpkh(tmpctx, &inkey);
script = bitcoin_scriptsig_p2sh_p2wpkh(tx, &inkey);
bitcoin_tx_input_set_script(tx, i, script);
} else {
/* Pure segwit uses an empty inputScript; NULL has
* tal_count() == 0, so it works great here. */
subscript = NULL;
bitcoin_tx_input_set_script(tx, i, NULL);
}
/* This is the core crypto magic. */
sign_tx_input(tx, i, subscript, wscript, &inprivkey, &inkey,
SIGHASH_ALL, &sig);
/* The witness is [sig] [key] */
bitcoin_tx_input_set_witness(
tx, i, take(bitcoin_witness_p2wpkh(tx, &sig, &inkey)));
}
}
/*~ lightningd asks us to sign the transaction to fund a channel; it feeds us
* the set of inputs and the local and remote pubkeys, and we sign it. */
static struct io_plan *handle_sign_funding_tx(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct amount_sat satoshi_out, change_out;
u32 change_keyindex;
struct pubkey local_pubkey, remote_pubkey;
struct utxo **utxos;
struct bitcoin_tx *tx;
u16 outnum;
struct pubkey *changekey;
/* FIXME: Check fee is "reasonable" */
if (!fromwire_hsm_sign_funding(tmpctx, msg_in,
&satoshi_out, &change_out,
&change_keyindex, &local_pubkey,
&remote_pubkey, &utxos))
return bad_req(conn, c, msg_in);
if (amount_sat_greater(change_out, AMOUNT_SAT(0))) {
changekey = tal(tmpctx, struct pubkey);
bitcoin_key(NULL, changekey, change_keyindex);
} else
changekey = NULL;
tx = funding_tx(tmpctx, c->chainparams, &outnum,
/*~ For simplicity, our generated code is not const
* correct. The C rules around const and
* pointer-to-pointer are a bit weird, so we use
* ccan/cast which ensures the type is correct and
* we're not casting something random */
cast_const2(const struct utxo **, utxos),
satoshi_out, &local_pubkey, &remote_pubkey,
change_out, changekey,
NULL);
sign_all_inputs(tx, utxos);
return req_reply(conn, c, take(towire_hsm_sign_funding_reply(NULL, tx)));
}
/*~ lightningd asks us to sign a withdrawal; same as above but in theory
* we can do more to check the previous case is valid. */
static struct io_plan *handle_sign_withdrawal_tx(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct amount_sat satoshi_out, change_out;
u32 change_keyindex;
struct utxo **utxos;
struct bitcoin_tx *tx;
struct pubkey changekey;
struct bitcoin_tx_output **outputs;
if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in, &satoshi_out,
&change_out, &change_keyindex,
&outputs, &utxos))
return bad_req(conn, c, msg_in);
if (!bip32_pubkey(&secretstuff.bip32, &changekey, change_keyindex))
return bad_req_fmt(conn, c, msg_in,
"Failed to get key %u", change_keyindex);
tx = withdraw_tx(tmpctx, c->chainparams,
cast_const2(const struct utxo **, utxos), outputs,
&changekey, change_out, NULL, NULL);
sign_all_inputs(tx, utxos);
return req_reply(conn, c,
take(towire_hsm_sign_withdrawal_reply(NULL, tx)));
}
/*~ Lightning invoices, defined by BOLT 11, are signed. This has been
* surprisingly controversial; it means a node needs to be online to create
* invoices. However, it seems clear to me that in a world without
* intermedaries you need proof that you have received an offer (the
* signature), as well as proof that you've paid it (the preimage). */
static struct io_plan *handle_sign_invoice(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
/*~ We make up a 'u5' type to represent BOLT11's 5-bits-per-byte
* format: it's only for human consumption, as typedefs are almost
* entirely transparent to the C compiler. */
u5 *u5bytes;
u8 *hrpu8;
char *hrp;
struct sha256 sha;
secp256k1_ecdsa_recoverable_signature rsig;
struct hash_u5 hu5;
struct privkey node_pkey;
if (!fromwire_hsm_sign_invoice(tmpctx, msg_in, &u5bytes, &hrpu8))
return bad_req(conn, c, msg_in);
/* BOLT #11:
*
* A writer... MUST set `signature` to a valid 512-bit
* secp256k1 signature of the SHA2 256-bit hash of the
* human-readable part, represented as UTF-8 bytes,
* concatenated with the data part (excluding the signature)
* with 0 bits appended to pad the data to the next byte
* boundary, with a trailing byte containing the recovery ID
* (0, 1, 2, or 3).
*/
/* FIXME: Check invoice! */
/*~ tal_dup_arr() does what you'd expect: allocate an array by copying
* another; the cast is needed because the hrp is a 'char' array, not
* a 'u8' (unsigned char) as it's the "human readable" part.
*
* The final arg of tal_dup_arr() is how many extra bytes to allocate:
* it's so often zero that I've thought about dropping the argument, but
* in cases like this (adding a NUL terminator) it's perfect. */
hrp = tal_dup_arr(tmpctx, char, (char *)hrpu8, tal_count(hrpu8), 1);
hrp[tal_count(hrpu8)] = '\0';
hash_u5_init(&hu5, hrp);
hash_u5(&hu5, u5bytes, tal_count(u5bytes));
hash_u5_done(&hu5, &sha);
node_key(&node_pkey, NULL);
/*~ By no small coincidence, this libsecp routine uses the exact
* recovery signature format mandated by BOLT 11. */
if (!secp256k1_ecdsa_sign_recoverable(secp256k1_ctx, &rsig,
(const u8 *)&sha,
node_pkey.secret.data,
NULL, NULL)) {
return bad_req_fmt(conn, c, msg_in, "Failed to sign invoice");
}
return req_reply(conn, c,
take(towire_hsm_sign_invoice_reply(NULL, &rsig)));
}
/*~ It's optional for nodes to send node_announcement, but it lets us set our
* favourite color and cool alias! Plus other minor details like how to
* connect to us. */
static struct io_plan *handle_sign_node_announcement(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
/* BOLT #7:
*
* The origin node:
*...
* - MUST set `signature` to the signature of the double-SHA256 of the
* entire remaining packet after `signature` (using the key given by
* `node_id`).
*/
/* 2 bytes msg type + 64 bytes signature */
size_t offset = 66;
struct sha256_double hash;
struct privkey node_pkey;
secp256k1_ecdsa_signature sig;
u8 *reply;
u8 *ann;
if (!fromwire_hsm_node_announcement_sig_req(tmpctx, msg_in, &ann))
return bad_req(conn, c, msg_in);
if (tal_count(ann) < offset)
return bad_req_fmt(conn, c, msg_in,
"Node announcement too short");
if (fromwire_peektype(ann) != WIRE_NODE_ANNOUNCEMENT)
return bad_req_fmt(conn, c, msg_in,
"Invalid announcement");
node_key(&node_pkey, NULL);
sha256_double(&hash, ann + offset, tal_count(ann) - offset);
sign_hash(&node_pkey, &hash, &sig);
reply = towire_hsm_node_announcement_sig_reply(NULL, &sig);
return req_reply(conn, c, take(reply));
}
#if DEVELOPER
static struct io_plan *handle_memleak(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct htable *memtable;
bool found_leak;
u8 *reply;
memtable = memleak_enter_allocations(tmpctx, msg_in, msg_in);
/* Now delete clients and anything they point to. */
memleak_remove_referenced(memtable, c);
memleak_scan_region(memtable,
dbid_zero_clients, sizeof(dbid_zero_clients));
memleak_remove_uintmap(memtable, &clients);
memleak_scan_region(memtable, status_conn, tal_bytelen(status_conn));
memleak_scan_region(memtable, dev_force_privkey, 0);
memleak_scan_region(memtable, dev_force_bip32_seed, 0);
found_leak = dump_memleak(memtable);
reply = towire_hsm_dev_memleak_reply(NULL, found_leak);
return req_reply(conn, c, take(reply));
}
#endif /* DEVELOPER */
/*~ This routine checks that a client is allowed to call the handler. */
static bool check_client_capabilities(struct client *client,
enum hsm_wire_type t)
{
/*~ Here's a useful trick: enums in C are not real types, they're
* semantic sugar sprinkled over an int, bascally (in fact, older
* versions of gcc used to convert the values ints in the parser!).
*
* But GCC will do one thing for us: if we have a switch statement
* with a controlling expression which is an enum, it will warn us
* if a declared enum value is *not* handled in the switch, eg:
* enumeration value FOOBAR not handled in switch [-Werror=switch]
*
* This only works if there's no 'default' label, which is sometimes
* hard, as we *can* have non-enum values in our enum. But the tradeoff
* is worth it so the compiler tells us everywhere we have to fix when
* we add a new enum identifier!
*/
switch (t) {
case WIRE_HSM_ECDH_REQ:
return (client->capabilities & HSM_CAP_ECDH) != 0;
case WIRE_HSM_CANNOUNCEMENT_SIG_REQ:
case WIRE_HSM_CUPDATE_SIG_REQ:
case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REQ:
return (client->capabilities & HSM_CAP_SIGN_GOSSIP) != 0;
case WIRE_HSM_SIGN_DELAYED_PAYMENT_TO_US:
case WIRE_HSM_SIGN_REMOTE_HTLC_TO_US:
case WIRE_HSM_SIGN_PENALTY_TO_US:
case WIRE_HSM_SIGN_LOCAL_HTLC_TX:
return (client->capabilities & HSM_CAP_SIGN_ONCHAIN_TX) != 0;
case WIRE_HSM_GET_PER_COMMITMENT_POINT:
case WIRE_HSM_CHECK_FUTURE_SECRET:
return (client->capabilities & HSM_CAP_COMMITMENT_POINT) != 0;
case WIRE_HSM_SIGN_REMOTE_COMMITMENT_TX:
case WIRE_HSM_SIGN_REMOTE_HTLC_TX:
return (client->capabilities & HSM_CAP_SIGN_REMOTE_TX) != 0;
case WIRE_HSM_SIGN_MUTUAL_CLOSE_TX:
return (client->capabilities & HSM_CAP_SIGN_CLOSING_TX) != 0;
case WIRE_HSM_INIT:
case WIRE_HSM_CLIENT_HSMFD:
case WIRE_HSM_SIGN_FUNDING:
case WIRE_HSM_SIGN_WITHDRAWAL:
case WIRE_HSM_SIGN_INVOICE:
case WIRE_HSM_SIGN_COMMITMENT_TX:
case WIRE_HSM_GET_CHANNEL_BASEPOINTS:
case WIRE_HSM_DEV_MEMLEAK:
return (client->capabilities & HSM_CAP_MASTER) != 0;
/*~ These are messages sent by the HSM so we should never receive them. */
/* FIXME: Since we autogenerate these, we should really generate separate
* enums for replies to avoid this kind of clutter! */
case WIRE_HSM_ECDH_RESP:
case WIRE_HSM_CANNOUNCEMENT_SIG_REPLY:
case WIRE_HSM_CUPDATE_SIG_REPLY:
case WIRE_HSM_CLIENT_HSMFD_REPLY:
case WIRE_HSM_SIGN_FUNDING_REPLY:
case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REPLY:
case WIRE_HSM_SIGN_WITHDRAWAL_REPLY:
case WIRE_HSM_SIGN_INVOICE_REPLY:
case WIRE_HSM_INIT_REPLY:
case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST:
case WIRE_HSM_SIGN_COMMITMENT_TX_REPLY:
case WIRE_HSM_SIGN_TX_REPLY:
case WIRE_HSM_GET_PER_COMMITMENT_POINT_REPLY:
case WIRE_HSM_CHECK_FUTURE_SECRET_REPLY:
case WIRE_HSM_GET_CHANNEL_BASEPOINTS_REPLY:
case WIRE_HSM_DEV_MEMLEAK_REPLY:
break;
}
return false;
}
/*~ This is the core of the HSM daemon: handling requests. */
static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
{
enum hsm_wire_type t = fromwire_peektype(c->msg_in);
status_debug("Client: Received message %d from client", t);
/* Before we do anything else, is this client allowed to do
* what he asks for? */
if (!check_client_capabilities(c, t))
return bad_req_fmt(conn, c, c->msg_in,
"does not have capability to run %d", t);
/* Now actually go and do what the client asked for */
switch (t) {
case WIRE_HSM_INIT:
return init_hsm(conn, c, c->msg_in);
case WIRE_HSM_CLIENT_HSMFD:
return pass_client_hsmfd(conn, c, c->msg_in);
case WIRE_HSM_GET_CHANNEL_BASEPOINTS:
return handle_get_channel_basepoints(conn, c, c->msg_in);
case WIRE_HSM_ECDH_REQ:
return handle_ecdh(conn, c, c->msg_in);
case WIRE_HSM_CANNOUNCEMENT_SIG_REQ:
return handle_cannouncement_sig(conn, c, c->msg_in);
case WIRE_HSM_CUPDATE_SIG_REQ:
return handle_channel_update_sig(conn, c, c->msg_in);
case WIRE_HSM_SIGN_FUNDING:
return handle_sign_funding_tx(conn, c, c->msg_in);
case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REQ:
return handle_sign_node_announcement(conn, c, c->msg_in);
case WIRE_HSM_SIGN_INVOICE:
return handle_sign_invoice(conn, c, c->msg_in);
case WIRE_HSM_SIGN_WITHDRAWAL:
return handle_sign_withdrawal_tx(conn, c, c->msg_in);
case WIRE_HSM_SIGN_COMMITMENT_TX:
return handle_sign_commitment_tx(conn, c, c->msg_in);
case WIRE_HSM_SIGN_DELAYED_PAYMENT_TO_US:
return handle_sign_delayed_payment_to_us(conn, c, c->msg_in);
case WIRE_HSM_SIGN_REMOTE_HTLC_TO_US:
return handle_sign_remote_htlc_to_us(conn, c, c->msg_in);
case WIRE_HSM_SIGN_PENALTY_TO_US:
return handle_sign_penalty_to_us(conn, c, c->msg_in);
case WIRE_HSM_SIGN_LOCAL_HTLC_TX:
return handle_sign_local_htlc_tx(conn, c, c->msg_in);
case WIRE_HSM_GET_PER_COMMITMENT_POINT:
return handle_get_per_commitment_point(conn, c, c->msg_in);
case WIRE_HSM_CHECK_FUTURE_SECRET:
return handle_check_future_secret(conn, c, c->msg_in);
case WIRE_HSM_SIGN_REMOTE_COMMITMENT_TX:
return handle_sign_remote_commitment_tx(conn, c, c->msg_in);
case WIRE_HSM_SIGN_REMOTE_HTLC_TX:
return handle_sign_remote_htlc_tx(conn, c, c->msg_in);
case WIRE_HSM_SIGN_MUTUAL_CLOSE_TX:
return handle_sign_mutual_close_tx(conn, c, c->msg_in);
#if DEVELOPER
case WIRE_HSM_DEV_MEMLEAK:
return handle_memleak(conn, c, c->msg_in);
#else
case WIRE_HSM_DEV_MEMLEAK:
#endif /* DEVELOPER */
case WIRE_HSM_ECDH_RESP:
case WIRE_HSM_CANNOUNCEMENT_SIG_REPLY:
case WIRE_HSM_CUPDATE_SIG_REPLY:
case WIRE_HSM_CLIENT_HSMFD_REPLY:
case WIRE_HSM_SIGN_FUNDING_REPLY:
case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REPLY:
case WIRE_HSM_SIGN_WITHDRAWAL_REPLY:
case WIRE_HSM_SIGN_INVOICE_REPLY:
case WIRE_HSM_INIT_REPLY:
case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST:
case WIRE_HSM_SIGN_COMMITMENT_TX_REPLY:
case WIRE_HSM_SIGN_TX_REPLY:
case WIRE_HSM_GET_PER_COMMITMENT_POINT_REPLY:
case WIRE_HSM_CHECK_FUTURE_SECRET_REPLY:
case WIRE_HSM_GET_CHANNEL_BASEPOINTS_REPLY:
case WIRE_HSM_DEV_MEMLEAK_REPLY:
break;
}
return bad_req_fmt(conn, c, c->msg_in, "Unknown request");
}
static void master_gone(struct io_conn *unused UNUSED, struct client *c UNUSED)
{
daemon_shutdown();
/* Can't tell master, it's gone. */
exit(2);
}
int main(int argc, char *argv[])
{
struct client *master;
setup_locale();
/* This sets up tmpctx, various DEVELOPER options, backtraces, etc. */
subdaemon_setup(argc, argv);
/* A trivial daemon_conn just for writing. */
status_conn = daemon_conn_new(NULL, STDIN_FILENO, NULL, NULL, NULL);
status_setup_async(status_conn);
uintmap_init(&clients);
master = new_client(NULL, NULL, NULL, 0, HSM_CAP_MASTER | HSM_CAP_SIGN_GOSSIP,
REQ_FD);
/* First client == lightningd. */
assert(is_lightningd(master));
/* When conn closes, everything is freed. */
io_set_finish(master->conn, master_gone, master);
/*~ The two NULL args are a list of timers, and the timer which expired:
* we don't have any timers. */
io_loop(NULL, NULL);
/*~ This should never be reached: io_loop only exits on io_break which
* we don't call, a timer expiry which we don't have, or all connections
* being closed, and closing the master calls master_gone. */
abort();
}
/*~ Congratulations on making it through the first of the seven dwarves!
* (And Christian wondered why I'm so fond of having separate daemons!).
*
* We continue our story in the next-more-complex daemon: connectd/connectd.c
*/