From f7e9509f7158bfcda0e7e7c267dfc5bfd6434495 Mon Sep 17 00:00:00 2001 From: Mark Gritter Date: Wed, 8 May 2019 00:00:30 -0700 Subject: [PATCH] Robsustness checks against malformed input. --- ber.go | 22 +++++++++++++++++++++- ber_test.go | 9 ++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/ber.go b/ber.go index 89e96d3..c616b00 100644 --- a/ber.go +++ b/ber.go @@ -135,14 +135,24 @@ func encodeLength(out *bytes.Buffer, length int) (err error) { func readObject(ber []byte, offset int) (asn1Object, int, error) { //fmt.Printf("\n====> Starting readObject at offset: %d\n\n", offset) tagStart := offset + if offset >= len(ber) { + return nil, 0, errors.New("ber2der: not enough bytes to read tag") + } b := ber[offset] offset++ + tag := b & 0x1F // last 5 bits if tag == 0x1F { tag = 0 + if offset >= len(ber) { + return nil, 0, errors.New("ber2der: not enough bytes to read tag") + } for ber[offset] >= 0x80 { tag = tag*128 + ber[offset] - 0x80 offset++ + if offset >= len(ber) { + return nil, 0, errors.New("ber2der: not enough bytes to read tag") + } } tag = tag*128 + ber[offset] - 0x80 offset++ @@ -159,10 +169,17 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) { */ // read length var length int + if offset >= len(ber) { + return nil, 0, errors.New("ber2der: not enough bytes to read length") + } l := ber[offset] offset++ indefinite := false if l > 0x80 { + if offset >= len(ber) { + return nil, 0, errors.New("ber2der: not enough bytes to read length") + } + numberOfBytes := (int)(l & 0x7F) if numberOfBytes > 4 { // int is only guaranteed to be 32bit return nil, 0, errors.New("ber2der: BER tag length too long") @@ -173,6 +190,9 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) { if 0x0 == (int)(ber[offset]) { return nil, 0, errors.New("ber2der: BER tag length has leading zero") } + if offset+numberOfBytes > len(ber) { + return nil, 0, errors.New("ber2der: not enough bytes to read length") + } //fmt.Printf("--> (compute length) indicator byte: %x\n", l) //fmt.Printf("--> (compute length) length bytes: % X\n", ber[offset:offset+numberOfBytes]) for i := 0; i < numberOfBytes; i++ { @@ -240,7 +260,7 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) { } func isIndefiniteTermination(ber []byte, offset int) (bool, error) { - if len(ber) - offset < 2 { + if len(ber)-offset < 2 { return false, errors.New("ber2der: Invalid BER format") } diff --git a/ber_test.go b/ber_test.go index 19a0f51..c5f5be6 100644 --- a/ber_test.go +++ b/ber_test.go @@ -42,11 +42,18 @@ func TestBer2Der_Negatives(t *testing.T) { Input []byte ErrorContains string }{ - {[]byte{0x30, 0x85}, "length too long"}, + {[]byte{0x30, 0x85}, "not enough"}, + {[]byte{0x30, 0x85, 0x00}, "length too long"}, {[]byte{0x30, 0x84, 0x80, 0x0, 0x0, 0x0}, "length is negative"}, {[]byte{0x30, 0x82, 0x0, 0x1}, "length has leading zero"}, {[]byte{0x30, 0x80, 0x1, 0x2, 0x1, 0x2}, "Invalid BER format"}, {[]byte{0x30, 0x03, 0x01, 0x02}, "length is more than available data"}, + {[]byte{0x1f}, "not enough bytes to read tag"}, + {[]byte{0x1f, 0x80, 0x81, 0xff}, "not enough bytes to read tag"}, + {[]byte{0x1f, 0x00}, "not enough bytes to read length"}, + {[]byte{0x1f, 0x00, 0xf0}, "not enough bytes to read length"}, + {[]byte{0x1f, 0x00, 0x83}, "not enough bytes to read length"}, + {[]byte{0x1f, 0x00, 0x83, 0xff}, "not enough bytes to read length"}, } for _, fixture := range fixtures {