Skip to content

Commit d1c650a

Browse files
committed
extra: initialize receiver in MultiScalarMult
(*Point).MultiScalarMult failed to initialize its receiver. If the method is called on an initialized point that is not the identity point, MultiScalarMult produces an incorrect result. If the method is called on an uninitialized point, the behavior is undefined. In particular, if the receiver is the zero value, MultiScalarMult returns an invalid point that compares Equal to every point. This was independently reported by @WeebDataHoarder and @shaharcohen1. Fixes CVE-2026-26958 Fixes GHSA-fw7p-63qq-7hpr
1 parent 325f520 commit d1c650a

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

edwards25519_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ var I = NewIdentityPoint()
1818
func checkOnCurve(t *testing.T, points ...*Point) {
1919
t.Helper()
2020
for i, p := range points {
21+
if p.z.Equal(new(field.Element)) == 1 {
22+
t.Errorf("point %d has Z == 0 (degenerate projective point)", i)
23+
}
2124
var XX, YY, ZZ, ZZZZ field.Element
2225
XX.Square(&p.x)
2326
YY.Square(&p.y)

extra.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ func (v *Point) MultiScalarMult(scalars []*Scalar, points []*Point) *Point {
265265
tmp1 := &projP1xP1{}
266266
tmp2 := &projP2{}
267267
// Lookup-and-add the appropriate multiple of each input point
268+
v.Set(NewIdentityPoint())
268269
for j := range tables {
269270
tables[j].SelectInto(multiple, digits[j][63])
270271
tmp1.Add(v, multiple) // tmp1 = v + x_(j,63)*Q in P1xP1 coords

extra_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,36 @@ func TestMultiScalarMultMatchesBaseMult(t *testing.T) {
149149
}
150150
}
151151

152+
func TestMultiScalarMultZeroReceiver(t *testing.T) {
153+
// A zero-value (uninitialized) receiver should be handled correctly,
154+
// producing a valid point on the curve.
155+
var p Point
156+
p.MultiScalarMult([]*Scalar{dalekScalar}, []*Point{B})
157+
158+
var check Point
159+
check.ScalarBaseMult(dalekScalar)
160+
161+
checkOnCurve(t, &p, &check)
162+
if p.Equal(&check) != 1 {
163+
t.Error("MultiScalarMult with zero-value receiver did not match ScalarBaseMult")
164+
}
165+
}
166+
167+
func TestMultiScalarMultReceiverAliasing(t *testing.T) {
168+
// The receiver v aliasing one of the input points should produce
169+
// the correct result.
170+
p := NewGeneratorPoint()
171+
p.MultiScalarMult([]*Scalar{dalekScalar}, []*Point{p})
172+
173+
var check Point
174+
check.ScalarBaseMult(dalekScalar)
175+
176+
checkOnCurve(t, p, &check)
177+
if p.Equal(&check) != 1 {
178+
t.Error("MultiScalarMult with aliased receiver did not match ScalarBaseMult")
179+
}
180+
}
181+
152182
func TestVarTimeMultiScalarMultMatchesBaseMult(t *testing.T) {
153183
varTimeMultiScalarMultMatchesBaseMult := func(x, y, z Scalar) bool {
154184
var p, q1, q2, q3, check Point

0 commit comments

Comments
 (0)