From be4c3dd9e4c1ac79de5c55755ce1171df963dd7d Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Wed, 31 Jul 2024 14:11:00 +0200 Subject: [PATCH] zpay32: enforce a cipher text upper limit To prevent an attacker from causing us to assign a huge in-memory buffer, we place a cap on the maximum cipher text size of a blinded path hop. --- zpay32/blinded_path.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/zpay32/blinded_path.go b/zpay32/blinded_path.go index 1f3adb8ce..0c4da57ee 100644 --- a/zpay32/blinded_path.go +++ b/zpay32/blinded_path.go @@ -4,7 +4,6 @@ import ( "encoding/binary" "fmt" "io" - "math" "github.com/btcsuite/btcd/btcec/v2" sphinx "github.com/lightningnetwork/lightning-onion" @@ -21,6 +20,12 @@ const ( // proposal](https://github.com/lightning/blips/pull/39) for a detailed // calculation. maxNumHopsPerPath = 7 + + // maxCipherTextLength defines the largest cipher text size allowed. + // This is derived by using the `data_length` upper bound of 639 bytes + // and then assuming the case of a path with only a single hop (meaning + // the cipher text may be as large as possible). + maxCipherTextLength = 535 ) var ( @@ -215,6 +220,12 @@ func DecodeBlindedHop(r io.Reader) (*sphinx.BlindedHopInfo, error) { return nil, err } + if dataLen > maxCipherTextLength { + return nil, fmt.Errorf("a blinded hop cipher text blob may "+ + "not exceed the maximum of %d bytes", + maxCipherTextLength) + } + encryptedData := make([]byte, dataLen) _, err = r.Read(encryptedData) if err != nil { @@ -238,9 +249,9 @@ func EncodeBlindedHop(w io.Writer, hop *sphinx.BlindedHopInfo) error { return err } - if len(hop.CipherText) > math.MaxUint16 { + if len(hop.CipherText) > maxCipherTextLength { return fmt.Errorf("encrypted recipient data can not exceed a "+ - "length of %d bytes", math.MaxUint16) + "length of %d bytes", maxCipherTextLength) } err = tlv.WriteVarInt(w, uint64(len(hop.CipherText)), &[8]byte{})