From f2d835522c722ccedb7eafb7845b1f6d4ac7b263 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 1 Jul 2016 11:27:57 +0930 Subject: [PATCH] bitcoin: implement sig_valid. Update libsecp256k1 has a normalize function, which allows us to test if the signature was in low-S form. Signed-off-by: Rusty Russell --- bitcoin/signature.c | 9 ++++++--- bitcoin/signature.h | 2 +- daemon/cryptopkt.c | 5 +++-- daemon/packets.c | 9 +++++---- daemon/peer.c | 2 +- protobuf_convert.c | 12 ++++++++---- protobuf_convert.h | 8 ++++++-- 7 files changed, 30 insertions(+), 17 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 54b14d551..f669b5460 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -252,8 +252,11 @@ size_t signature_to_der(secp256k1_context *secpctx, } /* Signature must have low S value. */ -bool sig_valid(const struct signature *sig) +bool sig_valid(secp256k1_context *secpctx, const struct signature *sig) { - /* FIXME! Need libsecp support. */ - return true; + secp256k1_ecdsa_signature tmp; + + if (secp256k1_ecdsa_signature_normalize(secpctx, &tmp, &sig->sig) == 0) + return true; + return false; } diff --git a/bitcoin/signature.h b/bitcoin/signature.h index dca6c3388..d2251ca94 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -52,7 +52,7 @@ bool check_tx_sig(secp256k1_context *secpctx, const struct bitcoin_signature *sig); /* Signature must have low S value. */ -bool sig_valid(const struct signature *s); +bool sig_valid(secp256k1_context *secpctx, const struct signature *sig); /* Give DER encoding of signature: returns length used (<= 72). */ size_t signature_to_der(secp256k1_context *secpctx, diff --git a/daemon/cryptopkt.c b/daemon/cryptopkt.c index db9464040..687810192 100644 --- a/daemon/cryptopkt.c +++ b/daemon/cryptopkt.c @@ -356,7 +356,8 @@ static struct io_plan *check_proof(struct io_conn *conn, struct peer *peer) if (!auth) return io_close(conn); - if (!proto_to_signature(auth->session_sig, &sig)) { + if (!proto_to_signature(peer->dstate->secpctx, auth->session_sig, + &sig)) { log_unusual(peer->log, "Invalid auth signature"); return io_close(conn); } @@ -428,7 +429,7 @@ static Pkt *authenticate_pkt(const tal_t *ctx, Authenticate *auth = tal(ctx, Authenticate); authenticate__init(auth); auth->node_id = pubkey_to_proto(auth, secpctx, node_id); - auth->session_sig = signature_to_proto(auth, sig); + auth->session_sig = signature_to_proto(auth, secpctx, sig); return pkt_wrap(ctx, auth, PKT__PKT_AUTH); } diff --git a/daemon/packets.c b/daemon/packets.c index f071e5450..60578e0b6 100644 --- a/daemon/packets.c +++ b/daemon/packets.c @@ -146,7 +146,8 @@ void queue_pkt_open_commit_sig(struct peer *peer) peer->remote.commit->sig->stype = SIGHASH_ALL; peer_sign_theircommit(peer, peer->remote.commit->tx, &peer->remote.commit->sig->sig); - s->sig = signature_to_proto(s, &peer->remote.commit->sig->sig); + s->sig = signature_to_proto(s, peer->dstate->secpctx, + &peer->remote.commit->sig->sig); queue_pkt(peer, PKT__PKT_OPEN_COMMIT_SIG, s); } @@ -304,7 +305,7 @@ void queue_pkt_commit(struct peer *peer) /* Now send message */ update_commit__init(u); - u->sig = signature_to_proto(u, &ci->sig->sig); + u->sig = signature_to_proto(u, peer->dstate->secpctx, &ci->sig->sig); queue_pkt(peer, PKT__PKT_UPDATE_COMMIT, u); } @@ -456,7 +457,7 @@ void queue_pkt_close_signature(struct peer *peer) close_tx = peer_create_close_tx(peer, peer->closing.our_fee); peer_sign_mutual_close(peer, close_tx, &our_close_sig); - c->sig = signature_to_proto(c, &our_close_sig); + c->sig = signature_to_proto(c, peer->dstate->secpctx, &our_close_sig); c->close_fee = peer->closing.our_fee; log_info(peer->log, "queue_pkt_close_signature: offered close fee %" PRIu64, c->close_fee); @@ -530,7 +531,7 @@ static Pkt *check_and_save_commit_sig(struct peer *peer, assert(!ci->sig); sig->stype = SIGHASH_ALL; - if (!proto_to_signature(pb, &sig->sig)) + if (!proto_to_signature(peer->dstate->secpctx, pb, &sig->sig)) return pkt_err(peer, "Malformed signature"); log_debug(peer->log, "Checking sig for %u/%u msatoshis, %zu/%zu htlcs", diff --git a/daemon/peer.c b/daemon/peer.c index 4ccce98ad..446e624ae 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -268,7 +268,7 @@ static bool closing_pkt_in(struct peer *peer, const Pkt *pkt) * transaction with the given `close_fee`, and MUST fail the * connection if it is not. */ theirsig.stype = SIGHASH_ALL; - if (!proto_to_signature(c->sig, &theirsig.sig)) + if (!proto_to_signature(peer->dstate->secpctx, c->sig, &theirsig.sig)) return peer_comms_err(peer, pkt_err(peer, "Invalid signature format")); diff --git a/protobuf_convert.c b/protobuf_convert.c index 223f20319..46b4e679c 100644 --- a/protobuf_convert.c +++ b/protobuf_convert.c @@ -4,12 +4,14 @@ #include "protobuf_convert.h" #include -Signature *signature_to_proto(const tal_t *ctx, const struct signature *sig) +Signature *signature_to_proto(const tal_t *ctx, + secp256k1_context *secpctx, + const struct signature *sig) { Signature *pb = tal(ctx, Signature); signature__init(pb); - assert(sig_valid(sig)); + assert(sig_valid(secpctx, sig)); /* FIXME: Need a portable way to encode signatures in libsecp! */ @@ -26,7 +28,9 @@ Signature *signature_to_proto(const tal_t *ctx, const struct signature *sig) return pb; } -bool proto_to_signature(const Signature *pb, struct signature *sig) +bool proto_to_signature(secp256k1_context *secpctx, + const Signature *pb, + struct signature *sig) { /* Kill me again. */ /* FIXME: Need a portable way to encode signatures in libsecp! */ @@ -40,7 +44,7 @@ bool proto_to_signature(const Signature *pb, struct signature *sig) memcpy(sig->sig.data + 48, &pb->s3, 8); memcpy(sig->sig.data + 56, &pb->s4, 8); - return sig_valid(sig); + return sig_valid(secpctx, sig); } BitcoinPubkey *pubkey_to_proto(const tal_t *ctx, diff --git a/protobuf_convert.h b/protobuf_convert.h index 0a12c3a2d..de6e49846 100644 --- a/protobuf_convert.h +++ b/protobuf_convert.h @@ -8,8 +8,12 @@ /* Convert to-from protobuf to internal representation. */ struct signature; -Signature *signature_to_proto(const tal_t *ctx, const struct signature *sig); -bool proto_to_signature(const Signature *pb, struct signature *sig); +Signature *signature_to_proto(const tal_t *ctx, + secp256k1_context *secpctx, + const struct signature *sig); +bool proto_to_signature(secp256k1_context *secpctx, + const Signature *pb, + struct signature *sig); /* Convert to-from protobuf to internal representation. */ struct pubkey;