golang/go

x/crypto/openpgp: ReadMessage(): Panic on invalid input in math/big.nat.div() (division by zero)

marete opened this issue · 3 comments

The following program panics:

package main

import (
    "bytes"
    "encoding/hex"
    "io"
    "log"
    "os"

    "golang.org/x/crypto/openpgp"
)

// An empty Keyring
type emptyKR struct {
}

func (kr emptyKR) KeysById(id uint64) []openpgp.Key {
    return nil
}

func (kr emptyKR) DecryptionKeys() []openpgp.Key {
    return nil
}

func (kr emptyKR) KeysByIdUsage(uint64, byte) []openpgp.Key {
    return nil
}

var data = "9c3004303030300100000011303030000000000000010130303030303030303030303030303030303030303030303030303030303030303030303030303030303030"

func main() {
    buf, err := hex.DecodeString(data)
    if err != nil {
        log.Fatalln(err)
    }

    md, err := openpgp.ReadMessage(bytes.NewBuffer(buf), emptyKR{},
        func([]openpgp.Key, bool) ([]byte, error) {
            return []byte("insecure"), nil
        }, nil)

    if err != nil {
        log.Fatalln(err)
    }

    _, err = io.Copy(os.Stdout, md.UnverifiedBody)
    if err != nil {
        log.Fatalln(err)
    }

    if md.SignatureError != nil {
        log.Fatalln("integrity check failed")
    }
}

with the trace:

panic: division by zero

goroutine 1 [running]:
math/big.nat.div(0x0, 0x0, 0x0, 0xc20803c570, 0x0, 0x5, 0x0, 0x0, 0x0, 0xc20803c570, ...)
    /opt/go/src/math/big/nat.go:503 +0xcb
math/big.(*Int).QuoRem(0xc208020320, 0xc2080200e0, 0xc2080202e0, 0xc2080202e0, 0x1, 0x5)
    /opt/go/src/math/big/int.go:224 +0xb6
math/big.(*Int).Mod(0xc2080202e0, 0xc2080200e0, 0xc2080202e0, 0xc2080202e0)
    /opt/go/src/math/big/int.go:255 +0x15c
crypto/rsa.(*PrivateKey).Precompute(0xc208068000)
    /opt/go/src/crypto/rsa/rsa.go:376 +0x1ba
golang.org/x/crypto/openpgp/packet.(*PrivateKey).parseRSAPrivateKey(0xc208040000, 0xc208066000, 0x22, 0x600, 0x0, 0x0)
    /home/marebri/devel/go/src/golang.org/x/crypto/openpgp/packet/private_key.go:266 +0x520
golang.org/x/crypto/openpgp/packet.(*PrivateKey).parsePrivateKey(0xc208040000, 0xc208066000, 0x22, 0x600, 0x0, 0x0)
    /home/marebri/devel/go/src/golang.org/x/crypto/openpgp/packet/private_key.go:234 +0x6c
golang.org/x/crypto/openpgp/packet.(*PrivateKey).parse(0xc208040000, 0x7f5e808d1bc0, 0xc208020080, 0x0, 0x0)
    /home/marebri/devel/go/src/golang.org/x/crypto/openpgp/packet/private_key.go:103 +0x3f8
golang.org/x/crypto/openpgp/packet.Read(0x7f5e808d1b60, 0xc2080120e0, 0x7f5e808d1be8, 0xc208040000, 0x0, 0x0)
    /home/marebri/devel/go/src/golang.org/x/crypto/openpgp/packet/packet.go:375 +0x152
golang.org/x/crypto/openpgp/packet.(*Reader).Next(0xc20803c330, 0x0, 0x0, 0x0, 0x0)
    /home/marebri/devel/go/src/golang.org/x/crypto/openpgp/packet/reader.go:37 +0x10c
golang.org/x/crypto/openpgp.ReadMessage(0x7f5e808d1b60, 0xc2080120e0, 0x7f5e808d1b88, 0x68c0a8, 0x5f0860, 0x0, 0xc208062000, 0x0, 0x0)
    /home/marebri/devel/go/src/golang.org/x/crypto/openpgp/read.go:101 +0x206
main.main()
    /home/marebri/devel/lab/go/crypto/openpgp/issues/50eccec52/main.go:40 +0x285

goroutine 2 [runnable]:
runtime.forcegchelper()
    /opt/go/src/runtime/proc.go:90
runtime.goexit()
    /opt/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 3 [runnable]:
runtime.bgsweep()
    /opt/go/src/runtime/mgc0.go:82
runtime.goexit()
    /opt/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 4 [runnable]:
runtime.runfinq()
    /opt/go/src/runtime/malloc.go:712
runtime.goexit()
    /opt/go/src/runtime/asm_amd64.s:2232 +0x1

Found using gofuzz. You may assign this issue to me.

What version of Go?

go version go1.4.2 linux/amd64

CL https://golang.org/cl/12356 mentions this issue.