Skip to content

Commit 27ec2bf

Browse files
committed
crypto/ed25519/internal/edwards25519: sync with filippo.io/edwards25519
Import the following commits (and minor comment fixes): * 17a0e59 - field: fix heap escape in SqrtRatio <Filippo Valsorda> * edec5b9 - field: fix SqrtRatio when arguments and receiver alias <Filippo Valsorda> * 26ce6fc - edwards25519: expand the SetUniformBytes docs <Filippo Valsorda> * c1c1311 - edwards25519: make Scalar and field.Element setters return errors <Filippo Valsorda> Change-Id: I102eb04818a2bed43467f3eda6fd4c46b09878fe Reviewed-on: https://go-review.googlesource.com/c/go/+/373077 Trust: Filippo Valsorda <filippo@golang.org> Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Katie Hockman <katie@golang.org> Trust: Katie Hockman <katie@golang.org> Run-TryBot: Katie Hockman <katie@golang.org>
1 parent 81767e2 commit 27ec2bf

File tree

8 files changed

+90
-48
lines changed

8 files changed

+90
-48
lines changed

src/crypto/ed25519/ed25519.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,10 @@ func newKeyFromSeed(privateKey, seed []byte) {
126126
}
127127

128128
h := sha512.Sum512(seed)
129-
s := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
129+
s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
130+
if err != nil {
131+
panic("ed25519: internal error: setting scalar failed")
132+
}
130133
A := (&edwards25519.Point{}).ScalarBaseMult(s)
131134

132135
publicKey := A.Bytes()
@@ -152,15 +155,21 @@ func sign(signature, privateKey, message []byte) {
152155
seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:]
153156

154157
h := sha512.Sum512(seed)
155-
s := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
158+
s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
159+
if err != nil {
160+
panic("ed25519: internal error: setting scalar failed")
161+
}
156162
prefix := h[32:]
157163

158164
mh := sha512.New()
159165
mh.Write(prefix)
160166
mh.Write(message)
161167
messageDigest := make([]byte, 0, sha512.Size)
162168
messageDigest = mh.Sum(messageDigest)
163-
r := edwards25519.NewScalar().SetUniformBytes(messageDigest)
169+
r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest)
170+
if err != nil {
171+
panic("ed25519: internal error: setting scalar failed")
172+
}
164173

165174
R := (&edwards25519.Point{}).ScalarBaseMult(r)
166175

@@ -170,7 +179,10 @@ func sign(signature, privateKey, message []byte) {
170179
kh.Write(message)
171180
hramDigest := make([]byte, 0, sha512.Size)
172181
hramDigest = kh.Sum(hramDigest)
173-
k := edwards25519.NewScalar().SetUniformBytes(hramDigest)
182+
k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest)
183+
if err != nil {
184+
panic("ed25519: internal error: setting scalar failed")
185+
}
174186

175187
S := edwards25519.NewScalar().MultiplyAdd(k, s, r)
176188

@@ -200,7 +212,10 @@ func Verify(publicKey PublicKey, message, sig []byte) bool {
200212
kh.Write(message)
201213
hramDigest := make([]byte, 0, sha512.Size)
202214
hramDigest = kh.Sum(hramDigest)
203-
k := edwards25519.NewScalar().SetUniformBytes(hramDigest)
215+
k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest)
216+
if err != nil {
217+
panic("ed25519: internal error: setting scalar failed")
218+
}
204219

