Browse Source

struct secret: use everywhere.

We alternated between using a sha256 and using a privkey, but there are
numerous places where we have a random 32 bytes which are neither.

This fixes many of them (plus, struct privkey is now defined in terms of
struct secret).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 8 years ago
parent
commit
b99c5620ef
  1. 6
      bitcoin/base58.c
  2. 7
      bitcoin/privkey.h
  3. 3
      bitcoin/pubkey.c
  4. 2
      bitcoin/signature.c
  5. 2
      daemon/lightningd.h
  6. 7
      daemon/peer.c
  7. 24
      daemon/secrets.c
  8. 2
      daemon/sphinx.c
  9. 3
      daemon/wallet.c
  10. 5
      lightningd/channel/channel.c
  11. 2
      lightningd/channel/channel_wire.csv
  12. 36
      lightningd/cryptomsg.c
  13. 6
      lightningd/cryptomsg.h
  14. 6
      lightningd/derive_basepoints.c
  15. 6
      lightningd/derive_basepoints.h
  16. 2
      lightningd/dev_newhtlc.c
  17. 50
      lightningd/handshake/handshake.c
  18. 22
      lightningd/handshake/test/run-handshake.c
  19. 2
      lightningd/hsm/client.c
  20. 4
      lightningd/hsm/client.h
  21. 24
      lightningd/hsm/hsm.c
  22. 4
      lightningd/hsm/hsm_client_wire_csv
  23. 4
      lightningd/hsm/hsm_wire.csv
  24. 4
      lightningd/htlc_end.h
  25. 23
      lightningd/key_derive.c
  26. 7
      lightningd/key_derive.h
  27. 2
      lightningd/lightningd.h
  28. 2
      lightningd/pay.c
  29. 13
      lightningd/peer_control.c
  30. 22
      lightningd/sphinx.c
  31. 11
      lightningd/sphinx.h
  32. 70
      lightningd/test/run-commit_tx.c
  33. 16
      lightningd/test/run-cryptomsg.c
  34. 23
      lightningd/test/run-key_derive.c
  35. 26
      test/test_sphinx.c
  36. 1
      type_to_string.h
  37. 7
      wire/fromwire.c
  38. 7
      wire/towire.c
  39. 2
      wire/wire.h

6
bitcoin/base58.c

@ -114,7 +114,7 @@ char *key_to_base58(const tal_t *ctx, bool test_net, const struct privkey *key)
u8 version = test_net ? 239 : 128; u8 version = test_net ? 239 : 128;
size_t outlen = sizeof(out); size_t outlen = sizeof(out);
memcpy(buf, key->secret, sizeof(key->secret)); memcpy(buf, key->secret.data, sizeof(key->secret.data));
/* Mark this as a compressed key. */ /* Mark this as a compressed key. */
buf[32] = 1; buf[32] = 1;
@ -148,9 +148,9 @@ bool key_from_base58(const char *base58, size_t base58_len,
return false; return false;
/* Copy out secret. */ /* Copy out secret. */
memcpy(priv->secret, keybuf + 1, sizeof(priv->secret)); memcpy(priv->secret.data, keybuf + 1, sizeof(priv->secret.data));
if (!secp256k1_ec_seckey_verify(secp256k1_ctx, priv->secret)) if (!secp256k1_ec_seckey_verify(secp256k1_ctx, priv->secret.data))
return false; return false;
/* Get public key, too. */ /* Get public key, too. */

7
bitcoin/privkey.h

@ -3,8 +3,13 @@
#include "config.h" #include "config.h"
#include <ccan/short_types/short_types.h> #include <ccan/short_types/short_types.h>
/* General 256-bit secret, which must be private. Used in various places. */
struct secret {
u8 data[32];
};
/* This is a private key. Keep it secret. */ /* This is a private key. Keep it secret. */
struct privkey { struct privkey {
u8 secret[32]; struct secret secret;
}; };
#endif /* LIGHTNING_BITCOIN_PRIVKEY_H */ #endif /* LIGHTNING_BITCOIN_PRIVKEY_H */

3
bitcoin/pubkey.c

@ -34,7 +34,7 @@ bool pubkey_from_privkey(const struct privkey *privkey,
struct pubkey *key) struct pubkey *key)
{ {
if (!secp256k1_ec_pubkey_create(secp256k1_ctx, if (!secp256k1_ec_pubkey_create(secp256k1_ctx,
&key->pubkey, privkey->secret)) &key->pubkey, privkey->secret.data))
return false; return false;
return true; return true;
} }
@ -98,3 +98,4 @@ static char *privkey_to_hexstr(const tal_t *ctx, const struct privkey *secret)
return str; return str;
} }
REGISTER_TYPE_TO_STRING(privkey, privkey_to_hexstr); REGISTER_TYPE_TO_STRING(privkey, privkey_to_hexstr);
REGISTER_TYPE_TO_HEXSTR(secret);

2
bitcoin/signature.c

@ -83,7 +83,7 @@ void sign_hash(const struct privkey *privkey,
ok = secp256k1_ecdsa_sign(secp256k1_ctx, ok = secp256k1_ecdsa_sign(secp256k1_ctx,
s, s,
h->sha.u.u8, h->sha.u.u8,
privkey->secret, NULL, NULL); privkey->secret.data, NULL, NULL);
assert(ok); assert(ok);
} }

2
daemon/lightningd.h

