Skip to content

Commit 47fbc2b

Browse files
holimanenriquefynn
authored andcommitted
crypto/bn256: improve bn256 fuzzer (ethereum#21815)
* crypto/cloudflare: fix nil deref in random G1/G2 reading * crypto/bn256: improve fuzzer * crypto/bn256: fix some flaws in fuzzer
1 parent b11eb36 commit 47fbc2b

File tree

2 files changed

+53
-66
lines changed

2 files changed

+53
-66
lines changed

crypto/bn256/bn256_fuzz.go

Lines changed: 52 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,52 @@ package bn256
88

99
import (
1010
"bytes"
11+
"fmt"
12+
"io"
1113
"math/big"
1214

1315
cloudflare "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
1416
google "github.com/ethereum/go-ethereum/crypto/bn256/google"
1517
)
1618

17-
// FuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries.
18-
func FuzzAdd(data []byte) int {
19-
// Ensure we have enough data in the first place
20-
if len(data) != 128 {
21-
return 0
19+
func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1) {
20+
_, xc, err := cloudflare.RandomG1(input)
21+
if err != nil {
22+
// insufficient input
23+
return nil, nil
2224
}
23-
// Ensure both libs can parse the first curve point
24-
xc := new(cloudflare.G1)
25-
_, errc := xc.Unmarshal(data[:64])
26-
2725
xg := new(google.G1)
28-
_, errg := xg.Unmarshal(data[:64])
29-
30-
if (errc == nil) != (errg == nil) {
31-
panic("parse mismatch")
32-
} else if errc != nil {
33-
return 0
26+
if _, err := xg.Unmarshal(xc.Marshal()); err != nil {
27+
panic(fmt.Sprintf("Could not marshal cloudflare -> google:", err))
3428
}
35-
// Ensure both libs can parse the second curve point
36-
yc := new(cloudflare.G1)
37-
_, errc = yc.Unmarshal(data[64:])
29+
return xc, xg
30+
}
3831

39-
yg := new(google.G1)
40-
_, errg = yg.Unmarshal(data[64:])
32+
func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2) {
33+
_, xc, err := cloudflare.RandomG2(input)
34+
if err != nil {
35+
// insufficient input
36+
return nil, nil
37+
}
38+
xg := new(google.G2)
39+
if _, err := xg.Unmarshal(xc.Marshal()); err != nil {
40+
panic(fmt.Sprintf("Could not marshal cloudflare -> google:", err))
41+
}
42+
return xc, xg
43+
}
4144

42-
if (errc == nil) != (errg == nil) {
43-
panic("parse mismatch")
44-
} else if errc != nil {
45+
// FuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries.
46+
func FuzzAdd(data []byte) int {
47+
input := bytes.NewReader(data)
48+
xc, xg := getG1Points(input)
49+
if xc == nil {
4550
return 0
4651
}
52+
yc, yg := getG1Points(input)
53+
if yc == nil {
54+
return 0
55+
}
56+
// Ensure both libs can parse the second curve point
4757
// Add the two points and ensure they result in the same output
4858
rc := new(cloudflare.G1)
4959
rc.Add(xc, yc)
@@ -54,73 +64,50 @@ func FuzzAdd(data []byte) int {
5464
if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
5565
panic("add mismatch")
5666
}
57-
return 0
67+
return 1
5868
}
5969

6070
// FuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare
6171
// libraries.
6272
func FuzzMul(data []byte) int {
63-
// Ensure we have enough data in the first place
64-
if len(data) != 96 {
73+
input := bytes.NewReader(data)
74+
pc, pg := getG1Points(input)
75+
if pc == nil {
6576
return 0
6677
}
67-
// Ensure both libs can parse the curve point
68-
pc := new(cloudflare.G1)
69-
_, errc := pc.Unmarshal(data[:64])
70-
71-
pg := new(google.G1)
72-
_, errg := pg.Unmarshal(data[:64])
73-
74-
if (errc == nil) != (errg == nil) {
75-
panic("parse mismatch")
76-
} else if errc != nil {
78+
// Add the two points and ensure they result in the same output
79+
remaining := input.Len()
80+
if remaining == 0 {
7781
return 0
7882
}
79-
// Add the two points and ensure they result in the same output
83+
buf := make([]byte, remaining)
84+
input.Read(buf)
85+
8086
rc := new(cloudflare.G1)
81-
rc.ScalarMult(pc, new(big.Int).SetBytes(data[64:]))
87+
rc.ScalarMult(pc, new(big.Int).SetBytes(buf))
8288

8389
rg := new(google.G1)
84-
rg.ScalarMult(pg, new(big.Int).SetBytes(data[64:]))
90+
rg.ScalarMult(pg, new(big.Int).SetBytes(buf))
8591

8692
if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
8793
panic("scalar mul mismatch")
8894
}
89-
return 0
95+
return 1
9096
}
9197

9298
func FuzzPair(data []byte) int {
93-
// Ensure we have enough data in the first place
94-
if len(data) != 192 {
99+
input := bytes.NewReader(data)
100+
pc, pg := getG1Points(input)
101+
if pc == nil {
95102
return 0
96103
}
97-
// Ensure both libs can parse the curve point
98-
pc := new(cloudflare.G1)
99-
_, errc := pc.Unmarshal(data[:64])
100-
101-
pg := new(google.G1)
102-
_, errg := pg.Unmarshal(data[:64])
103-
104-
if (errc == nil) != (errg == nil) {
105-
panic("parse mismatch")
106-
} else if errc != nil {
107-
return 0
108-
}
109-
// Ensure both libs can parse the twist point
110-
tc := new(cloudflare.G2)
111-
_, errc = tc.Unmarshal(data[64:])
112-
113-
tg := new(google.G2)
114-
_, errg = tg.Unmarshal(data[64:])
115-
116-
if (errc == nil) != (errg == nil) {
117-
panic("parse mismatch")
118-
} else if errc != nil {
104+
tc, tg := getG2Points(input)
105+
if tc == nil {
119106
return 0
120107
}
121108
// Pair the two points and ensure thet result in the same output
122109
if cloudflare.PairingCheck([]*cloudflare.G1{pc}, []*cloudflare.G2{tc}) != google.PairingCheck([]*google.G1{pg}, []*google.G2{tg}) {
123110
panic("pair mismatch")
124111
}
125-
return 0
112+
return 1
126113
}

crypto/bn256/cloudflare/bn256.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
func randomK(r io.Reader) (k *big.Int, err error) {
2424
for {
2525
k, err = rand.Int(r, Order)
26-
if k.Sign() > 0 || err != nil {
26+
if err != nil || k.Sign() > 0 {
2727
return
2828
}
2929
}

0 commit comments

Comments
 (0)