205220
S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:])
206221
if err != nil {

src/crypto/ed25519/internal/edwards25519/edwards25519.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ func (v *Point) SetBytes(x []byte) (*Point, error) {
151151
// at https://hdevalence.ca/blog/2020-10-04-its-25519am, specifically the
152152
// "Canonical A, R" section.
153153

154-
if len(x) != 32 {
154+
y, err := new(field.Element).SetBytes(x)
155+
if err != nil {
155156
return nil, errors.New("edwards25519: invalid point encoding length")
156157
}
157-
y := new(field.Element).SetBytes(x)
158158

159159
// -x² + y² = 1 + dx²y²
160160
// x² + dx²y² = x²(dy² + 1) = y² - 1
@@ -224,7 +224,7 @@ func (v *Point) fromP2(p *projP2) *Point {
224224
}
225225

226226
// d is a constant in the curve equation.
227-
var d = new(field.Element).SetBytes([]byte{
227+
var d, _ = new(field.Element).SetBytes([]byte{
228228
0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
229229
0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
230230
0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,

src/crypto/ed25519/internal/edwards25519/field/fe.go

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package field
88
import (
99
"crypto/subtle"
1010
"encoding/binary"
11+
"errors"
1112
"math/bits"
1213
)
1314

@@ -186,14 +187,17 @@ func (v *Element) Set(a *Element) *Element {
186187
return v
187188
}
188189

189-
// SetBytes sets v to x, which must be a 32-byte little-endian encoding.
190+
// SetBytes sets v to x, where x is a 32-byte little-endian encoding. If x is
191+
// not of the right length, SetBytes returns nil and an error, and the
192+
// receiver is unchanged.
190193
//
191194
// Consistent with RFC 7748, the most significant bit (the high bit of the
192195
// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1)
193-
// are accepted. Note that this is laxer than specified by RFC 8032.
194-
func (v *Element) SetBytes(x []byte) *Element {
196+
// are accepted. Note that this is laxer than specified by RFC 8032, but
197+
// consistent with most Ed25519 implementations.
198+
func (v *Element) SetBytes(x []byte) (*Element, error) {
195199
if len(x) != 32 {
196-
panic("edwards25519: invalid field element input size")
200+
return nil, errors.New("edwards25519: invalid field element input size")
197201
}
198202

199203
// Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51).
@@ -208,12 +212,12 @@ func (v *Element) SetBytes(x []byte) *Element {
208212
// Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51).
209213
v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1
210214
v.l3 &= maskLow51Bits
211-
// Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51).
215+
// Bits 204:255 (bytes 24:32, bits 192:256, shift 12, mask 51).
212216
// Note: not bytes 25:33, shift 4, to avoid overread.
213217
v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12
214218
v.l4 &= maskLow51Bits
215219

216-
return v
220+
return v, nil
217221
}
218222

219223
// Bytes returns the canonical 32-byte little-endian encoding of v.
@@ -391,26 +395,26 @@ var sqrtM1 = &Element{1718705420411056, 234908883556509,
391395
// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio
392396
// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00,
393397
// and returns r and 0.
394-
func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) {
395-
var a, b Element
398+
func (r *Element) SqrtRatio(u, v *Element) (R *Element, wasSquare int) {
399+
t0 := new(Element)
396400

397401
// r = (u * v3) * (u * v7)^((p-5)/8)
398-
v2 := a.Square(v)
399-
uv3 := b.Multiply(u, b.Multiply(v2, v))
400-
uv7 := a.Multiply(uv3, a.Square(v2))
401-
r.Multiply(uv3, r.Pow22523(uv7))
402+
v2 := new(Element).Square(v)
403+
uv3 := new(Element).Multiply(u, t0.Multiply(v2, v))
404+
uv7 := new(Element).Multiply(uv3, t0.Square(v2))
405+
rr := new(Element).Multiply(uv3, t0.Pow22523(uv7))
402406

403-
check := a.Multiply(v, a.Square(r)) // check = v * r^2
407+
check := new(Element).Multiply(v, t0.Square(rr)) // check = v * r^2
404408

405-
uNeg := b.Negate(u)
409+
uNeg := new(Element).Negate(u)
406410
correctSignSqrt := check.Equal(u)
407411
flippedSignSqrt := check.Equal(uNeg)
408-
flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1))
412+
flippedSignSqrtI := check.Equal(t0.Multiply(uNeg, sqrtM1))
409413

410-
rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r
414+
rPrime := new(Element).Multiply(rr, sqrtM1) // r_prime = SQRT_M1 * r
411415
// r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r)
412-
r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI)
416+
rr.Select(rPrime, rr, flippedSignSqrt|flippedSignSqrtI)
413417

414-
r.Absolute(r) // Choose the nonnegative square root.
418+
r.Absolute(rr) // Choose the nonnegative square root.
415419
return r, correctSignSqrt | flippedSignSqrt
416420
}

src/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,33 @@ func TestAliasing(t *testing.T) {
9696
{name: "Negate", oneArgF: (*Element).Negate},
9797
{name: "Set", oneArgF: (*Element).Set},
9898
{name: "Square", oneArgF: (*Element).Square},
99+
{name: "Pow22523", oneArgF: (*Element).Pow22523},
100+
{
101+
name: "Mult32",
102+
oneArgF: func(v, x *Element) *Element {
103+
return v.Mult32(x, 0xffffffff)
104+
},
105+
},
99106
{name: "Multiply", twoArgsF: (*Element).Multiply},
100107
{name: "Add", twoArgsF: (*Element).Add},
101108
{name: "Subtract", twoArgsF: (*Element).Subtract},
109+
{
110+
name: "SqrtRatio",
111+
twoArgsF: func(v, x, y *Element) *Element {
112+
r, _ := v.SqrtRatio(x, y)
113+
return r
114+
},
115+
},
102116
{
103117
name: "Select0",
104118
twoArgsF: func(v, x, y *Element) *Element {
105-
return (*Element).Select(v, x, y, 0)
119+
return v.Select(x, y, 0)
106120
},
107121
},
108122
{
109123
name: "Select1",
110124
twoArgsF: func(v, x, y *Element) *Element {
111-
return (*Element).Select(v, x, y, 1)
125+
return v.Select(x, y, 1)
112126
},
113127
},
114128
} {

src/crypto/ed25519/internal/edwards25519/field/fe_generic.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ func (v *Element) carryPropagateGeneric() *Element {
254254
c3 := v.l3 >> 51
255255
c4 := v.l4 >> 51
256256

257+
// c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and
258+
// the final l0 will be at most 52 bits. Similarly for the rest.
257259
v.l0 = v.l0&maskLow51Bits + c4*19
258260
v.l1 = v.l1&maskLow51Bits + c0
259261
v.l2 = v.l2&maskLow51Bits + c1

src/crypto/ed25519/internal/edwards25519/field/fe_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ func TestSetBytesRoundTrip(t *testing.T) {
192192

193193
for _, tt := range tests {
194194
b := tt.fe.Bytes()
195-
if !bytes.Equal(b, tt.b) || new(Element).SetBytes(tt.b).Equal(&tt.fe) != 1 {
195+
fe, _ := new(Element).SetBytes(tt.b)
196+
if !bytes.Equal(b, tt.b) || fe.Equal(&tt.fe) != 1 {
196197
t.Errorf("Failed fixed roundtrip: %v", tt)
197198
}
198199
}
@@ -217,8 +218,8 @@ func TestBytesBigEquivalence(t *testing.T) {
217218
return false
218219
}
219220

220-
buf := make([]byte, 32) // pad with zeroes
221-
copy(buf, swapEndianness(fe1.toBig().Bytes()))
221+
buf := make([]byte, 32)
222+
buf = swapEndianness(fe1.toBig().FillBytes(buf))
222223

223224
return bytes.Equal(fe.Bytes(), buf) && isInBounds(&fe) && isInBounds(&fe1)
224225
}
@@ -244,7 +245,8 @@ func (v *Element) fromBig(n *big.Int) *Element {
244245
}
245246
}
246247

247-
return v.SetBytes(buf[:32])
248+
v.SetBytes(buf[:32])
249+
return v
248250
}
249251

250252
func (v *Element) fromDecimal(s string) *Element {
@@ -471,9 +473,9 @@ func TestSqrtRatio(t *testing.T) {
471473
}
472474

473475
for i, tt := range tests {
474-
u := new(Element).SetBytes(decodeHex(tt.u))
475-
v := new(Element).SetBytes(decodeHex(tt.v))
476-
want := new(Element).SetBytes(decodeHex(tt.r))
476+
u, _ := new(Element).SetBytes(decodeHex(tt.u))
477+
v, _ := new(Element).SetBytes(decodeHex(tt.v))
478+
want, _ := new(Element).SetBytes(decodeHex(tt.r))
477479
got, wasSquare := new(Element).SqrtRatio(u, v)
478480
if got.Equal(want) == 0 || wasSquare != tt.wasSquare {
479481
t.Errorf("%d: got (%v, %v), want (%v, %v)", i, got, wasSquare, want, tt.wasSquare)

src/crypto/ed25519/internal/edwards25519/scalar.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
// The zero value is a valid zero element.
2323
type Scalar struct {
2424
// s is the Scalar value in little-endian. The value is always reduced
25-
// between operations.
25+
// modulo l between operations.
2626
s [32]byte
2727
}
2828

@@ -79,16 +79,20 @@ func (s *Scalar) Set(x *Scalar) *Scalar {
7979
return s
8080
}
8181

82-
// SetUniformBytes sets s to an uniformly distributed value given 64 uniformly
83-
// distributed random bytes.
84-
func (s *Scalar) SetUniformBytes(x []byte) *Scalar {
82+
// SetUniformBytes sets s = x mod l, where x is a 64-byte little-endian integer.
83+
// If x is not of the right length, SetUniformBytes returns nil and an error,
84+
// and the receiver is unchanged.
85+
//
86+
// SetUniformBytes can be used to set s to an uniformly distributed value given
87+
// 64 uniformly distributed random bytes.
88+
func (s *Scalar) SetUniformBytes(x []byte) (*Scalar, error) {
8589
if len(x) != 64 {
86-
panic("edwards25519: invalid SetUniformBytes input length")
90+
return nil, errors.New("edwards25519: invalid SetUniformBytes input length")
8791
}
8892
var wideBytes [64]byte
8993
copy(wideBytes[:], x[:])
9094
scReduce(&s.s, &wideBytes)
91-
return s
95+
return s, nil
9296
}
9397

9498
// SetCanonicalBytes sets s = x, where x is a 32-byte little-endian encoding of
@@ -122,29 +126,30 @@ func isReduced(s *Scalar) bool {
122126

123127
// SetBytesWithClamping applies the buffer pruning described in RFC 8032,
124128
// Section 5.1.5 (also known as clamping) and sets s to the result. The input
125-
// must be 32 bytes, and it is not modified.
129+
// must be 32 bytes, and it is not modified. If x is not of the right length,
130+
// SetBytesWithClamping returns nil and an error, and the receiver is unchanged.
126131
//
127132
// Note that since Scalar values are always reduced modulo the prime order of
128133
// the curve, the resulting value will not preserve any of the cofactor-clearing
129134
// properties that clamping is meant to provide. It will however work as
130135
// expected as long as it is applied to points on the prime order subgroup, like
131136
// in Ed25519. In fact, it is lost to history why RFC 8032 adopted the
132137
// irrelevant RFC 7748 clamping, but it is now required for compatibility.
133-
func (s *Scalar) SetBytesWithClamping(x []byte) *Scalar {
138+
func (s *Scalar) SetBytesWithClamping(x []byte) (*Scalar, error) {
134139
// The description above omits the purpose of the high bits of the clamping
135140
// for brevity, but those are also lost to reductions, and are also
136141
// irrelevant to edwards25519 as they protect against a specific
137142
// implementation bug that was once observed in a generic Montgomery ladder.
138143
if len(x) != 32 {
139-
panic("edwards25519: invalid SetBytesWithClamping input length")
144+
return nil, errors.New("edwards25519: invalid SetBytesWithClamping input length")
140145
}
141146
var wideBytes [64]byte
142147
copy(wideBytes[:], x[:])
143148
wideBytes[0] &= 248
144149
wideBytes[31] &= 63
145150
wideBytes[31] |= 64
146151
scReduce(&s.s, &wideBytes)
147-
return s
152+
return s, nil
148153
}
149154

150155
// Bytes returns the canonical 32-byte little-endian encoding of s.

src/crypto/ed25519/internal/edwards25519/scalar_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,23 +113,23 @@ func TestScalarSetBytesWithClamping(t *testing.T) {
113113
// Generated with libsodium.js 1.0.18 crypto_scalarmult_ed25519_base.
114114

115115
random := "633d368491364dc9cd4c1bf891b1d59460face1644813240a313e61f2c88216e"
116-
s := new(Scalar).SetBytesWithClamping(decodeHex(random))
116+
s, _ := new(Scalar).SetBytesWithClamping(decodeHex(random))
117117
p := new(Point).ScalarBaseMult(s)
118118
want := "1d87a9026fd0126a5736fe1628c95dd419172b5b618457e041c9c861b2494a94"
119119
if got := hex.EncodeToString(p.Bytes()); got != want {
120120
t.Errorf("random: got %q, want %q", got, want)
121121
}
122122

123123
zero := "0000000000000000000000000000000000000000000000000000000000000000"
124-
s = new(Scalar).SetBytesWithClamping(decodeHex(zero))
124+
s, _ = new(Scalar).SetBytesWithClamping(decodeHex(zero))
125125
p = new(Point).ScalarBaseMult(s)
126126
want = "693e47972caf527c7883ad1b39822f026f47db2ab0e1919955b8993aa04411d1"
127127
if got := hex.EncodeToString(p.Bytes()); got != want {
128128
t.Errorf("zero: got %q, want %q", got, want)
129129
}
130130

131131
one := "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
132-
s = new(Scalar).SetBytesWithClamping(decodeHex(one))
132+
s, _ = new(Scalar).SetBytesWithClamping(decodeHex(one))
133133
p = new(Point).ScalarBaseMult(s)
134134
want = "12e9a68b73fd5aacdbcaf3e88c46fea6ebedb1aa84eed1842f07f8edab65e3a7"
135135
if got := hex.EncodeToString(p.Bytes()); got != want {

0 commit comments

Comments
 (0)