Browse Source

tests/fuzzers/bls1381: add bls fuzzer (#21796)

* added bls fuzzer

* crypto/bls12381: revert bls-changes, fixup fuzzer tests

* fuzzers: split bls fuzzing into 8 different units

* fuzzers/bls: remove (now stale) corpus

* crypto/bls12381: added blsfuzz corpus

* fuzzers/bls12381: fix the bls corpus

* fuzzers: fix oss-fuzz script

* tests/fuzzers: fixups on bls corpus

* test/fuzzers: remove leftover corpus

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
Martin Holst Swende 5 years ago
parent
commit
6104ab6b6d

+ 9 - 0
crypto/bls12381/fp_test.go

@@ -1393,6 +1393,15 @@ func BenchmarkMultiplication(t *testing.B) {
 	}
 }
 
+func BenchmarkInverse(t *testing.B) {
+	a, _ := new(fe).rand(rand.Reader)
+	b, _ := new(fe).rand(rand.Reader)
+	t.ResetTimer()
+	for i := 0; i < t.N; i++ {
+		inverse(a, b)
+	}
+}
+
 func padBytes(in []byte, size int) []byte {
 	out := make([]byte, size)
 	if len(in) > size {

+ 18 - 1
oss-fuzz.sh

@@ -30,13 +30,20 @@ function compile_fuzzer {
   path=$SRC/go-ethereum/$1
   func=$2
   fuzzer=$3
-  echo "Building $fuzzer"
+  corpusfile="${path}/testdata/${fuzzer}_seed_corpus.zip"
+  echo "Building $fuzzer (expecting corpus at $corpusfile)"
   (cd $path && \
         go-fuzz -func $func -o $WORK/$fuzzer.a . && \
         echo "First stage built OK" && \
         $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $WORK/$fuzzer.a -o $OUT/$fuzzer && \
         echo "Second stage built ok" )
 
+        ## Check if there exists a seed corpus file
+        if [ -f $corpusfile ]
+        then
+          cp $corpusfile $OUT/
+          echo "Found seed corpus: $corpusfile"
+        fi
 }
 
 compile_fuzzer common/bitutil  Fuzz      fuzzBitutilCompress
@@ -51,6 +58,16 @@ compile_fuzzer tests/fuzzers/rlp        Fuzz fuzzRlp
 compile_fuzzer tests/fuzzers/trie       Fuzz fuzzTrie
 compile_fuzzer tests/fuzzers/stacktrie  Fuzz fuzzStackTrie
 
+compile_fuzzer tests/fuzzers/bls12381  FuzzG1Add fuzz_g1_add
+compile_fuzzer tests/fuzzers/bls12381  FuzzG1Mul fuzz_g1_mul
+compile_fuzzer tests/fuzzers/bls12381  FuzzG1MultiExp fuzz_g1_multiexp
+compile_fuzzer tests/fuzzers/bls12381  FuzzG2Add fuzz_g2_add
+compile_fuzzer tests/fuzzers/bls12381  FuzzG2Mul fuzz_g2_mul
+compile_fuzzer tests/fuzzers/bls12381  FuzzG2MultiExp fuzz_g2_multiexp
+compile_fuzzer tests/fuzzers/bls12381  FuzzPairing fuzz_pairing
+compile_fuzzer tests/fuzzers/bls12381  FuzzMapG1 fuzz_map_g1
+compile_fuzzer tests/fuzzers/bls12381  FuzzMapG2 fuzz_map_g2
+
 # This doesn't work very well @TODO
 #compile_fuzzertests/fuzzers/abi Fuzz fuzzAbi
 

+ 101 - 0
tests/fuzzers/bls12381/bls_fuzzer.go

@@ -0,0 +1,101 @@
+// Copyright 2020 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package bls
+
+import (
+	"bytes"
+	"fmt"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/core/vm"
+)
+
+const (
+	blsG1Add      = byte(10)
+	blsG1Mul      = byte(11)
+	blsG1MultiExp = byte(12)
+	blsG2Add      = byte(13)
+	blsG2Mul      = byte(14)
+	blsG2MultiExp = byte(15)
+	blsPairing    = byte(16)
+	blsMapG1      = byte(17)
+	blsMapG2      = byte(18)
+)
+
+func FuzzG1Add(data []byte) int      { return fuzz(blsG1Add, data) }
+func FuzzG1Mul(data []byte) int      { return fuzz(blsG1Mul, data) }
+func FuzzG1MultiExp(data []byte) int { return fuzz(blsG1MultiExp, data) }
+func FuzzG2Add(data []byte) int      { return fuzz(blsG2Add, data) }
+func FuzzG2Mul(data []byte) int      { return fuzz(blsG2Mul, data) }
+func FuzzG2MultiExp(data []byte) int { return fuzz(blsG2MultiExp, data) }
+func FuzzPairing(data []byte) int    { return fuzz(blsPairing, data) }
+func FuzzMapG1(data []byte) int      { return fuzz(blsMapG1, data) }
+func FuzzMapG2(data []byte) int      { return fuzz(blsMapG2, data) }
+
+func checkInput(id byte, inputLen int) bool {
+	switch id {
+	case blsG1Add:
+		return inputLen == 256
+	case blsG1Mul:
+		return inputLen == 160
+	case blsG1MultiExp:
+		return inputLen%160 == 0
+	case blsG2Add:
+		return inputLen == 512
+	case blsG2Mul:
+		return inputLen == 288
+	case blsG2MultiExp:
+		return inputLen%288 == 0
+	case blsPairing:
+		return inputLen%384 == 0
+	case blsMapG1:
+		return inputLen == 64
+	case blsMapG2:
+		return inputLen == 128
+	}
+	panic("programmer error")
+}
+
+// The fuzzer functions must return
+// 1 if the fuzzer should increase priority of the
+//    given input during subsequent fuzzing (for example, the input is lexically
+//    correct and was parsed successfully);
+// -1 if the input must not be added to corpus even if gives new coverage; and
+// 0  otherwise
+// other values are reserved for future use.
+func fuzz(id byte, data []byte) int {
+	// Even on bad input, it should not crash, so we still test the gas calc
+	precompile := vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{id})]
+	gas := precompile.RequiredGas(data)
+	if !checkInput(id, len(data)) {
+		return 0
+	}
+	// If the gas cost is too large (25M), bail out
+	if gas > 25*1000*1000 {
+		return 0
+	}
+	cpy := make([]byte, len(data))
+	copy(cpy, data)
+	_, err := precompile.Run(cpy)
+	if !bytes.Equal(cpy, data) {
+		panic(fmt.Sprintf("input data modified, precompile %d: %x %x", id, data, cpy))
+	}
+	if err != nil {
+		return 0
+	}
+	return 1
+}

BIN
tests/fuzzers/bls12381/testdata/fuzz_g1_add_seed_corpus.zip


BIN
tests/fuzzers/bls12381/testdata/fuzz_g1_mul_seed_corpus.zip


BIN
tests/fuzzers/bls12381/testdata/fuzz_g1_multiexp_seed_corpus.zip


BIN
tests/fuzzers/bls12381/testdata/fuzz_g2_add_seed_corpus.zip


BIN
tests/fuzzers/bls12381/testdata/fuzz_g2_mul_seed_corpus.zip


BIN
tests/fuzzers/bls12381/testdata/fuzz_g2_multiexp_seed_corpus.zip


BIN
tests/fuzzers/bls12381/testdata/fuzz_map_g1_seed_corpus.zip


BIN
tests/fuzzers/bls12381/testdata/fuzz_map_g2_seed_corpus.zip


BIN
tests/fuzzers/bls12381/testdata/fuzz_pairing_seed_corpus.zip