From bcd66a43df33b6cbe12511b2a710af26a12ce9d3 Mon Sep 17 00:00:00 2001 From: Evgeny Khirin <32414982+evgeny-khirin@users.noreply.github.com> Date: Wed, 26 Dec 2018 12:40:28 +0200 Subject: [PATCH] [DEV-321] btcec/signature: fix DoS bug with signature parsing (#132) * [DEV-321] btcec/signature: fix DoS bug with signature parsing * [DEV-321] Added test for short signature --- btcec/signature.go | 14 ++++++++++---- btcec/signature_test.go | 12 ++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/btcec/signature.go b/btcec/signature.go index 6026c4241..a4781b00f 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -85,6 +85,11 @@ func (sig *Signature) IsEqual(otherSig *Signature) bool { sig.S.Cmp(otherSig.S) == 0 } +// minSigLen is the minimum length of a DER encoded signature and is +// when both R and S are 1 byte each. +// 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + +const minSigLen = 8 + func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) { // Originally this code used encoding/asn1 in order to parse the // signature, but a number of problems were found with this approach. @@ -98,9 +103,7 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) signature := &Signature{} - // minimal message is when both numbers are 1 bytes. adding up to: - // 0x30 + len + 0x02 + 0x01 + + 0x2 + 0x01 + - if len(sigStr) < 8 { + if len(sigStr) < minSigLen { return nil, errors.New("malformed signature: too short") } // 0x30 @@ -112,7 +115,10 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) // length of remaining message siglen := sigStr[index] index++ - if int(siglen+2) > len(sigStr) { + + // siglen should be less than the entire message and greater than + // the minimal message size. + if int(siglen+2) > len(sigStr) || int(siglen+2) < minSigLen { return nil, errors.New("malformed signature: bad length") } // trim the slice we're working on so we only look at what matters. diff --git a/btcec/signature_test.go b/btcec/signature_test.go index a8b3e1e98..69c8d79f0 100644 --- a/btcec/signature_test.go +++ b/btcec/signature_test.go @@ -112,6 +112,18 @@ var signatureTests = []signatureTest{ der: true, isValid: false, }, + { + name: "invalid message length", + sig: []byte{0x30, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00}, + der: false, + isValid: false, + }, + { + name: "too short signature", + sig: []byte{0x30, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01}, + der: false, + isValid: false, + }, { name: "long len", sig: []byte{0x30, 0x45, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,