Skip to content

Commit 193df9c

Browse files
mmcloughlinjosharian
authored andcommitted
curve25519: mask high bit when loading group point
Comparison against BoringSSL-generated test vectors showed mismatches with the pure Go implementation of curve25519. The problem was narrowed down to a missing mask in feFromBytes(). This diff adds the mask, bringing this back in line with the reference implementation and RFC 7748: When receiving such an array, implementations of X25519 (but not X448) MUST mask the most significant bit in the final byte. This is done to preserve compatibility with point formats that reserve the sign bit for use in other protocols and to increase resistance to implementation fingerprinting. Fixes golang/go#30095 Change-Id: If7efc0e2acd6efb761d6e3cb89cec359d7d81cb1 Reviewed-on: https://go-review.googlesource.com/c/161257 Run-TryBot: Filippo Valsorda <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Filippo Valsorda <[email protected]>
1 parent b8fe169 commit 193df9c

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

Diff for: curve25519/curve25519.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func feFromBytes(dst *fieldElement, src *[32]byte) {
8686
h6 := load3(src[20:]) << 7
8787
h7 := load3(src[23:]) << 5
8888
h8 := load3(src[26:]) << 4
89-
h9 := load3(src[29:]) << 2
89+
h9 := (load3(src[29:]) & 0x7fffff) << 2
9090

9191
var carry [10]int64
9292
carry[9] = (h9 + 1<<24) >> 25

Diff for: curve25519/curve25519_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
package curve25519
66

77
import (
8+
"bytes"
9+
"crypto/rand"
810
"fmt"
911
"testing"
1012
)
@@ -28,6 +30,30 @@ func TestBaseScalarMult(t *testing.T) {
2830
}
2931
}
3032

33+
// TestHighBitIgnored tests the following requirement in RFC 7748:
34+
//
35+
// When receiving such an array, implementations of X25519 (but not X448) MUST
36+
// mask the most significant bit in the final byte.
37+
//
38+
// Regression test for issue #30095.
39+
func TestHighBitIgnored(t *testing.T) {
40+
var s, u [32]byte
41+
rand.Read(s[:])
42+
rand.Read(u[:])
43+
44+
var hi0, hi1 [32]byte
45+
46+
u[31] &= 0x7f
47+
ScalarMult(&hi0, &s, &u)
48+
49+
u[31] |= 0x80
50+
ScalarMult(&hi1, &s, &u)
51+
52+
if !bytes.Equal(hi0[:], hi1[:]) {
53+
t.Errorf("high bit of group point should not affect result")
54+
}
55+
}
56+
3157
func BenchmarkScalarBaseMult(b *testing.B) {
3258
var in, out [32]byte
3359
in[0] = 1

0 commit comments

Comments
 (0)