Skip to content

Commit 66de6b8

Browse files
rustyrussellcdecker
authored andcommitted
channeld: use pointer for shared secret.
It's more natural than using a zero-secret when something goes wrong. Also note that the HSM will actually kill the connection if the ECDH fails, which is fortunately statistically unlikely. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 7e01efb commit 66de6b8

File tree

8 files changed

+69
-52
lines changed

8 files changed

+69
-52
lines changed

channeld/channeld.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -527,29 +527,26 @@ static void handle_peer_announcement_signatures(struct peer *peer, const u8 *msg
527527
channel_announcement_negotiate(peer);
528528
}
529529

530-
static bool get_shared_secret(const struct htlc *htlc,
531-
struct secret *shared_secret)
530+
static struct secret *get_shared_secret(const tal_t *ctx,
531+
const struct htlc *htlc)
532532
{
533533
struct pubkey ephemeral;
534534
struct onionpacket *op;
535+
struct secret *secret = tal(ctx, struct secret);
535536
const u8 *msg;
536537

537538
/* We unwrap the onion now. */
538539
op = parse_onionpacket(tmpctx, htlc->routing, TOTAL_PACKET_SIZE);
539-
if (!op) {
540-
/* Return an invalid shared secret. */
541-
memset(shared_secret, 0, sizeof(*shared_secret));
542-
return false;
543-
}
540+
if (!op)
541+
return tal_free(secret);
544542

545543
/* Because wire takes struct pubkey. */
546544
ephemeral.pubkey = op->ephemeralkey;
547545
msg = hsm_req(tmpctx, towire_hsm_ecdh_req(tmpctx, &ephemeral));
548-
if (!fromwire_hsm_ecdh_resp(msg, shared_secret))
546+
if (!fromwire_hsm_ecdh_resp(msg, secret))
549547
status_failed(STATUS_FAIL_HSM_IO, "Reading ecdh response");
550548

551-
/* Gives all-zero shares_secret if it was invalid. */
552-
return !memeqzero(shared_secret, sizeof(*shared_secret));
549+
return secret;
553550
}
554551

555552
static void handle_peer_add_htlc(struct peer *peer, const u8 *msg)
@@ -581,8 +578,7 @@ static void handle_peer_add_htlc(struct peer *peer, const u8 *msg)
581578

582579
/* If this is wrong, we don't complain yet; when it's confirmed we'll
583580
* send it to the master which handles all HTLC failures. */
584-
htlc->shared_secret = tal(htlc, struct secret);
585-
get_shared_secret(htlc, htlc->shared_secret);
581+
htlc->shared_secret = get_shared_secret(htlc, htlc);
586582
}
587583