@ -99,7 +99,7 @@ struct lightningd_state {
struct list_head pay_commands; struct list_head pay_commands;
/* Our private key */ /* Our private key */
struct secret *secret; struct privkey *privkey;
/* This is us. */ /* This is us. */
struct pubkey id; struct pubkey id;

7
daemon/peer.c

@ -878,7 +878,6 @@ static void their_htlc_added(struct peer *peer, struct htlc *htlc,
struct peer *only_dest) struct peer *only_dest)
{ {
struct invoice *invoice; struct invoice *invoice;
struct privkey pk;
struct onionpacket *packet; struct onionpacket *packet;
struct route_step *step = NULL; struct route_step *step = NULL;
@ -909,15 +908,13 @@ static void their_htlc_added(struct peer *peer, struct htlc *htlc,
return; return;
} }
//FIXME: dirty trick to retrieve unexported state
memcpy(&pk, peer->dstate->secret, sizeof(pk));
packet = parse_onionpacket(peer, packet = parse_onionpacket(peer,
htlc->routing, tal_count(htlc->routing)); htlc->routing, tal_count(htlc->routing));
if (packet) { if (packet) {
u8 shared_secret[32]; u8 shared_secret[32];
if (onion_shared_secret(shared_secret, packet, &pk)) if (onion_shared_secret(shared_secret, packet,
peer->dstate->privkey))
step = process_onionpacket(packet, packet, step = process_onionpacket(packet, packet,
shared_secret, shared_secret,
htlc->rhash.u.u8, htlc->rhash.u.u8,

24
daemon/secrets.c

@ -22,18 +22,13 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
struct secret {
/* Secret ID of our node; public is dstate->id. */
struct privkey privkey;
};
void privkey_sign(struct lightningd_state *dstate, const void *src, size_t len, void privkey_sign(struct lightningd_state *dstate, const void *src, size_t len,
secp256k1_ecdsa_signature *sig) secp256k1_ecdsa_signature *sig)
{ {
struct sha256_double h; struct sha256_double h;
sha256_double(&h, memcheck(src, len), len); sha256_double(&h, memcheck(src, len), len);
sign_hash(&dstate->secret->privkey, &h, sig); sign_hash(dstate->privkey, &h, sig);
} }
struct peer_secrets { struct peer_secrets {
@ -142,7 +137,8 @@ static void new_keypair(struct lightningd_state *dstate,
struct privkey *privkey, struct pubkey *pubkey) struct privkey *privkey, struct pubkey *pubkey)
{ {
do { do {
randombytes_buf(privkey->secret, sizeof(privkey->secret)); randombytes_buf(privkey->secret.data,
sizeof(privkey->secret.data));
} while (!pubkey_from_privkey(privkey, pubkey)); } while (!pubkey_from_privkey(privkey, pubkey));
} }
@ -215,7 +211,7 @@ void secrets_init(struct lightningd_state *dstate)
{ {
int fd; int fd;
dstate->secret = tal(dstate, struct secret); dstate->privkey = tal(dstate, struct privkey);
fd = open("privkey", O_RDONLY); fd = open("privkey", O_RDONLY);
if (fd < 0) { if (fd < 0) {
@ -223,14 +219,14 @@ void secrets_init(struct lightningd_state *dstate)
fatal("Failed to open privkey: %s", strerror(errno)); fatal("Failed to open privkey: %s", strerror(errno));
log_unusual(dstate->base_log, "Creating privkey file"); log_unusual(dstate->base_log, "Creating privkey file");
new_keypair(dstate, &dstate->secret->privkey, &dstate->id); new_keypair(dstate, dstate->privkey, &dstate->id);
fd = open("privkey", O_CREAT|O_EXCL|O_WRONLY, 0400); fd = open("privkey", O_CREAT|O_EXCL|O_WRONLY, 0400);
if (fd < 0) if (fd < 0)
fatal("Failed to create privkey file: %s", fatal("Failed to create privkey file: %s",
strerror(errno)); strerror(errno));
if (!write_all(fd, dstate->secret->privkey.secret, if (!write_all(fd, &dstate->privkey->secret,
sizeof(dstate->secret->privkey.secret))) { sizeof(dstate->privkey->secret))) {
unlink_noerr("privkey"); unlink_noerr("privkey");
fatal("Failed to write to privkey file: %s", fatal("Failed to write to privkey file: %s",
strerror(errno)); strerror(errno));
@ -244,11 +240,11 @@ void secrets_init(struct lightningd_state *dstate)
if (fd < 0) if (fd < 0)
fatal("Failed to reopen privkey: %s", strerror(errno)); fatal("Failed to reopen privkey: %s", strerror(errno));
} }
if (!read_all(fd, dstate->secret->privkey.secret, if (!read_all(fd, &dstate->privkey->secret,
sizeof(dstate->secret->privkey.secret))) sizeof(dstate->privkey->secret)))
fatal("Failed to read privkey: %s", strerror(errno)); fatal("Failed to read privkey: %s", strerror(errno));
close(fd); close(fd);
if (!pubkey_from_privkey(&dstate->secret->privkey, &dstate->id)) if (!pubkey_from_privkey(dstate->privkey, &dstate->id))
fatal("Invalid privkey"); fatal("Invalid privkey");
log_info_struct(dstate->base_log, "ID: %s", struct pubkey, &dstate->id); log_info_struct(dstate->base_log, "ID: %s", struct pubkey, &dstate->id);

2
daemon/sphinx.c

@ -260,7 +260,7 @@ bool onion_shared_secret(
const struct privkey *privkey) const struct privkey *privkey)
{ {
return create_shared_secret(secret, &packet->ephemeralkey, return create_shared_secret(secret, &packet->ephemeralkey,
privkey->secret); privkey->secret.data);
} }
void pubkey_hash160( void pubkey_hash160(

3
daemon/wallet.c

@ -45,7 +45,8 @@ bool restore_wallet_address(struct lightningd_state *dstate,
static void new_keypair(struct privkey *privkey, struct pubkey *pubkey) static void new_keypair(struct privkey *privkey, struct pubkey *pubkey)
{ {
do { do {
randombytes_buf(privkey->secret, sizeof(privkey->secret)); randombytes_buf(privkey->secret.data,
sizeof(privkey->secret.data));
} while (!pubkey_from_privkey(privkey, pubkey)); } while (!pubkey_from_privkey(privkey, pubkey));
} }

5
lightningd/channel/channel.c

@ -595,7 +595,8 @@ static void their_htlc_locked(const struct htlc *htlc, struct peer *peer)
u8 *msg; u8 *msg;
struct onionpacket *op; struct onionpacket *op;
struct route_step *rs; struct route_step *rs;
struct sha256 ss, bad_onion_sha; struct sha256 bad_onion_sha;
struct secret ss;
enum onion_type failcode; enum onion_type failcode;
enum channel_remove_err rerr; enum channel_remove_err rerr;
struct pubkey ephemeral; struct pubkey ephemeral;
@ -625,7 +626,7 @@ static void their_htlc_locked(const struct htlc *htlc, struct peer *peer)
goto bad_onion; goto bad_onion;
} }
rs = process_onionpacket(tmpctx, op, ss.u.u8, htlc->rhash.u.u8, rs = process_onionpacket(tmpctx, op, ss.data, htlc->rhash.u.u8,
sizeof(htlc->rhash)); sizeof(htlc->rhash));
if (!rs) { if (!rs) {
failcode = WIRE_INVALID_ONION_HMAC; failcode = WIRE_INVALID_ONION_HMAC;

2
lightningd/channel/channel_wire.csv

@ -88,7 +88,7 @@ channel_accepted_htlc,0,forward,bool
channel_accepted_htlc,0,amt_to_forward,u64 channel_accepted_htlc,0,amt_to_forward,u64
channel_accepted_htlc,0,outgoing_cltv_value,u32 channel_accepted_htlc,0,outgoing_cltv_value,u32
channel_accepted_htlc,0,next_channel,struct short_channel_id channel_accepted_htlc,0,next_channel,struct short_channel_id
channel_accepted_htlc,0,shared_secret,32 channel_accepted_htlc,0,shared_secret,struct secret
# FIXME: Add code to commit current channel state! # FIXME: Add code to commit current channel state!

Can't render this file because it has a wrong number of fields in line 2.

36
lightningd/cryptomsg.c

@ -14,9 +14,9 @@
#include <wire/wire.h> #include <wire/wire.h>
#include <wire/wire_io.h> #include <wire/wire_io.h>
static void hkdf_two_keys(struct sha256 *out1, struct sha256 *out2, static void hkdf_two_keys(struct secret *out1, struct secret *out2,
const struct sha256 *in1, const struct secret *in1,
const struct sha256 *in2) const struct secret *in2)
{ {
/* BOLT #8: /* BOLT #8:
* *
@ -26,7 +26,7 @@ static void hkdf_two_keys(struct sha256 *out1, struct sha256 *out2,
* of cryptographic randomness using the extract-and-expand * of cryptographic randomness using the extract-and-expand
* component of the `HKDF`. * component of the `HKDF`.
*/ */
struct sha256 okm[2]; struct secret okm[2];
BUILD_ASSERT(sizeof(okm) == 64); BUILD_ASSERT(sizeof(okm) == 64);
hkdf_sha256(okm, sizeof(okm), in1, sizeof(*in1), in2, sizeof(*in2), hkdf_sha256(okm, sizeof(okm), in1, sizeof(*in1), in2, sizeof(*in2),
@ -35,9 +35,9 @@ static void hkdf_two_keys(struct sha256 *out1, struct sha256 *out2,
*out2 = okm[1]; *out2 = okm[1];
} }
static void maybe_rotate_key(u64 *n, struct sha256 *k, struct sha256 *ck) static void maybe_rotate_key(u64 *n, struct secret *k, struct secret *ck)
{ {
struct sha256 new_k, new_ck; struct secret new_k, new_ck;
/* BOLT #8: /* BOLT #8:
* *
@ -113,7 +113,7 @@ u8 *cryptomsg_decrypt_body(const tal_t *ctx,
memcheck(in, inlen), memcheck(in, inlen),
inlen, inlen,
NULL, 0, NULL, 0,
npub, cs->rk.u.u8) != 0) { npub, cs->rk.data) != 0) {
/* FIXME: Report error! */ /* FIXME: Report error! */
return tal_free(decrypted); return tal_free(decrypted);
} }
@ -176,7 +176,7 @@ bool cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp)
&mlen, NULL, &mlen, NULL,
memcheck(hdr, 18), 18, memcheck(hdr, 18), 18,
NULL, 0, NULL, 0,
npub, cs->rk.u.u8) != 0) { npub, cs->rk.data) != 0) {
/* FIXME: Report error! */ /* FIXME: Report error! */
return false; return false;
} }
@ -275,7 +275,7 @@ u8 *cryptomsg_encrypt_msg(const tal_t *ctx,
sizeof(l), sizeof(l),
NULL, 0, NULL, 0,
NULL, npub, NULL, npub,
cs->sk.u.u8); cs->sk.data);
assert(ret == 0); assert(ret == 0);
assert(clen == sizeof(l) + 16); assert(clen == sizeof(l) + 16);
#ifdef SUPERVERBOSE #ifdef SUPERVERBOSE
@ -300,7 +300,7 @@ u8 *cryptomsg_encrypt_msg(const tal_t *ctx,
mlen, mlen,
NULL, 0, NULL, 0,
NULL, npub, NULL, npub,
cs->sk.u.u8); cs->sk.data);
assert(ret == 0); assert(ret == 0);
assert(clen == mlen + 16); assert(clen == mlen + 16);
#ifdef SUPERVERBOSE #ifdef SUPERVERBOSE
@ -346,18 +346,18 @@ void towire_crypto_state(u8 **ptr, const struct crypto_state *cs)
{ {
towire_u64(ptr, cs->rn); towire_u64(ptr, cs->rn);
towire_u64(ptr, cs->sn); towire_u64(ptr, cs->sn);
towire_sha256(ptr, &cs->sk); towire_secret(ptr, &cs->sk);
towire_sha256(ptr, &cs->rk); towire_secret(ptr, &cs->rk);
towire_sha256(ptr, &cs->s_ck); towire_secret(ptr, &cs->s_ck);
towire_sha256(ptr, &cs->r_ck); towire_secret(ptr, &cs->r_ck);
} }
void fromwire_crypto_state(const u8 **ptr, size_t *max, struct crypto_state *cs) void fromwire_crypto_state(const u8 **ptr, size_t *max, struct crypto_state *cs)
{ {
cs->rn = fromwire_u64(ptr, max); cs->rn = fromwire_u64(ptr, max);
cs->sn = fromwire_u64(ptr, max); cs->sn = fromwire_u64(ptr, max);
fromwire_sha256(ptr, max, &cs->sk); fromwire_secret(ptr, max, &cs->sk);
fromwire_sha256(ptr, max, &cs->rk); fromwire_secret(ptr, max, &cs->rk);
fromwire_sha256(ptr, max, &cs->s_ck); fromwire_secret(ptr, max, &cs->s_ck);
fromwire_sha256(ptr, max, &cs->r_ck); fromwire_secret(ptr, max, &cs->r_ck);
} }

6
lightningd/cryptomsg.h

@ -1,7 +1,7 @@
#ifndef LIGHTNING_LIGHTNINGD_CRYPTOMSG_H #ifndef LIGHTNING_LIGHTNINGD_CRYPTOMSG_H
#define LIGHTNING_LIGHTNINGD_CRYPTOMSG_H #define LIGHTNING_LIGHTNINGD_CRYPTOMSG_H
#include "config.h" #include "config.h"
#include <ccan/crypto/sha256/sha256.h> #include <bitcoin/privkey.h>
#include <ccan/short_types/short_types.h> #include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h> #include <ccan/tal/tal.h>
@ -12,9 +12,9 @@ struct crypto_state {
/* Received and sent nonces. */ /* Received and sent nonces. */
u64 rn, sn; u64 rn, sn;
/* Sending and receiving keys. */ /* Sending and receiving keys. */
struct sha256 sk, rk; struct secret sk, rk;
/* Chaining key for re-keying */ /* Chaining key for re-keying */
struct sha256 s_ck, r_ck; struct secret s_ck, r_ck;
}; };
struct peer_crypto_state { struct peer_crypto_state {

6
lightningd/derive_basepoints.c

@ -23,9 +23,9 @@ bool derive_basepoints(const struct privkey *seed,
"c-lightning", strlen("c-lightning")); "c-lightning", strlen("c-lightning"));
secrets->funding_privkey = keys.f; secrets->funding_privkey = keys.f;
secrets->revocation_basepoint_secret = keys.r; secrets->revocation_basepoint_secret = keys.r.secret;
secrets->payment_basepoint_secret = keys.p; secrets->payment_basepoint_secret = keys.p.secret;
secrets->delayed_payment_basepoint_secret = keys.d; secrets->delayed_payment_basepoint_secret = keys.d.secret;
if (!pubkey_from_privkey(&keys.f, funding_pubkey) if (!pubkey_from_privkey(&keys.f, funding_pubkey)
|| !pubkey_from_privkey(&keys.r, &basepoints->revocation) || !pubkey_from_privkey(&keys.r, &basepoints->revocation)

6
lightningd/derive_basepoints.h

@ -14,9 +14,9 @@ struct basepoints {
struct secrets { struct secrets {
struct privkey funding_privkey; struct privkey funding_privkey;
struct privkey revocation_basepoint_secret; struct secret revocation_basepoint_secret;
struct privkey payment_basepoint_secret; struct secret payment_basepoint_secret;
struct privkey delayed_payment_basepoint_secret; struct secret delayed_payment_basepoint_secret;
}; };
bool derive_basepoints(const struct privkey *seed, bool derive_basepoints(const struct privkey *seed,

2
lightningd/dev_newhtlc.c

@ -62,7 +62,7 @@ static void json_dev_newhtlc(struct command *cmd,
u8 *onion; u8 *onion;
struct htlc_end *hend; struct htlc_end *hend;
struct pubkey *path = tal_arrz(cmd, struct pubkey, 1); struct pubkey *path = tal_arrz(cmd, struct pubkey, 1);
struct sha256 *shared_secrets; struct secret *shared_secrets;
if (!json_get_params(buffer, params, if (!json_get_params(buffer, params,
"peerid", &peeridtok, "peerid", &peeridtok,

50
lightningd/handshake/handshake.c

@ -25,12 +25,6 @@
#define REQ_FD STDIN_FILENO #define REQ_FD STDIN_FILENO
/* Representing chacha keys and ecdh results we derive them from;
* even though it's not really an SHA */
struct secret {
struct sha256 s;
};
/* BOLT #8: /* BOLT #8:
* *
* * `generateKey()` * * `generateKey()`
@ -51,9 +45,9 @@ static struct keypair generate_key(void)
struct keypair k; struct keypair k;
do { do {
randombytes_buf(k.priv.secret, sizeof(k.priv.secret)); randombytes_buf(k.priv.secret.data, sizeof(k.priv.secret.data));
} while (!secp256k1_ec_pubkey_create(secp256k1_ctx, } while (!secp256k1_ec_pubkey_create(secp256k1_ctx,
&k.pub.pubkey, k.priv.secret)); &k.pub.pubkey, k.priv.secret.data));
return k; return k;
} }
@ -181,7 +175,7 @@ static void encrypt_ad(const struct secret *k, u64 nonce,
memcheck(plaintext, plaintext_len), memcheck(plaintext, plaintext_len),
plaintext_len, plaintext_len,
additional_data, additional_data_len, additional_data, additional_data_len,
NULL, npub, k->s.u.u8); NULL, npub, k->data);
assert(ret == 0); assert(ret == 0);
assert(clen == plaintext_len + crypto_aead_chacha20poly1305_ietf_ABYTES); assert(clen == plaintext_len + crypto_aead_chacha20poly1305_ietf_ABYTES);
} }
@ -213,7 +207,7 @@ static bool decrypt(const struct secret *k, u64 nonce,
memcheck(ciphertext, ciphertext_len), memcheck(ciphertext, ciphertext_len),
ciphertext_len, ciphertext_len,
additional_data, additional_data_len, additional_data, additional_data_len,
npub, k->s.u.u8) != 0) npub, k->data) != 0)
return false; return false;
assert(mlen == ciphertext_len - crypto_aead_chacha20poly1305_ietf_ABYTES); assert(mlen == ciphertext_len - crypto_aead_chacha20poly1305_ietf_ABYTES);
@ -337,10 +331,10 @@ static void act_one_initiator(struct handshake *h, int fd,
* * The initiator performs a `ECDH` between its newly generated * * The initiator performs a `ECDH` between its newly generated
* ephemeral key with the remote node's static public key. * ephemeral key with the remote node's static public key.
*/ */
if (!secp256k1_ecdh(secp256k1_ctx, h->ss.s.u.u8, if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data,
&their_id->pubkey, h->e.priv.secret)) &their_id->pubkey, h->e.priv.secret.data))
status_failed(WIRE_INITR_ACT1_BAD_ECDH_FOR_SS, "%s", ""); status_failed(WIRE_INITR_ACT1_BAD_ECDH_FOR_SS, "%s", "");
status_trace("# ss=0x%s", tal_hexstr(trc, &h->ss.s, sizeof(h->ss.s))); status_trace("# ss=0x%s", tal_hexstr(trc, h->ss.data, sizeof(h->ss.data)));
/* BOLT #8: /* BOLT #8:
* *
@ -442,7 +436,7 @@ static void act_one_responder(struct handshake *h, int fd, struct pubkey *re)
* * The responder performs an `ECDH` between its static public * * The responder performs an `ECDH` between its static public
* key and the initiator's ephemeral public key. * key and the initiator's ephemeral public key.
*/ */
if (!hsm_do_ecdh(&h->ss.s, re)) if (!hsm_do_ecdh(&h->ss, re))
status_failed(WIRE_RESPR_ACT1_BAD_HSM_ECDH, status_failed(WIRE_RESPR_ACT1_BAD_HSM_ECDH,
"re=%s", "re=%s",
type_to_string(trc, struct pubkey, re)); type_to_string(trc, struct pubkey, re));
@ -547,12 +541,12 @@ static void act_two_responder(struct handshake *h, int fd,
* * where `re` is the ephemeral key of the initiator which was * * where `re` is the ephemeral key of the initiator which was
* received during `ActOne`. * received during `ActOne`.
*/ */
if (!secp256k1_ecdh(secp256k1_ctx, h->ss.s.u.u8, &re->pubkey, if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, &re->pubkey,
h->e.priv.secret)) h->e.priv.secret.data))
status_failed(WIRE_RESPR_ACT2_BAD_ECDH_FOR_SS, "re=%s e.priv=%s", status_failed(WIRE_RESPR_ACT2_BAD_ECDH_FOR_SS, "re=%s e.priv=%s",
type_to_string(trc, struct pubkey, re), type_to_string(trc, struct pubkey, re),
tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv))); tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv)));
status_trace("# ss=0x%s", tal_hexstr(trc, &h->ss.s, sizeof(h->ss.s))); status_trace("# ss=0x%s", tal_hexstr(trc, &h->ss, sizeof(h->ss)));
/* BOLT #8: /* BOLT #8:
* *
@ -652,8 +646,8 @@ static void act_two_initiator(struct handshake *h, int fd, struct pubkey *re)
* *
* * `ss = ECDH(re, e.priv)` * * `ss = ECDH(re, e.priv)`
*/ */
if (!secp256k1_ecdh(secp256k1_ctx, h->ss.s.u.u8, &re->pubkey, if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, &re->pubkey,
h->e.priv.secret)) h->e.priv.secret.data))
status_failed(WIRE_INITR_ACT2_BAD_ECDH_FOR_SS, "re=%s e.priv=%s", status_failed(WIRE_INITR_ACT2_BAD_ECDH_FOR_SS, "re=%s e.priv=%s",
type_to_string(trc, struct pubkey, re), type_to_string(trc, struct pubkey, re),
tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv))); tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv)));
@ -757,7 +751,7 @@ static void act_three_initiator(struct handshake *h, int fd,
* * where `re` is the ephemeral public key of the responder. * * where `re` is the ephemeral public key of the responder.
* *
*/ */
if (!hsm_do_ecdh(&h->ss.s, re)) if (!hsm_do_ecdh(&h->ss, re))
status_failed(WIRE_INITR_ACT3_BAD_HSM_ECDH, status_failed(WIRE_INITR_ACT3_BAD_HSM_ECDH,
"re=%s", "re=%s",
type_to_string(trc, struct pubkey, re)); type_to_string(trc, struct pubkey, re));
@ -862,8 +856,8 @@ static void act_three_responder(struct handshake *h, int fd,
* * `ss = ECDH(rs, e.priv)` * * `ss = ECDH(rs, e.priv)`
* * where `e` is the responder's original ephemeral key * * where `e` is the responder's original ephemeral key
*/ */
if (!secp256k1_ecdh(secp256k1_ctx, h->ss.s.u.u8, &their_id->pubkey, if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, &their_id->pubkey,
h->e.priv.secret)) h->e.priv.secret.data))
status_failed(WIRE_RESPR_ACT3_BAD_ECDH_FOR_SS, "rs=%s e.priv=%s", status_failed(WIRE_RESPR_ACT3_BAD_ECDH_FOR_SS, "rs=%s e.priv=%s",
type_to_string(trc, struct pubkey, their_id), type_to_string(trc, struct pubkey, their_id),
tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv))); tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv)));
@ -990,9 +984,9 @@ int main(int argc, char *argv[])
if (fromwire_handshake_responder(msg, NULL, &my_id)) { if (fromwire_handshake_responder(msg, NULL, &my_id)) {
responder(clientfd, &my_id, &their_id, &ck, &sk, &rk); responder(clientfd, &my_id, &their_id, &ck, &sk, &rk);
cs.rn = cs.sn = 0; cs.rn = cs.sn = 0;
cs.sk = sk.s; cs.sk = sk;
cs.rk = rk.s; cs.rk = rk;
cs.r_ck = cs.s_ck = ck.s; cs.r_ck = cs.s_ck = ck;
wire_sync_write(REQ_FD, wire_sync_write(REQ_FD,
towire_handshake_responder_reply(msg, towire_handshake_responder_reply(msg,
&their_id, &their_id,
@ -1001,9 +995,9 @@ int main(int argc, char *argv[])
&their_id)) { &their_id)) {
initiator(clientfd, &my_id, &their_id, &ck, &sk, &rk); initiator(clientfd, &my_id, &their_id, &ck, &sk, &rk);
cs.rn = cs.sn = 0; cs.rn = cs.sn = 0;
cs.sk = sk.s; cs.sk = sk;
cs.rk = rk.s; cs.rk = rk;
cs.r_ck = cs.s_ck = ck.s; cs.r_ck = cs.s_ck = ck;
wire_sync_write(REQ_FD, wire_sync_write(REQ_FD,
towire_handshake_initiator_reply(msg, &cs)); towire_handshake_initiator_reply(msg, &cs));
} else } else

22
lightningd/handshake/test/run-handshake.c

@ -61,10 +61,10 @@ void hsm_setup(int fd)
{ {
} }
bool hsm_do_ecdh(struct sha256 *ss, const struct pubkey *point) bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point)
{ {
return secp256k1_ecdh(secp256k1_ctx, ss->u.u8, &point->pubkey, return secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey,
privkey.secret) == 1; privkey.secret.data) == 1;
} }
int main(void) int main(void)
@ -80,11 +80,11 @@ int main(void)
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN); | SECP256K1_CONTEXT_SIGN);
memset(responder_privkey.secret, 0x21, memset(responder_privkey.secret.data, 0x21,
sizeof(responder_privkey.secret)); sizeof(responder_privkey.secret.data));
if (!secp256k1_ec_pubkey_create(secp256k1_ctx, if (!secp256k1_ec_pubkey_create(secp256k1_ctx,
&responder_id.pubkey, &responder_id.pubkey,
responder_privkey.secret)) responder_privkey.secret.data))
errx(1, "Keygen failed"); errx(1, "Keygen failed");
if (pipe(fds1) != 0 || pipe(fds2) != 0) if (pipe(fds1) != 0 || pipe(fds2) != 0)
@ -104,7 +104,7 @@ int main(void)
privkey = responder_privkey; privkey = responder_privkey;
status_prefix = "RESPR"; status_prefix = "RESPR";
status_trace("ls.priv: 0x%s", status_trace("ls.priv: 0x%s",
tal_hexstr(trc, responder_privkey.secret, tal_hexstr(trc, &responder_privkey,
sizeof(responder_privkey))); sizeof(responder_privkey)));
status_trace("ls.pub: 0x%s", status_trace("ls.pub: 0x%s",
type_to_string(trc, struct pubkey, &responder_id)); type_to_string(trc, struct pubkey, &responder_id));
@ -125,19 +125,19 @@ int main(void)
close(fds2[1]); close(fds2[1]);
close(fds1[0]); close(fds1[0]);
memset(initiator_privkey.secret, 0x11, memset(initiator_privkey.secret.data, 0x11,
sizeof(initiator_privkey.secret)); sizeof(initiator_privkey.secret.data));
memset(e_priv, 0x12, sizeof(e_priv)); memset(e_priv, 0x12, sizeof(e_priv));
if (!secp256k1_ec_pubkey_create(secp256k1_ctx, if (!secp256k1_ec_pubkey_create(secp256k1_ctx,
&initiator_id.pubkey, &initiator_id.pubkey,
initiator_privkey.secret)) initiator_privkey.secret.data))
errx(1, "Initiator keygen failed"); errx(1, "Initiator keygen failed");
privkey = initiator_privkey; privkey = initiator_privkey;
status_prefix = "INITR"; status_prefix = "INITR";
status_trace("rs.pub: 0x%s", status_trace("rs.pub: 0x%s",
type_to_string(trc, struct pubkey, &responder_id)); type_to_string(trc, struct pubkey, &responder_id));
status_trace("ls.priv: 0x%s", status_trace("ls.priv: 0x%s",
tal_hexstr(trc, initiator_privkey.secret, tal_hexstr(trc, &initiator_privkey,
sizeof(initiator_privkey))); sizeof(initiator_privkey)));
status_trace("ls.pub: 0x%s", status_trace("ls.pub: 0x%s",
type_to_string(trc, struct pubkey, &initiator_id)); type_to_string(trc, struct pubkey, &initiator_id));

