Skip to content

Commit f0c0e0f

Browse files
committed
crypto/elliptic: inline marshaling into nistec pointFromAffine
Marshal behavior for invalid points is undefined, so don't use it to check if points are valid. For #52182 Change-Id: If167893bc4b029f71bb2528564f2bd96bee7221c Reviewed-on: https://go-review.googlesource.com/c/go/+/382994 Run-TryBot: Filippo Valsorda <[email protected]> Reviewed-by: Russ Cox <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]>
1 parent 83ff0b0 commit f0c0e0f

File tree

1 file changed

+25
-21
lines changed

1 file changed

+25
-21
lines changed

src/crypto/elliptic/nistec.go

+25-21
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package elliptic
77
import (
88
"crypto/elliptic/internal/nistec"
99
"crypto/rand"
10+
"errors"
1011
"math/big"
1112
)
1213

@@ -114,28 +115,31 @@ func (curve *nistCurve[Point]) IsOnCurve(x, y *big.Int) bool {
114115
if x.Sign() == 0 && y.Sign() == 0 {
115116
return false
116117
}
117-
_, ok := curve.pointFromAffine(x, y)
118-
return ok
118+
_, err := curve.pointFromAffine(x, y)
119+
return err == nil
119120
}
120121

121-
func (curve *nistCurve[Point]) pointFromAffine(x, y *big.Int) (p Point, ok bool) {
122+
func (curve *nistCurve[Point]) pointFromAffine(x, y *big.Int) (p Point, err error) {
123+
p = curve.newPoint()
122124
// (0, 0) is by convention the point at infinity, which can't be represented
123-
// in affine coordinates. Marshal incorrectly encodes it as an uncompressed
124-
// point, which SetBytes would correctly reject. See Issue 37294.
125+
// in affine coordinates. See Issue 37294.
125126
if x.Sign() == 0 && y.Sign() == 0 {
126-
return curve.newPoint(), true
127+
return p, nil
127128
}
129+
// Reject values that would not get correctly encoded.
128130
if x.Sign() < 0 || y.Sign() < 0 {
129-
return curve.newPoint(), false
131+
return p, errors.New("negative coordinate")
130132
}
131133
if x.BitLen() > curve.params.BitSize || y.BitLen() > curve.params.BitSize {
132-
return *new(Point), false
134+
return p, errors.New("overflowing coordinate")
133135
}
134-
p, err := curve.newPoint().SetBytes(Marshal(curve, x, y))
135-
if err != nil {
136-
return *new(Point), false
137-
}
138-
return p, true
136+
// Encode the coordinates and let SetBytes reject invalid points.
137+
byteLen := (curve.params.BitSize + 7) / 8
138+
buf := make([]byte, 1+2*byteLen)
139+
buf[0] = 4 // uncompressed point
140+
x.FillBytes(buf[1 : 1+byteLen])
141+
y.FillBytes(buf[1+byteLen : 1+2*byteLen])
142+
return p.SetBytes(buf)
139143
}
140144

141145
func (curve *nistCurve[Point]) pointToAffine(p Point) (x, y *big.Int) {
@@ -170,28 +174,28 @@ func (curve *nistCurve[Point]) randomPoint() (x, y *big.Int) {
170174
}
171175

172176
func (curve *nistCurve[Point]) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
173-
p1, ok := curve.pointFromAffine(x1, y1)
174-
if !ok {
177+
p1, err := curve.pointFromAffine(x1, y1)
178+
if err != nil {
175179
return curve.randomPoint()
176180
}
177-
p2, ok := curve.pointFromAffine(x2, y2)
178-
if !ok {
181+
p2, err := curve.pointFromAffine(x2, y2)
182+
if err != nil {
179183
return curve.randomPoint()
180184
}
181185
return curve.pointToAffine(p1.Add(p1, p2))
182186
}
183187

184188
func (curve *nistCurve[Point]) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
185-
p, ok := curve.pointFromAffine(x1, y1)
186-
if !ok {
189+
p, err := curve.pointFromAffine(x1, y1)
190+
if err != nil {
187191
return curve.randomPoint()
188192
}
189193
return curve.pointToAffine(p.Double(p))
190194
}
191195

192196
func (curve *nistCurve[Point]) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
193-
p, ok := curve.pointFromAffine(Bx, By)
194-
if !ok {
197+
p, err := curve.pointFromAffine(Bx, By)
198+
if err != nil {
195199
return curve.randomPoint()
196200
}
197201
return curve.pointToAffine(p.ScalarMult(p, scalar))

0 commit comments

Comments
 (0)