588584
static void handle_peer_feechange(struct peer *peer, const u8 *msg)
@@ -1215,7 +1211,12 @@ static u8 *got_commitsig_msg(const tal_t *ctx,
12151211
memcpy(a->onion_routing_packet,
12161212
htlc->routing,
12171213
sizeof(a->onion_routing_packet));
1218-
*s = *htlc->shared_secret;
1214+
/* Invalid shared secret gets set to all-zero: our
1215+
* code generator can't make arrays of optional values */
1216+
if (!htlc->shared_secret)
1217+
memset(s, 0, sizeof(*s));
1218+
else
1219+
*s = *htlc->shared_secret;
12191220
} else if (htlc->state == RCVD_REMOVE_COMMIT) {
12201221
if (htlc->r) {
12211222
struct fulfilled_htlc *f;
@@ -2589,8 +2590,7 @@ static void init_shared_secrets(struct channel *channel,
25892590
continue;
25902591

25912592
htlc = channel_get_htlc(channel, REMOTE, htlcs[i].id);
2592-
htlc->shared_secret = tal(htlc, struct secret);
2593-
get_shared_secret(htlc, htlc->shared_secret);
2593+
htlc->shared_secret = get_shared_secret(htlc, htlc);
25942594
}
25952595
}
25962596

connectd/connectd.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,18 +1445,24 @@ static struct io_plan *recv_req(struct io_conn *conn,
14451445
* knowledge of the HSM, but also at one stage I made a hacky gossip vampire
14461446
* tool which used the handshake code, so it's nice to keep that
14471447
* standalone. */
1448-
bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point)
1448+
struct secret *hsm_do_ecdh(const tal_t *ctx, const struct pubkey *point)
14491449
{
14501450
u8 *req = towire_hsm_ecdh_req(tmpctx, point), *resp;
1451+
struct secret *secret = tal(ctx, struct secret);
14511452

14521453
if (!wire_sync_write(HSM_FD, req))
1453-
return false;
1454+
return tal_free(secret);
14541455
resp = wire_sync_read(req, HSM_FD);
14551456
if (!resp)
1456-
return false;
1457-
if (!fromwire_hsm_ecdh_resp(resp, ss))
1458-
return false;
1459-
return true;
1457+
return tal_free(secret);
1458+
1459+
/* Note: hsmd will actually hang up on us if it can't ECDH: that implies
1460+
* that our node private key is invalid, and we shouldn't have made
1461+
* it this far. */
1462+
if (!fromwire_hsm_ecdh_resp(resp, secret))
1463+
return tal_free(secret);
1464+
1465+
return secret;
14601466
}
14611467

14621468
/*~ UNUSED is defined to an __attribute__ for GCC; at one stage we tried to use

connectd/handshake.c

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ struct handshake {
159159
struct secret temp_k;
160160
struct sha256 h;
161161
struct keypair e;
162-
struct secret ss;
162+
struct secret *ss;
163163

164164
/* Used between the Acts */
165165
struct pubkey re;
@@ -473,18 +473,19 @@ static struct io_plan *act_three_initiator(struct io_conn *conn,
473473
* * where `re` is the ephemeral public key of the responder
474474
*
475475
*/
476-
if (!hsm_do_ecdh(&h->ss, &h->re))
476+
h->ss = hsm_do_ecdh(h, &h->re);
477+
if (!h->ss)
477478
return handshake_failed(conn, h);
478479

479-
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, &h->ss, sizeof(h->ss)));
480+
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, h->ss, sizeof(*h->ss)));
480481

481482
/* BOLT #8:
482483
*
483484
* 4. `ck, temp_k3 = HKDF(ck, ss)`
484485
* * The final intermediate shared secret is mixed into the running
485486
* chaining key.
486487
*/
487-
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss));
488+
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, h->ss, sizeof(*h->ss));
488489
SUPERVERBOSE("# ck,temp_k3=0x%s,0x%s",
489490
tal_hexstr(tmpctx, &h->ck, sizeof(h->ck)),
490491
tal_hexstr(tmpctx, &h->temp_k, sizeof(h->temp_k)));
@@ -549,19 +550,19 @@ static struct io_plan *act_two_initiator2(struct io_conn *conn,
549550
* 5. `ss = ECDH(re, e.priv)`
550551
* * where `re` is the responder's ephemeral public key
551552
*/
552-
if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, &h->re.pubkey,
553+
if (!secp256k1_ecdh(secp256k1_ctx, h->ss->data, &h->re.pubkey,
553554
h->e.priv.secret.data))
554555
return handshake_failed(conn, h);
555556

556-
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, &h->ss, sizeof(h->ss)));
557+
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, h->ss, sizeof(*h->ss)));
557558

558559
/* BOLT #8:
559560
*
560561
* 6. `ck, temp_k2 = HKDF(ck, ss)`
561562
* * A new temporary encryption key is generated, which is
562563
* used to generate the authenticating MAC.
563564
*/
564-
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss));
565+
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, h->ss, sizeof(*h->ss));
565566
SUPERVERBOSE("# ck,temp_k2=0x%s,0x%s",
566567
tal_hexstr(tmpctx, &h->ck, sizeof(h->ck)),
567568
tal_hexstr(tmpctx, &h->temp_k, sizeof(h->temp_k)));
@@ -639,19 +640,20 @@ static struct io_plan *act_one_initiator(struct io_conn *conn,
639640
* * The initiator performs an ECDH between its newly generated
640641
* ephemeral key and the remote node's static public key.
641642
*/
642-
if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data,
643+
h->ss = tal(h, struct secret);
644+
if (!secp256k1_ecdh(secp256k1_ctx, h->ss->data,
643645
&h->their_id.pubkey, h->e.priv.secret.data))
644646
return handshake_failed(conn, h);
645647

646-
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, h->ss.data, sizeof(h->ss.data)));
648+
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, h->ss->data, sizeof(h->ss->data)));
647649