2
lightningd/hsm/client.c

@ -9,7 +9,7 @@ void hsm_setup(int fd)
hsm_fd = fd; hsm_fd = fd;
} }
bool hsm_do_ecdh(struct sha256 *ss, const struct pubkey *point) bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point)
{ {
u8 *req = towire_hsm_ecdh_req(NULL, point), *resp; u8 *req = towire_hsm_ecdh_req(NULL, point), *resp;
size_t len; size_t len;

4
lightningd/hsm/client.h

@ -7,11 +7,11 @@
#include <stdbool.h> #include <stdbool.h>
struct pubkey; struct pubkey;
struct sha256; struct secret;
/* Setup communication to the HSM */ /* Setup communication to the HSM */
void hsm_setup(int fd); void hsm_setup(int fd);
/* Do ECDH using this node id secret. */ /* Do ECDH using this node id secret. */
bool hsm_do_ecdh(struct sha256 *ss, const struct pubkey *point); bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point);
#endif /* LIGHTNING_LIGHTNINGD_HSM_H */ #endif /* LIGHTNING_LIGHTNINGD_HSM_H */

24
lightningd/hsm/hsm.c

@ -37,7 +37,7 @@
/* Nobody will ever find it here! */ /* Nobody will ever find it here! */
static struct { static struct {
struct privkey hsm_secret; struct secret hsm_secret;
struct ext_key bip32; struct ext_key bip32;
} secretstuff; } secretstuff;
@ -49,26 +49,26 @@ struct client {
struct io_plan *(*handle)(struct io_conn *, struct daemon_conn *); struct io_plan *(*handle)(struct io_conn *, struct daemon_conn *);
}; };
static void node_key(struct privkey *node_secret, struct pubkey *node_id) static void node_key(struct privkey *node_privkey, struct pubkey *node_id)
{ {
u32 salt = 0; u32 salt = 0;
struct privkey unused_s; struct privkey unused_s;
struct pubkey unused_k; struct pubkey unused_k;
if (node_secret == NULL) if (node_privkey == NULL)
node_secret = &unused_s; node_privkey = &unused_s;
else if (node_id == NULL) else if (node_id == NULL)
node_id = &unused_k; node_id = &unused_k;
do { do {
hkdf_sha256(node_secret, sizeof(*node_secret), hkdf_sha256(node_privkey, sizeof(*node_privkey),
&salt, sizeof(salt), &salt, sizeof(salt),
&secretstuff.hsm_secret, &secretstuff.hsm_secret,
sizeof(secretstuff.hsm_secret), sizeof(secretstuff.hsm_secret),
"nodeid", 6); "nodeid", 6);
salt++; salt++;
} while (!secp256k1_ec_pubkey_create(secp256k1_ctx, &node_id->pubkey, } while (!secp256k1_ec_pubkey_create(secp256k1_ctx, &node_id->pubkey,
node_secret->secret)); node_privkey->secret.data));
} }
static struct client *new_client(struct daemon_conn *master, static struct client *new_client(struct daemon_conn *master,
@ -95,7 +95,7 @@ static struct io_plan *handle_ecdh(struct io_conn *conn, struct daemon_conn *dc)
struct client *c = container_of(dc, struct client, dc); struct client *c = container_of(dc, struct client, dc);
struct privkey privkey; struct privkey privkey;
struct pubkey point; struct pubkey point;
struct sha256 ss; struct secret ss;
if (!fromwire_hsm_ecdh_req(dc->msg_in, NULL, &point)) { if (!fromwire_hsm_ecdh_req(dc->msg_in, NULL, &point)) {
daemon_conn_send(c->master, daemon_conn_send(c->master,
@ -106,8 +106,8 @@ static struct io_plan *handle_ecdh(struct io_conn *conn, struct daemon_conn *dc)
} }
node_key(&privkey, NULL); node_key(&privkey, NULL);
if (secp256k1_ecdh(secp256k1_ctx, ss.u.u8, &point.pubkey, if (secp256k1_ecdh(secp256k1_ctx, ss.data, &point.pubkey,
privkey.secret) != 1) { privkey.secret.data) != 1) {
status_trace("secp256k1_ecdh fail for client %"PRIu64, c->id); status_trace("secp256k1_ecdh fail for client %"PRIu64, c->id);
daemon_conn_send(c->master, daemon_conn_send(c->master,
take(towire_hsmstatus_client_bad_request(c, take(towire_hsmstatus_client_bad_request(c,
@ -238,7 +238,7 @@ static struct io_plan *handle_channeld(struct io_conn *conn,
static void send_init_response(struct daemon_conn *master) static void send_init_response(struct daemon_conn *master)
{ {
struct pubkey node_id; struct pubkey node_id;
struct privkey peer_seed; struct secret peer_seed;
u8 *serialized_extkey = tal_arr(master, u8, BIP32_SERIALIZED_LEN), *msg; u8 *serialized_extkey = tal_arr(master, u8, BIP32_SERIALIZED_LEN), *msg;
hkdf_sha256(&peer_seed, sizeof(peer_seed), NULL, 0, hkdf_sha256(&peer_seed, sizeof(peer_seed), NULL, 0,
@ -343,9 +343,9 @@ static void bitcoin_keypair(struct privkey *privkey,
"BIP32 of %u failed", index); "BIP32 of %u failed", index);
/* libwally says: The private key with prefix byte 0 */ /* libwally says: The private key with prefix byte 0 */
memcpy(privkey->secret, ext.priv_key+1, 32); memcpy(privkey->secret.data, ext.priv_key+1, 32);
if (!secp256k1_ec_pubkey_create(secp256k1_ctx, &pubkey->pubkey, if (!secp256k1_ec_pubkey_create(secp256k1_ctx, &pubkey->pubkey,
privkey->secret)) privkey->secret.data))
status_failed(WIRE_HSMSTATUS_KEY_FAILED, status_failed(WIRE_HSMSTATUS_KEY_FAILED,
"BIP32 pubkey %u create failed", index); "BIP32 pubkey %u create failed", index);
} }

4
lightningd/hsm/hsm_client_wire_csv

@ -1,8 +1,8 @@
# Give me ECDH(node-id-secret,point) # Give me ECDH(node-id-secret,point)
hsm_ecdh_req,1 hsm_ecdh_req,1
hsm_ecdh_req,0,point,33 hsm_ecdh_req,0,point,struct pubkey
hsm_ecdh_resp,100 hsm_ecdh_resp,100
hsm_ecdh_resp,0,ss,32 hsm_ecdh_resp,0,ss,struct secret
hsm_cannouncement_sig_req,2 hsm_cannouncement_sig_req,2
hsm_cannouncement_sig_req,0,bitcoin_id,struct pubkey hsm_cannouncement_sig_req,0,bitcoin_id,struct pubkey

4
lightningd/hsm/hsm_wire.csv

@ -17,7 +17,7 @@ hsmctl_init,0,new,bool
hsmctl_init_reply,101 hsmctl_init_reply,101
hsmctl_init_reply,0,node_id,33 hsmctl_init_reply,0,node_id,33
hsmctl_init_reply,33,peer_seed,struct privkey hsmctl_init_reply,33,peer_seed,struct secret
hsmctl_init_reply,65,bip32_len,2 hsmctl_init_reply,65,bip32_len,2
hsmctl_init_reply,67,bip32_seed,bip32_len*u8 hsmctl_init_reply,67,bip32_seed,bip32_len*u8
@ -49,4 +49,4 @@ hsmctl_hsmfd_channeld,5
hsmctl_hsmfd_channeld,0,unique_id,8 hsmctl_hsmfd_channeld,0,unique_id,8
# Empty reply, just an fd # Empty reply, just an fd
hsmctl_hsmfd_channeld_reply,105 hsmctl_hsmfd_channeld_reply,105

Can't render this file because it has a wrong number of fields in line 2.

4
lightningd/htlc_end.h

@ -31,11 +31,11 @@ struct htlc_end {
/* If we are forwarding, remember the shared secret for an /* If we are forwarding, remember the shared secret for an
* eventual reply */ * eventual reply */
struct sha256 *shared_secret; struct secret *shared_secret;
/* If we are the origin, remember all shared secrets, so we /* If we are the origin, remember all shared secrets, so we
* can unwrap an eventual reply */ * can unwrap an eventual reply */
struct sha256 *path_secrets; struct secret *path_secrets;
}; };
static inline const struct htlc_end *keyof_htlc_end(const struct htlc_end *e) static inline const struct htlc_end *keyof_htlc_end(const struct htlc_end *e)

23
lightningd/key_derive.c

@ -58,7 +58,7 @@ bool derive_simple_key(const struct pubkey *basepoint,
* *
* secretkey = basepoint-secret + SHA256(per-commitment-point || basepoint) * secretkey = basepoint-secret + SHA256(per-commitment-point || basepoint)
*/ */
bool derive_simple_privkey(const struct privkey *base_secret, bool derive_simple_privkey(const struct secret *base_secret,
const struct pubkey *basepoint, const struct pubkey *basepoint,
const struct pubkey *per_commitment_point, const struct pubkey *per_commitment_point,
struct privkey *key) struct privkey *key)
@ -77,8 +77,8 @@ bool derive_simple_privkey(const struct privkey *base_secret,
printf("# = 0x%s\n", tal_hexstr(tmpctx, &sha, sizeof(sha))); printf("# = 0x%s\n", tal_hexstr(tmpctx, &sha, sizeof(sha)));
#endif #endif
*key = *base_secret; key->secret = *base_secret;
if (secp256k1_ec_privkey_tweak_add(secp256k1_ctx, key->secret, if (secp256k1_ec_privkey_tweak_add(secp256k1_ctx, key->secret.data,
sha.u.u8) != 1) sha.u.u8) != 1)
return false; return false;
#ifdef SUPERVERBOSE #ifdef SUPERVERBOSE
@ -175,15 +175,15 @@ bool derive_revocation_key(const struct pubkey *basepoint,
* *
* revocationsecretkey = revocation-basepoint-secret * SHA256(revocation-basepoint || per-commitment-point) + per-commitment-secret*SHA256(per-commitment-point || revocation-basepoint) * revocationsecretkey = revocation-basepoint-secret * SHA256(revocation-basepoint || per-commitment-point) + per-commitment-secret*SHA256(per-commitment-point || revocation-basepoint)
*/ */
bool derive_revocation_privkey(const struct privkey *base_secret, bool derive_revocation_privkey(const struct secret *base_secret,
const struct privkey *per_commitment_secret, const struct secret *per_commitment_secret,
const struct pubkey *basepoint, const struct pubkey *basepoint,
const struct pubkey *per_commitment_point, const struct pubkey *per_commitment_point,
struct privkey *key) struct privkey *key)
{ {
struct sha256 sha; struct sha256 sha;
unsigned char der_keys[PUBKEY_DER_LEN * 2]; unsigned char der_keys[PUBKEY_DER_LEN * 2];
struct privkey part2; struct secret part2;
pubkey_to_der(der_keys, basepoint); pubkey_to_der(der_keys, basepoint);
pubkey_to_der(der_keys + PUBKEY_DER_LEN, per_commitment_point); pubkey_to_der(der_keys + PUBKEY_DER_LEN, per_commitment_point);
@ -196,8 +196,9 @@ bool derive_revocation_privkey(const struct privkey *base_secret,
printf("# = 0x%s\n", tal_hexstr(tmpctx, sha.u.u8, sizeof(sha.u.u8))), printf("# = 0x%s\n", tal_hexstr(tmpctx, sha.u.u8, sizeof(sha.u.u8))),
#endif #endif
*key = *base_secret; key->secret = *base_secret;
if (secp256k1_ec_privkey_tweak_mul(secp256k1_ctx, key->secret, sha.u.u8) if (secp256k1_ec_privkey_tweak_mul(secp256k1_ctx, key->secret.data,
sha.u.u8)
!= 1) != 1)
return false; return false;
#ifdef SUPERVERBOSE #ifdef SUPERVERBOSE
@ -218,7 +219,7 @@ bool derive_revocation_privkey(const struct privkey *base_secret,
#endif #endif
part2 = *per_commitment_secret; part2 = *per_commitment_secret;
if (secp256k1_ec_privkey_tweak_mul(secp256k1_ctx, part2.secret, if (secp256k1_ec_privkey_tweak_mul(secp256k1_ctx, part2.data,
sha.u.u8) != 1) sha.u.u8) != 1)
return false; return false;
#ifdef SUPERVERBOSE #ifdef SUPERVERBOSE
@ -228,8 +229,8 @@ bool derive_revocation_privkey(const struct privkey *base_secret,
printf("# = 0x%s\n", tal_hexstr(tmpctx, &part2, sizeof(part2))); printf("# = 0x%s\n", tal_hexstr(tmpctx, &part2, sizeof(part2)));
#endif #endif
if (secp256k1_ec_privkey_tweak_add(secp256k1_ctx, key->secret, if (secp256k1_ec_privkey_tweak_add(secp256k1_ctx, key->secret.data,
part2.secret) != 1) part2.data) != 1)
return false; return false;
#ifdef SUPERVERBOSE #ifdef SUPERVERBOSE

7
lightningd/key_derive.h

@ -3,13 +3,14 @@
#include "config.h" #include "config.h"
struct pubkey; struct pubkey;
struct secret;
/* For `localkey`, `remotekey`, `local-delayedkey` and `remote-delayedkey` */ /* For `localkey`, `remotekey`, `local-delayedkey` and `remote-delayedkey` */
bool derive_simple_key(const struct pubkey *basepoint, bool derive_simple_key(const struct pubkey *basepoint,
const struct pubkey *per_commitment_point, const struct pubkey *per_commitment_point,
struct pubkey *key); struct pubkey *key);
bool derive_simple_privkey(const struct privkey *base_secret, bool derive_simple_privkey(const struct secret *base_secret,
const struct pubkey *basepoint, const struct pubkey *basepoint,
const struct pubkey *per_commitment_point, const struct pubkey *per_commitment_point,
struct privkey *key); struct privkey *key);
@ -19,8 +20,8 @@ bool derive_revocation_key(const struct pubkey *basepoint,
const struct pubkey *per_commitment_point, const struct pubkey *per_commitment_point,
struct pubkey *key); struct pubkey *key);
bool derive_revocation_privkey(const struct privkey *base_secret, bool derive_revocation_privkey(const struct secret *base_secret,
const struct privkey *per_commitment_secret, const struct secret *per_commitment_secret,
const struct pubkey *basepoint, const struct pubkey *basepoint,
const struct pubkey *per_commitment_point, const struct pubkey *per_commitment_point,
struct privkey *key); struct privkey *key);

2
lightningd/lightningd.h

@ -33,7 +33,7 @@ struct lightningd {
/* All peers we're tracking. */ /* All peers we're tracking. */
struct list_head peers; struct list_head peers;
/* FIXME: This should stay in HSM */ /* FIXME: This should stay in HSM */
struct privkey peer_seed; struct secret peer_seed;
/* Used to give a unique seed to every peer. */ /* Used to give a unique seed to every peer. */
u64 peer_counter; u64 peer_counter;

2
lightningd/pay.c

@ -163,7 +163,7 @@ static void json_sendpay(struct command *cmd,
u64 amount, lastamount; u64 amount, lastamount;
struct onionpacket *packet; struct onionpacket *packet;
u8 *msg; u8 *msg;
struct sha256 *path_secrets; struct secret *path_secrets;
if (!json_get_params(buffer, params, if (!json_get_params(buffer, params,
"route", &routetok, "route", &routetok,

13
lightningd/peer_control.c

@ -641,12 +641,12 @@ struct decoding_htlc {
u32 cltv_expiry; u32 cltv_expiry;
struct sha256 payment_hash; struct sha256 payment_hash;
u8 onion[TOTAL_PACKET_SIZE]; u8 onion[TOTAL_PACKET_SIZE];
u8 shared_secret[32]; struct secret shared_secret;
}; };
static void fail_htlc(struct peer *peer, struct htlc_end *hend, const u8 *msg) static void fail_htlc(struct peer *peer, struct htlc_end *hend, const u8 *msg)
{ {
u8 *reply = wrap_onionreply(hend, hend->shared_secret->u.u8, msg); u8 *reply = wrap_onionreply(hend, hend->shared_secret, msg);
subd_send_msg(peer->owner, subd_send_msg(peer->owner,
take(towire_channel_fail_htlc(peer, hend->htlc_id, reply))); take(towire_channel_fail_htlc(peer, hend->htlc_id, reply)));
if (taken(msg)) if (taken(msg))
@ -660,7 +660,7 @@ static void fail_local_htlc(struct peer *peer, struct htlc_end *hend, const u8 *
log_broken(peer->log, "failed htlc %"PRIu64" code 0x%04x (%s)", log_broken(peer->log, "failed htlc %"PRIu64" code 0x%04x (%s)",
hend->htlc_id, failcode, onion_type_name(failcode)); hend->htlc_id, failcode, onion_type_name(failcode));
reply = create_onionreply(hend, hend->shared_secret->u.u8, msg); reply = create_onionreply(hend, hend->shared_secret, msg);
fail_htlc(peer, hend, reply); fail_htlc(peer, hend, reply);
} }
@ -1088,7 +1088,7 @@ static int peer_accepted_htlc(struct peer *peer, const u8 *msg)
u8 *req; u8 *req;
hend = tal(msg, struct htlc_end); hend = tal(msg, struct htlc_end);
hend->shared_secret = tal(hend, struct sha256); hend->shared_secret = tal(hend, struct secret);
if (!fromwire_channel_accepted_htlc(msg, NULL, if (!fromwire_channel_accepted_htlc(msg, NULL,
&hend->htlc_id, &hend->msatoshis, &hend->htlc_id, &hend->msatoshis,
&hend->cltv_expiry, &hend->payment_hash, &hend->cltv_expiry, &hend->payment_hash,
@ -1179,10 +1179,9 @@ static int peer_failed_htlc(struct peer *peer, const u8 *msg)
reason); reason);
} else { } else {
size_t numhops = tal_count(hend->path_secrets); size_t numhops = tal_count(hend->path_secrets);
u8 **shared_secrets = tal_arr(hend, u8*, numhops); struct secret *shared_secrets = tal_arr(hend, struct secret, numhops);
for (size_t i=0; i<numhops; i++) { for (size_t i=0; i<numhops; i++) {
shared_secrets[i] = tal_arr(hend, u8, 32); shared_secrets[i] = hend->path_secrets[i];
memcpy(shared_secrets[i], hend->path_secrets[i].u.u8, 32);
} }
reply = unwrap_onionreply(msg, shared_secrets, numhops, reason); reply = unwrap_onionreply(msg, shared_secrets, numhops, reason);
failcode = fromwire_peektype(reply->msg); failcode = fromwire_peektype(reply->msg);

22
lightningd/sphinx.c

@ -233,7 +233,7 @@ bool onion_shared_secret(
const struct privkey *privkey) const struct privkey *privkey)
{ {
return create_shared_secret(secret, &packet->ephemeralkey, return create_shared_secret(secret, &packet->ephemeralkey,
privkey->secret); privkey->secret.data);
} }
void pubkey_hash160( void pubkey_hash160(
@ -363,7 +363,7 @@ struct onionpacket *create_onionpacket(
const u8 *sessionkey, const u8 *sessionkey,
const u8 *assocdata, const u8 *assocdata,
const size_t assocdatalen, const size_t assocdatalen,
struct sha256 **path_secrets struct secret **path_secrets
) )
{ {
struct onionpacket *packet = talz(ctx, struct onionpacket); struct onionpacket *packet = talz(ctx, struct onionpacket);
@ -373,7 +373,7 @@ struct onionpacket *create_onionpacket(
u8 nexthmac[SECURITY_PARAMETER]; u8 nexthmac[SECURITY_PARAMETER];
u8 stream[ROUTING_INFO_SIZE]; u8 stream[ROUTING_INFO_SIZE];
struct hop_params *params = generate_hop_params(ctx, sessionkey, path); struct hop_params *params = generate_hop_params(ctx, sessionkey, path);
struct sha256 *secrets = tal_arr(ctx, struct sha256, num_hops); struct secret *secrets = tal_arr(ctx, struct secret, num_hops);
if (!params) if (!params)
return NULL; return NULL;
@ -470,7 +470,7 @@ struct route_step *process_onionpacket(
return step; return step;
} }
u8 *create_onionreply(const tal_t *ctx, const u8 *shared_secret, u8 *create_onionreply(const tal_t *ctx, const struct secret *shared_secret,
const u8 *failure_msg) const u8 *failure_msg)
{ {
size_t msglen = tal_len(failure_msg); size_t msglen = tal_len(failure_msg);
@ -485,7 +485,7 @@ u8 *create_onionreply(const tal_t *ctx, const u8 *shared_secret,
towire_pad(&payload, padlen); towire_pad(&payload, padlen);
assert(tal_len(payload) == ONION_REPLY_SIZE + 4); assert(tal_len(payload) == ONION_REPLY_SIZE + 4);
generate_key(key, "um", 2, shared_secret); generate_key(key, "um", 2, shared_secret->data);
compute_hmac(hmac, payload, tal_len(payload), key, KEY_LEN); compute_hmac(hmac, payload, tal_len(payload), key, KEY_LEN);
towire(&reply, hmac, sizeof(hmac)); towire(&reply, hmac, sizeof(hmac));
@ -495,19 +495,21 @@ u8 *create_onionreply(const tal_t *ctx, const u8 *shared_secret,
return reply; return reply;
} }
u8 *wrap_onionreply(const tal_t *ctx, const u8 *shared_secret, const u8 *reply) u8 *wrap_onionreply(const tal_t *ctx,
const struct secret *shared_secret, const u8 *reply)
{ {
u8 key[KEY_LEN]; u8 key[KEY_LEN];
size_t streamlen = tal_len(reply); size_t streamlen = tal_len(reply);
u8 stream[streamlen]; u8 stream[streamlen];
u8 *result = tal_arr(ctx, u8, streamlen); u8 *result = tal_arr(ctx, u8, streamlen);
generate_key(key, "ammag", 5, shared_secret); generate_key(key, "ammag", 5, shared_secret->data);
generate_cipher_stream(stream, key, streamlen); generate_cipher_stream(stream, key, streamlen);
xorbytes(result, stream, reply, streamlen); xorbytes(result, stream, reply, streamlen);
return result; return result;
} }
struct onionreply *unwrap_onionreply(const tal_t *ctx, u8 **shared_secrets, struct onionreply *unwrap_onionreply(const tal_t *ctx,
const struct secret *shared_secrets,
const int numhops, const u8 *reply) const int numhops, const u8 *reply)
{ {
tal_t *tmpctx = tal_tmpctx(ctx); tal_t *tmpctx = tal_tmpctx(ctx);
@ -528,11 +530,11 @@ struct onionreply *unwrap_onionreply(const tal_t *ctx, u8 **shared_secrets,
for (int i = 0; i < numhops; i++) { for (int i = 0; i < numhops; i++) {
/* Since the encryption is just XORing with the cipher /* Since the encryption is just XORing with the cipher
* stream encryption is identical to decryption */ * stream encryption is identical to decryption */
msg = wrap_onionreply(tmpctx, shared_secrets[i], msg); msg = wrap_onionreply(tmpctx, &shared_secrets[i], msg);
/* Check if the HMAC matches, this means that this is /* Check if the HMAC matches, this means that this is
* the origin */ * the origin */
generate_key(key, "um", 2, shared_secrets[i]); generate_key(key, "um", 2, shared_secrets[i].data);
compute_hmac(hmac, msg + sizeof(hmac), compute_hmac(hmac, msg + sizeof(hmac),
tal_len(msg) - sizeof(hmac), key, KEY_LEN); tal_len(msg) - sizeof(hmac), key, KEY_LEN);
if (memcmp(hmac, msg, sizeof(hmac)) == 0) { if (memcmp(hmac, msg, sizeof(hmac)) == 0) {

11
lightningd/sphinx.h

@ -87,7 +87,7 @@ struct onionpacket *create_onionpacket(
const u8 * sessionkey, const u8 * sessionkey,
const u8 *assocdata, const u8 *assocdata,
const size_t assocdatalen, const size_t assocdatalen,
struct sha256 **path_secrets struct secret **path_secrets
); );
/** /**
@ -162,7 +162,8 @@ struct onionreply {
* HMAC * HMAC
* @failure_msg: message (must support tal_len) * @failure_msg: message (must support tal_len)
*/ */
u8 *create_onionreply(const tal_t *ctx, const u8 *shared_secret, const u8 *failure_msg); u8 *create_onionreply(const tal_t *ctx, const struct secret *shared_secret,
const u8 *failure_msg);
/** /**
* wrap_onionreply - Add another encryption layer to the reply. * wrap_onionreply - Add another encryption layer to the reply.
@ -172,7 +173,8 @@ u8 *create_onionreply(const tal_t *ctx, const u8 *shared_secret, const u8 *failu
* encryption. * encryption.
* @reply: the reply to wrap * @reply: the reply to wrap
*/ */
u8 *wrap_onionreply(const tal_t *ctx, const u8 *shared_secret, const u8 *reply); u8 *wrap_onionreply(const tal_t *ctx, const struct secret *shared_secret,
const u8 *reply);
/** /**
* unwrap_onionreply - Remove layers, check integrity and parse reply * unwrap_onionreply - Remove layers, check integrity and parse reply
@ -182,7 +184,8 @@ u8 *wrap_onionreply(const tal_t *ctx, const u8 *shared_secret, const u8 *reply);
* @numhops: path length and number of shared_secrets provided * @numhops: path length and number of shared_secrets provided
* @reply: the incoming reply * @reply: the incoming reply
*/ */
struct onionreply *unwrap_onionreply(const tal_t *ctx, u8 **shared_secrets, struct onionreply *unwrap_onionreply(const tal_t *ctx,
const struct secret *shared_secrets,
const int numhops, const u8 *reply); const int numhops, const u8 *reply);
#endif /* LIGHTNING_DAEMON_SPHINX_H */ #endif /* LIGHTNING_DAEMON_SPHINX_H */

70
lightningd/test/run-commit_tx.c

@ -41,9 +41,9 @@ static struct sha256_double txid_from_hex(const char *hex)
return sha256; return sha256;
} }
static struct privkey privkey_from_hex(const char *hex) static struct secret secret_from_hex(const char *hex)
{ {
struct privkey pk; struct secret s;
size_t len; size_t len;
if (strstarts(hex, "0x")) if (strstarts(hex, "0x"))
hex += 2; hex += 2;
@ -56,9 +56,17 @@ static struct privkey privkey_from_hex(const char *hex)
*/ */
if (len == 66 && strends(hex, "01")) if (len == 66 && strends(hex, "01"))
len -= 2; len -= 2;
if (!hex_decode(hex, len, &pk, sizeof(pk))) if (!hex_decode(hex, len, &s, sizeof(s)))
abort(); abort();
return pk; return s;
}
static bool pubkey_from_secret(const struct secret *secret,
struct pubkey *key)
{
return secp256k1_ec_pubkey_create(secp256k1_ctx,
&key->pubkey,
secret->data);
} }
static void tx_must_be_eq(const struct bitcoin_tx *a, static void tx_must_be_eq(const struct bitcoin_tx *a,
@ -420,10 +428,10 @@ int main(void)
u16 to_self_delay; u16 to_self_delay;
/* x_ prefix means internal vars we used to derive spec */ /* x_ prefix means internal vars we used to derive spec */
struct privkey local_funding_privkey, x_remote_funding_privkey; struct privkey local_funding_privkey, x_remote_funding_privkey;
struct privkey x_local_payment_basepoint_secret, x_remote_payment_basepoint_secret; struct secret x_local_payment_basepoint_secret, x_remote_payment_basepoint_secret;
struct privkey x_local_per_commitment_secret; struct secret x_local_per_commitment_secret;
struct privkey x_local_delayed_payment_basepoint_secret; struct secret x_local_delayed_payment_basepoint_secret;
struct privkey x_remote_revocation_basepoint_secret; struct secret x_remote_revocation_basepoint_secret;
struct privkey local_secretkey, x_remote_secretkey; struct privkey local_secretkey, x_remote_secretkey;
struct privkey x_local_delayed_secretkey; struct privkey x_local_delayed_secretkey;
struct pubkey local_funding_pubkey, remote_funding_pubkey; struct pubkey local_funding_pubkey, remote_funding_pubkey;
@ -503,61 +511,61 @@ int main(void)
* # From local_delayed_payment_basepoint_secret, local_per_commitment_point and local_delayed_payment_basepoint * # From local_delayed_payment_basepoint_secret, local_per_commitment_point and local_delayed_payment_basepoint
* INTERNAL: local_delayed_secretkey: adf3464ce9c2f230fd2582fda4c6965e4993ca5524e8c9580e3df0cf226981ad01 * INTERNAL: local_delayed_secretkey: adf3464ce9c2f230fd2582fda4c6965e4993ca5524e8c9580e3df0cf226981ad01
*/ */
local_funding_privkey = privkey_from_hex("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f374901"); local_funding_privkey.secret = secret_from_hex("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f374901");
x_remote_funding_privkey = privkey_from_hex("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e1301"); x_remote_funding_privkey.secret = secret_from_hex("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e1301");
SUPERVERBOSE("INTERNAL: remote_funding_privkey: %s01\n", SUPERVERBOSE("INTERNAL: remote_funding_privkey: %s01\n",
type_to_string(tmpctx, struct privkey, type_to_string(tmpctx, struct privkey,
&x_remote_funding_privkey)); &x_remote_funding_privkey));
x_local_payment_basepoint_secret = privkey_from_hex("1111111111111111111111111111111111111111111111111111111111111111"); x_local_payment_basepoint_secret = secret_from_hex("1111111111111111111111111111111111111111111111111111111111111111");
SUPERVERBOSE("INTERNAL: local_payment_basepoint_secret: %s\n", SUPERVERBOSE("INTERNAL: local_payment_basepoint_secret: %s\n",
type_to_string(tmpctx, struct privkey, type_to_string(tmpctx, struct secret,
&x_local_payment_basepoint_secret)); &x_local_payment_basepoint_secret));
x_remote_revocation_basepoint_secret = privkey_from_hex("2222222222222222222222222222222222222222222222222222222222222222"); x_remote_revocation_basepoint_secret = secret_from_hex("2222222222222222222222222222222222222222222222222222222222222222");
SUPERVERBOSE("INTERNAL: remote_revocation_basepoint_secret: %s\n", SUPERVERBOSE("INTERNAL: remote_revocation_basepoint_secret: %s\n",
type_to_string(tmpctx, struct privkey, type_to_string(tmpctx, struct secret,
&x_remote_revocation_basepoint_secret)); &x_remote_revocation_basepoint_secret));
x_local_delayed_payment_basepoint_secret = privkey_from_hex("3333333333333333333333333333333333333333333333333333333333333333"); x_local_delayed_payment_basepoint_secret = secret_from_hex("3333333333333333333333333333333333333333333333333333333333333333");
SUPERVERBOSE("INTERNAL: local_delayed_payment_basepoint_secret: %s\n", SUPERVERBOSE("INTERNAL: local_delayed_payment_basepoint_secret: %s\n",
type_to_string(tmpctx, struct privkey, type_to_string(tmpctx, struct secret,
&x_local_delayed_payment_basepoint_secret)); &x_local_delayed_payment_basepoint_secret));
x_remote_payment_basepoint_secret = privkey_from_hex("4444444444444444444444444444444444444444444444444444444444444444"); x_remote_payment_basepoint_secret = secret_from_hex("4444444444444444444444444444444444444444444444444444444444444444");
SUPERVERBOSE("INTERNAL: remote_payment_basepoint_secret: %s\n", SUPERVERBOSE("INTERNAL: remote_payment_basepoint_secret: %s\n",
type_to_string(tmpctx, struct privkey, type_to_string(tmpctx, struct secret,
&x_remote_payment_basepoint_secret)); &x_remote_payment_basepoint_secret));
x_local_per_commitment_secret = privkey_from_hex("0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100"); x_local_per_commitment_secret = secret_from_hex("0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100");
SUPERVERBOSE("x_local_per_commitment_secret: %s\n", SUPERVERBOSE("x_local_per_commitment_secret: %s\n",
type_to_string(tmpctx, struct privkey, type_to_string(tmpctx, struct secret,
&x_local_per_commitment_secret)); &x_local_per_commitment_secret));
if (!pubkey_from_privkey(&x_remote_revocation_basepoint_secret, if (!pubkey_from_secret(&x_remote_revocation_basepoint_secret,
&x_remote_revocation_basepoint)) &x_remote_revocation_basepoint))
abort(); abort();
SUPERVERBOSE("# From remote_revocation_basepoint_secret\n" SUPERVERBOSE("# From remote_revocation_basepoint_secret\n"
"INTERNAL: remote_revocation_basepoint: %s\n", "INTERNAL: remote_revocation_basepoint: %s\n",
type_to_string(tmpctx, struct pubkey, type_to_string(tmpctx, struct pubkey,
&x_remote_revocation_basepoint)); &x_remote_revocation_basepoint));
if (!pubkey_from_privkey(&x_local_delayed_payment_basepoint_secret, if (!pubkey_from_secret(&x_local_delayed_payment_basepoint_secret,
&x_local_delayed_payment_basepoint)) &x_local_delayed_payment_basepoint))
abort(); abort();
SUPERVERBOSE("# From local_delayed_payment_basepoint_secret\n" SUPERVERBOSE("# From local_delayed_payment_basepoint_secret\n"
"INTERNAL: local_delayed_payment_basepoint: %s\n", "INTERNAL: local_delayed_payment_basepoint: %s\n",
type_to_string(tmpctx, struct pubkey, type_to_string(tmpctx, struct pubkey,
&x_local_delayed_payment_basepoint)); &x_local_delayed_payment_basepoint));
if (!pubkey_from_privkey(&x_local_per_commitment_secret, if (!pubkey_from_secret(&x_local_per_commitment_secret,
&x_local_per_commitment_point)) &x_local_per_commitment_point))
abort(); abort();
SUPERVERBOSE("INTERNAL: local_per_commitment_point: %s\n", SUPERVERBOSE("INTERNAL: local_per_commitment_point: %s\n",
type_to_string(tmpctx, struct pubkey, type_to_string(tmpctx, struct pubkey,
&x_local_per_commitment_point)); &x_local_per_commitment_point));
if (!pubkey_from_privkey(&x_local_payment_basepoint_secret, if (!pubkey_from_secret(&x_local_payment_basepoint_secret,
&local_payment_basepoint)) &local_payment_basepoint))
abort(); abort();
if (!pubkey_from_privkey(&x_remote_payment_basepoint_secret, if (!pubkey_from_secret(&x_remote_payment_basepoint_secret,
&remote_payment_basepoint)) &remote_payment_basepoint))
abort(); abort();
if (!derive_simple_privkey(&x_remote_payment_basepoint_secret, if (!derive_simple_privkey(&x_remote_payment_basepoint_secret,

16
lightningd/test/run-cryptomsg.c

@ -59,20 +59,20 @@ static struct io_plan *check_msg_read(struct io_conn *conn, struct peer *peer,
return NULL; return NULL;
} }
static struct sha256 sha256_from_hex(const char *hex) static struct secret secret_from_hex(const char *hex)
{ {
struct sha256 sha256; struct secret secret;
hex += 2; hex += 2;
if (!hex_decode(hex, strlen(hex), &sha256, sizeof(sha256))) if (!hex_decode(hex, strlen(hex), &secret, sizeof(secret)))
abort(); abort();
return sha256; return secret;
} }
int main(void) int main(void)
{ {
tal_t *tmpctx = tal_tmpctx(NULL); tal_t *tmpctx = tal_tmpctx(NULL);
struct peer_crypto_state cs_out, cs_in; struct peer_crypto_state cs_out, cs_in;
struct sha256 sk, rk, ck; struct secret sk, rk, ck;
const void *msg = tal_dup_arr(tmpctx, char, "hello", 5, 0); const void *msg = tal_dup_arr(tmpctx, char, "hello", 5, 0);
size_t i; size_t i;
@ -89,9 +89,9 @@ int main(void)
* # HKDF(0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01,zero) * # HKDF(0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01,zero)
* output: sk,rk=0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9,0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442 * output: sk,rk=0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9,0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442
*/ */
ck = sha256_from_hex("0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"); ck = secret_from_hex("0x919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01");
sk = sha256_from_hex("0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9"); sk = secret_from_hex("0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9");
rk = sha256_from_hex("0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442"); rk = secret_from_hex("0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442");
cs_out.cs.sn = cs_out.cs.rn = cs_in.cs.sn = cs_in.cs.rn = 0; cs_out.cs.sn = cs_out.cs.rn = cs_in.cs.sn = cs_in.cs.rn = 0;
cs_out.cs.sk = cs_in.cs.rk = sk; cs_out.cs.sk = cs_in.cs.rk = sk;

23
lightningd/test/run-key_derive.c

@ -10,35 +10,40 @@ static void *tmpctx;
#include <stdio.h> #include <stdio.h>
#include <type_to_string.h> #include <type_to_string.h>
static struct privkey privkey_from_hex(const char *hex) static struct secret secret_from_hex(const char *hex)
{ {
struct privkey privkey; struct secret s;
hex += 2; hex += 2;
if (!hex_decode(hex, strlen(hex), &privkey, sizeof(privkey))) if (!hex_decode(hex, strlen(hex), &s, sizeof(s)))
abort(); abort();
return privkey; return s;
} }
int main(void) int main(void)
{ {
struct privkey base_secret, per_commitment_secret, privkey; struct privkey privkey;
struct secret base_secret, per_commitment_secret;
struct pubkey base_point, per_commitment_point, pubkey, pubkey2; struct pubkey base_point, per_commitment_point, pubkey, pubkey2;
tmpctx = tal_tmpctx(NULL); tmpctx = tal_tmpctx(NULL);
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN); | SECP256K1_CONTEXT_SIGN);
base_secret = privkey_from_hex("0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); base_secret = secret_from_hex("0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
per_commitment_secret = privkey_from_hex("0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100"); per_commitment_secret = secret_from_hex("0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100");
printf("base_secret: 0x%s\n", printf("base_secret: 0x%s\n",
tal_hexstr(tmpctx, &base_secret, sizeof(base_secret))); tal_hexstr(tmpctx, &base_secret, sizeof(base_secret)));
printf("per_commitment_secret: 0x%s\n", printf("per_commitment_secret: 0x%s\n",
tal_hexstr(tmpctx, &per_commitment_secret, tal_hexstr(tmpctx, &per_commitment_secret,
sizeof(per_commitment_secret))); sizeof(per_commitment_secret)));
if (!pubkey_from_privkey(&per_commitment_secret, &per_commitment_point)) if (!secp256k1_ec_pubkey_create(secp256k1_ctx,
&per_commitment_point.pubkey,
per_commitment_secret.data))
abort(); abort();
if (!pubkey_from_privkey(&base_secret, &base_point)) if (!secp256k1_ec_pubkey_create(secp256k1_ctx,
&base_point.pubkey,
base_secret.data))
abort(); abort();
printf("base_point: 0x%s\n", printf("base_point: 0x%s\n",
type_to_string(tmpctx, struct pubkey, &base_point)); type_to_string(tmpctx, struct pubkey, &base_point));

26
test/test_sphinx.c

@ -14,6 +14,14 @@
secp256k1_context *secp256k1_ctx; secp256k1_context *secp256k1_ctx;
static struct secret secret_from_hex(const char *hex)
{
struct secret s;
if (!hex_decode(hex, strlen(hex), &s, sizeof(s)))
abort();
return s;
}
/* Create an onionreply with the test vector parameters and check that /* Create an onionreply with the test vector parameters and check that
* we match the test vectors and that we can also unwrap it. */ * we match the test vectors and that we can also unwrap it. */
static void run_unit_tests(void) static void run_unit_tests(void)
@ -31,12 +39,12 @@ static void run_unit_tests(void)
"21e13c2d7cfe7e18836df50872466117a295783ab8aab0e7ecc8c725503ad02d", "21e13c2d7cfe7e18836df50872466117a295783ab8aab0e7ecc8c725503ad02d",
"b5756b9b542727dbafc6765a49488b023a725d631af688fc031217e90770c328", "b5756b9b542727dbafc6765a49488b023a725d631af688fc031217e90770c328",
}; };
u8 *ss[] = { struct secret ss[] = {
tal_hexdata(tmpctx, secrets[0], 64), secret_from_hex(secrets[0]),
tal_hexdata(tmpctx, secrets[1], 64), secret_from_hex(secrets[1]),
tal_hexdata(tmpctx, secrets[2], 64), secret_from_hex(secrets[2]),
tal_hexdata(tmpctx, secrets[3], 64), secret_from_hex(secrets[3]),
tal_hexdata(tmpctx, secrets[4], 64), secret_from_hex(secrets[4])
}; };
int replylen = 164 * 2; int replylen = 164 * 2;
@ -90,10 +98,10 @@ static void run_unit_tests(void)
replylen), replylen),
}; };
reply = create_onionreply(tmpctx, ss[4], raw); reply = create_onionreply(tmpctx, &ss[4], raw);
for (int i = 4; i >= 0; i--) { for (int i = 4; i >= 0; i--) {
printf("input_packet %s\n", tal_hex(tmpctx, reply)); printf("input_packet %s\n", tal_hex(tmpctx, reply));
reply = wrap_onionreply(tmpctx, ss[i], reply); reply = wrap_onionreply(tmpctx, &ss[i], reply);
printf("obfuscated_packet %s\n", tal_hex(tmpctx, reply)); printf("obfuscated_packet %s\n", tal_hex(tmpctx, reply));
assert(memcmp(reply, intermediates[i], tal_len(reply)) == 0); assert(memcmp(reply, intermediates[i], tal_len(reply)) == 0);
} }
@ -140,7 +148,7 @@ int main(int argc, char **argv)
u8 privkeys[argc - 1][32]; u8 privkeys[argc - 1][32];
u8 sessionkey[32]; u8 sessionkey[32];
struct hop_data hops_data[num_hops]; struct hop_data hops_data[num_hops];
struct sha256 *shared_secrets; struct secret *shared_secrets;
memset(&sessionkey, 'A', sizeof(sessionkey)); memset(&sessionkey, 'A', sizeof(sessionkey));

1
type_to_string.h

@ -21,6 +21,7 @@ union printable_types {
const secp256k1_pubkey *secp256k1_pubkey; const secp256k1_pubkey *secp256k1_pubkey;
const struct channel_id *channel_id; const struct channel_id *channel_id;
const struct short_channel_id *short_channel_id; const struct short_channel_id *short_channel_id;
const struct secret *secret;
const struct privkey *privkey; const struct privkey *privkey;
const secp256k1_ecdsa_signature *secp256k1_ecdsa_signature; const secp256k1_ecdsa_signature *secp256k1_ecdsa_signature;
const struct channel *channel; const struct channel *channel;

7
wire/fromwire.c

@ -106,9 +106,14 @@ void fromwire_pubkey(const u8 **cursor, size_t *max, struct pubkey *pubkey)
fail_pull(cursor, max); fail_pull(cursor, max);
} }
void fromwire_secret(const u8 **cursor, size_t *max, struct secret *secret)
{
fromwire(cursor, max, secret->data, sizeof(secret->data));
}
void fromwire_privkey(const u8 **cursor, size_t *max, struct privkey *privkey) void fromwire_privkey(const u8 **cursor, size_t *max, struct privkey *privkey)
{ {
fromwire(cursor, max, privkey->secret, sizeof(privkey->secret)); fromwire_secret(cursor, max, &privkey->secret);
} }
void fromwire_secp256k1_ecdsa_signature(const u8 **cursor, void fromwire_secp256k1_ecdsa_signature(const u8 **cursor,

7
wire/towire.c

@ -58,9 +58,14 @@ void towire_pubkey(u8 **pptr, const struct pubkey *pubkey)
towire(pptr, output, outputlen); towire(pptr, output, outputlen);
} }
void towire_secret(u8 **pptr, const struct secret *secret)
{
towire(pptr, secret->data, sizeof(secret->data));
}
void towire_privkey(u8 **pptr, const struct privkey *privkey) void towire_privkey(u8 **pptr, const struct privkey *privkey)
{ {
towire(pptr, privkey->secret, sizeof(privkey->secret)); towire_secret(pptr, &privkey->secret);
} }
void towire_secp256k1_ecdsa_signature(u8 **pptr, void towire_secp256k1_ecdsa_signature(u8 **pptr,

2
wire/wire.h

@ -31,6 +31,7 @@ int fromwire_peektype(const u8 *cursor);
void towire(u8 **pptr, const void *data, size_t len); void towire(u8 **pptr, const void *data, size_t len);
void towire_pubkey(u8 **pptr, const struct pubkey *pubkey); void towire_pubkey(u8 **pptr, const struct pubkey *pubkey);
void towire_privkey(u8 **pptr, const struct privkey *privkey); void towire_privkey(u8 **pptr, const struct privkey *privkey);
void towire_secret(u8 **pptr, const struct secret *secret);
void towire_secp256k1_ecdsa_signature(u8 **pptr, void towire_secp256k1_ecdsa_signature(u8 **pptr,
const secp256k1_ecdsa_signature *signature); const secp256k1_ecdsa_signature *signature);
void towire_channel_id(u8 **pptr, const struct channel_id *channel_id); void towire_channel_id(u8 **pptr, const struct channel_id *channel_id);
@ -55,6 +56,7 @@ u16 fromwire_u16(const u8 **cursor, size_t *max);
u32 fromwire_u32(const u8 **cursor, size_t *max); u32 fromwire_u32(const u8 **cursor, size_t *max);
u64 fromwire_u64(const u8 **cursor, size_t *max); u64 fromwire_u64(const u8 **cursor, size_t *max);
bool fromwire_bool(const u8 **cursor, size_t *max); bool fromwire_bool(const u8 **cursor, size_t *max);
void fromwire_secret(const u8 **cursor, size_t *max, struct secret *secret);
void fromwire_privkey(const u8 **cursor, size_t *max, struct privkey *privkey); void fromwire_privkey(const u8 **cursor, size_t *max, struct privkey *privkey);
void fromwire_pubkey(const u8 **cursor, size_t *max, struct pubkey *pubkey); void fromwire_pubkey(const u8 **cursor, size_t *max, struct pubkey *pubkey);
void fromwire_secp256k1_ecdsa_signature(const u8 **cursor, size_t *max, void fromwire_secp256k1_ecdsa_signature(const u8 **cursor, size_t *max,

Loading…
Cancel
Save