Merge pull request #7127 from morehouse/native_fuzzing

brontide+lnwire+wtwire+zpay32: migrate fuzz tests
This commit is contained in:
Oliver Gugger 2022-11-11 16:26:03 +01:00 committed by GitHub
commit 404e18afab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 1763 additions and 2131 deletions

709
brontide/fuzz_test.go Normal file
View File

@ -0,0 +1,709 @@
package brontide
import (
"bytes"
"encoding/hex"
"math"
"testing"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/keychain"
)
var (
initBytes = []byte{
0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
0xd, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
}
respBytes = []byte{
0xaa, 0xb6, 0x37, 0xd9, 0xfc, 0xd2, 0xc6, 0xda,
0x63, 0x59, 0xe6, 0x99, 0x31, 0x13, 0xa1, 0x17,
0xd, 0xe7, 0x95, 0xe9, 0xb7, 0x25, 0xb8, 0x4d,
0x1e, 0xb, 0x4c, 0xf9, 0x9e, 0xc5, 0x8c, 0xe9,
}
// Returns the initiator's ephemeral private key.
initEphemeral = EphemeralGenerator(func() (*btcec.PrivateKey, error) {
e := "121212121212121212121212121212121212121212121212121212" +
"1212121212"
eBytes, err := hex.DecodeString(e)
if err != nil {
return nil, err
}
priv, _ := btcec.PrivKeyFromBytes(eBytes)
return priv, nil
})
// Returns the responder's ephemeral private key.
respEphemeral = EphemeralGenerator(func() (*btcec.PrivateKey, error) {
e := "222222222222222222222222222222222222222222222222222" +
"2222222222222"
eBytes, err := hex.DecodeString(e)
if err != nil {
return nil, err
}
priv, _ := btcec.PrivKeyFromBytes(eBytes)
return priv, nil
})
)
// completeHandshake takes two brontide machines (initiator, responder)
// and completes the brontide handshake between them. If any part of the
// handshake fails, this function will panic.
func completeHandshake(t *testing.T, initiator, responder *Machine) {
t.Helper()
if err := handshake(initiator, responder); err != nil {
nilAndPanic(t, initiator, responder, err)
}
}
// handshake actually completes the brontide handshake and bubbles up
// an error to the calling function.
func handshake(initiator, responder *Machine) error {
// Generate ActOne and send to the responder.
actOne, err := initiator.GenActOne()
if err != nil {
return err
}
if err := responder.RecvActOne(actOne); err != nil {
return err
}
// Generate ActTwo and send to initiator.
actTwo, err := responder.GenActTwo()
if err != nil {
return err
}
if err := initiator.RecvActTwo(actTwo); err != nil {
return err
}
// Generate ActThree and send to responder.
actThree, err := initiator.GenActThree()
if err != nil {
return err
}
return responder.RecvActThree(actThree)
}
// nilAndPanic first nils the initiator and responder's Curve fields and then
// panics.
func nilAndPanic(t *testing.T, initiator, responder *Machine, err error) {
t.Helper()
t.Fatalf("error: %v, initiator: %v, responder: %v", err,
spew.Sdump(initiator), spew.Sdump(responder))
}
// getBrontideMachines returns two brontide machines that use random keys
// everywhere.
func getBrontideMachines() (*Machine, *Machine) {
initPriv, _ := btcec.NewPrivateKey()
respPriv, _ := btcec.NewPrivateKey()
respPub := (respPriv.PubKey())
initPrivECDH := &keychain.PrivKeyECDH{PrivKey: initPriv}
respPrivECDH := &keychain.PrivKeyECDH{PrivKey: respPriv}
initiator := NewBrontideMachine(true, initPrivECDH, respPub)
responder := NewBrontideMachine(false, respPrivECDH, nil)
return initiator, responder
}
// getStaticBrontideMachines returns two brontide machines that use static keys
// everywhere.
func getStaticBrontideMachines() (*Machine, *Machine) {
initPriv, _ := btcec.PrivKeyFromBytes(initBytes)
respPriv, respPub := btcec.PrivKeyFromBytes(respBytes)
initPrivECDH := &keychain.PrivKeyECDH{PrivKey: initPriv}
respPrivECDH := &keychain.PrivKeyECDH{PrivKey: respPriv}
initiator := NewBrontideMachine(
true, initPrivECDH, respPub, initEphemeral,
)
responder := NewBrontideMachine(
false, respPrivECDH, nil, respEphemeral,
)
return initiator, responder
}
// FuzzRandomActOne fuzz tests ActOne in the brontide handshake.
func FuzzRandomActOne(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Check if data is large enough.
if len(data) < ActOneSize {
return
}
// This will return brontide machines with random keys.
_, responder := getBrontideMachines()
// Copy data into [ActOneSize]byte.
var actOne [ActOneSize]byte
copy(actOne[:], data)
// Responder receives ActOne, should fail on the MAC check.
if err := responder.RecvActOne(actOne); err == nil {
nilAndPanic(t, nil, responder, nil)
}
})
}
// FuzzRandomActThree fuzz tests ActThree in the brontide handshake.
func FuzzRandomActThree(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Check if data is large enough.
if len(data) < ActThreeSize {
return
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Generate ActOne and send to the responder.
actOne, err := initiator.GenActOne()
if err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Receiving ActOne should succeed, so we panic on error.
if err := responder.RecvActOne(actOne); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Generate ActTwo - this is not sent to the initiator because
// nothing is done with the initiator after this point and it
// would slow down fuzzing. GenActTwo needs to be called to set
// the appropriate state in the responder machine.
_, err = responder.GenActTwo()
if err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Copy data into [ActThreeSize]byte.
var actThree [ActThreeSize]byte
copy(actThree[:], data)
// Responder receives ActThree, should fail on the MAC check.
if err := responder.RecvActThree(actThree); err == nil {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzRandomActTwo fuzz tests ActTwo in the brontide handshake.
func FuzzRandomActTwo(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Check if data is large enough.
if len(data) < ActTwoSize {
return
}
// This will return brontide machines with random keys.
initiator, _ := getBrontideMachines()
// Generate ActOne - this isn't sent to the responder because
// nothing is done with the responder machine and this would
// slow down fuzzing. GenActOne needs to be called to set the
// appropriate state in the initiator machine.
_, err := initiator.GenActOne()
if err != nil {
nilAndPanic(t, initiator, nil, err)
}
// Copy data into [ActTwoSize]byte.
var actTwo [ActTwoSize]byte
copy(actTwo[:], data)
// Initiator receives ActTwo, should fail.
if err := initiator.RecvActTwo(actTwo); err == nil {
nilAndPanic(t, initiator, nil, nil)
}
})
}
// FuzzRandomInitDecrypt fuzz tests decrypting arbitrary data with the
// initiator.
func FuzzRandomInitDecrypt(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Decrypt the encrypted message using ReadMessage w/ initiator
// machine.
if _, err := initiator.ReadMessage(r); err == nil {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzRandomInitEncDec fuzz tests round-trip encryption and decryption between
// the initiator and the responder.
func FuzzRandomInitEncDec(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Ensure that length of message is not greater than max allowed
// size.
if len(data) > math.MaxUint16 {
return
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ initiator machine.
if err := initiator.WriteMessage(data); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Flush the encrypted message w/ initiator machine.
if _, err := initiator.Flush(&b); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Decrypt the ciphertext using ReadMessage w/ responder
// machine.
plaintext, err := responder.ReadMessage(&b)
if err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Check that the decrypted message and the original message are
// equal.
if !bytes.Equal(data, plaintext) {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzRandomInitEncrypt fuzz tests the encryption of arbitrary data with the
// initiator.
func FuzzRandomInitEncrypt(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Ensure that length of message is not greater than max allowed
// size.
if len(data) > math.MaxUint16 {
return
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ initiator machine.
if err := initiator.WriteMessage(data); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Flush the encrypted message w/ initiator machine.
if _, err := initiator.Flush(&b); err != nil {
nilAndPanic(t, initiator, responder, err)
}
})
}
// FuzzRandomRespDecrypt fuzz tests the decryption of arbitrary data with the
// responder.
func FuzzRandomRespDecrypt(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Decrypt the encrypted message using ReadMessage w/ responder
// machine.
if _, err := responder.ReadMessage(r); err == nil {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzRandomRespEncDec fuzz tests round-trip encryption and decryption between
// the responder and the initiator.
func FuzzRandomRespEncDec(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Ensure that length of message is not greater than max allowed
// size.
if len(data) > math.MaxUint16 {
return
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ responder machine.
if err := responder.WriteMessage(data); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Flush the encrypted message w/ responder machine.
if _, err := responder.Flush(&b); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Decrypt the ciphertext using ReadMessage w/ initiator
// machine.
plaintext, err := initiator.ReadMessage(&b)
if err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Check that the decrypted message and the original message are
// equal.
if !bytes.Equal(data, plaintext) {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzRandomRespEncrypt fuzz tests encryption of arbitrary data with the
// responder.
func FuzzRandomRespEncrypt(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Ensure that length of message is not greater than max allowed
// size.
if len(data) > math.MaxUint16 {
return
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ responder machine.
if err := responder.WriteMessage(data); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Flush the encrypted message w/ responder machine.
if _, err := responder.Flush(&b); err != nil {
nilAndPanic(t, initiator, responder, err)
}
})
}
// FuzzStaticActOne fuzz tests ActOne in the brontide handshake.
func FuzzStaticActOne(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Check if data is large enough.
if len(data) < ActOneSize {
return
}
// This will return brontide machines with static keys.
_, responder := getStaticBrontideMachines()
// Copy data into [ActOneSize]byte.
var actOne [ActOneSize]byte
copy(actOne[:], data)
// Responder receives ActOne, should fail.
if err := responder.RecvActOne(actOne); err == nil {
nilAndPanic(t, nil, responder, nil)
}
})
}
// FuzzStaticActThree fuzz tests ActThree in the brontide handshake.
func FuzzStaticActThree(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Check if data is large enough.
if len(data) < ActThreeSize {
return
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Generate ActOne and send to the responder.
actOne, err := initiator.GenActOne()
if err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Receiving ActOne should succeed, so we panic on error.
if err := responder.RecvActOne(actOne); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Generate ActTwo - this is not sent to the initiator because
// nothing is done with the initiator after this point and it
// would slow down fuzzing. GenActTwo needs to be called to set
// the appropriate state in the responder machine.
_, err = responder.GenActTwo()
if err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Copy data into [ActThreeSize]byte.
var actThree [ActThreeSize]byte
copy(actThree[:], data)
// Responder receives ActThree, should fail.
if err := responder.RecvActThree(actThree); err == nil {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzStaticActTwo fuzz tests ActTwo in the brontide handshake.
func FuzzStaticActTwo(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Check if data is large enough.
if len(data) < ActTwoSize {
return
}
// This will return brontide machines with static keys.
initiator, _ := getStaticBrontideMachines()
// Generate ActOne - this isn't sent to the responder because
// nothing is done with the responder machine and this would
// slow down fuzzing. GenActOne needs to be called to set the
// appropriate state in the initiator machine.
_, err := initiator.GenActOne()
if err != nil {
nilAndPanic(t, initiator, nil, err)
}
// Copy data into [ActTwoSize]byte.
var actTwo [ActTwoSize]byte
copy(actTwo[:], data)
// Initiator receives ActTwo, should fail.
if err := initiator.RecvActTwo(actTwo); err == nil {
nilAndPanic(t, initiator, nil, nil)
}
})
}
// FuzzStaticInitDecrypt fuzz tests the decryption of arbitrary data with the
// initiator.
func FuzzStaticInitDecrypt(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Decrypt the encrypted message using ReadMessage w/ initiator
// machine.
if _, err := initiator.ReadMessage(r); err == nil {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzStaticInitEncDec fuzz tests round-trip encryption and decryption between
// the initiator and the responder.
func FuzzStaticInitEncDec(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Ensure that length of message is not greater than max allowed
// size.
if len(data) > math.MaxUint16 {
return
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ initiator machine.
if err := initiator.WriteMessage(data); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Flush the encrypted message w/ initiator machine.
if _, err := initiator.Flush(&b); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Decrypt the ciphertext using ReadMessage w/ responder
// machine.
plaintext, err := responder.ReadMessage(&b)
if err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Check that the decrypted message and the original message are
// equal.
if !bytes.Equal(data, plaintext) {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzStaticInitEncrypt fuzz tests the encryption of arbitrary data with the
// initiator.
func FuzzStaticInitEncrypt(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Ensure that length of message is not greater than max allowed
// size.
if len(data) > math.MaxUint16 {
return
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ initiator machine.
if err := initiator.WriteMessage(data); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Flush the encrypted message w/ initiator machine.
if _, err := initiator.Flush(&b); err != nil {
nilAndPanic(t, initiator, responder, err)
}
})
}
// FuzzStaticRespDecrypt fuzz tests the decryption of arbitrary data with the
// responder.
func FuzzStaticRespDecrypt(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Decrypt the encrypted message using ReadMessage w/ responder
// machine.
if _, err := responder.ReadMessage(r); err == nil {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzStaticRespEncDec fuzz tests the round-trip encryption and decryption
// between the responder and the initiator.
func FuzzStaticRespEncDec(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Ensure that length of message is not greater than max allowed
// size.
if len(data) > math.MaxUint16 {
return
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ responder machine.
if err := responder.WriteMessage(data); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Flush the encrypted message w/ responder machine.
if _, err := responder.Flush(&b); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Decrypt the ciphertext using ReadMessage w/ initiator
// machine.
plaintext, err := initiator.ReadMessage(&b)
if err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Check that the decrypted message and the original message are
// equal.
if !bytes.Equal(data, plaintext) {
nilAndPanic(t, initiator, responder, nil)
}
})
}
// FuzzStaticRespEncrypt fuzz tests the encryption of arbitrary data with the
// responder.
func FuzzStaticRespEncrypt(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Ensure that length of message is not greater than max allowed
// size.
if len(data) > math.MaxUint16 {
return
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(t, initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ responder machine.
if err := responder.WriteMessage(data); err != nil {
nilAndPanic(t, initiator, responder, err)
}
// Flush the encrypted message w/ responder machine.
if _, err := responder.Flush(&b); err != nil {
nilAndPanic(t, initiator, responder, err)
}
})
}

View File

@ -131,6 +131,9 @@ certain large transactions](https://github.com/lightningnetwork/lnd/pull/7100).
* [Fixed a bug where paying an invoice with a malformed route hint triggers a
never-ending retry loop](https://github.com/lightningnetwork/lnd/pull/6766)
* [Migrated from go-fuzz to Go 1.18's new standard fuzz testing
library](https://github.com/lightningnetwork/lnd/pull/7127).
## `lncli`
* [Add an `insecure` flag to skip tls auth as well as a `metadata` string slice
flag](https://github.com/lightningnetwork/lnd/pull/6818) that allows the
@ -226,6 +229,7 @@ to refactor the itest for code health and maintenance.
* andreihod
* Carla Kirk-Cohen
* Conner Babinchak
* cutiful
* Daniel McNally
* Elle Mouton

View File

@ -1,139 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"encoding/hex"
"fmt"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/brontide"
"github.com/lightningnetwork/lnd/keychain"
)
var (
initBytes = []byte{
0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
0xd, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
}
respBytes = []byte{
0xaa, 0xb6, 0x37, 0xd9, 0xfc, 0xd2, 0xc6, 0xda,
0x63, 0x59, 0xe6, 0x99, 0x31, 0x13, 0xa1, 0x17,
0xd, 0xe7, 0x95, 0xe9, 0xb7, 0x25, 0xb8, 0x4d,
0x1e, 0xb, 0x4c, 0xf9, 0x9e, 0xc5, 0x8c, 0xe9,
}
// Returns the initiator's ephemeral private key.
initEphemeral = brontide.EphemeralGenerator(func() (*btcec.PrivateKey, error) {
e := "121212121212121212121212121212121212121212121212121212" +
"1212121212"
eBytes, err := hex.DecodeString(e)
if err != nil {
return nil, err
}
priv, _ := btcec.PrivKeyFromBytes(eBytes)
return priv, nil
})
// Returns the responder's ephemeral private key.
respEphemeral = brontide.EphemeralGenerator(func() (*btcec.PrivateKey, error) {
e := "222222222222222222222222222222222222222222222222222" +
"2222222222222"
eBytes, err := hex.DecodeString(e)
if err != nil {
return nil, err
}
priv, _ := btcec.PrivKeyFromBytes(eBytes)
return priv, nil
})
)
// completeHandshake takes two brontide machines (initiator, responder)
// and completes the brontide handshake between them. If any part of the
// handshake fails, this function will panic.
func completeHandshake(initiator, responder *brontide.Machine) {
if err := handshake(initiator, responder); err != nil {
nilAndPanic(initiator, responder, err)
}
}
// handshake actually completes the brontide handshake and bubbles up
// an error to the calling function.
func handshake(initiator, responder *brontide.Machine) error {
// Generate ActOne and send to the responder.
actOne, err := initiator.GenActOne()
if err != nil {
return err
}
if err := responder.RecvActOne(actOne); err != nil {
return err
}
// Generate ActTwo and send to initiator.
actTwo, err := responder.GenActTwo()
if err != nil {
return err
}
if err := initiator.RecvActTwo(actTwo); err != nil {
return err
}
// Generate ActThree and send to responder.
actThree, err := initiator.GenActThree()
if err != nil {
return err
}
return responder.RecvActThree(actThree)
}
// nilAndPanic first nils the initiator and responder's Curve fields and then
// panics.
func nilAndPanic(initiator, responder *brontide.Machine, err error) {
panic(fmt.Errorf("error: %v, initiator: %v, responder: %v", err,
spew.Sdump(initiator), spew.Sdump(responder)))
}
// getBrontideMachines returns two brontide machines that use random keys
// everywhere.
func getBrontideMachines() (*brontide.Machine, *brontide.Machine) {
initPriv, _ := btcec.NewPrivateKey()
respPriv, _ := btcec.NewPrivateKey()
respPub := (*btcec.PublicKey)(&respPriv.PublicKey)
initPrivECDH := &keychain.PrivKeyECDH{PrivKey: initPriv}
respPrivECDH := &keychain.PrivKeyECDH{PrivKey: respPriv}
initiator := brontide.NewBrontideMachine(true, initPrivECDH, respPub)
responder := brontide.NewBrontideMachine(false, respPrivECDH, nil)
return initiator, responder
}
// getStaticBrontideMachines returns two brontide machines that use static keys
// everywhere.
func getStaticBrontideMachines() (*brontide.Machine, *brontide.Machine) {
initPriv, _ := btcec.PrivKeyFromBytes(initBytes)
respPriv, respPub := btcec.PrivKeyFromBytes(respBytes)
initPrivECDH := &keychain.PrivKeyECDH{PrivKey: initPriv}
respPrivECDH := &keychain.PrivKeyECDH{PrivKey: respPriv}
initiator := brontide.NewBrontideMachine(
true, initPrivECDH, respPub, initEphemeral,
)
responder := brontide.NewBrontideMachine(
false, respPrivECDH, nil, respEphemeral,
)
return initiator, responder
}

View File

@ -1,31 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"github.com/lightningnetwork/lnd/brontide"
)
// Fuzz_random_actone is a go-fuzz harness for ActOne in the brontide
// handshake.
func Fuzz_random_actone(data []byte) int {
// Check if data is large enough.
if len(data) < brontide.ActOneSize {
return 1
}
// This will return brontide machines with random keys.
_, responder := getBrontideMachines()
// Copy data into [ActOneSize]byte.
var actOne [brontide.ActOneSize]byte
copy(actOne[:], data)
// Responder receives ActOne, should fail on the MAC check.
if err := responder.RecvActOne(actOne); err == nil {
nilAndPanic(nil, responder, nil)
}
return 1
}

View File

@ -1,51 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"github.com/lightningnetwork/lnd/brontide"
)
// Fuzz_random_actthree is a go-fuzz harness for ActThree in the brontide
// handshake.
func Fuzz_random_actthree(data []byte) int {
// Check if data is large enough.
if len(data) < brontide.ActThreeSize {
return 1
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Generate ActOne and send to the responder.
actOne, err := initiator.GenActOne()
if err != nil {
nilAndPanic(initiator, responder, err)
}
// Receiving ActOne should succeed, so we panic on error.
if err := responder.RecvActOne(actOne); err != nil {
nilAndPanic(initiator, responder, err)
}
// Generate ActTwo - this is not sent to the initiator because nothing is
// done with the initiator after this point and it would slow down fuzzing.
// GenActTwo needs to be called to set the appropriate state in the
// responder machine.
_, err = responder.GenActTwo()
if err != nil {
nilAndPanic(initiator, responder, err)
}
// Copy data into [ActThreeSize]byte.
var actThree [brontide.ActThreeSize]byte
copy(actThree[:], data)
// Responder receives ActThree, should fail on the MAC check.
if err := responder.RecvActThree(actThree); err == nil {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,40 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"github.com/lightningnetwork/lnd/brontide"
)
// Fuzz_random_acttwo is a go-fuzz harness for ActTwo in the brontide
// handshake.
func Fuzz_random_acttwo(data []byte) int {
// Check if data is large enough.
if len(data) < brontide.ActTwoSize {
return 1
}
// This will return brontide machines with random keys.
initiator, _ := getBrontideMachines()
// Generate ActOne - this isn't sent to the responder because nothing is
// done with the responder machine and this would slow down fuzzing.
// GenActOne needs to be called to set the appropriate state in the
// initiator machine.
_, err := initiator.GenActOne()
if err != nil {
nilAndPanic(initiator, nil, err)
}
// Copy data into [ActTwoSize]byte.
var actTwo [brontide.ActTwoSize]byte
copy(actTwo[:], data)
// Initiator receives ActTwo, should fail.
if err := initiator.RecvActTwo(actTwo); err == nil {
nilAndPanic(initiator, nil, nil)
}
return 1
}

View File

@ -1,28 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
)
// Fuzz_random_init_decrypt is a go-fuzz harness that decrypts arbitrary data
// with the initiator.
func Fuzz_random_init_decrypt(data []byte) int {
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Decrypt the encrypted message using ReadMessage w/ initiator machine.
if _, err := initiator.ReadMessage(r); err == nil {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,49 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
"math"
)
// Fuzz_random_init_enc_dec is a go-fuzz harness that tests round-trip
// encryption and decryption between the initiator and the responder.
func Fuzz_random_init_enc_dec(data []byte) int {
// Ensure that length of message is not greater than max allowed size.
if len(data) > math.MaxUint16 {
return 1
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ initiator machine.
if err := initiator.WriteMessage(data); err != nil {
nilAndPanic(initiator, responder, err)
}
// Flush the encrypted message w/ initiator machine.
if _, err := initiator.Flush(&b); err != nil {
nilAndPanic(initiator, responder, err)
}
// Decrypt the ciphertext using ReadMessage w/ responder machine.
plaintext, err := responder.ReadMessage(&b)
if err != nil {
nilAndPanic(initiator, responder, err)
}
// Check that the decrypted message and the original message are equal.
if !bytes.Equal(data, plaintext) {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,38 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
"math"
)
// Fuzz_random_init_encrypt is a go-fuzz harness that encrypts arbitrary data
// with the initiator.
func Fuzz_random_init_encrypt(data []byte) int {
// Ensure that length of message is not greater than max allowed size.
if len(data) > math.MaxUint16 {
return 1
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ initiator machine.
if err := initiator.WriteMessage(data); err != nil {
nilAndPanic(initiator, responder, err)
}
// Flush the encrypted message w/ initiator machine.
if _, err := initiator.Flush(&b); err != nil {
nilAndPanic(initiator, responder, err)
}
return 1
}

View File

@ -1,28 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
)
// Fuzz_random_resp_decrypt is a go-fuzz harness that decrypts arbitrary data
// with the responder.
func Fuzz_random_resp_decrypt(data []byte) int {
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Decrypt the encrypted message using ReadMessage w/ responder machine.
if _, err := responder.ReadMessage(r); err == nil {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,49 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
"math"
)
// Fuzz_random_resp_enc_dec is a go-fuzz harness that tests round-trip
// encryption and decryption between the responder and the initiator.
func Fuzz_random_resp_enc_dec(data []byte) int {
// Ensure that length of message is not greater than max allowed size.
if len(data) > math.MaxUint16 {
return 1
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ responder machine.
if err := responder.WriteMessage(data); err != nil {
nilAndPanic(initiator, responder, err)
}
// Flush the encrypted message w/ responder machine.
if _, err := responder.Flush(&b); err != nil {
nilAndPanic(initiator, responder, err)
}
// Decrypt the ciphertext using ReadMessage w/ initiator machine.
plaintext, err := initiator.ReadMessage(&b)
if err != nil {
nilAndPanic(initiator, responder, err)
}
// Check that the decrypted message and the original message are equal.
if !bytes.Equal(data, plaintext) {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,38 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
"math"
)
// Fuzz_random_resp_encrypt is a go-fuzz harness that encrypts arbitrary data
// with the responder.
func Fuzz_random_resp_encrypt(data []byte) int {
// Ensure that length of message is not greater than max allowed size.
if len(data) > math.MaxUint16 {
return 1
}
// This will return brontide machines with random keys.
initiator, responder := getBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ responder machine.
if err := responder.WriteMessage(data); err != nil {
nilAndPanic(initiator, responder, err)
}
// Flush the encrypted message w/ responder machine.
if _, err := responder.Flush(&b); err != nil {
nilAndPanic(initiator, responder, err)
}
return 1
}

View File

@ -1,31 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"github.com/lightningnetwork/lnd/brontide"
)
// Fuzz_static_actone is a go-fuzz harness for ActOne in the brontide
// handshake.
func Fuzz_static_actone(data []byte) int {
// Check if data is large enough.
if len(data) < brontide.ActOneSize {
return 1
}
// This will return brontide machines with static keys.
_, responder := getStaticBrontideMachines()
// Copy data into [ActOneSize]byte.
var actOne [brontide.ActOneSize]byte
copy(actOne[:], data)
// Responder receives ActOne, should fail.
if err := responder.RecvActOne(actOne); err == nil {
nilAndPanic(nil, responder, nil)
}
return 1
}

View File

@ -1,51 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"github.com/lightningnetwork/lnd/brontide"
)
// Fuzz_static_actthree is a go-fuzz harness for ActThree in the brontide
// handshake.
func Fuzz_static_actthree(data []byte) int {
// Check if data is large enough.
if len(data) < brontide.ActThreeSize {
return 1
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Generate ActOne and send to the responder.
actOne, err := initiator.GenActOne()
if err != nil {
nilAndPanic(initiator, responder, err)
}
// Receiving ActOne should succeed, so we panic on error.
if err := responder.RecvActOne(actOne); err != nil {
nilAndPanic(initiator, responder, err)
}
// Generate ActTwo - this is not sent to the initiator because nothing is
// done with the initiator after this point and it would slow down fuzzing.
// GenActTwo needs to be called to set the appropriate state in the responder
// machine.
_, err = responder.GenActTwo()
if err != nil {
nilAndPanic(initiator, responder, err)
}
// Copy data into [ActThreeSize]byte.
var actThree [brontide.ActThreeSize]byte
copy(actThree[:], data)
// Responder receives ActThree, should fail.
if err := responder.RecvActThree(actThree); err == nil {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,40 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"github.com/lightningnetwork/lnd/brontide"
)
// Fuzz_static_acttwo is a go-fuzz harness for ActTwo in the brontide
// handshake.
func Fuzz_static_acttwo(data []byte) int {
// Check if data is large enough.
if len(data) < brontide.ActTwoSize {
return 1
}
// This will return brontide machines with static keys.
initiator, _ := getStaticBrontideMachines()
// Generate ActOne - this isn't sent to the responder because nothing is
// done with the responder machine and this would slow down fuzzing.
// GenActOne needs to be called to set the appropriate state in the initiator
// machine.
_, err := initiator.GenActOne()
if err != nil {
nilAndPanic(initiator, nil, err)
}
// Copy data into [ActTwoSize]byte.
var actTwo [brontide.ActTwoSize]byte
copy(actTwo[:], data)
// Initiator receives ActTwo, should fail.
if err := initiator.RecvActTwo(actTwo); err == nil {
nilAndPanic(initiator, nil, nil)
}
return 1
}

View File

@ -1,28 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
)
// Fuzz_static_init_decrypt is a go-fuzz harness that decrypts arbitrary data
// with the initiator.
func Fuzz_static_init_decrypt(data []byte) int {
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Decrypt the encrypted message using ReadMessage w/ initiator machine.
if _, err := initiator.ReadMessage(r); err == nil {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,50 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
"math"
)
// Fuzz_static_init_enc_dec is a go-fuzz harness that tests round-trip
// encryption and decryption
// between the initiator and the responder.
func Fuzz_static_init_enc_dec(data []byte) int {
// Ensure that length of message is not greater than max allowed size.
if len(data) > math.MaxUint16 {
return 1
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ initiator machine.
if err := initiator.WriteMessage(data); err != nil {
nilAndPanic(initiator, responder, err)
}
// Flush the encrypted message w/ initiator machine.
if _, err := initiator.Flush(&b); err != nil {
nilAndPanic(initiator, responder, err)
}
// Decrypt the ciphertext using ReadMessage w/ responder machine.
plaintext, err := responder.ReadMessage(&b)
if err != nil {
nilAndPanic(initiator, responder, err)
}
// Check that the decrypted message and the original message are equal.
if !bytes.Equal(data, plaintext) {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,38 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
"math"
)
// Fuzz_static_init_encrypt is a go-fuzz harness that encrypts arbitrary data
// with the initiator.
func Fuzz_static_init_encrypt(data []byte) int {
// Ensure that length of message is not greater than max allowed size.
if len(data) > math.MaxUint16 {
return 1
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ initiator machine.
if err := initiator.WriteMessage(data); err != nil {
nilAndPanic(initiator, responder, err)
}
// Flush the encrypted message w/ initiator machine.
if _, err := initiator.Flush(&b); err != nil {
nilAndPanic(initiator, responder, err)
}
return 1
}

View File

@ -1,28 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
)
// Fuzz_static_resp_decrypt is a go-fuzz harness that decrypts arbitrary data
// with the responder.
func Fuzz_static_resp_decrypt(data []byte) int {
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Decrypt the encrypted message using ReadMessage w/ responder machine.
if _, err := responder.ReadMessage(r); err == nil {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,49 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
"math"
)
// Fuzz_static_resp_enc_dec is a go-fuzz harness that tests round-trip
// encryption and decryption between the responder and the initiator.
func Fuzz_static_resp_enc_dec(data []byte) int {
// Ensure that length of message is not greater than max allowed size.
if len(data) > math.MaxUint16 {
return 1
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ responder machine.
if err := responder.WriteMessage(data); err != nil {
nilAndPanic(initiator, responder, err)
}
// Flush the encrypted message w/ responder machine.
if _, err := responder.Flush(&b); err != nil {
nilAndPanic(initiator, responder, err)
}
// Decrypt the ciphertext using ReadMessage w/ initiator machine.
plaintext, err := initiator.ReadMessage(&b)
if err != nil {
nilAndPanic(initiator, responder, err)
}
// Check that the decrypted message and the original message are equal.
if !bytes.Equal(data, plaintext) {
nilAndPanic(initiator, responder, nil)
}
return 1
}

View File

@ -1,38 +0,0 @@
//go:build gofuzz
// +build gofuzz
package brontidefuzz
import (
"bytes"
"math"
)
// Fuzz_static_resp_encrypt is a go-fuzz harness that encrypts arbitrary data
// with the responder.
func Fuzz_static_resp_encrypt(data []byte) int {
// Ensure that length of message is not greater than max allowed size.
if len(data) > math.MaxUint16 {
return 1
}
// This will return brontide machines with static keys.
initiator, responder := getStaticBrontideMachines()
// Complete the brontide handshake.
completeHandshake(initiator, responder)
var b bytes.Buffer
// Encrypt the message using WriteMessage w/ responder machine.
if err := responder.WriteMessage(data); err != nil {
nilAndPanic(initiator, responder, err)
}
// Flush the encrypted message w/ responder machine.
if _, err := responder.Flush(&b); err != nil {
nilAndPanic(initiator, responder, err)
}
return 1
}

View File

@ -1,129 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"bytes"
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_accept_channel is used by go-fuzz.
func Fuzz_accept_channel(data []byte) int {
// Prefix with MsgAcceptChannel.
data = prefixWithMsgType(data, lnwire.MsgAcceptChannel)
// We have to do this here instead of in fuzz.Harness so that
// reflect.DeepEqual isn't called. Because of the UpfrontShutdownScript
// encoding, the first message and second message aren't deeply equal since
// the first has a nil slice and the other has an empty slice.
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message type) is
// less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > lnwire.MaxMsgBody {
return 1
}
msg, err := lnwire.ReadMessage(r, 0)
if err != nil {
// go-fuzz generated []byte that cannot be represented as a
// wire message but we will return 0 so go-fuzz can modify the
// input.
return 1
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := lnwire.WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic
panic(err)
}
// Deserialize the message from the serialized bytes buffer, and then
// assert that the original message is equal to the newly deserialized
// message.
newMsg, err := lnwire.ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer, panic
panic(err)
}
// Now compare every field instead of using reflect.DeepEqual.
// For UpfrontShutdownScript, we only compare bytes. This probably takes
// up more branches than necessary, but that's fine for now.
var shouldPanic bool
first := msg.(*lnwire.AcceptChannel)
second := newMsg.(*lnwire.AcceptChannel)
if !bytes.Equal(first.PendingChannelID[:], second.PendingChannelID[:]) {
shouldPanic = true
}
if first.DustLimit != second.DustLimit {
shouldPanic = true
}
if first.MaxValueInFlight != second.MaxValueInFlight {
shouldPanic = true
}
if first.ChannelReserve != second.ChannelReserve {
shouldPanic = true
}
if first.HtlcMinimum != second.HtlcMinimum {
shouldPanic = true
}
if first.MinAcceptDepth != second.MinAcceptDepth {
shouldPanic = true
}
if first.CsvDelay != second.CsvDelay {
shouldPanic = true
}
if first.MaxAcceptedHTLCs != second.MaxAcceptedHTLCs {
shouldPanic = true
}
if !first.FundingKey.IsEqual(second.FundingKey) {
shouldPanic = true
}
if !first.RevocationPoint.IsEqual(second.RevocationPoint) {
shouldPanic = true
}
if !first.PaymentPoint.IsEqual(second.PaymentPoint) {
shouldPanic = true
}
if !first.DelayedPaymentPoint.IsEqual(second.DelayedPaymentPoint) {
shouldPanic = true
}
if !first.HtlcPoint.IsEqual(second.HtlcPoint) {
shouldPanic = true
}
if !first.FirstCommitmentPoint.IsEqual(second.FirstCommitmentPoint) {
shouldPanic = true
}
if !bytes.Equal(first.UpfrontShutdownScript, second.UpfrontShutdownScript) {
shouldPanic = true
}
if shouldPanic {
panic("original message and deserialized message are not equal")
}
// Add this input to the corpus.
return 1
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_announce_signatures is used by go-fuzz.
func Fuzz_announce_signatures(data []byte) int {
// Prefix with MsgAnnounceSignatures.
data = prefixWithMsgType(data, lnwire.MsgAnnounceSignatures)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_channel_announcement is used by go-fuzz.
func Fuzz_channel_announcement(data []byte) int {
// Prefix with MsgChannelAnnouncement.
data = prefixWithMsgType(data, lnwire.MsgChannelAnnouncement)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_channel_reestablish is used by go-fuzz.
func Fuzz_channel_reestablish(data []byte) int {
// Prefix with MsgChannelReestablish.
data = prefixWithMsgType(data, lnwire.MsgChannelReestablish)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_channel_update is used by go-fuzz.
func Fuzz_channel_update(data []byte) int {
// Prefix with MsgChannelUpdate.
data = prefixWithMsgType(data, lnwire.MsgChannelUpdate)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_closing_signed is used by go-fuzz.
func Fuzz_closing_signed(data []byte) int {
// Prefix with MsgClosingSigned.
data = prefixWithMsgType(data, lnwire.MsgClosingSigned)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_commit_sig is used by go-fuzz.
func Fuzz_commit_sig(data []byte) int {
// Prefix with MsgCommitSig.
data = prefixWithMsgType(data, lnwire.MsgCommitSig)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_error is used by go-fuzz.
func Fuzz_error(data []byte) int {
// Prefix with MsgError.
data = prefixWithMsgType(data, lnwire.MsgError)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_funding_created is used by go-fuzz.
func Fuzz_funding_created(data []byte) int {
// Prefix with MsgFundingCreated.
data = prefixWithMsgType(data, lnwire.MsgFundingCreated)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_funding_locked is used by go-fuzz.
func Fuzz_funding_locked(data []byte) int {
// Prefix with MsgFundingLocked.
data = prefixWithMsgType(data, lnwire.MsgFundingLocked)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_funding_signed is used by go-fuzz.
func Fuzz_funding_signed(data []byte) int {
// Prefix with MsgFundingSigned.
prefixWithMsgType(data, lnwire.MsgFundingSigned)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,65 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"bytes"
"encoding/binary"
"reflect"
"github.com/lightningnetwork/lnd/lnwire"
)
// prefixWithMsgType takes []byte and adds a wire protocol prefix
// to make the []byte into an actual message to be used in fuzzing.
func prefixWithMsgType(data []byte, prefix lnwire.MessageType) []byte {
var prefixBytes [2]byte
binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix))
data = append(prefixBytes[:], data...)
return data
}
// harness performs the actual fuzz testing of the appropriate wire message.
// This function will check that the passed-in message passes wire length checks,
// is a valid message once deserialized, and passes a sequence of serialization
// and deserialization checks. Returns an int that determines whether the input
// is unique or not.
func harness(data []byte) int {
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Check that the created message is not greater than the maximum
// message size.
if len(data) > lnwire.MaxSliceLength {
return 1
}
msg, err := lnwire.ReadMessage(r, 0)
if err != nil {
return 1
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := lnwire.WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic
panic(err)
}
// Deserialize the message from the serialized bytes buffer, and then
// assert that the original message is equal to the newly deserialized
// message.
newMsg, err := lnwire.ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer, panic
panic(err)
}
if !reflect.DeepEqual(msg, newMsg) {
// Deserialized message and original message are not deeply equal.
panic("original message and deserialized message are not deeply equal")
}
return 1
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_gossip_timestamp_range is used by go-fuzz.
func Fuzz_gossip_timestamp_range(data []byte) int {
// Prefix with MsgGossipTimestampRange.
data = prefixWithMsgType(data, lnwire.MsgGossipTimestampRange)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_init is used by go-fuzz.
func Fuzz_init(data []byte) int {
// Prefix with MsgInit.
data = prefixWithMsgType(data, lnwire.MsgInit)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,103 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"bytes"
"reflect"
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_node_announcement is used by go-fuzz.
func Fuzz_node_announcement(data []byte) int {
// Prefix with MsgNodeAnnouncement.
data = prefixWithMsgType(data, lnwire.MsgNodeAnnouncement)
// We have to do this here instead of in fuzz.Harness so that
// reflect.DeepEqual isn't called. Address (de)serialization messes up
// the fuzzing assertions.
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message type) is
// less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > lnwire.MaxMsgBody {
return 1
}
msg, err := lnwire.ReadMessage(r, 0)
if err != nil {
return 1
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := lnwire.WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic
panic(err)
}
// Deserialize the message from the serialized bytes buffer, and then
// assert that the original message is equal to the newly deserialized
// message.
newMsg, err := lnwire.ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer, panic
panic(err)
}
// Now compare every field instead of using reflect.DeepEqual for the
// Addresses field.
var shouldPanic bool
first := msg.(*lnwire.NodeAnnouncement)
second := newMsg.(*lnwire.NodeAnnouncement)
if !bytes.Equal(first.Signature[:], second.Signature[:]) {
shouldPanic = true
}
if !reflect.DeepEqual(first.Features, second.Features) {
shouldPanic = true
}
if first.Timestamp != second.Timestamp {
shouldPanic = true
}
if !bytes.Equal(first.NodeID[:], second.NodeID[:]) {
shouldPanic = true
}
if !reflect.DeepEqual(first.RGBColor, second.RGBColor) {
shouldPanic = true
}
if !bytes.Equal(first.Alias[:], second.Alias[:]) {
shouldPanic = true
}
if len(first.Addresses) != len(second.Addresses) {
shouldPanic = true
}
for i := range first.Addresses {
if first.Addresses[i].String() != second.Addresses[i].String() {
shouldPanic = true
break
}
}
if !reflect.DeepEqual(first.ExtraOpaqueData, second.ExtraOpaqueData) {
shouldPanic = true
}
if shouldPanic {
panic("original message and deserialized message are not equal")
}
// Add this input to the corpus.
return 1
}

View File

@ -1,142 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"bytes"
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_open_channel is used by go-fuzz.
func Fuzz_open_channel(data []byte) int {
// Prefix with MsgOpenChannel.
data = prefixWithMsgType(data, lnwire.MsgOpenChannel)
// We have to do this here instead of in fuzz.Harness so that
// reflect.DeepEqual isn't called. Because of the UpfrontShutdownScript
// encoding, the first message and second message aren't deeply equal since
// the first has a nil slice and the other has an empty slice.
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message type) is
// less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > lnwire.MaxMsgBody {
return 1
}
msg, err := lnwire.ReadMessage(r, 0)
if err != nil {
return 1
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := lnwire.WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic
panic(err)
}
// Deserialize the message from the serialized bytes buffer, and then
// assert that the original message is equal to the newly deserialized
// message.
newMsg, err := lnwire.ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer, panic
panic(err)
}
// Now compare every field instead of using reflect.DeepEqual.
// For UpfrontShutdownScript, we only compare bytes. This probably takes
// up more branches than necessary, but that's fine for now.
var shouldPanic bool
first := msg.(*lnwire.OpenChannel)
second := newMsg.(*lnwire.OpenChannel)
if !first.ChainHash.IsEqual(&second.ChainHash) {
shouldPanic = true
}
if !bytes.Equal(first.PendingChannelID[:], second.PendingChannelID[:]) {
shouldPanic = true
}
if first.FundingAmount != second.FundingAmount {
shouldPanic = true
}
if first.PushAmount != second.PushAmount {
shouldPanic = true
}
if first.DustLimit != second.DustLimit {
shouldPanic = true
}
if first.MaxValueInFlight != second.MaxValueInFlight {
shouldPanic = true
}
if first.ChannelReserve != second.ChannelReserve {
shouldPanic = true
}
if first.HtlcMinimum != second.HtlcMinimum {
shouldPanic = true
}
if first.FeePerKiloWeight != second.FeePerKiloWeight {
shouldPanic = true
}
if first.CsvDelay != second.CsvDelay {
shouldPanic = true
}
if first.MaxAcceptedHTLCs != second.MaxAcceptedHTLCs {
shouldPanic = true
}
if !first.FundingKey.IsEqual(second.FundingKey) {
shouldPanic = true
}
if !first.RevocationPoint.IsEqual(second.RevocationPoint) {
shouldPanic = true
}
if !first.PaymentPoint.IsEqual(second.PaymentPoint) {
shouldPanic = true
}
if !first.DelayedPaymentPoint.IsEqual(second.DelayedPaymentPoint) {
shouldPanic = true
}
if !first.HtlcPoint.IsEqual(second.HtlcPoint) {
shouldPanic = true
}
if !first.FirstCommitmentPoint.IsEqual(second.FirstCommitmentPoint) {
shouldPanic = true
}
if first.ChannelFlags != second.ChannelFlags {
shouldPanic = true
}
if !bytes.Equal(first.UpfrontShutdownScript, second.UpfrontShutdownScript) {
shouldPanic = true
}
if shouldPanic {
panic("original message and deserialized message are not equal")
}
// Add this input to the corpus.
return 1
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_ping is used by go-fuzz.
func Fuzz_ping(data []byte) int {
// Prefix with MsgPing.
data = prefixWithMsgType(data, lnwire.MsgPing)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_pong is used by go-fuzz.
func Fuzz_pong(data []byte) int {
// Prefix with MsgPong.
data = prefixWithMsgType(data, lnwire.MsgPong)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_query_channel_range is used by go-fuzz.
func Fuzz_query_channel_range(data []byte) int {
// Prefix with MsgQueryChannelRange.
data = prefixWithMsgType(data, lnwire.MsgQueryChannelRange)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_query_short_chan_ids is used by go-fuzz.
func Fuzz_query_short_chan_ids(data []byte) int {
// Prefix with MsgQueryShortChanIDs.
data = prefixWithMsgType(data, lnwire.MsgQueryShortChanIDs)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,48 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"bytes"
"compress/zlib"
"encoding/binary"
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_query_short_chan_ids_zlib is used by go-fuzz.
func Fuzz_query_short_chan_ids_zlib(data []byte) int {
var buf bytes.Buffer
zlibWriter := zlib.NewWriter(&buf)
_, err := zlibWriter.Write(data)
if err != nil {
// Zlib bug?
panic(err)
}
if err := zlibWriter.Close(); err != nil {
// Zlib bug?
panic(err)
}
compressedPayload := buf.Bytes()
chainhash := []byte("00000000000000000000000000000000")
numBytesInBody := len(compressedPayload) + 1
zlibByte := []byte("\x01")
bodyBytes := make([]byte, 2)
binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody))
payload := append(chainhash, bodyBytes...)
payload = append(payload, zlibByte...)
payload = append(payload, compressedPayload...)
// Prefix with MsgQueryShortChanIDs.
payload = prefixWithMsgType(payload, lnwire.MsgQueryShortChanIDs)
// Pass the message into our general fuzz harness for wire messages!
return harness(payload)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_reply_channel_range is used by go-fuzz.
func Fuzz_reply_channel_range(data []byte) int {
// Prefix with MsgReplyChannelRange.
data = prefixWithMsgType(data, lnwire.MsgReplyChannelRange)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,56 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"bytes"
"compress/zlib"
"encoding/binary"
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_reply_channel_range_zlib is used by go-fuzz.
func Fuzz_reply_channel_range_zlib(data []byte) int {
var buf bytes.Buffer
zlibWriter := zlib.NewWriter(&buf)
_, err := zlibWriter.Write(data)
if err != nil {
// Zlib bug?
panic(err)
}
if err := zlibWriter.Close(); err != nil {
// Zlib bug?
panic(err)
}
compressedPayload := buf.Bytes()
// Initialize some []byte vars which will prefix our payload
chainhash := []byte("00000000000000000000000000000000")
firstBlockHeight := []byte("\x00\x00\x00\x00")
numBlocks := []byte("\x00\x00\x00\x00")
completeByte := []byte("\x00")
numBytesInBody := len(compressedPayload) + 1
zlibByte := []byte("\x01")
bodyBytes := make([]byte, 2)
binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody))
payload := append(chainhash, firstBlockHeight...)
payload = append(payload, numBlocks...)
payload = append(payload, completeByte...)
payload = append(payload, bodyBytes...)
payload = append(payload, zlibByte...)
payload = append(payload, compressedPayload...)
// Prefix with MsgReplyChannelRange.
payload = prefixWithMsgType(payload, lnwire.MsgReplyChannelRange)
// Pass the message into our general fuzz harness for wire messages!
return harness(payload)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_reply_short_chan_ids_end is used by go-fuzz.
func Fuzz_reply_short_chan_ids_end(data []byte) int {
// Prefix with MsgReplyShortChanIDsEnd.
data = prefixWithMsgType(data, lnwire.MsgReplyShortChanIDsEnd)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_revoke_and_ack is used by go-fuzz.
func Fuzz_revoke_and_ack(data []byte) int {
// Prefix with MsgRevokeAndAck.
data = prefixWithMsgType(data, lnwire.MsgRevokeAndAck)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_shutdown is used by go-fuzz.
func Fuzz_shutdown(data []byte) int {
// Prefix with MsgShutdown.
data = prefixWithMsgType(data, lnwire.MsgShutdown)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_update_add_htlc is used by go-fuzz.
func Fuzz_update_add_htlc(data []byte) int {
// Prefix with MsgUpdateAddHTLC.
data = prefixWithMsgType(data, lnwire.MsgUpdateAddHTLC)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_update_fail_htlc is used by go-fuzz.
func Fuzz_update_fail_htlc(data []byte) int {
// Prefix with MsgUpdateFailHTLC.
data = prefixWithMsgType(data, lnwire.MsgUpdateFailHTLC)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_update_fail_malformed_htlc is used by go-fuzz.
func Fuzz_update_fail_malformed_htlc(data []byte) int {
// Prefix with MsgUpdateFailMalformedHTLC.
data = prefixWithMsgType(data, lnwire.MsgUpdateFailMalformedHTLC)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_update_fee is used by go-fuzz.
func Fuzz_update_fee(data []byte) int {
// Prefix with MsgUpdateFee.
data = prefixWithMsgType(data, lnwire.MsgUpdateFee)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,17 +0,0 @@
//go:build gofuzz
// +build gofuzz
package lnwirefuzz
import (
"github.com/lightningnetwork/lnd/lnwire"
)
// Fuzz_update_fulfill_htlc is used by go-fuzz.
func Fuzz_update_fulfill_htlc(data []byte) int {
// Prefix with MsgUpdateFulfillHTLC.
data = prefixWithMsgType(data, lnwire.MsgUpdateFulfillHTLC)
// Pass the message into our general fuzz harness for wire messages!
return harness(data)
}

View File

@ -1,21 +0,0 @@
//go:build gofuzz
// +build gofuzz
package wtwirefuzz
import (
"github.com/lightningnetwork/lnd/watchtower/wtwire"
)
// Fuzz_create_session is used by go-fuzz.
func Fuzz_create_session(data []byte) int {
// Prefix with MsgCreateSession.
data = prefixWithMsgType(data, wtwire.MsgCreateSession)
// Create an empty message so that the FuzzHarness func can check if the
// max payload constraint is violated.
emptyMsg := wtwire.CreateSession{}
// Pass the message into our general fuzz harness for wire messages!
return harness(data, &emptyMsg)
}

View File

@ -1,21 +0,0 @@
//go:build gofuzz
// +build gofuzz
package wtwirefuzz
import (
"github.com/lightningnetwork/lnd/watchtower/wtwire"
)
// Fuzz_create_session_reply is used by go-fuzz.
func Fuzz_create_session_reply(data []byte) int {
// Prefix with MsgCreateSessionReply.
data = prefixWithMsgType(data, wtwire.MsgCreateSessionReply)
// Create an empty message so that the FuzzHarness func can check if the
// max payload constraint is violated.
emptyMsg := wtwire.CreateSessionReply{}
// Pass the message into our general fuzz harness for wire messages!
return harness(data, &emptyMsg)
}

View File

@ -1,21 +0,0 @@
//go:build gofuzz
// +build gofuzz
package wtwirefuzz
import (
"github.com/lightningnetwork/lnd/watchtower/wtwire"
)
// Fuzz_delete_session is used by go-fuzz.
func Fuzz_delete_session(data []byte) int {
// Prefix with MsgDeleteSession.
data = prefixWithMsgType(data, wtwire.MsgDeleteSession)
// Create an empty message so that the FuzzHarness func can check if the
// max payload constraint is violated.
emptyMsg := wtwire.DeleteSession{}
// Pass the message into our general fuzz harness for wire messages!
return harness(data, &emptyMsg)
}

View File

@ -1,21 +0,0 @@
//go:build gofuzz
// +build gofuzz
package wtwirefuzz
import (
"github.com/lightningnetwork/lnd/watchtower/wtwire"
)
// Fuzz_delete_session_reply is used by go-fuzz.
func Fuzz_delete_session_reply(data []byte) int {
// Prefix with MsgDeleteSessionReply.
data = prefixWithMsgType(data, wtwire.MsgDeleteSessionReply)
// Create an empty message so that the FuzzHarness func can check if the
// max payload constraint is violated.
emptyMsg := wtwire.DeleteSessionReply{}
// Pass the message into our general fuzz harness for wire messages!
return harness(data, &emptyMsg)
}

View File

@ -1,21 +0,0 @@
//go:build gofuzz
// +build gofuzz
package wtwirefuzz
import (
"github.com/lightningnetwork/lnd/watchtower/wtwire"
)
// Fuzz_error is used by go-fuzz.
func Fuzz_error(data []byte) int {
// Prefix with MsgError.
data = prefixWithMsgType(data, wtwire.MsgError)
// Create an empty message so that the FuzzHarness func can check if the
// max payload constraint is violated.
emptyMsg := wtwire.Error{}
// Pass the message into our general fuzz harness for wire messages!
return harness(data, &emptyMsg)
}

View File

@ -1,76 +0,0 @@
//go:build gofuzz
// +build gofuzz
package wtwirefuzz
import (
"bytes"
"encoding/binary"
"fmt"
"reflect"
"github.com/lightningnetwork/lnd/watchtower/wtwire"
)
// prefixWithMsgType takes []byte and adds a wire protocol prefix
// to make the []byte into an actual message to be used in fuzzing.
func prefixWithMsgType(data []byte, prefix wtwire.MessageType) []byte {
var prefixBytes [2]byte
binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix))
data = append(prefixBytes[:], data...)
return data
}
// harness performs the actual fuzz testing of the appropriate wire message.
// This function will check that the passed-in message passes wire length checks,
// is a valid message once deserialized, and passes a sequence of serialization
// and deserialization checks. Returns an int that determines whether the input
// is unique or not.
func harness(data []byte, emptyMsg wtwire.Message) int {
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message type) is
// less than max payload size for the wire message. We check this because
// otherwise `go-fuzz` will keep creating inputs that crash on ReadMessage
// due to a large message size.
payloadLen := uint32(len(data)) - 2
if payloadLen > emptyMsg.MaxPayloadLength(0) {
// Ignore this input - max payload constraint violated.
return 1
}
msg, err := wtwire.ReadMessage(r, 0)
if err != nil {
// go-fuzz generated []byte that cannot be represented as a
// wire message but we will return 0 so go-fuzz can modify the
// input.
return 1
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := wtwire.WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic.
panic(err)
}
// Deserialize the message from the serialized bytes buffer, and then
// assert that the original message is equal to the newly deserialized
// message.
newMsg, err := wtwire.ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer, panic.
panic(err)
}
if !reflect.DeepEqual(msg, newMsg) {
// Deserialized message and original message are not
// deeply equal.
panic(fmt.Errorf("deserialized message and original message " +
"are not deeply equal."))
}
// Add this input to the corpus.
return 1
}

View File

@ -1,21 +0,0 @@
//go:build gofuzz
// +build gofuzz
package wtwirefuzz
import (
"github.com/lightningnetwork/lnd/watchtower/wtwire"
)
// Fuzz_init is used by go-fuzz.
func Fuzz_init(data []byte) int {
// Prefix with MsgInit.
data = prefixWithMsgType(data, wtwire.MsgInit)
// Create an empty message so that the FuzzHarness func can check if the
// max payload constraint is violated.
emptyMsg := wtwire.Init{}
// Pass the message into our general fuzz harness for wire messages!
return harness(data, &emptyMsg)
}

View File

@ -1,21 +0,0 @@
//go:build gofuzz
// +build gofuzz
package wtwirefuzz
import (
"github.com/lightningnetwork/lnd/watchtower/wtwire"
)
// Fuzz_state_update is used by go-fuzz.
func Fuzz_state_update(data []byte) int {
// Prefix with MsgStateUpdate.
data = prefixWithMsgType(data, wtwire.MsgStateUpdate)
// Create an empty message so that the FuzzHarness func can check if the
// max payload constraint is violated.
emptyMsg := wtwire.StateUpdate{}
// Pass the message into our general fuzz harness for wire messages!
return harness(data, &emptyMsg)
}

View File

@ -1,21 +0,0 @@
//go:build gofuzz
// +build gofuzz
package wtwirefuzz
import (
"github.com/lightningnetwork/lnd/watchtower/wtwire"
)
// Fuzz_state_update_reply is used by go-fuzz.
func Fuzz_state_update_reply(data []byte) int {
// Prefix with MsgStateUpdateReply.
data = prefixWithMsgType(data, wtwire.MsgStateUpdateReply)
// Create an empty message so that the FuzzHarness func can check if the
// max payload constraint is violated.
emptyMsg := wtwire.StateUpdateReply{}
// Pass the message into our general fuzz harness for wire messages!
return harness(data, &emptyMsg)
}

View File

@ -1,23 +0,0 @@
//go:build gofuzz
// +build gofuzz
package zpay32fuzz
import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/lightningnetwork/lnd/zpay32"
)
// Fuzz_decode is used by go-fuzz.
func Fuzz_decode(data []byte) int {
inv, err := zpay32.Decode(string(data), &chaincfg.TestNet3Params)
if err != nil {
return 1
}
// Call these functions as a sanity check to make sure the invoice
// is well-formed.
_ = inv.MinFinalCLTVExpiry()
_ = inv.Expiry()
return 1
}

View File

@ -1,52 +0,0 @@
//go:build gofuzz
// +build gofuzz
package zpay32fuzz
import (
"encoding/hex"
"fmt"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/lightningnetwork/lnd/zpay32"
)
// Fuzz_encode is used by go-fuzz.
func Fuzz_encode(data []byte) int {
inv, err := zpay32.Decode(string(data), &chaincfg.TestNet3Params)
if err != nil {
return 1
}
// Call these functions as a sanity check to make sure the invoice
// is well-formed.
_ = inv.MinFinalCLTVExpiry()
_ = inv.Expiry()
// Initialize the static key we will be using for this fuzz test.
testPrivKeyBytes, _ := hex.DecodeString("e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734")
testPrivKey, _ := btcec.PrivKeyFromBytes(testPrivKeyBytes)
// Then, initialize the testMessageSigner so we can encode out
// invoices with this private key.
testMessageSigner := zpay32.MessageSigner{
SignCompact: func(msg []byte) ([]byte, error) {
hash := chainhash.HashB(msg)
sig, err := ecdsa.SignCompact(testPrivKey, hash, true)
if err != nil {
return nil, fmt.Errorf("can't sign the "+
"message: %v", err)
}
return sig, nil
},
}
_, err = inv.Encode(testMessageSigner)
if err != nil {
return 1
}
return 1
}

798
lnwire/fuzz_test.go Normal file
View File

@ -0,0 +1,798 @@
package lnwire
import (
"bytes"
"compress/zlib"
"encoding/binary"
"reflect"
"testing"
)
// prefixWithMsgType takes []byte and adds a wire protocol prefix
// to make the []byte into an actual message to be used in fuzzing.
func prefixWithMsgType(data []byte, prefix MessageType) []byte {
var prefixBytes [2]byte
binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix))
data = append(prefixBytes[:], data...)
return data
}
// harness performs the actual fuzz testing of the appropriate wire message.
// This function will check that the passed-in message passes wire length
// checks, is a valid message once deserialized, and passes a sequence of
// serialization and deserialization checks.
func harness(t *testing.T, data []byte) {
t.Helper()
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Check that the created message is not greater than the maximum
// message size.
if len(data) > MaxSliceLength {
return
}
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic
t.Fatal(err)
}
// Deserialize the message from the serialized bytes buffer, and then
// assert that the original message is equal to the newly deserialized
// message.
newMsg, err := ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer, panic
t.Fatal(err)
}
if !reflect.DeepEqual(msg, newMsg) {
// Deserialized message and original message are not deeply
// equal.
t.Fatal("original message and deserialized message are not " +
"deeply equal")
}
}
func FuzzAcceptChannel(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
data = prefixWithMsgType(data, MsgAcceptChannel)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message
// type) is less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > MaxMsgBody {
return
}
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic
t.Fatal(err)
}
// Deserialize the message from the serialized bytes buffer, and
// then assert that the original message is equal to the newly
// deserialized message.
newMsg, err := ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer,
// panic
t.Fatal(err)
}
// Now compare every field instead of using reflect.DeepEqual.
// For UpfrontShutdownScript, we only compare bytes. This
// probably takes up more branches than necessary, but that's
// fine for now.
var shouldPanic bool
first, ok := msg.(*AcceptChannel)
if !ok {
t.Fatal("message was not AcceptChannel")
}
second, ok := newMsg.(*AcceptChannel)
if !ok {
t.Fatal("new message was not AcceptChannel")
}
if !bytes.Equal(first.PendingChannelID[:],
second.PendingChannelID[:]) {
shouldPanic = true
}
if first.DustLimit != second.DustLimit {
shouldPanic = true
}
if first.MaxValueInFlight != second.MaxValueInFlight {
shouldPanic = true
}
if first.ChannelReserve != second.ChannelReserve {
shouldPanic = true
}
if first.HtlcMinimum != second.HtlcMinimum {
shouldPanic = true
}
if first.MinAcceptDepth != second.MinAcceptDepth {
shouldPanic = true
}
if first.CsvDelay != second.CsvDelay {
shouldPanic = true
}
if first.MaxAcceptedHTLCs != second.MaxAcceptedHTLCs {
shouldPanic = true
}
if !first.FundingKey.IsEqual(second.FundingKey) {
shouldPanic = true
}
if !first.RevocationPoint.IsEqual(second.RevocationPoint) {
shouldPanic = true
}
if !first.PaymentPoint.IsEqual(second.PaymentPoint) {
shouldPanic = true
}
if !first.DelayedPaymentPoint.IsEqual(
second.DelayedPaymentPoint) {
shouldPanic = true
}
if !first.HtlcPoint.IsEqual(second.HtlcPoint) {
shouldPanic = true
}
if !first.FirstCommitmentPoint.IsEqual(
second.FirstCommitmentPoint) {
shouldPanic = true
}
if !bytes.Equal(first.UpfrontShutdownScript,
second.UpfrontShutdownScript) {
shouldPanic = true
}
if shouldPanic {
t.Fatal("original message and deseralized message " +
"are not equal")
}
})
}
func FuzzAnnounceSignatures(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgAnnounceSignatures.
data = prefixWithMsgType(data, MsgAnnounceSignatures)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzChannelAnnouncement(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgChannelAnnouncement.
data = prefixWithMsgType(data, MsgChannelAnnouncement)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzChannelReestablish(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgChannelReestablish.
data = prefixWithMsgType(data, MsgChannelReestablish)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzChannelUpdate(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgChannelUpdate.
data = prefixWithMsgType(data, MsgChannelUpdate)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzClosingSigned(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgClosingSigned.
data = prefixWithMsgType(data, MsgClosingSigned)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzCommitSig(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgCommitSig.
data = prefixWithMsgType(data, MsgCommitSig)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzError(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgError.
data = prefixWithMsgType(data, MsgError)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzFundingCreated(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgFundingCreated.
data = prefixWithMsgType(data, MsgFundingCreated)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzFundingLocked(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgFundingLocked.
data = prefixWithMsgType(data, MsgFundingLocked)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzFundingSigned(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgFundingSigned.
data = prefixWithMsgType(data, MsgFundingSigned)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzGossipTimestampRange(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgGossipTimestampRange.
data = prefixWithMsgType(data, MsgGossipTimestampRange)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzInit(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgInit.
data = prefixWithMsgType(data, MsgInit)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzNodeAnnouncement(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgNodeAnnouncement.
data = prefixWithMsgType(data, MsgNodeAnnouncement)
// We have to do this here instead of in harness so that
// reflect.DeepEqual isn't called. Address (de)serialization
// messes up the fuzzing assertions.
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message
// type) is less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > MaxMsgBody {
return
}
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic
t.Fatal(err)
}
// Deserialize the message from the serialized bytes buffer, and
// then assert that the original message is equal to the newly
// deserialized message.
newMsg, err := ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer,
// panic
t.Fatal(err)
}
// Now compare every field instead of using reflect.DeepEqual
// for the Addresses field.
var shouldPanic bool
first, ok := msg.(*NodeAnnouncement)
if !ok {
t.Fatal("message was not NodeAnnouncement")
}
second, ok := newMsg.(*NodeAnnouncement)
if !ok {
t.Fatal("new message was not NodeAnnouncement")
}
if !bytes.Equal(first.Signature[:], second.Signature[:]) {
shouldPanic = true
}
if !reflect.DeepEqual(first.Features, second.Features) {
shouldPanic = true
}
if first.Timestamp != second.Timestamp {
shouldPanic = true
}
if !bytes.Equal(first.NodeID[:], second.NodeID[:]) {
shouldPanic = true
}
if !reflect.DeepEqual(first.RGBColor, second.RGBColor) {
shouldPanic = true
}
if !bytes.Equal(first.Alias[:], second.Alias[:]) {
shouldPanic = true
}
if len(first.Addresses) != len(second.Addresses) {
shouldPanic = true
}
for i := range first.Addresses {
if first.Addresses[i].String() !=
second.Addresses[i].String() {
shouldPanic = true
break
}
}
if !reflect.DeepEqual(first.ExtraOpaqueData,
second.ExtraOpaqueData) {
shouldPanic = true
}
if shouldPanic {
t.Fatal("original message and deserialized message " +
"are not equal")
}
})
}
func FuzzOpenChannel(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgOpenChannel.
data = prefixWithMsgType(data, MsgOpenChannel)
// We have to do this here instead of in harness so that
// reflect.DeepEqual isn't called. Because of the
// UpfrontShutdownScript encoding, the first message and second
// message aren't deeply equal since the first has a nil slice
// and the other has an empty slice.
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message
// type) is less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > MaxMsgBody {
return
}
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic
t.Fatal(err)
}
// Deserialize the message from the serialized bytes buffer, and
// then assert that the original message is equal to the newly
// deserialized message.
newMsg, err := ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer,
// panic
t.Fatal(err)
}
// Now compare every field instead of using reflect.DeepEqual.
// For UpfrontShutdownScript, we only compare bytes. This
// probably takes up more branches than necessary, but that's
// fine for now.
var shouldPanic bool
first, ok := msg.(*OpenChannel)
if !ok {
t.Fatal("message was not OpenChannel")
}
second, ok := newMsg.(*OpenChannel)
if !ok {
t.Fatal("new message was not OpenChannel")
}
if !first.ChainHash.IsEqual(&second.ChainHash) {
shouldPanic = true
}
if !bytes.Equal(first.PendingChannelID[:],
second.PendingChannelID[:]) {
shouldPanic = true
}
if first.FundingAmount != second.FundingAmount {
shouldPanic = true
}
if first.PushAmount != second.PushAmount {
shouldPanic = true
}
if first.DustLimit != second.DustLimit {
shouldPanic = true
}
if first.MaxValueInFlight != second.MaxValueInFlight {
shouldPanic = true
}
if first.ChannelReserve != second.ChannelReserve {
shouldPanic = true
}
if first.HtlcMinimum != second.HtlcMinimum {
shouldPanic = true
}
if first.FeePerKiloWeight != second.FeePerKiloWeight {
shouldPanic = true
}
if first.CsvDelay != second.CsvDelay {
shouldPanic = true
}
if first.MaxAcceptedHTLCs != second.MaxAcceptedHTLCs {
shouldPanic = true
}
if !first.FundingKey.IsEqual(second.FundingKey) {
shouldPanic = true
}
if !first.RevocationPoint.IsEqual(second.RevocationPoint) {
shouldPanic = true
}
if !first.PaymentPoint.IsEqual(second.PaymentPoint) {
shouldPanic = true
}
if !first.DelayedPaymentPoint.IsEqual(
second.DelayedPaymentPoint) {
shouldPanic = true
}
if !first.HtlcPoint.IsEqual(second.HtlcPoint) {
shouldPanic = true
}
if !first.FirstCommitmentPoint.IsEqual(
second.FirstCommitmentPoint) {
shouldPanic = true
}
if first.ChannelFlags != second.ChannelFlags {
shouldPanic = true
}
if !bytes.Equal(first.UpfrontShutdownScript,
second.UpfrontShutdownScript) {
shouldPanic = true
}
if shouldPanic {
t.Fatal("original message and deserialized message " +
"are not equal")
}
})
}
func FuzzPing(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgPing.
data = prefixWithMsgType(data, MsgPing)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzPong(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgPong.
data = prefixWithMsgType(data, MsgPong)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzQueryChannelRange(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgQueryChannelRange.
data = prefixWithMsgType(data, MsgQueryChannelRange)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzZlibQueryShortChanIDs(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
var buf bytes.Buffer
zlibWriter := zlib.NewWriter(&buf)
_, err := zlibWriter.Write(data)
if err != nil {
// Zlib bug?
t.Fatal(err)
}
if err := zlibWriter.Close(); err != nil {
// Zlib bug?
t.Fatal(err)
}
compressedPayload := buf.Bytes()
chainhash := []byte("00000000000000000000000000000000")
numBytesInBody := len(compressedPayload) + 1
zlibByte := []byte("\x01")
bodyBytes := make([]byte, 2)
binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody))
payload := chainhash
payload = append(payload, bodyBytes...)
payload = append(payload, zlibByte...)
payload = append(payload, compressedPayload...)
// Prefix with MsgQueryShortChanIDs.
payload = prefixWithMsgType(payload, MsgQueryShortChanIDs)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, payload)
})
}
func FuzzQueryShortChanIDs(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgQueryShortChanIDs.
data = prefixWithMsgType(data, MsgQueryShortChanIDs)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzZlibReplyChannelRange(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
var buf bytes.Buffer
zlibWriter := zlib.NewWriter(&buf)
_, err := zlibWriter.Write(data)
if err != nil {
// Zlib bug?
t.Fatal(err)
}
if err := zlibWriter.Close(); err != nil {
// Zlib bug?
t.Fatal(err)
}
compressedPayload := buf.Bytes()
// Initialize some []byte vars which will prefix our payload
chainhash := []byte("00000000000000000000000000000000")
firstBlockHeight := []byte("\x00\x00\x00\x00")
numBlocks := []byte("\x00\x00\x00\x00")
completeByte := []byte("\x00")
numBytesInBody := len(compressedPayload) + 1
zlibByte := []byte("\x01")
bodyBytes := make([]byte, 2)
binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody))
payload := chainhash
payload = append(payload, firstBlockHeight...)
payload = append(payload, numBlocks...)
payload = append(payload, completeByte...)
payload = append(payload, bodyBytes...)
payload = append(payload, zlibByte...)
payload = append(payload, compressedPayload...)
// Prefix with MsgReplyChannelRange.
payload = prefixWithMsgType(payload, MsgReplyChannelRange)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, payload)
})
}
func FuzzReplyChannelRange(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgReplyChannelRange.
data = prefixWithMsgType(data, MsgReplyChannelRange)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzReplyShortChanIDsEnd(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgReplyShortChanIDsEnd.
data = prefixWithMsgType(data, MsgReplyShortChanIDsEnd)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzRevokeAndAck(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgRevokeAndAck.
data = prefixWithMsgType(data, MsgRevokeAndAck)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzShutdown(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgShutdown.
data = prefixWithMsgType(data, MsgShutdown)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzUpdateAddHTLC(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateAddHTLC.
data = prefixWithMsgType(data, MsgUpdateAddHTLC)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzUpdateFailHTLC(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateFailHTLC.
data = prefixWithMsgType(data, MsgUpdateFailHTLC)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzUpdateFailMalformedHTLC(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateFailMalformedHTLC.
data = prefixWithMsgType(data, MsgUpdateFailMalformedHTLC)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzUpdateFee(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateFee.
data = prefixWithMsgType(data, MsgUpdateFee)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}
func FuzzUpdateFulfillHTLC(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateFulFillHTLC.
data = prefixWithMsgType(data, MsgUpdateFulfillHTLC)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
})
}

View File

@ -0,0 +1,186 @@
package wtwire
import (
"bytes"
"encoding/binary"
"reflect"
"testing"
)
// prefixWithMsgType takes []byte and adds a wire protocol prefix
// to make the []byte into an actual message to be used in fuzzing.
func prefixWithMsgType(data []byte, prefix MessageType) []byte {
var prefixBytes [2]byte
binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix))
data = append(prefixBytes[:], data...)
return data
}
// harness performs the actual fuzz testing of the appropriate wire message.
// This function will check that the passed-in message passes wire length
// checks, is a valid message once deserialized, and passes a sequence of
// serialization and deserialization checks. Returns an int that determines
// whether the input is unique or not.
func harness(t *testing.T, data []byte, emptyMsg Message) {
t.Helper()
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message type) is
// less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > emptyMsg.MaxPayloadLength(0) {
// Ignore this input - max payload constraint violated.
return
}
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
if _, err := WriteMessage(&b, msg, 0); err != nil {
// Could not serialize message into bytes buffer, panic.
t.Fatal(err)
}
// Deserialize the message from the serialized bytes buffer, and then
// assert that the original message is equal to the newly deserialized
// message.
newMsg, err := ReadMessage(&b, 0)
if err != nil {
// Could not deserialize message from bytes buffer, panic.
t.Fatal(err)
}
if !reflect.DeepEqual(msg, newMsg) {
// Deserialized message and original message are not
// deeply equal.
t.Fatal("deserialized message and original message " +
"are not deeply equal.")
}
}
func FuzzCreateSessionReply(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgCreateSessionReply.
data = prefixWithMsgType(data, MsgCreateSessionReply)
// Create an empty message so that the FuzzHarness func can
// check if the max payload constraint is violated.
emptyMsg := CreateSessionReply{}
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data, &emptyMsg)
})
}
func FuzzCreateSession(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgCreateSession.
data = prefixWithMsgType(data, MsgCreateSession)
// Create an empty message so that the FuzzHarness func can
// check if the max payload constraint is violated.
emptyMsg := CreateSession{}
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data, &emptyMsg)
})
}
func FuzzDeleteSessionReply(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgDeleteSessionReply.
data = prefixWithMsgType(data, MsgDeleteSessionReply)
// Create an empty message so that the FuzzHarness func can
// check if the max payload constraint is violated.
emptyMsg := DeleteSessionReply{}
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data, &emptyMsg)
})
}
func FuzzDeleteSession(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgDeleteSession.
data = prefixWithMsgType(data, MsgDeleteSession)
// Create an empty message so that the FuzzHarness func can
// check if the max payload constraint is violated.
emptyMsg := DeleteSession{}
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data, &emptyMsg)
})
}
func FuzzError(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgError.
data = prefixWithMsgType(data, MsgError)
// Create an empty message so that the FuzzHarness func can
// check if the max payload constraint is violated.
emptyMsg := Error{}
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data, &emptyMsg)
})
}
func FuzzInit(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgInit.
data = prefixWithMsgType(data, MsgInit)
// Create an empty message so that the FuzzHarness func can
// check if the max payload constraint is violated.
emptyMsg := Init{}
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data, &emptyMsg)
})
}
func FuzzStateUpdateReply(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgStateUpdateReply.
data = prefixWithMsgType(data, MsgStateUpdateReply)
// Create an empty message so that the FuzzHarness func can
// check if the max payload constraint is violated.
emptyMsg := StateUpdateReply{}
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data, &emptyMsg)
})
}
func FuzzStateUpdate(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgStateUpdate.
data = prefixWithMsgType(data, MsgStateUpdate)
// Create an empty message so that the FuzzHarness func can
// check if the max payload constraint is violated.
emptyMsg := StateUpdate{}
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data, &emptyMsg)
})
}

