aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/crypto/elliptic
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-09-24 21:46:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-09-24 21:46:21 +0000
commitdd931d9b48647e898dc80927c532ae93cc09e192 (patch)
tree71be2295cd79b8a182f6130611658db8628772d5 /libgo/go/crypto/elliptic
parent779d8a5ad09b01428726ea5a0e6c87bd9ac3c0e4 (diff)
downloadgcc-dd931d9b48647e898dc80927c532ae93cc09e192.zip
gcc-dd931d9b48647e898dc80927c532ae93cc09e192.tar.gz
gcc-dd931d9b48647e898dc80927c532ae93cc09e192.tar.bz2
libgo: update to Go 1.11
Reviewed-on: https://go-review.googlesource.com/136435 gotools/: * Makefile.am (mostlyclean-local): Run chmod on check-go-dir to make sure it is writable. (check-go-tools): Likewise. (check-vet): Copy internal/objabi to check-vet-dir. * Makefile.in: Rebuild. From-SVN: r264546
Diffstat (limited to 'libgo/go/crypto/elliptic')
-rw-r--r--libgo/go/crypto/elliptic/elliptic.go6
-rw-r--r--libgo/go/crypto/elliptic/elliptic_test.go4
-rw-r--r--libgo/go/crypto/elliptic/fuzz_test.go54
-rw-r--r--libgo/go/crypto/elliptic/p224.go4
-rw-r--r--libgo/go/crypto/elliptic/p256.go8
-rw-r--r--libgo/go/crypto/elliptic/p256_asm.go (renamed from libgo/go/crypto/elliptic/p256_amd64.go)209
-rw-r--r--libgo/go/crypto/elliptic/p256_generic.go2
7 files changed, 159 insertions, 128 deletions
diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go
index 35aacf2..4fc2b5e 100644
--- a/libgo/go/crypto/elliptic/elliptic.go
+++ b/libgo/go/crypto/elliptic/elliptic.go
@@ -20,7 +20,7 @@ import (
)
// A Curve represents a short-form Weierstrass curve with a=-3.
-// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
+// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
type Curve interface {
// Params returns the parameters for the curve.
Params() *CurveParams
@@ -108,7 +108,7 @@ func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
// (x2, y2, z2) and returns their sum, also in Jacobian form.
func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
- // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
+ // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int)
if z1.Sign() == 0 {
x3.Set(x2)
@@ -191,7 +191,7 @@ func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
// returns its double, also in Jacobian form.
func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
- // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
+ // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
delta := new(big.Int).Mul(z, z)
delta.Mod(delta, curve.P)
gamma := new(big.Int).Mul(y, y)
diff --git a/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go
index f661359..09c5483 100644
--- a/libgo/go/crypto/elliptic/elliptic_test.go
+++ b/libgo/go/crypto/elliptic/elliptic_test.go
@@ -608,7 +608,7 @@ func TestUnmarshalToLargeCoordinates(t *testing.T) {
copy(invalidX[33:], y.Bytes())
if X, Y := Unmarshal(curve, invalidX); X != nil || Y != nil {
- t.Errorf("Unmarshal accpets invalid X coordinate")
+ t.Errorf("Unmarshal accepts invalid X coordinate")
}
// This is a point on the curve with a small y value, small enough that we can add p and still be within 32 bytes.
@@ -625,6 +625,6 @@ func TestUnmarshalToLargeCoordinates(t *testing.T) {
copy(invalidY[33:], y.Bytes())
if X, Y := Unmarshal(curve, invalidY); X != nil || Y != nil {
- t.Errorf("Unmarshal accpets invalid Y coordinate")
+ t.Errorf("Unmarshal accepts invalid Y coordinate")
}
}
diff --git a/libgo/go/crypto/elliptic/fuzz_test.go b/libgo/go/crypto/elliptic/fuzz_test.go
new file mode 100644
index 0000000..10196cf
--- /dev/null
+++ b/libgo/go/crypto/elliptic/fuzz_test.go
@@ -0,0 +1,54 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64 arm64
+
+package elliptic
+
+import (
+ "crypto/rand"
+ "testing"
+ "time"
+)
+
+func TestFuzz(t *testing.T) {
+
+ p256 := P256()
+ p256Generic := p256.Params()
+
+ var scalar1 [32]byte
+ var scalar2 [32]byte
+ var timeout *time.Timer
+
+ if testing.Short() {
+ timeout = time.NewTimer(500 * time.Millisecond)
+ } else {
+ timeout = time.NewTimer(2 * time.Second)
+ }
+
+ for {
+ select {
+ case <-timeout.C:
+ return
+ default:
+ }
+
+ rand.Read(scalar1[:])
+ rand.Read(scalar2[:])
+
+ x, y := p256.ScalarBaseMult(scalar1[:])
+ x2, y2 := p256Generic.ScalarBaseMult(scalar1[:])
+
+ xx, yy := p256.ScalarMult(x, y, scalar2[:])
+ xx2, yy2 := p256Generic.ScalarMult(x2, y2, scalar2[:])
+
+ if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 {
+ t.Fatalf("ScalarBaseMult does not match reference result with scalar: %x, please report this error to security@golang.org", scalar1)
+ }
+
+ if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 {
+ t.Fatalf("ScalarMult does not match reference result with scalars: %x and %x, please report this error to security@golang.org", scalar1, scalar2)
+ }
+ }
+}
diff --git a/libgo/go/crypto/elliptic/p224.go b/libgo/go/crypto/elliptic/p224.go
index 22d0e24..2ea63f3 100644
--- a/libgo/go/crypto/elliptic/p224.go
+++ b/libgo/go/crypto/elliptic/p224.go
@@ -7,7 +7,7 @@ package elliptic
// This is a constant-time, 32-bit implementation of P224. See FIPS 186-3,
// section D.2.2.
//
-// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
+// See https://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
import (
"math/big"
@@ -503,7 +503,7 @@ func p224Contract(out, in *p224FieldElement) {
// p224AddJacobian computes *out = a+b where a != b.
func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
- // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl
+ // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl
var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement
var c p224LargeFieldElement
diff --git a/libgo/go/crypto/elliptic/p256.go b/libgo/go/crypto/elliptic/p256.go
index a0933dc..937d2a4 100644
--- a/libgo/go/crypto/elliptic/p256.go
+++ b/libgo/go/crypto/elliptic/p256.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// -build !amd64
+// -build !amd64,!arm64
package elliptic
@@ -817,7 +817,7 @@ func p256Scalar8(out *[p256Limbs]uint32) {
// p256PointDouble sets {xOut,yOut,zOut} = 2*{x,y,z}.
//
-// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
+// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
func p256PointDouble(xOut, yOut, zOut, x, y, z *[p256Limbs]uint32) {
var delta, gamma, alpha, beta, tmp, tmp2 [p256Limbs]uint32
@@ -850,7 +850,7 @@ func p256PointDouble(xOut, yOut, zOut, x, y, z *[p256Limbs]uint32) {
// p256PointAddMixed sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,1}.
// (i.e. the second point is affine.)
//
-// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
+// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
//
// Note that this function does not handle P+P, infinity+P nor P+infinity
// correctly.
@@ -886,7 +886,7 @@ func p256PointAddMixed(xOut, yOut, zOut, x1, y1, z1, x2, y2 *[p256Limbs]uint32)
// p256PointAdd sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,z2}.
//
-// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
+// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
//
// Note that this function does not handle P+P, infinity+P nor P+infinity
// correctly.
diff --git a/libgo/go/crypto/elliptic/p256_amd64.go b/libgo/go/crypto/elliptic/p256_asm.go
index f108e73..aee065b 100644
--- a/libgo/go/crypto/elliptic/p256_amd64.go
+++ b/libgo/go/crypto/elliptic/p256_asm.go
@@ -7,11 +7,11 @@
// detail in:
// S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with
// 256-bit primes"
-// http://link.springer.com/article/10.1007%2Fs13389-014-0090-x
+// https://link.springer.com/article/10.1007%2Fs13389-014-0090-x
// https://eprint.iacr.org/2013/816.pdf
-// +build ignore
-// +build amd64
+// +build ignore_for_gccgo
+// +build amd64 arm64
package elliptic
@@ -32,7 +32,7 @@ type (
var (
p256 p256Curve
- p256Precomputed *[37][64 * 8]uint64
+ p256Precomputed *[43][32 * 8]uint64
precomputeOnce sync.Once
)
@@ -51,14 +51,14 @@ func (curve p256Curve) Params() *CurveParams {
return curve.CurveParams
}
-// Functions implemented in p256_asm_amd64.s
+// Functions implemented in p256_asm_*64.s
// Montgomery multiplication modulo P256
//go:noescape
func p256Mul(res, in1, in2 []uint64)
-// Montgomery square modulo P256
+// Montgomery square modulo P256, repeated n times (n >= 1)
//go:noescape
-func p256Sqr(res, in []uint64)
+func p256Sqr(res, in []uint64, n int)
// Montgomery multiplication by 1
//go:noescape
@@ -122,11 +122,20 @@ func (curve p256Curve) Inverse(k *big.Int) *big.Int {
k = new(big.Int).Mod(k, p256.N)
}
- // table will store precomputed powers of x. The four words at index
- // 4×i store x^(i+1).
- var table [4 * 15]uint64
+ // table will store precomputed powers of x.
+ var table [4 * 9]uint64
+ var (
+ _1 = table[4*0 : 4*1]
+ _11 = table[4*1 : 4*2]
+ _101 = table[4*2 : 4*3]
+ _111 = table[4*3 : 4*4]
+ _1111 = table[4*4 : 4*5]
+ _10101 = table[4*5 : 4*6]
+ _101111 = table[4*6 : 4*7]
+ x = table[4*7 : 4*8]
+ t = table[4*8 : 4*9]
+ )
- x := make([]uint64, 4)
fromBig(x[:], k)
// This code operates in the Montgomery domain where R = 2^256 mod n
// and n is the order of the scalar field. (See initP256 for the
@@ -134,53 +143,49 @@ func (curve p256Curve) Inverse(k *big.Int) *big.Int {
// multiplication of x and y in the calculates (x × y × R^-1) mod n. RR
// is R×R mod n thus the Montgomery multiplication x and RR gives x×R,
// i.e. converts x into the Montgomery domain.
+ // Window values borrowed from https://briansmith.org/ecc-inversion-addition-chains-01#p256_scalar_inversion
RR := []uint64{0x83244c95be79eea2, 0x4699799c49bd6fa6, 0x2845b2392b6bec59, 0x66e12d94f3d95620}
- p256OrdMul(table[:4], x, RR)
-
- // Prepare the table, no need in constant time access, because the
- // power is not a secret. (Entry 0 is never used.)
- for i := 2; i < 16; i += 2 {
- p256OrdSqr(table[4*(i-1):], table[4*((i/2)-1):], 1)
- p256OrdMul(table[4*i:], table[4*(i-1):], table[:4])
- }
-
- x[0] = table[4*14+0] // f
- x[1] = table[4*14+1]
- x[2] = table[4*14+2]
- x[3] = table[4*14+3]
-
- p256OrdSqr(x, x, 4)
- p256OrdMul(x, x, table[4*14:4*14+4]) // ff
- t := make([]uint64, 4, 4)
- t[0] = x[0]
- t[1] = x[1]
- t[2] = x[2]
- t[3] = x[3]
-
- p256OrdSqr(x, x, 8)
- p256OrdMul(x, x, t) // ffff
- t[0] = x[0]
- t[1] = x[1]
- t[2] = x[2]
- t[3] = x[3]
-
- p256OrdSqr(x, x, 16)
- p256OrdMul(x, x, t) // ffffffff
- t[0] = x[0]
- t[1] = x[1]
- t[2] = x[2]
- t[3] = x[3]
-
- p256OrdSqr(x, x, 64) // ffffffff0000000000000000
- p256OrdMul(x, x, t) // ffffffff00000000ffffffff
- p256OrdSqr(x, x, 32) // ffffffff00000000ffffffff00000000
- p256OrdMul(x, x, t) // ffffffff00000000ffffffffffffffff
-
- // Remaining 32 windows
- expLo := [32]byte{0xb, 0xc, 0xe, 0x6, 0xf, 0xa, 0xa, 0xd, 0xa, 0x7, 0x1, 0x7, 0x9, 0xe, 0x8, 0x4, 0xf, 0x3, 0xb, 0x9, 0xc, 0xa, 0xc, 0x2, 0xf, 0xc, 0x6, 0x3, 0x2, 0x5, 0x4, 0xf}
- for i := 0; i < 32; i++ {
- p256OrdSqr(x, x, 4)
- p256OrdMul(x, x, table[4*(expLo[i]-1):])
+ p256OrdMul(_1, x, RR) // _1
+ p256OrdSqr(x, _1, 1) // _10
+ p256OrdMul(_11, x, _1) // _11
+ p256OrdMul(_101, x, _11) // _101
+ p256OrdMul(_111, x, _101) // _111
+ p256OrdSqr(x, _101, 1) // _1010
+ p256OrdMul(_1111, _101, x) // _1111
+
+ p256OrdSqr(t, x, 1) // _10100
+ p256OrdMul(_10101, t, _1) // _10101
+ p256OrdSqr(x, _10101, 1) // _101010
+ p256OrdMul(_101111, _101, x) // _101111
+ p256OrdMul(x, _10101, x) // _111111 = x6
+ p256OrdSqr(t, x, 2) // _11111100
+ p256OrdMul(t, t, _11) // _11111111 = x8
+ p256OrdSqr(x, t, 8) // _ff00
+ p256OrdMul(x, x, t) // _ffff = x16
+ p256OrdSqr(t, x, 16) // _ffff0000
+ p256OrdMul(t, t, x) // _ffffffff = x32
+
+ p256OrdSqr(x, t, 64)
+ p256OrdMul(x, x, t)
+ p256OrdSqr(x, x, 32)
+ p256OrdMul(x, x, t)
+
+ sqrs := []uint8{
+ 6, 5, 4, 5, 5,
+ 4, 3, 3, 5, 9,
+ 6, 2, 5, 6, 5,
+ 4, 5, 5, 3, 10,
+ 2, 5, 5, 3, 7, 6}
+ muls := [][]uint64{
+ _101111, _111, _11, _1111, _10101,
+ _101, _101, _101, _111, _101111,
+ _1111, _1, _1, _1111, _111,
+ _111, _111, _101, _11, _101111,
+ _11, _11, _11, _1, _10101, _1111}
+
+ for i, s := range sqrs {
+ p256OrdSqr(x, x, int(s))
+ p256OrdMul(x, x, muls[i])
}
// Multiplying by one in the Montgomery domain converts a Montgomery
@@ -310,7 +315,7 @@ func (p *p256Point) p256PointToAffine() (x, y *big.Int) {
zInv := make([]uint64, 4)
zInvSq := make([]uint64, 4)
p256Inverse(zInv, p.xyz[8:12])
- p256Sqr(zInvSq, zInv)
+ p256Sqr(zInvSq, zInv, 1)
p256Mul(zInv, zInv, zInvSq)
p256Mul(zInvSq, p.xyz[0:4], zInvSq)
@@ -347,71 +352,43 @@ func p256Inverse(out, in []uint64) {
p16 := stack[4*3 : 4*3+4]
p32 := stack[4*4 : 4*4+4]
- p256Sqr(out, in)
+ p256Sqr(out, in, 1)
p256Mul(p2, out, in) // 3*p
- p256Sqr(out, p2)
- p256Sqr(out, out)
+ p256Sqr(out, p2, 2)
p256Mul(p4, out, p2) // f*p
- p256Sqr(out, p4)
- p256Sqr(out, out)
- p256Sqr(out, out)
- p256Sqr(out, out)
+ p256Sqr(out, p4, 4)
p256Mul(p8, out, p4) // ff*p
- p256Sqr(out, p8)
-
- for i := 0; i < 7; i++ {
- p256Sqr(out, out)
- }
+ p256Sqr(out, p8, 8)
p256Mul(p16, out, p8) // ffff*p
- p256Sqr(out, p16)
- for i := 0; i < 15; i++ {
- p256Sqr(out, out)
- }
+ p256Sqr(out, p16, 16)
p256Mul(p32, out, p16) // ffffffff*p
- p256Sqr(out, p32)
-
- for i := 0; i < 31; i++ {
- p256Sqr(out, out)
- }
+ p256Sqr(out, p32, 32)
p256Mul(out, out, in)
- for i := 0; i < 32*4; i++ {
- p256Sqr(out, out)
- }
+ p256Sqr(out, out, 128)
p256Mul(out, out, p32)
- for i := 0; i < 32; i++ {
- p256Sqr(out, out)
- }
+ p256Sqr(out, out, 32)
p256Mul(out, out, p32)
- for i := 0; i < 16; i++ {
- p256Sqr(out, out)
- }
+ p256Sqr(out, out, 16)
p256Mul(out, out, p16)
- for i := 0; i < 8; i++ {
- p256Sqr(out, out)
- }
+ p256Sqr(out, out, 8)
p256Mul(out, out, p8)
- p256Sqr(out, out)
- p256Sqr(out, out)
- p256Sqr(out, out)
- p256Sqr(out, out)
+ p256Sqr(out, out, 4)
p256Mul(out, out, p4)
- p256Sqr(out, out)
- p256Sqr(out, out)
+ p256Sqr(out, out, 2)
p256Mul(out, out, p2)
- p256Sqr(out, out)
- p256Sqr(out, out)
+ p256Sqr(out, out, 2)
p256Mul(out, out, in)
}
@@ -427,16 +404,16 @@ func boothW5(in uint) (int, int) {
return int(d), int(s & 1)
}
-func boothW7(in uint) (int, int) {
- var s uint = ^((in >> 7) - 1)
- var d uint = (1 << 8) - in - 1
+func boothW6(in uint) (int, int) {
+ var s uint = ^((in >> 6) - 1)
+ var d uint = (1 << 7) - in - 1
d = (d & s) | (in & (^s))
d = (d >> 1) + (d & 1)
return int(d), int(s & 1)
}
func initTable() {
- p256Precomputed = new([37][64 * 8]uint64)
+ p256Precomputed = new([43][32 * 8]uint64)
basePoint := []uint64{
0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6,
@@ -449,19 +426,19 @@ func initTable() {
zInv := make([]uint64, 4)
zInvSq := make([]uint64, 4)
- for j := 0; j < 64; j++ {
+ for j := 0; j < 32; j++ {
copy(t1, t2)
- for i := 0; i < 37; i++ {
- // The window size is 7 so we need to double 7 times.
+ for i := 0; i < 43; i++ {
+ // The window size is 6 so we need to double 6 times.
if i != 0 {
- for k := 0; k < 7; k++ {
+ for k := 0; k < 6; k++ {
p256PointDoubleAsm(t1, t1)
}
}
// Convert the point to affine form. (Its values are
// still in Montgomery form however.)
p256Inverse(zInv, t1[8:12])
- p256Sqr(zInvSq, zInv)
+ p256Sqr(zInvSq, zInv, 1)
p256Mul(zInv, zInv, zInvSq)
p256Mul(t1[:4], t1[:4], zInvSq)
@@ -482,8 +459,8 @@ func initTable() {
func (p *p256Point) p256BaseMult(scalar []uint64) {
precomputeOnce.Do(initTable)
- wvalue := (scalar[0] << 1) & 0xff
- sel, sign := boothW7(uint(wvalue))
+ wvalue := (scalar[0] << 1) & 0x7f
+ sel, sign := boothW6(uint(wvalue))
p256SelectBase(p.xyz[0:8], p256Precomputed[0][0:], sel)
p256NegCond(p.xyz[4:8], sign)
@@ -500,17 +477,17 @@ func (p *p256Point) p256BaseMult(scalar []uint64) {
t0.xyz[10] = 0xffffffffffffffff
t0.xyz[11] = 0x00000000fffffffe
- index := uint(6)
+ index := uint(5)
zero := sel
- for i := 1; i < 37; i++ {
+ for i := 1; i < 43; i++ {
if index < 192 {
- wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0xff
+ wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0x7f
} else {
- wvalue = (scalar[index/64] >> (index % 64)) & 0xff
+ wvalue = (scalar[index/64] >> (index % 64)) & 0x7f
}
- index += 7
- sel, sign = boothW7(uint(wvalue))
+ index += 6
+ sel, sign = boothW6(uint(wvalue))
p256SelectBase(t0.xyz[0:8], p256Precomputed[i][0:], sel)
p256PointAddAffineAsm(p.xyz[0:12], p.xyz[0:12], t0.xyz[0:8], sign, sel, zero)
zero |= sel
diff --git a/libgo/go/crypto/elliptic/p256_generic.go b/libgo/go/crypto/elliptic/p256_generic.go
index 49445c3..48954a2 100644
--- a/libgo/go/crypto/elliptic/p256_generic.go
+++ b/libgo/go/crypto/elliptic/p256_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// -build !amd64,!s390x
+// -build !amd64,!s390x,!arm64
package elliptic