648650
/* BOLT #8:
649651
*
650652
* 4. `ck, temp_k1 = HKDF(ck, ss)`
651653
* * A new temporary encryption key is generated, which is
652654
* used to generate the authenticating MAC.
653655
*/
654-
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss));
656+
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, h->ss, sizeof(*h->ss));
655657
SUPERVERBOSE("# ck,temp_k1=0x%s,0x%s",
656658
tal_hexstr(tmpctx, &h->ck, sizeof(h->ck)),
657659
tal_hexstr(tmpctx, &h->temp_k, sizeof(h->temp_k)));
@@ -740,16 +742,16 @@ static struct io_plan *act_three_responder2(struct io_conn *conn,
740742
* 6. `ss = ECDH(rs, e.priv)`
741743
* * where `e` is the responder's original ephemeral key
742744
*/
743-
if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, &h->their_id.pubkey,
745+
if (!secp256k1_ecdh(secp256k1_ctx, h->ss->data, &h->their_id.pubkey,
744746
h->e.priv.secret.data))
745747
return handshake_failed(conn, h);
746748

747-
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, &h->ss, sizeof(h->ss)));
749+
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, h->ss, sizeof(*h->ss)));
748750

749751
/* BOLT #8:
750752
* 7. `ck, temp_k3 = HKDF(ck, ss)`
751753
*/
752-
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss));
754+
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, h->ss, sizeof(*h->ss));
753755
SUPERVERBOSE("# ck,temp_k3=0x%s,0x%s",
754756
tal_hexstr(tmpctx, &h->ck, sizeof(h->ck)),
755757
tal_hexstr(tmpctx, &h->temp_k, sizeof(h->temp_k)));
@@ -815,18 +817,18 @@ static struct io_plan *act_two_responder(struct io_conn *conn,
815817
* * where `re` is the ephemeral key of the initiator, which was
816818
* received during Act One
817819
*/
818-
if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, &h->re.pubkey,
820+
if (!secp256k1_ecdh(secp256k1_ctx, h->ss->data, &h->re.pubkey,
819821
h->e.priv.secret.data))
820822
return handshake_failed(conn, h);
821-
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, &h->ss, sizeof(h->ss)));
823+
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, h->ss, sizeof(*h->ss)));
822824

823825
/* BOLT #8:
824826
*
825827
* 4. `ck, temp_k2 = HKDF(ck, ss)`
826828
* * A new temporary encryption key is generated, which is
827829
* used to generate the authenticating MAC.
828830
*/
829-
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss));
831+
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, h->ss, sizeof(*h->ss));
830832
SUPERVERBOSE("# ck,temp_k2=0x%s,0x%s",
831833
tal_hexstr(tmpctx, &h->ck, sizeof(h->ck)),
832834
tal_hexstr(tmpctx, &h->temp_k, sizeof(h->temp_k)));
@@ -902,18 +904,19 @@ static struct io_plan *act_one_responder2(struct io_conn *conn,
902904
* * The responder performs an ECDH between its static private key and
903905
* the initiator's ephemeral public key.
904906
*/
905-
if (!hsm_do_ecdh(&h->ss, &h->re))
907+
h->ss = hsm_do_ecdh(h, &h->re);
908+
if (!h->ss)
906909
return handshake_failed(conn, h);
907910

908-
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, &h->ss, sizeof(h->ss)));
911+
SUPERVERBOSE("# ss=0x%s", tal_hexstr(tmpctx, h->ss, sizeof(*h->ss)));
909912