66
zpay32/fuzz_test.go Normal file
View File

@ -0,0 +1,66 @@
package zpay32
import (
"encoding/hex"
"fmt"
"testing"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
)
func FuzzDecode(f *testing.F) {
f.Fuzz(func(t *testing.T, data string) {
inv, err := Decode(data, &chaincfg.TestNet3Params)
if err != nil {
return
}
// Call these functions as a sanity check to make sure the
// invoice is well-formed.
_ = inv.MinFinalCLTVExpiry()
_ = inv.Expiry()
})
}
func FuzzEncode(f *testing.F) {
f.Fuzz(func(t *testing.T, data string) {
inv, err := Decode(data, &chaincfg.TestNet3Params)
if err != nil {
return
}
// Call these functions as a sanity check to make sure the
// invoice is well-formed.
_ = inv.MinFinalCLTVExpiry()
_ = inv.Expiry()
// Initialize the static key we will be using for this fuzz
// test.
testPrivKeyBytes, _ := hex.DecodeString("e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734") // nolint:lll
testPrivKey, _ := btcec.PrivKeyFromBytes(testPrivKeyBytes)
// Then, initialize the testMessageSigner so we can encode out
// invoices with this private key.
testMessageSigner := MessageSigner{
SignCompact: func(msg []byte) ([]byte, error) {
hash := chainhash.HashB(msg)
sig, err := ecdsa.SignCompact(testPrivKey, hash,
true)
if err != nil {
return nil,
fmt.Errorf("can't sign the "+
"message: %v", err)
}
return sig, nil
},
}
_, err = inv.Encode(testMessageSigner)
if err != nil {
return
}
})
}