[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
This commit is contained in:
Evgeny Khirin 2018-12-26 12:40:28 +02:00 committed by stasatdaglabs
parent ca084f595e
commit bcd66a43df
2 changed files with 22 additions and 4 deletions

View File

@ -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 + <byte> + 0x2 + 0x01 + <byte>
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 + <byte> + 0x2 + 0x01 + <byte>
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.

View File

@ -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,