Skip to content

Commit 978e39e

Browse files
FiloSottilerolandshoemaker
authored andcommitted
crypto/elliptic: tolerate large inputs to IsOnCurve methods
The behavior of all Curve methods and package functions when provided an off-curve point is undefined, except for IsOnCurve which should really always return false, not panic. Change-Id: I52f65df25c5af0314fef2c63d0778db72c0f1313 Reviewed-on: https://go-review.googlesource.com/c/go/+/361402 Trust: Filippo Valsorda <[email protected]> Run-TryBot: Filippo Valsorda <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]> TryBot-Result: Go Bot <[email protected]>
1 parent 99699d1 commit 978e39e

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

src/crypto/elliptic/elliptic_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,16 @@ func testMarshalCompressed(t *testing.T, curve Curve, x, y *big.Int, want []byte
241241
}
242242
}
243243

244+
func TestLargeIsOnCurve(t *testing.T) {
245+
testAllCurves(t, func(t *testing.T, curve Curve) {
246+
large := big.NewInt(1)
247+
large.Lsh(large, 1000)
248+
if curve.IsOnCurve(large, large) {
249+
t.Errorf("(2^1000, 2^1000) is reported on the curve")
250+
}
251+
})
252+
}
253+
244254
func benchmarkAllCurves(t *testing.B, f func(*testing.B, Curve)) {
245255
tests := []struct {
246256
name string

src/crypto/elliptic/p224.go

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ func (curve p224Curve) Params() *CurveParams {
5050
}
5151

5252
func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool {
53+
if bigX.BitLen() > 224 || bigY.BitLen() > 224 {
54+
return false
55+
}
56+
5357
var x, y p224FieldElement
5458
p224FromBig(&x, bigX)
5559
p224FromBig(&y, bigY)

src/crypto/elliptic/p521.go

+11-5
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,25 @@ func (curve p521Curve) Params() *CurveParams {
5555
}
5656

5757
func (curve p521Curve) IsOnCurve(x, y *big.Int) bool {
58-
// IsOnCurve is documented to reject (0, 0), so we don't use
59-
// p521PointFromAffine, but let SetBytes reject the invalid Marshal output.
60-
_, err := nistec.NewP521Point().SetBytes(Marshal(curve, x, y))
61-
return err == nil
58+
// IsOnCurve is documented to reject (0, 0), the conventional point at
59+
// infinity, which however is accepted by p521PointFromAffine.
60+
if x.Sign() == 0 && y.Sign() == 0 {
61+
return false
62+
}
63+
_, ok := p521PointFromAffine(x, y)
64+
return ok
6265
}
6366

6467
func p521PointFromAffine(x, y *big.Int) (p *nistec.P521Point, ok bool) {
6568
// (0, 0) is by convention the point at infinity, which can't be represented
6669
// in affine coordinates. Marshal incorrectly encodes it as an uncompressed
67-
// point, which SetBytes correctly rejects. See Issue 37294.
70+
// point, which SetBytes would correctly reject. See Issue 37294.
6871
if x.Sign() == 0 && y.Sign() == 0 {
6972
return nistec.NewP521Point(), true
7073
}
74+
if x.BitLen() > 521 || y.BitLen() > 521 {
75+
return nil, false
76+
}
7177
p, err := nistec.NewP521Point().SetBytes(Marshal(P521(), x, y))
7278
if err != nil {
7379
return nil, false

0 commit comments

Comments
 (0)