brontide: implement handshake versioning enforcement per the spec
This commit is contained in:
parent
71c6e837e3
commit
60f66fe2d7
@ -47,9 +47,11 @@ func Dial(localPriv *btcec.PrivateKey, netAddr *lnwire.NetAddress) (*Conn, error
|
|||||||
// Initiate the handshake by sending the first act to the receiver.
|
// Initiate the handshake by sending the first act to the receiver.
|
||||||
actOne, err := b.noise.GenActOne()
|
actOne, err := b.noise.GenActOne()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
b.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, err := conn.Write(actOne[:]); err != nil {
|
if _, err := conn.Write(actOne[:]); err != nil {
|
||||||
|
b.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,9 +61,11 @@ func Dial(localPriv *btcec.PrivateKey, netAddr *lnwire.NetAddress) (*Conn, error
|
|||||||
// secrecy.
|
// secrecy.
|
||||||
var actTwo [ActTwoSize]byte
|
var actTwo [ActTwoSize]byte
|
||||||
if _, err := io.ReadFull(conn, actTwo[:]); err != nil {
|
if _, err := io.ReadFull(conn, actTwo[:]); err != nil {
|
||||||
|
b.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := b.noise.RecvActTwo(actTwo); err != nil {
|
if err := b.noise.RecvActTwo(actTwo); err != nil {
|
||||||
|
b.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,9 +73,11 @@ func Dial(localPriv *btcec.PrivateKey, netAddr *lnwire.NetAddress) (*Conn, error
|
|||||||
// key and execute the final ECDH operation.
|
// key and execute the final ECDH operation.
|
||||||
actThree, err := b.noise.GenActThree()
|
actThree, err := b.noise.GenActThree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
b.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, err := conn.Write(actThree[:]); err != nil {
|
if _, err := conn.Write(actThree[:]); err != nil {
|
||||||
|
b.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +64,11 @@ func (l *Listener) Accept() (net.Conn, error) {
|
|||||||
// this portion will fail with a non-nil error.
|
// this portion will fail with a non-nil error.
|
||||||
var actOne [ActOneSize]byte
|
var actOne [ActOneSize]byte
|
||||||
if _, err := io.ReadFull(conn, actOne[:]); err != nil {
|
if _, err := io.ReadFull(conn, actOne[:]); err != nil {
|
||||||
|
brontideConn.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := brontideConn.noise.RecvActOne(actOne); err != nil {
|
if err := brontideConn.noise.RecvActOne(actOne); err != nil {
|
||||||
|
brontideConn.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,9 +76,11 @@ func (l *Listener) Accept() (net.Conn, error) {
|
|||||||
// key for the session along with an authenticating tag.
|
// key for the session along with an authenticating tag.
|
||||||
actTwo, err := brontideConn.noise.GenActTwo()
|
actTwo, err := brontideConn.noise.GenActTwo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
brontideConn.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, err := conn.Write(actTwo[:]); err != nil {
|
if _, err := conn.Write(actTwo[:]); err != nil {
|
||||||
|
brontideConn.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,9 +89,11 @@ func (l *Listener) Accept() (net.Conn, error) {
|
|||||||
// sides have mutually authenticated each other.
|
// sides have mutually authenticated each other.
|
||||||
var actThree [ActThreeSize]byte
|
var actThree [ActThreeSize]byte
|
||||||
if _, err := io.ReadFull(conn, actThree[:]); err != nil {
|
if _, err := io.ReadFull(conn, actThree[:]); err != nil {
|
||||||
|
brontideConn.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := brontideConn.noise.RecvActThree(actThree); err != nil {
|
if err := brontideConn.noise.RecvActThree(actThree); err != nil {
|
||||||
|
brontideConn.conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
@ -330,30 +331,34 @@ func NewBrontideMachine(initiator bool, localPub *btcec.PrivateKey,
|
|||||||
return &BrontideMachine{handshakeState: handshake}
|
return &BrontideMachine{handshakeState: handshake}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): add version bytes, paramterize in constructor above
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// HandshakeVersion is the expected version of the brontide handshake.
|
||||||
|
// Any messages that carry a different version will cause the handshake
|
||||||
|
// to abort immediately.
|
||||||
|
HandshakeVersion = byte(0)
|
||||||
|
|
||||||
// ActOneSize is the size of the packet sent from initiator to
|
// ActOneSize is the size of the packet sent from initiator to
|
||||||
// responder in ActOne. The packet consists of an ephemeral key in
|
// responder in ActOne. The packet consists of a handshake version, an
|
||||||
// compressed format, and a 16-byte poly1305 tag.
|
// ephemeral key in compressed format, and a 16-byte poly1305 tag.
|
||||||
//
|
//
|
||||||
// 33 + 16
|
// 1 + 33 + 16
|
||||||
ActOneSize = 49
|
ActOneSize = 50
|
||||||
|
|
||||||
// ActTwoSize is the size the packet sent from responder to initiator
|
// ActTwoSize is the size the packet sent from responder to initiator
|
||||||
// in ActTwo. The packet consists of an ephemeral key in compressed
|
// in ActTwo. The packet consists of a handshake version, an ephemeral
|
||||||
// format and a 16-byte poly1305 tag.
|
// key in compressed format and a 16-byte poly1305 tag.
|
||||||
//
|
//
|
||||||
// 33 + 16
|
// 1 + 33 + 16
|
||||||
ActTwoSize = 49
|
ActTwoSize = 50
|
||||||
|
|
||||||
// ActThreeSize is the size of the packet sent from initiator to
|
// ActThreeSize is the size of the packet sent from initiator to
|
||||||
// responder in ActThree. The packet consists of the initiators static
|
// responder in ActThree. The packet consists of a handshake version,
|
||||||
// key encrypted with strong forward secrecy and a 16-byte poly1035
|
// the initiators static key encrypted with strong forward secrecy and
|
||||||
|
// a 16-byte poly1035
|
||||||
// tag.
|
// tag.
|
||||||
//
|
//
|
||||||
// 33 + 16 + 16
|
// 1 + 33 + 16 + 16
|
||||||
ActThreeSize = 65
|
ActThreeSize = 66
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenActOne generates the initial packet (act one) to be sent from initiator
|
// GenActOne generates the initial packet (act one) to be sent from initiator
|
||||||
@ -384,8 +389,9 @@ func (b *BrontideMachine) GenActOne() ([ActOneSize]byte, error) {
|
|||||||
|
|
||||||
authPayload := b.EncryptAndHash([]byte{})
|
authPayload := b.EncryptAndHash([]byte{})
|
||||||
|
|
||||||
copy(actOne[:33], ephemeral)
|
actOne[0] = HandshakeVersion
|
||||||
copy(actOne[33:], authPayload)
|
copy(actOne[1:34], ephemeral)
|
||||||
|
copy(actOne[34:], authPayload)
|
||||||
|
|
||||||
return actOne, nil
|
return actOne, nil
|
||||||
}
|
}
|
||||||
@ -401,8 +407,15 @@ func (b *BrontideMachine) RecvActOne(actOne [ActOneSize]byte) error {
|
|||||||
p [16]byte
|
p [16]byte
|
||||||
)
|
)
|
||||||
|
|
||||||
copy(e[:], actOne[:33])
|
// If the handshake version is unknown, then the handshake fails
|
||||||
copy(p[:], actOne[33:])
|
// immediately.
|
||||||
|
if actOne[0] != HandshakeVersion {
|
||||||
|
return fmt.Errorf("Invalid handshake version: %v, only %v is "+
|
||||||
|
"valid", actOne[0], HandshakeVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(e[:], actOne[1:34])
|
||||||
|
copy(p[:], actOne[34:])
|
||||||
|
|
||||||
// e
|
// e
|
||||||
b.remoteEphemeral, err = btcec.ParsePubKey(e[:], btcec.S256())
|
b.remoteEphemeral, err = btcec.ParsePubKey(e[:], btcec.S256())
|
||||||
@ -451,8 +464,9 @@ func (b *BrontideMachine) GenActTwo() ([ActTwoSize]byte, error) {
|
|||||||
|
|
||||||
authPayload := b.EncryptAndHash([]byte{})
|
authPayload := b.EncryptAndHash([]byte{})
|
||||||
|
|
||||||
copy(actTwo[:33], ephemeral)
|
actTwo[0] = HandshakeVersion
|
||||||
copy(actTwo[33:], authPayload)
|
copy(actTwo[1:34], ephemeral)
|
||||||
|
copy(actTwo[34:], authPayload)
|
||||||
|
|
||||||
return actTwo, nil
|
return actTwo, nil
|
||||||
}
|
}
|
||||||
@ -467,8 +481,15 @@ func (b *BrontideMachine) RecvActTwo(actTwo [ActTwoSize]byte) error {
|
|||||||
p [16]byte
|
p [16]byte
|
||||||
)
|
)
|
||||||
|
|
||||||
copy(e[:], actTwo[:33])
|
// If the handshake version is unknown, then the handshake fails
|
||||||
copy(p[:], actTwo[33:])
|
// immediately.
|
||||||
|
if actTwo[0] != HandshakeVersion {
|
||||||
|
return fmt.Errorf("Invalid handshake version: %v, only %v is "+
|
||||||
|
"valid", actTwo[0], HandshakeVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(e[:], actTwo[1:34])
|
||||||
|
copy(p[:], actTwo[34:])
|
||||||
|
|
||||||
// e
|
// e
|
||||||
b.remoteEphemeral, err = btcec.ParsePubKey(e[:], btcec.S256())
|
b.remoteEphemeral, err = btcec.ParsePubKey(e[:], btcec.S256())
|
||||||
@ -506,8 +527,9 @@ func (b *BrontideMachine) GenActThree() ([ActThreeSize]byte, error) {
|
|||||||
|
|
||||||
authPayload := b.EncryptAndHash([]byte{})
|
authPayload := b.EncryptAndHash([]byte{})
|
||||||
|
|
||||||
copy(actThree[:49], ciphertext)
|
actThree[0] = HandshakeVersion
|
||||||
copy(actThree[49:], authPayload)
|
copy(actThree[1:50], ciphertext)
|
||||||
|
copy(actThree[50:], authPayload)
|
||||||
|
|
||||||
// With the final ECDH operation complete, derive the session sending
|
// With the final ECDH operation complete, derive the session sending
|
||||||
// and receiving keys.
|
// and receiving keys.
|
||||||
@ -527,8 +549,15 @@ func (b *BrontideMachine) RecvActThree(actThree [ActThreeSize]byte) error {
|
|||||||
p [16]byte
|
p [16]byte
|
||||||
)
|
)
|
||||||
|
|
||||||
copy(s[:], actThree[:33+16])
|
// If the handshake version is unknown, then the handshake fails
|
||||||
copy(p[:], actThree[33+16:])
|
// immediately.
|
||||||
|
if actThree[0] != HandshakeVersion {
|
||||||
|
return fmt.Errorf("Invalid handshake version: %v, only %v is "+
|
||||||
|
"valid", actThree[0], HandshakeVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(s[:], actThree[1:33+16+1])
|
||||||
|
copy(p[:], actThree[33+16+1:])
|
||||||
|
|
||||||
// s
|
// s
|
||||||
remotePub, err := b.DecryptAndHash(s[:])
|
remotePub, err := b.DecryptAndHash(s[:])
|
||||||
|
@ -46,16 +46,17 @@ func establishTestConnection() (net.Conn, net.Conn, error) {
|
|||||||
connChan := make(chan net.Conn)
|
connChan := make(chan net.Conn)
|
||||||
go func() {
|
go func() {
|
||||||
conn, err := Dial(remotePriv, netAddr)
|
conn, err := Dial(remotePriv, netAddr)
|
||||||
|
|
||||||
errChan <- err
|
errChan <- err
|
||||||
connChan <- conn
|
connChan <- conn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
localConn, listenErr := listener.Accept()
|
localConn, listenErr := listener.Accept()
|
||||||
if listenErr != nil {
|
if listenErr != nil {
|
||||||
return nil, nil, err
|
return nil, nil, listenErr
|
||||||
}
|
}
|
||||||
|
|
||||||
if dialErr := <-errChan; err != nil {
|
if dialErr := <-errChan; dialErr != nil {
|
||||||
return nil, nil, dialErr
|
return nil, nil, dialErr
|
||||||
}
|
}
|
||||||
remoteConn := <-connChan
|
remoteConn := <-connChan
|
||||||
|
Loading…
Reference in New Issue
Block a user