910913
/* BOLT #8:
911914
*
912915
* 6. `ck, temp_k1 = HKDF(ck, ss)`
913916
* * A new temporary encryption key is generated, which will
914917
* shortly be used to check the authenticating MAC.
915918
*/
916-
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss));
919+
hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, h->ss, sizeof(*h->ss));
917920
SUPERVERBOSE("# ck,temp_k1=0x%s,0x%s",
918921
tal_hexstr(tmpctx, &h->ck, sizeof(h->ck)),
919922
tal_hexstr(tmpctx, &h->temp_k, sizeof(h->temp_k)));

connectd/handshake.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef LIGHTNING_CONNECTD_HANDSHAKE_H
22
#define LIGHTNING_CONNECTD_HANDSHAKE_H
33
#include "config.h"
4+
#include <ccan/tal/tal.h>
45
#include <ccan/typesafe_cb/typesafe_cb.h>
56

67
struct crypto_state;
@@ -52,5 +53,5 @@ struct io_plan *responder_handshake_(struct io_conn *conn,
5253
void *cbarg);
5354

5455
/* helper which is defined in connect.c */
55-
bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point);
56+
struct secret *hsm_do_ecdh(const tal_t *ctx, const struct pubkey *point);
5657
#endif /* LIGHTNING_CONNECTD_HANDSHAKE_H */

connectd/test/run-initiator-success.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,13 @@ static struct io_plan *success(struct io_conn *conn UNUSED,
190190
exit(0);
191191
}
192192

193-
bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point)
193+
struct secret *hsm_do_ecdh(const tal_t *ctx, const struct pubkey *point)
194194
{
195-
return secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey,
196-
ls_priv.secret.data) == 1;
195+
struct secret *ss = tal(ctx, struct secret);
196+
if (secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey,
197+
ls_priv.secret.data) != 1)
198+
return tal_free(ss);
199+
return ss;
197200
}
198201

199202
int main(void)

connectd/test/run-responder-success.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,13 @@ static struct io_plan *success(struct io_conn *conn UNUSED,
187187
exit(0);
188188
}
189189

190-
bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point)
190+
struct secret *hsm_do_ecdh(const tal_t *ctx, const struct pubkey *point)
191191
{
192-
return secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey,
193-
ls_priv.secret.data) == 1;
192+
struct secret *ss = tal(ctx, struct secret);
193+
if (secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey,
194+
ls_priv.secret.data) != 1)
195+
return tal_free(ss);
196+
return ss;
194197
}
195198

196199
int main(void)

devtools/gossipwith.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,13 @@ void peer_failed_connection_lost(void)
7272
exit(0);
7373
}
7474

75-
bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point)
75+
struct secret *hsm_do_ecdh(const tal_t *ctx, const struct pubkey *point)
7676
{
77+
struct secret *ss = tal(ctx, struct secret);
7778
if (secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey,
7879
notsosecret.data) != 1)
79-
errx(1, "ECDH failed");
80-
return true;
80+
return tal_free(ss);
81+
return ss;
8182
}
8283

8384
/* We don't want to discard *any* messages. */

hsmd/hsmd.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,8 +554,8 @@ static struct io_plan *handle_ecdh(struct io_conn *conn,
554554
if (!fromwire_hsm_ecdh_req(msg_in, &point))
555555
return bad_req(conn, c, msg_in);
556556

557-
/*~ We simply use the secp256k1_ecdh function, which really shouldn't
558-
* fail (iff the point is invalid). */
557+
/*~ We simply use the secp256k1_ecdh function: if ss.data is invalid,
558+
* we kill them for bad randomness (~1 in 2^127 if ss.data is random) */
559559
node_key(&privkey, NULL);
560560
if (secp256k1_ecdh(secp256k1_ctx, ss.data, &point.pubkey,
561561
privkey.secret.data) != 1) {

0 commit comments

Comments
 (0)