]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/elliptic: port P-224 and P-384 to fiat-crypto
authorFilippo Valsorda <filippo@golang.org>
Sat, 30 Oct 2021 04:27:51 +0000 (00:27 -0400)
committerFilippo Valsorda <filippo@golang.org>
Fri, 5 Nov 2021 19:01:13 +0000 (19:01 +0000)
Also, adopt addchain code generation for field inversion, and switch
P-521 to Montgomery multiplication, which is significantly slower but
allows us to reuse the P-224/P-256/P-384 wrapper code. No one uses P-521
anyway, and it's still faster than it was in Go 1.16.

Removed a portion of tests that ran the P-224 vectors against P-256,
for some reason.

Sadly, fiat-crypto is not fast enough to replace the generic 32-bit
P-256 implementation (just yet?).

A change in visible behavior is that we literally can't internally
operate on invalid curve points anymore (yay!) but the crypto/elliptic
API locked us into accepting any pair of integers for
Add/Double/ScalarMult and return no error (sigh), although of course
that's undefined behavior. Panics are always regretted. Returning nil
leads to panics. A fixed point might be exploited. The most reasonable
solution felt to return a made up random point, which is not that
different from an off-curve point but leaks less.

name                                  old time/op    new time/op    delta
pkg:crypto/elliptic goos:darwin goarch:arm64
ScalarBaseMult/P224-8                    573µs ± 0%     146µs ± 0%   -74.56%  (p=0.000 n=7+9)
ScalarMult/P224-8                        574µs ± 0%     152µs ± 5%   -73.58%  (p=0.000 n=7+10)
MarshalUnmarshal/P224/Uncompressed-8     664ns ± 0%     481ns ± 1%   -27.64%  (p=0.000 n=8+10)
MarshalUnmarshal/P224/Compressed-8       666ns ± 1%     480ns ± 0%   -27.92%  (p=0.000 n=10+10)
pkg:crypto/ecdsa goos:darwin goarch:arm64
Sign/P224-8                              597µs ± 0%     169µs ± 2%   -71.71%  (p=0.000 n=10+9)
Verify/P224-8                           1.18ms ± 1%    0.32ms ± 5%   -72.81%  (p=0.000 n=10+10)
GenerateKey/P224-8                       577µs ± 0%     147µs ± 0%   -74.51%  (p=0.000 n=8+8)

name                                  old time/op    new time/op    delta
pkg:crypto/elliptic goos:darwin goarch:arm64
ScalarBaseMult/P384-8                   2.01ms ± 2%    0.50ms ± 0%  -75.00%  (p=0.000 n=10+8)
ScalarMult/P384-8                       2.02ms ± 3%    0.51ms ± 3%  -74.64%  (p=0.000 n=10+10)
MarshalUnmarshal/P384/Uncompressed-8    1.09µs ± 1%    0.76µs ± 0%  -30.27%  (p=0.000 n=10+9)
MarshalUnmarshal/P384/Compressed-8      1.08µs ± 0%    0.76µs ± 1%  -29.86%  (p=0.000 n=8+10)
pkg:crypto/ecdsa goos:darwin goarch:arm64
Sign/P384-8                             2.06ms ± 1%    0.56ms ± 2%  -72.76%  (p=0.000 n=10+10)
Verify/P384-8                           4.06ms ± 2%    1.08ms ± 0%  -73.49%  (p=0.000 n=10+8)
GenerateKey/P384-8                      2.01ms ± 1%    0.51ms ± 3%  -74.65%  (p=0.000 n=10+10)

name                                  old time/op    new time/op    delta
pkg:crypto/elliptic goos:darwin goarch:arm64
ScalarBaseMult/P521-8                    715µs ± 6%    1525µs ± 4%  +113.39%  (p=0.000 n=10+10)
ScalarMult/P521-8                        698µs ± 1%    1543µs ± 1%  +120.99%  (p=0.000 n=9+9)
MarshalUnmarshal/P521/Uncompressed-8     797ns ± 0%    1296ns ± 0%   +62.65%  (p=0.000 n=10+9)
MarshalUnmarshal/P521/Compressed-8       798ns ± 0%    1299ns ± 1%   +62.82%  (p=0.000 n=8+10)
pkg:crypto/ecdsa goos:darwin goarch:arm64
Sign/P521-8                              810µs ± 3%    1645µs ± 0%  +103.03%  (p=0.000 n=10+10)
Verify/P521-8                           1.42ms ± 1%    3.19ms ± 1%  +125.28%  (p=0.000 n=10+8)
GenerateKey/P521-8                       698µs ± 1%    1549µs ± 0%  +121.87%  (p=0.000 n=10+7)

Updates #40171

Change-Id: I34edf5002b5e9fad0ebb6c1e2119fb123ea6d18f
Reviewed-on: https://go-review.googlesource.com/c/go/+/360014
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>

28 files changed:
src/cmd/compile/internal/ssa/stmtlines_test.go
src/crypto/elliptic/elliptic.go
src/crypto/elliptic/elliptic_test.go
src/crypto/elliptic/internal/fiat/Dockerfile
src/crypto/elliptic/internal/fiat/README
src/crypto/elliptic/internal/fiat/fiat_test.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/generate.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p224.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p224_fiat64.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p224_invert.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p384.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p384_fiat64.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p384_invert.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p521.go
src/crypto/elliptic/internal/fiat/p521_fiat64.go
src/crypto/elliptic/internal/fiat/p521_invert.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p521_test.go [deleted file]
src/crypto/elliptic/internal/nistec/nistec_test.go [new file with mode: 0644]
src/crypto/elliptic/internal/nistec/p224.go [new file with mode: 0644]
src/crypto/elliptic/internal/nistec/p384.go [new file with mode: 0644]
src/crypto/elliptic/internal/nistec/p521.go
src/crypto/elliptic/internal/nistec/p521_test.go [deleted file]
src/crypto/elliptic/p224.go
src/crypto/elliptic/p224_test.go
src/crypto/elliptic/p256.go
src/crypto/elliptic/p256_test.go
src/crypto/elliptic/p384.go [new file with mode: 0644]
src/crypto/elliptic/p521.go

index 90dd261c557fec7d5603cd7b3d3c5520f9382a19..088f9802e6484f849667b54f2edea84863f8cbdb 100644 (file)
@@ -89,6 +89,9 @@ func TestStmtLines(t *testing.T) {
                if pkgname == "runtime" {
                        continue
                }
+               if pkgname == "crypto/elliptic/internal/fiat" {
+                       continue // golang.org/issue/49372
+               }
                if e.Val(dwarf.AttrStmtList) == nil {
                        continue
                }
index cdde0c4e607b2f7c6f6a7295538496833b0155c7..d06a284154659643d181ee20835c9ffbb319d92b 100644 (file)
@@ -85,7 +85,7 @@ func (curve *CurveParams) polynomial(x *big.Int) *big.Int {
 func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok {
                return specific.IsOnCurve(x, y)
        }
 
@@ -128,7 +128,7 @@ func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.
 func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok {
                return specific.Add(x1, y1, x2, y2)
        }
 
@@ -218,7 +218,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
 func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok {
                return specific.Double(x1, y1)
        }
 
@@ -290,7 +290,7 @@ func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
 func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok {
                return specific.ScalarMult(Bx, By, k)
        }
 
@@ -313,7 +313,7 @@ func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.
 func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok {
                return specific.ScalarBaseMult(k)
        }
 
@@ -431,7 +431,6 @@ func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) {
 }
 
 var initonce sync.Once
-var p384 *CurveParams
 
 func initAll() {
        initP224()
@@ -440,15 +439,16 @@ func initAll() {
        initP521()
 }
 
-func initP384() {
-       // See FIPS 186-3, section D.2.4
-       p384 = &CurveParams{Name: "P-384"}
-       p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10)
-       p384.N, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", 10)
-       p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16)
-       p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16)
-       p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16)
-       p384.BitSize = 384
+// P224 returns a Curve which implements NIST P-224 (FIPS 186-3, section D.2.2),
+// also known as secp224r1. The CurveParams.Name of this Curve is "P-224".
+//
+// Multiple invocations of this function will return the same value, so it can
+// be used for equality checks and switch statements.
+//
+// The cryptographic operations are implemented using constant-time algorithms.
+func P224() Curve {
+       initonce.Do(initAll)
+       return p224
 }
 
 // P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3),
@@ -470,7 +470,7 @@ func P256() Curve {
 // Multiple invocations of this function will return the same value, so it can
 // be used for equality checks and switch statements.
 //
-// The cryptographic operations do not use constant-time algorithms.
+// The cryptographic operations are implemented using constant-time algorithms.
 func P384() Curve {
        initonce.Do(initAll)
        return p384
index d30a6939a4e35c5382d15c52d78b03de2a3cf884..f5b36f75ca0439a28d90c8cd2c75557252089c53 100644 (file)
@@ -14,9 +14,8 @@ import (
 
 // genericParamsForCurve returns the dereferenced CurveParams for
 // the specified curve. This is used to avoid the logic for
-// upgrading a curve to it's specific implementation, forcing
-// usage of the generic implementation. This is only relevant
-// for the P224, P256, and P521 curves.
+// upgrading a curve to its specific implementation, forcing
+// usage of the generic implementation.
 func genericParamsForCurve(c Curve) *CurveParams {
        d := *(c.Params())
        return &d
index 7b5ece0e30f482066b4c1bf808b49d8e3020fc80..2877e0b2c125036d3e7313a2bee52eca0fcc6195 100644 (file)
@@ -4,9 +4,9 @@
 
 FROM coqorg/coq:8.13.2
 
-RUN git clone https://github.com/mit-plv/fiat-crypto
-RUN cd fiat-crypto && git checkout c076f3550bea2bb7f4cb5766a32594b9e67694f2
-RUN cd fiat-crypto && git submodule update --init --recursive
+RUN git clone https://github.com/mit-plv/fiat-crypto && cd fiat-crypto && \
+    git checkout 23d2dbc4ab897d14bde4404f70cd6991635f9c01 && \
+    git submodule update --init --recursive
 RUN cd fiat-crypto && eval $(opam env) && make -j4 standalone-ocaml SKIP_BEDROCK2=1
 
-ENTRYPOINT ["fiat-crypto/src/ExtractionOCaml/unsaturated_solinas"]
+ENV PATH /home/coq/fiat-crypto/src/ExtractionOCaml:$PATH
index 171f57a32742f85391482ea1672f1ad68fe83aeb..916ebc14ce8ad607516e88aad231bc246ae577d0 100644 (file)
@@ -1,17 +1,12 @@
 The code in this package was autogenerated by the fiat-crypto project
-at commit c076f3550 from a formally verified model.
-
-    docker build -t fiat-crypto:c076f3550 .
-    docker run fiat-crypto:c076f3550 --lang Go --no-wide-int --cmovznz-by-mul \
-        --internal-static --public-function-case camelCase --public-type-case camelCase \
-        --private-function-case camelCase --private-type-case camelCase \
-        --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' \
-        --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' \
-        --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' \
-        carry_mul carry_square carry add sub to_bytes from_bytes selectznz \
-        > p521_fiat64.go
-
-It comes under the following license.
+at version v0.0.9 from a formally verified model, and by the addchain
+project at a recent tip version.
+
+    docker build -t fiat-crypto:v0.0.9 .
+    go install github.com/mmcloughlin/addchain/cmd/addchain@v0.3.1-0.20211027081849-6a7d3decbe08
+    ../../../../../bin/go run generate.go
+
+fiat-crypto code comes under the following license.
 
     Copyright (c) 2015-2020 The fiat-crypto Authors. All rights reserved.
 
diff --git a/src/crypto/elliptic/internal/fiat/fiat_test.go b/src/crypto/elliptic/internal/fiat/fiat_test.go
new file mode 100644 (file)
index 0000000..9ecd863
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright 2021 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.
+
+package fiat_test
+
+import (
+       "crypto/elliptic/internal/fiat"
+       "testing"
+)
+
+func BenchmarkMul(b *testing.B) {
+       b.Run("P224", func(b *testing.B) {
+               v := new(fiat.P224Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Mul(v, v)
+               }
+       })
+       b.Run("P384", func(b *testing.B) {
+               v := new(fiat.P384Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Mul(v, v)
+               }
+       })
+       b.Run("P521", func(b *testing.B) {
+               v := new(fiat.P521Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Mul(v, v)
+               }
+       })
+}
+
+func BenchmarkSquare(b *testing.B) {
+       b.Run("P224", func(b *testing.B) {
+               v := new(fiat.P224Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Square(v)
+               }
+       })
+       b.Run("P384", func(b *testing.B) {
+               v := new(fiat.P384Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Square(v)
+               }
+       })
+       b.Run("P521", func(b *testing.B) {
+               v := new(fiat.P521Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Square(v)
+               }
+       })
+}
diff --git a/src/crypto/elliptic/internal/fiat/generate.go b/src/crypto/elliptic/internal/fiat/generate.go
new file mode 100644 (file)
index 0000000..fd8509d
--- /dev/null
@@ -0,0 +1,330 @@
+// Copyright 2021 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.
+
+//go:build ignore
+
+package main
+
+import (
+       "bytes"
+       "go/format"
+       "io"
+       "log"
+       "os"
+       "os/exec"
+       "text/template"
+)
+
+var curves = []struct {
+       Element  string
+       Prime    string
+       Prefix   string
+       FiatType string
+       BytesLen int
+}{
+       {
+               Element:  "P224Element",
+               Prime:    "2^224 - 2^96 + 1",
+               Prefix:   "p224",
+               FiatType: "[4]uint64",
+               BytesLen: 28,
+       },
+       // The 32-bit pure Go P-256 in crypto/elliptic is still faster than the
+       // autogenerated code here, regrettably.
+       // {
+       //  Element:  "P256Element",
+       //  Prime:    "2^256 - 2^224 + 2^192 + 2^96 - 1",
+       //  Prefix:   "p256",
+       //  FiatType: "[4]uint64",
+       //  BytesLen: 32,
+       // },
+       {
+               Element:  "P384Element",
+               Prime:    "2^384 - 2^128 - 2^96 + 2^32 - 1",
+               Prefix:   "p384",
+               FiatType: "[6]uint64",
+               BytesLen: 48,
+       },
+       // Note that unsaturated_solinas would be about 2x faster than
+       // word_by_word_montgomery for P-521, but this curve is used rarely enough
+       // that it's not worth carrying unsaturated_solinas support for it.
+       {
+               Element:  "P521Element",
+               Prime:    "2^521 - 1",
+               Prefix:   "p521",
+               FiatType: "[9]uint64",
+               BytesLen: 66,
+       },
+}
+
+func main() {
+       t := template.Must(template.New("montgomery").Parse(tmplWrapper))
+
+       tmplAddchainFile, err := os.CreateTemp("", "addchain-template")
+       if err != nil {
+               log.Fatal(err)
+       }
+       defer os.Remove(tmplAddchainFile.Name())
+       if _, err := io.WriteString(tmplAddchainFile, tmplAddchain); err != nil {
+               log.Fatal(err)
+       }
+       if err := tmplAddchainFile.Close(); err != nil {
+               log.Fatal(err)
+       }
+
+       for _, c := range curves {
+               log.Printf("Generating %s.go...", c.Prefix)
+               f, err := os.Create(c.Prefix + ".go")
+               if err != nil {
+                       log.Fatal(err)
+               }
+               if err := t.Execute(f, c); err != nil {
+                       log.Fatal(err)
+               }
+               if err := f.Close(); err != nil {
+                       log.Fatal(err)
+               }
+
+               log.Printf("Generating %s_fiat64.go...", c.Prefix)
+               cmd := exec.Command("docker", "run", "--rm", "--entrypoint", "word_by_word_montgomery",
+                       "fiat-crypto:v0.0.9", "--lang", "Go", "--no-wide-int", "--cmovznz-by-mul",
+                       "--relax-primitive-carry-to-bitwidth", "32,64", "--internal-static",
+                       "--public-function-case", "camelCase", "--public-type-case", "camelCase",
+                       "--private-function-case", "camelCase", "--private-type-case", "camelCase",
+                       "--doc-text-before-function-name", "", "--doc-newline-before-package-declaration",
+                       "--doc-prepend-header", "Code generated by Fiat Cryptography. DO NOT EDIT.",
+                       "--package-name", "fiat", "--no-prefix-fiat", c.Prefix, "64", c.Prime,
+                       "mul", "square", "add", "sub", "one", "from_montgomery", "to_montgomery",
+                       "selectznz", "to_bytes", "from_bytes")
+               cmd.Stderr = os.Stderr
+               out, err := cmd.Output()
+               if err != nil {
+                       log.Fatal(err)
+               }
+               out, err = format.Source(out)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               if err := os.WriteFile(c.Prefix+"_fiat64.go", out, 0644); err != nil {
+                       log.Fatal(err)
+               }
+
+               log.Printf("Generating %s_invert.go...", c.Prefix)
+               f, err = os.CreateTemp("", "addchain-"+c.Prefix)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               defer os.Remove(f.Name())
+               cmd = exec.Command("addchain", "search", c.Prime+" - 2")
+               cmd.Stderr = os.Stderr
+               cmd.Stdout = f
+               if err := cmd.Run(); err != nil {
+                       log.Fatal(err)
+               }
+               if err := f.Close(); err != nil {
+                       log.Fatal(err)
+               }
+               cmd = exec.Command("addchain", "gen", "-tmpl", tmplAddchainFile.Name(), f.Name())
+               cmd.Stderr = os.Stderr
+               out, err = cmd.Output()
+               if err != nil {
+                       log.Fatal(err)
+               }
+               out = bytes.Replace(out, []byte("Element"), []byte(c.Element), -1)
+               out, err = format.Source(out)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               if err := os.WriteFile(c.Prefix+"_invert.go", out, 0644); err != nil {
+                       log.Fatal(err)
+               }
+       }
+}
+
+const tmplWrapper = `// Copyright 2021 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.
+
+// Code generated by generate.go. DO NOT EDIT.
+
+package fiat
+
+import (
+       "crypto/subtle"
+       "errors"
+)
+
+// {{ .Element }} is an integer modulo {{ .Prime }}.
+//
+// The zero value is a valid zero element.
+type {{ .Element }} struct {
+       // Values are represented internally always in the Montgomery domain, and
+       // converted in Bytes and SetBytes.
+       x {{ .Prefix }}MontgomeryDomainFieldElement
+}
+
+const {{ .Prefix }}ElementLen = {{ .BytesLen }}
+
+type {{ .Prefix }}UntypedFieldElement = {{ .FiatType }}
+
+// One sets e = 1, and returns e.
+func (e *{{ .Element }}) One() *{{ .Element }} {
+       {{ .Prefix }}SetOne(&e.x)
+       return e
+}
+
+// Equal returns 1 if e == t, and zero otherwise.
+func (e *{{ .Element }}) Equal(t *{{ .Element }}) int {
+       eBytes := e.Bytes()
+       tBytes := t.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, tBytes)
+}
+
+var {{ .Prefix }}ZeroEncoding = new({{ .Element }}).Bytes()
+
+// IsZero returns 1 if e == 0, and zero otherwise.
+func (e *{{ .Element }}) IsZero() int {
+       eBytes := e.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, {{ .Prefix }}ZeroEncoding)
+}
+
+// Set sets e = t, and returns e.
+func (e *{{ .Element }}) Set(t *{{ .Element }}) *{{ .Element }} {
+       e.x = t.x
+       return e
+}
+
+// Bytes returns the {{ .BytesLen }}-byte big-endian encoding of e.
+func (e *{{ .Element }}) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [{{ .Prefix }}ElementLen]byte
+       return e.bytes(&out)
+}
+
+func (e *{{ .Element }}) bytes(out *[{{ .Prefix }}ElementLen]byte) []byte {
+       var tmp {{ .Prefix }}NonMontgomeryDomainFieldElement
+       {{ .Prefix }}FromMontgomery(&tmp, &e.x)
+       {{ .Prefix }}ToBytes(out, (*{{ .Prefix }}UntypedFieldElement)(&tmp))
+       {{ .Prefix }}InvertEndianness(out[:])
+       return out[:]
+}
+
+// {{ .Prefix }}MinusOneEncoding is the encoding of -1 mod p, so p - 1, the
+// highest canonical encoding. It is used by SetBytes to check for non-canonical
+// encodings such as p + k, 2p + k, etc.
+var {{ .Prefix }}MinusOneEncoding = new({{ .Element }}).Sub(
+       new({{ .Element }}), new({{ .Element }}).One()).Bytes()
+
+// SetBytes sets e = v, where v is a big-endian {{ .BytesLen }}-byte encoding, and returns e.
+// If v is not {{ .BytesLen }} bytes or it encodes a value higher than {{ .Prime }},
+// SetBytes returns nil and an error, and e is unchanged.
+func (e *{{ .Element }}) SetBytes(v []byte) (*{{ .Element }}, error) {
+       if len(v) != {{ .Prefix }}ElementLen {
+               return nil, errors.New("invalid {{ .Element }} encoding")
+       }
+       for i := range v {
+               if v[i] < {{ .Prefix }}MinusOneEncoding[i] {
+                       break
+               }
+               if v[i] > {{ .Prefix }}MinusOneEncoding[i] {
+                       return nil, errors.New("invalid {{ .Element }} encoding")
+               }
+       }
+       var in [{{ .Prefix }}ElementLen]byte
+       copy(in[:], v)
+       {{ .Prefix }}InvertEndianness(in[:])
+       var tmp {{ .Prefix }}NonMontgomeryDomainFieldElement
+       {{ .Prefix }}FromBytes((*{{ .Prefix }}UntypedFieldElement)(&tmp), &in)
+       {{ .Prefix }}ToMontgomery(&e.x, &tmp)
+       return e, nil
+}
+
+// Add sets e = t1 + t2, and returns e.
+func (e *{{ .Element }}) Add(t1, t2 *{{ .Element }}) *{{ .Element }} {
+       {{ .Prefix }}Add(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Sub sets e = t1 - t2, and returns e.
+func (e *{{ .Element }}) Sub(t1, t2 *{{ .Element }}) *{{ .Element }} {
+       {{ .Prefix }}Sub(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Mul sets e = t1 * t2, and returns e.
+func (e *{{ .Element }}) Mul(t1, t2 *{{ .Element }}) *{{ .Element }} {
+       {{ .Prefix }}Mul(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Square sets e = t * t, and returns e.
+func (e *{{ .Element }}) Square(t *{{ .Element }}) *{{ .Element }} {
+       {{ .Prefix }}Square(&e.x, &t.x)
+       return e
+}
+
+// Select sets v to a if cond == 1, and to b if cond == 0.
+func (v *{{ .Element }}) Select(a, b *{{ .Element }}, cond int) *{{ .Element }} {
+       {{ .Prefix }}Selectznz((*{{ .Prefix }}UntypedFieldElement)(&v.x), {{ .Prefix }}Uint1(cond),
+               (*{{ .Prefix }}UntypedFieldElement)(&b.x), (*{{ .Prefix }}UntypedFieldElement)(&a.x))
+       return v
+}
+
+func {{ .Prefix }}InvertEndianness(v []byte) {
+       for i := 0; i < len(v)/2; i++ {
+               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
+       }
+}
+`
+
+const tmplAddchain = `// Copyright 2021 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.
+
+// Code generated by {{ .Meta.Name }}. DO NOT EDIT.
+
+package fiat
+
+// Invert sets e = 1/x, and returns e.
+//
+// If x == 0, Invert returns e = 0.
+func (e *Element) Invert(x *Element) *Element {
+       // Inversion is implemented as exponentiation with exponent p − 2.
+       // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the
+       // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}.
+       //
+       {{- range lines (format .Script) }}
+       //      {{ . }}
+       {{- end }}
+       //
+
+       var z = new(Element).Set(e)
+       {{- range .Program.Temporaries }}
+       var {{ . }} = new(Element)
+       {{- end }}
+       {{ range $i := .Program.Instructions -}}
+       {{- with add $i.Op }}
+       {{ $i.Output }}.Mul({{ .X }}, {{ .Y }})
+       {{- end -}}
+
+       {{- with double $i.Op }}
+       {{ $i.Output }}.Square({{ .X }})
+       {{- end -}}
+
+       {{- with shift $i.Op -}}
+       {{- $first := 0 -}}
+       {{- if ne $i.Output.Identifier .X.Identifier }}
+       {{ $i.Output }}.Square({{ .X }})
+       {{- $first = 1 -}}
+       {{- end }}
+       for s := {{ $first }}; s < {{ .S }}; s++ {
+               {{ $i.Output }}.Square({{ $i.Output }})
+       }
+       {{- end -}}
+       {{- end }}
+
+       return e.Set(z)
+}
+`
diff --git a/src/crypto/elliptic/internal/fiat/p224.go b/src/crypto/elliptic/internal/fiat/p224.go
new file mode 100644 (file)
index 0000000..4dddeb0
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright 2021 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.
+
+// Code generated by generate.go. DO NOT EDIT.
+
+package fiat
+
+import (
+       "crypto/subtle"
+       "errors"
+)
+
+// P224Element is an integer modulo 2^224 - 2^96 + 1.
+//
+// The zero value is a valid zero element.
+type P224Element struct {
+       // Values are represented internally always in the Montgomery domain, and
+       // converted in Bytes and SetBytes.
+       x p224MontgomeryDomainFieldElement
+}
+
+const p224ElementLen = 28
+
+type p224UntypedFieldElement = [4]uint64
+
+// One sets e = 1, and returns e.
+func (e *P224Element) One() *P224Element {
+       p224SetOne(&e.x)
+       return e
+}
+
+// Equal returns 1 if e == t, and zero otherwise.
+func (e *P224Element) Equal(t *P224Element) int {
+       eBytes := e.Bytes()
+       tBytes := t.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, tBytes)
+}
+
+var p224ZeroEncoding = new(P224Element).Bytes()
+
+// IsZero returns 1 if e == 0, and zero otherwise.
+func (e *P224Element) IsZero() int {
+       eBytes := e.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, p224ZeroEncoding)
+}
+
+// Set sets e = t, and returns e.
+func (e *P224Element) Set(t *P224Element) *P224Element {
+       e.x = t.x
+       return e
+}
+
+// Bytes returns the 28-byte big-endian encoding of e.
+func (e *P224Element) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [p224ElementLen]byte
+       return e.bytes(&out)
+}
+
+func (e *P224Element) bytes(out *[p224ElementLen]byte) []byte {
+       var tmp p224NonMontgomeryDomainFieldElement
+       p224FromMontgomery(&tmp, &e.x)
+       p224ToBytes(out, (*p224UntypedFieldElement)(&tmp))
+       p224InvertEndianness(out[:])
+       return out[:]
+}
+
+// p224MinusOneEncoding is the encoding of -1 mod p, so p - 1, the
+// highest canonical encoding. It is used by SetBytes to check for non-canonical
+// encodings such as p + k, 2p + k, etc.
+var p224MinusOneEncoding = new(P224Element).Sub(
+       new(P224Element), new(P224Element).One()).Bytes()
+
+// SetBytes sets e = v, where v is a big-endian 28-byte encoding, and returns e.
+// If v is not 28 bytes or it encodes a value higher than 2^224 - 2^96 + 1,
+// SetBytes returns nil and an error, and e is unchanged.
+func (e *P224Element) SetBytes(v []byte) (*P224Element, error) {
+       if len(v) != p224ElementLen {
+               return nil, errors.New("invalid P224Element encoding")
+       }
+       for i := range v {
+               if v[i] < p224MinusOneEncoding[i] {
+                       break
+               }
+               if v[i] > p224MinusOneEncoding[i] {
+                       return nil, errors.New("invalid P224Element encoding")
+               }
+       }
+       var in [p224ElementLen]byte
+       copy(in[:], v)
+       p224InvertEndianness(in[:])
+       var tmp p224NonMontgomeryDomainFieldElement
+       p224FromBytes((*p224UntypedFieldElement)(&tmp), &in)
+       p224ToMontgomery(&e.x, &tmp)
+       return e, nil
+}
+
+// Add sets e = t1 + t2, and returns e.
+func (e *P224Element) Add(t1, t2 *P224Element) *P224Element {
+       p224Add(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Sub sets e = t1 - t2, and returns e.
+func (e *P224Element) Sub(t1, t2 *P224Element) *P224Element {
+       p224Sub(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Mul sets e = t1 * t2, and returns e.
+func (e *P224Element) Mul(t1, t2 *P224Element) *P224Element {
+       p224Mul(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Square sets e = t * t, and returns e.
+func (e *P224Element) Square(t *P224Element) *P224Element {
+       p224Square(&e.x, &t.x)
+       return e
+}
+
+// Select sets v to a if cond == 1, and to b if cond == 0.
+func (v *P224Element) Select(a, b *P224Element, cond int) *P224Element {
+       p224Selectznz((*p224UntypedFieldElement)(&v.x), p224Uint1(cond),
+               (*p224UntypedFieldElement)(&b.x), (*p224UntypedFieldElement)(&a.x))
+       return v
+}
+
+func p224InvertEndianness(v []byte) {
+       for i := 0; i < len(v)/2; i++ {
+               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
+       }
+}
diff --git a/src/crypto/elliptic/internal/fiat/p224_fiat64.go b/src/crypto/elliptic/internal/fiat/p224_fiat64.go
new file mode 100644 (file)
index 0000000..4ece3e9
--- /dev/null
@@ -0,0 +1,1429 @@
+// Code generated by Fiat Cryptography. DO NOT EDIT.
+//
+// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p224 64 '2^224 - 2^96 + 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes
+//
+// curve description: p224
+//
+// machine_wordsize = 64 (from "64")
+//
+// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes
+//
+// m = 0xffffffffffffffffffffffffffffffff000000000000000000000001 (from "2^224 - 2^96 + 1")
+//
+//
+//
+// NOTE: In addition to the bounds specified above each function, all
+//
+//   functions synthesized for this Montgomery arithmetic require the
+//
+//   input to be strictly less than the prime modulus (m), and also
+//
+//   require the input to be in the unique saturated representation.
+//
+//   All functions also ensure that these two properties are true of
+//
+//   return values.
+//
+//
+//
+// Computed values:
+//
+//   eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192)
+//
+//   bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216)
+//
+//   twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in
+//
+//                            if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256
+
+package fiat
+
+import "math/bits"
+
+type p224Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+type p224Int1 int64   // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+
+// The type p224MontgomeryDomainFieldElement is a field element in the Montgomery domain.
+//
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p224MontgomeryDomainFieldElement [4]uint64
+
+// The type p224NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain.
+//
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p224NonMontgomeryDomainFieldElement [4]uint64
+
+// p224CmovznzU64 is a single-word conditional move.
+//
+// Postconditions:
+//   out1 = (if arg1 = 0 then arg2 else arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [0x0 ~> 0xffffffffffffffff]
+//   arg3: [0x0 ~> 0xffffffffffffffff]
+// Output Bounds:
+//   out1: [0x0 ~> 0xffffffffffffffff]
+func p224CmovznzU64(out1 *uint64, arg1 p224Uint1, arg2 uint64, arg3 uint64) {
+       x1 := (uint64(arg1) * 0xffffffffffffffff)
+       x2 := ((x1 & arg3) | ((^x1) & arg2))
+       *out1 = x2
+}
+
+// p224Mul multiplies two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+//   0 ≤ eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
+//   0 ≤ eval out1 < m
+//
+func p224Mul(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[0]
+       var x5 uint64
+       var x6 uint64
+       x6, x5 = bits.Mul64(x4, arg2[3])
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x4, arg2[2])
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x4, arg2[1])
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x4, arg2[0])
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Add64(x12, x9, uint64(0x0))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16)))
+       x19 := (uint64(p224Uint1(x18)) + x6)
+       var x20 uint64
+       _, x20 = bits.Mul64(x11, 0xffffffffffffffff)
+       var x22 uint64
+       var x23 uint64
+       x23, x22 = bits.Mul64(x20, 0xffffffff)
+       var x24 uint64
+       var x25 uint64
+       x25, x24 = bits.Mul64(x20, 0xffffffffffffffff)
+       var x26 uint64
+       var x27 uint64
+       x27, x26 = bits.Mul64(x20, 0xffffffff00000000)
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(x27, x24, uint64(0x0))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(x25, x22, uint64(p224Uint1(x29)))
+       x32 := (uint64(p224Uint1(x31)) + x23)
+       var x34 uint64
+       _, x34 = bits.Add64(x11, x20, uint64(0x0))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Add64(x13, x26, uint64(p224Uint1(x34)))
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x15, x28, uint64(p224Uint1(x36)))
+       var x39 uint64
+       var x40 uint64
+       x39, x40 = bits.Add64(x17, x30, uint64(p224Uint1(x38)))
+       var x41 uint64
+       var x42 uint64
+       x41, x42 = bits.Add64(x19, x32, uint64(p224Uint1(x40)))
+       var x43 uint64
+       var x44 uint64
+       x44, x43 = bits.Mul64(x1, arg2[3])
+       var x45 uint64
+       var x46 uint64
+       x46, x45 = bits.Mul64(x1, arg2[2])
+       var x47 uint64
+       var x48 uint64
+       x48, x47 = bits.Mul64(x1, arg2[1])
+       var x49 uint64
+       var x50 uint64
+       x50, x49 = bits.Mul64(x1, arg2[0])
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(x50, x47, uint64(0x0))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(x48, x45, uint64(p224Uint1(x52)))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(x46, x43, uint64(p224Uint1(x54)))
+       x57 := (uint64(p224Uint1(x56)) + x44)
+       var x58 uint64
+       var x59 uint64
+       x58, x59 = bits.Add64(x35, x49, uint64(0x0))
+       var x60 uint64
+       var x61 uint64
+       x60, x61 = bits.Add64(x37, x51, uint64(p224Uint1(x59)))
+       var x62 uint64
+       var x63 uint64
+       x62, x63 = bits.Add64(x39, x53, uint64(p224Uint1(x61)))
+       var x64 uint64
+       var x65 uint64
+       x64, x65 = bits.Add64(x41, x55, uint64(p224Uint1(x63)))
+       var x66 uint64
+       var x67 uint64
+       x66, x67 = bits.Add64(uint64(p224Uint1(x42)), x57, uint64(p224Uint1(x65)))
+       var x68 uint64
+       _, x68 = bits.Mul64(x58, 0xffffffffffffffff)
+       var x70 uint64
+       var x71 uint64
+       x71, x70 = bits.Mul64(x68, 0xffffffff)
+       var x72 uint64
+       var x73 uint64
+       x73, x72 = bits.Mul64(x68, 0xffffffffffffffff)
+       var x74 uint64
+       var x75 uint64
+       x75, x74 = bits.Mul64(x68, 0xffffffff00000000)
+       var x76 uint64
+       var x77 uint64
+       x76, x77 = bits.Add64(x75, x72, uint64(0x0))
+       var x78 uint64
+       var x79 uint64
+       x78, x79 = bits.Add64(x73, x70, uint64(p224Uint1(x77)))
+       x80 := (uint64(p224Uint1(x79)) + x71)
+       var x82 uint64
+       _, x82 = bits.Add64(x58, x68, uint64(0x0))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x60, x74, uint64(p224Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x62, x76, uint64(p224Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x64, x78, uint64(p224Uint1(x86)))
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x66, x80, uint64(p224Uint1(x88)))
+       x91 := (uint64(p224Uint1(x90)) + uint64(p224Uint1(x67)))
+       var x92 uint64
+       var x93 uint64
+       x93, x92 = bits.Mul64(x2, arg2[3])
+       var x94 uint64
+       var x95 uint64
+       x95, x94 = bits.Mul64(x2, arg2[2])
+       var x96 uint64
+       var x97 uint64
+       x97, x96 = bits.Mul64(x2, arg2[1])
+       var x98 uint64
+       var x99 uint64
+       x99, x98 = bits.Mul64(x2, arg2[0])
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x99, x96, uint64(0x0))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x97, x94, uint64(p224Uint1(x101)))
+       var x104 uint64
+       var x105 uint64
+       x104, x105 = bits.Add64(x95, x92, uint64(p224Uint1(x103)))
+       x106 := (uint64(p224Uint1(x105)) + x93)
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Add64(x83, x98, uint64(0x0))
+       var x109 uint64
+       var x110 uint64
+       x109, x110 = bits.Add64(x85, x100, uint64(p224Uint1(x108)))
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x87, x102, uint64(p224Uint1(x110)))
+       var x113 uint64
+       var x114 uint64
+       x113, x114 = bits.Add64(x89, x104, uint64(p224Uint1(x112)))
+       var x115 uint64
+       var x116 uint64
+       x115, x116 = bits.Add64(x91, x106, uint64(p224Uint1(x114)))
+       var x117 uint64
+       _, x117 = bits.Mul64(x107, 0xffffffffffffffff)
+       var x119 uint64
+       var x120 uint64
+       x120, x119 = bits.Mul64(x117, 0xffffffff)
+       var x121 uint64
+       var x122 uint64
+       x122, x121 = bits.Mul64(x117, 0xffffffffffffffff)
+       var x123 uint64
+       var x124 uint64
+       x124, x123 = bits.Mul64(x117, 0xffffffff00000000)
+       var x125 uint64
+       var x126 uint64
+       x125, x126 = bits.Add64(x124, x121, uint64(0x0))
+       var x127 uint64
+       var x128 uint64
+       x127, x128 = bits.Add64(x122, x119, uint64(p224Uint1(x126)))
+       x129 := (uint64(p224Uint1(x128)) + x120)
+       var x131 uint64
+       _, x131 = bits.Add64(x107, x117, uint64(0x0))
+       var x132 uint64
+       var x133 uint64
+       x132, x133 = bits.Add64(x109, x123, uint64(p224Uint1(x131)))
+       var x134 uint64
+       var x135 uint64
+       x134, x135 = bits.Add64(x111, x125, uint64(p224Uint1(x133)))
+       var x136 uint64
+       var x137 uint64
+       x136, x137 = bits.Add64(x113, x127, uint64(p224Uint1(x135)))
+       var x138 uint64
+       var x139 uint64
+       x138, x139 = bits.Add64(x115, x129, uint64(p224Uint1(x137)))
+       x140 := (uint64(p224Uint1(x139)) + uint64(p224Uint1(x116)))
+       var x141 uint64
+       var x142 uint64
+       x142, x141 = bits.Mul64(x3, arg2[3])
+       var x143 uint64
+       var x144 uint64
+       x144, x143 = bits.Mul64(x3, arg2[2])
+       var x145 uint64
+       var x146 uint64
+       x146, x145 = bits.Mul64(x3, arg2[1])
+       var x147 uint64
+       var x148 uint64
+       x148, x147 = bits.Mul64(x3, arg2[0])
+       var x149 uint64
+       var x150 uint64
+       x149, x150 = bits.Add64(x148, x145, uint64(0x0))
+       var x151 uint64
+       var x152 uint64
+       x151, x152 = bits.Add64(x146, x143, uint64(p224Uint1(x150)))
+       var x153 uint64
+       var x154 uint64
+       x153, x154 = bits.Add64(x144, x141, uint64(p224Uint1(x152)))
+       x155 := (uint64(p224Uint1(x154)) + x142)
+       var x156 uint64
+       var x157 uint64
+       x156, x157 = bits.Add64(x132, x147, uint64(0x0))
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x134, x149, uint64(p224Uint1(x157)))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x136, x151, uint64(p224Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x138, x153, uint64(p224Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x140, x155, uint64(p224Uint1(x163)))
+       var x166 uint64
+       _, x166 = bits.Mul64(x156, 0xffffffffffffffff)
+       var x168 uint64
+       var x169 uint64
+       x169, x168 = bits.Mul64(x166, 0xffffffff)
+       var x170 uint64
+       var x171 uint64
+       x171, x170 = bits.Mul64(x166, 0xffffffffffffffff)
+       var x172 uint64
+       var x173 uint64
+       x173, x172 = bits.Mul64(x166, 0xffffffff00000000)
+       var x174 uint64
+       var x175 uint64
+       x174, x175 = bits.Add64(x173, x170, uint64(0x0))
+       var x176 uint64
+       var x177 uint64
+       x176, x177 = bits.Add64(x171, x168, uint64(p224Uint1(x175)))
+       x178 := (uint64(p224Uint1(x177)) + x169)
+       var x180 uint64
+       _, x180 = bits.Add64(x156, x166, uint64(0x0))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x158, x172, uint64(p224Uint1(x180)))
+       var x183 uint64
+       var x184 uint64
+       x183, x184 = bits.Add64(x160, x174, uint64(p224Uint1(x182)))
+       var x185 uint64
+       var x186 uint64
+       x185, x186 = bits.Add64(x162, x176, uint64(p224Uint1(x184)))
+       var x187 uint64
+       var x188 uint64
+       x187, x188 = bits.Add64(x164, x178, uint64(p224Uint1(x186)))
+       x189 := (uint64(p224Uint1(x188)) + uint64(p224Uint1(x165)))
+       var x190 uint64
+       var x191 uint64
+       x190, x191 = bits.Sub64(x181, uint64(0x1), uint64(0x0))
+       var x192 uint64
+       var x193 uint64
+       x192, x193 = bits.Sub64(x183, 0xffffffff00000000, uint64(p224Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Sub64(x185, 0xffffffffffffffff, uint64(p224Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Sub64(x187, 0xffffffff, uint64(p224Uint1(x195)))
+       var x199 uint64
+       _, x199 = bits.Sub64(x189, uint64(0x0), uint64(p224Uint1(x197)))
+       var x200 uint64
+       p224CmovznzU64(&x200, p224Uint1(x199), x190, x181)
+       var x201 uint64
+       p224CmovznzU64(&x201, p224Uint1(x199), x192, x183)
+       var x202 uint64
+       p224CmovznzU64(&x202, p224Uint1(x199), x194, x185)
+       var x203 uint64
+       p224CmovznzU64(&x203, p224Uint1(x199), x196, x187)
+       out1[0] = x200
+       out1[1] = x201
+       out1[2] = x202
+       out1[3] = x203
+}
+
+// p224Square squares a field element in the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m
+//   0 ≤ eval out1 < m
+//
+func p224Square(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[0]
+       var x5 uint64
+       var x6 uint64
+       x6, x5 = bits.Mul64(x4, arg1[3])
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x4, arg1[2])
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x4, arg1[1])
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x4, arg1[0])
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Add64(x12, x9, uint64(0x0))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16)))
+       x19 := (uint64(p224Uint1(x18)) + x6)
+       var x20 uint64
+       _, x20 = bits.Mul64(x11, 0xffffffffffffffff)
+       var x22 uint64
+       var x23 uint64
+       x23, x22 = bits.Mul64(x20, 0xffffffff)
+       var x24 uint64
+       var x25 uint64
+       x25, x24 = bits.Mul64(x20, 0xffffffffffffffff)
+       var x26 uint64
+       var x27 uint64
+       x27, x26 = bits.Mul64(x20, 0xffffffff00000000)
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(x27, x24, uint64(0x0))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(x25, x22, uint64(p224Uint1(x29)))
+       x32 := (uint64(p224Uint1(x31)) + x23)
+       var x34 uint64
+       _, x34 = bits.Add64(x11, x20, uint64(0x0))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Add64(x13, x26, uint64(p224Uint1(x34)))
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x15, x28, uint64(p224Uint1(x36)))
+       var x39 uint64
+       var x40 uint64
+       x39, x40 = bits.Add64(x17, x30, uint64(p224Uint1(x38)))
+       var x41 uint64
+       var x42 uint64
+       x41, x42 = bits.Add64(x19, x32, uint64(p224Uint1(x40)))
+       var x43 uint64
+       var x44 uint64
+       x44, x43 = bits.Mul64(x1, arg1[3])
+       var x45 uint64
+       var x46 uint64
+       x46, x45 = bits.Mul64(x1, arg1[2])
+       var x47 uint64
+       var x48 uint64
+       x48, x47 = bits.Mul64(x1, arg1[1])
+       var x49 uint64
+       var x50 uint64
+       x50, x49 = bits.Mul64(x1, arg1[0])
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(x50, x47, uint64(0x0))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(x48, x45, uint64(p224Uint1(x52)))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(x46, x43, uint64(p224Uint1(x54)))
+       x57 := (uint64(p224Uint1(x56)) + x44)
+       var x58 uint64
+       var x59 uint64
+       x58, x59 = bits.Add64(x35, x49, uint64(0x0))
+       var x60 uint64
+       var x61 uint64
+       x60, x61 = bits.Add64(x37, x51, uint64(p224Uint1(x59)))
+       var x62 uint64
+       var x63 uint64
+       x62, x63 = bits.Add64(x39, x53, uint64(p224Uint1(x61)))
+       var x64 uint64
+       var x65 uint64
+       x64, x65 = bits.Add64(x41, x55, uint64(p224Uint1(x63)))
+       var x66 uint64
+       var x67 uint64
+       x66, x67 = bits.Add64(uint64(p224Uint1(x42)), x57, uint64(p224Uint1(x65)))
+       var x68 uint64
+       _, x68 = bits.Mul64(x58, 0xffffffffffffffff)
+       var x70 uint64
+       var x71 uint64
+       x71, x70 = bits.Mul64(x68, 0xffffffff)
+       var x72 uint64
+       var x73 uint64
+       x73, x72 = bits.Mul64(x68, 0xffffffffffffffff)
+       var x74 uint64
+       var x75 uint64
+       x75, x74 = bits.Mul64(x68, 0xffffffff00000000)
+       var x76 uint64
+       var x77 uint64
+       x76, x77 = bits.Add64(x75, x72, uint64(0x0))
+       var x78 uint64
+       var x79 uint64
+       x78, x79 = bits.Add64(x73, x70, uint64(p224Uint1(x77)))
+       x80 := (uint64(p224Uint1(x79)) + x71)
+       var x82 uint64
+       _, x82 = bits.Add64(x58, x68, uint64(0x0))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x60, x74, uint64(p224Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x62, x76, uint64(p224Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x64, x78, uint64(p224Uint1(x86)))
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x66, x80, uint64(p224Uint1(x88)))
+       x91 := (uint64(p224Uint1(x90)) + uint64(p224Uint1(x67)))
+       var x92 uint64
+       var x93 uint64
+       x93, x92 = bits.Mul64(x2, arg1[3])
+       var x94 uint64
+       var x95 uint64
+       x95, x94 = bits.Mul64(x2, arg1[2])
+       var x96 uint64
+       var x97 uint64
+       x97, x96 = bits.Mul64(x2, arg1[1])
+       var x98 uint64
+       var x99 uint64
+       x99, x98 = bits.Mul64(x2, arg1[0])
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x99, x96, uint64(0x0))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x97, x94, uint64(p224Uint1(x101)))
+       var x104 uint64
+       var x105 uint64
+       x104, x105 = bits.Add64(x95, x92, uint64(p224Uint1(x103)))
+       x106 := (uint64(p224Uint1(x105)) + x93)
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Add64(x83, x98, uint64(0x0))
+       var x109 uint64
+       var x110 uint64
+       x109, x110 = bits.Add64(x85, x100, uint64(p224Uint1(x108)))
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x87, x102, uint64(p224Uint1(x110)))
+       var x113 uint64
+       var x114 uint64
+       x113, x114 = bits.Add64(x89, x104, uint64(p224Uint1(x112)))
+       var x115 uint64
+       var x116 uint64
+       x115, x116 = bits.Add64(x91, x106, uint64(p224Uint1(x114)))
+       var x117 uint64
+       _, x117 = bits.Mul64(x107, 0xffffffffffffffff)
+       var x119 uint64
+       var x120 uint64
+       x120, x119 = bits.Mul64(x117, 0xffffffff)
+       var x121 uint64
+       var x122 uint64
+       x122, x121 = bits.Mul64(x117, 0xffffffffffffffff)
+       var x123 uint64
+       var x124 uint64
+       x124, x123 = bits.Mul64(x117, 0xffffffff00000000)
+       var x125 uint64
+       var x126 uint64
+       x125, x126 = bits.Add64(x124, x121, uint64(0x0))
+       var x127 uint64
+       var x128 uint64
+       x127, x128 = bits.Add64(x122, x119, uint64(p224Uint1(x126)))
+       x129 := (uint64(p224Uint1(x128)) + x120)
+       var x131 uint64
+       _, x131 = bits.Add64(x107, x117, uint64(0x0))
+       var x132 uint64
+       var x133 uint64
+       x132, x133 = bits.Add64(x109, x123, uint64(p224Uint1(x131)))
+       var x134 uint64
+       var x135 uint64
+       x134, x135 = bits.Add64(x111, x125, uint64(p224Uint1(x133)))
+       var x136 uint64
+       var x137 uint64
+       x136, x137 = bits.Add64(x113, x127, uint64(p224Uint1(x135)))
+       var x138 uint64
+       var x139 uint64
+       x138, x139 = bits.Add64(x115, x129, uint64(p224Uint1(x137)))
+       x140 := (uint64(p224Uint1(x139)) + uint64(p224Uint1(x116)))
+       var x141 uint64
+       var x142 uint64
+       x142, x141 = bits.Mul64(x3, arg1[3])
+       var x143 uint64
+       var x144 uint64
+       x144, x143 = bits.Mul64(x3, arg1[2])
+       var x145 uint64
+       var x146 uint64
+       x146, x145 = bits.Mul64(x3, arg1[1])
+       var x147 uint64
+       var x148 uint64
+       x148, x147 = bits.Mul64(x3, arg1[0])
+       var x149 uint64
+       var x150 uint64
+       x149, x150 = bits.Add64(x148, x145, uint64(0x0))
+       var x151 uint64
+       var x152 uint64
+       x151, x152 = bits.Add64(x146, x143, uint64(p224Uint1(x150)))
+       var x153 uint64
+       var x154 uint64
+       x153, x154 = bits.Add64(x144, x141, uint64(p224Uint1(x152)))
+       x155 := (uint64(p224Uint1(x154)) + x142)
+       var x156 uint64
+       var x157 uint64
+       x156, x157 = bits.Add64(x132, x147, uint64(0x0))
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x134, x149, uint64(p224Uint1(x157)))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x136, x151, uint64(p224Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x138, x153, uint64(p224Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x140, x155, uint64(p224Uint1(x163)))
+       var x166 uint64
+       _, x166 = bits.Mul64(x156, 0xffffffffffffffff)
+       var x168 uint64
+       var x169 uint64
+       x169, x168 = bits.Mul64(x166, 0xffffffff)
+       var x170 uint64
+       var x171 uint64
+       x171, x170 = bits.Mul64(x166, 0xffffffffffffffff)
+       var x172 uint64
+       var x173 uint64
+       x173, x172 = bits.Mul64(x166, 0xffffffff00000000)
+       var x174 uint64
+       var x175 uint64
+       x174, x175 = bits.Add64(x173, x170, uint64(0x0))
+       var x176 uint64
+       var x177 uint64
+       x176, x177 = bits.Add64(x171, x168, uint64(p224Uint1(x175)))
+       x178 := (uint64(p224Uint1(x177)) + x169)
+       var x180 uint64
+       _, x180 = bits.Add64(x156, x166, uint64(0x0))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x158, x172, uint64(p224Uint1(x180)))
+       var x183 uint64
+       var x184 uint64
+       x183, x184 = bits.Add64(x160, x174, uint64(p224Uint1(x182)))
+       var x185 uint64
+       var x186 uint64
+       x185, x186 = bits.Add64(x162, x176, uint64(p224Uint1(x184)))
+       var x187 uint64
+       var x188 uint64
+       x187, x188 = bits.Add64(x164, x178, uint64(p224Uint1(x186)))
+       x189 := (uint64(p224Uint1(x188)) + uint64(p224Uint1(x165)))
+       var x190 uint64
+       var x191 uint64
+       x190, x191 = bits.Sub64(x181, uint64(0x1), uint64(0x0))
+       var x192 uint64
+       var x193 uint64
+       x192, x193 = bits.Sub64(x183, 0xffffffff00000000, uint64(p224Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Sub64(x185, 0xffffffffffffffff, uint64(p224Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Sub64(x187, 0xffffffff, uint64(p224Uint1(x195)))
+       var x199 uint64
+       _, x199 = bits.Sub64(x189, uint64(0x0), uint64(p224Uint1(x197)))
+       var x200 uint64
+       p224CmovznzU64(&x200, p224Uint1(x199), x190, x181)
+       var x201 uint64
+       p224CmovznzU64(&x201, p224Uint1(x199), x192, x183)
+       var x202 uint64
+       p224CmovznzU64(&x202, p224Uint1(x199), x194, x185)
+       var x203 uint64
+       p224CmovznzU64(&x203, p224Uint1(x199), x196, x187)
+       out1[0] = x200
+       out1[1] = x201
+       out1[2] = x202
+       out1[3] = x203
+}
+
+// p224Add adds two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+//   0 ≤ eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
+//   0 ≤ eval out1 < m
+//
+func p224Add(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p224Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p224Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p224Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Sub64(x1, uint64(0x1), uint64(0x0))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Sub64(x3, 0xffffffff00000000, uint64(p224Uint1(x10)))
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Sub64(x5, 0xffffffffffffffff, uint64(p224Uint1(x12)))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Sub64(x7, 0xffffffff, uint64(p224Uint1(x14)))
+       var x18 uint64
+       _, x18 = bits.Sub64(uint64(p224Uint1(x8)), uint64(0x0), uint64(p224Uint1(x16)))
+       var x19 uint64
+       p224CmovznzU64(&x19, p224Uint1(x18), x9, x1)
+       var x20 uint64
+       p224CmovznzU64(&x20, p224Uint1(x18), x11, x3)
+       var x21 uint64
+       p224CmovznzU64(&x21, p224Uint1(x18), x13, x5)
+       var x22 uint64
+       p224CmovznzU64(&x22, p224Uint1(x18), x15, x7)
+       out1[0] = x19
+       out1[1] = x20
+       out1[2] = x21
+       out1[3] = x22
+}
+
+// p224Sub subtracts two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+//   0 ≤ eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
+//   0 ≤ eval out1 < m
+//
+func p224Sub(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p224Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p224Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p224Uint1(x6)))
+       var x9 uint64
+       p224CmovznzU64(&x9, p224Uint1(x8), uint64(0x0), 0xffffffffffffffff)
+       var x10 uint64
+       var x11 uint64
+       x10, x11 = bits.Add64(x1, uint64((p224Uint1(x9) & 0x1)), uint64(0x0))
+       var x12 uint64
+       var x13 uint64
+       x12, x13 = bits.Add64(x3, (x9 & 0xffffffff00000000), uint64(p224Uint1(x11)))
+       var x14 uint64
+       var x15 uint64
+       x14, x15 = bits.Add64(x5, x9, uint64(p224Uint1(x13)))
+       var x16 uint64
+       x16, _ = bits.Add64(x7, (x9 & 0xffffffff), uint64(p224Uint1(x15)))
+       out1[0] = x10
+       out1[1] = x12
+       out1[2] = x14
+       out1[3] = x16
+}
+
+// p224SetOne returns the field element one in the Montgomery domain.
+//
+// Postconditions:
+//   eval (from_montgomery out1) mod m = 1 mod m
+//   0 ≤ eval out1 < m
+//
+func p224SetOne(out1 *p224MontgomeryDomainFieldElement) {
+       out1[0] = 0xffffffff00000000
+       out1[1] = 0xffffffffffffffff
+       out1[2] = uint64(0x0)
+       out1[3] = uint64(0x0)
+}
+
+// p224FromMontgomery translates a field element out of the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m
+//   0 ≤ eval out1 < m
+//
+func p224FromMontgomery(out1 *p224NonMontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement) {
+       x1 := arg1[0]
+       var x2 uint64
+       _, x2 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x4 uint64
+       var x5 uint64
+       x5, x4 = bits.Mul64(x2, 0xffffffff)
+       var x6 uint64
+       var x7 uint64
+       x7, x6 = bits.Mul64(x2, 0xffffffffffffffff)
+       var x8 uint64
+       var x9 uint64
+       x9, x8 = bits.Mul64(x2, 0xffffffff00000000)
+       var x10 uint64
+       var x11 uint64
+       x10, x11 = bits.Add64(x9, x6, uint64(0x0))
+       var x12 uint64
+       var x13 uint64
+       x12, x13 = bits.Add64(x7, x4, uint64(p224Uint1(x11)))
+       var x15 uint64
+       _, x15 = bits.Add64(x1, x2, uint64(0x0))
+       var x16 uint64
+       var x17 uint64
+       x16, x17 = bits.Add64(uint64(0x0), x8, uint64(p224Uint1(x15)))
+       var x18 uint64
+       var x19 uint64
+       x18, x19 = bits.Add64(uint64(0x0), x10, uint64(p224Uint1(x17)))
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(uint64(0x0), x12, uint64(p224Uint1(x19)))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x16, arg1[1], uint64(0x0))
+       var x24 uint64
+       var x25 uint64
+       x24, x25 = bits.Add64(x18, uint64(0x0), uint64(p224Uint1(x23)))
+       var x26 uint64
+       var x27 uint64
+       x26, x27 = bits.Add64(x20, uint64(0x0), uint64(p224Uint1(x25)))
+       var x28 uint64
+       _, x28 = bits.Mul64(x22, 0xffffffffffffffff)
+       var x30 uint64
+       var x31 uint64
+       x31, x30 = bits.Mul64(x28, 0xffffffff)
+       var x32 uint64
+       var x33 uint64
+       x33, x32 = bits.Mul64(x28, 0xffffffffffffffff)
+       var x34 uint64
+       var x35 uint64
+       x35, x34 = bits.Mul64(x28, 0xffffffff00000000)
+       var x36 uint64
+       var x37 uint64
+       x36, x37 = bits.Add64(x35, x32, uint64(0x0))
+       var x38 uint64
+       var x39 uint64
+       x38, x39 = bits.Add64(x33, x30, uint64(p224Uint1(x37)))
+       var x41 uint64
+       _, x41 = bits.Add64(x22, x28, uint64(0x0))
+       var x42 uint64
+       var x43 uint64
+       x42, x43 = bits.Add64(x24, x34, uint64(p224Uint1(x41)))
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(x26, x36, uint64(p224Uint1(x43)))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64((uint64(p224Uint1(x27)) + (uint64(p224Uint1(x21)) + (uint64(p224Uint1(x13)) + x5))), x38, uint64(p224Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(x42, arg1[2], uint64(0x0))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(x44, uint64(0x0), uint64(p224Uint1(x49)))
+       var x52 uint64
+       var x53 uint64
+       x52, x53 = bits.Add64(x46, uint64(0x0), uint64(p224Uint1(x51)))
+       var x54 uint64
+       _, x54 = bits.Mul64(x48, 0xffffffffffffffff)
+       var x56 uint64
+       var x57 uint64
+       x57, x56 = bits.Mul64(x54, 0xffffffff)
+       var x58 uint64
+       var x59 uint64
+       x59, x58 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x60 uint64
+       var x61 uint64
+       x61, x60 = bits.Mul64(x54, 0xffffffff00000000)
+       var x62 uint64
+       var x63 uint64
+       x62, x63 = bits.Add64(x61, x58, uint64(0x0))
+       var x64 uint64
+       var x65 uint64
+       x64, x65 = bits.Add64(x59, x56, uint64(p224Uint1(x63)))
+       var x67 uint64
+       _, x67 = bits.Add64(x48, x54, uint64(0x0))
+       var x68 uint64
+       var x69 uint64
+       x68, x69 = bits.Add64(x50, x60, uint64(p224Uint1(x67)))
+       var x70 uint64
+       var x71 uint64
+       x70, x71 = bits.Add64(x52, x62, uint64(p224Uint1(x69)))
+       var x72 uint64
+       var x73 uint64
+       x72, x73 = bits.Add64((uint64(p224Uint1(x53)) + (uint64(p224Uint1(x47)) + (uint64(p224Uint1(x39)) + x31))), x64, uint64(p224Uint1(x71)))
+       var x74 uint64
+       var x75 uint64
+       x74, x75 = bits.Add64(x68, arg1[3], uint64(0x0))
+       var x76 uint64
+       var x77 uint64
+       x76, x77 = bits.Add64(x70, uint64(0x0), uint64(p224Uint1(x75)))
+       var x78 uint64
+       var x79 uint64
+       x78, x79 = bits.Add64(x72, uint64(0x0), uint64(p224Uint1(x77)))
+       var x80 uint64
+       _, x80 = bits.Mul64(x74, 0xffffffffffffffff)
+       var x82 uint64
+       var x83 uint64
+       x83, x82 = bits.Mul64(x80, 0xffffffff)
+       var x84 uint64
+       var x85 uint64
+       x85, x84 = bits.Mul64(x80, 0xffffffffffffffff)
+       var x86 uint64
+       var x87 uint64
+       x87, x86 = bits.Mul64(x80, 0xffffffff00000000)
+       var x88 uint64
+       var x89 uint64
+       x88, x89 = bits.Add64(x87, x84, uint64(0x0))
+       var x90 uint64
+       var x91 uint64
+       x90, x91 = bits.Add64(x85, x82, uint64(p224Uint1(x89)))
+       var x93 uint64
+       _, x93 = bits.Add64(x74, x80, uint64(0x0))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x76, x86, uint64(p224Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x78, x88, uint64(p224Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64((uint64(p224Uint1(x79)) + (uint64(p224Uint1(x73)) + (uint64(p224Uint1(x65)) + x57))), x90, uint64(p224Uint1(x97)))
+       x100 := (uint64(p224Uint1(x99)) + (uint64(p224Uint1(x91)) + x83))
+       var x101 uint64
+       var x102 uint64
+       x101, x102 = bits.Sub64(x94, uint64(0x1), uint64(0x0))
+       var x103 uint64
+       var x104 uint64
+       x103, x104 = bits.Sub64(x96, 0xffffffff00000000, uint64(p224Uint1(x102)))
+       var x105 uint64
+       var x106 uint64
+       x105, x106 = bits.Sub64(x98, 0xffffffffffffffff, uint64(p224Uint1(x104)))
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Sub64(x100, 0xffffffff, uint64(p224Uint1(x106)))
+       var x110 uint64
+       _, x110 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p224Uint1(x108)))
+       var x111 uint64
+       p224CmovznzU64(&x111, p224Uint1(x110), x101, x94)
+       var x112 uint64
+       p224CmovznzU64(&x112, p224Uint1(x110), x103, x96)
+       var x113 uint64
+       p224CmovznzU64(&x113, p224Uint1(x110), x105, x98)
+       var x114 uint64
+       p224CmovznzU64(&x114, p224Uint1(x110), x107, x100)
+       out1[0] = x111
+       out1[1] = x112
+       out1[2] = x113
+       out1[3] = x114
+}
+
+// p224ToMontgomery translates a field element into the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = eval arg1 mod m
+//   0 ≤ eval out1 < m
+//
+func p224ToMontgomery(out1 *p224MontgomeryDomainFieldElement, arg1 *p224NonMontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[0]
+       var x5 uint64
+       var x6 uint64
+       x6, x5 = bits.Mul64(x4, 0xffffffff)
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x4, 0xfffffffe00000000)
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x4, 0xffffffff00000000)
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x4, 0xffffffff00000001)
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Add64(x12, x9, uint64(0x0))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16)))
+       var x19 uint64
+       _, x19 = bits.Mul64(x11, 0xffffffffffffffff)
+       var x21 uint64
+       var x22 uint64
+       x22, x21 = bits.Mul64(x19, 0xffffffff)
+       var x23 uint64
+       var x24 uint64
+       x24, x23 = bits.Mul64(x19, 0xffffffffffffffff)
+       var x25 uint64
+       var x26 uint64
+       x26, x25 = bits.Mul64(x19, 0xffffffff00000000)
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Add64(x26, x23, uint64(0x0))
+       var x29 uint64
+       var x30 uint64
+       x29, x30 = bits.Add64(x24, x21, uint64(p224Uint1(x28)))
+       var x32 uint64
+       _, x32 = bits.Add64(x11, x19, uint64(0x0))
+       var x33 uint64
+       var x34 uint64
+       x33, x34 = bits.Add64(x13, x25, uint64(p224Uint1(x32)))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Add64(x15, x27, uint64(p224Uint1(x34)))
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x17, x29, uint64(p224Uint1(x36)))
+       var x39 uint64
+       var x40 uint64
+       x40, x39 = bits.Mul64(x1, 0xffffffff)
+       var x41 uint64
+       var x42 uint64
+       x42, x41 = bits.Mul64(x1, 0xfffffffe00000000)
+       var x43 uint64
+       var x44 uint64
+       x44, x43 = bits.Mul64(x1, 0xffffffff00000000)
+       var x45 uint64
+       var x46 uint64
+       x46, x45 = bits.Mul64(x1, 0xffffffff00000001)
+       var x47 uint64
+       var x48 uint64
+       x47, x48 = bits.Add64(x46, x43, uint64(0x0))
+       var x49 uint64
+       var x50 uint64
+       x49, x50 = bits.Add64(x44, x41, uint64(p224Uint1(x48)))
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(x42, x39, uint64(p224Uint1(x50)))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(x33, x45, uint64(0x0))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(x35, x47, uint64(p224Uint1(x54)))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(x37, x49, uint64(p224Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x59, x60 = bits.Add64(((uint64(p224Uint1(x38)) + (uint64(p224Uint1(x18)) + x6)) + (uint64(p224Uint1(x30)) + x22)), x51, uint64(p224Uint1(x58)))
+       var x61 uint64
+       _, x61 = bits.Mul64(x53, 0xffffffffffffffff)
+       var x63 uint64
+       var x64 uint64
+       x64, x63 = bits.Mul64(x61, 0xffffffff)
+       var x65 uint64
+       var x66 uint64
+       x66, x65 = bits.Mul64(x61, 0xffffffffffffffff)
+       var x67 uint64
+       var x68 uint64
+       x68, x67 = bits.Mul64(x61, 0xffffffff00000000)
+       var x69 uint64
+       var x70 uint64
+       x69, x70 = bits.Add64(x68, x65, uint64(0x0))
+       var x71 uint64
+       var x72 uint64
+       x71, x72 = bits.Add64(x66, x63, uint64(p224Uint1(x70)))
+       var x74 uint64
+       _, x74 = bits.Add64(x53, x61, uint64(0x0))
+       var x75 uint64
+       var x76 uint64
+       x75, x76 = bits.Add64(x55, x67, uint64(p224Uint1(x74)))
+       var x77 uint64
+       var x78 uint64
+       x77, x78 = bits.Add64(x57, x69, uint64(p224Uint1(x76)))
+       var x79 uint64
+       var x80 uint64
+       x79, x80 = bits.Add64(x59, x71, uint64(p224Uint1(x78)))
+       var x81 uint64
+       var x82 uint64
+       x82, x81 = bits.Mul64(x2, 0xffffffff)
+       var x83 uint64
+       var x84 uint64
+       x84, x83 = bits.Mul64(x2, 0xfffffffe00000000)
+       var x85 uint64
+       var x86 uint64
+       x86, x85 = bits.Mul64(x2, 0xffffffff00000000)
+       var x87 uint64
+       var x88 uint64
+       x88, x87 = bits.Mul64(x2, 0xffffffff00000001)
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x88, x85, uint64(0x0))
+       var x91 uint64
+       var x92 uint64
+       x91, x92 = bits.Add64(x86, x83, uint64(p224Uint1(x90)))
+       var x93 uint64
+       var x94 uint64
+       x93, x94 = bits.Add64(x84, x81, uint64(p224Uint1(x92)))
+       var x95 uint64
+       var x96 uint64
+       x95, x96 = bits.Add64(x75, x87, uint64(0x0))
+       var x97 uint64
+       var x98 uint64
+       x97, x98 = bits.Add64(x77, x89, uint64(p224Uint1(x96)))
+       var x99 uint64
+       var x100 uint64
+       x99, x100 = bits.Add64(x79, x91, uint64(p224Uint1(x98)))
+       var x101 uint64
+       var x102 uint64
+       x101, x102 = bits.Add64(((uint64(p224Uint1(x80)) + (uint64(p224Uint1(x60)) + (uint64(p224Uint1(x52)) + x40))) + (uint64(p224Uint1(x72)) + x64)), x93, uint64(p224Uint1(x100)))
+       var x103 uint64
+       _, x103 = bits.Mul64(x95, 0xffffffffffffffff)
+       var x105 uint64
+       var x106 uint64
+       x106, x105 = bits.Mul64(x103, 0xffffffff)
+       var x107 uint64
+       var x108 uint64
+       x108, x107 = bits.Mul64(x103, 0xffffffffffffffff)
+       var x109 uint64
+       var x110 uint64
+       x110, x109 = bits.Mul64(x103, 0xffffffff00000000)
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x110, x107, uint64(0x0))
+       var x113 uint64
+       var x114 uint64
+       x113, x114 = bits.Add64(x108, x105, uint64(p224Uint1(x112)))
+       var x116 uint64
+       _, x116 = bits.Add64(x95, x103, uint64(0x0))
+       var x117 uint64
+       var x118 uint64
+       x117, x118 = bits.Add64(x97, x109, uint64(p224Uint1(x116)))
+       var x119 uint64
+       var x120 uint64
+       x119, x120 = bits.Add64(x99, x111, uint64(p224Uint1(x118)))
+       var x121 uint64
+       var x122 uint64
+       x121, x122 = bits.Add64(x101, x113, uint64(p224Uint1(x120)))
+       var x123 uint64
+       var x124 uint64
+       x124, x123 = bits.Mul64(x3, 0xffffffff)
+       var x125 uint64
+       var x126 uint64
+       x126, x125 = bits.Mul64(x3, 0xfffffffe00000000)
+       var x127 uint64
+       var x128 uint64
+       x128, x127 = bits.Mul64(x3, 0xffffffff00000000)
+       var x129 uint64
+       var x130 uint64
+       x130, x129 = bits.Mul64(x3, 0xffffffff00000001)
+       var x131 uint64
+       var x132 uint64
+       x131, x132 = bits.Add64(x130, x127, uint64(0x0))
+       var x133 uint64
+       var x134 uint64
+       x133, x134 = bits.Add64(x128, x125, uint64(p224Uint1(x132)))
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x126, x123, uint64(p224Uint1(x134)))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x117, x129, uint64(0x0))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x119, x131, uint64(p224Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x121, x133, uint64(p224Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x143, x144 = bits.Add64(((uint64(p224Uint1(x122)) + (uint64(p224Uint1(x102)) + (uint64(p224Uint1(x94)) + x82))) + (uint64(p224Uint1(x114)) + x106)), x135, uint64(p224Uint1(x142)))
+       var x145 uint64
+       _, x145 = bits.Mul64(x137, 0xffffffffffffffff)
+       var x147 uint64
+       var x148 uint64
+       x148, x147 = bits.Mul64(x145, 0xffffffff)
+       var x149 uint64
+       var x150 uint64
+       x150, x149 = bits.Mul64(x145, 0xffffffffffffffff)
+       var x151 uint64
+       var x152 uint64
+       x152, x151 = bits.Mul64(x145, 0xffffffff00000000)
+       var x153 uint64
+       var x154 uint64
+       x153, x154 = bits.Add64(x152, x149, uint64(0x0))
+       var x155 uint64
+       var x156 uint64
+       x155, x156 = bits.Add64(x150, x147, uint64(p224Uint1(x154)))
+       var x158 uint64
+       _, x158 = bits.Add64(x137, x145, uint64(0x0))
+       var x159 uint64
+       var x160 uint64
+       x159, x160 = bits.Add64(x139, x151, uint64(p224Uint1(x158)))
+       var x161 uint64
+       var x162 uint64
+       x161, x162 = bits.Add64(x141, x153, uint64(p224Uint1(x160)))
+       var x163 uint64
+       var x164 uint64
+       x163, x164 = bits.Add64(x143, x155, uint64(p224Uint1(x162)))
+       x165 := ((uint64(p224Uint1(x164)) + (uint64(p224Uint1(x144)) + (uint64(p224Uint1(x136)) + x124))) + (uint64(p224Uint1(x156)) + x148))
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Sub64(x159, uint64(0x1), uint64(0x0))
+       var x168 uint64
+       var x169 uint64
+       x168, x169 = bits.Sub64(x161, 0xffffffff00000000, uint64(p224Uint1(x167)))
+       var x170 uint64
+       var x171 uint64
+       x170, x171 = bits.Sub64(x163, 0xffffffffffffffff, uint64(p224Uint1(x169)))
+       var x172 uint64
+       var x173 uint64
+       x172, x173 = bits.Sub64(x165, 0xffffffff, uint64(p224Uint1(x171)))
+       var x175 uint64
+       _, x175 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p224Uint1(x173)))
+       var x176 uint64
+       p224CmovznzU64(&x176, p224Uint1(x175), x166, x159)
+       var x177 uint64
+       p224CmovznzU64(&x177, p224Uint1(x175), x168, x161)
+       var x178 uint64
+       p224CmovznzU64(&x178, p224Uint1(x175), x170, x163)
+       var x179 uint64
+       p224CmovznzU64(&x179, p224Uint1(x175), x172, x165)
+       out1[0] = x176
+       out1[1] = x177
+       out1[2] = x178
+       out1[3] = x179
+}
+
+// p224Selectznz is a multi-limb conditional select.
+//
+// Postconditions:
+//   eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+//   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+func p224Selectznz(out1 *[4]uint64, arg1 p224Uint1, arg2 *[4]uint64, arg3 *[4]uint64) {
+       var x1 uint64
+       p224CmovznzU64(&x1, arg1, arg2[0], arg3[0])
+       var x2 uint64
+       p224CmovznzU64(&x2, arg1, arg2[1], arg3[1])
+       var x3 uint64
+       p224CmovznzU64(&x3, arg1, arg2[2], arg3[2])
+       var x4 uint64
+       p224CmovznzU64(&x4, arg1, arg2[3], arg3[3])
+       out1[0] = x1
+       out1[1] = x2
+       out1[2] = x3
+       out1[3] = x4
+}
+
+// p224ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+// Postconditions:
+//   out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..27]
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+func p224ToBytes(out1 *[28]uint8, arg1 *[4]uint64) {
+       x1 := arg1[3]
+       x2 := arg1[2]
+       x3 := arg1[1]
+       x4 := arg1[0]
+       x5 := (uint8(x4) & 0xff)
+       x6 := (x4 >> 8)
+       x7 := (uint8(x6) & 0xff)
+       x8 := (x6 >> 8)
+       x9 := (uint8(x8) & 0xff)
+       x10 := (x8 >> 8)
+       x11 := (uint8(x10) & 0xff)
+       x12 := (x10 >> 8)
+       x13 := (uint8(x12) & 0xff)
+       x14 := (x12 >> 8)
+       x15 := (uint8(x14) & 0xff)
+       x16 := (x14 >> 8)
+       x17 := (uint8(x16) & 0xff)
+       x18 := uint8((x16 >> 8))
+       x19 := (uint8(x3) & 0xff)
+       x20 := (x3 >> 8)
+       x21 := (uint8(x20) & 0xff)
+       x22 := (x20 >> 8)
+       x23 := (uint8(x22) & 0xff)
+       x24 := (x22 >> 8)
+       x25 := (uint8(x24) & 0xff)
+       x26 := (x24 >> 8)
+       x27 := (uint8(x26) & 0xff)
+       x28 := (x26 >> 8)
+       x29 := (uint8(x28) & 0xff)
+       x30 := (x28 >> 8)
+       x31 := (uint8(x30) & 0xff)
+       x32 := uint8((x30 >> 8))
+       x33 := (uint8(x2) & 0xff)
+       x34 := (x2 >> 8)
+       x35 := (uint8(x34) & 0xff)
+       x36 := (x34 >> 8)
+       x37 := (uint8(x36) & 0xff)
+       x38 := (x36 >> 8)
+       x39 := (uint8(x38) & 0xff)
+       x40 := (x38 >> 8)
+       x41 := (uint8(x40) & 0xff)
+       x42 := (x40 >> 8)
+       x43 := (uint8(x42) & 0xff)
+       x44 := (x42 >> 8)
+       x45 := (uint8(x44) & 0xff)
+       x46 := uint8((x44 >> 8))
+       x47 := (uint8(x1) & 0xff)
+       x48 := (x1 >> 8)
+       x49 := (uint8(x48) & 0xff)
+       x50 := (x48 >> 8)
+       x51 := (uint8(x50) & 0xff)
+       x52 := uint8((x50 >> 8))
+       out1[0] = x5
+       out1[1] = x7
+       out1[2] = x9
+       out1[3] = x11
+       out1[4] = x13
+       out1[5] = x15
+       out1[6] = x17
+       out1[7] = x18
+       out1[8] = x19
+       out1[9] = x21
+       out1[10] = x23
+       out1[11] = x25
+       out1[12] = x27
+       out1[13] = x29
+       out1[14] = x31
+       out1[15] = x32
+       out1[16] = x33
+       out1[17] = x35
+       out1[18] = x37
+       out1[19] = x39
+       out1[20] = x41
+       out1[21] = x43
+       out1[22] = x45
+       out1[23] = x46
+       out1[24] = x47
+       out1[25] = x49
+       out1[26] = x51
+       out1[27] = x52
+}
+
+// p224FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
+//
+// Preconditions:
+//   0 ≤ bytes_eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = bytes_eval arg1 mod m
+//   0 ≤ eval out1 < m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffff]]
+func p224FromBytes(out1 *[4]uint64, arg1 *[28]uint8) {
+       x1 := (uint64(arg1[27]) << 24)
+       x2 := (uint64(arg1[26]) << 16)
+       x3 := (uint64(arg1[25]) << 8)
+       x4 := arg1[24]
+       x5 := (uint64(arg1[23]) << 56)
+       x6 := (uint64(arg1[22]) << 48)
+       x7 := (uint64(arg1[21]) << 40)
+       x8 := (uint64(arg1[20]) << 32)
+       x9 := (uint64(arg1[19]) << 24)
+       x10 := (uint64(arg1[18]) << 16)
+       x11 := (uint64(arg1[17]) << 8)
+       x12 := arg1[16]
+       x13 := (uint64(arg1[15]) << 56)
+       x14 := (uint64(arg1[14]) << 48)
+       x15 := (uint64(arg1[13]) << 40)
+       x16 := (uint64(arg1[12]) << 32)
+       x17 := (uint64(arg1[11]) << 24)
+       x18 := (uint64(arg1[10]) << 16)
+       x19 := (uint64(arg1[9]) << 8)
+       x20 := arg1[8]
+       x21 := (uint64(arg1[7]) << 56)
+       x22 := (uint64(arg1[6]) << 48)
+       x23 := (uint64(arg1[5]) << 40)
+       x24 := (uint64(arg1[4]) << 32)
+       x25 := (uint64(arg1[3]) << 24)
+       x26 := (uint64(arg1[2]) << 16)
+       x27 := (uint64(arg1[1]) << 8)
+       x28 := arg1[0]
+       x29 := (x27 + uint64(x28))
+       x30 := (x26 + x29)
+       x31 := (x25 + x30)
+       x32 := (x24 + x31)
+       x33 := (x23 + x32)
+       x34 := (x22 + x33)
+       x35 := (x21 + x34)
+       x36 := (x19 + uint64(x20))
+       x37 := (x18 + x36)
+       x38 := (x17 + x37)
+       x39 := (x16 + x38)
+       x40 := (x15 + x39)
+       x41 := (x14 + x40)
+       x42 := (x13 + x41)
+       x43 := (x11 + uint64(x12))
+       x44 := (x10 + x43)
+       x45 := (x9 + x44)
+       x46 := (x8 + x45)
+       x47 := (x7 + x46)
+       x48 := (x6 + x47)
+       x49 := (x5 + x48)
+       x50 := (x3 + uint64(x4))
+       x51 := (x2 + x50)
+       x52 := (x1 + x51)
+       out1[0] = x35
+       out1[1] = x42
+       out1[2] = x49
+       out1[3] = x52
+}
diff --git a/src/crypto/elliptic/internal/fiat/p224_invert.go b/src/crypto/elliptic/internal/fiat/p224_invert.go
new file mode 100644 (file)
index 0000000..4163ed0
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright 2021 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.
+
+// Code generated by addchain. DO NOT EDIT.
+
+package fiat
+
+// Invert sets e = 1/x, and returns e.
+//
+// If x == 0, Invert returns e = 0.
+func (e *P224Element) Invert(x *P224Element) *P224Element {
+       // Inversion is implemented as exponentiation with exponent p − 2.
+       // The sequence of 11 multiplications and 223 squarings is derived from the
+       // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0.
+       //
+       //      _10     = 2*1
+       //      _11     = 1 + _10
+       //      _110    = 2*_11
+       //      _111    = 1 + _110
+       //      _111000 = _111 << 3
+       //      _111111 = _111 + _111000
+       //      x12     = _111111 << 6 + _111111
+       //      x14     = x12 << 2 + _11
+       //      x17     = x14 << 3 + _111
+       //      x31     = x17 << 14 + x14
+       //      x48     = x31 << 17 + x17
+       //      x96     = x48 << 48 + x48
+       //      x127    = x96 << 31 + x31
+       //      return    x127 << 97 + x96
+       //
+
+       var z = new(P224Element).Set(e)
+       var t0 = new(P224Element)
+       var t1 = new(P224Element)
+       var t2 = new(P224Element)
+
+       z.Square(x)
+       t0.Mul(x, z)
+       z.Square(t0)
+       z.Mul(x, z)
+       t1.Square(z)
+       for s := 1; s < 3; s++ {
+               t1.Square(t1)
+       }
+       t1.Mul(z, t1)
+       t2.Square(t1)
+       for s := 1; s < 6; s++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+       for s := 0; s < 2; s++ {
+               t1.Square(t1)
+       }
+       t0.Mul(t0, t1)
+       t1.Square(t0)
+       for s := 1; s < 3; s++ {
+               t1.Square(t1)
+       }
+       z.Mul(z, t1)
+       t1.Square(z)
+       for s := 1; s < 14; s++ {
+               t1.Square(t1)
+       }
+       t0.Mul(t0, t1)
+       t1.Square(t0)
+       for s := 1; s < 17; s++ {
+               t1.Square(t1)
+       }
+       z.Mul(z, t1)
+       t1.Square(z)
+       for s := 1; s < 48; s++ {
+               t1.Square(t1)
+       }
+       z.Mul(z, t1)
+       t1.Square(z)
+       for s := 1; s < 31; s++ {
+               t1.Square(t1)
+       }
+       t0.Mul(t0, t1)
+       for s := 0; s < 97; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+
+       return e.Set(z)
+}
diff --git a/src/crypto/elliptic/internal/fiat/p384.go b/src/crypto/elliptic/internal/fiat/p384.go
new file mode 100644 (file)
index 0000000..5474d77
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright 2021 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.
+
+// Code generated by generate.go. DO NOT EDIT.
+
+package fiat
+
+import (
+       "crypto/subtle"
+       "errors"
+)
+
+// P384Element is an integer modulo 2^384 - 2^128 - 2^96 + 2^32 - 1.
+//
+// The zero value is a valid zero element.
+type P384Element struct {
+       // Values are represented internally always in the Montgomery domain, and
+       // converted in Bytes and SetBytes.
+       x p384MontgomeryDomainFieldElement
+}
+
+const p384ElementLen = 48
+
+type p384UntypedFieldElement = [6]uint64
+
+// One sets e = 1, and returns e.
+func (e *P384Element) One() *P384Element {
+       p384SetOne(&e.x)
+       return e
+}
+
+// Equal returns 1 if e == t, and zero otherwise.
+func (e *P384Element) Equal(t *P384Element) int {
+       eBytes := e.Bytes()
+       tBytes := t.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, tBytes)
+}
+
+var p384ZeroEncoding = new(P384Element).Bytes()
+
+// IsZero returns 1 if e == 0, and zero otherwise.
+func (e *P384Element) IsZero() int {
+       eBytes := e.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, p384ZeroEncoding)
+}
+
+// Set sets e = t, and returns e.
+func (e *P384Element) Set(t *P384Element) *P384Element {
+       e.x = t.x
+       return e
+}
+
+// Bytes returns the 48-byte big-endian encoding of e.
+func (e *P384Element) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [p384ElementLen]byte
+       return e.bytes(&out)
+}
+
+func (e *P384Element) bytes(out *[p384ElementLen]byte) []byte {
+       var tmp p384NonMontgomeryDomainFieldElement
+       p384FromMontgomery(&tmp, &e.x)
+       p384ToBytes(out, (*p384UntypedFieldElement)(&tmp))
+       p384InvertEndianness(out[:])
+       return out[:]
+}
+
+// p384MinusOneEncoding is the encoding of -1 mod p, so p - 1, the
+// highest canonical encoding. It is used by SetBytes to check for non-canonical
+// encodings such as p + k, 2p + k, etc.
+var p384MinusOneEncoding = new(P384Element).Sub(
+       new(P384Element), new(P384Element).One()).Bytes()
+
+// SetBytes sets e = v, where v is a big-endian 48-byte encoding, and returns e.
+// If v is not 48 bytes or it encodes a value higher than 2^384 - 2^128 - 2^96 + 2^32 - 1,
+// SetBytes returns nil and an error, and e is unchanged.
+func (e *P384Element) SetBytes(v []byte) (*P384Element, error) {
+       if len(v) != p384ElementLen {
+               return nil, errors.New("invalid P384Element encoding")
+       }
+       for i := range v {
+               if v[i] < p384MinusOneEncoding[i] {
+                       break
+               }
+               if v[i] > p384MinusOneEncoding[i] {
+                       return nil, errors.New("invalid P384Element encoding")
+               }
+       }
+       var in [p384ElementLen]byte
+       copy(in[:], v)
+       p384InvertEndianness(in[:])
+       var tmp p384NonMontgomeryDomainFieldElement
+       p384FromBytes((*p384UntypedFieldElement)(&tmp), &in)
+       p384ToMontgomery(&e.x, &tmp)
+       return e, nil
+}
+
+// Add sets e = t1 + t2, and returns e.
+func (e *P384Element) Add(t1, t2 *P384Element) *P384Element {
+       p384Add(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Sub sets e = t1 - t2, and returns e.
+func (e *P384Element) Sub(t1, t2 *P384Element) *P384Element {
+       p384Sub(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Mul sets e = t1 * t2, and returns e.
+func (e *P384Element) Mul(t1, t2 *P384Element) *P384Element {
+       p384Mul(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Square sets e = t * t, and returns e.
+func (e *P384Element) Square(t *P384Element) *P384Element {
+       p384Square(&e.x, &t.x)
+       return e
+}
+
+// Select sets v to a if cond == 1, and to b if cond == 0.
+func (v *P384Element) Select(a, b *P384Element, cond int) *P384Element {
+       p384Selectznz((*p384UntypedFieldElement)(&v.x), p384Uint1(cond),
+               (*p384UntypedFieldElement)(&b.x), (*p384UntypedFieldElement)(&a.x))
+       return v
+}
+
+func p384InvertEndianness(v []byte) {
+       for i := 0; i < len(v)/2; i++ {
+               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
+       }
+}
diff --git a/src/crypto/elliptic/internal/fiat/p384_fiat64.go b/src/crypto/elliptic/internal/fiat/p384_fiat64.go
new file mode 100644 (file)
index 0000000..493bed4
--- /dev/null
@@ -0,0 +1,3004 @@
+// Code generated by Fiat Cryptography. DO NOT EDIT.
+//
+// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p384 64 '2^384 - 2^128 - 2^96 + 2^32 - 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes
+//
+// curve description: p384
+//
+// machine_wordsize = 64 (from "64")
+//
+// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes
+//
+// m = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff (from "2^384 - 2^128 - 2^96 + 2^32 - 1")
+//
+//
+//
+// NOTE: In addition to the bounds specified above each function, all
+//
+//   functions synthesized for this Montgomery arithmetic require the
+//
+//   input to be strictly less than the prime modulus (m), and also
+//
+//   require the input to be in the unique saturated representation.
+//
+//   All functions also ensure that these two properties are true of
+//
+//   return values.
+//
+//
+//
+// Computed values:
+//
+//   eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140)
+//
+//   bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178)
+//
+//   twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) in
+//
+//                            if x1 & (2^384-1) < 2^383 then x1 & (2^384-1) else (x1 & (2^384-1)) - 2^384
+
+package fiat
+
+import "math/bits"
+
+type p384Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+type p384Int1 int64   // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+
+// The type p384MontgomeryDomainFieldElement is a field element in the Montgomery domain.
+//
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p384MontgomeryDomainFieldElement [6]uint64
+
+// The type p384NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain.
+//
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p384NonMontgomeryDomainFieldElement [6]uint64
+
+// p384CmovznzU64 is a single-word conditional move.
+//
+// Postconditions:
+//   out1 = (if arg1 = 0 then arg2 else arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [0x0 ~> 0xffffffffffffffff]
+//   arg3: [0x0 ~> 0xffffffffffffffff]
+// Output Bounds:
+//   out1: [0x0 ~> 0xffffffffffffffff]
+func p384CmovznzU64(out1 *uint64, arg1 p384Uint1, arg2 uint64, arg3 uint64) {
+       x1 := (uint64(arg1) * 0xffffffffffffffff)
+       x2 := ((x1 & arg3) | ((^x1) & arg2))
+       *out1 = x2
+}
+
+// p384Mul multiplies two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+//   0 ≤ eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
+//   0 ≤ eval out1 < m
+//
+func p384Mul(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[0]
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x6, arg2[5])
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x6, arg2[4])
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x6, arg2[3])
+       var x13 uint64
+       var x14 uint64
+       x14, x13 = bits.Mul64(x6, arg2[2])
+       var x15 uint64
+       var x16 uint64
+       x16, x15 = bits.Mul64(x6, arg2[1])
+       var x17 uint64
+       var x18 uint64
+       x18, x17 = bits.Mul64(x6, arg2[0])
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Add64(x18, x15, uint64(0x0))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Add64(x16, x13, uint64(p384Uint1(x20)))
+       var x23 uint64
+       var x24 uint64
+       x23, x24 = bits.Add64(x14, x11, uint64(p384Uint1(x22)))
+       var x25 uint64
+       var x26 uint64
+       x25, x26 = bits.Add64(x12, x9, uint64(p384Uint1(x24)))
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Add64(x10, x7, uint64(p384Uint1(x26)))
+       x29 := (uint64(p384Uint1(x28)) + x8)
+       var x30 uint64
+       _, x30 = bits.Mul64(x17, 0x100000001)
+       var x32 uint64
+       var x33 uint64
+       x33, x32 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x34 uint64
+       var x35 uint64
+       x35, x34 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x36 uint64
+       var x37 uint64
+       x37, x36 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x38 uint64
+       var x39 uint64
+       x39, x38 = bits.Mul64(x30, 0xfffffffffffffffe)
+       var x40 uint64
+       var x41 uint64
+       x41, x40 = bits.Mul64(x30, 0xffffffff00000000)
+       var x42 uint64
+       var x43 uint64
+       x43, x42 = bits.Mul64(x30, 0xffffffff)
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(x43, x40, uint64(0x0))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64(x41, x38, uint64(p384Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(x39, x36, uint64(p384Uint1(x47)))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(x37, x34, uint64(p384Uint1(x49)))
+       var x52 uint64
+       var x53 uint64
+       x52, x53 = bits.Add64(x35, x32, uint64(p384Uint1(x51)))
+       x54 := (uint64(p384Uint1(x53)) + x33)
+       var x56 uint64
+       _, x56 = bits.Add64(x17, x42, uint64(0x0))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(x19, x44, uint64(p384Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x59, x60 = bits.Add64(x21, x46, uint64(p384Uint1(x58)))
+       var x61 uint64
+       var x62 uint64
+       x61, x62 = bits.Add64(x23, x48, uint64(p384Uint1(x60)))
+       var x63 uint64
+       var x64 uint64
+       x63, x64 = bits.Add64(x25, x50, uint64(p384Uint1(x62)))
+       var x65 uint64
+       var x66 uint64
+       x65, x66 = bits.Add64(x27, x52, uint64(p384Uint1(x64)))
+       var x67 uint64
+       var x68 uint64
+       x67, x68 = bits.Add64(x29, x54, uint64(p384Uint1(x66)))
+       var x69 uint64
+       var x70 uint64
+       x70, x69 = bits.Mul64(x1, arg2[5])
+       var x71 uint64
+       var x72 uint64
+       x72, x71 = bits.Mul64(x1, arg2[4])
+       var x73 uint64
+       var x74 uint64
+       x74, x73 = bits.Mul64(x1, arg2[3])
+       var x75 uint64
+       var x76 uint64
+       x76, x75 = bits.Mul64(x1, arg2[2])
+       var x77 uint64
+       var x78 uint64
+       x78, x77 = bits.Mul64(x1, arg2[1])
+       var x79 uint64
+       var x80 uint64
+       x80, x79 = bits.Mul64(x1, arg2[0])
+       var x81 uint64
+       var x82 uint64
+       x81, x82 = bits.Add64(x80, x77, uint64(0x0))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x78, x75, uint64(p384Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x76, x73, uint64(p384Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x74, x71, uint64(p384Uint1(x86)))
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x72, x69, uint64(p384Uint1(x88)))
+       x91 := (uint64(p384Uint1(x90)) + x70)
+       var x92 uint64
+       var x93 uint64
+       x92, x93 = bits.Add64(x57, x79, uint64(0x0))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x59, x81, uint64(p384Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x61, x83, uint64(p384Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64(x63, x85, uint64(p384Uint1(x97)))
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x65, x87, uint64(p384Uint1(x99)))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x67, x89, uint64(p384Uint1(x101)))
+       var x104 uint64
+       var x105 uint64
+       x104, x105 = bits.Add64(uint64(p384Uint1(x68)), x91, uint64(p384Uint1(x103)))
+       var x106 uint64
+       _, x106 = bits.Mul64(x92, 0x100000001)
+       var x108 uint64
+       var x109 uint64
+       x109, x108 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x110 uint64
+       var x111 uint64
+       x111, x110 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x112 uint64
+       var x113 uint64
+       x113, x112 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x114 uint64
+       var x115 uint64
+       x115, x114 = bits.Mul64(x106, 0xfffffffffffffffe)
+       var x116 uint64
+       var x117 uint64
+       x117, x116 = bits.Mul64(x106, 0xffffffff00000000)
+       var x118 uint64
+       var x119 uint64
+       x119, x118 = bits.Mul64(x106, 0xffffffff)
+       var x120 uint64
+       var x121 uint64
+       x120, x121 = bits.Add64(x119, x116, uint64(0x0))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x117, x114, uint64(p384Uint1(x121)))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x115, x112, uint64(p384Uint1(x123)))
+       var x126 uint64
+       var x127 uint64
+       x126, x127 = bits.Add64(x113, x110, uint64(p384Uint1(x125)))
+       var x128 uint64
+       var x129 uint64
+       x128, x129 = bits.Add64(x111, x108, uint64(p384Uint1(x127)))
+       x130 := (uint64(p384Uint1(x129)) + x109)
+       var x132 uint64
+       _, x132 = bits.Add64(x92, x118, uint64(0x0))
+       var x133 uint64
+       var x134 uint64
+       x133, x134 = bits.Add64(x94, x120, uint64(p384Uint1(x132)))
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x96, x122, uint64(p384Uint1(x134)))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x98, x124, uint64(p384Uint1(x136)))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x100, x126, uint64(p384Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x102, x128, uint64(p384Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x143, x144 = bits.Add64(x104, x130, uint64(p384Uint1(x142)))
+       x145 := (uint64(p384Uint1(x144)) + uint64(p384Uint1(x105)))
+       var x146 uint64
+       var x147 uint64
+       x147, x146 = bits.Mul64(x2, arg2[5])
+       var x148 uint64
+       var x149 uint64
+       x149, x148 = bits.Mul64(x2, arg2[4])
+       var x150 uint64
+       var x151 uint64
+       x151, x150 = bits.Mul64(x2, arg2[3])
+       var x152 uint64
+       var x153 uint64
+       x153, x152 = bits.Mul64(x2, arg2[2])
+       var x154 uint64
+       var x155 uint64
+       x155, x154 = bits.Mul64(x2, arg2[1])
+       var x156 uint64
+       var x157 uint64
+       x157, x156 = bits.Mul64(x2, arg2[0])
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x157, x154, uint64(0x0))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x155, x152, uint64(p384Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x153, x150, uint64(p384Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x151, x148, uint64(p384Uint1(x163)))
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Add64(x149, x146, uint64(p384Uint1(x165)))
+       x168 := (uint64(p384Uint1(x167)) + x147)
+       var x169 uint64
+       var x170 uint64
+       x169, x170 = bits.Add64(x133, x156, uint64(0x0))
+       var x171 uint64
+       var x172 uint64
+       x171, x172 = bits.Add64(x135, x158, uint64(p384Uint1(x170)))
+       var x173 uint64
+       var x174 uint64
+       x173, x174 = bits.Add64(x137, x160, uint64(p384Uint1(x172)))
+       var x175 uint64
+       var x176 uint64
+       x175, x176 = bits.Add64(x139, x162, uint64(p384Uint1(x174)))
+       var x177 uint64
+       var x178 uint64
+       x177, x178 = bits.Add64(x141, x164, uint64(p384Uint1(x176)))
+       var x179 uint64
+       var x180 uint64
+       x179, x180 = bits.Add64(x143, x166, uint64(p384Uint1(x178)))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x145, x168, uint64(p384Uint1(x180)))
+       var x183 uint64
+       _, x183 = bits.Mul64(x169, 0x100000001)
+       var x185 uint64
+       var x186 uint64
+       x186, x185 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x187 uint64
+       var x188 uint64
+       x188, x187 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x189 uint64
+       var x190 uint64
+       x190, x189 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x191 uint64
+       var x192 uint64
+       x192, x191 = bits.Mul64(x183, 0xfffffffffffffffe)
+       var x193 uint64
+       var x194 uint64
+       x194, x193 = bits.Mul64(x183, 0xffffffff00000000)
+       var x195 uint64
+       var x196 uint64
+       x196, x195 = bits.Mul64(x183, 0xffffffff)
+       var x197 uint64
+       var x198 uint64
+       x197, x198 = bits.Add64(x196, x193, uint64(0x0))
+       var x199 uint64
+       var x200 uint64
+       x199, x200 = bits.Add64(x194, x191, uint64(p384Uint1(x198)))
+       var x201 uint64
+       var x202 uint64
+       x201, x202 = bits.Add64(x192, x189, uint64(p384Uint1(x200)))
+       var x203 uint64
+       var x204 uint64
+       x203, x204 = bits.Add64(x190, x187, uint64(p384Uint1(x202)))
+       var x205 uint64
+       var x206 uint64
+       x205, x206 = bits.Add64(x188, x185, uint64(p384Uint1(x204)))
+       x207 := (uint64(p384Uint1(x206)) + x186)
+       var x209 uint64
+       _, x209 = bits.Add64(x169, x195, uint64(0x0))
+       var x210 uint64
+       var x211 uint64
+       x210, x211 = bits.Add64(x171, x197, uint64(p384Uint1(x209)))
+       var x212 uint64
+       var x213 uint64
+       x212, x213 = bits.Add64(x173, x199, uint64(p384Uint1(x211)))
+       var x214 uint64
+       var x215 uint64
+       x214, x215 = bits.Add64(x175, x201, uint64(p384Uint1(x213)))
+       var x216 uint64
+       var x217 uint64
+       x216, x217 = bits.Add64(x177, x203, uint64(p384Uint1(x215)))
+       var x218 uint64
+       var x219 uint64
+       x218, x219 = bits.Add64(x179, x205, uint64(p384Uint1(x217)))
+       var x220 uint64
+       var x221 uint64
+       x220, x221 = bits.Add64(x181, x207, uint64(p384Uint1(x219)))
+       x222 := (uint64(p384Uint1(x221)) + uint64(p384Uint1(x182)))
+       var x223 uint64
+       var x224 uint64
+       x224, x223 = bits.Mul64(x3, arg2[5])
+       var x225 uint64
+       var x226 uint64
+       x226, x225 = bits.Mul64(x3, arg2[4])
+       var x227 uint64
+       var x228 uint64
+       x228, x227 = bits.Mul64(x3, arg2[3])
+       var x229 uint64
+       var x230 uint64
+       x230, x229 = bits.Mul64(x3, arg2[2])
+       var x231 uint64
+       var x232 uint64
+       x232, x231 = bits.Mul64(x3, arg2[1])
+       var x233 uint64
+       var x234 uint64
+       x234, x233 = bits.Mul64(x3, arg2[0])
+       var x235 uint64
+       var x236 uint64
+       x235, x236 = bits.Add64(x234, x231, uint64(0x0))
+       var x237 uint64
+       var x238 uint64
+       x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236)))
+       var x239 uint64
+       var x240 uint64
+       x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238)))
+       var x241 uint64
+       var x242 uint64
+       x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240)))
+       var x243 uint64
+       var x244 uint64
+       x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242)))
+       x245 := (uint64(p384Uint1(x244)) + x224)
+       var x246 uint64
+       var x247 uint64
+       x246, x247 = bits.Add64(x210, x233, uint64(0x0))
+       var x248 uint64
+       var x249 uint64
+       x248, x249 = bits.Add64(x212, x235, uint64(p384Uint1(x247)))
+       var x250 uint64
+       var x251 uint64
+       x250, x251 = bits.Add64(x214, x237, uint64(p384Uint1(x249)))
+       var x252 uint64
+       var x253 uint64
+       x252, x253 = bits.Add64(x216, x239, uint64(p384Uint1(x251)))
+       var x254 uint64
+       var x255 uint64
+       x254, x255 = bits.Add64(x218, x241, uint64(p384Uint1(x253)))
+       var x256 uint64
+       var x257 uint64
+       x256, x257 = bits.Add64(x220, x243, uint64(p384Uint1(x255)))
+       var x258 uint64
+       var x259 uint64
+       x258, x259 = bits.Add64(x222, x245, uint64(p384Uint1(x257)))
+       var x260 uint64
+       _, x260 = bits.Mul64(x246, 0x100000001)
+       var x262 uint64
+       var x263 uint64
+       x263, x262 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x264 uint64
+       var x265 uint64
+       x265, x264 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x266 uint64
+       var x267 uint64
+       x267, x266 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x268 uint64
+       var x269 uint64
+       x269, x268 = bits.Mul64(x260, 0xfffffffffffffffe)
+       var x270 uint64
+       var x271 uint64
+       x271, x270 = bits.Mul64(x260, 0xffffffff00000000)
+       var x272 uint64
+       var x273 uint64
+       x273, x272 = bits.Mul64(x260, 0xffffffff)
+       var x274 uint64
+       var x275 uint64
+       x274, x275 = bits.Add64(x273, x270, uint64(0x0))
+       var x276 uint64
+       var x277 uint64
+       x276, x277 = bits.Add64(x271, x268, uint64(p384Uint1(x275)))
+       var x278 uint64
+       var x279 uint64
+       x278, x279 = bits.Add64(x269, x266, uint64(p384Uint1(x277)))
+       var x280 uint64
+       var x281 uint64
+       x280, x281 = bits.Add64(x267, x264, uint64(p384Uint1(x279)))
+       var x282 uint64
+       var x283 uint64
+       x282, x283 = bits.Add64(x265, x262, uint64(p384Uint1(x281)))
+       x284 := (uint64(p384Uint1(x283)) + x263)
+       var x286 uint64
+       _, x286 = bits.Add64(x246, x272, uint64(0x0))
+       var x287 uint64
+       var x288 uint64
+       x287, x288 = bits.Add64(x248, x274, uint64(p384Uint1(x286)))
+       var x289 uint64
+       var x290 uint64
+       x289, x290 = bits.Add64(x250, x276, uint64(p384Uint1(x288)))
+       var x291 uint64
+       var x292 uint64
+       x291, x292 = bits.Add64(x252, x278, uint64(p384Uint1(x290)))
+       var x293 uint64
+       var x294 uint64
+       x293, x294 = bits.Add64(x254, x280, uint64(p384Uint1(x292)))
+       var x295 uint64
+       var x296 uint64
+       x295, x296 = bits.Add64(x256, x282, uint64(p384Uint1(x294)))
+       var x297 uint64
+       var x298 uint64
+       x297, x298 = bits.Add64(x258, x284, uint64(p384Uint1(x296)))
+       x299 := (uint64(p384Uint1(x298)) + uint64(p384Uint1(x259)))
+       var x300 uint64
+       var x301 uint64
+       x301, x300 = bits.Mul64(x4, arg2[5])
+       var x302 uint64
+       var x303 uint64
+       x303, x302 = bits.Mul64(x4, arg2[4])
+       var x304 uint64
+       var x305 uint64
+       x305, x304 = bits.Mul64(x4, arg2[3])
+       var x306 uint64
+       var x307 uint64
+       x307, x306 = bits.Mul64(x4, arg2[2])
+       var x308 uint64
+       var x309 uint64
+       x309, x308 = bits.Mul64(x4, arg2[1])
+       var x310 uint64
+       var x311 uint64
+       x311, x310 = bits.Mul64(x4, arg2[0])
+       var x312 uint64
+       var x313 uint64
+       x312, x313 = bits.Add64(x311, x308, uint64(0x0))
+       var x314 uint64
+       var x315 uint64
+       x314, x315 = bits.Add64(x309, x306, uint64(p384Uint1(x313)))
+       var x316 uint64
+       var x317 uint64
+       x316, x317 = bits.Add64(x307, x304, uint64(p384Uint1(x315)))
+       var x318 uint64
+       var x319 uint64
+       x318, x319 = bits.Add64(x305, x302, uint64(p384Uint1(x317)))
+       var x320 uint64
+       var x321 uint64
+       x320, x321 = bits.Add64(x303, x300, uint64(p384Uint1(x319)))
+       x322 := (uint64(p384Uint1(x321)) + x301)
+       var x323 uint64
+       var x324 uint64
+       x323, x324 = bits.Add64(x287, x310, uint64(0x0))
+       var x325 uint64
+       var x326 uint64
+       x325, x326 = bits.Add64(x289, x312, uint64(p384Uint1(x324)))
+       var x327 uint64
+       var x328 uint64
+       x327, x328 = bits.Add64(x291, x314, uint64(p384Uint1(x326)))
+       var x329 uint64
+       var x330 uint64
+       x329, x330 = bits.Add64(x293, x316, uint64(p384Uint1(x328)))
+       var x331 uint64
+       var x332 uint64
+       x331, x332 = bits.Add64(x295, x318, uint64(p384Uint1(x330)))
+       var x333 uint64
+       var x334 uint64
+       x333, x334 = bits.Add64(x297, x320, uint64(p384Uint1(x332)))
+       var x335 uint64
+       var x336 uint64
+       x335, x336 = bits.Add64(x299, x322, uint64(p384Uint1(x334)))
+       var x337 uint64
+       _, x337 = bits.Mul64(x323, 0x100000001)
+       var x339 uint64
+       var x340 uint64
+       x340, x339 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x341 uint64
+       var x342 uint64
+       x342, x341 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x343 uint64
+       var x344 uint64
+       x344, x343 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x345 uint64
+       var x346 uint64
+       x346, x345 = bits.Mul64(x337, 0xfffffffffffffffe)
+       var x347 uint64
+       var x348 uint64
+       x348, x347 = bits.Mul64(x337, 0xffffffff00000000)
+       var x349 uint64
+       var x350 uint64
+       x350, x349 = bits.Mul64(x337, 0xffffffff)
+       var x351 uint64
+       var x352 uint64
+       x351, x352 = bits.Add64(x350, x347, uint64(0x0))
+       var x353 uint64
+       var x354 uint64
+       x353, x354 = bits.Add64(x348, x345, uint64(p384Uint1(x352)))
+       var x355 uint64
+       var x356 uint64
+       x355, x356 = bits.Add64(x346, x343, uint64(p384Uint1(x354)))
+       var x357 uint64
+       var x358 uint64
+       x357, x358 = bits.Add64(x344, x341, uint64(p384Uint1(x356)))
+       var x359 uint64
+       var x360 uint64
+       x359, x360 = bits.Add64(x342, x339, uint64(p384Uint1(x358)))
+       x361 := (uint64(p384Uint1(x360)) + x340)
+       var x363 uint64
+       _, x363 = bits.Add64(x323, x349, uint64(0x0))
+       var x364 uint64
+       var x365 uint64
+       x364, x365 = bits.Add64(x325, x351, uint64(p384Uint1(x363)))
+       var x366 uint64
+       var x367 uint64
+       x366, x367 = bits.Add64(x327, x353, uint64(p384Uint1(x365)))
+       var x368 uint64
+       var x369 uint64
+       x368, x369 = bits.Add64(x329, x355, uint64(p384Uint1(x367)))
+       var x370 uint64
+       var x371 uint64
+       x370, x371 = bits.Add64(x331, x357, uint64(p384Uint1(x369)))
+       var x372 uint64
+       var x373 uint64
+       x372, x373 = bits.Add64(x333, x359, uint64(p384Uint1(x371)))
+       var x374 uint64
+       var x375 uint64
+       x374, x375 = bits.Add64(x335, x361, uint64(p384Uint1(x373)))
+       x376 := (uint64(p384Uint1(x375)) + uint64(p384Uint1(x336)))
+       var x377 uint64
+       var x378 uint64
+       x378, x377 = bits.Mul64(x5, arg2[5])
+       var x379 uint64
+       var x380 uint64
+       x380, x379 = bits.Mul64(x5, arg2[4])
+       var x381 uint64
+       var x382 uint64
+       x382, x381 = bits.Mul64(x5, arg2[3])
+       var x383 uint64
+       var x384 uint64
+       x384, x383 = bits.Mul64(x5, arg2[2])
+       var x385 uint64
+       var x386 uint64
+       x386, x385 = bits.Mul64(x5, arg2[1])
+       var x387 uint64
+       var x388 uint64
+       x388, x387 = bits.Mul64(x5, arg2[0])
+       var x389 uint64
+       var x390 uint64
+       x389, x390 = bits.Add64(x388, x385, uint64(0x0))
+       var x391 uint64
+       var x392 uint64
+       x391, x392 = bits.Add64(x386, x383, uint64(p384Uint1(x390)))
+       var x393 uint64
+       var x394 uint64
+       x393, x394 = bits.Add64(x384, x381, uint64(p384Uint1(x392)))
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Add64(x382, x379, uint64(p384Uint1(x394)))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Add64(x380, x377, uint64(p384Uint1(x396)))
+       x399 := (uint64(p384Uint1(x398)) + x378)
+       var x400 uint64
+       var x401 uint64
+       x400, x401 = bits.Add64(x364, x387, uint64(0x0))
+       var x402 uint64
+       var x403 uint64
+       x402, x403 = bits.Add64(x366, x389, uint64(p384Uint1(x401)))
+       var x404 uint64
+       var x405 uint64
+       x404, x405 = bits.Add64(x368, x391, uint64(p384Uint1(x403)))
+       var x406 uint64
+       var x407 uint64
+       x406, x407 = bits.Add64(x370, x393, uint64(p384Uint1(x405)))
+       var x408 uint64
+       var x409 uint64
+       x408, x409 = bits.Add64(x372, x395, uint64(p384Uint1(x407)))
+       var x410 uint64
+       var x411 uint64
+       x410, x411 = bits.Add64(x374, x397, uint64(p384Uint1(x409)))
+       var x412 uint64
+       var x413 uint64
+       x412, x413 = bits.Add64(x376, x399, uint64(p384Uint1(x411)))
+       var x414 uint64
+       _, x414 = bits.Mul64(x400, 0x100000001)
+       var x416 uint64
+       var x417 uint64
+       x417, x416 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x418 uint64
+       var x419 uint64
+       x419, x418 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x420 uint64
+       var x421 uint64
+       x421, x420 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x422 uint64
+       var x423 uint64
+       x423, x422 = bits.Mul64(x414, 0xfffffffffffffffe)
+       var x424 uint64
+       var x425 uint64
+       x425, x424 = bits.Mul64(x414, 0xffffffff00000000)
+       var x426 uint64
+       var x427 uint64
+       x427, x426 = bits.Mul64(x414, 0xffffffff)
+       var x428 uint64
+       var x429 uint64
+       x428, x429 = bits.Add64(x427, x424, uint64(0x0))
+       var x430 uint64
+       var x431 uint64
+       x430, x431 = bits.Add64(x425, x422, uint64(p384Uint1(x429)))
+       var x432 uint64
+       var x433 uint64
+       x432, x433 = bits.Add64(x423, x420, uint64(p384Uint1(x431)))
+       var x434 uint64
+       var x435 uint64
+       x434, x435 = bits.Add64(x421, x418, uint64(p384Uint1(x433)))
+       var x436 uint64
+       var x437 uint64
+       x436, x437 = bits.Add64(x419, x416, uint64(p384Uint1(x435)))
+       x438 := (uint64(p384Uint1(x437)) + x417)
+       var x440 uint64
+       _, x440 = bits.Add64(x400, x426, uint64(0x0))
+       var x441 uint64
+       var x442 uint64
+       x441, x442 = bits.Add64(x402, x428, uint64(p384Uint1(x440)))
+       var x443 uint64
+       var x444 uint64
+       x443, x444 = bits.Add64(x404, x430, uint64(p384Uint1(x442)))
+       var x445 uint64
+       var x446 uint64
+       x445, x446 = bits.Add64(x406, x432, uint64(p384Uint1(x444)))
+       var x447 uint64
+       var x448 uint64
+       x447, x448 = bits.Add64(x408, x434, uint64(p384Uint1(x446)))
+       var x449 uint64
+       var x450 uint64
+       x449, x450 = bits.Add64(x410, x436, uint64(p384Uint1(x448)))
+       var x451 uint64
+       var x452 uint64
+       x451, x452 = bits.Add64(x412, x438, uint64(p384Uint1(x450)))
+       x453 := (uint64(p384Uint1(x452)) + uint64(p384Uint1(x413)))
+       var x454 uint64
+       var x455 uint64
+       x454, x455 = bits.Sub64(x441, 0xffffffff, uint64(0x0))
+       var x456 uint64
+       var x457 uint64
+       x456, x457 = bits.Sub64(x443, 0xffffffff00000000, uint64(p384Uint1(x455)))
+       var x458 uint64
+       var x459 uint64
+       x458, x459 = bits.Sub64(x445, 0xfffffffffffffffe, uint64(p384Uint1(x457)))
+       var x460 uint64
+       var x461 uint64
+       x460, x461 = bits.Sub64(x447, 0xffffffffffffffff, uint64(p384Uint1(x459)))
+       var x462 uint64
+       var x463 uint64
+       x462, x463 = bits.Sub64(x449, 0xffffffffffffffff, uint64(p384Uint1(x461)))
+       var x464 uint64
+       var x465 uint64
+       x464, x465 = bits.Sub64(x451, 0xffffffffffffffff, uint64(p384Uint1(x463)))
+       var x467 uint64
+       _, x467 = bits.Sub64(x453, uint64(0x0), uint64(p384Uint1(x465)))
+       var x468 uint64
+       p384CmovznzU64(&x468, p384Uint1(x467), x454, x441)
+       var x469 uint64
+       p384CmovznzU64(&x469, p384Uint1(x467), x456, x443)
+       var x470 uint64
+       p384CmovznzU64(&x470, p384Uint1(x467), x458, x445)
+       var x471 uint64
+       p384CmovznzU64(&x471, p384Uint1(x467), x460, x447)
+       var x472 uint64
+       p384CmovznzU64(&x472, p384Uint1(x467), x462, x449)
+       var x473 uint64
+       p384CmovznzU64(&x473, p384Uint1(x467), x464, x451)
+       out1[0] = x468
+       out1[1] = x469
+       out1[2] = x470
+       out1[3] = x471
+       out1[4] = x472
+       out1[5] = x473
+}
+
+// p384Square squares a field element in the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m
+//   0 ≤ eval out1 < m
+//
+func p384Square(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[0]
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x6, arg1[5])
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x6, arg1[4])
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x6, arg1[3])
+       var x13 uint64
+       var x14 uint64
+       x14, x13 = bits.Mul64(x6, arg1[2])
+       var x15 uint64
+       var x16 uint64
+       x16, x15 = bits.Mul64(x6, arg1[1])
+       var x17 uint64
+       var x18 uint64
+       x18, x17 = bits.Mul64(x6, arg1[0])
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Add64(x18, x15, uint64(0x0))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Add64(x16, x13, uint64(p384Uint1(x20)))
+       var x23 uint64
+       var x24 uint64
+       x23, x24 = bits.Add64(x14, x11, uint64(p384Uint1(x22)))
+       var x25 uint64
+       var x26 uint64
+       x25, x26 = bits.Add64(x12, x9, uint64(p384Uint1(x24)))
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Add64(x10, x7, uint64(p384Uint1(x26)))
+       x29 := (uint64(p384Uint1(x28)) + x8)
+       var x30 uint64
+       _, x30 = bits.Mul64(x17, 0x100000001)
+       var x32 uint64
+       var x33 uint64
+       x33, x32 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x34 uint64
+       var x35 uint64
+       x35, x34 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x36 uint64
+       var x37 uint64
+       x37, x36 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x38 uint64
+       var x39 uint64
+       x39, x38 = bits.Mul64(x30, 0xfffffffffffffffe)
+       var x40 uint64
+       var x41 uint64
+       x41, x40 = bits.Mul64(x30, 0xffffffff00000000)
+       var x42 uint64
+       var x43 uint64
+       x43, x42 = bits.Mul64(x30, 0xffffffff)
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(x43, x40, uint64(0x0))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64(x41, x38, uint64(p384Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(x39, x36, uint64(p384Uint1(x47)))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(x37, x34, uint64(p384Uint1(x49)))
+       var x52 uint64
+       var x53 uint64
+       x52, x53 = bits.Add64(x35, x32, uint64(p384Uint1(x51)))
+       x54 := (uint64(p384Uint1(x53)) + x33)
+       var x56 uint64
+       _, x56 = bits.Add64(x17, x42, uint64(0x0))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(x19, x44, uint64(p384Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x59, x60 = bits.Add64(x21, x46, uint64(p384Uint1(x58)))
+       var x61 uint64
+       var x62 uint64
+       x61, x62 = bits.Add64(x23, x48, uint64(p384Uint1(x60)))
+       var x63 uint64
+       var x64 uint64
+       x63, x64 = bits.Add64(x25, x50, uint64(p384Uint1(x62)))
+       var x65 uint64
+       var x66 uint64
+       x65, x66 = bits.Add64(x27, x52, uint64(p384Uint1(x64)))
+       var x67 uint64
+       var x68 uint64
+       x67, x68 = bits.Add64(x29, x54, uint64(p384Uint1(x66)))
+       var x69 uint64
+       var x70 uint64
+       x70, x69 = bits.Mul64(x1, arg1[5])
+       var x71 uint64
+       var x72 uint64
+       x72, x71 = bits.Mul64(x1, arg1[4])
+       var x73 uint64
+       var x74 uint64
+       x74, x73 = bits.Mul64(x1, arg1[3])
+       var x75 uint64
+       var x76 uint64
+       x76, x75 = bits.Mul64(x1, arg1[2])
+       var x77 uint64
+       var x78 uint64
+       x78, x77 = bits.Mul64(x1, arg1[1])
+       var x79 uint64
+       var x80 uint64
+       x80, x79 = bits.Mul64(x1, arg1[0])
+       var x81 uint64
+       var x82 uint64
+       x81, x82 = bits.Add64(x80, x77, uint64(0x0))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x78, x75, uint64(p384Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x76, x73, uint64(p384Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x74, x71, uint64(p384Uint1(x86)))
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x72, x69, uint64(p384Uint1(x88)))
+       x91 := (uint64(p384Uint1(x90)) + x70)
+       var x92 uint64
+       var x93 uint64
+       x92, x93 = bits.Add64(x57, x79, uint64(0x0))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x59, x81, uint64(p384Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x61, x83, uint64(p384Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64(x63, x85, uint64(p384Uint1(x97)))
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x65, x87, uint64(p384Uint1(x99)))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x67, x89, uint64(p384Uint1(x101)))
+       var x104 uint64
+       var x105 uint64
+       x104, x105 = bits.Add64(uint64(p384Uint1(x68)), x91, uint64(p384Uint1(x103)))
+       var x106 uint64
+       _, x106 = bits.Mul64(x92, 0x100000001)
+       var x108 uint64
+       var x109 uint64
+       x109, x108 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x110 uint64
+       var x111 uint64
+       x111, x110 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x112 uint64
+       var x113 uint64
+       x113, x112 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x114 uint64
+       var x115 uint64
+       x115, x114 = bits.Mul64(x106, 0xfffffffffffffffe)
+       var x116 uint64
+       var x117 uint64
+       x117, x116 = bits.Mul64(x106, 0xffffffff00000000)
+       var x118 uint64
+       var x119 uint64
+       x119, x118 = bits.Mul64(x106, 0xffffffff)
+       var x120 uint64
+       var x121 uint64
+       x120, x121 = bits.Add64(x119, x116, uint64(0x0))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x117, x114, uint64(p384Uint1(x121)))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x115, x112, uint64(p384Uint1(x123)))
+       var x126 uint64
+       var x127 uint64
+       x126, x127 = bits.Add64(x113, x110, uint64(p384Uint1(x125)))
+       var x128 uint64
+       var x129 uint64
+       x128, x129 = bits.Add64(x111, x108, uint64(p384Uint1(x127)))
+       x130 := (uint64(p384Uint1(x129)) + x109)
+       var x132 uint64
+       _, x132 = bits.Add64(x92, x118, uint64(0x0))
+       var x133 uint64
+       var x134 uint64
+       x133, x134 = bits.Add64(x94, x120, uint64(p384Uint1(x132)))
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x96, x122, uint64(p384Uint1(x134)))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x98, x124, uint64(p384Uint1(x136)))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x100, x126, uint64(p384Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x102, x128, uint64(p384Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x143, x144 = bits.Add64(x104, x130, uint64(p384Uint1(x142)))
+       x145 := (uint64(p384Uint1(x144)) + uint64(p384Uint1(x105)))
+       var x146 uint64
+       var x147 uint64
+       x147, x146 = bits.Mul64(x2, arg1[5])
+       var x148 uint64
+       var x149 uint64
+       x149, x148 = bits.Mul64(x2, arg1[4])
+       var x150 uint64
+       var x151 uint64
+       x151, x150 = bits.Mul64(x2, arg1[3])
+       var x152 uint64
+       var x153 uint64
+       x153, x152 = bits.Mul64(x2, arg1[2])
+       var x154 uint64
+       var x155 uint64
+       x155, x154 = bits.Mul64(x2, arg1[1])
+       var x156 uint64
+       var x157 uint64
+       x157, x156 = bits.Mul64(x2, arg1[0])
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x157, x154, uint64(0x0))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x155, x152, uint64(p384Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x153, x150, uint64(p384Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x151, x148, uint64(p384Uint1(x163)))
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Add64(x149, x146, uint64(p384Uint1(x165)))
+       x168 := (uint64(p384Uint1(x167)) + x147)
+       var x169 uint64
+       var x170 uint64
+       x169, x170 = bits.Add64(x133, x156, uint64(0x0))
+       var x171 uint64
+       var x172 uint64
+       x171, x172 = bits.Add64(x135, x158, uint64(p384Uint1(x170)))
+       var x173 uint64
+       var x174 uint64
+       x173, x174 = bits.Add64(x137, x160, uint64(p384Uint1(x172)))
+       var x175 uint64
+       var x176 uint64
+       x175, x176 = bits.Add64(x139, x162, uint64(p384Uint1(x174)))
+       var x177 uint64
+       var x178 uint64
+       x177, x178 = bits.Add64(x141, x164, uint64(p384Uint1(x176)))
+       var x179 uint64
+       var x180 uint64
+       x179, x180 = bits.Add64(x143, x166, uint64(p384Uint1(x178)))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x145, x168, uint64(p384Uint1(x180)))
+       var x183 uint64
+       _, x183 = bits.Mul64(x169, 0x100000001)
+       var x185 uint64
+       var x186 uint64
+       x186, x185 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x187 uint64
+       var x188 uint64
+       x188, x187 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x189 uint64
+       var x190 uint64
+       x190, x189 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x191 uint64
+       var x192 uint64
+       x192, x191 = bits.Mul64(x183, 0xfffffffffffffffe)
+       var x193 uint64
+       var x194 uint64
+       x194, x193 = bits.Mul64(x183, 0xffffffff00000000)
+       var x195 uint64
+       var x196 uint64
+       x196, x195 = bits.Mul64(x183, 0xffffffff)
+       var x197 uint64
+       var x198 uint64
+       x197, x198 = bits.Add64(x196, x193, uint64(0x0))
+       var x199 uint64
+       var x200 uint64
+       x199, x200 = bits.Add64(x194, x191, uint64(p384Uint1(x198)))
+       var x201 uint64
+       var x202 uint64
+       x201, x202 = bits.Add64(x192, x189, uint64(p384Uint1(x200)))
+       var x203 uint64
+       var x204 uint64
+       x203, x204 = bits.Add64(x190, x187, uint64(p384Uint1(x202)))
+       var x205 uint64
+       var x206 uint64
+       x205, x206 = bits.Add64(x188, x185, uint64(p384Uint1(x204)))
+       x207 := (uint64(p384Uint1(x206)) + x186)
+       var x209 uint64
+       _, x209 = bits.Add64(x169, x195, uint64(0x0))
+       var x210 uint64
+       var x211 uint64
+       x210, x211 = bits.Add64(x171, x197, uint64(p384Uint1(x209)))
+       var x212 uint64
+       var x213 uint64
+       x212, x213 = bits.Add64(x173, x199, uint64(p384Uint1(x211)))
+       var x214 uint64
+       var x215 uint64
+       x214, x215 = bits.Add64(x175, x201, uint64(p384Uint1(x213)))
+       var x216 uint64
+       var x217 uint64
+       x216, x217 = bits.Add64(x177, x203, uint64(p384Uint1(x215)))
+       var x218 uint64
+       var x219 uint64
+       x218, x219 = bits.Add64(x179, x205, uint64(p384Uint1(x217)))
+       var x220 uint64
+       var x221 uint64
+       x220, x221 = bits.Add64(x181, x207, uint64(p384Uint1(x219)))
+       x222 := (uint64(p384Uint1(x221)) + uint64(p384Uint1(x182)))
+       var x223 uint64
+       var x224 uint64
+       x224, x223 = bits.Mul64(x3, arg1[5])
+       var x225 uint64
+       var x226 uint64
+       x226, x225 = bits.Mul64(x3, arg1[4])
+       var x227 uint64
+       var x228 uint64
+       x228, x227 = bits.Mul64(x3, arg1[3])
+       var x229 uint64
+       var x230 uint64
+       x230, x229 = bits.Mul64(x3, arg1[2])
+       var x231 uint64
+       var x232 uint64
+       x232, x231 = bits.Mul64(x3, arg1[1])
+       var x233 uint64
+       var x234 uint64
+       x234, x233 = bits.Mul64(x3, arg1[0])
+       var x235 uint64
+       var x236 uint64
+       x235, x236 = bits.Add64(x234, x231, uint64(0x0))
+       var x237 uint64
+       var x238 uint64
+       x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236)))
+       var x239 uint64
+       var x240 uint64
+       x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238)))
+       var x241 uint64
+       var x242 uint64
+       x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240)))
+       var x243 uint64
+       var x244 uint64
+       x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242)))
+       x245 := (uint64(p384Uint1(x244)) + x224)
+       var x246 uint64
+       var x247 uint64
+       x246, x247 = bits.Add64(x210, x233, uint64(0x0))
+       var x248 uint64
+       var x249 uint64
+       x248, x249 = bits.Add64(x212, x235, uint64(p384Uint1(x247)))
+       var x250 uint64
+       var x251 uint64
+       x250, x251 = bits.Add64(x214, x237, uint64(p384Uint1(x249)))
+       var x252 uint64
+       var x253 uint64
+       x252, x253 = bits.Add64(x216, x239, uint64(p384Uint1(x251)))
+       var x254 uint64
+       var x255 uint64
+       x254, x255 = bits.Add64(x218, x241, uint64(p384Uint1(x253)))
+       var x256 uint64
+       var x257 uint64
+       x256, x257 = bits.Add64(x220, x243, uint64(p384Uint1(x255)))
+       var x258 uint64
+       var x259 uint64
+       x258, x259 = bits.Add64(x222, x245, uint64(p384Uint1(x257)))
+       var x260 uint64
+       _, x260 = bits.Mul64(x246, 0x100000001)
+       var x262 uint64
+       var x263 uint64
+       x263, x262 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x264 uint64
+       var x265 uint64
+       x265, x264 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x266 uint64
+       var x267 uint64
+       x267, x266 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x268 uint64
+       var x269 uint64
+       x269, x268 = bits.Mul64(x260, 0xfffffffffffffffe)
+       var x270 uint64
+       var x271 uint64
+       x271, x270 = bits.Mul64(x260, 0xffffffff00000000)
+       var x272 uint64
+       var x273 uint64
+       x273, x272 = bits.Mul64(x260, 0xffffffff)
+       var x274 uint64
+       var x275 uint64
+       x274, x275 = bits.Add64(x273, x270, uint64(0x0))
+       var x276 uint64
+       var x277 uint64
+       x276, x277 = bits.Add64(x271, x268, uint64(p384Uint1(x275)))
+       var x278 uint64
+       var x279 uint64
+       x278, x279 = bits.Add64(x269, x266, uint64(p384Uint1(x277)))
+       var x280 uint64
+       var x281 uint64
+       x280, x281 = bits.Add64(x267, x264, uint64(p384Uint1(x279)))
+       var x282 uint64
+       var x283 uint64
+       x282, x283 = bits.Add64(x265, x262, uint64(p384Uint1(x281)))
+       x284 := (uint64(p384Uint1(x283)) + x263)
+       var x286 uint64
+       _, x286 = bits.Add64(x246, x272, uint64(0x0))
+       var x287 uint64
+       var x288 uint64
+       x287, x288 = bits.Add64(x248, x274, uint64(p384Uint1(x286)))
+       var x289 uint64
+       var x290 uint64
+       x289, x290 = bits.Add64(x250, x276, uint64(p384Uint1(x288)))
+       var x291 uint64
+       var x292 uint64
+       x291, x292 = bits.Add64(x252, x278, uint64(p384Uint1(x290)))
+       var x293 uint64
+       var x294 uint64
+       x293, x294 = bits.Add64(x254, x280, uint64(p384Uint1(x292)))
+       var x295 uint64
+       var x296 uint64
+       x295, x296 = bits.Add64(x256, x282, uint64(p384Uint1(x294)))
+       var x297 uint64
+       var x298 uint64
+       x297, x298 = bits.Add64(x258, x284, uint64(p384Uint1(x296)))
+       x299 := (uint64(p384Uint1(x298)) + uint64(p384Uint1(x259)))
+       var x300 uint64
+       var x301 uint64
+       x301, x300 = bits.Mul64(x4, arg1[5])
+       var x302 uint64
+       var x303 uint64
+       x303, x302 = bits.Mul64(x4, arg1[4])
+       var x304 uint64
+       var x305 uint64
+       x305, x304 = bits.Mul64(x4, arg1[3])
+       var x306 uint64
+       var x307 uint64
+       x307, x306 = bits.Mul64(x4, arg1[2])
+       var x308 uint64
+       var x309 uint64
+       x309, x308 = bits.Mul64(x4, arg1[1])
+       var x310 uint64
+       var x311 uint64
+       x311, x310 = bits.Mul64(x4, arg1[0])
+       var x312 uint64
+       var x313 uint64
+       x312, x313 = bits.Add64(x311, x308, uint64(0x0))
+       var x314 uint64
+       var x315 uint64
+       x314, x315 = bits.Add64(x309, x306, uint64(p384Uint1(x313)))
+       var x316 uint64
+       var x317 uint64
+       x316, x317 = bits.Add64(x307, x304, uint64(p384Uint1(x315)))
+       var x318 uint64
+       var x319 uint64
+       x318, x319 = bits.Add64(x305, x302, uint64(p384Uint1(x317)))
+       var x320 uint64
+       var x321 uint64
+       x320, x321 = bits.Add64(x303, x300, uint64(p384Uint1(x319)))
+       x322 := (uint64(p384Uint1(x321)) + x301)
+       var x323 uint64
+       var x324 uint64
+       x323, x324 = bits.Add64(x287, x310, uint64(0x0))
+       var x325 uint64
+       var x326 uint64
+       x325, x326 = bits.Add64(x289, x312, uint64(p384Uint1(x324)))
+       var x327 uint64
+       var x328 uint64
+       x327, x328 = bits.Add64(x291, x314, uint64(p384Uint1(x326)))
+       var x329 uint64
+       var x330 uint64
+       x329, x330 = bits.Add64(x293, x316, uint64(p384Uint1(x328)))
+       var x331 uint64
+       var x332 uint64
+       x331, x332 = bits.Add64(x295, x318, uint64(p384Uint1(x330)))
+       var x333 uint64
+       var x334 uint64
+       x333, x334 = bits.Add64(x297, x320, uint64(p384Uint1(x332)))
+       var x335 uint64
+       var x336 uint64
+       x335, x336 = bits.Add64(x299, x322, uint64(p384Uint1(x334)))
+       var x337 uint64
+       _, x337 = bits.Mul64(x323, 0x100000001)
+       var x339 uint64
+       var x340 uint64
+       x340, x339 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x341 uint64
+       var x342 uint64
+       x342, x341 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x343 uint64
+       var x344 uint64
+       x344, x343 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x345 uint64
+       var x346 uint64
+       x346, x345 = bits.Mul64(x337, 0xfffffffffffffffe)
+       var x347 uint64
+       var x348 uint64
+       x348, x347 = bits.Mul64(x337, 0xffffffff00000000)
+       var x349 uint64
+       var x350 uint64
+       x350, x349 = bits.Mul64(x337, 0xffffffff)
+       var x351 uint64
+       var x352 uint64
+       x351, x352 = bits.Add64(x350, x347, uint64(0x0))
+       var x353 uint64
+       var x354 uint64
+       x353, x354 = bits.Add64(x348, x345, uint64(p384Uint1(x352)))
+       var x355 uint64
+       var x356 uint64
+       x355, x356 = bits.Add64(x346, x343, uint64(p384Uint1(x354)))
+       var x357 uint64
+       var x358 uint64
+       x357, x358 = bits.Add64(x344, x341, uint64(p384Uint1(x356)))
+       var x359 uint64
+       var x360 uint64
+       x359, x360 = bits.Add64(x342, x339, uint64(p384Uint1(x358)))
+       x361 := (uint64(p384Uint1(x360)) + x340)
+       var x363 uint64
+       _, x363 = bits.Add64(x323, x349, uint64(0x0))
+       var x364 uint64
+       var x365 uint64
+       x364, x365 = bits.Add64(x325, x351, uint64(p384Uint1(x363)))
+       var x366 uint64
+       var x367 uint64
+       x366, x367 = bits.Add64(x327, x353, uint64(p384Uint1(x365)))
+       var x368 uint64
+       var x369 uint64
+       x368, x369 = bits.Add64(x329, x355, uint64(p384Uint1(x367)))
+       var x370 uint64
+       var x371 uint64
+       x370, x371 = bits.Add64(x331, x357, uint64(p384Uint1(x369)))
+       var x372 uint64
+       var x373 uint64
+       x372, x373 = bits.Add64(x333, x359, uint64(p384Uint1(x371)))
+       var x374 uint64
+       var x375 uint64
+       x374, x375 = bits.Add64(x335, x361, uint64(p384Uint1(x373)))
+       x376 := (uint64(p384Uint1(x375)) + uint64(p384Uint1(x336)))
+       var x377 uint64
+       var x378 uint64
+       x378, x377 = bits.Mul64(x5, arg1[5])
+       var x379 uint64
+       var x380 uint64
+       x380, x379 = bits.Mul64(x5, arg1[4])
+       var x381 uint64
+       var x382 uint64
+       x382, x381 = bits.Mul64(x5, arg1[3])
+       var x383 uint64
+       var x384 uint64
+       x384, x383 = bits.Mul64(x5, arg1[2])
+       var x385 uint64
+       var x386 uint64
+       x386, x385 = bits.Mul64(x5, arg1[1])
+       var x387 uint64
+       var x388 uint64
+       x388, x387 = bits.Mul64(x5, arg1[0])
+       var x389 uint64
+       var x390 uint64
+       x389, x390 = bits.Add64(x388, x385, uint64(0x0))
+       var x391 uint64
+       var x392 uint64
+       x391, x392 = bits.Add64(x386, x383, uint64(p384Uint1(x390)))
+       var x393 uint64
+       var x394 uint64
+       x393, x394 = bits.Add64(x384, x381, uint64(p384Uint1(x392)))
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Add64(x382, x379, uint64(p384Uint1(x394)))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Add64(x380, x377, uint64(p384Uint1(x396)))
+       x399 := (uint64(p384Uint1(x398)) + x378)
+       var x400 uint64
+       var x401 uint64
+       x400, x401 = bits.Add64(x364, x387, uint64(0x0))
+       var x402 uint64
+       var x403 uint64
+       x402, x403 = bits.Add64(x366, x389, uint64(p384Uint1(x401)))
+       var x404 uint64
+       var x405 uint64
+       x404, x405 = bits.Add64(x368, x391, uint64(p384Uint1(x403)))
+       var x406 uint64
+       var x407 uint64
+       x406, x407 = bits.Add64(x370, x393, uint64(p384Uint1(x405)))
+       var x408 uint64
+       var x409 uint64
+       x408, x409 = bits.Add64(x372, x395, uint64(p384Uint1(x407)))
+       var x410 uint64
+       var x411 uint64
+       x410, x411 = bits.Add64(x374, x397, uint64(p384Uint1(x409)))
+       var x412 uint64
+       var x413 uint64
+       x412, x413 = bits.Add64(x376, x399, uint64(p384Uint1(x411)))
+       var x414 uint64
+       _, x414 = bits.Mul64(x400, 0x100000001)
+       var x416 uint64
+       var x417 uint64
+       x417, x416 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x418 uint64
+       var x419 uint64
+       x419, x418 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x420 uint64
+       var x421 uint64
+       x421, x420 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x422 uint64
+       var x423 uint64
+       x423, x422 = bits.Mul64(x414, 0xfffffffffffffffe)
+       var x424 uint64
+       var x425 uint64
+       x425, x424 = bits.Mul64(x414, 0xffffffff00000000)
+       var x426 uint64
+       var x427 uint64
+       x427, x426 = bits.Mul64(x414, 0xffffffff)
+       var x428 uint64
+       var x429 uint64
+       x428, x429 = bits.Add64(x427, x424, uint64(0x0))
+       var x430 uint64
+       var x431 uint64
+       x430, x431 = bits.Add64(x425, x422, uint64(p384Uint1(x429)))
+       var x432 uint64
+       var x433 uint64
+       x432, x433 = bits.Add64(x423, x420, uint64(p384Uint1(x431)))
+       var x434 uint64
+       var x435 uint64
+       x434, x435 = bits.Add64(x421, x418, uint64(p384Uint1(x433)))
+       var x436 uint64
+       var x437 uint64
+       x436, x437 = bits.Add64(x419, x416, uint64(p384Uint1(x435)))
+       x438 := (uint64(p384Uint1(x437)) + x417)
+       var x440 uint64
+       _, x440 = bits.Add64(x400, x426, uint64(0x0))
+       var x441 uint64
+       var x442 uint64
+       x441, x442 = bits.Add64(x402, x428, uint64(p384Uint1(x440)))
+       var x443 uint64
+       var x444 uint64
+       x443, x444 = bits.Add64(x404, x430, uint64(p384Uint1(x442)))
+       var x445 uint64
+       var x446 uint64
+       x445, x446 = bits.Add64(x406, x432, uint64(p384Uint1(x444)))
+       var x447 uint64
+       var x448 uint64
+       x447, x448 = bits.Add64(x408, x434, uint64(p384Uint1(x446)))
+       var x449 uint64
+       var x450 uint64
+       x449, x450 = bits.Add64(x410, x436, uint64(p384Uint1(x448)))
+       var x451 uint64
+       var x452 uint64
+       x451, x452 = bits.Add64(x412, x438, uint64(p384Uint1(x450)))
+       x453 := (uint64(p384Uint1(x452)) + uint64(p384Uint1(x413)))
+       var x454 uint64
+       var x455 uint64
+       x454, x455 = bits.Sub64(x441, 0xffffffff, uint64(0x0))
+       var x456 uint64
+       var x457 uint64
+       x456, x457 = bits.Sub64(x443, 0xffffffff00000000, uint64(p384Uint1(x455)))
+       var x458 uint64
+       var x459 uint64
+       x458, x459 = bits.Sub64(x445, 0xfffffffffffffffe, uint64(p384Uint1(x457)))
+       var x460 uint64
+       var x461 uint64
+       x460, x461 = bits.Sub64(x447, 0xffffffffffffffff, uint64(p384Uint1(x459)))
+       var x462 uint64
+       var x463 uint64
+       x462, x463 = bits.Sub64(x449, 0xffffffffffffffff, uint64(p384Uint1(x461)))
+       var x464 uint64
+       var x465 uint64
+       x464, x465 = bits.Sub64(x451, 0xffffffffffffffff, uint64(p384Uint1(x463)))
+       var x467 uint64
+       _, x467 = bits.Sub64(x453, uint64(0x0), uint64(p384Uint1(x465)))
+       var x468 uint64
+       p384CmovznzU64(&x468, p384Uint1(x467), x454, x441)
+       var x469 uint64
+       p384CmovznzU64(&x469, p384Uint1(x467), x456, x443)
+       var x470 uint64
+       p384CmovznzU64(&x470, p384Uint1(x467), x458, x445)
+       var x471 uint64
+       p384CmovznzU64(&x471, p384Uint1(x467), x460, x447)
+       var x472 uint64
+       p384CmovznzU64(&x472, p384Uint1(x467), x462, x449)
+       var x473 uint64
+       p384CmovznzU64(&x473, p384Uint1(x467), x464, x451)
+       out1[0] = x468
+       out1[1] = x469
+       out1[2] = x470
+       out1[3] = x471
+       out1[4] = x472
+       out1[5] = x473
+}
+
+// p384Add adds two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+//   0 ≤ eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
+//   0 ≤ eval out1 < m
+//
+func p384Add(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p384Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p384Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p384Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Add64(arg1[4], arg2[4], uint64(p384Uint1(x8)))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Add64(arg1[5], arg2[5], uint64(p384Uint1(x10)))
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Sub64(x1, 0xffffffff, uint64(0x0))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Sub64(x3, 0xffffffff00000000, uint64(p384Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Sub64(x5, 0xfffffffffffffffe, uint64(p384Uint1(x16)))
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Sub64(x7, 0xffffffffffffffff, uint64(p384Uint1(x18)))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Sub64(x9, 0xffffffffffffffff, uint64(p384Uint1(x20)))
+       var x23 uint64
+       var x24 uint64
+       x23, x24 = bits.Sub64(x11, 0xffffffffffffffff, uint64(p384Uint1(x22)))
+       var x26 uint64
+       _, x26 = bits.Sub64(uint64(p384Uint1(x12)), uint64(0x0), uint64(p384Uint1(x24)))
+       var x27 uint64
+       p384CmovznzU64(&x27, p384Uint1(x26), x13, x1)
+       var x28 uint64
+       p384CmovznzU64(&x28, p384Uint1(x26), x15, x3)
+       var x29 uint64
+       p384CmovznzU64(&x29, p384Uint1(x26), x17, x5)
+       var x30 uint64
+       p384CmovznzU64(&x30, p384Uint1(x26), x19, x7)
+       var x31 uint64
+       p384CmovznzU64(&x31, p384Uint1(x26), x21, x9)
+       var x32 uint64
+       p384CmovznzU64(&x32, p384Uint1(x26), x23, x11)
+       out1[0] = x27
+       out1[1] = x28
+       out1[2] = x29
+       out1[3] = x30
+       out1[4] = x31
+       out1[5] = x32
+}
+
+// p384Sub subtracts two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+//   0 ≤ eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
+//   0 ≤ eval out1 < m
+//
+func p384Sub(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p384Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p384Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p384Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Sub64(arg1[4], arg2[4], uint64(p384Uint1(x8)))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Sub64(arg1[5], arg2[5], uint64(p384Uint1(x10)))
+       var x13 uint64
+       p384CmovznzU64(&x13, p384Uint1(x12), uint64(0x0), 0xffffffffffffffff)
+       var x14 uint64
+       var x15 uint64
+       x14, x15 = bits.Add64(x1, (x13 & 0xffffffff), uint64(0x0))
+       var x16 uint64
+       var x17 uint64
+       x16, x17 = bits.Add64(x3, (x13 & 0xffffffff00000000), uint64(p384Uint1(x15)))
+       var x18 uint64
+       var x19 uint64
+       x18, x19 = bits.Add64(x5, (x13 & 0xfffffffffffffffe), uint64(p384Uint1(x17)))
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(x7, x13, uint64(p384Uint1(x19)))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x9, x13, uint64(p384Uint1(x21)))
+       var x24 uint64
+       x24, _ = bits.Add64(x11, x13, uint64(p384Uint1(x23)))
+       out1[0] = x14
+       out1[1] = x16
+       out1[2] = x18
+       out1[3] = x20
+       out1[4] = x22
+       out1[5] = x24
+}
+
+// p384SetOne returns the field element one in the Montgomery domain.
+//
+// Postconditions:
+//   eval (from_montgomery out1) mod m = 1 mod m
+//   0 ≤ eval out1 < m
+//
+func p384SetOne(out1 *p384MontgomeryDomainFieldElement) {
+       out1[0] = 0xffffffff00000001
+       out1[1] = 0xffffffff
+       out1[2] = uint64(0x1)
+       out1[3] = uint64(0x0)
+       out1[4] = uint64(0x0)
+       out1[5] = uint64(0x0)
+}
+
+// p384FromMontgomery translates a field element out of the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^6) mod m
+//   0 ≤ eval out1 < m
+//
+func p384FromMontgomery(out1 *p384NonMontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement) {
+       x1 := arg1[0]
+       var x2 uint64
+       _, x2 = bits.Mul64(x1, 0x100000001)
+       var x4 uint64
+       var x5 uint64
+       x5, x4 = bits.Mul64(x2, 0xffffffffffffffff)
+       var x6 uint64
+       var x7 uint64
+       x7, x6 = bits.Mul64(x2, 0xffffffffffffffff)
+       var x8 uint64
+       var x9 uint64
+       x9, x8 = bits.Mul64(x2, 0xffffffffffffffff)
+       var x10 uint64
+       var x11 uint64
+       x11, x10 = bits.Mul64(x2, 0xfffffffffffffffe)
+       var x12 uint64
+       var x13 uint64
+       x13, x12 = bits.Mul64(x2, 0xffffffff00000000)
+       var x14 uint64
+       var x15 uint64
+       x15, x14 = bits.Mul64(x2, 0xffffffff)
+       var x16 uint64
+       var x17 uint64
+       x16, x17 = bits.Add64(x15, x12, uint64(0x0))
+       var x18 uint64
+       var x19 uint64
+       x18, x19 = bits.Add64(x13, x10, uint64(p384Uint1(x17)))
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(x11, x8, uint64(p384Uint1(x19)))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x9, x6, uint64(p384Uint1(x21)))
+       var x24 uint64
+       var x25 uint64
+       x24, x25 = bits.Add64(x7, x4, uint64(p384Uint1(x23)))
+       var x27 uint64
+       _, x27 = bits.Add64(x1, x14, uint64(0x0))
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(uint64(0x0), x16, uint64(p384Uint1(x27)))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(uint64(0x0), x18, uint64(p384Uint1(x29)))
+       var x32 uint64
+       var x33 uint64
+       x32, x33 = bits.Add64(uint64(0x0), x20, uint64(p384Uint1(x31)))
+       var x34 uint64
+       var x35 uint64
+       x34, x35 = bits.Add64(uint64(0x0), x22, uint64(p384Uint1(x33)))
+       var x36 uint64
+       var x37 uint64
+       x36, x37 = bits.Add64(uint64(0x0), x24, uint64(p384Uint1(x35)))
+       var x38 uint64
+       var x39 uint64
+       x38, x39 = bits.Add64(uint64(0x0), (uint64(p384Uint1(x25)) + x5), uint64(p384Uint1(x37)))
+       var x40 uint64
+       var x41 uint64
+       x40, x41 = bits.Add64(x28, arg1[1], uint64(0x0))
+       var x42 uint64
+       var x43 uint64
+       x42, x43 = bits.Add64(x30, uint64(0x0), uint64(p384Uint1(x41)))
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(x32, uint64(0x0), uint64(p384Uint1(x43)))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64(x34, uint64(0x0), uint64(p384Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(x36, uint64(0x0), uint64(p384Uint1(x47)))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(x38, uint64(0x0), uint64(p384Uint1(x49)))
+       var x52 uint64
+       _, x52 = bits.Mul64(x40, 0x100000001)
+       var x54 uint64
+       var x55 uint64
+       x55, x54 = bits.Mul64(x52, 0xffffffffffffffff)
+       var x56 uint64
+       var x57 uint64
+       x57, x56 = bits.Mul64(x52, 0xffffffffffffffff)
+       var x58 uint64
+       var x59 uint64
+       x59, x58 = bits.Mul64(x52, 0xffffffffffffffff)
+       var x60 uint64
+       var x61 uint64
+       x61, x60 = bits.Mul64(x52, 0xfffffffffffffffe)
+       var x62 uint64
+       var x63 uint64
+       x63, x62 = bits.Mul64(x52, 0xffffffff00000000)
+       var x64 uint64
+       var x65 uint64
+       x65, x64 = bits.Mul64(x52, 0xffffffff)
+       var x66 uint64
+       var x67 uint64
+       x66, x67 = bits.Add64(x65, x62, uint64(0x0))
+       var x68 uint64
+       var x69 uint64
+       x68, x69 = bits.Add64(x63, x60, uint64(p384Uint1(x67)))
+       var x70 uint64
+       var x71 uint64
+       x70, x71 = bits.Add64(x61, x58, uint64(p384Uint1(x69)))
+       var x72 uint64
+       var x73 uint64
+       x72, x73 = bits.Add64(x59, x56, uint64(p384Uint1(x71)))
+       var x74 uint64
+       var x75 uint64
+       x74, x75 = bits.Add64(x57, x54, uint64(p384Uint1(x73)))
+       var x77 uint64
+       _, x77 = bits.Add64(x40, x64, uint64(0x0))
+       var x78 uint64
+       var x79 uint64
+       x78, x79 = bits.Add64(x42, x66, uint64(p384Uint1(x77)))
+       var x80 uint64
+       var x81 uint64
+       x80, x81 = bits.Add64(x44, x68, uint64(p384Uint1(x79)))
+       var x82 uint64
+       var x83 uint64
+       x82, x83 = bits.Add64(x46, x70, uint64(p384Uint1(x81)))
+       var x84 uint64
+       var x85 uint64
+       x84, x85 = bits.Add64(x48, x72, uint64(p384Uint1(x83)))
+       var x86 uint64
+       var x87 uint64
+       x86, x87 = bits.Add64(x50, x74, uint64(p384Uint1(x85)))
+       var x88 uint64
+       var x89 uint64
+       x88, x89 = bits.Add64((uint64(p384Uint1(x51)) + uint64(p384Uint1(x39))), (uint64(p384Uint1(x75)) + x55), uint64(p384Uint1(x87)))
+       var x90 uint64
+       var x91 uint64
+       x90, x91 = bits.Add64(x78, arg1[2], uint64(0x0))
+       var x92 uint64
+       var x93 uint64
+       x92, x93 = bits.Add64(x80, uint64(0x0), uint64(p384Uint1(x91)))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x82, uint64(0x0), uint64(p384Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x84, uint64(0x0), uint64(p384Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64(x86, uint64(0x0), uint64(p384Uint1(x97)))
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x88, uint64(0x0), uint64(p384Uint1(x99)))
+       var x102 uint64
+       _, x102 = bits.Mul64(x90, 0x100000001)
+       var x104 uint64
+       var x105 uint64
+       x105, x104 = bits.Mul64(x102, 0xffffffffffffffff)
+       var x106 uint64
+       var x107 uint64
+       x107, x106 = bits.Mul64(x102, 0xffffffffffffffff)
+       var x108 uint64
+       var x109 uint64
+       x109, x108 = bits.Mul64(x102, 0xffffffffffffffff)
+       var x110 uint64
+       var x111 uint64
+       x111, x110 = bits.Mul64(x102, 0xfffffffffffffffe)
+       var x112 uint64
+       var x113 uint64
+       x113, x112 = bits.Mul64(x102, 0xffffffff00000000)
+       var x114 uint64
+       var x115 uint64
+       x115, x114 = bits.Mul64(x102, 0xffffffff)
+       var x116 uint64
+       var x117 uint64
+       x116, x117 = bits.Add64(x115, x112, uint64(0x0))
+       var x118 uint64
+       var x119 uint64
+       x118, x119 = bits.Add64(x113, x110, uint64(p384Uint1(x117)))
+       var x120 uint64
+       var x121 uint64
+       x120, x121 = bits.Add64(x111, x108, uint64(p384Uint1(x119)))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x109, x106, uint64(p384Uint1(x121)))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x107, x104, uint64(p384Uint1(x123)))
+       var x127 uint64
+       _, x127 = bits.Add64(x90, x114, uint64(0x0))
+       var x128 uint64
+       var x129 uint64
+       x128, x129 = bits.Add64(x92, x116, uint64(p384Uint1(x127)))
+       var x130 uint64
+       var x131 uint64
+       x130, x131 = bits.Add64(x94, x118, uint64(p384Uint1(x129)))
+       var x132 uint64
+       var x133 uint64
+       x132, x133 = bits.Add64(x96, x120, uint64(p384Uint1(x131)))
+       var x134 uint64
+       var x135 uint64
+       x134, x135 = bits.Add64(x98, x122, uint64(p384Uint1(x133)))
+       var x136 uint64
+       var x137 uint64
+       x136, x137 = bits.Add64(x100, x124, uint64(p384Uint1(x135)))
+       var x138 uint64
+       var x139 uint64
+       x138, x139 = bits.Add64((uint64(p384Uint1(x101)) + uint64(p384Uint1(x89))), (uint64(p384Uint1(x125)) + x105), uint64(p384Uint1(x137)))
+       var x140 uint64
+       var x141 uint64
+       x140, x141 = bits.Add64(x128, arg1[3], uint64(0x0))
+       var x142 uint64
+       var x143 uint64
+       x142, x143 = bits.Add64(x130, uint64(0x0), uint64(p384Uint1(x141)))
+       var x144 uint64
+       var x145 uint64
+       x144, x145 = bits.Add64(x132, uint64(0x0), uint64(p384Uint1(x143)))
+       var x146 uint64
+       var x147 uint64
+       x146, x147 = bits.Add64(x134, uint64(0x0), uint64(p384Uint1(x145)))
+       var x148 uint64
+       var x149 uint64
+       x148, x149 = bits.Add64(x136, uint64(0x0), uint64(p384Uint1(x147)))
+       var x150 uint64
+       var x151 uint64
+       x150, x151 = bits.Add64(x138, uint64(0x0), uint64(p384Uint1(x149)))
+       var x152 uint64
+       _, x152 = bits.Mul64(x140, 0x100000001)
+       var x154 uint64
+       var x155 uint64
+       x155, x154 = bits.Mul64(x152, 0xffffffffffffffff)
+       var x156 uint64
+       var x157 uint64
+       x157, x156 = bits.Mul64(x152, 0xffffffffffffffff)
+       var x158 uint64
+       var x159 uint64
+       x159, x158 = bits.Mul64(x152, 0xffffffffffffffff)
+       var x160 uint64
+       var x161 uint64
+       x161, x160 = bits.Mul64(x152, 0xfffffffffffffffe)
+       var x162 uint64
+       var x163 uint64
+       x163, x162 = bits.Mul64(x152, 0xffffffff00000000)
+       var x164 uint64
+       var x165 uint64
+       x165, x164 = bits.Mul64(x152, 0xffffffff)
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Add64(x165, x162, uint64(0x0))
+       var x168 uint64
+       var x169 uint64
+       x168, x169 = bits.Add64(x163, x160, uint64(p384Uint1(x167)))
+       var x170 uint64
+       var x171 uint64
+       x170, x171 = bits.Add64(x161, x158, uint64(p384Uint1(x169)))
+       var x172 uint64
+       var x173 uint64
+       x172, x173 = bits.Add64(x159, x156, uint64(p384Uint1(x171)))
+       var x174 uint64
+       var x175 uint64
+       x174, x175 = bits.Add64(x157, x154, uint64(p384Uint1(x173)))
+       var x177 uint64
+       _, x177 = bits.Add64(x140, x164, uint64(0x0))
+       var x178 uint64
+       var x179 uint64
+       x178, x179 = bits.Add64(x142, x166, uint64(p384Uint1(x177)))
+       var x180 uint64
+       var x181 uint64
+       x180, x181 = bits.Add64(x144, x168, uint64(p384Uint1(x179)))
+       var x182 uint64
+       var x183 uint64
+       x182, x183 = bits.Add64(x146, x170, uint64(p384Uint1(x181)))
+       var x184 uint64
+       var x185 uint64
+       x184, x185 = bits.Add64(x148, x172, uint64(p384Uint1(x183)))
+       var x186 uint64
+       var x187 uint64
+       x186, x187 = bits.Add64(x150, x174, uint64(p384Uint1(x185)))
+       var x188 uint64
+       var x189 uint64
+       x188, x189 = bits.Add64((uint64(p384Uint1(x151)) + uint64(p384Uint1(x139))), (uint64(p384Uint1(x175)) + x155), uint64(p384Uint1(x187)))
+       var x190 uint64
+       var x191 uint64
+       x190, x191 = bits.Add64(x178, arg1[4], uint64(0x0))
+       var x192 uint64
+       var x193 uint64
+       x192, x193 = bits.Add64(x180, uint64(0x0), uint64(p384Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Add64(x182, uint64(0x0), uint64(p384Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Add64(x184, uint64(0x0), uint64(p384Uint1(x195)))
+       var x198 uint64
+       var x199 uint64
+       x198, x199 = bits.Add64(x186, uint64(0x0), uint64(p384Uint1(x197)))
+       var x200 uint64
+       var x201 uint64
+       x200, x201 = bits.Add64(x188, uint64(0x0), uint64(p384Uint1(x199)))
+       var x202 uint64
+       _, x202 = bits.Mul64(x190, 0x100000001)
+       var x204 uint64
+       var x205 uint64
+       x205, x204 = bits.Mul64(x202, 0xffffffffffffffff)
+       var x206 uint64
+       var x207 uint64
+       x207, x206 = bits.Mul64(x202, 0xffffffffffffffff)
+       var x208 uint64
+       var x209 uint64
+       x209, x208 = bits.Mul64(x202, 0xffffffffffffffff)
+       var x210 uint64
+       var x211 uint64
+       x211, x210 = bits.Mul64(x202, 0xfffffffffffffffe)
+       var x212 uint64
+       var x213 uint64
+       x213, x212 = bits.Mul64(x202, 0xffffffff00000000)
+       var x214 uint64
+       var x215 uint64
+       x215, x214 = bits.Mul64(x202, 0xffffffff)
+       var x216 uint64
+       var x217 uint64
+       x216, x217 = bits.Add64(x215, x212, uint64(0x0))
+       var x218 uint64
+       var x219 uint64
+       x218, x219 = bits.Add64(x213, x210, uint64(p384Uint1(x217)))
+       var x220 uint64
+       var x221 uint64
+       x220, x221 = bits.Add64(x211, x208, uint64(p384Uint1(x219)))
+       var x222 uint64
+       var x223 uint64
+       x222, x223 = bits.Add64(x209, x206, uint64(p384Uint1(x221)))
+       var x224 uint64
+       var x225 uint64
+       x224, x225 = bits.Add64(x207, x204, uint64(p384Uint1(x223)))
+       var x227 uint64
+       _, x227 = bits.Add64(x190, x214, uint64(0x0))
+       var x228 uint64
+       var x229 uint64
+       x228, x229 = bits.Add64(x192, x216, uint64(p384Uint1(x227)))
+       var x230 uint64
+       var x231 uint64
+       x230, x231 = bits.Add64(x194, x218, uint64(p384Uint1(x229)))
+       var x232 uint64
+       var x233 uint64
+       x232, x233 = bits.Add64(x196, x220, uint64(p384Uint1(x231)))
+       var x234 uint64
+       var x235 uint64
+       x234, x235 = bits.Add64(x198, x222, uint64(p384Uint1(x233)))
+       var x236 uint64
+       var x237 uint64
+       x236, x237 = bits.Add64(x200, x224, uint64(p384Uint1(x235)))
+       var x238 uint64
+       var x239 uint64
+       x238, x239 = bits.Add64((uint64(p384Uint1(x201)) + uint64(p384Uint1(x189))), (uint64(p384Uint1(x225)) + x205), uint64(p384Uint1(x237)))
+       var x240 uint64
+       var x241 uint64
+       x240, x241 = bits.Add64(x228, arg1[5], uint64(0x0))
+       var x242 uint64
+       var x243 uint64
+       x242, x243 = bits.Add64(x230, uint64(0x0), uint64(p384Uint1(x241)))
+       var x244 uint64
+       var x245 uint64
+       x244, x245 = bits.Add64(x232, uint64(0x0), uint64(p384Uint1(x243)))
+       var x246 uint64
+       var x247 uint64
+       x246, x247 = bits.Add64(x234, uint64(0x0), uint64(p384Uint1(x245)))
+       var x248 uint64
+       var x249 uint64
+       x248, x249 = bits.Add64(x236, uint64(0x0), uint64(p384Uint1(x247)))
+       var x250 uint64
+       var x251 uint64
+       x250, x251 = bits.Add64(x238, uint64(0x0), uint64(p384Uint1(x249)))
+       var x252 uint64
+       _, x252 = bits.Mul64(x240, 0x100000001)
+       var x254 uint64
+       var x255 uint64
+       x255, x254 = bits.Mul64(x252, 0xffffffffffffffff)
+       var x256 uint64
+       var x257 uint64
+       x257, x256 = bits.Mul64(x252, 0xffffffffffffffff)
+       var x258 uint64
+       var x259 uint64
+       x259, x258 = bits.Mul64(x252, 0xffffffffffffffff)
+       var x260 uint64
+       var x261 uint64
+       x261, x260 = bits.Mul64(x252, 0xfffffffffffffffe)
+       var x262 uint64
+       var x263 uint64
+       x263, x262 = bits.Mul64(x252, 0xffffffff00000000)
+       var x264 uint64
+       var x265 uint64
+       x265, x264 = bits.Mul64(x252, 0xffffffff)
+       var x266 uint64
+       var x267 uint64
+       x266, x267 = bits.Add64(x265, x262, uint64(0x0))
+       var x268 uint64
+       var x269 uint64
+       x268, x269 = bits.Add64(x263, x260, uint64(p384Uint1(x267)))
+       var x270 uint64
+       var x271 uint64
+       x270, x271 = bits.Add64(x261, x258, uint64(p384Uint1(x269)))
+       var x272 uint64
+       var x273 uint64
+       x272, x273 = bits.Add64(x259, x256, uint64(p384Uint1(x271)))
+       var x274 uint64
+       var x275 uint64
+       x274, x275 = bits.Add64(x257, x254, uint64(p384Uint1(x273)))
+       var x277 uint64
+       _, x277 = bits.Add64(x240, x264, uint64(0x0))
+       var x278 uint64
+       var x279 uint64
+       x278, x279 = bits.Add64(x242, x266, uint64(p384Uint1(x277)))
+       var x280 uint64
+       var x281 uint64
+       x280, x281 = bits.Add64(x244, x268, uint64(p384Uint1(x279)))
+       var x282 uint64
+       var x283 uint64
+       x282, x283 = bits.Add64(x246, x270, uint64(p384Uint1(x281)))
+       var x284 uint64
+       var x285 uint64
+       x284, x285 = bits.Add64(x248, x272, uint64(p384Uint1(x283)))
+       var x286 uint64
+       var x287 uint64
+       x286, x287 = bits.Add64(x250, x274, uint64(p384Uint1(x285)))
+       var x288 uint64
+       var x289 uint64
+       x288, x289 = bits.Add64((uint64(p384Uint1(x251)) + uint64(p384Uint1(x239))), (uint64(p384Uint1(x275)) + x255), uint64(p384Uint1(x287)))
+       var x290 uint64
+       var x291 uint64
+       x290, x291 = bits.Sub64(x278, 0xffffffff, uint64(0x0))
+       var x292 uint64
+       var x293 uint64
+       x292, x293 = bits.Sub64(x280, 0xffffffff00000000, uint64(p384Uint1(x291)))
+       var x294 uint64
+       var x295 uint64
+       x294, x295 = bits.Sub64(x282, 0xfffffffffffffffe, uint64(p384Uint1(x293)))
+       var x296 uint64
+       var x297 uint64
+       x296, x297 = bits.Sub64(x284, 0xffffffffffffffff, uint64(p384Uint1(x295)))
+       var x298 uint64
+       var x299 uint64
+       x298, x299 = bits.Sub64(x286, 0xffffffffffffffff, uint64(p384Uint1(x297)))
+       var x300 uint64
+       var x301 uint64
+       x300, x301 = bits.Sub64(x288, 0xffffffffffffffff, uint64(p384Uint1(x299)))
+       var x303 uint64
+       _, x303 = bits.Sub64(uint64(p384Uint1(x289)), uint64(0x0), uint64(p384Uint1(x301)))
+       var x304 uint64
+       p384CmovznzU64(&x304, p384Uint1(x303), x290, x278)
+       var x305 uint64
+       p384CmovznzU64(&x305, p384Uint1(x303), x292, x280)
+       var x306 uint64
+       p384CmovznzU64(&x306, p384Uint1(x303), x294, x282)
+       var x307 uint64
+       p384CmovznzU64(&x307, p384Uint1(x303), x296, x284)
+       var x308 uint64
+       p384CmovznzU64(&x308, p384Uint1(x303), x298, x286)
+       var x309 uint64
+       p384CmovznzU64(&x309, p384Uint1(x303), x300, x288)
+       out1[0] = x304
+       out1[1] = x305
+       out1[2] = x306
+       out1[3] = x307
+       out1[4] = x308
+       out1[5] = x309
+}
+
+// p384ToMontgomery translates a field element into the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = eval arg1 mod m
+//   0 ≤ eval out1 < m
+//
+func p384ToMontgomery(out1 *p384MontgomeryDomainFieldElement, arg1 *p384NonMontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[0]
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x6, 0x200000000)
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x6, 0xfffffffe00000000)
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x6, 0x200000000)
+       var x13 uint64
+       var x14 uint64
+       x14, x13 = bits.Mul64(x6, 0xfffffffe00000001)
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(x14, x11, uint64(0x0))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(x12, x9, uint64(p384Uint1(x16)))
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Add64(x10, x7, uint64(p384Uint1(x18)))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Add64(x8, x6, uint64(p384Uint1(x20)))
+       var x23 uint64
+       _, x23 = bits.Mul64(x13, 0x100000001)
+       var x25 uint64
+       var x26 uint64
+       x26, x25 = bits.Mul64(x23, 0xffffffffffffffff)
+       var x27 uint64
+       var x28 uint64
+       x28, x27 = bits.Mul64(x23, 0xffffffffffffffff)
+       var x29 uint64
+       var x30 uint64
+       x30, x29 = bits.Mul64(x23, 0xffffffffffffffff)
+       var x31 uint64
+       var x32 uint64
+       x32, x31 = bits.Mul64(x23, 0xfffffffffffffffe)
+       var x33 uint64
+       var x34 uint64
+       x34, x33 = bits.Mul64(x23, 0xffffffff00000000)
+       var x35 uint64
+       var x36 uint64
+       x36, x35 = bits.Mul64(x23, 0xffffffff)
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x36, x33, uint64(0x0))
+       var x39 uint64
+       var x40 uint64
+       x39, x40 = bits.Add64(x34, x31, uint64(p384Uint1(x38)))
+       var x41 uint64
+       var x42 uint64
+       x41, x42 = bits.Add64(x32, x29, uint64(p384Uint1(x40)))
+       var x43 uint64
+       var x44 uint64
+       x43, x44 = bits.Add64(x30, x27, uint64(p384Uint1(x42)))
+       var x45 uint64
+       var x46 uint64
+       x45, x46 = bits.Add64(x28, x25, uint64(p384Uint1(x44)))
+       var x48 uint64
+       _, x48 = bits.Add64(x13, x35, uint64(0x0))
+       var x49 uint64
+       var x50 uint64
+       x49, x50 = bits.Add64(x15, x37, uint64(p384Uint1(x48)))
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(x17, x39, uint64(p384Uint1(x50)))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(x19, x41, uint64(p384Uint1(x52)))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(x21, x43, uint64(p384Uint1(x54)))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(uint64(p384Uint1(x22)), x45, uint64(p384Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x59, x60 = bits.Add64(uint64(0x0), (uint64(p384Uint1(x46)) + x26), uint64(p384Uint1(x58)))
+       var x61 uint64
+       var x62 uint64
+       x62, x61 = bits.Mul64(x1, 0x200000000)
+       var x63 uint64
+       var x64 uint64
+       x64, x63 = bits.Mul64(x1, 0xfffffffe00000000)
+       var x65 uint64
+       var x66 uint64
+       x66, x65 = bits.Mul64(x1, 0x200000000)
+       var x67 uint64
+       var x68 uint64
+       x68, x67 = bits.Mul64(x1, 0xfffffffe00000001)
+       var x69 uint64
+       var x70 uint64
+       x69, x70 = bits.Add64(x68, x65, uint64(0x0))
+       var x71 uint64
+       var x72 uint64
+       x71, x72 = bits.Add64(x66, x63, uint64(p384Uint1(x70)))
+       var x73 uint64
+       var x74 uint64
+       x73, x74 = bits.Add64(x64, x61, uint64(p384Uint1(x72)))
+       var x75 uint64
+       var x76 uint64
+       x75, x76 = bits.Add64(x62, x1, uint64(p384Uint1(x74)))
+       var x77 uint64
+       var x78 uint64
+       x77, x78 = bits.Add64(x49, x67, uint64(0x0))
+       var x79 uint64
+       var x80 uint64
+       x79, x80 = bits.Add64(x51, x69, uint64(p384Uint1(x78)))
+       var x81 uint64
+       var x82 uint64
+       x81, x82 = bits.Add64(x53, x71, uint64(p384Uint1(x80)))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x55, x73, uint64(p384Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x57, x75, uint64(p384Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x59, uint64(p384Uint1(x76)), uint64(p384Uint1(x86)))
+       var x89 uint64
+       _, x89 = bits.Mul64(x77, 0x100000001)
+       var x91 uint64
+       var x92 uint64
+       x92, x91 = bits.Mul64(x89, 0xffffffffffffffff)
+       var x93 uint64
+       var x94 uint64
+       x94, x93 = bits.Mul64(x89, 0xffffffffffffffff)
+       var x95 uint64
+       var x96 uint64
+       x96, x95 = bits.Mul64(x89, 0xffffffffffffffff)
+       var x97 uint64
+       var x98 uint64
+       x98, x97 = bits.Mul64(x89, 0xfffffffffffffffe)
+       var x99 uint64
+       var x100 uint64
+       x100, x99 = bits.Mul64(x89, 0xffffffff00000000)
+       var x101 uint64
+       var x102 uint64
+       x102, x101 = bits.Mul64(x89, 0xffffffff)
+       var x103 uint64
+       var x104 uint64
+       x103, x104 = bits.Add64(x102, x99, uint64(0x0))
+       var x105 uint64
+       var x106 uint64
+       x105, x106 = bits.Add64(x100, x97, uint64(p384Uint1(x104)))
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Add64(x98, x95, uint64(p384Uint1(x106)))
+       var x109 uint64
+       var x110 uint64
+       x109, x110 = bits.Add64(x96, x93, uint64(p384Uint1(x108)))
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x94, x91, uint64(p384Uint1(x110)))
+       var x114 uint64
+       _, x114 = bits.Add64(x77, x101, uint64(0x0))
+       var x115 uint64
+       var x116 uint64
+       x115, x116 = bits.Add64(x79, x103, uint64(p384Uint1(x114)))
+       var x117 uint64
+       var x118 uint64
+       x117, x118 = bits.Add64(x81, x105, uint64(p384Uint1(x116)))
+       var x119 uint64
+       var x120 uint64
+       x119, x120 = bits.Add64(x83, x107, uint64(p384Uint1(x118)))
+       var x121 uint64
+       var x122 uint64
+       x121, x122 = bits.Add64(x85, x109, uint64(p384Uint1(x120)))
+       var x123 uint64
+       var x124 uint64
+       x123, x124 = bits.Add64(x87, x111, uint64(p384Uint1(x122)))
+       var x125 uint64
+       var x126 uint64
+       x125, x126 = bits.Add64((uint64(p384Uint1(x88)) + uint64(p384Uint1(x60))), (uint64(p384Uint1(x112)) + x92), uint64(p384Uint1(x124)))
+       var x127 uint64
+       var x128 uint64
+       x128, x127 = bits.Mul64(x2, 0x200000000)
+       var x129 uint64
+       var x130 uint64
+       x130, x129 = bits.Mul64(x2, 0xfffffffe00000000)
+       var x131 uint64
+       var x132 uint64
+       x132, x131 = bits.Mul64(x2, 0x200000000)
+       var x133 uint64
+       var x134 uint64
+       x134, x133 = bits.Mul64(x2, 0xfffffffe00000001)
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x134, x131, uint64(0x0))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x132, x129, uint64(p384Uint1(x136)))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x130, x127, uint64(p384Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x128, x2, uint64(p384Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x143, x144 = bits.Add64(x115, x133, uint64(0x0))
+       var x145 uint64
+       var x146 uint64
+       x145, x146 = bits.Add64(x117, x135, uint64(p384Uint1(x144)))
+       var x147 uint64
+       var x148 uint64
+       x147, x148 = bits.Add64(x119, x137, uint64(p384Uint1(x146)))
+       var x149 uint64
+       var x150 uint64
+       x149, x150 = bits.Add64(x121, x139, uint64(p384Uint1(x148)))
+       var x151 uint64
+       var x152 uint64
+       x151, x152 = bits.Add64(x123, x141, uint64(p384Uint1(x150)))
+       var x153 uint64
+       var x154 uint64
+       x153, x154 = bits.Add64(x125, uint64(p384Uint1(x142)), uint64(p384Uint1(x152)))
+       var x155 uint64
+       _, x155 = bits.Mul64(x143, 0x100000001)
+       var x157 uint64
+       var x158 uint64
+       x158, x157 = bits.Mul64(x155, 0xffffffffffffffff)
+       var x159 uint64
+       var x160 uint64
+       x160, x159 = bits.Mul64(x155, 0xffffffffffffffff)
+       var x161 uint64
+       var x162 uint64
+       x162, x161 = bits.Mul64(x155, 0xffffffffffffffff)
+       var x163 uint64
+       var x164 uint64
+       x164, x163 = bits.Mul64(x155, 0xfffffffffffffffe)
+       var x165 uint64
+       var x166 uint64
+       x166, x165 = bits.Mul64(x155, 0xffffffff00000000)
+       var x167 uint64
+       var x168 uint64
+       x168, x167 = bits.Mul64(x155, 0xffffffff)
+       var x169 uint64
+       var x170 uint64
+       x169, x170 = bits.Add64(x168, x165, uint64(0x0))
+       var x171 uint64
+       var x172 uint64
+       x171, x172 = bits.Add64(x166, x163, uint64(p384Uint1(x170)))
+       var x173 uint64
+       var x174 uint64
+       x173, x174 = bits.Add64(x164, x161, uint64(p384Uint1(x172)))
+       var x175 uint64
+       var x176 uint64
+       x175, x176 = bits.Add64(x162, x159, uint64(p384Uint1(x174)))
+       var x177 uint64
+       var x178 uint64
+       x177, x178 = bits.Add64(x160, x157, uint64(p384Uint1(x176)))
+       var x180 uint64
+       _, x180 = bits.Add64(x143, x167, uint64(0x0))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x145, x169, uint64(p384Uint1(x180)))
+       var x183 uint64
+       var x184 uint64
+       x183, x184 = bits.Add64(x147, x171, uint64(p384Uint1(x182)))
+       var x185 uint64
+       var x186 uint64
+       x185, x186 = bits.Add64(x149, x173, uint64(p384Uint1(x184)))
+       var x187 uint64
+       var x188 uint64
+       x187, x188 = bits.Add64(x151, x175, uint64(p384Uint1(x186)))
+       var x189 uint64
+       var x190 uint64
+       x189, x190 = bits.Add64(x153, x177, uint64(p384Uint1(x188)))
+       var x191 uint64
+       var x192 uint64
+       x191, x192 = bits.Add64((uint64(p384Uint1(x154)) + uint64(p384Uint1(x126))), (uint64(p384Uint1(x178)) + x158), uint64(p384Uint1(x190)))
+       var x193 uint64
+       var x194 uint64
+       x194, x193 = bits.Mul64(x3, 0x200000000)
+       var x195 uint64
+       var x196 uint64
+       x196, x195 = bits.Mul64(x3, 0xfffffffe00000000)
+       var x197 uint64
+       var x198 uint64
+       x198, x197 = bits.Mul64(x3, 0x200000000)
+       var x199 uint64
+       var x200 uint64
+       x200, x199 = bits.Mul64(x3, 0xfffffffe00000001)
+       var x201 uint64
+       var x202 uint64
+       x201, x202 = bits.Add64(x200, x197, uint64(0x0))
+       var x203 uint64
+       var x204 uint64
+       x203, x204 = bits.Add64(x198, x195, uint64(p384Uint1(x202)))
+       var x205 uint64
+       var x206 uint64
+       x205, x206 = bits.Add64(x196, x193, uint64(p384Uint1(x204)))
+       var x207 uint64
+       var x208 uint64
+       x207, x208 = bits.Add64(x194, x3, uint64(p384Uint1(x206)))
+       var x209 uint64
+       var x210 uint64
+       x209, x210 = bits.Add64(x181, x199, uint64(0x0))
+       var x211 uint64
+       var x212 uint64
+       x211, x212 = bits.Add64(x183, x201, uint64(p384Uint1(x210)))
+       var x213 uint64
+       var x214 uint64
+       x213, x214 = bits.Add64(x185, x203, uint64(p384Uint1(x212)))
+       var x215 uint64
+       var x216 uint64
+       x215, x216 = bits.Add64(x187, x205, uint64(p384Uint1(x214)))
+       var x217 uint64
+       var x218 uint64
+       x217, x218 = bits.Add64(x189, x207, uint64(p384Uint1(x216)))
+       var x219 uint64
+       var x220 uint64
+       x219, x220 = bits.Add64(x191, uint64(p384Uint1(x208)), uint64(p384Uint1(x218)))
+       var x221 uint64
+       _, x221 = bits.Mul64(x209, 0x100000001)
+       var x223 uint64
+       var x224 uint64
+       x224, x223 = bits.Mul64(x221, 0xffffffffffffffff)
+       var x225 uint64
+       var x226 uint64
+       x226, x225 = bits.Mul64(x221, 0xffffffffffffffff)
+       var x227 uint64
+       var x228 uint64
+       x228, x227 = bits.Mul64(x221, 0xffffffffffffffff)
+       var x229 uint64
+       var x230 uint64
+       x230, x229 = bits.Mul64(x221, 0xfffffffffffffffe)
+       var x231 uint64
+       var x232 uint64
+       x232, x231 = bits.Mul64(x221, 0xffffffff00000000)
+       var x233 uint64
+       var x234 uint64
+       x234, x233 = bits.Mul64(x221, 0xffffffff)
+       var x235 uint64
+       var x236 uint64
+       x235, x236 = bits.Add64(x234, x231, uint64(0x0))
+       var x237 uint64
+       var x238 uint64
+       x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236)))
+       var x239 uint64
+       var x240 uint64
+       x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238)))
+       var x241 uint64
+       var x242 uint64
+       x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240)))
+       var x243 uint64
+       var x244 uint64
+       x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242)))
+       var x246 uint64
+       _, x246 = bits.Add64(x209, x233, uint64(0x0))
+       var x247 uint64
+       var x248 uint64
+       x247, x248 = bits.Add64(x211, x235, uint64(p384Uint1(x246)))
+       var x249 uint64
+       var x250 uint64
+       x249, x250 = bits.Add64(x213, x237, uint64(p384Uint1(x248)))
+       var x251 uint64
+       var x252 uint64
+       x251, x252 = bits.Add64(x215, x239, uint64(p384Uint1(x250)))
+       var x253 uint64
+       var x254 uint64
+       x253, x254 = bits.Add64(x217, x241, uint64(p384Uint1(x252)))
+       var x255 uint64
+       var x256 uint64
+       x255, x256 = bits.Add64(x219, x243, uint64(p384Uint1(x254)))
+       var x257 uint64
+       var x258 uint64
+       x257, x258 = bits.Add64((uint64(p384Uint1(x220)) + uint64(p384Uint1(x192))), (uint64(p384Uint1(x244)) + x224), uint64(p384Uint1(x256)))
+       var x259 uint64
+       var x260 uint64
+       x260, x259 = bits.Mul64(x4, 0x200000000)
+       var x261 uint64
+       var x262 uint64
+       x262, x261 = bits.Mul64(x4, 0xfffffffe00000000)
+       var x263 uint64
+       var x264 uint64
+       x264, x263 = bits.Mul64(x4, 0x200000000)
+       var x265 uint64
+       var x266 uint64
+       x266, x265 = bits.Mul64(x4, 0xfffffffe00000001)
+       var x267 uint64
+       var x268 uint64
+       x267, x268 = bits.Add64(x266, x263, uint64(0x0))
+       var x269 uint64
+       var x270 uint64
+       x269, x270 = bits.Add64(x264, x261, uint64(p384Uint1(x268)))
+       var x271 uint64
+       var x272 uint64
+       x271, x272 = bits.Add64(x262, x259, uint64(p384Uint1(x270)))
+       var x273 uint64
+       var x274 uint64
+       x273, x274 = bits.Add64(x260, x4, uint64(p384Uint1(x272)))
+       var x275 uint64
+       var x276 uint64
+       x275, x276 = bits.Add64(x247, x265, uint64(0x0))
+       var x277 uint64
+       var x278 uint64
+       x277, x278 = bits.Add64(x249, x267, uint64(p384Uint1(x276)))
+       var x279 uint64
+       var x280 uint64
+       x279, x280 = bits.Add64(x251, x269, uint64(p384Uint1(x278)))
+       var x281 uint64
+       var x282 uint64
+       x281, x282 = bits.Add64(x253, x271, uint64(p384Uint1(x280)))
+       var x283 uint64
+       var x284 uint64
+       x283, x284 = bits.Add64(x255, x273, uint64(p384Uint1(x282)))
+       var x285 uint64
+       var x286 uint64
+       x285, x286 = bits.Add64(x257, uint64(p384Uint1(x274)), uint64(p384Uint1(x284)))
+       var x287 uint64
+       _, x287 = bits.Mul64(x275, 0x100000001)
+       var x289 uint64
+       var x290 uint64
+       x290, x289 = bits.Mul64(x287, 0xffffffffffffffff)
+       var x291 uint64
+       var x292 uint64
+       x292, x291 = bits.Mul64(x287, 0xffffffffffffffff)
+       var x293 uint64
+       var x294 uint64
+       x294, x293 = bits.Mul64(x287, 0xffffffffffffffff)
+       var x295 uint64
+       var x296 uint64
+       x296, x295 = bits.Mul64(x287, 0xfffffffffffffffe)
+       var x297 uint64
+       var x298 uint64
+       x298, x297 = bits.Mul64(x287, 0xffffffff00000000)
+       var x299 uint64
+       var x300 uint64
+       x300, x299 = bits.Mul64(x287, 0xffffffff)
+       var x301 uint64
+       var x302 uint64
+       x301, x302 = bits.Add64(x300, x297, uint64(0x0))
+       var x303 uint64
+       var x304 uint64
+       x303, x304 = bits.Add64(x298, x295, uint64(p384Uint1(x302)))
+       var x305 uint64
+       var x306 uint64
+       x305, x306 = bits.Add64(x296, x293, uint64(p384Uint1(x304)))
+       var x307 uint64
+       var x308 uint64
+       x307, x308 = bits.Add64(x294, x291, uint64(p384Uint1(x306)))
+       var x309 uint64
+       var x310 uint64
+       x309, x310 = bits.Add64(x292, x289, uint64(p384Uint1(x308)))
+       var x312 uint64
+       _, x312 = bits.Add64(x275, x299, uint64(0x0))
+       var x313 uint64
+       var x314 uint64
+       x313, x314 = bits.Add64(x277, x301, uint64(p384Uint1(x312)))
+       var x315 uint64
+       var x316 uint64
+       x315, x316 = bits.Add64(x279, x303, uint64(p384Uint1(x314)))
+       var x317 uint64
+       var x318 uint64
+       x317, x318 = bits.Add64(x281, x305, uint64(p384Uint1(x316)))
+       var x319 uint64
+       var x320 uint64
+       x319, x320 = bits.Add64(x283, x307, uint64(p384Uint1(x318)))
+       var x321 uint64
+       var x322 uint64
+       x321, x322 = bits.Add64(x285, x309, uint64(p384Uint1(x320)))
+       var x323 uint64
+       var x324 uint64
+       x323, x324 = bits.Add64((uint64(p384Uint1(x286)) + uint64(p384Uint1(x258))), (uint64(p384Uint1(x310)) + x290), uint64(p384Uint1(x322)))
+       var x325 uint64
+       var x326 uint64
+       x326, x325 = bits.Mul64(x5, 0x200000000)
+       var x327 uint64
+       var x328 uint64
+       x328, x327 = bits.Mul64(x5, 0xfffffffe00000000)
+       var x329 uint64
+       var x330 uint64
+       x330, x329 = bits.Mul64(x5, 0x200000000)
+       var x331 uint64
+       var x332 uint64
+       x332, x331 = bits.Mul64(x5, 0xfffffffe00000001)
+       var x333 uint64
+       var x334 uint64
+       x333, x334 = bits.Add64(x332, x329, uint64(0x0))
+       var x335 uint64
+       var x336 uint64
+       x335, x336 = bits.Add64(x330, x327, uint64(p384Uint1(x334)))
+       var x337 uint64
+       var x338 uint64
+       x337, x338 = bits.Add64(x328, x325, uint64(p384Uint1(x336)))
+       var x339 uint64
+       var x340 uint64
+       x339, x340 = bits.Add64(x326, x5, uint64(p384Uint1(x338)))
+       var x341 uint64
+       var x342 uint64
+       x341, x342 = bits.Add64(x313, x331, uint64(0x0))
+       var x343 uint64
+       var x344 uint64
+       x343, x344 = bits.Add64(x315, x333, uint64(p384Uint1(x342)))
+       var x345 uint64
+       var x346 uint64
+       x345, x346 = bits.Add64(x317, x335, uint64(p384Uint1(x344)))
+       var x347 uint64
+       var x348 uint64
+       x347, x348 = bits.Add64(x319, x337, uint64(p384Uint1(x346)))
+       var x349 uint64
+       var x350 uint64
+       x349, x350 = bits.Add64(x321, x339, uint64(p384Uint1(x348)))
+       var x351 uint64
+       var x352 uint64
+       x351, x352 = bits.Add64(x323, uint64(p384Uint1(x340)), uint64(p384Uint1(x350)))
+       var x353 uint64
+       _, x353 = bits.Mul64(x341, 0x100000001)
+       var x355 uint64
+       var x356 uint64
+       x356, x355 = bits.Mul64(x353, 0xffffffffffffffff)
+       var x357 uint64
+       var x358 uint64
+       x358, x357 = bits.Mul64(x353, 0xffffffffffffffff)
+       var x359 uint64
+       var x360 uint64
+       x360, x359 = bits.Mul64(x353, 0xffffffffffffffff)
+       var x361 uint64
+       var x362 uint64
+       x362, x361 = bits.Mul64(x353, 0xfffffffffffffffe)
+       var x363 uint64
+       var x364 uint64
+       x364, x363 = bits.Mul64(x353, 0xffffffff00000000)
+       var x365 uint64
+       var x366 uint64
+       x366, x365 = bits.Mul64(x353, 0xffffffff)
+       var x367 uint64
+       var x368 uint64
+       x367, x368 = bits.Add64(x366, x363, uint64(0x0))
+       var x369 uint64
+       var x370 uint64
+       x369, x370 = bits.Add64(x364, x361, uint64(p384Uint1(x368)))
+       var x371 uint64
+       var x372 uint64
+       x371, x372 = bits.Add64(x362, x359, uint64(p384Uint1(x370)))
+       var x373 uint64
+       var x374 uint64
+       x373, x374 = bits.Add64(x360, x357, uint64(p384Uint1(x372)))
+       var x375 uint64
+       var x376 uint64
+       x375, x376 = bits.Add64(x358, x355, uint64(p384Uint1(x374)))
+       var x378 uint64
+       _, x378 = bits.Add64(x341, x365, uint64(0x0))
+       var x379 uint64
+       var x380 uint64
+       x379, x380 = bits.Add64(x343, x367, uint64(p384Uint1(x378)))
+       var x381 uint64
+       var x382 uint64
+       x381, x382 = bits.Add64(x345, x369, uint64(p384Uint1(x380)))
+       var x383 uint64
+       var x384 uint64
+       x383, x384 = bits.Add64(x347, x371, uint64(p384Uint1(x382)))
+       var x385 uint64
+       var x386 uint64
+       x385, x386 = bits.Add64(x349, x373, uint64(p384Uint1(x384)))
+       var x387 uint64
+       var x388 uint64
+       x387, x388 = bits.Add64(x351, x375, uint64(p384Uint1(x386)))
+       var x389 uint64
+       var x390 uint64
+       x389, x390 = bits.Add64((uint64(p384Uint1(x352)) + uint64(p384Uint1(x324))), (uint64(p384Uint1(x376)) + x356), uint64(p384Uint1(x388)))
+       var x391 uint64
+       var x392 uint64
+       x391, x392 = bits.Sub64(x379, 0xffffffff, uint64(0x0))
+       var x393 uint64
+       var x394 uint64
+       x393, x394 = bits.Sub64(x381, 0xffffffff00000000, uint64(p384Uint1(x392)))
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Sub64(x383, 0xfffffffffffffffe, uint64(p384Uint1(x394)))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Sub64(x385, 0xffffffffffffffff, uint64(p384Uint1(x396)))
+       var x399 uint64
+       var x400 uint64
+       x399, x400 = bits.Sub64(x387, 0xffffffffffffffff, uint64(p384Uint1(x398)))
+       var x401 uint64
+       var x402 uint64
+       x401, x402 = bits.Sub64(x389, 0xffffffffffffffff, uint64(p384Uint1(x400)))
+       var x404 uint64
+       _, x404 = bits.Sub64(uint64(p384Uint1(x390)), uint64(0x0), uint64(p384Uint1(x402)))
+       var x405 uint64
+       p384CmovznzU64(&x405, p384Uint1(x404), x391, x379)
+       var x406 uint64
+       p384CmovznzU64(&x406, p384Uint1(x404), x393, x381)
+       var x407 uint64
+       p384CmovznzU64(&x407, p384Uint1(x404), x395, x383)
+       var x408 uint64
+       p384CmovznzU64(&x408, p384Uint1(x404), x397, x385)
+       var x409 uint64
+       p384CmovznzU64(&x409, p384Uint1(x404), x399, x387)
+       var x410 uint64
+       p384CmovznzU64(&x410, p384Uint1(x404), x401, x389)
+       out1[0] = x405
+       out1[1] = x406
+       out1[2] = x407
+       out1[3] = x408
+       out1[4] = x409
+       out1[5] = x410
+}
+
+// p384Selectznz is a multi-limb conditional select.
+//
+// Postconditions:
+//   eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+//   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+func p384Selectznz(out1 *[6]uint64, arg1 p384Uint1, arg2 *[6]uint64, arg3 *[6]uint64) {
+       var x1 uint64
+       p384CmovznzU64(&x1, arg1, arg2[0], arg3[0])
+       var x2 uint64
+       p384CmovznzU64(&x2, arg1, arg2[1], arg3[1])
+       var x3 uint64
+       p384CmovznzU64(&x3, arg1, arg2[2], arg3[2])
+       var x4 uint64
+       p384CmovznzU64(&x4, arg1, arg2[3], arg3[3])
+       var x5 uint64
+       p384CmovznzU64(&x5, arg1, arg2[4], arg3[4])
+       var x6 uint64
+       p384CmovznzU64(&x6, arg1, arg2[5], arg3[5])
+       out1[0] = x1
+       out1[1] = x2
+       out1[2] = x3
+       out1[3] = x4
+       out1[4] = x5
+       out1[5] = x6
+}
+
+// p384ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+// Postconditions:
+//   out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..47]
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+func p384ToBytes(out1 *[48]uint8, arg1 *[6]uint64) {
+       x1 := arg1[5]
+       x2 := arg1[4]
+       x3 := arg1[3]
+       x4 := arg1[2]
+       x5 := arg1[1]
+       x6 := arg1[0]
+       x7 := (uint8(x6) & 0xff)
+       x8 := (x6 >> 8)
+       x9 := (uint8(x8) & 0xff)
+       x10 := (x8 >> 8)
+       x11 := (uint8(x10) & 0xff)
+       x12 := (x10 >> 8)
+       x13 := (uint8(x12) & 0xff)
+       x14 := (x12 >> 8)
+       x15 := (uint8(x14) & 0xff)
+       x16 := (x14 >> 8)
+       x17 := (uint8(x16) & 0xff)
+       x18 := (x16 >> 8)
+       x19 := (uint8(x18) & 0xff)
+       x20 := uint8((x18 >> 8))
+       x21 := (uint8(x5) & 0xff)
+       x22 := (x5 >> 8)
+       x23 := (uint8(x22) & 0xff)
+       x24 := (x22 >> 8)
+       x25 := (uint8(x24) & 0xff)
+       x26 := (x24 >> 8)
+       x27 := (uint8(x26) & 0xff)
+       x28 := (x26 >> 8)
+       x29 := (uint8(x28) & 0xff)
+       x30 := (x28 >> 8)
+       x31 := (uint8(x30) & 0xff)
+       x32 := (x30 >> 8)
+       x33 := (uint8(x32) & 0xff)
+       x34 := uint8((x32 >> 8))
+       x35 := (uint8(x4) & 0xff)
+       x36 := (x4 >> 8)
+       x37 := (uint8(x36) & 0xff)
+       x38 := (x36 >> 8)
+       x39 := (uint8(x38) & 0xff)
+       x40 := (x38 >> 8)
+       x41 := (uint8(x40) & 0xff)
+       x42 := (x40 >> 8)
+       x43 := (uint8(x42) & 0xff)
+       x44 := (x42 >> 8)
+       x45 := (uint8(x44) & 0xff)
+       x46 := (x44 >> 8)
+       x47 := (uint8(x46) & 0xff)
+       x48 := uint8((x46 >> 8))
+       x49 := (uint8(x3) & 0xff)
+       x50 := (x3 >> 8)
+       x51 := (uint8(x50) & 0xff)
+       x52 := (x50 >> 8)
+       x53 := (uint8(x52) & 0xff)
+       x54 := (x52 >> 8)
+       x55 := (uint8(x54) & 0xff)
+       x56 := (x54 >> 8)
+       x57 := (uint8(x56) & 0xff)
+       x58 := (x56 >> 8)
+       x59 := (uint8(x58) & 0xff)
+       x60 := (x58 >> 8)
+       x61 := (uint8(x60) & 0xff)
+       x62 := uint8((x60 >> 8))
+       x63 := (uint8(x2) & 0xff)
+       x64 := (x2 >> 8)
+       x65 := (uint8(x64) & 0xff)
+       x66 := (x64 >> 8)
+       x67 := (uint8(x66) & 0xff)
+       x68 := (x66 >> 8)
+       x69 := (uint8(x68) & 0xff)
+       x70 := (x68 >> 8)
+       x71 := (uint8(x70) & 0xff)
+       x72 := (x70 >> 8)
+       x73 := (uint8(x72) & 0xff)
+       x74 := (x72 >> 8)
+       x75 := (uint8(x74) & 0xff)
+       x76 := uint8((x74 >> 8))
+       x77 := (uint8(x1) & 0xff)
+       x78 := (x1 >> 8)
+       x79 := (uint8(x78) & 0xff)
+       x80 := (x78 >> 8)
+       x81 := (uint8(x80) & 0xff)
+       x82 := (x80 >> 8)
+       x83 := (uint8(x82) & 0xff)
+       x84 := (x82 >> 8)
+       x85 := (uint8(x84) & 0xff)
+       x86 := (x84 >> 8)
+       x87 := (uint8(x86) & 0xff)
+       x88 := (x86 >> 8)
+       x89 := (uint8(x88) & 0xff)
+       x90 := uint8((x88 >> 8))
+       out1[0] = x7
+       out1[1] = x9
+       out1[2] = x11
+       out1[3] = x13
+       out1[4] = x15
+       out1[5] = x17
+       out1[6] = x19
+       out1[7] = x20
+       out1[8] = x21
+       out1[9] = x23
+       out1[10] = x25
+       out1[11] = x27
+       out1[12] = x29
+       out1[13] = x31
+       out1[14] = x33
+       out1[15] = x34
+       out1[16] = x35
+       out1[17] = x37
+       out1[18] = x39
+       out1[19] = x41
+       out1[20] = x43
+       out1[21] = x45
+       out1[22] = x47
+       out1[23] = x48
+       out1[24] = x49
+       out1[25] = x51
+       out1[26] = x53
+       out1[27] = x55
+       out1[28] = x57
+       out1[29] = x59
+       out1[30] = x61
+       out1[31] = x62
+       out1[32] = x63
+       out1[33] = x65
+       out1[34] = x67
+       out1[35] = x69
+       out1[36] = x71
+       out1[37] = x73
+       out1[38] = x75
+       out1[39] = x76
+       out1[40] = x77
+       out1[41] = x79
+       out1[42] = x81
+       out1[43] = x83
+       out1[44] = x85
+       out1[45] = x87
+       out1[46] = x89
+       out1[47] = x90
+}
+
+// p384FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
+//
+// Preconditions:
+//   0 ≤ bytes_eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = bytes_eval arg1 mod m
+//   0 ≤ eval out1 < m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+func p384FromBytes(out1 *[6]uint64, arg1 *[48]uint8) {
+       x1 := (uint64(arg1[47]) << 56)
+       x2 := (uint64(arg1[46]) << 48)
+       x3 := (uint64(arg1[45]) << 40)
+       x4 := (uint64(arg1[44]) << 32)
+       x5 := (uint64(arg1[43]) << 24)
+       x6 := (uint64(arg1[42]) << 16)
+       x7 := (uint64(arg1[41]) << 8)
+       x8 := arg1[40]
+       x9 := (uint64(arg1[39]) << 56)
+       x10 := (uint64(arg1[38]) << 48)
+       x11 := (uint64(arg1[37]) << 40)
+       x12 := (uint64(arg1[36]) << 32)
+       x13 := (uint64(arg1[35]) << 24)
+       x14 := (uint64(arg1[34]) << 16)
+       x15 := (uint64(arg1[33]) << 8)
+       x16 := arg1[32]
+       x17 := (uint64(arg1[31]) << 56)
+       x18 := (uint64(arg1[30]) << 48)
+       x19 := (uint64(arg1[29]) << 40)
+       x20 := (uint64(arg1[28]) << 32)
+       x21 := (uint64(arg1[27]) << 24)
+       x22 := (uint64(arg1[26]) << 16)
+       x23 := (uint64(arg1[25]) << 8)
+       x24 := arg1[24]
+       x25 := (uint64(arg1[23]) << 56)
+       x26 := (uint64(arg1[22]) << 48)
+       x27 := (uint64(arg1[21]) << 40)
+       x28 := (uint64(arg1[20]) << 32)
+       x29 := (uint64(arg1[19]) << 24)
+       x30 := (uint64(arg1[18]) << 16)
+       x31 := (uint64(arg1[17]) << 8)
+       x32 := arg1[16]
+       x33 := (uint64(arg1[15]) << 56)
+       x34 := (uint64(arg1[14]) << 48)
+       x35 := (uint64(arg1[13]) << 40)
+       x36 := (uint64(arg1[12]) << 32)
+       x37 := (uint64(arg1[11]) << 24)
+       x38 := (uint64(arg1[10]) << 16)
+       x39 := (uint64(arg1[9]) << 8)
+       x40 := arg1[8]
+       x41 := (uint64(arg1[7]) << 56)
+       x42 := (uint64(arg1[6]) << 48)
+       x43 := (uint64(arg1[5]) << 40)
+       x44 := (uint64(arg1[4]) << 32)
+       x45 := (uint64(arg1[3]) << 24)
+       x46 := (uint64(arg1[2]) << 16)
+       x47 := (uint64(arg1[1]) << 8)
+       x48 := arg1[0]
+       x49 := (x47 + uint64(x48))
+       x50 := (x46 + x49)
+       x51 := (x45 + x50)
+       x52 := (x44 + x51)
+       x53 := (x43 + x52)
+       x54 := (x42 + x53)
+       x55 := (x41 + x54)
+       x56 := (x39 + uint64(x40))
+       x57 := (x38 + x56)
+       x58 := (x37 + x57)
+       x59 := (x36 + x58)
+       x60 := (x35 + x59)
+       x61 := (x34 + x60)
+       x62 := (x33 + x61)
+       x63 := (x31 + uint64(x32))
+       x64 := (x30 + x63)
+       x65 := (x29 + x64)
+       x66 := (x28 + x65)
+       x67 := (x27 + x66)
+       x68 := (x26 + x67)
+       x69 := (x25 + x68)
+       x70 := (x23 + uint64(x24))
+       x71 := (x22 + x70)
+       x72 := (x21 + x71)
+       x73 := (x20 + x72)
+       x74 := (x19 + x73)
+       x75 := (x18 + x74)
+       x76 := (x17 + x75)
+       x77 := (x15 + uint64(x16))
+       x78 := (x14 + x77)
+       x79 := (x13 + x78)
+       x80 := (x12 + x79)
+       x81 := (x11 + x80)
+       x82 := (x10 + x81)
+       x83 := (x9 + x82)
+       x84 := (x7 + uint64(x8))
+       x85 := (x6 + x84)
+       x86 := (x5 + x85)
+       x87 := (x4 + x86)
+       x88 := (x3 + x87)
+       x89 := (x2 + x88)
+       x90 := (x1 + x89)
+       out1[0] = x55
+       out1[1] = x62
+       out1[2] = x69
+       out1[3] = x76
+       out1[4] = x83
+       out1[5] = x90
+}
diff --git a/src/crypto/elliptic/internal/fiat/p384_invert.go b/src/crypto/elliptic/internal/fiat/p384_invert.go
new file mode 100644 (file)
index 0000000..24169e9
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright 2021 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.
+
+// Code generated by addchain. DO NOT EDIT.
+
+package fiat
+
+// Invert sets e = 1/x, and returns e.
+//
+// If x == 0, Invert returns e = 0.
+func (e *P384Element) Invert(x *P384Element) *P384Element {
+       // Inversion is implemented as exponentiation with exponent p − 2.
+       // The sequence of 15 multiplications and 383 squarings is derived from the
+       // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0.
+       //
+       //      _10     = 2*1
+       //      _11     = 1 + _10
+       //      _110    = 2*_11
+       //      _111    = 1 + _110
+       //      _111000 = _111 << 3
+       //      _111111 = _111 + _111000
+       //      x12     = _111111 << 6 + _111111
+       //      x24     = x12 << 12 + x12
+       //      x30     = x24 << 6 + _111111
+       //      x31     = 2*x30 + 1
+       //      x32     = 2*x31 + 1
+       //      x63     = x32 << 31 + x31
+       //      x126    = x63 << 63 + x63
+       //      x252    = x126 << 126 + x126
+       //      x255    = x252 << 3 + _111
+       //      i397    = ((x255 << 33 + x32) << 94 + x30) << 2
+       //      return    1 + i397
+       //
+
+       var z = new(P384Element).Set(e)
+       var t0 = new(P384Element)
+       var t1 = new(P384Element)
+       var t2 = new(P384Element)
+       var t3 = new(P384Element)
+
+       z.Square(x)
+       z.Mul(x, z)
+       z.Square(z)
+       t1.Mul(x, z)
+       z.Square(t1)
+       for s := 1; s < 3; s++ {
+               z.Square(z)
+       }
+       z.Mul(t1, z)
+       t0.Square(z)
+       for s := 1; s < 6; s++ {
+               t0.Square(t0)
+       }
+       t0.Mul(z, t0)
+       t2.Square(t0)
+       for s := 1; s < 12; s++ {
+               t2.Square(t2)
+       }
+       t0.Mul(t0, t2)
+       for s := 0; s < 6; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       t2.Mul(x, t0)
+       t0.Square(t2)
+       t0.Mul(x, t0)
+       t3.Square(t0)
+       for s := 1; s < 31; s++ {
+               t3.Square(t3)
+       }
+       t2.Mul(t2, t3)
+       t3.Square(t2)
+       for s := 1; s < 63; s++ {
+               t3.Square(t3)
+       }
+       t2.Mul(t2, t3)
+       t3.Square(t2)
+       for s := 1; s < 126; s++ {
+               t3.Square(t3)
+       }
+       t2.Mul(t2, t3)
+       for s := 0; s < 3; s++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+       for s := 0; s < 33; s++ {
+               t1.Square(t1)
+       }
+       t0.Mul(t0, t1)
+       for s := 0; s < 94; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       for s := 0; s < 2; s++ {
+               z.Square(z)
+       }
+       z.Mul(x, z)
+
+       return e.Set(z)
+}
index 647c3f914f7b7f04c8f372acc95c6a1484c5c365..3d12117e496a661872cbc49a2b88fc4b4b184009 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package fiat implements prime order fields using formally verified algorithms
-// from the Fiat Cryptography project.
+// Code generated by generate.go. DO NOT EDIT.
+
 package fiat
 
 import (
@@ -15,20 +15,18 @@ import (
 //
 // The zero value is a valid zero element.
 type P521Element struct {
-       // This element has the following bounds, which are tighter than
-       // the output bounds of some operations. Those operations must be
-       // followed by a carry.
-       //
-       // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000],
-       // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000],
-       // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]
-       x [9]uint64
+       // Values are represented internally always in the Montgomery domain, and
+       // converted in Bytes and SetBytes.
+       x p521MontgomeryDomainFieldElement
 }
 
+const p521ElementLen = 66
+
+type p521UntypedFieldElement = [9]uint64
+
 // One sets e = 1, and returns e.
 func (e *P521Element) One() *P521Element {
-       *e = P521Element{}
-       e.x[0] = 1
+       p521SetOne(&e.x)
        return e
 }
 
@@ -57,153 +55,81 @@ func (e *P521Element) Set(t *P521Element) *P521Element {
 func (e *P521Element) Bytes() []byte {
        // This function is outlined to make the allocations inline in the caller
        // rather than happen on the heap.
-       var out [66]byte
+       var out [p521ElementLen]byte
        return e.bytes(&out)
 }
 
-func (e *P521Element) bytes(out *[66]byte) []byte {
-       p521ToBytes(out, &e.x)
-       invertEndianness(out[:])
+func (e *P521Element) bytes(out *[p521ElementLen]byte) []byte {
+       var tmp p521NonMontgomeryDomainFieldElement
+       p521FromMontgomery(&tmp, &e.x)
+       p521ToBytes(out, (*p521UntypedFieldElement)(&tmp))
+       p521InvertEndianness(out[:])
        return out[:]
 }
 
-// SetBytes sets e = v, where v is a big-endian 66-byte encoding, and returns
-// e. If v is not 66 bytes or it encodes a value higher than 2^521 - 1, SetBytes
-// returns nil and an error, and e is unchanged.
+// p521MinusOneEncoding is the encoding of -1 mod p, so p - 1, the
+// highest canonical encoding. It is used by SetBytes to check for non-canonical
+// encodings such as p + k, 2p + k, etc.
+var p521MinusOneEncoding = new(P521Element).Sub(
+       new(P521Element), new(P521Element).One()).Bytes()
+
+// SetBytes sets e = v, where v is a big-endian 66-byte encoding, and returns e.
+// If v is not 66 bytes or it encodes a value higher than 2^521 - 1,
+// SetBytes returns nil and an error, and e is unchanged.
 func (e *P521Element) SetBytes(v []byte) (*P521Element, error) {
-       if len(v) != 66 || v[0] > 1 {
-               return nil, errors.New("invalid P-521 field encoding")
+       if len(v) != p521ElementLen {
+               return nil, errors.New("invalid P521Element encoding")
+       }
+       for i := range v {
+               if v[i] < p521MinusOneEncoding[i] {
+                       break
+               }
+               if v[i] > p521MinusOneEncoding[i] {
+                       return nil, errors.New("invalid P521Element encoding")
+               }
        }
-       var in [66]byte
+       var in [p521ElementLen]byte
        copy(in[:], v)
-       invertEndianness(in[:])
-       p521FromBytes(&e.x, &in)
+       p521InvertEndianness(in[:])
+       var tmp p521NonMontgomeryDomainFieldElement
+       p521FromBytes((*p521UntypedFieldElement)(&tmp), &in)
+       p521ToMontgomery(&e.x, &tmp)
        return e, nil
 }
 
-func invertEndianness(v []byte) {
-       for i := 0; i < len(v)/2; i++ {
-               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
-       }
-}
-
 // Add sets e = t1 + t2, and returns e.
 func (e *P521Element) Add(t1, t2 *P521Element) *P521Element {
        p521Add(&e.x, &t1.x, &t2.x)
-       p521Carry(&e.x, &e.x)
        return e
 }
 
 // Sub sets e = t1 - t2, and returns e.
 func (e *P521Element) Sub(t1, t2 *P521Element) *P521Element {
        p521Sub(&e.x, &t1.x, &t2.x)
-       p521Carry(&e.x, &e.x)
        return e
 }
 
 // Mul sets e = t1 * t2, and returns e.
 func (e *P521Element) Mul(t1, t2 *P521Element) *P521Element {
-       p521CarryMul(&e.x, &t1.x, &t2.x)
+       p521Mul(&e.x, &t1.x, &t2.x)
        return e
 }
 
 // Square sets e = t * t, and returns e.
 func (e *P521Element) Square(t *P521Element) *P521Element {
-       p521CarrySquare(&e.x, &t.x)
+       p521Square(&e.x, &t.x)
        return e
 }
 
-// Select sets e to a if cond == 1, and to b if cond == 0.
+// Select sets v to a if cond == 1, and to b if cond == 0.
 func (v *P521Element) Select(a, b *P521Element, cond int) *P521Element {
-       p521Selectznz(&v.x, p521Uint1(cond), &b.x, &a.x)
+       p521Selectznz((*p521UntypedFieldElement)(&v.x), p521Uint1(cond),
+               (*p521UntypedFieldElement)(&b.x), (*p521UntypedFieldElement)(&a.x))
        return v
 }
 
-// Invert sets e = 1/t, and returns e.
-//
-// If t == 0, Invert returns e = 0.
-func (e *P521Element) Invert(t *P521Element) *P521Element {
-       // Inversion is implemented as exponentiation with exponent p − 2.
-       // The sequence of multiplications and squarings was generated with
-       // github.com/mmcloughlin/addchain v0.2.0.
-
-       var t1, t2 = new(P521Element), new(P521Element)
-
-       // _10 = 2 * 1
-       t1.Square(t)
-
-       // _11 = 1 + _10
-       t1.Mul(t, t1)
-
-       // _1100 = _11 << 2
-       t2.Square(t1)
-       t2.Square(t2)
-
-       // _1111 = _11 + _1100
-       t1.Mul(t1, t2)
-
-       // _11110000 = _1111 << 4
-       t2.Square(t1)
-       for i := 0; i < 3; i++ {
-               t2.Square(t2)
-       }
-
-       // _11111111 = _1111 + _11110000
-       t1.Mul(t1, t2)
-
-       // x16 = _11111111<<8 + _11111111
-       t2.Square(t1)
-       for i := 0; i < 7; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x32 = x16<<16 + x16
-       t2.Square(t1)
-       for i := 0; i < 15; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x64 = x32<<32 + x32
-       t2.Square(t1)
-       for i := 0; i < 31; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x65 = 2*x64 + 1
-       t2.Square(t1)
-       t2.Mul(t2, t)
-
-       // x129 = x65<<64 + x64
-       for i := 0; i < 64; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x130 = 2*x129 + 1
-       t2.Square(t1)
-       t2.Mul(t2, t)
-
-       // x259 = x130<<129 + x129
-       for i := 0; i < 129; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x260 = 2*x259 + 1
-       t2.Square(t1)
-       t2.Mul(t2, t)
-
-       // x519 = x260<<259 + x259
-       for i := 0; i < 259; i++ {
-               t2.Square(t2)
+func p521InvertEndianness(v []byte) {
+       for i := 0; i < len(v)/2; i++ {
+               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
        }
-       t1.Mul(t1, t2)
-
-       // return x519<<2 + 1
-       t1.Square(t1)
-       t1.Square(t1)
-       return e.Mul(t1, t)
 }
index f86283b587eb9a03d28b27459edc314e5c2560cb..9f4f290f4cae2de70cb802f79b48ce7b702470f5 100644 (file)
 // Code generated by Fiat Cryptography. DO NOT EDIT.
 //
-// Autogenerated: 'fiat-crypto/src/ExtractionOCaml/unsaturated_solinas' --lang Go --no-wide-int --cmovznz-by-mul --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' carry_mul carry_square carry add sub to_bytes from_bytes selectznz
+// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p521 64 '2^521 - 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes
 //
 // curve description: p521
 //
 // machine_wordsize = 64 (from "64")
 //
-// requested operations: carry_mul, carry_square, carry, add, sub, to_bytes, from_bytes, selectznz
+// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes
 //
-// n = 9 (from "9")
+// m = 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff (from "2^521 - 1")
 //
-// s-c = 2^521 - [(1, 1)] (from "2^521 - 1")
 //
-// tight_bounds_multiplier = 1 (from "")
 //
+// NOTE: In addition to the bounds specified above each function, all
 //
+//   functions synthesized for this Montgomery arithmetic require the
 //
-// Computed values:
+//   input to be strictly less than the prime modulus (m), and also
+//
+//   require the input to be in the unique saturated representation.
+//
+//   All functions also ensure that these two properties are true of
+//
+//   return values.
 //
-//   carry_chain = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1]
 //
-//   eval z = z[0] + (z[1] << 58) + (z[2] << 116) + (z[3] << 174) + (z[4] << 232) + (z[5] << 0x122) + (z[6] << 0x15c) + (z[7] << 0x196) + (z[8] << 0x1d0)
+//
+// Computed values:
+//
+//   eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) + (z[6] << 0x180) + (z[7] << 0x1c0) + (z[8] << 2^9)
 //
 //   bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178) + (z[48] << 0x180) + (z[49] << 0x188) + (z[50] << 0x190) + (z[51] << 0x198) + (z[52] << 0x1a0) + (z[53] << 0x1a8) + (z[54] << 0x1b0) + (z[55] << 0x1b8) + (z[56] << 0x1c0) + (z[57] << 0x1c8) + (z[58] << 0x1d0) + (z[59] << 0x1d8) + (z[60] << 0x1e0) + (z[61] << 0x1e8) + (z[62] << 0x1f0) + (z[63] << 0x1f8) + (z[64] << 2^9) + (z[65] << 0x208)
 //
-//   balance = [0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x3fffffffffffffe]
+//   twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) + (z[6] << 0x180) + (z[7] << 0x1c0) + (z[8] << 2^9) in
+//
+//                            if x1 & (2^576-1) < 2^575 then x1 & (2^576-1) else (x1 & (2^576-1)) - 2^576
 
 package fiat
 
 import "math/bits"
 
-type p521Uint1 uint8
-type p521Int1 int8
-
-// p521AddcarryxU64 is a thin wrapper around bits.Add64 that uses p521Uint1 rather than uint64
-func p521AddcarryxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) {
-       sum, carryOut := bits.Add64(x, y, uint64(carry))
-       return sum, p521Uint1(carryOut)
-}
-
-// p521SubborrowxU64 is a thin wrapper around bits.Sub64 that uses p521Uint1 rather than uint64
-func p521SubborrowxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) {
-       sum, carryOut := bits.Sub64(x, y, uint64(carry))
-       return sum, p521Uint1(carryOut)
-}
-
-// p521AddcarryxU58 is an addition with carry.
-//
-// Postconditions:
-//   out1 = (arg1 + arg2 + arg3) mod 2^58
-//   out2 = ⌊(arg1 + arg2 + arg3) / 2^58⌋
-//
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [0x0 ~> 0x3ffffffffffffff]
-//   arg3: [0x0 ~> 0x3ffffffffffffff]
-// Output Bounds:
-//   out1: [0x0 ~> 0x3ffffffffffffff]
-//   out2: [0x0 ~> 0x1]
-func p521AddcarryxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
-       x1 := ((uint64(arg1) + arg2) + arg3)
-       x2 := (x1 & 0x3ffffffffffffff)
-       x3 := p521Uint1((x1 >> 58))
-       *out1 = x2
-       *out2 = x3
-}
-
-// p521SubborrowxU58 is a subtraction with borrow.
-//
-// Postconditions:
-//   out1 = (-arg1 + arg2 + -arg3) mod 2^58
-//   out2 = -⌊(-arg1 + arg2 + -arg3) / 2^58⌋
-//
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [0x0 ~> 0x3ffffffffffffff]
-//   arg3: [0x0 ~> 0x3ffffffffffffff]
-// Output Bounds:
-//   out1: [0x0 ~> 0x3ffffffffffffff]
-//   out2: [0x0 ~> 0x1]
-func p521SubborrowxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
-       x1 := ((int64(arg2) - int64(arg1)) - int64(arg3))
-       x2 := p521Int1((x1 >> 58))
-       x3 := (uint64(x1) & 0x3ffffffffffffff)
-       *out1 = x3
-       *out2 = (0x0 - p521Uint1(x2))
-}
+type p521Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+type p521Int1 int64   // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
 
-// p521AddcarryxU57 is an addition with carry.
-//
-// Postconditions:
-//   out1 = (arg1 + arg2 + arg3) mod 2^57
-//   out2 = ⌊(arg1 + arg2 + arg3) / 2^57⌋
+// The type p521MontgomeryDomainFieldElement is a field element in the Montgomery domain.
 //
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [0x0 ~> 0x1ffffffffffffff]
-//   arg3: [0x0 ~> 0x1ffffffffffffff]
-// Output Bounds:
-//   out1: [0x0 ~> 0x1ffffffffffffff]
-//   out2: [0x0 ~> 0x1]
-func p521AddcarryxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
-       x1 := ((uint64(arg1) + arg2) + arg3)
-       x2 := (x1 & 0x1ffffffffffffff)
-       x3 := p521Uint1((x1 >> 57))
-       *out1 = x2
-       *out2 = x3
-}
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p521MontgomeryDomainFieldElement [9]uint64
 
-// p521SubborrowxU57 is a subtraction with borrow.
+// The type p521NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain.
 //
-// Postconditions:
-//   out1 = (-arg1 + arg2 + -arg3) mod 2^57
-//   out2 = -⌊(-arg1 + arg2 + -arg3) / 2^57⌋
-//
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [0x0 ~> 0x1ffffffffffffff]
-//   arg3: [0x0 ~> 0x1ffffffffffffff]
-// Output Bounds:
-//   out1: [0x0 ~> 0x1ffffffffffffff]
-//   out2: [0x0 ~> 0x1]
-func p521SubborrowxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
-       x1 := ((int64(arg2) - int64(arg1)) - int64(arg3))
-       x2 := p521Int1((x1 >> 57))
-       x3 := (uint64(x1) & 0x1ffffffffffffff)
-       *out1 = x3
-       *out2 = (0x0 - p521Uint1(x2))
-}
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p521NonMontgomeryDomainFieldElement [9]uint64
 
 // p521CmovznzU64 is a single-word conditional move.
 //
@@ -146,1229 +70,5083 @@ func p521CmovznzU64(out1 *uint64, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
        *out1 = x2
 }
 
-// p521CarryMul multiplies two field elements and reduces the result.
+// p521Mul multiplies two field elements in the Montgomery domain.
 //
+// Preconditions:
+//   0 ≤ eval arg1 < m
+//   0 ≤ eval arg2 < m
 // Postconditions:
-//   eval out1 mod m = (eval arg1 * eval arg2) mod m
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
+//   0 ≤ eval out1 < m
 //
-// Input Bounds:
-//   arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-//   arg2: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-func p521CarryMul(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
-       var x1 uint64
-       var x2 uint64
-       x2, x1 = bits.Mul64(arg1[8], (arg2[8] * 0x2))
-       var x3 uint64
-       var x4 uint64
-       x4, x3 = bits.Mul64(arg1[8], (arg2[7] * 0x2))
-       var x5 uint64
-       var x6 uint64
-       x6, x5 = bits.Mul64(arg1[8], (arg2[6] * 0x2))
-       var x7 uint64
-       var x8 uint64
-       x8, x7 = bits.Mul64(arg1[8], (arg2[5] * 0x2))
-       var x9 uint64
+func p521Mul(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[6]
+       x7 := arg1[7]
+       x8 := arg1[8]
+       x9 := arg1[0]
        var x10 uint64
-       x10, x9 = bits.Mul64(arg1[8], (arg2[4] * 0x2))
        var x11 uint64
+       x11, x10 = bits.Mul64(x9, arg2[8])
        var x12 uint64
-       x12, x11 = bits.Mul64(arg1[8], (arg2[3] * 0x2))
        var x13 uint64
+       x13, x12 = bits.Mul64(x9, arg2[7])
        var x14 uint64
-       x14, x13 = bits.Mul64(arg1[8], (arg2[2] * 0x2))
        var x15 uint64
+       x15, x14 = bits.Mul64(x9, arg2[6])
        var x16 uint64
-       x16, x15 = bits.Mul64(arg1[8], (arg2[1] * 0x2))
        var x17 uint64
+       x17, x16 = bits.Mul64(x9, arg2[5])
        var x18 uint64
-       x18, x17 = bits.Mul64(arg1[7], (arg2[8] * 0x2))
        var x19 uint64
+       x19, x18 = bits.Mul64(x9, arg2[4])
        var x20 uint64
-       x20, x19 = bits.Mul64(arg1[7], (arg2[7] * 0x2))
        var x21 uint64
+       x21, x20 = bits.Mul64(x9, arg2[3])
        var x22 uint64
-       x22, x21 = bits.Mul64(arg1[7], (arg2[6] * 0x2))
        var x23 uint64
+       x23, x22 = bits.Mul64(x9, arg2[2])
        var x24 uint64
-       x24, x23 = bits.Mul64(arg1[7], (arg2[5] * 0x2))
        var x25 uint64
+       x25, x24 = bits.Mul64(x9, arg2[1])
        var x26 uint64
-       x26, x25 = bits.Mul64(arg1[7], (arg2[4] * 0x2))
        var x27 uint64
+       x27, x26 = bits.Mul64(x9, arg2[0])
        var x28 uint64
-       x28, x27 = bits.Mul64(arg1[7], (arg2[3] * 0x2))
        var x29 uint64
+       x28, x29 = bits.Add64(x27, x24, uint64(0x0))
        var x30 uint64
-       x30, x29 = bits.Mul64(arg1[7], (arg2[2] * 0x2))
        var x31 uint64
+       x30, x31 = bits.Add64(x25, x22, uint64(p521Uint1(x29)))
        var x32 uint64
-       x32, x31 = bits.Mul64(arg1[6], (arg2[8] * 0x2))
        var x33 uint64
+       x32, x33 = bits.Add64(x23, x20, uint64(p521Uint1(x31)))
        var x34 uint64
-       x34, x33 = bits.Mul64(arg1[6], (arg2[7] * 0x2))
        var x35 uint64
+       x34, x35 = bits.Add64(x21, x18, uint64(p521Uint1(x33)))
        var x36 uint64
-       x36, x35 = bits.Mul64(arg1[6], (arg2[6] * 0x2))
        var x37 uint64
+       x36, x37 = bits.Add64(x19, x16, uint64(p521Uint1(x35)))
        var x38 uint64
-       x38, x37 = bits.Mul64(arg1[6], (arg2[5] * 0x2))
        var x39 uint64
+       x38, x39 = bits.Add64(x17, x14, uint64(p521Uint1(x37)))
        var x40 uint64
-       x40, x39 = bits.Mul64(arg1[6], (arg2[4] * 0x2))
        var x41 uint64
+       x40, x41 = bits.Add64(x15, x12, uint64(p521Uint1(x39)))
        var x42 uint64
-       x42, x41 = bits.Mul64(arg1[6], (arg2[3] * 0x2))
        var x43 uint64
-       var x44 uint64
-       x44, x43 = bits.Mul64(arg1[5], (arg2[8] * 0x2))
+       x42, x43 = bits.Add64(x13, x10, uint64(p521Uint1(x41)))
+       x44 := (uint64(p521Uint1(x43)) + x11)
        var x45 uint64
        var x46 uint64
-       x46, x45 = bits.Mul64(arg1[5], (arg2[7] * 0x2))
+       x46, x45 = bits.Mul64(x26, 0x1ff)
        var x47 uint64
        var x48 uint64
-       x48, x47 = bits.Mul64(arg1[5], (arg2[6] * 0x2))
+       x48, x47 = bits.Mul64(x26, 0xffffffffffffffff)
        var x49 uint64
        var x50 uint64
-       x50, x49 = bits.Mul64(arg1[5], (arg2[5] * 0x2))
+       x50, x49 = bits.Mul64(x26, 0xffffffffffffffff)
        var x51 uint64
        var x52 uint64
-       x52, x51 = bits.Mul64(arg1[5], (arg2[4] * 0x2))
+       x52, x51 = bits.Mul64(x26, 0xffffffffffffffff)
        var x53 uint64
        var x54 uint64
-       x54, x53 = bits.Mul64(arg1[4], (arg2[8] * 0x2))
+       x54, x53 = bits.Mul64(x26, 0xffffffffffffffff)
        var x55 uint64
        var x56 uint64
-       x56, x55 = bits.Mul64(arg1[4], (arg2[7] * 0x2))
+       x56, x55 = bits.Mul64(x26, 0xffffffffffffffff)
        var x57 uint64
        var x58 uint64
-       x58, x57 = bits.Mul64(arg1[4], (arg2[6] * 0x2))
+       x58, x57 = bits.Mul64(x26, 0xffffffffffffffff)
        var x59 uint64
        var x60 uint64
-       x60, x59 = bits.Mul64(arg1[4], (arg2[5] * 0x2))
+       x60, x59 = bits.Mul64(x26, 0xffffffffffffffff)
        var x61 uint64
        var x62 uint64
-       x62, x61 = bits.Mul64(arg1[3], (arg2[8] * 0x2))
+       x62, x61 = bits.Mul64(x26, 0xffffffffffffffff)
        var x63 uint64
        var x64 uint64
-       x64, x63 = bits.Mul64(arg1[3], (arg2[7] * 0x2))
+       x63, x64 = bits.Add64(x62, x59, uint64(0x0))
        var x65 uint64
        var x66 uint64
-       x66, x65 = bits.Mul64(arg1[3], (arg2[6] * 0x2))
+       x65, x66 = bits.Add64(x60, x57, uint64(p521Uint1(x64)))
        var x67 uint64
        var x68 uint64
-       x68, x67 = bits.Mul64(arg1[2], (arg2[8] * 0x2))
+       x67, x68 = bits.Add64(x58, x55, uint64(p521Uint1(x66)))
        var x69 uint64
        var x70 uint64
-       x70, x69 = bits.Mul64(arg1[2], (arg2[7] * 0x2))
+       x69, x70 = bits.Add64(x56, x53, uint64(p521Uint1(x68)))
        var x71 uint64
        var x72 uint64
-       x72, x71 = bits.Mul64(arg1[1], (arg2[8] * 0x2))
+       x71, x72 = bits.Add64(x54, x51, uint64(p521Uint1(x70)))
        var x73 uint64
        var x74 uint64
-       x74, x73 = bits.Mul64(arg1[8], arg2[0])
+       x73, x74 = bits.Add64(x52, x49, uint64(p521Uint1(x72)))
        var x75 uint64
        var x76 uint64
-       x76, x75 = bits.Mul64(arg1[7], arg2[1])
+       x75, x76 = bits.Add64(x50, x47, uint64(p521Uint1(x74)))
        var x77 uint64
        var x78 uint64
-       x78, x77 = bits.Mul64(arg1[7], arg2[0])
-       var x79 uint64
-       var x80 uint64
-       x80, x79 = bits.Mul64(arg1[6], arg2[2])
+       x77, x78 = bits.Add64(x48, x45, uint64(p521Uint1(x76)))
+       x79 := (uint64(p521Uint1(x78)) + x46)
        var x81 uint64
+       _, x81 = bits.Add64(x26, x61, uint64(0x0))
        var x82 uint64
-       x82, x81 = bits.Mul64(arg1[6], arg2[1])
        var x83 uint64
+       x82, x83 = bits.Add64(x28, x63, uint64(p521Uint1(x81)))
        var x84 uint64
-       x84, x83 = bits.Mul64(arg1[6], arg2[0])
        var x85 uint64
+       x84, x85 = bits.Add64(x30, x65, uint64(p521Uint1(x83)))
        var x86 uint64
-       x86, x85 = bits.Mul64(arg1[5], arg2[3])
        var x87 uint64
+       x86, x87 = bits.Add64(x32, x67, uint64(p521Uint1(x85)))
        var x88 uint64
-       x88, x87 = bits.Mul64(arg1[5], arg2[2])
        var x89 uint64
+       x88, x89 = bits.Add64(x34, x69, uint64(p521Uint1(x87)))
        var x90 uint64
-       x90, x89 = bits.Mul64(arg1[5], arg2[1])
        var x91 uint64
+       x90, x91 = bits.Add64(x36, x71, uint64(p521Uint1(x89)))
        var x92 uint64
-       x92, x91 = bits.Mul64(arg1[5], arg2[0])
        var x93 uint64
+       x92, x93 = bits.Add64(x38, x73, uint64(p521Uint1(x91)))
        var x94 uint64
-       x94, x93 = bits.Mul64(arg1[4], arg2[4])
        var x95 uint64
+       x94, x95 = bits.Add64(x40, x75, uint64(p521Uint1(x93)))
        var x96 uint64
-       x96, x95 = bits.Mul64(arg1[4], arg2[3])
        var x97 uint64
+       x96, x97 = bits.Add64(x42, x77, uint64(p521Uint1(x95)))
        var x98 uint64
-       x98, x97 = bits.Mul64(arg1[4], arg2[2])
        var x99 uint64
+       x98, x99 = bits.Add64(x44, x79, uint64(p521Uint1(x97)))
        var x100 uint64
-       x100, x99 = bits.Mul64(arg1[4], arg2[1])
        var x101 uint64
+       x101, x100 = bits.Mul64(x1, arg2[8])
        var x102 uint64
-       x102, x101 = bits.Mul64(arg1[4], arg2[0])
        var x103 uint64
+       x103, x102 = bits.Mul64(x1, arg2[7])
        var x104 uint64
-       x104, x103 = bits.Mul64(arg1[3], arg2[5])
        var x105 uint64
+       x105, x104 = bits.Mul64(x1, arg2[6])
        var x106 uint64
-       x106, x105 = bits.Mul64(arg1[3], arg2[4])
        var x107 uint64
+       x107, x106 = bits.Mul64(x1, arg2[5])
        var x108 uint64
-       x108, x107 = bits.Mul64(arg1[3], arg2[3])
        var x109 uint64
+       x109, x108 = bits.Mul64(x1, arg2[4])
        var x110 uint64
-       x110, x109 = bits.Mul64(arg1[3], arg2[2])
        var x111 uint64
+       x111, x110 = bits.Mul64(x1, arg2[3])
        var x112 uint64
-       x112, x111 = bits.Mul64(arg1[3], arg2[1])
        var x113 uint64
+       x113, x112 = bits.Mul64(x1, arg2[2])
        var x114 uint64
-       x114, x113 = bits.Mul64(arg1[3], arg2[0])
        var x115 uint64
+       x115, x114 = bits.Mul64(x1, arg2[1])
        var x116 uint64
-       x116, x115 = bits.Mul64(arg1[2], arg2[6])
        var x117 uint64
+       x117, x116 = bits.Mul64(x1, arg2[0])
        var x118 uint64
-       x118, x117 = bits.Mul64(arg1[2], arg2[5])
        var x119 uint64
+       x118, x119 = bits.Add64(x117, x114, uint64(0x0))
        var x120 uint64
-       x120, x119 = bits.Mul64(arg1[2], arg2[4])
        var x121 uint64
+       x120, x121 = bits.Add64(x115, x112, uint64(p521Uint1(x119)))
        var x122 uint64
-       x122, x121 = bits.Mul64(arg1[2], arg2[3])
        var x123 uint64
+       x122, x123 = bits.Add64(x113, x110, uint64(p521Uint1(x121)))
        var x124 uint64
-       x124, x123 = bits.Mul64(arg1[2], arg2[2])
        var x125 uint64
+       x124, x125 = bits.Add64(x111, x108, uint64(p521Uint1(x123)))
        var x126 uint64
-       x126, x125 = bits.Mul64(arg1[2], arg2[1])
        var x127 uint64
+       x126, x127 = bits.Add64(x109, x106, uint64(p521Uint1(x125)))
        var x128 uint64
-       x128, x127 = bits.Mul64(arg1[2], arg2[0])
        var x129 uint64
+       x128, x129 = bits.Add64(x107, x104, uint64(p521Uint1(x127)))
        var x130 uint64
-       x130, x129 = bits.Mul64(arg1[1], arg2[7])
        var x131 uint64
+       x130, x131 = bits.Add64(x105, x102, uint64(p521Uint1(x129)))
        var x132 uint64
-       x132, x131 = bits.Mul64(arg1[1], arg2[6])
        var x133 uint64
-       var x134 uint64
-       x134, x133 = bits.Mul64(arg1[1], arg2[5])
+       x132, x133 = bits.Add64(x103, x100, uint64(p521Uint1(x131)))
+       x134 := (uint64(p521Uint1(x133)) + x101)
        var x135 uint64
        var x136 uint64
-       x136, x135 = bits.Mul64(arg1[1], arg2[4])
+       x135, x136 = bits.Add64(x82, x116, uint64(0x0))
        var x137 uint64
        var x138 uint64
-       x138, x137 = bits.Mul64(arg1[1], arg2[3])
+       x137, x138 = bits.Add64(x84, x118, uint64(p521Uint1(x136)))
        var x139 uint64
        var x140 uint64
-       x140, x139 = bits.Mul64(arg1[1], arg2[2])
+       x139, x140 = bits.Add64(x86, x120, uint64(p521Uint1(x138)))
        var x141 uint64
        var x142 uint64
-       x142, x141 = bits.Mul64(arg1[1], arg2[1])
+       x141, x142 = bits.Add64(x88, x122, uint64(p521Uint1(x140)))
        var x143 uint64
        var x144 uint64
-       x144, x143 = bits.Mul64(arg1[1], arg2[0])
+       x143, x144 = bits.Add64(x90, x124, uint64(p521Uint1(x142)))
        var x145 uint64
        var x146 uint64
-       x146, x145 = bits.Mul64(arg1[0], arg2[8])
+       x145, x146 = bits.Add64(x92, x126, uint64(p521Uint1(x144)))
        var x147 uint64
        var x148 uint64
-       x148, x147 = bits.Mul64(arg1[0], arg2[7])
+       x147, x148 = bits.Add64(x94, x128, uint64(p521Uint1(x146)))
        var x149 uint64
        var x150 uint64
-       x150, x149 = bits.Mul64(arg1[0], arg2[6])
+       x149, x150 = bits.Add64(x96, x130, uint64(p521Uint1(x148)))
        var x151 uint64
        var x152 uint64
-       x152, x151 = bits.Mul64(arg1[0], arg2[5])
+       x151, x152 = bits.Add64(x98, x132, uint64(p521Uint1(x150)))
        var x153 uint64
        var x154 uint64
-       x154, x153 = bits.Mul64(arg1[0], arg2[4])
+       x153, x154 = bits.Add64(uint64(p521Uint1(x99)), x134, uint64(p521Uint1(x152)))
        var x155 uint64
        var x156 uint64
-       x156, x155 = bits.Mul64(arg1[0], arg2[3])
+       x156, x155 = bits.Mul64(x135, 0x1ff)
        var x157 uint64
        var x158 uint64
-       x158, x157 = bits.Mul64(arg1[0], arg2[2])
+       x158, x157 = bits.Mul64(x135, 0xffffffffffffffff)
        var x159 uint64
        var x160 uint64
-       x160, x159 = bits.Mul64(arg1[0], arg2[1])
+       x160, x159 = bits.Mul64(x135, 0xffffffffffffffff)
        var x161 uint64
        var x162 uint64
-       x162, x161 = bits.Mul64(arg1[0], arg2[0])
+       x162, x161 = bits.Mul64(x135, 0xffffffffffffffff)
        var x163 uint64
-       var x164 p521Uint1
-       x163, x164 = p521AddcarryxU64(x29, x15, 0x0)
+       var x164 uint64
+       x164, x163 = bits.Mul64(x135, 0xffffffffffffffff)
        var x165 uint64
-       x165, _ = p521AddcarryxU64(x30, x16, x164)
+       var x166 uint64
+       x166, x165 = bits.Mul64(x135, 0xffffffffffffffff)
        var x167 uint64
-       var x168 p521Uint1
-       x167, x168 = p521AddcarryxU64(x41, x163, 0x0)
+       var x168 uint64
+       x168, x167 = bits.Mul64(x135, 0xffffffffffffffff)
        var x169 uint64
-       x169, _ = p521AddcarryxU64(x42, x165, x168)
+       var x170 uint64
+       x170, x169 = bits.Mul64(x135, 0xffffffffffffffff)
        var x171 uint64
-       var x172 p521Uint1
-       x171, x172 = p521AddcarryxU64(x51, x167, 0x0)
+       var x172 uint64
+       x172, x171 = bits.Mul64(x135, 0xffffffffffffffff)
        var x173 uint64
-       x173, _ = p521AddcarryxU64(x52, x169, x172)
+       var x174 uint64
+       x173, x174 = bits.Add64(x172, x169, uint64(0x0))
        var x175 uint64
-       var x176 p521Uint1
-       x175, x176 = p521AddcarryxU64(x59, x171, 0x0)
+       var x176 uint64
+       x175, x176 = bits.Add64(x170, x167, uint64(p521Uint1(x174)))
        var x177 uint64
-       x177, _ = p521AddcarryxU64(x60, x173, x176)
+       var x178 uint64
+       x177, x178 = bits.Add64(x168, x165, uint64(p521Uint1(x176)))
        var x179 uint64
-       var x180 p521Uint1
-       x179, x180 = p521AddcarryxU64(x65, x175, 0x0)
+       var x180 uint64
+       x179, x180 = bits.Add64(x166, x163, uint64(p521Uint1(x178)))
        var x181 uint64
-       x181, _ = p521AddcarryxU64(x66, x177, x180)
+       var x182 uint64
+       x181, x182 = bits.Add64(x164, x161, uint64(p521Uint1(x180)))
        var x183 uint64
-       var x184 p521Uint1
-       x183, x184 = p521AddcarryxU64(x69, x179, 0x0)
+       var x184 uint64
+       x183, x184 = bits.Add64(x162, x159, uint64(p521Uint1(x182)))
        var x185 uint64
-       x185, _ = p521AddcarryxU64(x70, x181, x184)
+       var x186 uint64
+       x185, x186 = bits.Add64(x160, x157, uint64(p521Uint1(x184)))
        var x187 uint64
-       var x188 p521Uint1
-       x187, x188 = p521AddcarryxU64(x71, x183, 0x0)
-       var x189 uint64
-       x189, _ = p521AddcarryxU64(x72, x185, x188)
+       var x188 uint64
+       x187, x188 = bits.Add64(x158, x155, uint64(p521Uint1(x186)))
+       x189 := (uint64(p521Uint1(x188)) + x156)
        var x191 uint64
-       var x192 p521Uint1
-       x191, x192 = p521AddcarryxU64(x161, x187, 0x0)
+       _, x191 = bits.Add64(x135, x171, uint64(0x0))
+       var x192 uint64
        var x193 uint64
-       x193, _ = p521AddcarryxU64(x162, x189, x192)
-       x195 := ((x191 >> 58) | ((x193 << 6) & 0xffffffffffffffff))
-       x196 := (x193 >> 58)
-       x197 := (x191 & 0x3ffffffffffffff)
+       x192, x193 = bits.Add64(x137, x173, uint64(p521Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Add64(x139, x175, uint64(p521Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Add64(x141, x177, uint64(p521Uint1(x195)))
        var x198 uint64
-       var x199 p521Uint1
-       x198, x199 = p521AddcarryxU64(x75, x73, 0x0)
+       var x199 uint64
+       x198, x199 = bits.Add64(x143, x179, uint64(p521Uint1(x197)))
        var x200 uint64
-       x200, _ = p521AddcarryxU64(x76, x74, x199)
+       var x201 uint64
+       x200, x201 = bits.Add64(x145, x181, uint64(p521Uint1(x199)))
        var x202 uint64
-       var x203 p521Uint1
-       x202, x203 = p521AddcarryxU64(x79, x198, 0x0)
+       var x203 uint64
+       x202, x203 = bits.Add64(x147, x183, uint64(p521Uint1(x201)))
        var x204 uint64
-       x204, _ = p521AddcarryxU64(x80, x200, x203)
+       var x205 uint64
+       x204, x205 = bits.Add64(x149, x185, uint64(p521Uint1(x203)))
        var x206 uint64
-       var x207 p521Uint1
-       x206, x207 = p521AddcarryxU64(x85, x202, 0x0)
+       var x207 uint64
+       x206, x207 = bits.Add64(x151, x187, uint64(p521Uint1(x205)))
        var x208 uint64
-       x208, _ = p521AddcarryxU64(x86, x204, x207)
-       var x210 uint64
-       var x211 p521Uint1
-       x210, x211 = p521AddcarryxU64(x93, x206, 0x0)
+       var x209 uint64
+       x208, x209 = bits.Add64(x153, x189, uint64(p521Uint1(x207)))
+       x210 := (uint64(p521Uint1(x209)) + uint64(p521Uint1(x154)))
+       var x211 uint64
        var x212 uint64
-       x212, _ = p521AddcarryxU64(x94, x208, x211)
+       x212, x211 = bits.Mul64(x2, arg2[8])
+       var x213 uint64
        var x214 uint64
-       var x215 p521Uint1
-       x214, x215 = p521AddcarryxU64(x103, x210, 0x0)
+       x214, x213 = bits.Mul64(x2, arg2[7])
+       var x215 uint64
        var x216 uint64
-       x216, _ = p521AddcarryxU64(x104, x212, x215)
+       x216, x215 = bits.Mul64(x2, arg2[6])
+       var x217 uint64
        var x218 uint64
-       var x219 p521Uint1
-       x218, x219 = p521AddcarryxU64(x115, x214, 0x0)
+       x218, x217 = bits.Mul64(x2, arg2[5])
+       var x219 uint64
        var x220 uint64
-       x220, _ = p521AddcarryxU64(x116, x216, x219)
+       x220, x219 = bits.Mul64(x2, arg2[4])
+       var x221 uint64
        var x222 uint64
-       var x223 p521Uint1
-       x222, x223 = p521AddcarryxU64(x129, x218, 0x0)
+       x222, x221 = bits.Mul64(x2, arg2[3])
+       var x223 uint64
        var x224 uint64
-       x224, _ = p521AddcarryxU64(x130, x220, x223)
+       x224, x223 = bits.Mul64(x2, arg2[2])
+       var x225 uint64
        var x226 uint64
-       var x227 p521Uint1
-       x226, x227 = p521AddcarryxU64(x145, x222, 0x0)
+       x226, x225 = bits.Mul64(x2, arg2[1])
+       var x227 uint64
        var x228 uint64
-       x228, _ = p521AddcarryxU64(x146, x224, x227)
+       x228, x227 = bits.Mul64(x2, arg2[0])
+       var x229 uint64
        var x230 uint64
-       var x231 p521Uint1
-       x230, x231 = p521AddcarryxU64(x77, x1, 0x0)
+       x229, x230 = bits.Add64(x228, x225, uint64(0x0))
+       var x231 uint64
        var x232 uint64
-       x232, _ = p521AddcarryxU64(x78, x2, x231)
+       x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230)))
+       var x233 uint64
        var x234 uint64
-       var x235 p521Uint1
-       x234, x235 = p521AddcarryxU64(x81, x230, 0x0)
+       x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232)))
+       var x235 uint64
        var x236 uint64
-       x236, _ = p521AddcarryxU64(x82, x232, x235)
+       x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234)))
+       var x237 uint64
        var x238 uint64
-       var x239 p521Uint1
-       x238, x239 = p521AddcarryxU64(x87, x234, 0x0)
+       x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236)))
+       var x239 uint64
        var x240 uint64
-       x240, _ = p521AddcarryxU64(x88, x236, x239)
+       x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238)))
+       var x241 uint64
        var x242 uint64
-       var x243 p521Uint1
-       x242, x243 = p521AddcarryxU64(x95, x238, 0x0)
+       x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240)))
+       var x243 uint64
        var x244 uint64
-       x244, _ = p521AddcarryxU64(x96, x240, x243)
+       x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242)))
+       x245 := (uint64(p521Uint1(x244)) + x212)
        var x246 uint64
-       var x247 p521Uint1
-       x246, x247 = p521AddcarryxU64(x105, x242, 0x0)
+       var x247 uint64
+       x246, x247 = bits.Add64(x192, x227, uint64(0x0))
        var x248 uint64
-       x248, _ = p521AddcarryxU64(x106, x244, x247)
+       var x249 uint64
+       x248, x249 = bits.Add64(x194, x229, uint64(p521Uint1(x247)))
        var x250 uint64
-       var x251 p521Uint1
-       x250, x251 = p521AddcarryxU64(x117, x246, 0x0)
+       var x251 uint64
+       x250, x251 = bits.Add64(x196, x231, uint64(p521Uint1(x249)))
        var x252 uint64
-       x252, _ = p521AddcarryxU64(x118, x248, x251)
+       var x253 uint64
+       x252, x253 = bits.Add64(x198, x233, uint64(p521Uint1(x251)))
        var x254 uint64
-       var x255 p521Uint1
-       x254, x255 = p521AddcarryxU64(x131, x250, 0x0)
+       var x255 uint64
+       x254, x255 = bits.Add64(x200, x235, uint64(p521Uint1(x253)))
        var x256 uint64
-       x256, _ = p521AddcarryxU64(x132, x252, x255)
+       var x257 uint64
+       x256, x257 = bits.Add64(x202, x237, uint64(p521Uint1(x255)))
        var x258 uint64
-       var x259 p521Uint1
-       x258, x259 = p521AddcarryxU64(x147, x254, 0x0)
+       var x259 uint64
+       x258, x259 = bits.Add64(x204, x239, uint64(p521Uint1(x257)))
        var x260 uint64
-       x260, _ = p521AddcarryxU64(x148, x256, x259)
+       var x261 uint64
+       x260, x261 = bits.Add64(x206, x241, uint64(p521Uint1(x259)))
        var x262 uint64
-       var x263 p521Uint1
-       x262, x263 = p521AddcarryxU64(x17, x3, 0x0)
+       var x263 uint64
+       x262, x263 = bits.Add64(x208, x243, uint64(p521Uint1(x261)))
        var x264 uint64
-       x264, _ = p521AddcarryxU64(x18, x4, x263)
+       var x265 uint64
+       x264, x265 = bits.Add64(x210, x245, uint64(p521Uint1(x263)))
        var x266 uint64
-       var x267 p521Uint1
-       x266, x267 = p521AddcarryxU64(x83, x262, 0x0)
+       var x267 uint64
+       x267, x266 = bits.Mul64(x246, 0x1ff)
        var x268 uint64
-       x268, _ = p521AddcarryxU64(x84, x264, x267)
+       var x269 uint64
+       x269, x268 = bits.Mul64(x246, 0xffffffffffffffff)
        var x270 uint64
-       var x271 p521Uint1
-       x270, x271 = p521AddcarryxU64(x89, x266, 0x0)
+       var x271 uint64
+       x271, x270 = bits.Mul64(x246, 0xffffffffffffffff)
        var x272 uint64
-       x272, _ = p521AddcarryxU64(x90, x268, x271)
+       var x273 uint64
+       x273, x272 = bits.Mul64(x246, 0xffffffffffffffff)
        var x274 uint64
-       var x275 p521Uint1
-       x274, x275 = p521AddcarryxU64(x97, x270, 0x0)
+       var x275 uint64
+       x275, x274 = bits.Mul64(x246, 0xffffffffffffffff)
        var x276 uint64
-       x276, _ = p521AddcarryxU64(x98, x272, x275)
+       var x277 uint64
+       x277, x276 = bits.Mul64(x246, 0xffffffffffffffff)
        var x278 uint64
-       var x279 p521Uint1
-       x278, x279 = p521AddcarryxU64(x107, x274, 0x0)
+       var x279 uint64
+       x279, x278 = bits.Mul64(x246, 0xffffffffffffffff)
        var x280 uint64
-       x280, _ = p521AddcarryxU64(x108, x276, x279)
+       var x281 uint64
+       x281, x280 = bits.Mul64(x246, 0xffffffffffffffff)
        var x282 uint64
-       var x283 p521Uint1
-       x282, x283 = p521AddcarryxU64(x119, x278, 0x0)
+       var x283 uint64
+       x283, x282 = bits.Mul64(x246, 0xffffffffffffffff)
        var x284 uint64
-       x284, _ = p521AddcarryxU64(x120, x280, x283)
+       var x285 uint64
+       x284, x285 = bits.Add64(x283, x280, uint64(0x0))
        var x286 uint64
-       var x287 p521Uint1
-       x286, x287 = p521AddcarryxU64(x133, x282, 0x0)
+       var x287 uint64
+       x286, x287 = bits.Add64(x281, x278, uint64(p521Uint1(x285)))
        var x288 uint64
-       x288, _ = p521AddcarryxU64(x134, x284, x287)
+       var x289 uint64
+       x288, x289 = bits.Add64(x279, x276, uint64(p521Uint1(x287)))
        var x290 uint64
-       var x291 p521Uint1
-       x290, x291 = p521AddcarryxU64(x149, x286, 0x0)
+       var x291 uint64
+       x290, x291 = bits.Add64(x277, x274, uint64(p521Uint1(x289)))
        var x292 uint64
-       x292, _ = p521AddcarryxU64(x150, x288, x291)
+       var x293 uint64
+       x292, x293 = bits.Add64(x275, x272, uint64(p521Uint1(x291)))
        var x294 uint64
-       var x295 p521Uint1
-       x294, x295 = p521AddcarryxU64(x19, x5, 0x0)
+       var x295 uint64
+       x294, x295 = bits.Add64(x273, x270, uint64(p521Uint1(x293)))
        var x296 uint64
-       x296, _ = p521AddcarryxU64(x20, x6, x295)
+       var x297 uint64
+       x296, x297 = bits.Add64(x271, x268, uint64(p521Uint1(x295)))
        var x298 uint64
-       var x299 p521Uint1
-       x298, x299 = p521AddcarryxU64(x31, x294, 0x0)
-       var x300 uint64
-       x300, _ = p521AddcarryxU64(x32, x296, x299)
+       var x299 uint64
+       x298, x299 = bits.Add64(x269, x266, uint64(p521Uint1(x297)))
+       x300 := (uint64(p521Uint1(x299)) + x267)
        var x302 uint64
-       var x303 p521Uint1
-       x302, x303 = p521AddcarryxU64(x91, x298, 0x0)
+       _, x302 = bits.Add64(x246, x282, uint64(0x0))
+       var x303 uint64
        var x304 uint64
-       x304, _ = p521AddcarryxU64(x92, x300, x303)
+       x303, x304 = bits.Add64(x248, x284, uint64(p521Uint1(x302)))
+       var x305 uint64
        var x306 uint64
-       var x307 p521Uint1
-       x306, x307 = p521AddcarryxU64(x99, x302, 0x0)
+       x305, x306 = bits.Add64(x250, x286, uint64(p521Uint1(x304)))
+       var x307 uint64
        var x308 uint64
-       x308, _ = p521AddcarryxU64(x100, x304, x307)
+       x307, x308 = bits.Add64(x252, x288, uint64(p521Uint1(x306)))
+       var x309 uint64
        var x310 uint64
-       var x311 p521Uint1
-       x310, x311 = p521AddcarryxU64(x109, x306, 0x0)
+       x309, x310 = bits.Add64(x254, x290, uint64(p521Uint1(x308)))
+       var x311 uint64
        var x312 uint64
-       x312, _ = p521AddcarryxU64(x110, x308, x311)
+       x311, x312 = bits.Add64(x256, x292, uint64(p521Uint1(x310)))
+       var x313 uint64
        var x314 uint64
-       var x315 p521Uint1
-       x314, x315 = p521AddcarryxU64(x121, x310, 0x0)
+       x313, x314 = bits.Add64(x258, x294, uint64(p521Uint1(x312)))
+       var x315 uint64
        var x316 uint64
-       x316, _ = p521AddcarryxU64(x122, x312, x315)
+       x315, x316 = bits.Add64(x260, x296, uint64(p521Uint1(x314)))
+       var x317 uint64
        var x318 uint64
-       var x319 p521Uint1
-       x318, x319 = p521AddcarryxU64(x135, x314, 0x0)
+       x317, x318 = bits.Add64(x262, x298, uint64(p521Uint1(x316)))
+       var x319 uint64
        var x320 uint64
-       x320, _ = p521AddcarryxU64(x136, x316, x319)
+       x319, x320 = bits.Add64(x264, x300, uint64(p521Uint1(x318)))
+       x321 := (uint64(p521Uint1(x320)) + uint64(p521Uint1(x265)))
        var x322 uint64
-       var x323 p521Uint1
-       x322, x323 = p521AddcarryxU64(x151, x318, 0x0)
+       var x323 uint64
+       x323, x322 = bits.Mul64(x3, arg2[8])
        var x324 uint64
-       x324, _ = p521AddcarryxU64(x152, x320, x323)
+       var x325 uint64
+       x325, x324 = bits.Mul64(x3, arg2[7])
        var x326 uint64
-       var x327 p521Uint1
-       x326, x327 = p521AddcarryxU64(x21, x7, 0x0)
+       var x327 uint64
+       x327, x326 = bits.Mul64(x3, arg2[6])
        var x328 uint64
-       x328, _ = p521AddcarryxU64(x22, x8, x327)
+       var x329 uint64
+       x329, x328 = bits.Mul64(x3, arg2[5])
        var x330 uint64
-       var x331 p521Uint1
-       x330, x331 = p521AddcarryxU64(x33, x326, 0x0)
+       var x331 uint64
+       x331, x330 = bits.Mul64(x3, arg2[4])
        var x332 uint64
-       x332, _ = p521AddcarryxU64(x34, x328, x331)
+       var x333 uint64
+       x333, x332 = bits.Mul64(x3, arg2[3])
        var x334 uint64
-       var x335 p521Uint1
-       x334, x335 = p521AddcarryxU64(x43, x330, 0x0)
+       var x335 uint64
+       x335, x334 = bits.Mul64(x3, arg2[2])
        var x336 uint64
-       x336, _ = p521AddcarryxU64(x44, x332, x335)
+       var x337 uint64
+       x337, x336 = bits.Mul64(x3, arg2[1])
        var x338 uint64
-       var x339 p521Uint1
-       x338, x339 = p521AddcarryxU64(x101, x334, 0x0)
+       var x339 uint64
+       x339, x338 = bits.Mul64(x3, arg2[0])
        var x340 uint64
-       x340, _ = p521AddcarryxU64(x102, x336, x339)
+       var x341 uint64
+       x340, x341 = bits.Add64(x339, x336, uint64(0x0))
        var x342 uint64
-       var x343 p521Uint1
-       x342, x343 = p521AddcarryxU64(x111, x338, 0x0)
+       var x343 uint64
+       x342, x343 = bits.Add64(x337, x334, uint64(p521Uint1(x341)))
        var x344 uint64
-       x344, _ = p521AddcarryxU64(x112, x340, x343)
+       var x345 uint64
+       x344, x345 = bits.Add64(x335, x332, uint64(p521Uint1(x343)))
        var x346 uint64
-       var x347 p521Uint1
-       x346, x347 = p521AddcarryxU64(x123, x342, 0x0)
+       var x347 uint64
+       x346, x347 = bits.Add64(x333, x330, uint64(p521Uint1(x345)))
        var x348 uint64
-       x348, _ = p521AddcarryxU64(x124, x344, x347)
+       var x349 uint64
+       x348, x349 = bits.Add64(x331, x328, uint64(p521Uint1(x347)))
        var x350 uint64
-       var x351 p521Uint1
-       x350, x351 = p521AddcarryxU64(x137, x346, 0x0)
+       var x351 uint64
+       x350, x351 = bits.Add64(x329, x326, uint64(p521Uint1(x349)))
        var x352 uint64
-       x352, _ = p521AddcarryxU64(x138, x348, x351)
+       var x353 uint64
+       x352, x353 = bits.Add64(x327, x324, uint64(p521Uint1(x351)))
        var x354 uint64
-       var x355 p521Uint1
-       x354, x355 = p521AddcarryxU64(x153, x350, 0x0)
-       var x356 uint64
-       x356, _ = p521AddcarryxU64(x154, x352, x355)
+       var x355 uint64
+       x354, x355 = bits.Add64(x325, x322, uint64(p521Uint1(x353)))
+       x356 := (uint64(p521Uint1(x355)) + x323)
+       var x357 uint64
        var x358 uint64
-       var x359 p521Uint1
-       x358, x359 = p521AddcarryxU64(x23, x9, 0x0)
+       x357, x358 = bits.Add64(x303, x338, uint64(0x0))
+       var x359 uint64
        var x360 uint64
-       x360, _ = p521AddcarryxU64(x24, x10, x359)
+       x359, x360 = bits.Add64(x305, x340, uint64(p521Uint1(x358)))
+       var x361 uint64
        var x362 uint64
-       var x363 p521Uint1
-       x362, x363 = p521AddcarryxU64(x35, x358, 0x0)
+       x361, x362 = bits.Add64(x307, x342, uint64(p521Uint1(x360)))
+       var x363 uint64
        var x364 uint64
-       x364, _ = p521AddcarryxU64(x36, x360, x363)
+       x363, x364 = bits.Add64(x309, x344, uint64(p521Uint1(x362)))
+       var x365 uint64
        var x366 uint64
-       var x367 p521Uint1
-       x366, x367 = p521AddcarryxU64(x45, x362, 0x0)
+       x365, x366 = bits.Add64(x311, x346, uint64(p521Uint1(x364)))
+       var x367 uint64
        var x368 uint64
-       x368, _ = p521AddcarryxU64(x46, x364, x367)
+       x367, x368 = bits.Add64(x313, x348, uint64(p521Uint1(x366)))
+       var x369 uint64
        var x370 uint64
-       var x371 p521Uint1
-       x370, x371 = p521AddcarryxU64(x53, x366, 0x0)
+       x369, x370 = bits.Add64(x315, x350, uint64(p521Uint1(x368)))
+       var x371 uint64
        var x372 uint64
-       x372, _ = p521AddcarryxU64(x54, x368, x371)
+       x371, x372 = bits.Add64(x317, x352, uint64(p521Uint1(x370)))
+       var x373 uint64
        var x374 uint64
-       var x375 p521Uint1
-       x374, x375 = p521AddcarryxU64(x113, x370, 0x0)
+       x373, x374 = bits.Add64(x319, x354, uint64(p521Uint1(x372)))
+       var x375 uint64
        var x376 uint64
-       x376, _ = p521AddcarryxU64(x114, x372, x375)
+       x375, x376 = bits.Add64(x321, x356, uint64(p521Uint1(x374)))
+       var x377 uint64
        var x378 uint64
-       var x379 p521Uint1
-       x378, x379 = p521AddcarryxU64(x125, x374, 0x0)
+       x378, x377 = bits.Mul64(x357, 0x1ff)
+       var x379 uint64
        var x380 uint64
-       x380, _ = p521AddcarryxU64(x126, x376, x379)
+       x380, x379 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x381 uint64
        var x382 uint64
-       var x383 p521Uint1
-       x382, x383 = p521AddcarryxU64(x139, x378, 0x0)
+       x382, x381 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x383 uint64
        var x384 uint64
-       x384, _ = p521AddcarryxU64(x140, x380, x383)
+       x384, x383 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x385 uint64
        var x386 uint64
-       var x387 p521Uint1
-       x386, x387 = p521AddcarryxU64(x155, x382, 0x0)
+       x386, x385 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x387 uint64
        var x388 uint64
-       x388, _ = p521AddcarryxU64(x156, x384, x387)
+       x388, x387 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x389 uint64
        var x390 uint64
-       var x391 p521Uint1
-       x390, x391 = p521AddcarryxU64(x25, x11, 0x0)
+       x390, x389 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x391 uint64
        var x392 uint64
-       x392, _ = p521AddcarryxU64(x26, x12, x391)
+       x392, x391 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x393 uint64
        var x394 uint64
-       var x395 p521Uint1
-       x394, x395 = p521AddcarryxU64(x37, x390, 0x0)
+       x394, x393 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x395 uint64
        var x396 uint64
-       x396, _ = p521AddcarryxU64(x38, x392, x395)
+       x395, x396 = bits.Add64(x394, x391, uint64(0x0))
+       var x397 uint64
        var x398 uint64
-       var x399 p521Uint1
-       x398, x399 = p521AddcarryxU64(x47, x394, 0x0)
+       x397, x398 = bits.Add64(x392, x389, uint64(p521Uint1(x396)))
+       var x399 uint64
        var x400 uint64
-       x400, _ = p521AddcarryxU64(x48, x396, x399)
+       x399, x400 = bits.Add64(x390, x387, uint64(p521Uint1(x398)))
+       var x401 uint64
        var x402 uint64
-       var x403 p521Uint1
-       x402, x403 = p521AddcarryxU64(x55, x398, 0x0)
+       x401, x402 = bits.Add64(x388, x385, uint64(p521Uint1(x400)))
+       var x403 uint64
        var x404 uint64
-       x404, _ = p521AddcarryxU64(x56, x400, x403)
+       x403, x404 = bits.Add64(x386, x383, uint64(p521Uint1(x402)))
+       var x405 uint64
        var x406 uint64
-       var x407 p521Uint1
-       x406, x407 = p521AddcarryxU64(x61, x402, 0x0)
+       x405, x406 = bits.Add64(x384, x381, uint64(p521Uint1(x404)))
+       var x407 uint64
        var x408 uint64
-       x408, _ = p521AddcarryxU64(x62, x404, x407)
+       x407, x408 = bits.Add64(x382, x379, uint64(p521Uint1(x406)))
+       var x409 uint64
        var x410 uint64
-       var x411 p521Uint1
-       x410, x411 = p521AddcarryxU64(x127, x406, 0x0)
-       var x412 uint64
-       x412, _ = p521AddcarryxU64(x128, x408, x411)
+       x409, x410 = bits.Add64(x380, x377, uint64(p521Uint1(x408)))
+       x411 := (uint64(p521Uint1(x410)) + x378)
+       var x413 uint64
+       _, x413 = bits.Add64(x357, x393, uint64(0x0))
        var x414 uint64
-       var x415 p521Uint1
-       x414, x415 = p521AddcarryxU64(x141, x410, 0x0)
+       var x415 uint64
+       x414, x415 = bits.Add64(x359, x395, uint64(p521Uint1(x413)))
        var x416 uint64
-       x416, _ = p521AddcarryxU64(x142, x412, x415)
+       var x417 uint64
+       x416, x417 = bits.Add64(x361, x397, uint64(p521Uint1(x415)))
        var x418 uint64
-       var x419 p521Uint1
-       x418, x419 = p521AddcarryxU64(x157, x414, 0x0)
+       var x419 uint64
+       x418, x419 = bits.Add64(x363, x399, uint64(p521Uint1(x417)))
        var x420 uint64
-       x420, _ = p521AddcarryxU64(x158, x416, x419)
+       var x421 uint64
+       x420, x421 = bits.Add64(x365, x401, uint64(p521Uint1(x419)))
        var x422 uint64
-       var x423 p521Uint1
-       x422, x423 = p521AddcarryxU64(x27, x13, 0x0)
+       var x423 uint64
+       x422, x423 = bits.Add64(x367, x403, uint64(p521Uint1(x421)))
        var x424 uint64
-       x424, _ = p521AddcarryxU64(x28, x14, x423)
+       var x425 uint64
+       x424, x425 = bits.Add64(x369, x405, uint64(p521Uint1(x423)))
        var x426 uint64
-       var x427 p521Uint1
-       x426, x427 = p521AddcarryxU64(x39, x422, 0x0)
+       var x427 uint64
+       x426, x427 = bits.Add64(x371, x407, uint64(p521Uint1(x425)))
        var x428 uint64
-       x428, _ = p521AddcarryxU64(x40, x424, x427)
+       var x429 uint64
+       x428, x429 = bits.Add64(x373, x409, uint64(p521Uint1(x427)))
        var x430 uint64
-       var x431 p521Uint1
-       x430, x431 = p521AddcarryxU64(x49, x426, 0x0)
-       var x432 uint64
-       x432, _ = p521AddcarryxU64(x50, x428, x431)
+       var x431 uint64
+       x430, x431 = bits.Add64(x375, x411, uint64(p521Uint1(x429)))
+       x432 := (uint64(p521Uint1(x431)) + uint64(p521Uint1(x376)))
+       var x433 uint64
        var x434 uint64
-       var x435 p521Uint1
-       x434, x435 = p521AddcarryxU64(x57, x430, 0x0)
+       x434, x433 = bits.Mul64(x4, arg2[8])
+       var x435 uint64
        var x436 uint64
-       x436, _ = p521AddcarryxU64(x58, x432, x435)
+       x436, x435 = bits.Mul64(x4, arg2[7])
+       var x437 uint64
        var x438 uint64
-       var x439 p521Uint1
-       x438, x439 = p521AddcarryxU64(x63, x434, 0x0)
+       x438, x437 = bits.Mul64(x4, arg2[6])
+       var x439 uint64
        var x440 uint64
-       x440, _ = p521AddcarryxU64(x64, x436, x439)
+       x440, x439 = bits.Mul64(x4, arg2[5])
+       var x441 uint64
        var x442 uint64
-       var x443 p521Uint1
-       x442, x443 = p521AddcarryxU64(x67, x438, 0x0)
+       x442, x441 = bits.Mul64(x4, arg2[4])
+       var x443 uint64
        var x444 uint64
-       x444, _ = p521AddcarryxU64(x68, x440, x443)
+       x444, x443 = bits.Mul64(x4, arg2[3])
+       var x445 uint64
        var x446 uint64
-       var x447 p521Uint1
-       x446, x447 = p521AddcarryxU64(x143, x442, 0x0)
+       x446, x445 = bits.Mul64(x4, arg2[2])
+       var x447 uint64
        var x448 uint64
-       x448, _ = p521AddcarryxU64(x144, x444, x447)
+       x448, x447 = bits.Mul64(x4, arg2[1])
+       var x449 uint64
        var x450 uint64
-       var x451 p521Uint1
-       x450, x451 = p521AddcarryxU64(x159, x446, 0x0)
+       x450, x449 = bits.Mul64(x4, arg2[0])
+       var x451 uint64
        var x452 uint64
-       x452, _ = p521AddcarryxU64(x160, x448, x451)
+       x451, x452 = bits.Add64(x450, x447, uint64(0x0))
+       var x453 uint64
        var x454 uint64
-       var x455 p521Uint1
-       x454, x455 = p521AddcarryxU64(x195, x450, 0x0)
+       x453, x454 = bits.Add64(x448, x445, uint64(p521Uint1(x452)))
+       var x455 uint64
        var x456 uint64
-       x456, _ = p521AddcarryxU64(x196, x452, x455)
-       x458 := ((x454 >> 58) | ((x456 << 6) & 0xffffffffffffffff))
-       x459 := (x456 >> 58)
-       x460 := (x454 & 0x3ffffffffffffff)
+       x455, x456 = bits.Add64(x446, x443, uint64(p521Uint1(x454)))
+       var x457 uint64
+       var x458 uint64
+       x457, x458 = bits.Add64(x444, x441, uint64(p521Uint1(x456)))
+       var x459 uint64
+       var x460 uint64
+       x459, x460 = bits.Add64(x442, x439, uint64(p521Uint1(x458)))
        var x461 uint64
-       var x462 p521Uint1
-       x461, x462 = p521AddcarryxU64(x458, x418, 0x0)
+       var x462 uint64
+       x461, x462 = bits.Add64(x440, x437, uint64(p521Uint1(x460)))
        var x463 uint64
-       x463, _ = p521AddcarryxU64(x459, x420, x462)
-       x465 := ((x461 >> 58) | ((x463 << 6) & 0xffffffffffffffff))
-       x466 := (x463 >> 58)
-       x467 := (x461 & 0x3ffffffffffffff)
+       var x464 uint64
+       x463, x464 = bits.Add64(x438, x435, uint64(p521Uint1(x462)))
+       var x465 uint64
+       var x466 uint64
+       x465, x466 = bits.Add64(x436, x433, uint64(p521Uint1(x464)))
+       x467 := (uint64(p521Uint1(x466)) + x434)
        var x468 uint64
-       var x469 p521Uint1
-       x468, x469 = p521AddcarryxU64(x465, x386, 0x0)
+       var x469 uint64
+       x468, x469 = bits.Add64(x414, x449, uint64(0x0))
        var x470 uint64
-       x470, _ = p521AddcarryxU64(x466, x388, x469)
-       x472 := ((x468 >> 58) | ((x470 << 6) & 0xffffffffffffffff))
-       x473 := (x470 >> 58)
-       x474 := (x468 & 0x3ffffffffffffff)
+       var x471 uint64
+       x470, x471 = bits.Add64(x416, x451, uint64(p521Uint1(x469)))
+       var x472 uint64
+       var x473 uint64
+       x472, x473 = bits.Add64(x418, x453, uint64(p521Uint1(x471)))
+       var x474 uint64
        var x475 uint64
-       var x476 p521Uint1
-       x475, x476 = p521AddcarryxU64(x472, x354, 0x0)
+       x474, x475 = bits.Add64(x420, x455, uint64(p521Uint1(x473)))
+       var x476 uint64
        var x477 uint64
-       x477, _ = p521AddcarryxU64(x473, x356, x476)
-       x479 := ((x475 >> 58) | ((x477 << 6) & 0xffffffffffffffff))
-       x480 := (x477 >> 58)
-       x481 := (x475 & 0x3ffffffffffffff)
+       x476, x477 = bits.Add64(x422, x457, uint64(p521Uint1(x475)))
+       var x478 uint64
+       var x479 uint64
+       x478, x479 = bits.Add64(x424, x459, uint64(p521Uint1(x477)))
+       var x480 uint64
+       var x481 uint64
+       x480, x481 = bits.Add64(x426, x461, uint64(p521Uint1(x479)))
        var x482 uint64
-       var x483 p521Uint1
-       x482, x483 = p521AddcarryxU64(x479, x322, 0x0)
+       var x483 uint64
+       x482, x483 = bits.Add64(x428, x463, uint64(p521Uint1(x481)))
        var x484 uint64
-       x484, _ = p521AddcarryxU64(x480, x324, x483)
-       x486 := ((x482 >> 58) | ((x484 << 6) & 0xffffffffffffffff))
-       x487 := (x484 >> 58)
-       x488 := (x482 & 0x3ffffffffffffff)
+       var x485 uint64
+       x484, x485 = bits.Add64(x430, x465, uint64(p521Uint1(x483)))
+       var x486 uint64
+       var x487 uint64
+       x486, x487 = bits.Add64(x432, x467, uint64(p521Uint1(x485)))
+       var x488 uint64
        var x489 uint64
-       var x490 p521Uint1
-       x489, x490 = p521AddcarryxU64(x486, x290, 0x0)
+       x489, x488 = bits.Mul64(x468, 0x1ff)
+       var x490 uint64
        var x491 uint64
-       x491, _ = p521AddcarryxU64(x487, x292, x490)
-       x493 := ((x489 >> 58) | ((x491 << 6) & 0xffffffffffffffff))
-       x494 := (x491 >> 58)
-       x495 := (x489 & 0x3ffffffffffffff)
+       x491, x490 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x492 uint64
+       var x493 uint64
+       x493, x492 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x494 uint64
+       var x495 uint64
+       x495, x494 = bits.Mul64(x468, 0xffffffffffffffff)
        var x496 uint64
-       var x497 p521Uint1
-       x496, x497 = p521AddcarryxU64(x493, x258, 0x0)
+       var x497 uint64
+       x497, x496 = bits.Mul64(x468, 0xffffffffffffffff)
        var x498 uint64
-       x498, _ = p521AddcarryxU64(x494, x260, x497)
-       x500 := ((x496 >> 58) | ((x498 << 6) & 0xffffffffffffffff))
-       x501 := (x498 >> 58)
-       x502 := (x496 & 0x3ffffffffffffff)
+       var x499 uint64
+       x499, x498 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x500 uint64
+       var x501 uint64
+       x501, x500 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x502 uint64
        var x503 uint64
-       var x504 p521Uint1
-       x503, x504 = p521AddcarryxU64(x500, x226, 0x0)
+       x503, x502 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x504 uint64
        var x505 uint64
-       x505, _ = p521AddcarryxU64(x501, x228, x504)
-       x507 := ((x503 >> 57) | ((x505 << 7) & 0xffffffffffffffff))
-       x508 := (x505 >> 57)
-       x509 := (x503 & 0x1ffffffffffffff)
+       x505, x504 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x506 uint64
+       var x507 uint64
+       x506, x507 = bits.Add64(x505, x502, uint64(0x0))
+       var x508 uint64
+       var x509 uint64
+       x508, x509 = bits.Add64(x503, x500, uint64(p521Uint1(x507)))
        var x510 uint64
-       var x511 p521Uint1
-       x510, x511 = p521AddcarryxU64(x197, x507, 0x0)
-       x512 := (uint64(x511) + x508)
-       x513 := ((x510 >> 58) | ((x512 << 6) & 0xffffffffffffffff))
-       x514 := (x510 & 0x3ffffffffffffff)
-       x515 := (x513 + x460)
-       x516 := p521Uint1((x515 >> 58))
-       x517 := (x515 & 0x3ffffffffffffff)
-       x518 := (uint64(x516) + x467)
-       out1[0] = x514
-       out1[1] = x517
-       out1[2] = x518
-       out1[3] = x474
-       out1[4] = x481
-       out1[5] = x488
-       out1[6] = x495
-       out1[7] = x502
-       out1[8] = x509
+       var x511 uint64
+       x510, x511 = bits.Add64(x501, x498, uint64(p521Uint1(x509)))
+       var x512 uint64
+       var x513 uint64
+       x512, x513 = bits.Add64(x499, x496, uint64(p521Uint1(x511)))
+       var x514 uint64
+       var x515 uint64
+       x514, x515 = bits.Add64(x497, x494, uint64(p521Uint1(x513)))
+       var x516 uint64
+       var x517 uint64
+       x516, x517 = bits.Add64(x495, x492, uint64(p521Uint1(x515)))
+       var x518 uint64
+       var x519 uint64
+       x518, x519 = bits.Add64(x493, x490, uint64(p521Uint1(x517)))
+       var x520 uint64
+       var x521 uint64
+       x520, x521 = bits.Add64(x491, x488, uint64(p521Uint1(x519)))
+       x522 := (uint64(p521Uint1(x521)) + x489)
+       var x524 uint64
+       _, x524 = bits.Add64(x468, x504, uint64(0x0))
+       var x525 uint64
+       var x526 uint64
+       x525, x526 = bits.Add64(x470, x506, uint64(p521Uint1(x524)))
+       var x527 uint64
+       var x528 uint64
+       x527, x528 = bits.Add64(x472, x508, uint64(p521Uint1(x526)))
+       var x529 uint64
+       var x530 uint64
+       x529, x530 = bits.Add64(x474, x510, uint64(p521Uint1(x528)))
+       var x531 uint64
+       var x532 uint64
+       x531, x532 = bits.Add64(x476, x512, uint64(p521Uint1(x530)))
+       var x533 uint64
+       var x534 uint64
+       x533, x534 = bits.Add64(x478, x514, uint64(p521Uint1(x532)))
+       var x535 uint64
+       var x536 uint64
+       x535, x536 = bits.Add64(x480, x516, uint64(p521Uint1(x534)))
+       var x537 uint64
+       var x538 uint64
+       x537, x538 = bits.Add64(x482, x518, uint64(p521Uint1(x536)))
+       var x539 uint64
+       var x540 uint64
+       x539, x540 = bits.Add64(x484, x520, uint64(p521Uint1(x538)))
+       var x541 uint64
+       var x542 uint64
+       x541, x542 = bits.Add64(x486, x522, uint64(p521Uint1(x540)))
+       x543 := (uint64(p521Uint1(x542)) + uint64(p521Uint1(x487)))
+       var x544 uint64
+       var x545 uint64
+       x545, x544 = bits.Mul64(x5, arg2[8])
+       var x546 uint64
+       var x547 uint64
+       x547, x546 = bits.Mul64(x5, arg2[7])
+       var x548 uint64
+       var x549 uint64
+       x549, x548 = bits.Mul64(x5, arg2[6])
+       var x550 uint64
+       var x551 uint64
+       x551, x550 = bits.Mul64(x5, arg2[5])
+       var x552 uint64
+       var x553 uint64
+       x553, x552 = bits.Mul64(x5, arg2[4])
+       var x554 uint64
+       var x555 uint64
+       x555, x554 = bits.Mul64(x5, arg2[3])
+       var x556 uint64
+       var x557 uint64
+       x557, x556 = bits.Mul64(x5, arg2[2])
+       var x558 uint64
+       var x559 uint64
+       x559, x558 = bits.Mul64(x5, arg2[1])
+       var x560 uint64
+       var x561 uint64
+       x561, x560 = bits.Mul64(x5, arg2[0])
+       var x562 uint64
+       var x563 uint64
+       x562, x563 = bits.Add64(x561, x558, uint64(0x0))
+       var x564 uint64
+       var x565 uint64
+       x564, x565 = bits.Add64(x559, x556, uint64(p521Uint1(x563)))
+       var x566 uint64
+       var x567 uint64
+       x566, x567 = bits.Add64(x557, x554, uint64(p521Uint1(x565)))
+       var x568 uint64
+       var x569 uint64
+       x568, x569 = bits.Add64(x555, x552, uint64(p521Uint1(x567)))
+       var x570 uint64
+       var x571 uint64
+       x570, x571 = bits.Add64(x553, x550, uint64(p521Uint1(x569)))
+       var x572 uint64
+       var x573 uint64
+       x572, x573 = bits.Add64(x551, x548, uint64(p521Uint1(x571)))
+       var x574 uint64
+       var x575 uint64
+       x574, x575 = bits.Add64(x549, x546, uint64(p521Uint1(x573)))
+       var x576 uint64
+       var x577 uint64
+       x576, x577 = bits.Add64(x547, x544, uint64(p521Uint1(x575)))
+       x578 := (uint64(p521Uint1(x577)) + x545)
+       var x579 uint64
+       var x580 uint64
+       x579, x580 = bits.Add64(x525, x560, uint64(0x0))
+       var x581 uint64
+       var x582 uint64
+       x581, x582 = bits.Add64(x527, x562, uint64(p521Uint1(x580)))
+       var x583 uint64
+       var x584 uint64
+       x583, x584 = bits.Add64(x529, x564, uint64(p521Uint1(x582)))
+       var x585 uint64
+       var x586 uint64
+       x585, x586 = bits.Add64(x531, x566, uint64(p521Uint1(x584)))
+       var x587 uint64
+       var x588 uint64
+       x587, x588 = bits.Add64(x533, x568, uint64(p521Uint1(x586)))
+       var x589 uint64
+       var x590 uint64
+       x589, x590 = bits.Add64(x535, x570, uint64(p521Uint1(x588)))
+       var x591 uint64
+       var x592 uint64
+       x591, x592 = bits.Add64(x537, x572, uint64(p521Uint1(x590)))
+       var x593 uint64
+       var x594 uint64
+       x593, x594 = bits.Add64(x539, x574, uint64(p521Uint1(x592)))
+       var x595 uint64
+       var x596 uint64
+       x595, x596 = bits.Add64(x541, x576, uint64(p521Uint1(x594)))
+       var x597 uint64
+       var x598 uint64
+       x597, x598 = bits.Add64(x543, x578, uint64(p521Uint1(x596)))
+       var x599 uint64
+       var x600 uint64
+       x600, x599 = bits.Mul64(x579, 0x1ff)
+       var x601 uint64
+       var x602 uint64
+       x602, x601 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x603 uint64
+       var x604 uint64
+       x604, x603 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x605 uint64
+       var x606 uint64
+       x606, x605 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x607 uint64
+       var x608 uint64
+       x608, x607 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x609 uint64
+       var x610 uint64
+       x610, x609 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x611 uint64
+       var x612 uint64
+       x612, x611 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x613 uint64
+       var x614 uint64
+       x614, x613 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x615 uint64
+       var x616 uint64
+       x616, x615 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x617 uint64
+       var x618 uint64
+       x617, x618 = bits.Add64(x616, x613, uint64(0x0))
+       var x619 uint64
+       var x620 uint64
+       x619, x620 = bits.Add64(x614, x611, uint64(p521Uint1(x618)))
+       var x621 uint64
+       var x622 uint64
+       x621, x622 = bits.Add64(x612, x609, uint64(p521Uint1(x620)))
+       var x623 uint64
+       var x624 uint64
+       x623, x624 = bits.Add64(x610, x607, uint64(p521Uint1(x622)))
+       var x625 uint64
+       var x626 uint64
+       x625, x626 = bits.Add64(x608, x605, uint64(p521Uint1(x624)))
+       var x627 uint64
+       var x628 uint64
+       x627, x628 = bits.Add64(x606, x603, uint64(p521Uint1(x626)))
+       var x629 uint64
+       var x630 uint64
+       x629, x630 = bits.Add64(x604, x601, uint64(p521Uint1(x628)))
+       var x631 uint64
+       var x632 uint64
+       x631, x632 = bits.Add64(x602, x599, uint64(p521Uint1(x630)))
+       x633 := (uint64(p521Uint1(x632)) + x600)
+       var x635 uint64
+       _, x635 = bits.Add64(x579, x615, uint64(0x0))
+       var x636 uint64
+       var x637 uint64
+       x636, x637 = bits.Add64(x581, x617, uint64(p521Uint1(x635)))
+       var x638 uint64
+       var x639 uint64
+       x638, x639 = bits.Add64(x583, x619, uint64(p521Uint1(x637)))
+       var x640 uint64
+       var x641 uint64
+       x640, x641 = bits.Add64(x585, x621, uint64(p521Uint1(x639)))
+       var x642 uint64
+       var x643 uint64
+       x642, x643 = bits.Add64(x587, x623, uint64(p521Uint1(x641)))
+       var x644 uint64
+       var x645 uint64
+       x644, x645 = bits.Add64(x589, x625, uint64(p521Uint1(x643)))
+       var x646 uint64
+       var x647 uint64
+       x646, x647 = bits.Add64(x591, x627, uint64(p521Uint1(x645)))
+       var x648 uint64
+       var x649 uint64
+       x648, x649 = bits.Add64(x593, x629, uint64(p521Uint1(x647)))
+       var x650 uint64
+       var x651 uint64
+       x650, x651 = bits.Add64(x595, x631, uint64(p521Uint1(x649)))
+       var x652 uint64
+       var x653 uint64
+       x652, x653 = bits.Add64(x597, x633, uint64(p521Uint1(x651)))
+       x654 := (uint64(p521Uint1(x653)) + uint64(p521Uint1(x598)))
+       var x655 uint64
+       var x656 uint64
+       x656, x655 = bits.Mul64(x6, arg2[8])
+       var x657 uint64
+       var x658 uint64
+       x658, x657 = bits.Mul64(x6, arg2[7])
+       var x659 uint64
+       var x660 uint64
+       x660, x659 = bits.Mul64(x6, arg2[6])
+       var x661 uint64
+       var x662 uint64
+       x662, x661 = bits.Mul64(x6, arg2[5])
+       var x663 uint64
+       var x664 uint64
+       x664, x663 = bits.Mul64(x6, arg2[4])
+       var x665 uint64
+       var x666 uint64
+       x666, x665 = bits.Mul64(x6, arg2[3])
+       var x667 uint64
+       var x668 uint64
+       x668, x667 = bits.Mul64(x6, arg2[2])
+       var x669 uint64
+       var x670 uint64
+       x670, x669 = bits.Mul64(x6, arg2[1])
+       var x671 uint64
+       var x672 uint64
+       x672, x671 = bits.Mul64(x6, arg2[0])
+       var x673 uint64
+       var x674 uint64
+       x673, x674 = bits.Add64(x672, x669, uint64(0x0))
+       var x675 uint64
+       var x676 uint64
+       x675, x676 = bits.Add64(x670, x667, uint64(p521Uint1(x674)))
+       var x677 uint64
+       var x678 uint64
+       x677, x678 = bits.Add64(x668, x665, uint64(p521Uint1(x676)))
+       var x679 uint64
+       var x680 uint64
+       x679, x680 = bits.Add64(x666, x663, uint64(p521Uint1(x678)))
+       var x681 uint64
+       var x682 uint64
+       x681, x682 = bits.Add64(x664, x661, uint64(p521Uint1(x680)))
+       var x683 uint64
+       var x684 uint64
+       x683, x684 = bits.Add64(x662, x659, uint64(p521Uint1(x682)))
+       var x685 uint64
+       var x686 uint64
+       x685, x686 = bits.Add64(x660, x657, uint64(p521Uint1(x684)))
+       var x687 uint64
+       var x688 uint64
+       x687, x688 = bits.Add64(x658, x655, uint64(p521Uint1(x686)))
+       x689 := (uint64(p521Uint1(x688)) + x656)
+       var x690 uint64
+       var x691 uint64
+       x690, x691 = bits.Add64(x636, x671, uint64(0x0))
+       var x692 uint64
+       var x693 uint64
+       x692, x693 = bits.Add64(x638, x673, uint64(p521Uint1(x691)))
+       var x694 uint64
+       var x695 uint64
+       x694, x695 = bits.Add64(x640, x675, uint64(p521Uint1(x693)))
+       var x696 uint64
+       var x697 uint64
+       x696, x697 = bits.Add64(x642, x677, uint64(p521Uint1(x695)))
+       var x698 uint64
+       var x699 uint64
+       x698, x699 = bits.Add64(x644, x679, uint64(p521Uint1(x697)))
+       var x700 uint64
+       var x701 uint64
+       x700, x701 = bits.Add64(x646, x681, uint64(p521Uint1(x699)))
+       var x702 uint64
+       var x703 uint64
+       x702, x703 = bits.Add64(x648, x683, uint64(p521Uint1(x701)))
+       var x704 uint64
+       var x705 uint64
+       x704, x705 = bits.Add64(x650, x685, uint64(p521Uint1(x703)))
+       var x706 uint64
+       var x707 uint64
+       x706, x707 = bits.Add64(x652, x687, uint64(p521Uint1(x705)))
+       var x708 uint64
+       var x709 uint64
+       x708, x709 = bits.Add64(x654, x689, uint64(p521Uint1(x707)))
+       var x710 uint64
+       var x711 uint64
+       x711, x710 = bits.Mul64(x690, 0x1ff)
+       var x712 uint64
+       var x713 uint64
+       x713, x712 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x714 uint64
+       var x715 uint64
+       x715, x714 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x716 uint64
+       var x717 uint64
+       x717, x716 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x718 uint64
+       var x719 uint64
+       x719, x718 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x720 uint64
+       var x721 uint64
+       x721, x720 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x722 uint64
+       var x723 uint64
+       x723, x722 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x724 uint64
+       var x725 uint64
+       x725, x724 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x726 uint64
+       var x727 uint64
+       x727, x726 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x728 uint64
+       var x729 uint64
+       x728, x729 = bits.Add64(x727, x724, uint64(0x0))
+       var x730 uint64
+       var x731 uint64
+       x730, x731 = bits.Add64(x725, x722, uint64(p521Uint1(x729)))
+       var x732 uint64
+       var x733 uint64
+       x732, x733 = bits.Add64(x723, x720, uint64(p521Uint1(x731)))
+       var x734 uint64
+       var x735 uint64
+       x734, x735 = bits.Add64(x721, x718, uint64(p521Uint1(x733)))
+       var x736 uint64
+       var x737 uint64
+       x736, x737 = bits.Add64(x719, x716, uint64(p521Uint1(x735)))
+       var x738 uint64
+       var x739 uint64
+       x738, x739 = bits.Add64(x717, x714, uint64(p521Uint1(x737)))
+       var x740 uint64
+       var x741 uint64
+       x740, x741 = bits.Add64(x715, x712, uint64(p521Uint1(x739)))
+       var x742 uint64
+       var x743 uint64
+       x742, x743 = bits.Add64(x713, x710, uint64(p521Uint1(x741)))
+       x744 := (uint64(p521Uint1(x743)) + x711)
+       var x746 uint64
+       _, x746 = bits.Add64(x690, x726, uint64(0x0))
+       var x747 uint64
+       var x748 uint64
+       x747, x748 = bits.Add64(x692, x728, uint64(p521Uint1(x746)))
+       var x749 uint64
+       var x750 uint64
+       x749, x750 = bits.Add64(x694, x730, uint64(p521Uint1(x748)))
+       var x751 uint64
+       var x752 uint64
+       x751, x752 = bits.Add64(x696, x732, uint64(p521Uint1(x750)))
+       var x753 uint64
+       var x754 uint64
+       x753, x754 = bits.Add64(x698, x734, uint64(p521Uint1(x752)))
+       var x755 uint64
+       var x756 uint64
+       x755, x756 = bits.Add64(x700, x736, uint64(p521Uint1(x754)))
+       var x757 uint64
+       var x758 uint64
+       x757, x758 = bits.Add64(x702, x738, uint64(p521Uint1(x756)))
+       var x759 uint64
+       var x760 uint64
+       x759, x760 = bits.Add64(x704, x740, uint64(p521Uint1(x758)))
+       var x761 uint64
+       var x762 uint64
+       x761, x762 = bits.Add64(x706, x742, uint64(p521Uint1(x760)))
+       var x763 uint64
+       var x764 uint64
+       x763, x764 = bits.Add64(x708, x744, uint64(p521Uint1(x762)))
+       x765 := (uint64(p521Uint1(x764)) + uint64(p521Uint1(x709)))
+       var x766 uint64
+       var x767 uint64
+       x767, x766 = bits.Mul64(x7, arg2[8])
+       var x768 uint64
+       var x769 uint64
+       x769, x768 = bits.Mul64(x7, arg2[7])
+       var x770 uint64
+       var x771 uint64
+       x771, x770 = bits.Mul64(x7, arg2[6])
+       var x772 uint64
+       var x773 uint64
+       x773, x772 = bits.Mul64(x7, arg2[5])
+       var x774 uint64
+       var x775 uint64
+       x775, x774 = bits.Mul64(x7, arg2[4])
+       var x776 uint64
+       var x777 uint64
+       x777, x776 = bits.Mul64(x7, arg2[3])
+       var x778 uint64
+       var x779 uint64
+       x779, x778 = bits.Mul64(x7, arg2[2])
+       var x780 uint64
+       var x781 uint64
+       x781, x780 = bits.Mul64(x7, arg2[1])
+       var x782 uint64
+       var x783 uint64
+       x783, x782 = bits.Mul64(x7, arg2[0])
+       var x784 uint64
+       var x785 uint64
+       x784, x785 = bits.Add64(x783, x780, uint64(0x0))
+       var x786 uint64
+       var x787 uint64
+       x786, x787 = bits.Add64(x781, x778, uint64(p521Uint1(x785)))
+       var x788 uint64
+       var x789 uint64
+       x788, x789 = bits.Add64(x779, x776, uint64(p521Uint1(x787)))
+       var x790 uint64
+       var x791 uint64
+       x790, x791 = bits.Add64(x777, x774, uint64(p521Uint1(x789)))
+       var x792 uint64
+       var x793 uint64
+       x792, x793 = bits.Add64(x775, x772, uint64(p521Uint1(x791)))
+       var x794 uint64
+       var x795 uint64
+       x794, x795 = bits.Add64(x773, x770, uint64(p521Uint1(x793)))
+       var x796 uint64
+       var x797 uint64
+       x796, x797 = bits.Add64(x771, x768, uint64(p521Uint1(x795)))
+       var x798 uint64
+       var x799 uint64
+       x798, x799 = bits.Add64(x769, x766, uint64(p521Uint1(x797)))
+       x800 := (uint64(p521Uint1(x799)) + x767)
+       var x801 uint64
+       var x802 uint64
+       x801, x802 = bits.Add64(x747, x782, uint64(0x0))
+       var x803 uint64
+       var x804 uint64
+       x803, x804 = bits.Add64(x749, x784, uint64(p521Uint1(x802)))
+       var x805 uint64
+       var x806 uint64
+       x805, x806 = bits.Add64(x751, x786, uint64(p521Uint1(x804)))
+       var x807 uint64
+       var x808 uint64
+       x807, x808 = bits.Add64(x753, x788, uint64(p521Uint1(x806)))
+       var x809 uint64
+       var x810 uint64
+       x809, x810 = bits.Add64(x755, x790, uint64(p521Uint1(x808)))
+       var x811 uint64
+       var x812 uint64
+       x811, x812 = bits.Add64(x757, x792, uint64(p521Uint1(x810)))
+       var x813 uint64
+       var x814 uint64
+       x813, x814 = bits.Add64(x759, x794, uint64(p521Uint1(x812)))
+       var x815 uint64
+       var x816 uint64
+       x815, x816 = bits.Add64(x761, x796, uint64(p521Uint1(x814)))
+       var x817 uint64
+       var x818 uint64
+       x817, x818 = bits.Add64(x763, x798, uint64(p521Uint1(x816)))
+       var x819 uint64
+       var x820 uint64
+       x819, x820 = bits.Add64(x765, x800, uint64(p521Uint1(x818)))
+       var x821 uint64
+       var x822 uint64
+       x822, x821 = bits.Mul64(x801, 0x1ff)
+       var x823 uint64
+       var x824 uint64
+       x824, x823 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x825 uint64
+       var x826 uint64
+       x826, x825 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x827 uint64
+       var x828 uint64
+       x828, x827 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x829 uint64
+       var x830 uint64
+       x830, x829 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x831 uint64
+       var x832 uint64
+       x832, x831 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x833 uint64
+       var x834 uint64
+       x834, x833 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x835 uint64
+       var x836 uint64
+       x836, x835 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x837 uint64
+       var x838 uint64
+       x838, x837 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x839 uint64
+       var x840 uint64
+       x839, x840 = bits.Add64(x838, x835, uint64(0x0))
+       var x841 uint64
+       var x842 uint64
+       x841, x842 = bits.Add64(x836, x833, uint64(p521Uint1(x840)))
+       var x843 uint64
+       var x844 uint64
+       x843, x844 = bits.Add64(x834, x831, uint64(p521Uint1(x842)))
+       var x845 uint64
+       var x846 uint64
+       x845, x846 = bits.Add64(x832, x829, uint64(p521Uint1(x844)))
+       var x847 uint64
+       var x848 uint64
+       x847, x848 = bits.Add64(x830, x827, uint64(p521Uint1(x846)))
+       var x849 uint64
+       var x850 uint64
+       x849, x850 = bits.Add64(x828, x825, uint64(p521Uint1(x848)))
+       var x851 uint64
+       var x852 uint64
+       x851, x852 = bits.Add64(x826, x823, uint64(p521Uint1(x850)))
+       var x853 uint64
+       var x854 uint64
+       x853, x854 = bits.Add64(x824, x821, uint64(p521Uint1(x852)))
+       x855 := (uint64(p521Uint1(x854)) + x822)
+       var x857 uint64
+       _, x857 = bits.Add64(x801, x837, uint64(0x0))
+       var x858 uint64
+       var x859 uint64
+       x858, x859 = bits.Add64(x803, x839, uint64(p521Uint1(x857)))
+       var x860 uint64
+       var x861 uint64
+       x860, x861 = bits.Add64(x805, x841, uint64(p521Uint1(x859)))
+       var x862 uint64
+       var x863 uint64
+       x862, x863 = bits.Add64(x807, x843, uint64(p521Uint1(x861)))
+       var x864 uint64
+       var x865 uint64
+       x864, x865 = bits.Add64(x809, x845, uint64(p521Uint1(x863)))
+       var x866 uint64
+       var x867 uint64
+       x866, x867 = bits.Add64(x811, x847, uint64(p521Uint1(x865)))
+       var x868 uint64
+       var x869 uint64
+       x868, x869 = bits.Add64(x813, x849, uint64(p521Uint1(x867)))
+       var x870 uint64
+       var x871 uint64
+       x870, x871 = bits.Add64(x815, x851, uint64(p521Uint1(x869)))
+       var x872 uint64
+       var x873 uint64
+       x872, x873 = bits.Add64(x817, x853, uint64(p521Uint1(x871)))
+       var x874 uint64
+       var x875 uint64
+       x874, x875 = bits.Add64(x819, x855, uint64(p521Uint1(x873)))
+       x876 := (uint64(p521Uint1(x875)) + uint64(p521Uint1(x820)))
+       var x877 uint64
+       var x878 uint64
+       x878, x877 = bits.Mul64(x8, arg2[8])
+       var x879 uint64
+       var x880 uint64
+       x880, x879 = bits.Mul64(x8, arg2[7])
+       var x881 uint64
+       var x882 uint64
+       x882, x881 = bits.Mul64(x8, arg2[6])
+       var x883 uint64
+       var x884 uint64
+       x884, x883 = bits.Mul64(x8, arg2[5])
+       var x885 uint64
+       var x886 uint64
+       x886, x885 = bits.Mul64(x8, arg2[4])
+       var x887 uint64
+       var x888 uint64
+       x888, x887 = bits.Mul64(x8, arg2[3])
+       var x889 uint64
+       var x890 uint64
+       x890, x889 = bits.Mul64(x8, arg2[2])
+       var x891 uint64
+       var x892 uint64
+       x892, x891 = bits.Mul64(x8, arg2[1])
+       var x893 uint64
+       var x894 uint64
+       x894, x893 = bits.Mul64(x8, arg2[0])
+       var x895 uint64
+       var x896 uint64
+       x895, x896 = bits.Add64(x894, x891, uint64(0x0))
+       var x897 uint64
+       var x898 uint64
+       x897, x898 = bits.Add64(x892, x889, uint64(p521Uint1(x896)))
+       var x899 uint64
+       var x900 uint64
+       x899, x900 = bits.Add64(x890, x887, uint64(p521Uint1(x898)))
+       var x901 uint64
+       var x902 uint64
+       x901, x902 = bits.Add64(x888, x885, uint64(p521Uint1(x900)))
+       var x903 uint64
+       var x904 uint64
+       x903, x904 = bits.Add64(x886, x883, uint64(p521Uint1(x902)))
+       var x905 uint64
+       var x906 uint64
+       x905, x906 = bits.Add64(x884, x881, uint64(p521Uint1(x904)))
+       var x907 uint64
+       var x908 uint64
+       x907, x908 = bits.Add64(x882, x879, uint64(p521Uint1(x906)))
+       var x909 uint64
+       var x910 uint64
+       x909, x910 = bits.Add64(x880, x877, uint64(p521Uint1(x908)))
+       x911 := (uint64(p521Uint1(x910)) + x878)
+       var x912 uint64
+       var x913 uint64
+       x912, x913 = bits.Add64(x858, x893, uint64(0x0))
+       var x914 uint64
+       var x915 uint64
+       x914, x915 = bits.Add64(x860, x895, uint64(p521Uint1(x913)))
+       var x916 uint64
+       var x917 uint64
+       x916, x917 = bits.Add64(x862, x897, uint64(p521Uint1(x915)))
+       var x918 uint64
+       var x919 uint64
+       x918, x919 = bits.Add64(x864, x899, uint64(p521Uint1(x917)))
+       var x920 uint64
+       var x921 uint64
+       x920, x921 = bits.Add64(x866, x901, uint64(p521Uint1(x919)))
+       var x922 uint64
+       var x923 uint64
+       x922, x923 = bits.Add64(x868, x903, uint64(p521Uint1(x921)))
+       var x924 uint64
+       var x925 uint64
+       x924, x925 = bits.Add64(x870, x905, uint64(p521Uint1(x923)))
+       var x926 uint64
+       var x927 uint64
+       x926, x927 = bits.Add64(x872, x907, uint64(p521Uint1(x925)))
+       var x928 uint64
+       var x929 uint64
+       x928, x929 = bits.Add64(x874, x909, uint64(p521Uint1(x927)))
+       var x930 uint64
+       var x931 uint64
+       x930, x931 = bits.Add64(x876, x911, uint64(p521Uint1(x929)))
+       var x932 uint64
+       var x933 uint64
+       x933, x932 = bits.Mul64(x912, 0x1ff)
+       var x934 uint64
+       var x935 uint64
+       x935, x934 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x936 uint64
+       var x937 uint64
+       x937, x936 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x938 uint64
+       var x939 uint64
+       x939, x938 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x940 uint64
+       var x941 uint64
+       x941, x940 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x942 uint64
+       var x943 uint64
+       x943, x942 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x944 uint64
+       var x945 uint64
+       x945, x944 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x946 uint64
+       var x947 uint64
+       x947, x946 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x948 uint64
+       var x949 uint64
+       x949, x948 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x950 uint64
+       var x951 uint64
+       x950, x951 = bits.Add64(x949, x946, uint64(0x0))
+       var x952 uint64
+       var x953 uint64
+       x952, x953 = bits.Add64(x947, x944, uint64(p521Uint1(x951)))
+       var x954 uint64
+       var x955 uint64
+       x954, x955 = bits.Add64(x945, x942, uint64(p521Uint1(x953)))
+       var x956 uint64
+       var x957 uint64
+       x956, x957 = bits.Add64(x943, x940, uint64(p521Uint1(x955)))
+       var x958 uint64
+       var x959 uint64
+       x958, x959 = bits.Add64(x941, x938, uint64(p521Uint1(x957)))
+       var x960 uint64
+       var x961 uint64
+       x960, x961 = bits.Add64(x939, x936, uint64(p521Uint1(x959)))
+       var x962 uint64
+       var x963 uint64
+       x962, x963 = bits.Add64(x937, x934, uint64(p521Uint1(x961)))
+       var x964 uint64
+       var x965 uint64
+       x964, x965 = bits.Add64(x935, x932, uint64(p521Uint1(x963)))
+       x966 := (uint64(p521Uint1(x965)) + x933)
+       var x968 uint64
+       _, x968 = bits.Add64(x912, x948, uint64(0x0))
+       var x969 uint64
+       var x970 uint64
+       x969, x970 = bits.Add64(x914, x950, uint64(p521Uint1(x968)))
+       var x971 uint64
+       var x972 uint64
+       x971, x972 = bits.Add64(x916, x952, uint64(p521Uint1(x970)))
+       var x973 uint64
+       var x974 uint64
+       x973, x974 = bits.Add64(x918, x954, uint64(p521Uint1(x972)))
+       var x975 uint64
+       var x976 uint64
+       x975, x976 = bits.Add64(x920, x956, uint64(p521Uint1(x974)))
+       var x977 uint64
+       var x978 uint64
+       x977, x978 = bits.Add64(x922, x958, uint64(p521Uint1(x976)))
+       var x979 uint64
+       var x980 uint64
+       x979, x980 = bits.Add64(x924, x960, uint64(p521Uint1(x978)))
+       var x981 uint64
+       var x982 uint64
+       x981, x982 = bits.Add64(x926, x962, uint64(p521Uint1(x980)))
+       var x983 uint64
+       var x984 uint64
+       x983, x984 = bits.Add64(x928, x964, uint64(p521Uint1(x982)))
+       var x985 uint64
+       var x986 uint64
+       x985, x986 = bits.Add64(x930, x966, uint64(p521Uint1(x984)))
+       x987 := (uint64(p521Uint1(x986)) + uint64(p521Uint1(x931)))
+       var x988 uint64
+       var x989 uint64
+       x988, x989 = bits.Sub64(x969, 0xffffffffffffffff, uint64(0x0))
+       var x990 uint64
+       var x991 uint64
+       x990, x991 = bits.Sub64(x971, 0xffffffffffffffff, uint64(p521Uint1(x989)))
+       var x992 uint64
+       var x993 uint64
+       x992, x993 = bits.Sub64(x973, 0xffffffffffffffff, uint64(p521Uint1(x991)))
+       var x994 uint64
+       var x995 uint64
+       x994, x995 = bits.Sub64(x975, 0xffffffffffffffff, uint64(p521Uint1(x993)))
+       var x996 uint64
+       var x997 uint64
+       x996, x997 = bits.Sub64(x977, 0xffffffffffffffff, uint64(p521Uint1(x995)))
+       var x998 uint64
+       var x999 uint64
+       x998, x999 = bits.Sub64(x979, 0xffffffffffffffff, uint64(p521Uint1(x997)))
+       var x1000 uint64
+       var x1001 uint64
+       x1000, x1001 = bits.Sub64(x981, 0xffffffffffffffff, uint64(p521Uint1(x999)))
+       var x1002 uint64
+       var x1003 uint64
+       x1002, x1003 = bits.Sub64(x983, 0xffffffffffffffff, uint64(p521Uint1(x1001)))
+       var x1004 uint64
+       var x1005 uint64
+       x1004, x1005 = bits.Sub64(x985, 0x1ff, uint64(p521Uint1(x1003)))
+       var x1007 uint64
+       _, x1007 = bits.Sub64(x987, uint64(0x0), uint64(p521Uint1(x1005)))
+       var x1008 uint64
+       p521CmovznzU64(&x1008, p521Uint1(x1007), x988, x969)
+       var x1009 uint64
+       p521CmovznzU64(&x1009, p521Uint1(x1007), x990, x971)
+       var x1010 uint64
+       p521CmovznzU64(&x1010, p521Uint1(x1007), x992, x973)
+       var x1011 uint64
+       p521CmovznzU64(&x1011, p521Uint1(x1007), x994, x975)
+       var x1012 uint64
+       p521CmovznzU64(&x1012, p521Uint1(x1007), x996, x977)
+       var x1013 uint64
+       p521CmovznzU64(&x1013, p521Uint1(x1007), x998, x979)
+       var x1014 uint64
+       p521CmovznzU64(&x1014, p521Uint1(x1007), x1000, x981)
+       var x1015 uint64
+       p521CmovznzU64(&x1015, p521Uint1(x1007), x1002, x983)
+       var x1016 uint64
+       p521CmovznzU64(&x1016, p521Uint1(x1007), x1004, x985)
+       out1[0] = x1008
+       out1[1] = x1009
+       out1[2] = x1010
+       out1[3] = x1011
+       out1[4] = x1012
+       out1[5] = x1013
+       out1[6] = x1014
+       out1[7] = x1015
+       out1[8] = x1016
 }
 
-// p521CarrySquare squares a field element and reduces the result.
+// p521Square squares a field element in the Montgomery domain.
 //
+// Preconditions:
+//   0 ≤ eval arg1 < m
 // Postconditions:
-//   eval out1 mod m = (eval arg1 * eval arg1) mod m
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m
+//   0 ≤ eval out1 < m
 //
-// Input Bounds:
-//   arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-func p521CarrySquare(out1 *[9]uint64, arg1 *[9]uint64) {
-       x1 := arg1[8]
-       x2 := (x1 * 0x2)
-       x3 := (arg1[8] * 0x2)
-       x4 := arg1[7]
-       x5 := (x4 * 0x2)
-       x6 := (arg1[7] * 0x2)
-       x7 := arg1[6]
-       x8 := (x7 * 0x2)
-       x9 := (arg1[6] * 0x2)
-       x10 := arg1[5]
-       x11 := (x10 * 0x2)
-       x12 := (arg1[5] * 0x2)
-       x13 := (arg1[4] * 0x2)
-       x14 := (arg1[3] * 0x2)
-       x15 := (arg1[2] * 0x2)
-       x16 := (arg1[1] * 0x2)
+func p521Square(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[6]
+       x7 := arg1[7]
+       x8 := arg1[8]
+       x9 := arg1[0]
+       var x10 uint64
+       var x11 uint64
+       x11, x10 = bits.Mul64(x9, arg1[8])
+       var x12 uint64
+       var x13 uint64
+       x13, x12 = bits.Mul64(x9, arg1[7])
+       var x14 uint64
+       var x15 uint64
+       x15, x14 = bits.Mul64(x9, arg1[6])
+       var x16 uint64
        var x17 uint64
+       x17, x16 = bits.Mul64(x9, arg1[5])
        var x18 uint64
-       x18, x17 = bits.Mul64(arg1[8], (x1 * 0x2))
        var x19 uint64
+       x19, x18 = bits.Mul64(x9, arg1[4])
        var x20 uint64
-       x20, x19 = bits.Mul64(arg1[7], (x2 * 0x2))
        var x21 uint64
+       x21, x20 = bits.Mul64(x9, arg1[3])
        var x22 uint64
-       x22, x21 = bits.Mul64(arg1[7], (x4 * 0x2))
        var x23 uint64
+       x23, x22 = bits.Mul64(x9, arg1[2])
        var x24 uint64
-       x24, x23 = bits.Mul64(arg1[6], (x2 * 0x2))
        var x25 uint64
+       x25, x24 = bits.Mul64(x9, arg1[1])
        var x26 uint64
-       x26, x25 = bits.Mul64(arg1[6], (x5 * 0x2))
        var x27 uint64
+       x27, x26 = bits.Mul64(x9, arg1[0])
        var x28 uint64
-       x28, x27 = bits.Mul64(arg1[6], (x7 * 0x2))
        var x29 uint64
+       x28, x29 = bits.Add64(x27, x24, uint64(0x0))
        var x30 uint64
-       x30, x29 = bits.Mul64(arg1[5], (x2 * 0x2))
        var x31 uint64
+       x30, x31 = bits.Add64(x25, x22, uint64(p521Uint1(x29)))
        var x32 uint64
-       x32, x31 = bits.Mul64(arg1[5], (x5 * 0x2))
        var x33 uint64
+       x32, x33 = bits.Add64(x23, x20, uint64(p521Uint1(x31)))
        var x34 uint64
-       x34, x33 = bits.Mul64(arg1[5], (x8 * 0x2))
        var x35 uint64
+       x34, x35 = bits.Add64(x21, x18, uint64(p521Uint1(x33)))
        var x36 uint64
-       x36, x35 = bits.Mul64(arg1[5], (x10 * 0x2))
        var x37 uint64
+       x36, x37 = bits.Add64(x19, x16, uint64(p521Uint1(x35)))
        var x38 uint64
-       x38, x37 = bits.Mul64(arg1[4], (x2 * 0x2))
        var x39 uint64
+       x38, x39 = bits.Add64(x17, x14, uint64(p521Uint1(x37)))
        var x40 uint64
-       x40, x39 = bits.Mul64(arg1[4], (x5 * 0x2))
        var x41 uint64
+       x40, x41 = bits.Add64(x15, x12, uint64(p521Uint1(x39)))
        var x42 uint64
-       x42, x41 = bits.Mul64(arg1[4], (x8 * 0x2))
        var x43 uint64
-       var x44 uint64
-       x44, x43 = bits.Mul64(arg1[4], (x11 * 0x2))
+       x42, x43 = bits.Add64(x13, x10, uint64(p521Uint1(x41)))
+       x44 := (uint64(p521Uint1(x43)) + x11)
        var x45 uint64
        var x46 uint64
-       x46, x45 = bits.Mul64(arg1[4], arg1[4])
+       x46, x45 = bits.Mul64(x26, 0x1ff)
        var x47 uint64
        var x48 uint64
-       x48, x47 = bits.Mul64(arg1[3], (x2 * 0x2))
+       x48, x47 = bits.Mul64(x26, 0xffffffffffffffff)
        var x49 uint64
        var x50 uint64
-       x50, x49 = bits.Mul64(arg1[3], (x5 * 0x2))
+       x50, x49 = bits.Mul64(x26, 0xffffffffffffffff)
        var x51 uint64
        var x52 uint64
-       x52, x51 = bits.Mul64(arg1[3], (x8 * 0x2))
+       x52, x51 = bits.Mul64(x26, 0xffffffffffffffff)
        var x53 uint64
        var x54 uint64
-       x54, x53 = bits.Mul64(arg1[3], x12)
+       x54, x53 = bits.Mul64(x26, 0xffffffffffffffff)
        var x55 uint64
        var x56 uint64
-       x56, x55 = bits.Mul64(arg1[3], x13)
+       x56, x55 = bits.Mul64(x26, 0xffffffffffffffff)
        var x57 uint64
        var x58 uint64
-       x58, x57 = bits.Mul64(arg1[3], arg1[3])
+       x58, x57 = bits.Mul64(x26, 0xffffffffffffffff)
        var x59 uint64
        var x60 uint64
-       x60, x59 = bits.Mul64(arg1[2], (x2 * 0x2))
+       x60, x59 = bits.Mul64(x26, 0xffffffffffffffff)
        var x61 uint64
        var x62 uint64
-       x62, x61 = bits.Mul64(arg1[2], (x5 * 0x2))
+       x62, x61 = bits.Mul64(x26, 0xffffffffffffffff)
        var x63 uint64
        var x64 uint64
-       x64, x63 = bits.Mul64(arg1[2], x9)
+       x63, x64 = bits.Add64(x62, x59, uint64(0x0))
        var x65 uint64
        var x66 uint64
-       x66, x65 = bits.Mul64(arg1[2], x12)
+       x65, x66 = bits.Add64(x60, x57, uint64(p521Uint1(x64)))
        var x67 uint64
        var x68 uint64
-       x68, x67 = bits.Mul64(arg1[2], x13)
+       x67, x68 = bits.Add64(x58, x55, uint64(p521Uint1(x66)))
        var x69 uint64
        var x70 uint64
-       x70, x69 = bits.Mul64(arg1[2], x14)
+       x69, x70 = bits.Add64(x56, x53, uint64(p521Uint1(x68)))
        var x71 uint64
        var x72 uint64
-       x72, x71 = bits.Mul64(arg1[2], arg1[2])
+       x71, x72 = bits.Add64(x54, x51, uint64(p521Uint1(x70)))
        var x73 uint64
        var x74 uint64
-       x74, x73 = bits.Mul64(arg1[1], (x2 * 0x2))
+       x73, x74 = bits.Add64(x52, x49, uint64(p521Uint1(x72)))
        var x75 uint64
        var x76 uint64
-       x76, x75 = bits.Mul64(arg1[1], x6)
+       x75, x76 = bits.Add64(x50, x47, uint64(p521Uint1(x74)))
        var x77 uint64
        var x78 uint64
-       x78, x77 = bits.Mul64(arg1[1], x9)
-       var x79 uint64
-       var x80 uint64
-       x80, x79 = bits.Mul64(arg1[1], x12)
+       x77, x78 = bits.Add64(x48, x45, uint64(p521Uint1(x76)))
+       x79 := (uint64(p521Uint1(x78)) + x46)
        var x81 uint64
+       _, x81 = bits.Add64(x26, x61, uint64(0x0))
        var x82 uint64
-       x82, x81 = bits.Mul64(arg1[1], x13)
        var x83 uint64
+       x82, x83 = bits.Add64(x28, x63, uint64(p521Uint1(x81)))
        var x84 uint64
-       x84, x83 = bits.Mul64(arg1[1], x14)
        var x85 uint64
+       x84, x85 = bits.Add64(x30, x65, uint64(p521Uint1(x83)))
        var x86 uint64
-       x86, x85 = bits.Mul64(arg1[1], x15)
        var x87 uint64
+       x86, x87 = bits.Add64(x32, x67, uint64(p521Uint1(x85)))
        var x88 uint64
-       x88, x87 = bits.Mul64(arg1[1], arg1[1])
        var x89 uint64
+       x88, x89 = bits.Add64(x34, x69, uint64(p521Uint1(x87)))
        var x90 uint64
-       x90, x89 = bits.Mul64(arg1[0], x3)
        var x91 uint64
+       x90, x91 = bits.Add64(x36, x71, uint64(p521Uint1(x89)))
        var x92 uint64
-       x92, x91 = bits.Mul64(arg1[0], x6)
        var x93 uint64
+       x92, x93 = bits.Add64(x38, x73, uint64(p521Uint1(x91)))
        var x94 uint64
-       x94, x93 = bits.Mul64(arg1[0], x9)
        var x95 uint64
+       x94, x95 = bits.Add64(x40, x75, uint64(p521Uint1(x93)))
        var x96 uint64
-       x96, x95 = bits.Mul64(arg1[0], x12)
        var x97 uint64
+       x96, x97 = bits.Add64(x42, x77, uint64(p521Uint1(x95)))
        var x98 uint64
-       x98, x97 = bits.Mul64(arg1[0], x13)
        var x99 uint64
+       x98, x99 = bits.Add64(x44, x79, uint64(p521Uint1(x97)))
        var x100 uint64
-       x100, x99 = bits.Mul64(arg1[0], x14)
        var x101 uint64
+       x101, x100 = bits.Mul64(x1, arg1[8])
        var x102 uint64
-       x102, x101 = bits.Mul64(arg1[0], x15)
        var x103 uint64
+       x103, x102 = bits.Mul64(x1, arg1[7])
        var x104 uint64
-       x104, x103 = bits.Mul64(arg1[0], x16)
        var x105 uint64
+       x105, x104 = bits.Mul64(x1, arg1[6])
        var x106 uint64
-       x106, x105 = bits.Mul64(arg1[0], arg1[0])
        var x107 uint64
-       var x108 p521Uint1
-       x107, x108 = p521AddcarryxU64(x51, x43, 0x0)
+       x107, x106 = bits.Mul64(x1, arg1[5])
+       var x108 uint64
        var x109 uint64
-       x109, _ = p521AddcarryxU64(x52, x44, x108)
+       x109, x108 = bits.Mul64(x1, arg1[4])
+       var x110 uint64
        var x111 uint64
-       var x112 p521Uint1
-       x111, x112 = p521AddcarryxU64(x61, x107, 0x0)
+       x111, x110 = bits.Mul64(x1, arg1[3])
+       var x112 uint64
        var x113 uint64
-       x113, _ = p521AddcarryxU64(x62, x109, x112)
+       x113, x112 = bits.Mul64(x1, arg1[2])
+       var x114 uint64
        var x115 uint64
-       var x116 p521Uint1
-       x115, x116 = p521AddcarryxU64(x73, x111, 0x0)
+       x115, x114 = bits.Mul64(x1, arg1[1])
+       var x116 uint64
        var x117 uint64
-       x117, _ = p521AddcarryxU64(x74, x113, x116)
+       x117, x116 = bits.Mul64(x1, arg1[0])
+       var x118 uint64
        var x119 uint64
-       var x120 p521Uint1
-       x119, x120 = p521AddcarryxU64(x105, x115, 0x0)
+       x118, x119 = bits.Add64(x117, x114, uint64(0x0))
+       var x120 uint64
        var x121 uint64
-       x121, _ = p521AddcarryxU64(x106, x117, x120)
-       x123 := ((x119 >> 58) | ((x121 << 6) & 0xffffffffffffffff))
-       x124 := (x121 >> 58)
-       x125 := (x119 & 0x3ffffffffffffff)
+       x120, x121 = bits.Add64(x115, x112, uint64(p521Uint1(x119)))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x113, x110, uint64(p521Uint1(x121)))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x111, x108, uint64(p521Uint1(x123)))
        var x126 uint64
-       var x127 p521Uint1
-       x126, x127 = p521AddcarryxU64(x53, x45, 0x0)
+       var x127 uint64
+       x126, x127 = bits.Add64(x109, x106, uint64(p521Uint1(x125)))
        var x128 uint64
-       x128, _ = p521AddcarryxU64(x54, x46, x127)
+       var x129 uint64
+       x128, x129 = bits.Add64(x107, x104, uint64(p521Uint1(x127)))
        var x130 uint64
-       var x131 p521Uint1
-       x130, x131 = p521AddcarryxU64(x63, x126, 0x0)
+       var x131 uint64
+       x130, x131 = bits.Add64(x105, x102, uint64(p521Uint1(x129)))
        var x132 uint64
-       x132, _ = p521AddcarryxU64(x64, x128, x131)
-       var x134 uint64
-       var x135 p521Uint1
-       x134, x135 = p521AddcarryxU64(x75, x130, 0x0)
+       var x133 uint64
+       x132, x133 = bits.Add64(x103, x100, uint64(p521Uint1(x131)))
+       x134 := (uint64(p521Uint1(x133)) + x101)
+       var x135 uint64
        var x136 uint64
-       x136, _ = p521AddcarryxU64(x76, x132, x135)
+       x135, x136 = bits.Add64(x82, x116, uint64(0x0))
+       var x137 uint64
        var x138 uint64
-       var x139 p521Uint1
-       x138, x139 = p521AddcarryxU64(x89, x134, 0x0)
+       x137, x138 = bits.Add64(x84, x118, uint64(p521Uint1(x136)))
+       var x139 uint64
        var x140 uint64
-       x140, _ = p521AddcarryxU64(x90, x136, x139)
+       x139, x140 = bits.Add64(x86, x120, uint64(p521Uint1(x138)))
+       var x141 uint64
        var x142 uint64
-       var x143 p521Uint1
-       x142, x143 = p521AddcarryxU64(x55, x17, 0x0)
+       x141, x142 = bits.Add64(x88, x122, uint64(p521Uint1(x140)))
+       var x143 uint64
        var x144 uint64
-       x144, _ = p521AddcarryxU64(x56, x18, x143)
+       x143, x144 = bits.Add64(x90, x124, uint64(p521Uint1(x142)))
+       var x145 uint64
        var x146 uint64
-       var x147 p521Uint1
-       x146, x147 = p521AddcarryxU64(x65, x142, 0x0)
+       x145, x146 = bits.Add64(x92, x126, uint64(p521Uint1(x144)))
+       var x147 uint64
        var x148 uint64
-       x148, _ = p521AddcarryxU64(x66, x144, x147)
+       x147, x148 = bits.Add64(x94, x128, uint64(p521Uint1(x146)))
+       var x149 uint64
        var x150 uint64
-       var x151 p521Uint1
-       x150, x151 = p521AddcarryxU64(x77, x146, 0x0)
+       x149, x150 = bits.Add64(x96, x130, uint64(p521Uint1(x148)))
+       var x151 uint64
        var x152 uint64
-       x152, _ = p521AddcarryxU64(x78, x148, x151)
+       x151, x152 = bits.Add64(x98, x132, uint64(p521Uint1(x150)))
+       var x153 uint64
        var x154 uint64
-       var x155 p521Uint1
-       x154, x155 = p521AddcarryxU64(x91, x150, 0x0)
+       x153, x154 = bits.Add64(uint64(p521Uint1(x99)), x134, uint64(p521Uint1(x152)))
+       var x155 uint64
        var x156 uint64
-       x156, _ = p521AddcarryxU64(x92, x152, x155)
+       x156, x155 = bits.Mul64(x135, 0x1ff)
+       var x157 uint64
        var x158 uint64
-       var x159 p521Uint1
-       x158, x159 = p521AddcarryxU64(x57, x19, 0x0)
+       x158, x157 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x159 uint64
        var x160 uint64
-       x160, _ = p521AddcarryxU64(x58, x20, x159)
+       x160, x159 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x161 uint64
        var x162 uint64
-       var x163 p521Uint1
-       x162, x163 = p521AddcarryxU64(x67, x158, 0x0)
+       x162, x161 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x163 uint64
        var x164 uint64
-       x164, _ = p521AddcarryxU64(x68, x160, x163)
+       x164, x163 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x165 uint64
        var x166 uint64
-       var x167 p521Uint1
-       x166, x167 = p521AddcarryxU64(x79, x162, 0x0)
+       x166, x165 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x167 uint64
        var x168 uint64
-       x168, _ = p521AddcarryxU64(x80, x164, x167)
+       x168, x167 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x169 uint64
        var x170 uint64
-       var x171 p521Uint1
-       x170, x171 = p521AddcarryxU64(x93, x166, 0x0)
+       x170, x169 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x171 uint64
        var x172 uint64
-       x172, _ = p521AddcarryxU64(x94, x168, x171)
+       x172, x171 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x173 uint64
        var x174 uint64
-       var x175 p521Uint1
-       x174, x175 = p521AddcarryxU64(x23, x21, 0x0)
+       x173, x174 = bits.Add64(x172, x169, uint64(0x0))
+       var x175 uint64
        var x176 uint64
-       x176, _ = p521AddcarryxU64(x24, x22, x175)
+       x175, x176 = bits.Add64(x170, x167, uint64(p521Uint1(x174)))
+       var x177 uint64
        var x178 uint64
-       var x179 p521Uint1
-       x178, x179 = p521AddcarryxU64(x69, x174, 0x0)
+       x177, x178 = bits.Add64(x168, x165, uint64(p521Uint1(x176)))
+       var x179 uint64
        var x180 uint64
-       x180, _ = p521AddcarryxU64(x70, x176, x179)
+       x179, x180 = bits.Add64(x166, x163, uint64(p521Uint1(x178)))
+       var x181 uint64
        var x182 uint64
-       var x183 p521Uint1
-       x182, x183 = p521AddcarryxU64(x81, x178, 0x0)
+       x181, x182 = bits.Add64(x164, x161, uint64(p521Uint1(x180)))
+       var x183 uint64
        var x184 uint64
-       x184, _ = p521AddcarryxU64(x82, x180, x183)
+       x183, x184 = bits.Add64(x162, x159, uint64(p521Uint1(x182)))
+       var x185 uint64
        var x186 uint64
-       var x187 p521Uint1
-       x186, x187 = p521AddcarryxU64(x95, x182, 0x0)
+       x185, x186 = bits.Add64(x160, x157, uint64(p521Uint1(x184)))
+       var x187 uint64
        var x188 uint64
-       x188, _ = p521AddcarryxU64(x96, x184, x187)
-       var x190 uint64
-       var x191 p521Uint1
-       x190, x191 = p521AddcarryxU64(x29, x25, 0x0)
+       x187, x188 = bits.Add64(x158, x155, uint64(p521Uint1(x186)))
+       x189 := (uint64(p521Uint1(x188)) + x156)
+       var x191 uint64
+       _, x191 = bits.Add64(x135, x171, uint64(0x0))
        var x192 uint64
-       x192, _ = p521AddcarryxU64(x30, x26, x191)
+       var x193 uint64
+       x192, x193 = bits.Add64(x137, x173, uint64(p521Uint1(x191)))
        var x194 uint64
-       var x195 p521Uint1
-       x194, x195 = p521AddcarryxU64(x71, x190, 0x0)
+       var x195 uint64
+       x194, x195 = bits.Add64(x139, x175, uint64(p521Uint1(x193)))
        var x196 uint64
-       x196, _ = p521AddcarryxU64(x72, x192, x195)
+       var x197 uint64
+       x196, x197 = bits.Add64(x141, x177, uint64(p521Uint1(x195)))
        var x198 uint64
-       var x199 p521Uint1
-       x198, x199 = p521AddcarryxU64(x83, x194, 0x0)
+       var x199 uint64
+       x198, x199 = bits.Add64(x143, x179, uint64(p521Uint1(x197)))
        var x200 uint64
-       x200, _ = p521AddcarryxU64(x84, x196, x199)
+       var x201 uint64
+       x200, x201 = bits.Add64(x145, x181, uint64(p521Uint1(x199)))
        var x202 uint64
-       var x203 p521Uint1
-       x202, x203 = p521AddcarryxU64(x97, x198, 0x0)
+       var x203 uint64
+       x202, x203 = bits.Add64(x147, x183, uint64(p521Uint1(x201)))
        var x204 uint64
-       x204, _ = p521AddcarryxU64(x98, x200, x203)
+       var x205 uint64
+       x204, x205 = bits.Add64(x149, x185, uint64(p521Uint1(x203)))
        var x206 uint64
-       var x207 p521Uint1
-       x206, x207 = p521AddcarryxU64(x31, x27, 0x0)
+       var x207 uint64
+       x206, x207 = bits.Add64(x151, x187, uint64(p521Uint1(x205)))
        var x208 uint64
-       x208, _ = p521AddcarryxU64(x32, x28, x207)
-       var x210 uint64
-       var x211 p521Uint1
-       x210, x211 = p521AddcarryxU64(x37, x206, 0x0)
+       var x209 uint64
+       x208, x209 = bits.Add64(x153, x189, uint64(p521Uint1(x207)))
+       x210 := (uint64(p521Uint1(x209)) + uint64(p521Uint1(x154)))
+       var x211 uint64
        var x212 uint64
-       x212, _ = p521AddcarryxU64(x38, x208, x211)
+       x212, x211 = bits.Mul64(x2, arg1[8])
+       var x213 uint64
        var x214 uint64
-       var x215 p521Uint1
-       x214, x215 = p521AddcarryxU64(x85, x210, 0x0)
+       x214, x213 = bits.Mul64(x2, arg1[7])
+       var x215 uint64
        var x216 uint64
-       x216, _ = p521AddcarryxU64(x86, x212, x215)
+       x216, x215 = bits.Mul64(x2, arg1[6])
+       var x217 uint64
        var x218 uint64
-       var x219 p521Uint1
-       x218, x219 = p521AddcarryxU64(x99, x214, 0x0)
+       x218, x217 = bits.Mul64(x2, arg1[5])
+       var x219 uint64
        var x220 uint64
-       x220, _ = p521AddcarryxU64(x100, x216, x219)
+       x220, x219 = bits.Mul64(x2, arg1[4])
+       var x221 uint64
        var x222 uint64
-       var x223 p521Uint1
-       x222, x223 = p521AddcarryxU64(x39, x33, 0x0)
+       x222, x221 = bits.Mul64(x2, arg1[3])
+       var x223 uint64
        var x224 uint64
-       x224, _ = p521AddcarryxU64(x40, x34, x223)
+       x224, x223 = bits.Mul64(x2, arg1[2])
+       var x225 uint64
        var x226 uint64
-       var x227 p521Uint1
-       x226, x227 = p521AddcarryxU64(x47, x222, 0x0)
+       x226, x225 = bits.Mul64(x2, arg1[1])
+       var x227 uint64
        var x228 uint64
-       x228, _ = p521AddcarryxU64(x48, x224, x227)
+       x228, x227 = bits.Mul64(x2, arg1[0])
+       var x229 uint64
        var x230 uint64
-       var x231 p521Uint1
-       x230, x231 = p521AddcarryxU64(x87, x226, 0x0)
+       x229, x230 = bits.Add64(x228, x225, uint64(0x0))
+       var x231 uint64
        var x232 uint64
-       x232, _ = p521AddcarryxU64(x88, x228, x231)
+       x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230)))
+       var x233 uint64
        var x234 uint64
-       var x235 p521Uint1
-       x234, x235 = p521AddcarryxU64(x101, x230, 0x0)
+       x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232)))
+       var x235 uint64
        var x236 uint64
-       x236, _ = p521AddcarryxU64(x102, x232, x235)
+       x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234)))
+       var x237 uint64
        var x238 uint64
-       var x239 p521Uint1
-       x238, x239 = p521AddcarryxU64(x41, x35, 0x0)
+       x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236)))
+       var x239 uint64
        var x240 uint64
-       x240, _ = p521AddcarryxU64(x42, x36, x239)
+       x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238)))
+       var x241 uint64
        var x242 uint64
-       var x243 p521Uint1
-       x242, x243 = p521AddcarryxU64(x49, x238, 0x0)
+       x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240)))
+       var x243 uint64
        var x244 uint64
-       x244, _ = p521AddcarryxU64(x50, x240, x243)
+       x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242)))
+       x245 := (uint64(p521Uint1(x244)) + x212)
        var x246 uint64
-       var x247 p521Uint1
-       x246, x247 = p521AddcarryxU64(x59, x242, 0x0)
+       var x247 uint64
+       x246, x247 = bits.Add64(x192, x227, uint64(0x0))
        var x248 uint64
-       x248, _ = p521AddcarryxU64(x60, x244, x247)
+       var x249 uint64
+       x248, x249 = bits.Add64(x194, x229, uint64(p521Uint1(x247)))
        var x250 uint64
-       var x251 p521Uint1
-       x250, x251 = p521AddcarryxU64(x103, x246, 0x0)
+       var x251 uint64
+       x250, x251 = bits.Add64(x196, x231, uint64(p521Uint1(x249)))
        var x252 uint64
-       x252, _ = p521AddcarryxU64(x104, x248, x251)
+       var x253 uint64
+       x252, x253 = bits.Add64(x198, x233, uint64(p521Uint1(x251)))
        var x254 uint64
-       var x255 p521Uint1
-       x254, x255 = p521AddcarryxU64(x123, x250, 0x0)
+       var x255 uint64
+       x254, x255 = bits.Add64(x200, x235, uint64(p521Uint1(x253)))
        var x256 uint64
-       x256, _ = p521AddcarryxU64(x124, x252, x255)
-       x258 := ((x254 >> 58) | ((x256 << 6) & 0xffffffffffffffff))
-       x259 := (x256 >> 58)
-       x260 := (x254 & 0x3ffffffffffffff)
+       var x257 uint64
+       x256, x257 = bits.Add64(x202, x237, uint64(p521Uint1(x255)))
+       var x258 uint64
+       var x259 uint64
+       x258, x259 = bits.Add64(x204, x239, uint64(p521Uint1(x257)))
+       var x260 uint64
        var x261 uint64
-       var x262 p521Uint1
-       x261, x262 = p521AddcarryxU64(x258, x234, 0x0)
+       x260, x261 = bits.Add64(x206, x241, uint64(p521Uint1(x259)))
+       var x262 uint64
        var x263 uint64
-       x263, _ = p521AddcarryxU64(x259, x236, x262)
-       x265 := ((x261 >> 58) | ((x263 << 6) & 0xffffffffffffffff))
-       x266 := (x263 >> 58)
-       x267 := (x261 & 0x3ffffffffffffff)
+       x262, x263 = bits.Add64(x208, x243, uint64(p521Uint1(x261)))
+       var x264 uint64
+       var x265 uint64
+       x264, x265 = bits.Add64(x210, x245, uint64(p521Uint1(x263)))
+       var x266 uint64
+       var x267 uint64
+       x267, x266 = bits.Mul64(x246, 0x1ff)
        var x268 uint64
-       var x269 p521Uint1
-       x268, x269 = p521AddcarryxU64(x265, x218, 0x0)
+       var x269 uint64
+       x269, x268 = bits.Mul64(x246, 0xffffffffffffffff)
        var x270 uint64
-       x270, _ = p521AddcarryxU64(x266, x220, x269)
-       x272 := ((x268 >> 58) | ((x270 << 6) & 0xffffffffffffffff))
-       x273 := (x270 >> 58)
-       x274 := (x268 & 0x3ffffffffffffff)
+       var x271 uint64
+       x271, x270 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x272 uint64
+       var x273 uint64
+       x273, x272 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x274 uint64
        var x275 uint64
-       var x276 p521Uint1
-       x275, x276 = p521AddcarryxU64(x272, x202, 0x0)
+       x275, x274 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x276 uint64
        var x277 uint64
-       x277, _ = p521AddcarryxU64(x273, x204, x276)
-       x279 := ((x275 >> 58) | ((x277 << 6) & 0xffffffffffffffff))
-       x280 := (x277 >> 58)
-       x281 := (x275 & 0x3ffffffffffffff)
+       x277, x276 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x278 uint64
+       var x279 uint64
+       x279, x278 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x280 uint64
+       var x281 uint64
+       x281, x280 = bits.Mul64(x246, 0xffffffffffffffff)
        var x282 uint64
-       var x283 p521Uint1
-       x282, x283 = p521AddcarryxU64(x279, x186, 0x0)
+       var x283 uint64
+       x283, x282 = bits.Mul64(x246, 0xffffffffffffffff)
        var x284 uint64
-       x284, _ = p521AddcarryxU64(x280, x188, x283)
-       x286 := ((x282 >> 58) | ((x284 << 6) & 0xffffffffffffffff))
-       x287 := (x284 >> 58)
-       x288 := (x282 & 0x3ffffffffffffff)
+       var x285 uint64
+       x284, x285 = bits.Add64(x283, x280, uint64(0x0))
+       var x286 uint64
+       var x287 uint64
+       x286, x287 = bits.Add64(x281, x278, uint64(p521Uint1(x285)))
+       var x288 uint64
        var x289 uint64
-       var x290 p521Uint1
-       x289, x290 = p521AddcarryxU64(x286, x170, 0x0)
+       x288, x289 = bits.Add64(x279, x276, uint64(p521Uint1(x287)))
+       var x290 uint64
        var x291 uint64
-       x291, _ = p521AddcarryxU64(x287, x172, x290)
-       x293 := ((x289 >> 58) | ((x291 << 6) & 0xffffffffffffffff))
-       x294 := (x291 >> 58)
-       x295 := (x289 & 0x3ffffffffffffff)
+       x290, x291 = bits.Add64(x277, x274, uint64(p521Uint1(x289)))
+       var x292 uint64
+       var x293 uint64
+       x292, x293 = bits.Add64(x275, x272, uint64(p521Uint1(x291)))
+       var x294 uint64
+       var x295 uint64
+       x294, x295 = bits.Add64(x273, x270, uint64(p521Uint1(x293)))
        var x296 uint64
-       var x297 p521Uint1
-       x296, x297 = p521AddcarryxU64(x293, x154, 0x0)
+       var x297 uint64
+       x296, x297 = bits.Add64(x271, x268, uint64(p521Uint1(x295)))
        var x298 uint64
-       x298, _ = p521AddcarryxU64(x294, x156, x297)
-       x300 := ((x296 >> 58) | ((x298 << 6) & 0xffffffffffffffff))
-       x301 := (x298 >> 58)
-       x302 := (x296 & 0x3ffffffffffffff)
+       var x299 uint64
+       x298, x299 = bits.Add64(x269, x266, uint64(p521Uint1(x297)))
+       x300 := (uint64(p521Uint1(x299)) + x267)
+       var x302 uint64
+       _, x302 = bits.Add64(x246, x282, uint64(0x0))
        var x303 uint64
-       var x304 p521Uint1
-       x303, x304 = p521AddcarryxU64(x300, x138, 0x0)
+       var x304 uint64
+       x303, x304 = bits.Add64(x248, x284, uint64(p521Uint1(x302)))
        var x305 uint64
-       x305, _ = p521AddcarryxU64(x301, x140, x304)
-       x307 := ((x303 >> 57) | ((x305 << 7) & 0xffffffffffffffff))
-       x308 := (x305 >> 57)
-       x309 := (x303 & 0x1ffffffffffffff)
+       var x306 uint64
+       x305, x306 = bits.Add64(x250, x286, uint64(p521Uint1(x304)))
+       var x307 uint64
+       var x308 uint64
+       x307, x308 = bits.Add64(x252, x288, uint64(p521Uint1(x306)))
+       var x309 uint64
        var x310 uint64
-       var x311 p521Uint1
-       x310, x311 = p521AddcarryxU64(x125, x307, 0x0)
-       x312 := (uint64(x311) + x308)
-       x313 := ((x310 >> 58) | ((x312 << 6) & 0xffffffffffffffff))
-       x314 := (x310 & 0x3ffffffffffffff)
-       x315 := (x313 + x260)
-       x316 := p521Uint1((x315 >> 58))
-       x317 := (x315 & 0x3ffffffffffffff)
-       x318 := (uint64(x316) + x267)
-       out1[0] = x314
-       out1[1] = x317
-       out1[2] = x318
-       out1[3] = x274
-       out1[4] = x281
-       out1[5] = x288
-       out1[6] = x295
-       out1[7] = x302
-       out1[8] = x309
+       x309, x310 = bits.Add64(x254, x290, uint64(p521Uint1(x308)))
+       var x311 uint64
+       var x312 uint64
+       x311, x312 = bits.Add64(x256, x292, uint64(p521Uint1(x310)))
+       var x313 uint64
+       var x314 uint64
+       x313, x314 = bits.Add64(x258, x294, uint64(p521Uint1(x312)))
+       var x315 uint64
+       var x316 uint64
+       x315, x316 = bits.Add64(x260, x296, uint64(p521Uint1(x314)))
+       var x317 uint64
+       var x318 uint64
+       x317, x318 = bits.Add64(x262, x298, uint64(p521Uint1(x316)))
+       var x319 uint64
+       var x320 uint64
+       x319, x320 = bits.Add64(x264, x300, uint64(p521Uint1(x318)))
+       x321 := (uint64(p521Uint1(x320)) + uint64(p521Uint1(x265)))
+       var x322 uint64
+       var x323 uint64
+       x323, x322 = bits.Mul64(x3, arg1[8])
+       var x324 uint64
+       var x325 uint64
+       x325, x324 = bits.Mul64(x3, arg1[7])
+       var x326 uint64
+       var x327 uint64
+       x327, x326 = bits.Mul64(x3, arg1[6])
+       var x328 uint64
+       var x329 uint64
+       x329, x328 = bits.Mul64(x3, arg1[5])
+       var x330 uint64
+       var x331 uint64
+       x331, x330 = bits.Mul64(x3, arg1[4])
+       var x332 uint64
+       var x333 uint64
+       x333, x332 = bits.Mul64(x3, arg1[3])
+       var x334 uint64
+       var x335 uint64
+       x335, x334 = bits.Mul64(x3, arg1[2])
+       var x336 uint64
+       var x337 uint64
+       x337, x336 = bits.Mul64(x3, arg1[1])
+       var x338 uint64
+       var x339 uint64
+       x339, x338 = bits.Mul64(x3, arg1[0])
+       var x340 uint64
+       var x341 uint64
+       x340, x341 = bits.Add64(x339, x336, uint64(0x0))
+       var x342 uint64
+       var x343 uint64
+       x342, x343 = bits.Add64(x337, x334, uint64(p521Uint1(x341)))
+       var x344 uint64
+       var x345 uint64
+       x344, x345 = bits.Add64(x335, x332, uint64(p521Uint1(x343)))
+       var x346 uint64
+       var x347 uint64
+       x346, x347 = bits.Add64(x333, x330, uint64(p521Uint1(x345)))
+       var x348 uint64
+       var x349 uint64
+       x348, x349 = bits.Add64(x331, x328, uint64(p521Uint1(x347)))
+       var x350 uint64
+       var x351 uint64
+       x350, x351 = bits.Add64(x329, x326, uint64(p521Uint1(x349)))
+       var x352 uint64
+       var x353 uint64
+       x352, x353 = bits.Add64(x327, x324, uint64(p521Uint1(x351)))
+       var x354 uint64
+       var x355 uint64
+       x354, x355 = bits.Add64(x325, x322, uint64(p521Uint1(x353)))
+       x356 := (uint64(p521Uint1(x355)) + x323)
+       var x357 uint64
+       var x358 uint64
+       x357, x358 = bits.Add64(x303, x338, uint64(0x0))
+       var x359 uint64
+       var x360 uint64
+       x359, x360 = bits.Add64(x305, x340, uint64(p521Uint1(x358)))
+       var x361 uint64
+       var x362 uint64
+       x361, x362 = bits.Add64(x307, x342, uint64(p521Uint1(x360)))
+       var x363 uint64
+       var x364 uint64
+       x363, x364 = bits.Add64(x309, x344, uint64(p521Uint1(x362)))
+       var x365 uint64
+       var x366 uint64
+       x365, x366 = bits.Add64(x311, x346, uint64(p521Uint1(x364)))
+       var x367 uint64
+       var x368 uint64
+       x367, x368 = bits.Add64(x313, x348, uint64(p521Uint1(x366)))
+       var x369 uint64
+       var x370 uint64
+       x369, x370 = bits.Add64(x315, x350, uint64(p521Uint1(x368)))
+       var x371 uint64
+       var x372 uint64
+       x371, x372 = bits.Add64(x317, x352, uint64(p521Uint1(x370)))
+       var x373 uint64
+       var x374 uint64
+       x373, x374 = bits.Add64(x319, x354, uint64(p521Uint1(x372)))
+       var x375 uint64
+       var x376 uint64
+       x375, x376 = bits.Add64(x321, x356, uint64(p521Uint1(x374)))
+       var x377 uint64
+       var x378 uint64
+       x378, x377 = bits.Mul64(x357, 0x1ff)
+       var x379 uint64
+       var x380 uint64
+       x380, x379 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x381 uint64
+       var x382 uint64
+       x382, x381 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x383 uint64
+       var x384 uint64
+       x384, x383 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x385 uint64
+       var x386 uint64
+       x386, x385 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x387 uint64
+       var x388 uint64
+       x388, x387 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x389 uint64
+       var x390 uint64
+       x390, x389 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x391 uint64
+       var x392 uint64
+       x392, x391 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x393 uint64
+       var x394 uint64
+       x394, x393 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Add64(x394, x391, uint64(0x0))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Add64(x392, x389, uint64(p521Uint1(x396)))
+       var x399 uint64
+       var x400 uint64
+       x399, x400 = bits.Add64(x390, x387, uint64(p521Uint1(x398)))
+       var x401 uint64
+       var x402 uint64
+       x401, x402 = bits.Add64(x388, x385, uint64(p521Uint1(x400)))
+       var x403 uint64
+       var x404 uint64
+       x403, x404 = bits.Add64(x386, x383, uint64(p521Uint1(x402)))
+       var x405 uint64
+       var x406 uint64
+       x405, x406 = bits.Add64(x384, x381, uint64(p521Uint1(x404)))
+       var x407 uint64
+       var x408 uint64
+       x407, x408 = bits.Add64(x382, x379, uint64(p521Uint1(x406)))
+       var x409 uint64
+       var x410 uint64
+       x409, x410 = bits.Add64(x380, x377, uint64(p521Uint1(x408)))
+       x411 := (uint64(p521Uint1(x410)) + x378)
+       var x413 uint64
+       _, x413 = bits.Add64(x357, x393, uint64(0x0))
+       var x414 uint64
+       var x415 uint64
+       x414, x415 = bits.Add64(x359, x395, uint64(p521Uint1(x413)))
+       var x416 uint64
+       var x417 uint64
+       x416, x417 = bits.Add64(x361, x397, uint64(p521Uint1(x415)))
+       var x418 uint64
+       var x419 uint64
+       x418, x419 = bits.Add64(x363, x399, uint64(p521Uint1(x417)))
+       var x420 uint64
+       var x421 uint64
+       x420, x421 = bits.Add64(x365, x401, uint64(p521Uint1(x419)))
+       var x422 uint64
+       var x423 uint64
+       x422, x423 = bits.Add64(x367, x403, uint64(p521Uint1(x421)))
+       var x424 uint64
+       var x425 uint64
+       x424, x425 = bits.Add64(x369, x405, uint64(p521Uint1(x423)))
+       var x426 uint64
+       var x427 uint64
+       x426, x427 = bits.Add64(x371, x407, uint64(p521Uint1(x425)))
+       var x428 uint64
+       var x429 uint64
+       x428, x429 = bits.Add64(x373, x409, uint64(p521Uint1(x427)))
+       var x430 uint64
+       var x431 uint64
+       x430, x431 = bits.Add64(x375, x411, uint64(p521Uint1(x429)))
+       x432 := (uint64(p521Uint1(x431)) + uint64(p521Uint1(x376)))
+       var x433 uint64
+       var x434 uint64
+       x434, x433 = bits.Mul64(x4, arg1[8])
+       var x435 uint64
+       var x436 uint64
+       x436, x435 = bits.Mul64(x4, arg1[7])
+       var x437 uint64
+       var x438 uint64
+       x438, x437 = bits.Mul64(x4, arg1[6])
+       var x439 uint64
+       var x440 uint64
+       x440, x439 = bits.Mul64(x4, arg1[5])
+       var x441 uint64
+       var x442 uint64
+       x442, x441 = bits.Mul64(x4, arg1[4])
+       var x443 uint64
+       var x444 uint64
+       x444, x443 = bits.Mul64(x4, arg1[3])
+       var x445 uint64
+       var x446 uint64
+       x446, x445 = bits.Mul64(x4, arg1[2])
+       var x447 uint64
+       var x448 uint64
+       x448, x447 = bits.Mul64(x4, arg1[1])
+       var x449 uint64
+       var x450 uint64
+       x450, x449 = bits.Mul64(x4, arg1[0])
+       var x451 uint64
+       var x452 uint64
+       x451, x452 = bits.Add64(x450, x447, uint64(0x0))
+       var x453 uint64
+       var x454 uint64
+       x453, x454 = bits.Add64(x448, x445, uint64(p521Uint1(x452)))
+       var x455 uint64
+       var x456 uint64
+       x455, x456 = bits.Add64(x446, x443, uint64(p521Uint1(x454)))
+       var x457 uint64
+       var x458 uint64
+       x457, x458 = bits.Add64(x444, x441, uint64(p521Uint1(x456)))
+       var x459 uint64
+       var x460 uint64
+       x459, x460 = bits.Add64(x442, x439, uint64(p521Uint1(x458)))
+       var x461 uint64
+       var x462 uint64
+       x461, x462 = bits.Add64(x440, x437, uint64(p521Uint1(x460)))
+       var x463 uint64
+       var x464 uint64
+       x463, x464 = bits.Add64(x438, x435, uint64(p521Uint1(x462)))
+       var x465 uint64
+       var x466 uint64
+       x465, x466 = bits.Add64(x436, x433, uint64(p521Uint1(x464)))
+       x467 := (uint64(p521Uint1(x466)) + x434)
+       var x468 uint64
+       var x469 uint64
+       x468, x469 = bits.Add64(x414, x449, uint64(0x0))
+       var x470 uint64
+       var x471 uint64
+       x470, x471 = bits.Add64(x416, x451, uint64(p521Uint1(x469)))
+       var x472 uint64
+       var x473 uint64
+       x472, x473 = bits.Add64(x418, x453, uint64(p521Uint1(x471)))
+       var x474 uint64
+       var x475 uint64
+       x474, x475 = bits.Add64(x420, x455, uint64(p521Uint1(x473)))
+       var x476 uint64
+       var x477 uint64
+       x476, x477 = bits.Add64(x422, x457, uint64(p521Uint1(x475)))
+       var x478 uint64
+       var x479 uint64
+       x478, x479 = bits.Add64(x424, x459, uint64(p521Uint1(x477)))
+       var x480 uint64
+       var x481 uint64
+       x480, x481 = bits.Add64(x426, x461, uint64(p521Uint1(x479)))
+       var x482 uint64
+       var x483 uint64
+       x482, x483 = bits.Add64(x428, x463, uint64(p521Uint1(x481)))
+       var x484 uint64
+       var x485 uint64
+       x484, x485 = bits.Add64(x430, x465, uint64(p521Uint1(x483)))
+       var x486 uint64
+       var x487 uint64
+       x486, x487 = bits.Add64(x432, x467, uint64(p521Uint1(x485)))
+       var x488 uint64
+       var x489 uint64
+       x489, x488 = bits.Mul64(x468, 0x1ff)
+       var x490 uint64
+       var x491 uint64
+       x491, x490 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x492 uint64
+       var x493 uint64
+       x493, x492 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x494 uint64
+       var x495 uint64
+       x495, x494 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x496 uint64
+       var x497 uint64
+       x497, x496 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x498 uint64
+       var x499 uint64
+       x499, x498 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x500 uint64
+       var x501 uint64
+       x501, x500 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x502 uint64
+       var x503 uint64
+       x503, x502 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x504 uint64
+       var x505 uint64
+       x505, x504 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x506 uint64
+       var x507 uint64
+       x506, x507 = bits.Add64(x505, x502, uint64(0x0))
+       var x508 uint64
+       var x509 uint64
+       x508, x509 = bits.Add64(x503, x500, uint64(p521Uint1(x507)))
+       var x510 uint64
+       var x511 uint64
+       x510, x511 = bits.Add64(x501, x498, uint64(p521Uint1(x509)))
+       var x512 uint64
+       var x513 uint64
+       x512, x513 = bits.Add64(x499, x496, uint64(p521Uint1(x511)))
+       var x514 uint64
+       var x515 uint64
+       x514, x515 = bits.Add64(x497, x494, uint64(p521Uint1(x513)))
+       var x516 uint64
+       var x517 uint64
+       x516, x517 = bits.Add64(x495, x492, uint64(p521Uint1(x515)))
+       var x518 uint64
+       var x519 uint64
+       x518, x519 = bits.Add64(x493, x490, uint64(p521Uint1(x517)))
+       var x520 uint64
+       var x521 uint64
+       x520, x521 = bits.Add64(x491, x488, uint64(p521Uint1(x519)))
+       x522 := (uint64(p521Uint1(x521)) + x489)
+       var x524 uint64
+       _, x524 = bits.Add64(x468, x504, uint64(0x0))
+       var x525 uint64
+       var x526 uint64
+       x525, x526 = bits.Add64(x470, x506, uint64(p521Uint1(x524)))
+       var x527 uint64
+       var x528 uint64
+       x527, x528 = bits.Add64(x472, x508, uint64(p521Uint1(x526)))
+       var x529 uint64
+       var x530 uint64
+       x529, x530 = bits.Add64(x474, x510, uint64(p521Uint1(x528)))
+       var x531 uint64
+       var x532 uint64
+       x531, x532 = bits.Add64(x476, x512, uint64(p521Uint1(x530)))
+       var x533 uint64
+       var x534 uint64
+       x533, x534 = bits.Add64(x478, x514, uint64(p521Uint1(x532)))
+       var x535 uint64
+       var x536 uint64
+       x535, x536 = bits.Add64(x480, x516, uint64(p521Uint1(x534)))
+       var x537 uint64
+       var x538 uint64
+       x537, x538 = bits.Add64(x482, x518, uint64(p521Uint1(x536)))
+       var x539 uint64
+       var x540 uint64
+       x539, x540 = bits.Add64(x484, x520, uint64(p521Uint1(x538)))
+       var x541 uint64
+       var x542 uint64
+       x541, x542 = bits.Add64(x486, x522, uint64(p521Uint1(x540)))
+       x543 := (uint64(p521Uint1(x542)) + uint64(p521Uint1(x487)))
+       var x544 uint64
+       var x545 uint64
+       x545, x544 = bits.Mul64(x5, arg1[8])
+       var x546 uint64
+       var x547 uint64
+       x547, x546 = bits.Mul64(x5, arg1[7])
+       var x548 uint64
+       var x549 uint64
+       x549, x548 = bits.Mul64(x5, arg1[6])
+       var x550 uint64
+       var x551 uint64
+       x551, x550 = bits.Mul64(x5, arg1[5])
+       var x552 uint64
+       var x553 uint64
+       x553, x552 = bits.Mul64(x5, arg1[4])
+       var x554 uint64
+       var x555 uint64
+       x555, x554 = bits.Mul64(x5, arg1[3])
+       var x556 uint64
+       var x557 uint64
+       x557, x556 = bits.Mul64(x5, arg1[2])
+       var x558 uint64
+       var x559 uint64
+       x559, x558 = bits.Mul64(x5, arg1[1])
+       var x560 uint64
+       var x561 uint64
+       x561, x560 = bits.Mul64(x5, arg1[0])
+       var x562 uint64
+       var x563 uint64
+       x562, x563 = bits.Add64(x561, x558, uint64(0x0))
+       var x564 uint64
+       var x565 uint64
+       x564, x565 = bits.Add64(x559, x556, uint64(p521Uint1(x563)))
+       var x566 uint64
+       var x567 uint64
+       x566, x567 = bits.Add64(x557, x554, uint64(p521Uint1(x565)))
+       var x568 uint64
+       var x569 uint64
+       x568, x569 = bits.Add64(x555, x552, uint64(p521Uint1(x567)))
+       var x570 uint64
+       var x571 uint64
+       x570, x571 = bits.Add64(x553, x550, uint64(p521Uint1(x569)))
+       var x572 uint64
+       var x573 uint64
+       x572, x573 = bits.Add64(x551, x548, uint64(p521Uint1(x571)))
+       var x574 uint64
+       var x575 uint64
+       x574, x575 = bits.Add64(x549, x546, uint64(p521Uint1(x573)))
+       var x576 uint64
+       var x577 uint64
+       x576, x577 = bits.Add64(x547, x544, uint64(p521Uint1(x575)))
+       x578 := (uint64(p521Uint1(x577)) + x545)
+       var x579 uint64
+       var x580 uint64
+       x579, x580 = bits.Add64(x525, x560, uint64(0x0))
+       var x581 uint64
+       var x582 uint64
+       x581, x582 = bits.Add64(x527, x562, uint64(p521Uint1(x580)))
+       var x583 uint64
+       var x584 uint64
+       x583, x584 = bits.Add64(x529, x564, uint64(p521Uint1(x582)))
+       var x585 uint64
+       var x586 uint64
+       x585, x586 = bits.Add64(x531, x566, uint64(p521Uint1(x584)))
+       var x587 uint64
+       var x588 uint64
+       x587, x588 = bits.Add64(x533, x568, uint64(p521Uint1(x586)))
+       var x589 uint64
+       var x590 uint64
+       x589, x590 = bits.Add64(x535, x570, uint64(p521Uint1(x588)))
+       var x591 uint64
+       var x592 uint64
+       x591, x592 = bits.Add64(x537, x572, uint64(p521Uint1(x590)))
+       var x593 uint64
+       var x594 uint64
+       x593, x594 = bits.Add64(x539, x574, uint64(p521Uint1(x592)))
+       var x595 uint64
+       var x596 uint64
+       x595, x596 = bits.Add64(x541, x576, uint64(p521Uint1(x594)))
+       var x597 uint64
+       var x598 uint64
+       x597, x598 = bits.Add64(x543, x578, uint64(p521Uint1(x596)))
+       var x599 uint64
+       var x600 uint64
+       x600, x599 = bits.Mul64(x579, 0x1ff)
+       var x601 uint64
+       var x602 uint64
+       x602, x601 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x603 uint64
+       var x604 uint64
+       x604, x603 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x605 uint64
+       var x606 uint64
+       x606, x605 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x607 uint64
+       var x608 uint64
+       x608, x607 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x609 uint64
+       var x610 uint64
+       x610, x609 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x611 uint64
+       var x612 uint64
+       x612, x611 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x613 uint64
+       var x614 uint64
+       x614, x613 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x615 uint64
+       var x616 uint64
+       x616, x615 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x617 uint64
+       var x618 uint64
+       x617, x618 = bits.Add64(x616, x613, uint64(0x0))
+       var x619 uint64
+       var x620 uint64
+       x619, x620 = bits.Add64(x614, x611, uint64(p521Uint1(x618)))
+       var x621 uint64
+       var x622 uint64
+       x621, x622 = bits.Add64(x612, x609, uint64(p521Uint1(x620)))
+       var x623 uint64
+       var x624 uint64
+       x623, x624 = bits.Add64(x610, x607, uint64(p521Uint1(x622)))
+       var x625 uint64
+       var x626 uint64
+       x625, x626 = bits.Add64(x608, x605, uint64(p521Uint1(x624)))
+       var x627 uint64
+       var x628 uint64
+       x627, x628 = bits.Add64(x606, x603, uint64(p521Uint1(x626)))
+       var x629 uint64
+       var x630 uint64
+       x629, x630 = bits.Add64(x604, x601, uint64(p521Uint1(x628)))
+       var x631 uint64
+       var x632 uint64
+       x631, x632 = bits.Add64(x602, x599, uint64(p521Uint1(x630)))
+       x633 := (uint64(p521Uint1(x632)) + x600)
+       var x635 uint64
+       _, x635 = bits.Add64(x579, x615, uint64(0x0))
+       var x636 uint64
+       var x637 uint64
+       x636, x637 = bits.Add64(x581, x617, uint64(p521Uint1(x635)))
+       var x638 uint64
+       var x639 uint64
+       x638, x639 = bits.Add64(x583, x619, uint64(p521Uint1(x637)))
+       var x640 uint64
+       var x641 uint64
+       x640, x641 = bits.Add64(x585, x621, uint64(p521Uint1(x639)))
+       var x642 uint64
+       var x643 uint64
+       x642, x643 = bits.Add64(x587, x623, uint64(p521Uint1(x641)))
+       var x644 uint64
+       var x645 uint64
+       x644, x645 = bits.Add64(x589, x625, uint64(p521Uint1(x643)))
+       var x646 uint64
+       var x647 uint64
+       x646, x647 = bits.Add64(x591, x627, uint64(p521Uint1(x645)))
+       var x648 uint64
+       var x649 uint64
+       x648, x649 = bits.Add64(x593, x629, uint64(p521Uint1(x647)))
+       var x650 uint64
+       var x651 uint64
+       x650, x651 = bits.Add64(x595, x631, uint64(p521Uint1(x649)))
+       var x652 uint64
+       var x653 uint64
+       x652, x653 = bits.Add64(x597, x633, uint64(p521Uint1(x651)))
+       x654 := (uint64(p521Uint1(x653)) + uint64(p521Uint1(x598)))
+       var x655 uint64
+       var x656 uint64
+       x656, x655 = bits.Mul64(x6, arg1[8])
+       var x657 uint64
+       var x658 uint64
+       x658, x657 = bits.Mul64(x6, arg1[7])
+       var x659 uint64
+       var x660 uint64
+       x660, x659 = bits.Mul64(x6, arg1[6])
+       var x661 uint64
+       var x662 uint64
+       x662, x661 = bits.Mul64(x6, arg1[5])
+       var x663 uint64
+       var x664 uint64
+       x664, x663 = bits.Mul64(x6, arg1[4])
+       var x665 uint64
+       var x666 uint64
+       x666, x665 = bits.Mul64(x6, arg1[3])
+       var x667 uint64
+       var x668 uint64
+       x668, x667 = bits.Mul64(x6, arg1[2])
+       var x669 uint64
+       var x670 uint64
+       x670, x669 = bits.Mul64(x6, arg1[1])
+       var x671 uint64
+       var x672 uint64
+       x672, x671 = bits.Mul64(x6, arg1[0])
+       var x673 uint64
+       var x674 uint64
+       x673, x674 = bits.Add64(x672, x669, uint64(0x0))
+       var x675 uint64
+       var x676 uint64
+       x675, x676 = bits.Add64(x670, x667, uint64(p521Uint1(x674)))
+       var x677 uint64
+       var x678 uint64
+       x677, x678 = bits.Add64(x668, x665, uint64(p521Uint1(x676)))
+       var x679 uint64
+       var x680 uint64
+       x679, x680 = bits.Add64(x666, x663, uint64(p521Uint1(x678)))
+       var x681 uint64
+       var x682 uint64
+       x681, x682 = bits.Add64(x664, x661, uint64(p521Uint1(x680)))
+       var x683 uint64
+       var x684 uint64
+       x683, x684 = bits.Add64(x662, x659, uint64(p521Uint1(x682)))
+       var x685 uint64
+       var x686 uint64
+       x685, x686 = bits.Add64(x660, x657, uint64(p521Uint1(x684)))
+       var x687 uint64
+       var x688 uint64
+       x687, x688 = bits.Add64(x658, x655, uint64(p521Uint1(x686)))
+       x689 := (uint64(p521Uint1(x688)) + x656)
+       var x690 uint64
+       var x691 uint64
+       x690, x691 = bits.Add64(x636, x671, uint64(0x0))
+       var x692 uint64
+       var x693 uint64
+       x692, x693 = bits.Add64(x638, x673, uint64(p521Uint1(x691)))
+       var x694 uint64
+       var x695 uint64
+       x694, x695 = bits.Add64(x640, x675, uint64(p521Uint1(x693)))
+       var x696 uint64
+       var x697 uint64
+       x696, x697 = bits.Add64(x642, x677, uint64(p521Uint1(x695)))
+       var x698 uint64
+       var x699 uint64
+       x698, x699 = bits.Add64(x644, x679, uint64(p521Uint1(x697)))
+       var x700 uint64
+       var x701 uint64
+       x700, x701 = bits.Add64(x646, x681, uint64(p521Uint1(x699)))
+       var x702 uint64
+       var x703 uint64
+       x702, x703 = bits.Add64(x648, x683, uint64(p521Uint1(x701)))
+       var x704 uint64
+       var x705 uint64
+       x704, x705 = bits.Add64(x650, x685, uint64(p521Uint1(x703)))
+       var x706 uint64
+       var x707 uint64
+       x706, x707 = bits.Add64(x652, x687, uint64(p521Uint1(x705)))
+       var x708 uint64
+       var x709 uint64
+       x708, x709 = bits.Add64(x654, x689, uint64(p521Uint1(x707)))
+       var x710 uint64
+       var x711 uint64
+       x711, x710 = bits.Mul64(x690, 0x1ff)
+       var x712 uint64
+       var x713 uint64
+       x713, x712 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x714 uint64
+       var x715 uint64
+       x715, x714 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x716 uint64
+       var x717 uint64
+       x717, x716 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x718 uint64
+       var x719 uint64
+       x719, x718 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x720 uint64
+       var x721 uint64
+       x721, x720 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x722 uint64
+       var x723 uint64
+       x723, x722 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x724 uint64
+       var x725 uint64
+       x725, x724 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x726 uint64
+       var x727 uint64
+       x727, x726 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x728 uint64
+       var x729 uint64
+       x728, x729 = bits.Add64(x727, x724, uint64(0x0))
+       var x730 uint64
+       var x731 uint64
+       x730, x731 = bits.Add64(x725, x722, uint64(p521Uint1(x729)))
+       var x732 uint64
+       var x733 uint64
+       x732, x733 = bits.Add64(x723, x720, uint64(p521Uint1(x731)))
+       var x734 uint64
+       var x735 uint64
+       x734, x735 = bits.Add64(x721, x718, uint64(p521Uint1(x733)))
+       var x736 uint64
+       var x737 uint64
+       x736, x737 = bits.Add64(x719, x716, uint64(p521Uint1(x735)))
+       var x738 uint64
+       var x739 uint64
+       x738, x739 = bits.Add64(x717, x714, uint64(p521Uint1(x737)))
+       var x740 uint64
+       var x741 uint64
+       x740, x741 = bits.Add64(x715, x712, uint64(p521Uint1(x739)))
+       var x742 uint64
+       var x743 uint64
+       x742, x743 = bits.Add64(x713, x710, uint64(p521Uint1(x741)))
+       x744 := (uint64(p521Uint1(x743)) + x711)
+       var x746 uint64
+       _, x746 = bits.Add64(x690, x726, uint64(0x0))
+       var x747 uint64
+       var x748 uint64
+       x747, x748 = bits.Add64(x692, x728, uint64(p521Uint1(x746)))
+       var x749 uint64
+       var x750 uint64
+       x749, x750 = bits.Add64(x694, x730, uint64(p521Uint1(x748)))
+       var x751 uint64
+       var x752 uint64
+       x751, x752 = bits.Add64(x696, x732, uint64(p521Uint1(x750)))
+       var x753 uint64
+       var x754 uint64
+       x753, x754 = bits.Add64(x698, x734, uint64(p521Uint1(x752)))
+       var x755 uint64
+       var x756 uint64
+       x755, x756 = bits.Add64(x700, x736, uint64(p521Uint1(x754)))
+       var x757 uint64
+       var x758 uint64
+       x757, x758 = bits.Add64(x702, x738, uint64(p521Uint1(x756)))
+       var x759 uint64
+       var x760 uint64
+       x759, x760 = bits.Add64(x704, x740, uint64(p521Uint1(x758)))
+       var x761 uint64
+       var x762 uint64
+       x761, x762 = bits.Add64(x706, x742, uint64(p521Uint1(x760)))
+       var x763 uint64
+       var x764 uint64
+       x763, x764 = bits.Add64(x708, x744, uint64(p521Uint1(x762)))
+       x765 := (uint64(p521Uint1(x764)) + uint64(p521Uint1(x709)))
+       var x766 uint64
+       var x767 uint64
+       x767, x766 = bits.Mul64(x7, arg1[8])
+       var x768 uint64
+       var x769 uint64
+       x769, x768 = bits.Mul64(x7, arg1[7])
+       var x770 uint64
+       var x771 uint64
+       x771, x770 = bits.Mul64(x7, arg1[6])
+       var x772 uint64
+       var x773 uint64
+       x773, x772 = bits.Mul64(x7, arg1[5])
+       var x774 uint64
+       var x775 uint64
+       x775, x774 = bits.Mul64(x7, arg1[4])
+       var x776 uint64
+       var x777 uint64
+       x777, x776 = bits.Mul64(x7, arg1[3])
+       var x778 uint64
+       var x779 uint64
+       x779, x778 = bits.Mul64(x7, arg1[2])
+       var x780 uint64
+       var x781 uint64
+       x781, x780 = bits.Mul64(x7, arg1[1])
+       var x782 uint64
+       var x783 uint64
+       x783, x782 = bits.Mul64(x7, arg1[0])
+       var x784 uint64
+       var x785 uint64
+       x784, x785 = bits.Add64(x783, x780, uint64(0x0))
+       var x786 uint64
+       var x787 uint64
+       x786, x787 = bits.Add64(x781, x778, uint64(p521Uint1(x785)))
+       var x788 uint64
+       var x789 uint64
+       x788, x789 = bits.Add64(x779, x776, uint64(p521Uint1(x787)))
+       var x790 uint64
+       var x791 uint64
+       x790, x791 = bits.Add64(x777, x774, uint64(p521Uint1(x789)))
+       var x792 uint64
+       var x793 uint64
+       x792, x793 = bits.Add64(x775, x772, uint64(p521Uint1(x791)))
+       var x794 uint64
+       var x795 uint64
+       x794, x795 = bits.Add64(x773, x770, uint64(p521Uint1(x793)))
+       var x796 uint64
+       var x797 uint64
+       x796, x797 = bits.Add64(x771, x768, uint64(p521Uint1(x795)))
+       var x798 uint64
+       var x799 uint64
+       x798, x799 = bits.Add64(x769, x766, uint64(p521Uint1(x797)))
+       x800 := (uint64(p521Uint1(x799)) + x767)
+       var x801 uint64
+       var x802 uint64
+       x801, x802 = bits.Add64(x747, x782, uint64(0x0))
+       var x803 uint64
+       var x804 uint64
+       x803, x804 = bits.Add64(x749, x784, uint64(p521Uint1(x802)))
+       var x805 uint64
+       var x806 uint64
+       x805, x806 = bits.Add64(x751, x786, uint64(p521Uint1(x804)))
+       var x807 uint64
+       var x808 uint64
+       x807, x808 = bits.Add64(x753, x788, uint64(p521Uint1(x806)))
+       var x809 uint64
+       var x810 uint64
+       x809, x810 = bits.Add64(x755, x790, uint64(p521Uint1(x808)))
+       var x811 uint64
+       var x812 uint64
+       x811, x812 = bits.Add64(x757, x792, uint64(p521Uint1(x810)))
+       var x813 uint64
+       var x814 uint64
+       x813, x814 = bits.Add64(x759, x794, uint64(p521Uint1(x812)))
+       var x815 uint64
+       var x816 uint64
+       x815, x816 = bits.Add64(x761, x796, uint64(p521Uint1(x814)))
+       var x817 uint64
+       var x818 uint64
+       x817, x818 = bits.Add64(x763, x798, uint64(p521Uint1(x816)))
+       var x819 uint64
+       var x820 uint64
+       x819, x820 = bits.Add64(x765, x800, uint64(p521Uint1(x818)))
+       var x821 uint64
+       var x822 uint64
+       x822, x821 = bits.Mul64(x801, 0x1ff)
+       var x823 uint64
+       var x824 uint64
+       x824, x823 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x825 uint64
+       var x826 uint64
+       x826, x825 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x827 uint64
+       var x828 uint64
+       x828, x827 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x829 uint64
+       var x830 uint64
+       x830, x829 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x831 uint64
+       var x832 uint64
+       x832, x831 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x833 uint64
+       var x834 uint64
+       x834, x833 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x835 uint64
+       var x836 uint64
+       x836, x835 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x837 uint64
+       var x838 uint64
+       x838, x837 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x839 uint64
+       var x840 uint64
+       x839, x840 = bits.Add64(x838, x835, uint64(0x0))
+       var x841 uint64
+       var x842 uint64
+       x841, x842 = bits.Add64(x836, x833, uint64(p521Uint1(x840)))
+       var x843 uint64
+       var x844 uint64
+       x843, x844 = bits.Add64(x834, x831, uint64(p521Uint1(x842)))
+       var x845 uint64
+       var x846 uint64
+       x845, x846 = bits.Add64(x832, x829, uint64(p521Uint1(x844)))
+       var x847 uint64
+       var x848 uint64
+       x847, x848 = bits.Add64(x830, x827, uint64(p521Uint1(x846)))
+       var x849 uint64
+       var x850 uint64
+       x849, x850 = bits.Add64(x828, x825, uint64(p521Uint1(x848)))
+       var x851 uint64
+       var x852 uint64
+       x851, x852 = bits.Add64(x826, x823, uint64(p521Uint1(x850)))
+       var x853 uint64
+       var x854 uint64
+       x853, x854 = bits.Add64(x824, x821, uint64(p521Uint1(x852)))
+       x855 := (uint64(p521Uint1(x854)) + x822)
+       var x857 uint64
+       _, x857 = bits.Add64(x801, x837, uint64(0x0))
+       var x858 uint64
+       var x859 uint64
+       x858, x859 = bits.Add64(x803, x839, uint64(p521Uint1(x857)))
+       var x860 uint64
+       var x861 uint64
+       x860, x861 = bits.Add64(x805, x841, uint64(p521Uint1(x859)))
+       var x862 uint64
+       var x863 uint64
+       x862, x863 = bits.Add64(x807, x843, uint64(p521Uint1(x861)))
+       var x864 uint64
+       var x865 uint64
+       x864, x865 = bits.Add64(x809, x845, uint64(p521Uint1(x863)))
+       var x866 uint64
+       var x867 uint64
+       x866, x867 = bits.Add64(x811, x847, uint64(p521Uint1(x865)))
+       var x868 uint64
+       var x869 uint64
+       x868, x869 = bits.Add64(x813, x849, uint64(p521Uint1(x867)))
+       var x870 uint64
+       var x871 uint64
+       x870, x871 = bits.Add64(x815, x851, uint64(p521Uint1(x869)))
+       var x872 uint64
+       var x873 uint64
+       x872, x873 = bits.Add64(x817, x853, uint64(p521Uint1(x871)))
+       var x874 uint64
+       var x875 uint64
+       x874, x875 = bits.Add64(x819, x855, uint64(p521Uint1(x873)))
+       x876 := (uint64(p521Uint1(x875)) + uint64(p521Uint1(x820)))
+       var x877 uint64
+       var x878 uint64
+       x878, x877 = bits.Mul64(x8, arg1[8])
+       var x879 uint64
+       var x880 uint64
+       x880, x879 = bits.Mul64(x8, arg1[7])
+       var x881 uint64
+       var x882 uint64
+       x882, x881 = bits.Mul64(x8, arg1[6])
+       var x883 uint64
+       var x884 uint64
+       x884, x883 = bits.Mul64(x8, arg1[5])
+       var x885 uint64
+       var x886 uint64
+       x886, x885 = bits.Mul64(x8, arg1[4])
+       var x887 uint64
+       var x888 uint64
+       x888, x887 = bits.Mul64(x8, arg1[3])
+       var x889 uint64
+       var x890 uint64
+       x890, x889 = bits.Mul64(x8, arg1[2])
+       var x891 uint64
+       var x892 uint64
+       x892, x891 = bits.Mul64(x8, arg1[1])
+       var x893 uint64
+       var x894 uint64
+       x894, x893 = bits.Mul64(x8, arg1[0])
+       var x895 uint64
+       var x896 uint64
+       x895, x896 = bits.Add64(x894, x891, uint64(0x0))
+       var x897 uint64
+       var x898 uint64
+       x897, x898 = bits.Add64(x892, x889, uint64(p521Uint1(x896)))
+       var x899 uint64
+       var x900 uint64
+       x899, x900 = bits.Add64(x890, x887, uint64(p521Uint1(x898)))
+       var x901 uint64
+       var x902 uint64
+       x901, x902 = bits.Add64(x888, x885, uint64(p521Uint1(x900)))
+       var x903 uint64
+       var x904 uint64
+       x903, x904 = bits.Add64(x886, x883, uint64(p521Uint1(x902)))
+       var x905 uint64
+       var x906 uint64
+       x905, x906 = bits.Add64(x884, x881, uint64(p521Uint1(x904)))
+       var x907 uint64
+       var x908 uint64
+       x907, x908 = bits.Add64(x882, x879, uint64(p521Uint1(x906)))
+       var x909 uint64
+       var x910 uint64
+       x909, x910 = bits.Add64(x880, x877, uint64(p521Uint1(x908)))
+       x911 := (uint64(p521Uint1(x910)) + x878)
+       var x912 uint64
+       var x913 uint64
+       x912, x913 = bits.Add64(x858, x893, uint64(0x0))
+       var x914 uint64
+       var x915 uint64
+       x914, x915 = bits.Add64(x860, x895, uint64(p521Uint1(x913)))
+       var x916 uint64
+       var x917 uint64
+       x916, x917 = bits.Add64(x862, x897, uint64(p521Uint1(x915)))
+       var x918 uint64
+       var x919 uint64
+       x918, x919 = bits.Add64(x864, x899, uint64(p521Uint1(x917)))
+       var x920 uint64
+       var x921 uint64
+       x920, x921 = bits.Add64(x866, x901, uint64(p521Uint1(x919)))
+       var x922 uint64
+       var x923 uint64
+       x922, x923 = bits.Add64(x868, x903, uint64(p521Uint1(x921)))
+       var x924 uint64
+       var x925 uint64
+       x924, x925 = bits.Add64(x870, x905, uint64(p521Uint1(x923)))
+       var x926 uint64
+       var x927 uint64
+       x926, x927 = bits.Add64(x872, x907, uint64(p521Uint1(x925)))
+       var x928 uint64
+       var x929 uint64
+       x928, x929 = bits.Add64(x874, x909, uint64(p521Uint1(x927)))
+       var x930 uint64
+       var x931 uint64
+       x930, x931 = bits.Add64(x876, x911, uint64(p521Uint1(x929)))
+       var x932 uint64
+       var x933 uint64
+       x933, x932 = bits.Mul64(x912, 0x1ff)
+       var x934 uint64
+       var x935 uint64
+       x935, x934 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x936 uint64
+       var x937 uint64
+       x937, x936 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x938 uint64
+       var x939 uint64
+       x939, x938 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x940 uint64
+       var x941 uint64
+       x941, x940 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x942 uint64
+       var x943 uint64
+       x943, x942 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x944 uint64
+       var x945 uint64
+       x945, x944 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x946 uint64
+       var x947 uint64
+       x947, x946 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x948 uint64
+       var x949 uint64
+       x949, x948 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x950 uint64
+       var x951 uint64
+       x950, x951 = bits.Add64(x949, x946, uint64(0x0))
+       var x952 uint64
+       var x953 uint64
+       x952, x953 = bits.Add64(x947, x944, uint64(p521Uint1(x951)))
+       var x954 uint64
+       var x955 uint64
+       x954, x955 = bits.Add64(x945, x942, uint64(p521Uint1(x953)))
+       var x956 uint64
+       var x957 uint64
+       x956, x957 = bits.Add64(x943, x940, uint64(p521Uint1(x955)))
+       var x958 uint64
+       var x959 uint64
+       x958, x959 = bits.Add64(x941, x938, uint64(p521Uint1(x957)))
+       var x960 uint64
+       var x961 uint64
+       x960, x961 = bits.Add64(x939, x936, uint64(p521Uint1(x959)))
+       var x962 uint64
+       var x963 uint64
+       x962, x963 = bits.Add64(x937, x934, uint64(p521Uint1(x961)))
+       var x964 uint64
+       var x965 uint64
+       x964, x965 = bits.Add64(x935, x932, uint64(p521Uint1(x963)))
+       x966 := (uint64(p521Uint1(x965)) + x933)
+       var x968 uint64
+       _, x968 = bits.Add64(x912, x948, uint64(0x0))
+       var x969 uint64
+       var x970 uint64
+       x969, x970 = bits.Add64(x914, x950, uint64(p521Uint1(x968)))
+       var x971 uint64
+       var x972 uint64
+       x971, x972 = bits.Add64(x916, x952, uint64(p521Uint1(x970)))
+       var x973 uint64
+       var x974 uint64
+       x973, x974 = bits.Add64(x918, x954, uint64(p521Uint1(x972)))
+       var x975 uint64
+       var x976 uint64
+       x975, x976 = bits.Add64(x920, x956, uint64(p521Uint1(x974)))
+       var x977 uint64
+       var x978 uint64
+       x977, x978 = bits.Add64(x922, x958, uint64(p521Uint1(x976)))
+       var x979 uint64
+       var x980 uint64
+       x979, x980 = bits.Add64(x924, x960, uint64(p521Uint1(x978)))
+       var x981 uint64
+       var x982 uint64
+       x981, x982 = bits.Add64(x926, x962, uint64(p521Uint1(x980)))
+       var x983 uint64
+       var x984 uint64
+       x983, x984 = bits.Add64(x928, x964, uint64(p521Uint1(x982)))
+       var x985 uint64
+       var x986 uint64
+       x985, x986 = bits.Add64(x930, x966, uint64(p521Uint1(x984)))
+       x987 := (uint64(p521Uint1(x986)) + uint64(p521Uint1(x931)))
+       var x988 uint64
+       var x989 uint64
+       x988, x989 = bits.Sub64(x969, 0xffffffffffffffff, uint64(0x0))
+       var x990 uint64
+       var x991 uint64
+       x990, x991 = bits.Sub64(x971, 0xffffffffffffffff, uint64(p521Uint1(x989)))
+       var x992 uint64
+       var x993 uint64
+       x992, x993 = bits.Sub64(x973, 0xffffffffffffffff, uint64(p521Uint1(x991)))
+       var x994 uint64
+       var x995 uint64
+       x994, x995 = bits.Sub64(x975, 0xffffffffffffffff, uint64(p521Uint1(x993)))
+       var x996 uint64
+       var x997 uint64
+       x996, x997 = bits.Sub64(x977, 0xffffffffffffffff, uint64(p521Uint1(x995)))
+       var x998 uint64
+       var x999 uint64
+       x998, x999 = bits.Sub64(x979, 0xffffffffffffffff, uint64(p521Uint1(x997)))
+       var x1000 uint64
+       var x1001 uint64
+       x1000, x1001 = bits.Sub64(x981, 0xffffffffffffffff, uint64(p521Uint1(x999)))
+       var x1002 uint64
+       var x1003 uint64
+       x1002, x1003 = bits.Sub64(x983, 0xffffffffffffffff, uint64(p521Uint1(x1001)))
+       var x1004 uint64
+       var x1005 uint64
+       x1004, x1005 = bits.Sub64(x985, 0x1ff, uint64(p521Uint1(x1003)))
+       var x1007 uint64
+       _, x1007 = bits.Sub64(x987, uint64(0x0), uint64(p521Uint1(x1005)))
+       var x1008 uint64
+       p521CmovznzU64(&x1008, p521Uint1(x1007), x988, x969)
+       var x1009 uint64
+       p521CmovznzU64(&x1009, p521Uint1(x1007), x990, x971)
+       var x1010 uint64
+       p521CmovznzU64(&x1010, p521Uint1(x1007), x992, x973)
+       var x1011 uint64
+       p521CmovznzU64(&x1011, p521Uint1(x1007), x994, x975)
+       var x1012 uint64
+       p521CmovznzU64(&x1012, p521Uint1(x1007), x996, x977)
+       var x1013 uint64
+       p521CmovznzU64(&x1013, p521Uint1(x1007), x998, x979)
+       var x1014 uint64
+       p521CmovznzU64(&x1014, p521Uint1(x1007), x1000, x981)
+       var x1015 uint64
+       p521CmovznzU64(&x1015, p521Uint1(x1007), x1002, x983)
+       var x1016 uint64
+       p521CmovznzU64(&x1016, p521Uint1(x1007), x1004, x985)
+       out1[0] = x1008
+       out1[1] = x1009
+       out1[2] = x1010
+       out1[3] = x1011
+       out1[4] = x1012
+       out1[5] = x1013
+       out1[6] = x1014
+       out1[7] = x1015
+       out1[8] = x1016
 }
 
-// p521Carry reduces a field element.
+// p521Add adds two field elements in the Montgomery domain.
 //
+// Preconditions:
+//   0 ≤ eval arg1 < m
+//   0 ≤ eval arg2 < m
 // Postconditions:
-//   eval out1 mod m = eval arg1 mod m
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
+//   0 ≤ eval out1 < m
 //
-// Input Bounds:
-//   arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-func p521Carry(out1 *[9]uint64, arg1 *[9]uint64) {
-       x1 := arg1[0]
-       x2 := ((x1 >> 58) + arg1[1])
-       x3 := ((x2 >> 58) + arg1[2])
-       x4 := ((x3 >> 58) + arg1[3])
-       x5 := ((x4 >> 58) + arg1[4])
-       x6 := ((x5 >> 58) + arg1[5])
-       x7 := ((x6 >> 58) + arg1[6])
-       x8 := ((x7 >> 58) + arg1[7])
-       x9 := ((x8 >> 58) + arg1[8])
-       x10 := ((x1 & 0x3ffffffffffffff) + (x9 >> 57))
-       x11 := (uint64(p521Uint1((x10 >> 58))) + (x2 & 0x3ffffffffffffff))
-       x12 := (x10 & 0x3ffffffffffffff)
-       x13 := (x11 & 0x3ffffffffffffff)
-       x14 := (uint64(p521Uint1((x11 >> 58))) + (x3 & 0x3ffffffffffffff))
-       x15 := (x4 & 0x3ffffffffffffff)
-       x16 := (x5 & 0x3ffffffffffffff)
-       x17 := (x6 & 0x3ffffffffffffff)
-       x18 := (x7 & 0x3ffffffffffffff)
-       x19 := (x8 & 0x3ffffffffffffff)
-       x20 := (x9 & 0x1ffffffffffffff)
-       out1[0] = x12
-       out1[1] = x13
-       out1[2] = x14
-       out1[3] = x15
-       out1[4] = x16
-       out1[5] = x17
-       out1[6] = x18
-       out1[7] = x19
-       out1[8] = x20
-}
+func p521Add(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p521Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p521Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p521Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Add64(arg1[4], arg2[4], uint64(p521Uint1(x8)))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Add64(arg1[5], arg2[5], uint64(p521Uint1(x10)))
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Add64(arg1[6], arg2[6], uint64(p521Uint1(x12)))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(arg1[7], arg2[7], uint64(p521Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(arg1[8], arg2[8], uint64(p521Uint1(x16)))
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Sub64(x1, 0xffffffffffffffff, uint64(0x0))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Sub64(x3, 0xffffffffffffffff, uint64(p521Uint1(x20)))
+       var x23 uint64
+       var x24 uint64
+       x23, x24 = bits.Sub64(x5, 0xffffffffffffffff, uint64(p521Uint1(x22)))
+       var x25 uint64
+       var x26 uint64
+       x25, x26 = bits.Sub64(x7, 0xffffffffffffffff, uint64(p521Uint1(x24)))
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Sub64(x9, 0xffffffffffffffff, uint64(p521Uint1(x26)))
+       var x29 uint64
+       var x30 uint64
+       x29, x30 = bits.Sub64(x11, 0xffffffffffffffff, uint64(p521Uint1(x28)))
+       var x31 uint64
+       var x32 uint64
+       x31, x32 = bits.Sub64(x13, 0xffffffffffffffff, uint64(p521Uint1(x30)))
+       var x33 uint64
+       var x34 uint64
+       x33, x34 = bits.Sub64(x15, 0xffffffffffffffff, uint64(p521Uint1(x32)))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Sub64(x17, 0x1ff, uint64(p521Uint1(x34)))
+       var x38 uint64
+       _, x38 = bits.Sub64(uint64(p521Uint1(x18)), uint64(0x0), uint64(p521Uint1(x36)))
+       var x39 uint64
+       p521CmovznzU64(&x39, p521Uint1(x38), x19, x1)
+       var x40 uint64
+       p521CmovznzU64(&x40, p521Uint1(x38), x21, x3)
+       var x41 uint64
+       p521CmovznzU64(&x41, p521Uint1(x38), x23, x5)
+       var x42 uint64
+       p521CmovznzU64(&x42, p521Uint1(x38), x25, x7)
+       var x43 uint64
+       p521CmovznzU64(&x43, p521Uint1(x38), x27, x9)
+       var x44 uint64
+       p521CmovznzU64(&x44, p521Uint1(x38), x29, x11)
+       var x45 uint64
+       p521CmovznzU64(&x45, p521Uint1(x38), x31, x13)
+       var x46 uint64
+       p521CmovznzU64(&x46, p521Uint1(x38), x33, x15)
+       var x47 uint64
+       p521CmovznzU64(&x47, p521Uint1(x38), x35, x17)
+       out1[0] = x39
+       out1[1] = x40
+       out1[2] = x41
+       out1[3] = x42
+       out1[4] = x43
+       out1[5] = x44
+       out1[6] = x45
+       out1[7] = x46
+       out1[8] = x47
+}
+
+// p521Sub subtracts two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+//   0 ≤ eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
+//   0 ≤ eval out1 < m
+//
+func p521Sub(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p521Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p521Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p521Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Sub64(arg1[4], arg2[4], uint64(p521Uint1(x8)))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Sub64(arg1[5], arg2[5], uint64(p521Uint1(x10)))
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Sub64(arg1[6], arg2[6], uint64(p521Uint1(x12)))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Sub64(arg1[7], arg2[7], uint64(p521Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Sub64(arg1[8], arg2[8], uint64(p521Uint1(x16)))
+       var x19 uint64
+       p521CmovznzU64(&x19, p521Uint1(x18), uint64(0x0), 0xffffffffffffffff)
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(x1, x19, uint64(0x0))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x3, x19, uint64(p521Uint1(x21)))
+       var x24 uint64
+       var x25 uint64
+       x24, x25 = bits.Add64(x5, x19, uint64(p521Uint1(x23)))
+       var x26 uint64
+       var x27 uint64
+       x26, x27 = bits.Add64(x7, x19, uint64(p521Uint1(x25)))
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(x9, x19, uint64(p521Uint1(x27)))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(x11, x19, uint64(p521Uint1(x29)))
+       var x32 uint64
+       var x33 uint64
+       x32, x33 = bits.Add64(x13, x19, uint64(p521Uint1(x31)))
+       var x34 uint64
+       var x35 uint64
+       x34, x35 = bits.Add64(x15, x19, uint64(p521Uint1(x33)))
+       var x36 uint64
+       x36, _ = bits.Add64(x17, (x19 & 0x1ff), uint64(p521Uint1(x35)))
+       out1[0] = x20
+       out1[1] = x22
+       out1[2] = x24
+       out1[3] = x26
+       out1[4] = x28
+       out1[5] = x30
+       out1[6] = x32
+       out1[7] = x34
+       out1[8] = x36
+}
+
+// p521SetOne returns the field element one in the Montgomery domain.
+//
+// Postconditions:
+//   eval (from_montgomery out1) mod m = 1 mod m
+//   0 ≤ eval out1 < m
+//
+func p521SetOne(out1 *p521MontgomeryDomainFieldElement) {
+       out1[0] = 0x80000000000000
+       out1[1] = uint64(0x0)
+       out1[2] = uint64(0x0)
+       out1[3] = uint64(0x0)
+       out1[4] = uint64(0x0)
+       out1[5] = uint64(0x0)
+       out1[6] = uint64(0x0)
+       out1[7] = uint64(0x0)
+       out1[8] = uint64(0x0)
+}
+
+// p521FromMontgomery translates a field element out of the Montgomery domain.
+//
+// Preconditions:
+//   0 ≤ eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^9) mod m
+//   0 ≤ eval out1 < m
+//
+func p521FromMontgomery(out1 *p521NonMontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement) {
+       x1 := arg1[0]
+       var x2 uint64
+       var x3 uint64
+       x3, x2 = bits.Mul64(x1, 0x1ff)
+       var x4 uint64
+       var x5 uint64
+       x5, x4 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x6 uint64
+       var x7 uint64
+       x7, x6 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x8 uint64
+       var x9 uint64
+       x9, x8 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x10 uint64
+       var x11 uint64
+       x11, x10 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x12 uint64
+       var x13 uint64
+       x13, x12 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x14 uint64
+       var x15 uint64
+       x15, x14 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x16 uint64
+       var x17 uint64
+       x17, x16 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x18 uint64
+       var x19 uint64
+       x19, x18 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(x19, x16, uint64(0x0))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x17, x14, uint64(p521Uint1(x21)))
+       var x24 uint64
+       var x25 uint64
+       x24, x25 = bits.Add64(x15, x12, uint64(p521Uint1(x23)))
+       var x26 uint64
+       var x27 uint64
+       x26, x27 = bits.Add64(x13, x10, uint64(p521Uint1(x25)))
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(x11, x8, uint64(p521Uint1(x27)))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(x9, x6, uint64(p521Uint1(x29)))
+       var x32 uint64
+       var x33 uint64
+       x32, x33 = bits.Add64(x7, x4, uint64(p521Uint1(x31)))
+       var x34 uint64
+       var x35 uint64
+       x34, x35 = bits.Add64(x5, x2, uint64(p521Uint1(x33)))
+       var x37 uint64
+       _, x37 = bits.Add64(x1, x18, uint64(0x0))
+       var x38 uint64
+       var x39 uint64
+       x38, x39 = bits.Add64(uint64(0x0), x20, uint64(p521Uint1(x37)))
+       var x40 uint64
+       var x41 uint64
+       x40, x41 = bits.Add64(uint64(0x0), x22, uint64(p521Uint1(x39)))
+       var x42 uint64
+       var x43 uint64
+       x42, x43 = bits.Add64(uint64(0x0), x24, uint64(p521Uint1(x41)))
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(uint64(0x0), x26, uint64(p521Uint1(x43)))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64(uint64(0x0), x28, uint64(p521Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(uint64(0x0), x30, uint64(p521Uint1(x47)))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(uint64(0x0), x32, uint64(p521Uint1(x49)))
+       var x52 uint64
+       var x53 uint64
+       x52, x53 = bits.Add64(uint64(0x0), x34, uint64(p521Uint1(x51)))
+       var x54 uint64
+       var x55 uint64
+       x54, x55 = bits.Add64(x38, arg1[1], uint64(0x0))
+       var x56 uint64
+       var x57 uint64
+       x56, x57 = bits.Add64(x40, uint64(0x0), uint64(p521Uint1(x55)))
+       var x58 uint64
+       var x59 uint64
+       x58, x59 = bits.Add64(x42, uint64(0x0), uint64(p521Uint1(x57)))
+       var x60 uint64
+       var x61 uint64
+       x60, x61 = bits.Add64(x44, uint64(0x0), uint64(p521Uint1(x59)))
+       var x62 uint64
+       var x63 uint64
+       x62, x63 = bits.Add64(x46, uint64(0x0), uint64(p521Uint1(x61)))
+       var x64 uint64
+       var x65 uint64
+       x64, x65 = bits.Add64(x48, uint64(0x0), uint64(p521Uint1(x63)))
+       var x66 uint64
+       var x67 uint64
+       x66, x67 = bits.Add64(x50, uint64(0x0), uint64(p521Uint1(x65)))
+       var x68 uint64
+       var x69 uint64
+       x68, x69 = bits.Add64(x52, uint64(0x0), uint64(p521Uint1(x67)))
+       var x70 uint64
+       var x71 uint64
+       x71, x70 = bits.Mul64(x54, 0x1ff)
+       var x72 uint64
+       var x73 uint64
+       x73, x72 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x74 uint64
+       var x75 uint64
+       x75, x74 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x76 uint64
+       var x77 uint64
+       x77, x76 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x78 uint64
+       var x79 uint64
+       x79, x78 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x80 uint64
+       var x81 uint64
+       x81, x80 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x82 uint64
+       var x83 uint64
+       x83, x82 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x84 uint64
+       var x85 uint64
+       x85, x84 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x86 uint64
+       var x87 uint64
+       x87, x86 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x88 uint64
+       var x89 uint64
+       x88, x89 = bits.Add64(x87, x84, uint64(0x0))
+       var x90 uint64
+       var x91 uint64
+       x90, x91 = bits.Add64(x85, x82, uint64(p521Uint1(x89)))
+       var x92 uint64
+       var x93 uint64
+       x92, x93 = bits.Add64(x83, x80, uint64(p521Uint1(x91)))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x81, x78, uint64(p521Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x79, x76, uint64(p521Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64(x77, x74, uint64(p521Uint1(x97)))
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x75, x72, uint64(p521Uint1(x99)))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x73, x70, uint64(p521Uint1(x101)))
+       var x105 uint64
+       _, x105 = bits.Add64(x54, x86, uint64(0x0))
+       var x106 uint64
+       var x107 uint64
+       x106, x107 = bits.Add64(x56, x88, uint64(p521Uint1(x105)))
+       var x108 uint64
+       var x109 uint64
+       x108, x109 = bits.Add64(x58, x90, uint64(p521Uint1(x107)))
+       var x110 uint64
+       var x111 uint64
+       x110, x111 = bits.Add64(x60, x92, uint64(p521Uint1(x109)))
+       var x112 uint64
+       var x113 uint64
+       x112, x113 = bits.Add64(x62, x94, uint64(p521Uint1(x111)))
+       var x114 uint64
+       var x115 uint64
+       x114, x115 = bits.Add64(x64, x96, uint64(p521Uint1(x113)))
+       var x116 uint64
+       var x117 uint64
+       x116, x117 = bits.Add64(x66, x98, uint64(p521Uint1(x115)))
+       var x118 uint64
+       var x119 uint64
+       x118, x119 = bits.Add64(x68, x100, uint64(p521Uint1(x117)))
+       var x120 uint64
+       var x121 uint64
+       x120, x121 = bits.Add64((uint64(p521Uint1(x69)) + (uint64(p521Uint1(x53)) + (uint64(p521Uint1(x35)) + x3))), x102, uint64(p521Uint1(x119)))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x106, arg1[2], uint64(0x0))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x108, uint64(0x0), uint64(p521Uint1(x123)))
+       var x126 uint64
+       var x127 uint64
+       x126, x127 = bits.Add64(x110, uint64(0x0), uint64(p521Uint1(x125)))
+       var x128 uint64
+       var x129 uint64
+       x128, x129 = bits.Add64(x112, uint64(0x0), uint64(p521Uint1(x127)))
+       var x130 uint64
+       var x131 uint64
+       x130, x131 = bits.Add64(x114, uint64(0x0), uint64(p521Uint1(x129)))
+       var x132 uint64
+       var x133 uint64
+       x132, x133 = bits.Add64(x116, uint64(0x0), uint64(p521Uint1(x131)))
+       var x134 uint64
+       var x135 uint64
+       x134, x135 = bits.Add64(x118, uint64(0x0), uint64(p521Uint1(x133)))
+       var x136 uint64
+       var x137 uint64
+       x136, x137 = bits.Add64(x120, uint64(0x0), uint64(p521Uint1(x135)))
+       var x138 uint64
+       var x139 uint64
+       x139, x138 = bits.Mul64(x122, 0x1ff)
+       var x140 uint64
+       var x141 uint64
+       x141, x140 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x142 uint64
+       var x143 uint64
+       x143, x142 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x144 uint64
+       var x145 uint64
+       x145, x144 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x146 uint64
+       var x147 uint64
+       x147, x146 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x148 uint64
+       var x149 uint64
+       x149, x148 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x150 uint64
+       var x151 uint64
+       x151, x150 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x152 uint64
+       var x153 uint64
+       x153, x152 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x154 uint64
+       var x155 uint64
+       x155, x154 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x156 uint64
+       var x157 uint64
+       x156, x157 = bits.Add64(x155, x152, uint64(0x0))
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x153, x150, uint64(p521Uint1(x157)))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x151, x148, uint64(p521Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x149, x146, uint64(p521Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x147, x144, uint64(p521Uint1(x163)))
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Add64(x145, x142, uint64(p521Uint1(x165)))
+       var x168 uint64
+       var x169 uint64
+       x168, x169 = bits.Add64(x143, x140, uint64(p521Uint1(x167)))
+       var x170 uint64
+       var x171 uint64
+       x170, x171 = bits.Add64(x141, x138, uint64(p521Uint1(x169)))
+       var x173 uint64
+       _, x173 = bits.Add64(x122, x154, uint64(0x0))
+       var x174 uint64
+       var x175 uint64
+       x174, x175 = bits.Add64(x124, x156, uint64(p521Uint1(x173)))
+       var x176 uint64
+       var x177 uint64
+       x176, x177 = bits.Add64(x126, x158, uint64(p521Uint1(x175)))
+       var x178 uint64
+       var x179 uint64
+       x178, x179 = bits.Add64(x128, x160, uint64(p521Uint1(x177)))
+       var x180 uint64
+       var x181 uint64
+       x180, x181 = bits.Add64(x130, x162, uint64(p521Uint1(x179)))
+       var x182 uint64
+       var x183 uint64
+       x182, x183 = bits.Add64(x132, x164, uint64(p521Uint1(x181)))
+       var x184 uint64
+       var x185 uint64
+       x184, x185 = bits.Add64(x134, x166, uint64(p521Uint1(x183)))
+       var x186 uint64
+       var x187 uint64
+       x186, x187 = bits.Add64(x136, x168, uint64(p521Uint1(x185)))
+       var x188 uint64
+       var x189 uint64
+       x188, x189 = bits.Add64((uint64(p521Uint1(x137)) + (uint64(p521Uint1(x121)) + (uint64(p521Uint1(x103)) + x71))), x170, uint64(p521Uint1(x187)))
+       var x190 uint64
+       var x191 uint64
+       x190, x191 = bits.Add64(x174, arg1[3], uint64(0x0))
+       var x192 uint64
+       var x193 uint64
+       x192, x193 = bits.Add64(x176, uint64(0x0), uint64(p521Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Add64(x178, uint64(0x0), uint64(p521Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Add64(x180, uint64(0x0), uint64(p521Uint1(x195)))
+       var x198 uint64
+       var x199 uint64
+       x198, x199 = bits.Add64(x182, uint64(0x0), uint64(p521Uint1(x197)))
+       var x200 uint64
+       var x201 uint64
+       x200, x201 = bits.Add64(x184, uint64(0x0), uint64(p521Uint1(x199)))
+       var x202 uint64
+       var x203 uint64
+       x202, x203 = bits.Add64(x186, uint64(0x0), uint64(p521Uint1(x201)))
+       var x204 uint64
+       var x205 uint64
+       x204, x205 = bits.Add64(x188, uint64(0x0), uint64(p521Uint1(x203)))
+       var x206 uint64
+       var x207 uint64
+       x207, x206 = bits.Mul64(x190, 0x1ff)
+       var x208 uint64
+       var x209 uint64
+       x209, x208 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x210 uint64
+       var x211 uint64
+       x211, x210 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x212 uint64
+       var x213 uint64
+       x213, x212 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x214 uint64
+       var x215 uint64
+       x215, x214 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x216 uint64
+       var x217 uint64
+       x217, x216 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x218 uint64
+       var x219 uint64
+       x219, x218 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x220 uint64
+       var x221 uint64
+       x221, x220 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x222 uint64
+       var x223 uint64
+       x223, x222 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x224 uint64
+       var x225 uint64
+       x224, x225 = bits.Add64(x223, x220, uint64(0x0))
+       var x226 uint64
+       var x227 uint64
+       x226, x227 = bits.Add64(x221, x218, uint64(p521Uint1(x225)))
+       var x228 uint64
+       var x229 uint64
+       x228, x229 = bits.Add64(x219, x216, uint64(p521Uint1(x227)))
+       var x230 uint64
+       var x231 uint64
+       x230, x231 = bits.Add64(x217, x214, uint64(p521Uint1(x229)))
+       var x232 uint64
+       var x233 uint64
+       x232, x233 = bits.Add64(x215, x212, uint64(p521Uint1(x231)))
+       var x234 uint64
+       var x235 uint64
+       x234, x235 = bits.Add64(x213, x210, uint64(p521Uint1(x233)))
+       var x236 uint64
+       var x237 uint64
+       x236, x237 = bits.Add64(x211, x208, uint64(p521Uint1(x235)))
+       var x238 uint64
+       var x239 uint64
+       x238, x239 = bits.Add64(x209, x206, uint64(p521Uint1(x237)))
+       var x241 uint64
+       _, x241 = bits.Add64(x190, x222, uint64(0x0))
+       var x242 uint64
+       var x243 uint64
+       x242, x243 = bits.Add64(x192, x224, uint64(p521Uint1(x241)))
+       var x244 uint64
+       var x245 uint64
+       x244, x245 = bits.Add64(x194, x226, uint64(p521Uint1(x243)))
+       var x246 uint64
+       var x247 uint64
+       x246, x247 = bits.Add64(x196, x228, uint64(p521Uint1(x245)))
+       var x248 uint64
+       var x249 uint64
+       x248, x249 = bits.Add64(x198, x230, uint64(p521Uint1(x247)))
+       var x250 uint64
+       var x251 uint64
+       x250, x251 = bits.Add64(x200, x232, uint64(p521Uint1(x249)))
+       var x252 uint64
+       var x253 uint64
+       x252, x253 = bits.Add64(x202, x234, uint64(p521Uint1(x251)))
+       var x254 uint64
+       var x255 uint64
+       x254, x255 = bits.Add64(x204, x236, uint64(p521Uint1(x253)))
+       var x256 uint64
+       var x257 uint64
+       x256, x257 = bits.Add64((uint64(p521Uint1(x205)) + (uint64(p521Uint1(x189)) + (uint64(p521Uint1(x171)) + x139))), x238, uint64(p521Uint1(x255)))
+       var x258 uint64
+       var x259 uint64
+       x258, x259 = bits.Add64(x242, arg1[4], uint64(0x0))
+       var x260 uint64
+       var x261 uint64
+       x260, x261 = bits.Add64(x244, uint64(0x0), uint64(p521Uint1(x259)))
+       var x262 uint64
+       var x263 uint64
+       x262, x263 = bits.Add64(x246, uint64(0x0), uint64(p521Uint1(x261)))
+       var x264 uint64
+       var x265 uint64
+       x264, x265 = bits.Add64(x248, uint64(0x0), uint64(p521Uint1(x263)))
+       var x266 uint64
+       var x267 uint64
+       x266, x267 = bits.Add64(x250, uint64(0x0), uint64(p521Uint1(x265)))
+       var x268 uint64
+       var x269 uint64
+       x268, x269 = bits.Add64(x252, uint64(0x0), uint64(p521Uint1(x267)))
+       var x270 uint64
+       var x271 uint64
+       x270, x271 = bits.Add64(x254, uint64(0x0), uint64(p521Uint1(x269)))
+       var x272 uint64
+       var x273 uint64
+       x272, x273 = bits.Add64(x256, uint64(0x0), uint64(p521Uint1(x271)))
+       var x274 uint64
+       var x275 uint64
+       x275, x274 = bits.Mul64(x258, 0x1ff)
+       var x276 uint64
+       var x277 uint64
+       x277, x276 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x278 uint64
+       var x279 uint64
+       x279, x278 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x280 uint64
+       var x281 uint64
+       x281, x280 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x282 uint64
+       var x283 uint64
+       x283, x282 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x284 uint64
+       var x285 uint64
+       x285, x284 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x286 uint64
+       var x287 uint64
+       x287, x286 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x288 uint64
+       var x289 uint64
+       x289, x288 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x290 uint64
+       var x291 uint64
+       x291, x290 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x292 uint64
+       var x293 uint64
+       x292, x293 = bits.Add64(x291, x288, uint64(0x0))
+       var x294 uint64
+       var x295 uint64
+       x294, x295 = bits.Add64(x289, x286, uint64(p521Uint1(x293)))
+       var x296 uint64
+       var x297 uint64
+       x296, x297 = bits.Add64(x287, x284, uint64(p521Uint1(x295)))
+       var x298 uint64
+       var x299 uint64
+       x298, x299 = bits.Add64(x285, x282, uint64(p521Uint1(x297)))
+       var x300 uint64
+       var x301 uint64
+       x300, x301 = bits.Add64(x283, x280, uint64(p521Uint1(x299)))
+       var x302 uint64
+       var x303 uint64
+       x302, x303 = bits.Add64(x281, x278, uint64(p521Uint1(x301)))
+       var x304 uint64
+       var x305 uint64
+       x304, x305 = bits.Add64(x279, x276, uint64(p521Uint1(x303)))
+       var x306 uint64
+       var x307 uint64
+       x306, x307 = bits.Add64(x277, x274, uint64(p521Uint1(x305)))
+       var x309 uint64
+       _, x309 = bits.Add64(x258, x290, uint64(0x0))
+       var x310 uint64
+       var x311 uint64
+       x310, x311 = bits.Add64(x260, x292, uint64(p521Uint1(x309)))
+       var x312 uint64
+       var x313 uint64
+       x312, x313 = bits.Add64(x262, x294, uint64(p521Uint1(x311)))
+       var x314 uint64
+       var x315 uint64
+       x314, x315 = bits.Add64(x264, x296, uint64(p521Uint1(x313)))
+       var x316 uint64
+       var x317 uint64
+       x316, x317 = bits.Add64(x266, x298, uint64(p521Uint1(x315)))
+       var x318 uint64
+       var x319 uint64
+       x318, x319 = bits.Add64(x268, x300, uint64(p521Uint1(x317)))
+       var x320 uint64
+       var x321 uint64
+       x320, x321 = bits.Add64(x270, x302, uint64(p521Uint1(x319)))
+       var x322 uint64
+       var x323 uint64
+       x322, x323 = bits.Add64(x272, x304, uint64(p521Uint1(x321)))
+       var x324 uint64
+       var x325 uint64
+       x324, x325 = bits.Add64((uint64(p521Uint1(x273)) + (uint64(p521Uint1(x257)) + (uint64(p521Uint1(x239)) + x207))), x306, uint64(p521Uint1(x323)))
+       var x326 uint64
+       var x327 uint64
+       x326, x327 = bits.Add64(x310, arg1[5], uint64(0x0))
+       var x328 uint64
+       var x329 uint64
+       x328, x329 = bits.Add64(x312, uint64(0x0), uint64(p521Uint1(x327)))
+       var x330 uint64
+       var x331 uint64
+       x330, x331 = bits.Add64(x314, uint64(0x0), uint64(p521Uint1(x329)))
+       var x332 uint64
+       var x333 uint64
+       x332, x333 = bits.Add64(x316, uint64(0x0), uint64(p521Uint1(x331)))
+       var x334 uint64
+       var x335 uint64
+       x334, x335 = bits.Add64(x318, uint64(0x0), uint64(p521Uint1(x333)))
+       var x336 uint64
+       var x337 uint64
+       x336, x337 = bits.Add64(x320, uint64(0x0), uint64(p521Uint1(x335)))
+       var x338 uint64
+       var x339 uint64
+       x338, x339 = bits.Add64(x322, uint64(0x0), uint64(p521Uint1(x337)))
+       var x340 uint64
+       var x341 uint64
+       x340, x341 = bits.Add64(x324, uint64(0x0), uint64(p521Uint1(x339)))
+       var x342 uint64
+       var x343 uint64
+       x343, x342 = bits.Mul64(x326, 0x1ff)
+       var x344 uint64
+       var x345 uint64
+       x345, x344 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x346 uint64
+       var x347 uint64
+       x347, x346 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x348 uint64
+       var x349 uint64
+       x349, x348 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x350 uint64
+       var x351 uint64
+       x351, x350 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x352 uint64
+       var x353 uint64
+       x353, x352 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x354 uint64
+       var x355 uint64
+       x355, x354 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x356 uint64
+       var x357 uint64
+       x357, x356 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x358 uint64
+       var x359 uint64
+       x359, x358 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x360 uint64
+       var x361 uint64
+       x360, x361 = bits.Add64(x359, x356, uint64(0x0))
+       var x362 uint64
+       var x363 uint64
+       x362, x363 = bits.Add64(x357, x354, uint64(p521Uint1(x361)))
+       var x364 uint64
+       var x365 uint64
+       x364, x365 = bits.Add64(x355, x352, uint64(p521Uint1(x363)))
+       var x366 uint64
+       var x367 uint64
+       x366, x367 = bits.Add64(x353, x350, uint64(p521Uint1(x365)))
+       var x368 uint64
+       var x369 uint64
+       x368, x369 = bits.Add64(x351, x348, uint64(p521Uint1(x367)))
+       var x370 uint64
+       var x371 uint64
+       x370, x371 = bits.Add64(x349, x346, uint64(p521Uint1(x369)))
+       var x372 uint64
+       var x373 uint64
+       x372, x373 = bits.Add64(x347, x344, uint64(p521Uint1(x371)))
+       var x374 uint64
+       var x375 uint64
+       x374, x375 = bits.Add64(x345, x342, uint64(p521Uint1(x373)))
+       var x377 uint64
+       _, x377 = bits.Add64(x326, x358, uint64(0x0))
+       var x378 uint64
+       var x379 uint64
+       x378, x379 = bits.Add64(x328, x360, uint64(p521Uint1(x377)))
+       var x380 uint64
+       var x381 uint64
+       x380, x381 = bits.Add64(x330, x362, uint64(p521Uint1(x379)))
+       var x382 uint64
+       var x383 uint64
+       x382, x383 = bits.Add64(x332, x364, uint64(p521Uint1(x381)))
+       var x384 uint64
+       var x385 uint64
+       x384, x385 = bits.Add64(x334, x366, uint64(p521Uint1(x383)))
+       var x386 uint64
+       var x387 uint64
+       x386, x387 = bits.Add64(x336, x368, uint64(p521Uint1(x385)))
+       var x388 uint64
+       var x389 uint64
+       x388, x389 = bits.Add64(x338, x370, uint64(p521Uint1(x387)))
+       var x390 uint64
+       var x391 uint64
+       x390, x391 = bits.Add64(x340, x372, uint64(p521Uint1(x389)))
+       var x392 uint64
+       var x393 uint64
+       x392, x393 = bits.Add64((uint64(p521Uint1(x341)) + (uint64(p521Uint1(x325)) + (uint64(p521Uint1(x307)) + x275))), x374, uint64(p521Uint1(x391)))
+       var x394 uint64
+       var x395 uint64
+       x394, x395 = bits.Add64(x378, arg1[6], uint64(0x0))
+       var x396 uint64
+       var x397 uint64
+       x396, x397 = bits.Add64(x380, uint64(0x0), uint64(p521Uint1(x395)))
+       var x398 uint64
+       var x399 uint64
+       x398, x399 = bits.Add64(x382, uint64(0x0), uint64(p521Uint1(x397)))
+       var x400 uint64
+       var x401 uint64
+       x400, x401 = bits.Add64(x384, uint64(0x0), uint64(p521Uint1(x399)))
+       var x402 uint64
+       var x403 uint64
+       x402, x403 = bits.Add64(x386, uint64(0x0), uint64(p521Uint1(x401)))
+       var x404 uint64
+       var x405 uint64
+       x404, x405 = bits.Add64(x388, uint64(0x0), uint64(p521Uint1(x403)))
+       var x406 uint64
+       var x407 uint64
+       x406, x407 = bits.Add64(x390, uint64(0x0), uint64(p521Uint1(x405)))
+       var x408 uint64
+       var x409 uint64
+       x408, x409 = bits.Add64(x392, uint64(0x0), uint64(p521Uint1(x407)))
+       var x410 uint64
+       var x411 uint64
+       x411, x410 = bits.Mul64(x394, 0x1ff)
+       var x412 uint64
+       var x413 uint64
+       x413, x412 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x414 uint64
+       var x415 uint64
+       x415, x414 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x416 uint64
+       var x417 uint64
+       x417, x416 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x418 uint64
+       var x419 uint64
+       x419, x418 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x420 uint64
+       var x421 uint64
+       x421, x420 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x422 uint64
+       var x423 uint64
+       x423, x422 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x424 uint64
+       var x425 uint64
+       x425, x424 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x426 uint64
+       var x427 uint64
+       x427, x426 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x428 uint64
+       var x429 uint64
+       x428, x429 = bits.Add64(x427, x424, uint64(0x0))
+       var x430 uint64
+       var x431 uint64
+       x430, x431 = bits.Add64(x425, x422, uint64(p521Uint1(x429)))
+       var x432 uint64
+       var x433 uint64
+       x432, x433 = bits.Add64(x423, x420, uint64(p521Uint1(x431)))
+       var x434 uint64
+       var x435 uint64
+       x434, x435 = bits.Add64(x421, x418, uint64(p521Uint1(x433)))
+       var x436 uint64
+       var x437 uint64
+       x436, x437 = bits.Add64(x419, x416, uint64(p521Uint1(x435)))
+       var x438 uint64
+       var x439 uint64
+       x438, x439 = bits.Add64(x417, x414, uint64(p521Uint1(x437)))
+       var x440 uint64
+       var x441 uint64
+       x440, x441 = bits.Add64(x415, x412, uint64(p521Uint1(x439)))
+       var x442 uint64
+       var x443 uint64
+       x442, x443 = bits.Add64(x413, x410, uint64(p521Uint1(x441)))
+       var x445 uint64
+       _, x445 = bits.Add64(x394, x426, uint64(0x0))
+       var x446 uint64
+       var x447 uint64
+       x446, x447 = bits.Add64(x396, x428, uint64(p521Uint1(x445)))
+       var x448 uint64
+       var x449 uint64
+       x448, x449 = bits.Add64(x398, x430, uint64(p521Uint1(x447)))
+       var x450 uint64
+       var x451 uint64
+       x450, x451 = bits.Add64(x400, x432, uint64(p521Uint1(x449)))
+       var x452 uint64
+       var x453 uint64
+       x452, x453 = bits.Add64(x402, x434, uint64(p521Uint1(x451)))
+       var x454 uint64
+       var x455 uint64
+       x454, x455 = bits.Add64(x404, x436, uint64(p521Uint1(x453)))
+       var x456 uint64
+       var x457 uint64
+       x456, x457 = bits.Add64(x406, x438, uint64(p521Uint1(x455)))
+       var x458 uint64
+       var x459 uint64
+       x458, x459 = bits.Add64(x408, x440, uint64(p521Uint1(x457)))
+       var x460 uint64
+       var x461 uint64
+       x460, x461 = bits.Add64((uint64(p521Uint1(x409)) + (uint64(p521Uint1(x393)) + (uint64(p521Uint1(x375)) + x343))), x442, uint64(p521Uint1(x459)))
+       var x462 uint64
+       var x463 uint64
+       x462, x463 = bits.Add64(x446, arg1[7], uint64(0x0))
+       var x464 uint64
+       var x465 uint64
+       x464, x465 = bits.Add64(x448, uint64(0x0), uint64(p521Uint1(x463)))
+       var x466 uint64
+       var x467 uint64
+       x466, x467 = bits.Add64(x450, uint64(0x0), uint64(p521Uint1(x465)))
+       var x468 uint64
+       var x469 uint64
+       x468, x469 = bits.Add64(x452, uint64(0x0), uint64(p521Uint1(x467)))
+       var x470 uint64
+       var x471 uint64
+       x470, x471 = bits.Add64(x454, uint64(0x0), uint64(p521Uint1(x469)))
+       var x472 uint64
+       var x473 uint64
+       x472, x473 = bits.Add64(x456, uint64(0x0), uint64(p521Uint1(x471)))
+       var x474 uint64
+       var x475 uint64
+       x474, x475 = bits.Add64(x458, uint64(0x0), uint64(p521Uint1(x473)))
+       var x476 uint64
+       var x477 uint64
+       x476, x477 = bits.Add64(x460, uint64(0x0), uint64(p521Uint1(x475)))
+       var x478 uint64
+       var x479 uint64
+       x479, x478 = bits.Mul64(x462, 0x1ff)
+       var x480 uint64
+       var x481 uint64
+       x481, x480 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x482 uint64
+       var x483 uint64
+       x483, x482 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x484 uint64
+       var x485 uint64
+       x485, x484 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x486 uint64
+       var x487 uint64
+       x487, x486 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x488 uint64
+       var x489 uint64
+       x489, x488 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x490 uint64
+       var x491 uint64
+       x491, x490 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x492 uint64
+       var x493 uint64
+       x493, x492 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x494 uint64
+       var x495 uint64
+       x495, x494 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x496 uint64
+       var x497 uint64
+       x496, x497 = bits.Add64(x495, x492, uint64(0x0))
+       var x498 uint64
+       var x499 uint64
+       x498, x499 = bits.Add64(x493, x490, uint64(p521Uint1(x497)))
+       var x500 uint64
+       var x501 uint64
+       x500, x501 = bits.Add64(x491, x488, uint64(p521Uint1(x499)))
+       var x502 uint64
+       var x503 uint64
+       x502, x503 = bits.Add64(x489, x486, uint64(p521Uint1(x501)))
+       var x504 uint64
+       var x505 uint64
+       x504, x505 = bits.Add64(x487, x484, uint64(p521Uint1(x503)))
+       var x506 uint64
+       var x507 uint64
+       x506, x507 = bits.Add64(x485, x482, uint64(p521Uint1(x505)))
+       var x508 uint64
+       var x509 uint64
+       x508, x509 = bits.Add64(x483, x480, uint64(p521Uint1(x507)))
+       var x510 uint64
+       var x511 uint64
+       x510, x511 = bits.Add64(x481, x478, uint64(p521Uint1(x509)))
+       var x513 uint64
+       _, x513 = bits.Add64(x462, x494, uint64(0x0))
+       var x514 uint64
+       var x515 uint64
+       x514, x515 = bits.Add64(x464, x496, uint64(p521Uint1(x513)))
+       var x516 uint64
+       var x517 uint64
+       x516, x517 = bits.Add64(x466, x498, uint64(p521Uint1(x515)))
+       var x518 uint64
+       var x519 uint64
+       x518, x519 = bits.Add64(x468, x500, uint64(p521Uint1(x517)))
+       var x520 uint64
+       var x521 uint64
+       x520, x521 = bits.Add64(x470, x502, uint64(p521Uint1(x519)))
+       var x522 uint64
+       var x523 uint64
+       x522, x523 = bits.Add64(x472, x504, uint64(p521Uint1(x521)))
+       var x524 uint64
+       var x525 uint64
+       x524, x525 = bits.Add64(x474, x506, uint64(p521Uint1(x523)))
+       var x526 uint64
+       var x527 uint64
+       x526, x527 = bits.Add64(x476, x508, uint64(p521Uint1(x525)))
+       var x528 uint64
+       var x529 uint64
+       x528, x529 = bits.Add64((uint64(p521Uint1(x477)) + (uint64(p521Uint1(x461)) + (uint64(p521Uint1(x443)) + x411))), x510, uint64(p521Uint1(x527)))
+       var x530 uint64
+       var x531 uint64
+       x530, x531 = bits.Add64(x514, arg1[8], uint64(0x0))
+       var x532 uint64
+       var x533 uint64
+       x532, x533 = bits.Add64(x516, uint64(0x0), uint64(p521Uint1(x531)))
+       var x534 uint64
+       var x535 uint64
+       x534, x535 = bits.Add64(x518, uint64(0x0), uint64(p521Uint1(x533)))
+       var x536 uint64
+       var x537 uint64
+       x536, x537 = bits.Add64(x520, uint64(0x0), uint64(p521Uint1(x535)))
+       var x538 uint64
+       var x539 uint64
+       x538, x539 = bits.Add64(x522, uint64(0x0), uint64(p521Uint1(x537)))
+       var x540 uint64
+       var x541 uint64
+       x540, x541 = bits.Add64(x524, uint64(0x0), uint64(p521Uint1(x539)))
+       var x542 uint64
+       var x543 uint64
+       x542, x543 = bits.Add64(x526, uint64(0x0), uint64(p521Uint1(x541)))
+       var x544 uint64
+       var x545 uint64
+       x544, x545 = bits.Add64(x528, uint64(0x0), uint64(p521Uint1(x543)))
+       var x546 uint64
+       var x547 uint64
+       x547, x546 = bits.Mul64(x530, 0x1ff)
+       var x548 uint64
+       var x549 uint64
+       x549, x548 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x550 uint64
+       var x551 uint64
+       x551, x550 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x552 uint64
+       var x553 uint64
+       x553, x552 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x554 uint64
+       var x555 uint64
+       x555, x554 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x556 uint64
+       var x557 uint64
+       x557, x556 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x558 uint64
+       var x559 uint64
+       x559, x558 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x560 uint64
+       var x561 uint64
+       x561, x560 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x562 uint64
+       var x563 uint64
+       x563, x562 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x564 uint64
+       var x565 uint64
+       x564, x565 = bits.Add64(x563, x560, uint64(0x0))
+       var x566 uint64
+       var x567 uint64
+       x566, x567 = bits.Add64(x561, x558, uint64(p521Uint1(x565)))
+       var x568 uint64
+       var x569 uint64
+       x568, x569 = bits.Add64(x559, x556, uint64(p521Uint1(x567)))
+       var x570 uint64
+       var x571 uint64
+       x570, x571 = bits.Add64(x557, x554, uint64(p521Uint1(x569)))
+       var x572 uint64
+       var x573 uint64
+       x572, x573 = bits.Add64(x555, x552, uint64(p521Uint1(x571)))
+       var x574 uint64
+       var x575 uint64
+       x574, x575 = bits.Add64(x553, x550, uint64(p521Uint1(x573)))
+       var x576 uint64
+       var x577 uint64
+       x576, x577 = bits.Add64(x551, x548, uint64(p521Uint1(x575)))
+       var x578 uint64
+       var x579 uint64
+       x578, x579 = bits.Add64(x549, x546, uint64(p521Uint1(x577)))
+       var x581 uint64
+       _, x581 = bits.Add64(x530, x562, uint64(0x0))
+       var x582 uint64
+       var x583 uint64
+       x582, x583 = bits.Add64(x532, x564, uint64(p521Uint1(x581)))
+       var x584 uint64
+       var x585 uint64
+       x584, x585 = bits.Add64(x534, x566, uint64(p521Uint1(x583)))
+       var x586 uint64
+       var x587 uint64
+       x586, x587 = bits.Add64(x536, x568, uint64(p521Uint1(x585)))
+       var x588 uint64
+       var x589 uint64
+       x588, x589 = bits.Add64(x538, x570, uint64(p521Uint1(x587)))
+       var x590 uint64
+       var x591 uint64
+       x590, x591 = bits.Add64(x540, x572, uint64(p521Uint1(x589)))
+       var x592 uint64
+       var x593 uint64
+       x592, x593 = bits.Add64(x542, x574, uint64(p521Uint1(x591)))
+       var x594 uint64
+       var x595 uint64
+       x594, x595 = bits.Add64(x544, x576, uint64(p521Uint1(x593)))
+       var x596 uint64
+       var x597 uint64
+       x596, x597 = bits.Add64((uint64(p521Uint1(x545)) + (uint64(p521Uint1(x529)) + (uint64(p521Uint1(x511)) + x479))), x578, uint64(p521Uint1(x595)))
+       x598 := (uint64(p521Uint1(x597)) + (uint64(p521Uint1(x579)) + x547))
+       var x599 uint64
+       var x600 uint64
+       x599, x600 = bits.Sub64(x582, 0xffffffffffffffff, uint64(0x0))
+       var x601 uint64
+       var x602 uint64
+       x601, x602 = bits.Sub64(x584, 0xffffffffffffffff, uint64(p521Uint1(x600)))
+       var x603 uint64
+       var x604 uint64
+       x603, x604 = bits.Sub64(x586, 0xffffffffffffffff, uint64(p521Uint1(x602)))
+       var x605 uint64
+       var x606 uint64
+       x605, x606 = bits.Sub64(x588, 0xffffffffffffffff, uint64(p521Uint1(x604)))
+       var x607 uint64
+       var x608 uint64
+       x607, x608 = bits.Sub64(x590, 0xffffffffffffffff, uint64(p521Uint1(x606)))
+       var x609 uint64
+       var x610 uint64
+       x609, x610 = bits.Sub64(x592, 0xffffffffffffffff, uint64(p521Uint1(x608)))
+       var x611 uint64
+       var x612 uint64
+       x611, x612 = bits.Sub64(x594, 0xffffffffffffffff, uint64(p521Uint1(x610)))
+       var x613 uint64
+       var x614 uint64
+       x613, x614 = bits.Sub64(x596, 0xffffffffffffffff, uint64(p521Uint1(x612)))
+       var x615 uint64
+       var x616 uint64
+       x615, x616 = bits.Sub64(x598, 0x1ff, uint64(p521Uint1(x614)))
+       var x618 uint64
+       _, x618 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p521Uint1(x616)))
+       var x619 uint64
+       p521CmovznzU64(&x619, p521Uint1(x618), x599, x582)
+       var x620 uint64
+       p521CmovznzU64(&x620, p521Uint1(x618), x601, x584)
+       var x621 uint64
+       p521CmovznzU64(&x621, p521Uint1(x618), x603, x586)
+       var x622 uint64
+       p521CmovznzU64(&x622, p521Uint1(x618), x605, x588)
+       var x623 uint64
+       p521CmovznzU64(&x623, p521Uint1(x618), x607, x590)
+       var x624 uint64
+       p521CmovznzU64(&x624, p521Uint1(x618), x609, x592)
+       var x625 uint64
+       p521CmovznzU64(&x625, p521Uint1(x618), x611, x594)
+       var x626 uint64
+       p521CmovznzU64(&x626, p521Uint1(x618), x613, x596)
+       var x627 uint64
+       p521CmovznzU64(&x627, p521Uint1(x618), x615, x598)
+       out1[0] = x619
+       out1[1] = x620
+       out1[2] = x621
+       out1[3] = x622
+       out1[4] = x623
+       out1[5] = x624
+       out1[6] = x625
+       out1[7] = x626
+       out1[8] = x627
+}
 
-// p521Add adds two field elements.
+// p521ToMontgomery translates a field element into the Montgomery domain.
 //
+// Preconditions:
+//   0 ≤ eval arg1 < m
 // Postconditions:
-//   eval out1 mod m = (eval arg1 + eval arg2) mod m
+//   eval (from_montgomery out1) mod m = eval arg1 mod m
+//   0 ≤ eval out1 < m
 //
-// Input Bounds:
-//   arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-//   arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-func p521Add(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
-       x1 := (arg1[0] + arg2[0])
-       x2 := (arg1[1] + arg2[1])
-       x3 := (arg1[2] + arg2[2])
-       x4 := (arg1[3] + arg2[3])
-       x5 := (arg1[4] + arg2[4])
-       x6 := (arg1[5] + arg2[5])
-       x7 := (arg1[6] + arg2[6])
-       x8 := (arg1[7] + arg2[7])
-       x9 := (arg1[8] + arg2[8])
-       out1[0] = x1
-       out1[1] = x2
-       out1[2] = x3
-       out1[3] = x4
-       out1[4] = x5
-       out1[5] = x6
-       out1[6] = x7
-       out1[7] = x8
-       out1[8] = x9
+func p521ToMontgomery(out1 *p521MontgomeryDomainFieldElement, arg1 *p521NonMontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x2, x1 = bits.Mul64(arg1[0], 0x400000000000)
+       var x3 uint64
+       var x4 uint64
+       x4, x3 = bits.Mul64(arg1[1], 0x400000000000)
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Add64(x2, x3, uint64(0x0))
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x1, 0x1ff)
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x13 uint64
+       var x14 uint64
+       x14, x13 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x15 uint64
+       var x16 uint64
+       x16, x15 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x17 uint64
+       var x18 uint64
+       x18, x17 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x19 uint64
+       var x20 uint64
+       x20, x19 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x21 uint64
+       var x22 uint64
+       x22, x21 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x23 uint64
+       var x24 uint64
+       x24, x23 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x25 uint64
+       var x26 uint64
+       x25, x26 = bits.Add64(x24, x21, uint64(0x0))
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Add64(x22, x19, uint64(p521Uint1(x26)))
+       var x29 uint64
+       var x30 uint64
+       x29, x30 = bits.Add64(x20, x17, uint64(p521Uint1(x28)))
+       var x31 uint64
+       var x32 uint64
+       x31, x32 = bits.Add64(x18, x15, uint64(p521Uint1(x30)))
+       var x33 uint64
+       var x34 uint64
+       x33, x34 = bits.Add64(x16, x13, uint64(p521Uint1(x32)))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Add64(x14, x11, uint64(p521Uint1(x34)))
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x12, x9, uint64(p521Uint1(x36)))
+       var x39 uint64
+       var x40 uint64
+       x39, x40 = bits.Add64(x10, x7, uint64(p521Uint1(x38)))
+       var x42 uint64
+       _, x42 = bits.Add64(x1, x23, uint64(0x0))
+       var x43 uint64
+       var x44 uint64
+       x43, x44 = bits.Add64(x5, x25, uint64(p521Uint1(x42)))
+       var x45 uint64
+       var x46 uint64
+       x45, x46 = bits.Add64((uint64(p521Uint1(x6)) + x4), x27, uint64(p521Uint1(x44)))
+       var x47 uint64
+       var x48 uint64
+       x47, x48 = bits.Add64(uint64(0x0), x29, uint64(p521Uint1(x46)))
+       var x49 uint64
+       var x50 uint64
+       x49, x50 = bits.Add64(uint64(0x0), x31, uint64(p521Uint1(x48)))
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(uint64(0x0), x33, uint64(p521Uint1(x50)))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(uint64(0x0), x35, uint64(p521Uint1(x52)))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(uint64(0x0), x37, uint64(p521Uint1(x54)))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(uint64(0x0), x39, uint64(p521Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x60, x59 = bits.Mul64(arg1[2], 0x400000000000)
+       var x61 uint64
+       var x62 uint64
+       x61, x62 = bits.Add64(x45, x59, uint64(0x0))
+       var x63 uint64
+       var x64 uint64
+       x63, x64 = bits.Add64(x47, x60, uint64(p521Uint1(x62)))
+       var x65 uint64
+       var x66 uint64
+       x65, x66 = bits.Add64(x49, uint64(0x0), uint64(p521Uint1(x64)))
+       var x67 uint64
+       var x68 uint64
+       x67, x68 = bits.Add64(x51, uint64(0x0), uint64(p521Uint1(x66)))
+       var x69 uint64
+       var x70 uint64
+       x69, x70 = bits.Add64(x53, uint64(0x0), uint64(p521Uint1(x68)))
+       var x71 uint64
+       var x72 uint64
+       x71, x72 = bits.Add64(x55, uint64(0x0), uint64(p521Uint1(x70)))
+       var x73 uint64
+       var x74 uint64
+       x73, x74 = bits.Add64(x57, uint64(0x0), uint64(p521Uint1(x72)))
+       var x75 uint64
+       var x76 uint64
+       x76, x75 = bits.Mul64(x43, 0x1ff)
+       var x77 uint64
+       var x78 uint64
+       x78, x77 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x79 uint64
+       var x80 uint64
+       x80, x79 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x81 uint64
+       var x82 uint64
+       x82, x81 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x83 uint64
+       var x84 uint64
+       x84, x83 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x85 uint64
+       var x86 uint64
+       x86, x85 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x87 uint64
+       var x88 uint64
+       x88, x87 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x89 uint64
+       var x90 uint64
+       x90, x89 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x91 uint64
+       var x92 uint64
+       x92, x91 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x93 uint64
+       var x94 uint64
+       x93, x94 = bits.Add64(x92, x89, uint64(0x0))
+       var x95 uint64
+       var x96 uint64
+       x95, x96 = bits.Add64(x90, x87, uint64(p521Uint1(x94)))
+       var x97 uint64
+       var x98 uint64
+       x97, x98 = bits.Add64(x88, x85, uint64(p521Uint1(x96)))
+       var x99 uint64
+       var x100 uint64
+       x99, x100 = bits.Add64(x86, x83, uint64(p521Uint1(x98)))
+       var x101 uint64
+       var x102 uint64
+       x101, x102 = bits.Add64(x84, x81, uint64(p521Uint1(x100)))
+       var x103 uint64
+       var x104 uint64
+       x103, x104 = bits.Add64(x82, x79, uint64(p521Uint1(x102)))
+       var x105 uint64
+       var x106 uint64
+       x105, x106 = bits.Add64(x80, x77, uint64(p521Uint1(x104)))
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Add64(x78, x75, uint64(p521Uint1(x106)))
+       var x110 uint64
+       _, x110 = bits.Add64(x43, x91, uint64(0x0))
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x61, x93, uint64(p521Uint1(x110)))
+       var x113 uint64
+       var x114 uint64
+       x113, x114 = bits.Add64(x63, x95, uint64(p521Uint1(x112)))
+       var x115 uint64
+       var x116 uint64
+       x115, x116 = bits.Add64(x65, x97, uint64(p521Uint1(x114)))
+       var x117 uint64
+       var x118 uint64
+       x117, x118 = bits.Add64(x67, x99, uint64(p521Uint1(x116)))
+       var x119 uint64
+       var x120 uint64
+       x119, x120 = bits.Add64(x69, x101, uint64(p521Uint1(x118)))
+       var x121 uint64
+       var x122 uint64
+       x121, x122 = bits.Add64(x71, x103, uint64(p521Uint1(x120)))
+       var x123 uint64
+       var x124 uint64
+       x123, x124 = bits.Add64(x73, x105, uint64(p521Uint1(x122)))
+       var x125 uint64
+       var x126 uint64
+       x125, x126 = bits.Add64((uint64(p521Uint1(x74)) + (uint64(p521Uint1(x58)) + (uint64(p521Uint1(x40)) + x8))), x107, uint64(p521Uint1(x124)))
+       var x127 uint64
+       var x128 uint64
+       x128, x127 = bits.Mul64(arg1[3], 0x400000000000)
+       var x129 uint64
+       var x130 uint64
+       x129, x130 = bits.Add64(x113, x127, uint64(0x0))
+       var x131 uint64
+       var x132 uint64
+       x131, x132 = bits.Add64(x115, x128, uint64(p521Uint1(x130)))
+       var x133 uint64
+       var x134 uint64
+       x133, x134 = bits.Add64(x117, uint64(0x0), uint64(p521Uint1(x132)))
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x119, uint64(0x0), uint64(p521Uint1(x134)))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x121, uint64(0x0), uint64(p521Uint1(x136)))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x123, uint64(0x0), uint64(p521Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x125, uint64(0x0), uint64(p521Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x144, x143 = bits.Mul64(x111, 0x1ff)
+       var x145 uint64
+       var x146 uint64
+       x146, x145 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x147 uint64
+       var x148 uint64
+       x148, x147 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x149 uint64
+       var x150 uint64
+       x150, x149 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x151 uint64
+       var x152 uint64
+       x152, x151 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x153 uint64
+       var x154 uint64
+       x154, x153 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x155 uint64
+       var x156 uint64
+       x156, x155 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x157 uint64
+       var x158 uint64
+       x158, x157 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x159 uint64
+       var x160 uint64
+       x160, x159 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x161 uint64
+       var x162 uint64
+       x161, x162 = bits.Add64(x160, x157, uint64(0x0))
+       var x163 uint64
+       var x164 uint64
+       x163, x164 = bits.Add64(x158, x155, uint64(p521Uint1(x162)))
+       var x165 uint64
+       var x166 uint64
+       x165, x166 = bits.Add64(x156, x153, uint64(p521Uint1(x164)))
+       var x167 uint64
+       var x168 uint64
+       x167, x168 = bits.Add64(x154, x151, uint64(p521Uint1(x166)))
+       var x169 uint64
+       var x170 uint64
+       x169, x170 = bits.Add64(x152, x149, uint64(p521Uint1(x168)))
+       var x171 uint64
+       var x172 uint64
+       x171, x172 = bits.Add64(x150, x147, uint64(p521Uint1(x170)))
+       var x173 uint64
+       var x174 uint64
+       x173, x174 = bits.Add64(x148, x145, uint64(p521Uint1(x172)))
+       var x175 uint64
+       var x176 uint64
+       x175, x176 = bits.Add64(x146, x143, uint64(p521Uint1(x174)))
+       var x178 uint64
+       _, x178 = bits.Add64(x111, x159, uint64(0x0))
+       var x179 uint64
+       var x180 uint64
+       x179, x180 = bits.Add64(x129, x161, uint64(p521Uint1(x178)))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x131, x163, uint64(p521Uint1(x180)))
+       var x183 uint64
+       var x184 uint64
+       x183, x184 = bits.Add64(x133, x165, uint64(p521Uint1(x182)))
+       var x185 uint64
+       var x186 uint64
+       x185, x186 = bits.Add64(x135, x167, uint64(p521Uint1(x184)))
+       var x187 uint64
+       var x188 uint64
+       x187, x188 = bits.Add64(x137, x169, uint64(p521Uint1(x186)))
+       var x189 uint64
+       var x190 uint64
+       x189, x190 = bits.Add64(x139, x171, uint64(p521Uint1(x188)))
+       var x191 uint64
+       var x192 uint64
+       x191, x192 = bits.Add64(x141, x173, uint64(p521Uint1(x190)))
+       var x193 uint64
+       var x194 uint64
+       x193, x194 = bits.Add64((uint64(p521Uint1(x142)) + (uint64(p521Uint1(x126)) + (uint64(p521Uint1(x108)) + x76))), x175, uint64(p521Uint1(x192)))
+       var x195 uint64
+       var x196 uint64
+       x196, x195 = bits.Mul64(arg1[4], 0x400000000000)
+       var x197 uint64
+       var x198 uint64
+       x197, x198 = bits.Add64(x181, x195, uint64(0x0))
+       var x199 uint64
+       var x200 uint64
+       x199, x200 = bits.Add64(x183, x196, uint64(p521Uint1(x198)))
+       var x201 uint64
+       var x202 uint64
+       x201, x202 = bits.Add64(x185, uint64(0x0), uint64(p521Uint1(x200)))
+       var x203 uint64
+       var x204 uint64
+       x203, x204 = bits.Add64(x187, uint64(0x0), uint64(p521Uint1(x202)))
+       var x205 uint64
+       var x206 uint64
+       x205, x206 = bits.Add64(x189, uint64(0x0), uint64(p521Uint1(x204)))
+       var x207 uint64
+       var x208 uint64
+       x207, x208 = bits.Add64(x191, uint64(0x0), uint64(p521Uint1(x206)))
+       var x209 uint64
+       var x210 uint64
+       x209, x210 = bits.Add64(x193, uint64(0x0), uint64(p521Uint1(x208)))
+       var x211 uint64
+       var x212 uint64
+       x212, x211 = bits.Mul64(x179, 0x1ff)
+       var x213 uint64
+       var x214 uint64
+       x214, x213 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x215 uint64
+       var x216 uint64
+       x216, x215 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x217 uint64
+       var x218 uint64
+       x218, x217 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x219 uint64
+       var x220 uint64
+       x220, x219 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x221 uint64
+       var x222 uint64
+       x222, x221 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x223 uint64
+       var x224 uint64
+       x224, x223 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x225 uint64
+       var x226 uint64
+       x226, x225 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x227 uint64
+       var x228 uint64
+       x228, x227 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x229 uint64
+       var x230 uint64
+       x229, x230 = bits.Add64(x228, x225, uint64(0x0))
+       var x231 uint64
+       var x232 uint64
+       x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230)))
+       var x233 uint64
+       var x234 uint64
+       x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232)))
+       var x235 uint64
+       var x236 uint64
+       x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234)))
+       var x237 uint64
+       var x238 uint64
+       x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236)))
+       var x239 uint64
+       var x240 uint64
+       x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238)))
+       var x241 uint64
+       var x242 uint64
+       x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240)))
+       var x243 uint64
+       var x244 uint64
+       x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242)))
+       var x246 uint64
+       _, x246 = bits.Add64(x179, x227, uint64(0x0))
+       var x247 uint64
+       var x248 uint64
+       x247, x248 = bits.Add64(x197, x229, uint64(p521Uint1(x246)))
+       var x249 uint64
+       var x250 uint64
+       x249, x250 = bits.Add64(x199, x231, uint64(p521Uint1(x248)))
+       var x251 uint64
+       var x252 uint64
+       x251, x252 = bits.Add64(x201, x233, uint64(p521Uint1(x250)))
+       var x253 uint64
+       var x254 uint64
+       x253, x254 = bits.Add64(x203, x235, uint64(p521Uint1(x252)))
+       var x255 uint64
+       var x256 uint64
+       x255, x256 = bits.Add64(x205, x237, uint64(p521Uint1(x254)))
+       var x257 uint64
+       var x258 uint64
+       x257, x258 = bits.Add64(x207, x239, uint64(p521Uint1(x256)))
+       var x259 uint64
+       var x260 uint64
+       x259, x260 = bits.Add64(x209, x241, uint64(p521Uint1(x258)))
+       var x261 uint64
+       var x262 uint64
+       x261, x262 = bits.Add64((uint64(p521Uint1(x210)) + (uint64(p521Uint1(x194)) + (uint64(p521Uint1(x176)) + x144))), x243, uint64(p521Uint1(x260)))
+       var x263 uint64
+       var x264 uint64
+       x264, x263 = bits.Mul64(arg1[5], 0x400000000000)
+       var x265 uint64
+       var x266 uint64
+       x265, x266 = bits.Add64(x249, x263, uint64(0x0))
+       var x267 uint64
+       var x268 uint64
+       x267, x268 = bits.Add64(x251, x264, uint64(p521Uint1(x266)))
+       var x269 uint64
+       var x270 uint64
+       x269, x270 = bits.Add64(x253, uint64(0x0), uint64(p521Uint1(x268)))
+       var x271 uint64
+       var x272 uint64
+       x271, x272 = bits.Add64(x255, uint64(0x0), uint64(p521Uint1(x270)))
+       var x273 uint64
+       var x274 uint64
+       x273, x274 = bits.Add64(x257, uint64(0x0), uint64(p521Uint1(x272)))
+       var x275 uint64
+       var x276 uint64
+       x275, x276 = bits.Add64(x259, uint64(0x0), uint64(p521Uint1(x274)))
+       var x277 uint64
+       var x278 uint64
+       x277, x278 = bits.Add64(x261, uint64(0x0), uint64(p521Uint1(x276)))
+       var x279 uint64
+       var x280 uint64
+       x280, x279 = bits.Mul64(x247, 0x1ff)
+       var x281 uint64
+       var x282 uint64
+       x282, x281 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x283 uint64
+       var x284 uint64
+       x284, x283 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x285 uint64
+       var x286 uint64
+       x286, x285 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x287 uint64
+       var x288 uint64
+       x288, x287 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x289 uint64
+       var x290 uint64
+       x290, x289 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x291 uint64
+       var x292 uint64
+       x292, x291 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x293 uint64
+       var x294 uint64
+       x294, x293 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x295 uint64
+       var x296 uint64
+       x296, x295 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x297 uint64
+       var x298 uint64
+       x297, x298 = bits.Add64(x296, x293, uint64(0x0))
+       var x299 uint64
+       var x300 uint64
+       x299, x300 = bits.Add64(x294, x291, uint64(p521Uint1(x298)))
+       var x301 uint64
+       var x302 uint64
+       x301, x302 = bits.Add64(x292, x289, uint64(p521Uint1(x300)))
+       var x303 uint64
+       var x304 uint64
+       x303, x304 = bits.Add64(x290, x287, uint64(p521Uint1(x302)))
+       var x305 uint64
+       var x306 uint64
+       x305, x306 = bits.Add64(x288, x285, uint64(p521Uint1(x304)))
+       var x307 uint64
+       var x308 uint64
+       x307, x308 = bits.Add64(x286, x283, uint64(p521Uint1(x306)))
+       var x309 uint64
+       var x310 uint64
+       x309, x310 = bits.Add64(x284, x281, uint64(p521Uint1(x308)))
+       var x311 uint64
+       var x312 uint64
+       x311, x312 = bits.Add64(x282, x279, uint64(p521Uint1(x310)))
+       var x314 uint64
+       _, x314 = bits.Add64(x247, x295, uint64(0x0))
+       var x315 uint64
+       var x316 uint64
+       x315, x316 = bits.Add64(x265, x297, uint64(p521Uint1(x314)))
+       var x317 uint64
+       var x318 uint64
+       x317, x318 = bits.Add64(x267, x299, uint64(p521Uint1(x316)))
+       var x319 uint64
+       var x320 uint64
+       x319, x320 = bits.Add64(x269, x301, uint64(p521Uint1(x318)))
+       var x321 uint64
+       var x322 uint64
+       x321, x322 = bits.Add64(x271, x303, uint64(p521Uint1(x320)))
+       var x323 uint64
+       var x324 uint64
+       x323, x324 = bits.Add64(x273, x305, uint64(p521Uint1(x322)))
+       var x325 uint64
+       var x326 uint64
+       x325, x326 = bits.Add64(x275, x307, uint64(p521Uint1(x324)))
+       var x327 uint64
+       var x328 uint64
+       x327, x328 = bits.Add64(x277, x309, uint64(p521Uint1(x326)))
+       var x329 uint64
+       var x330 uint64
+       x329, x330 = bits.Add64((uint64(p521Uint1(x278)) + (uint64(p521Uint1(x262)) + (uint64(p521Uint1(x244)) + x212))), x311, uint64(p521Uint1(x328)))
+       var x331 uint64
+       var x332 uint64
+       x332, x331 = bits.Mul64(arg1[6], 0x400000000000)
+       var x333 uint64
+       var x334 uint64
+       x333, x334 = bits.Add64(x317, x331, uint64(0x0))
+       var x335 uint64
+       var x336 uint64
+       x335, x336 = bits.Add64(x319, x332, uint64(p521Uint1(x334)))
+       var x337 uint64
+       var x338 uint64
+       x337, x338 = bits.Add64(x321, uint64(0x0), uint64(p521Uint1(x336)))
+       var x339 uint64
+       var x340 uint64
+       x339, x340 = bits.Add64(x323, uint64(0x0), uint64(p521Uint1(x338)))
+       var x341 uint64
+       var x342 uint64
+       x341, x342 = bits.Add64(x325, uint64(0x0), uint64(p521Uint1(x340)))
+       var x343 uint64
+       var x344 uint64
+       x343, x344 = bits.Add64(x327, uint64(0x0), uint64(p521Uint1(x342)))
+       var x345 uint64
+       var x346 uint64
+       x345, x346 = bits.Add64(x329, uint64(0x0), uint64(p521Uint1(x344)))
+       var x347 uint64
+       var x348 uint64
+       x348, x347 = bits.Mul64(x315, 0x1ff)
+       var x349 uint64
+       var x350 uint64
+       x350, x349 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x351 uint64
+       var x352 uint64
+       x352, x351 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x353 uint64
+       var x354 uint64
+       x354, x353 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x355 uint64
+       var x356 uint64
+       x356, x355 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x357 uint64
+       var x358 uint64
+       x358, x357 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x359 uint64
+       var x360 uint64
+       x360, x359 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x361 uint64
+       var x362 uint64
+       x362, x361 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x363 uint64
+       var x364 uint64
+       x364, x363 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x365 uint64
+       var x366 uint64
+       x365, x366 = bits.Add64(x364, x361, uint64(0x0))
+       var x367 uint64
+       var x368 uint64
+       x367, x368 = bits.Add64(x362, x359, uint64(p521Uint1(x366)))
+       var x369 uint64
+       var x370 uint64
+       x369, x370 = bits.Add64(x360, x357, uint64(p521Uint1(x368)))
+       var x371 uint64
+       var x372 uint64
+       x371, x372 = bits.Add64(x358, x355, uint64(p521Uint1(x370)))
+       var x373 uint64
+       var x374 uint64
+       x373, x374 = bits.Add64(x356, x353, uint64(p521Uint1(x372)))
+       var x375 uint64
+       var x376 uint64
+       x375, x376 = bits.Add64(x354, x351, uint64(p521Uint1(x374)))
+       var x377 uint64
+       var x378 uint64
+       x377, x378 = bits.Add64(x352, x349, uint64(p521Uint1(x376)))
+       var x379 uint64
+       var x380 uint64
+       x379, x380 = bits.Add64(x350, x347, uint64(p521Uint1(x378)))
+       var x382 uint64
+       _, x382 = bits.Add64(x315, x363, uint64(0x0))
+       var x383 uint64
+       var x384 uint64
+       x383, x384 = bits.Add64(x333, x365, uint64(p521Uint1(x382)))
+       var x385 uint64
+       var x386 uint64
+       x385, x386 = bits.Add64(x335, x367, uint64(p521Uint1(x384)))
+       var x387 uint64
+       var x388 uint64
+       x387, x388 = bits.Add64(x337, x369, uint64(p521Uint1(x386)))
+       var x389 uint64
+       var x390 uint64
+       x389, x390 = bits.Add64(x339, x371, uint64(p521Uint1(x388)))
+       var x391 uint64
+       var x392 uint64
+       x391, x392 = bits.Add64(x341, x373, uint64(p521Uint1(x390)))
+       var x393 uint64
+       var x394 uint64
+       x393, x394 = bits.Add64(x343, x375, uint64(p521Uint1(x392)))
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Add64(x345, x377, uint64(p521Uint1(x394)))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Add64((uint64(p521Uint1(x346)) + (uint64(p521Uint1(x330)) + (uint64(p521Uint1(x312)) + x280))), x379, uint64(p521Uint1(x396)))
+       var x399 uint64
+       var x400 uint64
+       x400, x399 = bits.Mul64(arg1[7], 0x400000000000)
+       var x401 uint64
+       var x402 uint64
+       x401, x402 = bits.Add64(x385, x399, uint64(0x0))
+       var x403 uint64
+       var x404 uint64
+       x403, x404 = bits.Add64(x387, x400, uint64(p521Uint1(x402)))
+       var x405 uint64
+       var x406 uint64
+       x405, x406 = bits.Add64(x389, uint64(0x0), uint64(p521Uint1(x404)))
+       var x407 uint64
+       var x408 uint64
+       x407, x408 = bits.Add64(x391, uint64(0x0), uint64(p521Uint1(x406)))
+       var x409 uint64
+       var x410 uint64
+       x409, x410 = bits.Add64(x393, uint64(0x0), uint64(p521Uint1(x408)))
+       var x411 uint64
+       var x412 uint64
+       x411, x412 = bits.Add64(x395, uint64(0x0), uint64(p521Uint1(x410)))
+       var x413 uint64
+       var x414 uint64
+       x413, x414 = bits.Add64(x397, uint64(0x0), uint64(p521Uint1(x412)))
+       var x415 uint64
+       var x416 uint64
+       x416, x415 = bits.Mul64(x383, 0x1ff)
+       var x417 uint64
+       var x418 uint64
+       x418, x417 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x419 uint64
+       var x420 uint64
+       x420, x419 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x421 uint64
+       var x422 uint64
+       x422, x421 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x423 uint64
+       var x424 uint64
+       x424, x423 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x425 uint64
+       var x426 uint64
+       x426, x425 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x427 uint64
+       var x428 uint64
+       x428, x427 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x429 uint64
+       var x430 uint64
+       x430, x429 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x431 uint64
+       var x432 uint64
+       x432, x431 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x433 uint64
+       var x434 uint64
+       x433, x434 = bits.Add64(x432, x429, uint64(0x0))
+       var x435 uint64
+       var x436 uint64
+       x435, x436 = bits.Add64(x430, x427, uint64(p521Uint1(x434)))
+       var x437 uint64
+       var x438 uint64
+       x437, x438 = bits.Add64(x428, x425, uint64(p521Uint1(x436)))
+       var x439 uint64
+       var x440 uint64
+       x439, x440 = bits.Add64(x426, x423, uint64(p521Uint1(x438)))
+       var x441 uint64
+       var x442 uint64
+       x441, x442 = bits.Add64(x424, x421, uint64(p521Uint1(x440)))
+       var x443 uint64
+       var x444 uint64
+       x443, x444 = bits.Add64(x422, x419, uint64(p521Uint1(x442)))
+       var x445 uint64
+       var x446 uint64
+       x445, x446 = bits.Add64(x420, x417, uint64(p521Uint1(x444)))
+       var x447 uint64
+       var x448 uint64
+       x447, x448 = bits.Add64(x418, x415, uint64(p521Uint1(x446)))
+       var x450 uint64
+       _, x450 = bits.Add64(x383, x431, uint64(0x0))
+       var x451 uint64
+       var x452 uint64
+       x451, x452 = bits.Add64(x401, x433, uint64(p521Uint1(x450)))
+       var x453 uint64
+       var x454 uint64
+       x453, x454 = bits.Add64(x403, x435, uint64(p521Uint1(x452)))
+       var x455 uint64
+       var x456 uint64
+       x455, x456 = bits.Add64(x405, x437, uint64(p521Uint1(x454)))
+       var x457 uint64
+       var x458 uint64
+       x457, x458 = bits.Add64(x407, x439, uint64(p521Uint1(x456)))
+       var x459 uint64
+       var x460 uint64
+       x459, x460 = bits.Add64(x409, x441, uint64(p521Uint1(x458)))
+       var x461 uint64
+       var x462 uint64
+       x461, x462 = bits.Add64(x411, x443, uint64(p521Uint1(x460)))
+       var x463 uint64
+       var x464 uint64
+       x463, x464 = bits.Add64(x413, x445, uint64(p521Uint1(x462)))
+       var x465 uint64
+       var x466 uint64
+       x465, x466 = bits.Add64((uint64(p521Uint1(x414)) + (uint64(p521Uint1(x398)) + (uint64(p521Uint1(x380)) + x348))), x447, uint64(p521Uint1(x464)))
+       var x467 uint64
+       var x468 uint64
+       x468, x467 = bits.Mul64(arg1[8], 0x400000000000)
+       var x469 uint64
+       var x470 uint64
+       x469, x470 = bits.Add64(x453, x467, uint64(0x0))
+       var x471 uint64
+       var x472 uint64
+       x471, x472 = bits.Add64(x455, x468, uint64(p521Uint1(x470)))
+       var x473 uint64
+       var x474 uint64
+       x473, x474 = bits.Add64(x457, uint64(0x0), uint64(p521Uint1(x472)))
+       var x475 uint64
+       var x476 uint64
+       x475, x476 = bits.Add64(x459, uint64(0x0), uint64(p521Uint1(x474)))
+       var x477 uint64
+       var x478 uint64
+       x477, x478 = bits.Add64(x461, uint64(0x0), uint64(p521Uint1(x476)))
+       var x479 uint64
+       var x480 uint64
+       x479, x480 = bits.Add64(x463, uint64(0x0), uint64(p521Uint1(x478)))
+       var x481 uint64
+       var x482 uint64
+       x481, x482 = bits.Add64(x465, uint64(0x0), uint64(p521Uint1(x480)))
+       var x483 uint64
+       var x484 uint64
+       x484, x483 = bits.Mul64(x451, 0x1ff)
+       var x485 uint64
+       var x486 uint64
+       x486, x485 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x487 uint64
+       var x488 uint64
+       x488, x487 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x489 uint64
+       var x490 uint64
+       x490, x489 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x491 uint64
+       var x492 uint64
+       x492, x491 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x493 uint64
+       var x494 uint64
+       x494, x493 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x495 uint64
+       var x496 uint64
+       x496, x495 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x497 uint64
+       var x498 uint64
+       x498, x497 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x499 uint64
+       var x500 uint64
+       x500, x499 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x501 uint64
+       var x502 uint64
+       x501, x502 = bits.Add64(x500, x497, uint64(0x0))
+       var x503 uint64
+       var x504 uint64
+       x503, x504 = bits.Add64(x498, x495, uint64(p521Uint1(x502)))
+       var x505 uint64
+       var x506 uint64
+       x505, x506 = bits.Add64(x496, x493, uint64(p521Uint1(x504)))
+       var x507 uint64
+       var x508 uint64
+       x507, x508 = bits.Add64(x494, x491, uint64(p521Uint1(x506)))
+       var x509 uint64
+       var x510 uint64
+       x509, x510 = bits.Add64(x492, x489, uint64(p521Uint1(x508)))
+       var x511 uint64
+       var x512 uint64
+       x511, x512 = bits.Add64(x490, x487, uint64(p521Uint1(x510)))
+       var x513 uint64
+       var x514 uint64
+       x513, x514 = bits.Add64(x488, x485, uint64(p521Uint1(x512)))
+       var x515 uint64
+       var x516 uint64
+       x515, x516 = bits.Add64(x486, x483, uint64(p521Uint1(x514)))
+       var x518 uint64
+       _, x518 = bits.Add64(x451, x499, uint64(0x0))
+       var x519 uint64
+       var x520 uint64
+       x519, x520 = bits.Add64(x469, x501, uint64(p521Uint1(x518)))
+       var x521 uint64
+       var x522 uint64
+       x521, x522 = bits.Add64(x471, x503, uint64(p521Uint1(x520)))
+       var x523 uint64
+       var x524 uint64
+       x523, x524 = bits.Add64(x473, x505, uint64(p521Uint1(x522)))
+       var x525 uint64
+       var x526 uint64
+       x525, x526 = bits.Add64(x475, x507, uint64(p521Uint1(x524)))
+       var x527 uint64
+       var x528 uint64
+       x527, x528 = bits.Add64(x477, x509, uint64(p521Uint1(x526)))
+       var x529 uint64
+       var x530 uint64
+       x529, x530 = bits.Add64(x479, x511, uint64(p521Uint1(x528)))
+       var x531 uint64
+       var x532 uint64
+       x531, x532 = bits.Add64(x481, x513, uint64(p521Uint1(x530)))
+       var x533 uint64
+       var x534 uint64
+       x533, x534 = bits.Add64((uint64(p521Uint1(x482)) + (uint64(p521Uint1(x466)) + (uint64(p521Uint1(x448)) + x416))), x515, uint64(p521Uint1(x532)))
+       x535 := (uint64(p521Uint1(x534)) + (uint64(p521Uint1(x516)) + x484))
+       var x536 uint64
+       var x537 uint64
+       x536, x537 = bits.Sub64(x519, 0xffffffffffffffff, uint64(0x0))
+       var x538 uint64
+       var x539 uint64
+       x538, x539 = bits.Sub64(x521, 0xffffffffffffffff, uint64(p521Uint1(x537)))
+       var x540 uint64
+       var x541 uint64
+       x540, x541 = bits.Sub64(x523, 0xffffffffffffffff, uint64(p521Uint1(x539)))
+       var x542 uint64
+       var x543 uint64
+       x542, x543 = bits.Sub64(x525, 0xffffffffffffffff, uint64(p521Uint1(x541)))
+       var x544 uint64
+       var x545 uint64
+       x544, x545 = bits.Sub64(x527, 0xffffffffffffffff, uint64(p521Uint1(x543)))
+       var x546 uint64
+       var x547 uint64
+       x546, x547 = bits.Sub64(x529, 0xffffffffffffffff, uint64(p521Uint1(x545)))
+       var x548 uint64
+       var x549 uint64
+       x548, x549 = bits.Sub64(x531, 0xffffffffffffffff, uint64(p521Uint1(x547)))
+       var x550 uint64
+       var x551 uint64
+       x550, x551 = bits.Sub64(x533, 0xffffffffffffffff, uint64(p521Uint1(x549)))
+       var x552 uint64
+       var x553 uint64
+       x552, x553 = bits.Sub64(x535, 0x1ff, uint64(p521Uint1(x551)))
+       var x555 uint64
+       _, x555 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p521Uint1(x553)))
+       var x556 uint64
+       p521CmovznzU64(&x556, p521Uint1(x555), x536, x519)
+       var x557 uint64
+       p521CmovznzU64(&x557, p521Uint1(x555), x538, x521)
+       var x558 uint64
+       p521CmovznzU64(&x558, p521Uint1(x555), x540, x523)
+       var x559 uint64
+       p521CmovznzU64(&x559, p521Uint1(x555), x542, x525)
+       var x560 uint64
+       p521CmovznzU64(&x560, p521Uint1(x555), x544, x527)
+       var x561 uint64
+       p521CmovznzU64(&x561, p521Uint1(x555), x546, x529)
+       var x562 uint64
+       p521CmovznzU64(&x562, p521Uint1(x555), x548, x531)
+       var x563 uint64
+       p521CmovznzU64(&x563, p521Uint1(x555), x550, x533)
+       var x564 uint64
+       p521CmovznzU64(&x564, p521Uint1(x555), x552, x535)
+       out1[0] = x556
+       out1[1] = x557
+       out1[2] = x558
+       out1[3] = x559
+       out1[4] = x560
+       out1[5] = x561
+       out1[6] = x562
+       out1[7] = x563
+       out1[8] = x564
 }
 
-// p521Sub subtracts two field elements.
+// p521Selectznz is a multi-limb conditional select.
 //
 // Postconditions:
-//   eval out1 mod m = (eval arg1 - eval arg2) mod m
+//   eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
 //
 // Input Bounds:
-//   arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-//   arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+//   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
 // Output Bounds:
-//   out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
-       x1 := ((0x7fffffffffffffe + arg1[0]) - arg2[0])
-       x2 := ((0x7fffffffffffffe + arg1[1]) - arg2[1])
-       x3 := ((0x7fffffffffffffe + arg1[2]) - arg2[2])
-       x4 := ((0x7fffffffffffffe + arg1[3]) - arg2[3])
-       x5 := ((0x7fffffffffffffe + arg1[4]) - arg2[4])
-       x6 := ((0x7fffffffffffffe + arg1[5]) - arg2[5])
-       x7 := ((0x7fffffffffffffe + arg1[6]) - arg2[6])
-       x8 := ((0x7fffffffffffffe + arg1[7]) - arg2[7])
-       x9 := ((0x3fffffffffffffe + arg1[8]) - arg2[8])
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]uint64) {
+       var x1 uint64
+       p521CmovznzU64(&x1, arg1, arg2[0], arg3[0])
+       var x2 uint64
+       p521CmovznzU64(&x2, arg1, arg2[1], arg3[1])
+       var x3 uint64
+       p521CmovznzU64(&x3, arg1, arg2[2], arg3[2])
+       var x4 uint64
+       p521CmovznzU64(&x4, arg1, arg2[3], arg3[3])
+       var x5 uint64
+       p521CmovznzU64(&x5, arg1, arg2[4], arg3[4])
+       var x6 uint64
+       p521CmovznzU64(&x6, arg1, arg2[5], arg3[5])
+       var x7 uint64
+       p521CmovznzU64(&x7, arg1, arg2[6], arg3[6])
+       var x8 uint64
+       p521CmovznzU64(&x8, arg1, arg2[7], arg3[7])
+       var x9 uint64
+       p521CmovznzU64(&x9, arg1, arg2[8], arg3[8])
        out1[0] = x1
        out1[1] = x2
        out1[2] = x3
@@ -1380,346 +5158,280 @@ func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
        out1[8] = x9
 }
 
-// p521ToBytes serializes a field element to bytes in little-endian order.
+// p521ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
 //
+// Preconditions:
+//   0 ≤ eval arg1 < m
 // Postconditions:
 //   out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..65]
 //
 // Input Bounds:
-//   arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+//   arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1ff]]
 // Output Bounds:
 //   out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]]
 func p521ToBytes(out1 *[66]uint8, arg1 *[9]uint64) {
-       var x1 uint64
-       var x2 p521Uint1
-       p521SubborrowxU58(&x1, &x2, 0x0, arg1[0], 0x3ffffffffffffff)
-       var x3 uint64
-       var x4 p521Uint1
-       p521SubborrowxU58(&x3, &x4, x2, arg1[1], 0x3ffffffffffffff)
-       var x5 uint64
-       var x6 p521Uint1
-       p521SubborrowxU58(&x5, &x6, x4, arg1[2], 0x3ffffffffffffff)
-       var x7 uint64
-       var x8 p521Uint1
-       p521SubborrowxU58(&x7, &x8, x6, arg1[3], 0x3ffffffffffffff)
-       var x9 uint64
-       var x10 p521Uint1
-       p521SubborrowxU58(&x9, &x10, x8, arg1[4], 0x3ffffffffffffff)
-       var x11 uint64
-       var x12 p521Uint1
-       p521SubborrowxU58(&x11, &x12, x10, arg1[5], 0x3ffffffffffffff)
-       var x13 uint64
-       var x14 p521Uint1
-       p521SubborrowxU58(&x13, &x14, x12, arg1[6], 0x3ffffffffffffff)
-       var x15 uint64
-       var x16 p521Uint1
-       p521SubborrowxU58(&x15, &x16, x14, arg1[7], 0x3ffffffffffffff)
-       var x17 uint64
-       var x18 p521Uint1
-       p521SubborrowxU57(&x17, &x18, x16, arg1[8], 0x1ffffffffffffff)
-       var x19 uint64
-       p521CmovznzU64(&x19, x18, uint64(0x0), 0xffffffffffffffff)
-       var x20 uint64
-       var x21 p521Uint1
-       p521AddcarryxU58(&x20, &x21, 0x0, x1, (x19 & 0x3ffffffffffffff))
-       var x22 uint64
-       var x23 p521Uint1
-       p521AddcarryxU58(&x22, &x23, x21, x3, (x19 & 0x3ffffffffffffff))
-       var x24 uint64
-       var x25 p521Uint1
-       p521AddcarryxU58(&x24, &x25, x23, x5, (x19 & 0x3ffffffffffffff))
-       var x26 uint64
-       var x27 p521Uint1
-       p521AddcarryxU58(&x26, &x27, x25, x7, (x19 & 0x3ffffffffffffff))
-       var x28 uint64
-       var x29 p521Uint1
-       p521AddcarryxU58(&x28, &x29, x27, x9, (x19 & 0x3ffffffffffffff))
-       var x30 uint64
-       var x31 p521Uint1
-       p521AddcarryxU58(&x30, &x31, x29, x11, (x19 & 0x3ffffffffffffff))
-       var x32 uint64
-       var x33 p521Uint1
-       p521AddcarryxU58(&x32, &x33, x31, x13, (x19 & 0x3ffffffffffffff))
-       var x34 uint64
-       var x35 p521Uint1
-       p521AddcarryxU58(&x34, &x35, x33, x15, (x19 & 0x3ffffffffffffff))
-       var x36 uint64
-       var x37 p521Uint1
-       p521AddcarryxU57(&x36, &x37, x35, x17, (x19 & 0x1ffffffffffffff))
-       x38 := (x34 << 6)
-       x39 := (x32 << 4)
-       x40 := (x30 << 2)
-       x41 := (x26 << 6)
-       x42 := (x24 << 4)
-       x43 := (x22 << 2)
-       x44 := (uint8(x20) & 0xff)
-       x45 := (x20 >> 8)
+       x1 := arg1[8]
+       x2 := arg1[7]
+       x3 := arg1[6]
+       x4 := arg1[5]
+       x5 := arg1[4]
+       x6 := arg1[3]
+       x7 := arg1[2]
+       x8 := arg1[1]
+       x9 := arg1[0]
+       x10 := (uint8(x9) & 0xff)
+       x11 := (x9 >> 8)
+       x12 := (uint8(x11) & 0xff)
+       x13 := (x11 >> 8)
+       x14 := (uint8(x13) & 0xff)
+       x15 := (x13 >> 8)
+       x16 := (uint8(x15) & 0xff)
+       x17 := (x15 >> 8)
+       x18 := (uint8(x17) & 0xff)
+       x19 := (x17 >> 8)
+       x20 := (uint8(x19) & 0xff)
+       x21 := (x19 >> 8)
+       x22 := (uint8(x21) & 0xff)
+       x23 := uint8((x21 >> 8))
+       x24 := (uint8(x8) & 0xff)
+       x25 := (x8 >> 8)
+       x26 := (uint8(x25) & 0xff)
+       x27 := (x25 >> 8)
+       x28 := (uint8(x27) & 0xff)
+       x29 := (x27 >> 8)
+       x30 := (uint8(x29) & 0xff)
+       x31 := (x29 >> 8)
+       x32 := (uint8(x31) & 0xff)
+       x33 := (x31 >> 8)
+       x34 := (uint8(x33) & 0xff)
+       x35 := (x33 >> 8)
+       x36 := (uint8(x35) & 0xff)
+       x37 := uint8((x35 >> 8))
+       x38 := (uint8(x7) & 0xff)
+       x39 := (x7 >> 8)
+       x40 := (uint8(x39) & 0xff)
+       x41 := (x39 >> 8)
+       x42 := (uint8(x41) & 0xff)
+       x43 := (x41 >> 8)
+       x44 := (uint8(x43) & 0xff)
+       x45 := (x43 >> 8)
        x46 := (uint8(x45) & 0xff)
        x47 := (x45 >> 8)
        x48 := (uint8(x47) & 0xff)
        x49 := (x47 >> 8)
        x50 := (uint8(x49) & 0xff)
-       x51 := (x49 >> 8)
-       x52 := (uint8(x51) & 0xff)
-       x53 := (x51 >> 8)
+       x51 := uint8((x49 >> 8))
+       x52 := (uint8(x6) & 0xff)
+       x53 := (x6 >> 8)
        x54 := (uint8(x53) & 0xff)
        x55 := (x53 >> 8)
        x56 := (uint8(x55) & 0xff)
-       x57 := uint8((x55 >> 8))
-       x58 := (x43 + uint64(x57))
-       x59 := (uint8(x58) & 0xff)
-       x60 := (x58 >> 8)
-       x61 := (uint8(x60) & 0xff)
-       x62 := (x60 >> 8)
-       x63 := (uint8(x62) & 0xff)
-       x64 := (x62 >> 8)
-       x65 := (uint8(x64) & 0xff)
-       x66 := (x64 >> 8)
-       x67 := (uint8(x66) & 0xff)
-       x68 := (x66 >> 8)
-       x69 := (uint8(x68) & 0xff)
-       x70 := (x68 >> 8)
-       x71 := (uint8(x70) & 0xff)
-       x72 := uint8((x70 >> 8))
-       x73 := (x42 + uint64(x72))
+       x57 := (x55 >> 8)
+       x58 := (uint8(x57) & 0xff)
+       x59 := (x57 >> 8)
+       x60 := (uint8(x59) & 0xff)
+       x61 := (x59 >> 8)
+       x62 := (uint8(x61) & 0xff)
+       x63 := (x61 >> 8)
+       x64 := (uint8(x63) & 0xff)
+       x65 := uint8((x63 >> 8))
+       x66 := (uint8(x5) & 0xff)
+       x67 := (x5 >> 8)
+       x68 := (uint8(x67) & 0xff)
+       x69 := (x67 >> 8)
+       x70 := (uint8(x69) & 0xff)
+       x71 := (x69 >> 8)
+       x72 := (uint8(x71) & 0xff)
+       x73 := (x71 >> 8)
        x74 := (uint8(x73) & 0xff)
        x75 := (x73 >> 8)
        x76 := (uint8(x75) & 0xff)
        x77 := (x75 >> 8)
        x78 := (uint8(x77) & 0xff)
-       x79 := (x77 >> 8)
-       x80 := (uint8(x79) & 0xff)
-       x81 := (x79 >> 8)
+       x79 := uint8((x77 >> 8))
+       x80 := (uint8(x4) & 0xff)
+       x81 := (x4 >> 8)
        x82 := (uint8(x81) & 0xff)
        x83 := (x81 >> 8)
        x84 := (uint8(x83) & 0xff)
        x85 := (x83 >> 8)
        x86 := (uint8(x85) & 0xff)
-       x87 := uint8((x85 >> 8))
-       x88 := (x41 + uint64(x87))
-       x89 := (uint8(x88) & 0xff)
-       x90 := (x88 >> 8)
-       x91 := (uint8(x90) & 0xff)
-       x92 := (x90 >> 8)
-       x93 := (uint8(x92) & 0xff)
-       x94 := (x92 >> 8)
-       x95 := (uint8(x94) & 0xff)
-       x96 := (x94 >> 8)
-       x97 := (uint8(x96) & 0xff)
-       x98 := (x96 >> 8)
-       x99 := (uint8(x98) & 0xff)
-       x100 := (x98 >> 8)
-       x101 := (uint8(x100) & 0xff)
-       x102 := uint8((x100 >> 8))
-       x103 := (uint8(x28) & 0xff)
-       x104 := (x28 >> 8)
-       x105 := (uint8(x104) & 0xff)
-       x106 := (x104 >> 8)
-       x107 := (uint8(x106) & 0xff)
-       x108 := (x106 >> 8)
-       x109 := (uint8(x108) & 0xff)
-       x110 := (x108 >> 8)
-       x111 := (uint8(x110) & 0xff)
-       x112 := (x110 >> 8)
-       x113 := (uint8(x112) & 0xff)
-       x114 := (x112 >> 8)
-       x115 := (uint8(x114) & 0xff)
-       x116 := uint8((x114 >> 8))
-       x117 := (x40 + uint64(x116))
+       x87 := (x85 >> 8)
+       x88 := (uint8(x87) & 0xff)
+       x89 := (x87 >> 8)
+       x90 := (uint8(x89) & 0xff)
+       x91 := (x89 >> 8)
+       x92 := (uint8(x91) & 0xff)
+       x93 := uint8((x91 >> 8))
+       x94 := (uint8(x3) & 0xff)
+       x95 := (x3 >> 8)
+       x96 := (uint8(x95) & 0xff)
+       x97 := (x95 >> 8)
+       x98 := (uint8(x97) & 0xff)
+       x99 := (x97 >> 8)
+       x100 := (uint8(x99) & 0xff)
+       x101 := (x99 >> 8)
+       x102 := (uint8(x101) & 0xff)
+       x103 := (x101 >> 8)
+       x104 := (uint8(x103) & 0xff)
+       x105 := (x103 >> 8)
+       x106 := (uint8(x105) & 0xff)
+       x107 := uint8((x105 >> 8))
+       x108 := (uint8(x2) & 0xff)
+       x109 := (x2 >> 8)
+       x110 := (uint8(x109) & 0xff)
+       x111 := (x109 >> 8)
+       x112 := (uint8(x111) & 0xff)
+       x113 := (x111 >> 8)
+       x114 := (uint8(x113) & 0xff)
+       x115 := (x113 >> 8)
+       x116 := (uint8(x115) & 0xff)
+       x117 := (x115 >> 8)
        x118 := (uint8(x117) & 0xff)
        x119 := (x117 >> 8)
        x120 := (uint8(x119) & 0xff)
-       x121 := (x119 >> 8)
-       x122 := (uint8(x121) & 0xff)
-       x123 := (x121 >> 8)
-       x124 := (uint8(x123) & 0xff)
-       x125 := (x123 >> 8)
-       x126 := (uint8(x125) & 0xff)
-       x127 := (x125 >> 8)
-       x128 := (uint8(x127) & 0xff)
-       x129 := (x127 >> 8)
-       x130 := (uint8(x129) & 0xff)
-       x131 := uint8((x129 >> 8))
-       x132 := (x39 + uint64(x131))
-       x133 := (uint8(x132) & 0xff)
-       x134 := (x132 >> 8)
-       x135 := (uint8(x134) & 0xff)
-       x136 := (x134 >> 8)
-       x137 := (uint8(x136) & 0xff)
-       x138 := (x136 >> 8)
-       x139 := (uint8(x138) & 0xff)
-       x140 := (x138 >> 8)
-       x141 := (uint8(x140) & 0xff)
-       x142 := (x140 >> 8)
-       x143 := (uint8(x142) & 0xff)
-       x144 := (x142 >> 8)
-       x145 := (uint8(x144) & 0xff)
-       x146 := uint8((x144 >> 8))
-       x147 := (x38 + uint64(x146))
-       x148 := (uint8(x147) & 0xff)
-       x149 := (x147 >> 8)
-       x150 := (uint8(x149) & 0xff)
-       x151 := (x149 >> 8)
-       x152 := (uint8(x151) & 0xff)
-       x153 := (x151 >> 8)
-       x154 := (uint8(x153) & 0xff)
-       x155 := (x153 >> 8)
-       x156 := (uint8(x155) & 0xff)
-       x157 := (x155 >> 8)
-       x158 := (uint8(x157) & 0xff)
-       x159 := (x157 >> 8)
-       x160 := (uint8(x159) & 0xff)
-       x161 := uint8((x159 >> 8))
-       x162 := (uint8(x36) & 0xff)
-       x163 := (x36 >> 8)
-       x164 := (uint8(x163) & 0xff)
-       x165 := (x163 >> 8)
-       x166 := (uint8(x165) & 0xff)
-       x167 := (x165 >> 8)
-       x168 := (uint8(x167) & 0xff)
-       x169 := (x167 >> 8)
-       x170 := (uint8(x169) & 0xff)
-       x171 := (x169 >> 8)
-       x172 := (uint8(x171) & 0xff)
-       x173 := (x171 >> 8)
-       x174 := (uint8(x173) & 0xff)
-       x175 := p521Uint1((x173 >> 8))
-       out1[0] = x44
-       out1[1] = x46
-       out1[2] = x48
-       out1[3] = x50
-       out1[4] = x52
-       out1[5] = x54
-       out1[6] = x56
-       out1[7] = x59
-       out1[8] = x61
-       out1[9] = x63
-       out1[10] = x65
-       out1[11] = x67
-       out1[12] = x69
-       out1[13] = x71
-       out1[14] = x74
-       out1[15] = x76
-       out1[16] = x78
-       out1[17] = x80
-       out1[18] = x82
-       out1[19] = x84
-       out1[20] = x86
-       out1[21] = x89
-       out1[22] = x91
-       out1[23] = x93
-       out1[24] = x95
-       out1[25] = x97
-       out1[26] = x99
-       out1[27] = x101
-       out1[28] = x102
-       out1[29] = x103
-       out1[30] = x105
-       out1[31] = x107
-       out1[32] = x109
-       out1[33] = x111
-       out1[34] = x113
-       out1[35] = x115
-       out1[36] = x118
-       out1[37] = x120
-       out1[38] = x122
-       out1[39] = x124
-       out1[40] = x126
-       out1[41] = x128
-       out1[42] = x130
-       out1[43] = x133
-       out1[44] = x135
-       out1[45] = x137
-       out1[46] = x139
-       out1[47] = x141
-       out1[48] = x143
-       out1[49] = x145
-       out1[50] = x148
-       out1[51] = x150
-       out1[52] = x152
-       out1[53] = x154
-       out1[54] = x156
-       out1[55] = x158
-       out1[56] = x160
-       out1[57] = x161
-       out1[58] = x162
-       out1[59] = x164
-       out1[60] = x166
-       out1[61] = x168
-       out1[62] = x170
-       out1[63] = x172
-       out1[64] = x174
-       out1[65] = uint8(x175)
+       x121 := uint8((x119 >> 8))
+       x122 := (uint8(x1) & 0xff)
+       x123 := p521Uint1((x1 >> 8))
+       out1[0] = x10
+       out1[1] = x12
+       out1[2] = x14
+       out1[3] = x16
+       out1[4] = x18
+       out1[5] = x20
+       out1[6] = x22
+       out1[7] = x23
+       out1[8] = x24
+       out1[9] = x26
+       out1[10] = x28
+       out1[11] = x30
+       out1[12] = x32
+       out1[13] = x34
+       out1[14] = x36
+       out1[15] = x37
+       out1[16] = x38
+       out1[17] = x40
+       out1[18] = x42
+       out1[19] = x44
+       out1[20] = x46
+       out1[21] = x48
+       out1[22] = x50
+       out1[23] = x51
+       out1[24] = x52
+       out1[25] = x54
+       out1[26] = x56
+       out1[27] = x58
+       out1[28] = x60
+       out1[29] = x62
+       out1[30] = x64
+       out1[31] = x65
+       out1[32] = x66
+       out1[33] = x68
+       out1[34] = x70
+       out1[35] = x72
+       out1[36] = x74
+       out1[37] = x76
+       out1[38] = x78
+       out1[39] = x79
+       out1[40] = x80
+       out1[41] = x82
+       out1[42] = x84
+       out1[43] = x86
+       out1[44] = x88
+       out1[45] = x90
+       out1[46] = x92
+       out1[47] = x93
+       out1[48] = x94
+       out1[49] = x96
+       out1[50] = x98
+       out1[51] = x100
+       out1[52] = x102
+       out1[53] = x104
+       out1[54] = x106
+       out1[55] = x107
+       out1[56] = x108
+       out1[57] = x110
+       out1[58] = x112
+       out1[59] = x114
+       out1[60] = x116
+       out1[61] = x118
+       out1[62] = x120
+       out1[63] = x121
+       out1[64] = x122
+       out1[65] = uint8(x123)
 }
 
-// p521FromBytes deserializes a field element from bytes in little-endian order.
+// p521FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
 //
+// Preconditions:
+//   0 ≤ bytes_eval arg1 < m
 // Postconditions:
 //   eval out1 mod m = bytes_eval arg1 mod m
+//   0 ≤ eval out1 < m
 //
 // Input Bounds:
 //   arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]]
 // Output Bounds:
-//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1ff]]
 func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) {
-       x1 := (uint64(p521Uint1(arg1[65])) << 56)
-       x2 := (uint64(arg1[64]) << 48)
-       x3 := (uint64(arg1[63]) << 40)
-       x4 := (uint64(arg1[62]) << 32)
-       x5 := (uint64(arg1[61]) << 24)
-       x6 := (uint64(arg1[60]) << 16)
-       x7 := (uint64(arg1[59]) << 8)
-       x8 := arg1[58]
-       x9 := (uint64(arg1[57]) << 50)
-       x10 := (uint64(arg1[56]) << 42)
-       x11 := (uint64(arg1[55]) << 34)
-       x12 := (uint64(arg1[54]) << 26)
-       x13 := (uint64(arg1[53]) << 18)
-       x14 := (uint64(arg1[52]) << 10)
-       x15 := (uint64(arg1[51]) << 2)
-       x16 := (uint64(arg1[50]) << 52)
-       x17 := (uint64(arg1[49]) << 44)
-       x18 := (uint64(arg1[48]) << 36)
-       x19 := (uint64(arg1[47]) << 28)
-       x20 := (uint64(arg1[46]) << 20)
-       x21 := (uint64(arg1[45]) << 12)
-       x22 := (uint64(arg1[44]) << 4)
-       x23 := (uint64(arg1[43]) << 54)
-       x24 := (uint64(arg1[42]) << 46)
-       x25 := (uint64(arg1[41]) << 38)
-       x26 := (uint64(arg1[40]) << 30)
-       x27 := (uint64(arg1[39]) << 22)
-       x28 := (uint64(arg1[38]) << 14)
-       x29 := (uint64(arg1[37]) << 6)
-       x30 := (uint64(arg1[36]) << 56)
-       x31 := (uint64(arg1[35]) << 48)
-       x32 := (uint64(arg1[34]) << 40)
-       x33 := (uint64(arg1[33]) << 32)
-       x34 := (uint64(arg1[32]) << 24)
-       x35 := (uint64(arg1[31]) << 16)
-       x36 := (uint64(arg1[30]) << 8)
-       x37 := arg1[29]
-       x38 := (uint64(arg1[28]) << 50)
-       x39 := (uint64(arg1[27]) << 42)
-       x40 := (uint64(arg1[26]) << 34)
-       x41 := (uint64(arg1[25]) << 26)
-       x42 := (uint64(arg1[24]) << 18)
-       x43 := (uint64(arg1[23]) << 10)
-       x44 := (uint64(arg1[22]) << 2)
-       x45 := (uint64(arg1[21]) << 52)
-       x46 := (uint64(arg1[20]) << 44)
-       x47 := (uint64(arg1[19]) << 36)
-       x48 := (uint64(arg1[18]) << 28)
-       x49 := (uint64(arg1[17]) << 20)
-       x50 := (uint64(arg1[16]) << 12)
-       x51 := (uint64(arg1[15]) << 4)
-       x52 := (uint64(arg1[14]) << 54)
-       x53 := (uint64(arg1[13]) << 46)
-       x54 := (uint64(arg1[12]) << 38)
-       x55 := (uint64(arg1[11]) << 30)
-       x56 := (uint64(arg1[10]) << 22)
-       x57 := (uint64(arg1[9]) << 14)
-       x58 := (uint64(arg1[8]) << 6)
+       x1 := (uint64(p521Uint1(arg1[65])) << 8)
+       x2 := arg1[64]
+       x3 := (uint64(arg1[63]) << 56)
+       x4 := (uint64(arg1[62]) << 48)
+       x5 := (uint64(arg1[61]) << 40)
+       x6 := (uint64(arg1[60]) << 32)
+       x7 := (uint64(arg1[59]) << 24)
+       x8 := (uint64(arg1[58]) << 16)
+       x9 := (uint64(arg1[57]) << 8)
+       x10 := arg1[56]
+       x11 := (uint64(arg1[55]) << 56)
+       x12 := (uint64(arg1[54]) << 48)
+       x13 := (uint64(arg1[53]) << 40)
+       x14 := (uint64(arg1[52]) << 32)
+       x15 := (uint64(arg1[51]) << 24)
+       x16 := (uint64(arg1[50]) << 16)
+       x17 := (uint64(arg1[49]) << 8)
+       x18 := arg1[48]
+       x19 := (uint64(arg1[47]) << 56)
+       x20 := (uint64(arg1[46]) << 48)
+       x21 := (uint64(arg1[45]) << 40)
+       x22 := (uint64(arg1[44]) << 32)
+       x23 := (uint64(arg1[43]) << 24)
+       x24 := (uint64(arg1[42]) << 16)
+       x25 := (uint64(arg1[41]) << 8)
+       x26 := arg1[40]
+       x27 := (uint64(arg1[39]) << 56)
+       x28 := (uint64(arg1[38]) << 48)
+       x29 := (uint64(arg1[37]) << 40)
+       x30 := (uint64(arg1[36]) << 32)
+       x31 := (uint64(arg1[35]) << 24)
+       x32 := (uint64(arg1[34]) << 16)
+       x33 := (uint64(arg1[33]) << 8)
+       x34 := arg1[32]
+       x35 := (uint64(arg1[31]) << 56)
+       x36 := (uint64(arg1[30]) << 48)
+       x37 := (uint64(arg1[29]) << 40)
+       x38 := (uint64(arg1[28]) << 32)
+       x39 := (uint64(arg1[27]) << 24)
+       x40 := (uint64(arg1[26]) << 16)
+       x41 := (uint64(arg1[25]) << 8)
+       x42 := arg1[24]
+       x43 := (uint64(arg1[23]) << 56)
+       x44 := (uint64(arg1[22]) << 48)
+       x45 := (uint64(arg1[21]) << 40)
+       x46 := (uint64(arg1[20]) << 32)
+       x47 := (uint64(arg1[19]) << 24)
+       x48 := (uint64(arg1[18]) << 16)
+       x49 := (uint64(arg1[17]) << 8)
+       x50 := arg1[16]
+       x51 := (uint64(arg1[15]) << 56)
+       x52 := (uint64(arg1[14]) << 48)
+       x53 := (uint64(arg1[13]) << 40)
+       x54 := (uint64(arg1[12]) << 32)
+       x55 := (uint64(arg1[11]) << 24)
+       x56 := (uint64(arg1[10]) << 16)
+       x57 := (uint64(arg1[9]) << 8)
+       x58 := arg1[8]
        x59 := (uint64(arg1[7]) << 56)
        x60 := (uint64(arg1[6]) << 48)
        x61 := (uint64(arg1[5]) << 40)
@@ -1735,122 +5447,63 @@ func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) {
        x71 := (x61 + x70)
        x72 := (x60 + x71)
        x73 := (x59 + x72)
-       x74 := (x73 & 0x3ffffffffffffff)
-       x75 := uint8((x73 >> 58))
-       x76 := (x58 + uint64(x75))
-       x77 := (x57 + x76)
-       x78 := (x56 + x77)
-       x79 := (x55 + x78)
-       x80 := (x54 + x79)
-       x81 := (x53 + x80)
-       x82 := (x52 + x81)
-       x83 := (x82 & 0x3ffffffffffffff)
-       x84 := uint8((x82 >> 58))
-       x85 := (x51 + uint64(x84))
-       x86 := (x50 + x85)
-       x87 := (x49 + x86)
-       x88 := (x48 + x87)
-       x89 := (x47 + x88)
-       x90 := (x46 + x89)
-       x91 := (x45 + x90)
-       x92 := (x91 & 0x3ffffffffffffff)
-       x93 := uint8((x91 >> 58))
-       x94 := (x44 + uint64(x93))
-       x95 := (x43 + x94)
-       x96 := (x42 + x95)
-       x97 := (x41 + x96)
-       x98 := (x40 + x97)
-       x99 := (x39 + x98)
-       x100 := (x38 + x99)
-       x101 := (x36 + uint64(x37))
-       x102 := (x35 + x101)
-       x103 := (x34 + x102)
-       x104 := (x33 + x103)
-       x105 := (x32 + x104)
-       x106 := (x31 + x105)
-       x107 := (x30 + x106)
-       x108 := (x107 & 0x3ffffffffffffff)
-       x109 := uint8((x107 >> 58))
-       x110 := (x29 + uint64(x109))
-       x111 := (x28 + x110)
-       x112 := (x27 + x111)
-       x113 := (x26 + x112)
-       x114 := (x25 + x113)
-       x115 := (x24 + x114)
-       x116 := (x23 + x115)
-       x117 := (x116 & 0x3ffffffffffffff)
-       x118 := uint8((x116 >> 58))
-       x119 := (x22 + uint64(x118))
-       x120 := (x21 + x119)
-       x121 := (x20 + x120)
-       x122 := (x19 + x121)
-       x123 := (x18 + x122)
-       x124 := (x17 + x123)
-       x125 := (x16 + x124)
-       x126 := (x125 & 0x3ffffffffffffff)
-       x127 := uint8((x125 >> 58))
-       x128 := (x15 + uint64(x127))
-       x129 := (x14 + x128)
-       x130 := (x13 + x129)
-       x131 := (x12 + x130)
-       x132 := (x11 + x131)
-       x133 := (x10 + x132)
-       x134 := (x9 + x133)
-       x135 := (x7 + uint64(x8))
-       x136 := (x6 + x135)
-       x137 := (x5 + x136)
-       x138 := (x4 + x137)
-       x139 := (x3 + x138)
-       x140 := (x2 + x139)
-       x141 := (x1 + x140)
-       out1[0] = x74
-       out1[1] = x83
-       out1[2] = x92
-       out1[3] = x100
-       out1[4] = x108
-       out1[5] = x117
-       out1[6] = x126
-       out1[7] = x134
-       out1[8] = x141
-}
-
-// p521Selectznz is a multi-limb conditional select.
-//
-// Postconditions:
-//   eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
-//
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
-//   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
-func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]uint64) {
-       var x1 uint64
-       p521CmovznzU64(&x1, arg1, arg2[0], arg3[0])
-       var x2 uint64
-       p521CmovznzU64(&x2, arg1, arg2[1], arg3[1])
-       var x3 uint64
-       p521CmovznzU64(&x3, arg1, arg2[2], arg3[2])
-       var x4 uint64
-       p521CmovznzU64(&x4, arg1, arg2[3], arg3[3])
-       var x5 uint64
-       p521CmovznzU64(&x5, arg1, arg2[4], arg3[4])
-       var x6 uint64
-       p521CmovznzU64(&x6, arg1, arg2[5], arg3[5])
-       var x7 uint64
-       p521CmovznzU64(&x7, arg1, arg2[6], arg3[6])
-       var x8 uint64
-       p521CmovznzU64(&x8, arg1, arg2[7], arg3[7])
-       var x9 uint64
-       p521CmovznzU64(&x9, arg1, arg2[8], arg3[8])
-       out1[0] = x1
-       out1[1] = x2
-       out1[2] = x3
-       out1[3] = x4
-       out1[4] = x5
-       out1[5] = x6
-       out1[6] = x7
-       out1[7] = x8
-       out1[8] = x9
+       x74 := (x57 + uint64(x58))
+       x75 := (x56 + x74)
+       x76 := (x55 + x75)
+       x77 := (x54 + x76)
+       x78 := (x53 + x77)
+       x79 := (x52 + x78)
+       x80 := (x51 + x79)
+       x81 := (x49 + uint64(x50))
+       x82 := (x48 + x81)
+       x83 := (x47 + x82)
+       x84 := (x46 + x83)
+       x85 := (x45 + x84)
+       x86 := (x44 + x85)
+       x87 := (x43 + x86)
+       x88 := (x41 + uint64(x42))
+       x89 := (x40 + x88)
+       x90 := (x39 + x89)
+       x91 := (x38 + x90)
+       x92 := (x37 + x91)
+       x93 := (x36 + x92)
+       x94 := (x35 + x93)
+       x95 := (x33 + uint64(x34))
+       x96 := (x32 + x95)
+       x97 := (x31 + x96)
+       x98 := (x30 + x97)
+       x99 := (x29 + x98)
+       x100 := (x28 + x99)
+       x101 := (x27 + x100)
+       x102 := (x25 + uint64(x26))
+       x103 := (x24 + x102)
+       x104 := (x23 + x103)
+       x105 := (x22 + x104)
+       x106 := (x21 + x105)
+       x107 := (x20 + x106)
+       x108 := (x19 + x107)
+       x109 := (x17 + uint64(x18))
+       x110 := (x16 + x109)
+       x111 := (x15 + x110)
+       x112 := (x14 + x111)
+       x113 := (x13 + x112)
+       x114 := (x12 + x113)
+       x115 := (x11 + x114)
+       x116 := (x9 + uint64(x10))
+       x117 := (x8 + x116)
+       x118 := (x7 + x117)
+       x119 := (x6 + x118)
+       x120 := (x5 + x119)
+       x121 := (x4 + x120)
+       x122 := (x3 + x121)
+       x123 := (x1 + uint64(x2))
+       out1[0] = x73
+       out1[1] = x80
+       out1[2] = x87
+       out1[3] = x94
+       out1[4] = x101
+       out1[5] = x108
+       out1[6] = x115
+       out1[7] = x122
+       out1[8] = x123
 }
diff --git a/src/crypto/elliptic/internal/fiat/p521_invert.go b/src/crypto/elliptic/internal/fiat/p521_invert.go
new file mode 100644 (file)
index 0000000..407711a
--- /dev/null
@@ -0,0 +1,89 @@
+// Copyright 2021 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.
+
+// Code generated by addchain. DO NOT EDIT.
+
+package fiat
+
+// Invert sets e = 1/x, and returns e.
+//
+// If x == 0, Invert returns e = 0.
+func (e *P521Element) Invert(x *P521Element) *P521Element {
+       // Inversion is implemented as exponentiation with exponent p − 2.
+       // The sequence of 13 multiplications and 520 squarings is derived from the
+       // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0.
+       //
+       //      _10       = 2*1
+       //      _11       = 1 + _10
+       //      _1100     = _11 << 2
+       //      _1111     = _11 + _1100
+       //      _11110000 = _1111 << 4
+       //      _11111111 = _1111 + _11110000
+       //      x16       = _11111111 << 8 + _11111111
+       //      x32       = x16 << 16 + x16
+       //      x64       = x32 << 32 + x32
+       //      x65       = 2*x64 + 1
+       //      x129      = x65 << 64 + x64
+       //      x130      = 2*x129 + 1
+       //      x259      = x130 << 129 + x129
+       //      x260      = 2*x259 + 1
+       //      x519      = x260 << 259 + x259
+       //      return      x519 << 2 + 1
+       //
+
+       var z = new(P521Element).Set(e)
+       var t0 = new(P521Element)
+
+       z.Square(x)
+       z.Mul(x, z)
+       t0.Square(z)
+       for s := 1; s < 2; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       for s := 1; s < 4; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       for s := 1; s < 8; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       for s := 1; s < 16; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       for s := 1; s < 32; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       t0.Mul(x, t0)
+       for s := 0; s < 64; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       t0.Mul(x, t0)
+       for s := 0; s < 129; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       t0.Mul(x, t0)
+       for s := 0; s < 259; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       for s := 0; s < 2; s++ {
+               z.Square(z)
+       }
+       z.Mul(x, z)
+
+       return e.Set(z)
+}
diff --git a/src/crypto/elliptic/internal/fiat/p521_test.go b/src/crypto/elliptic/internal/fiat/p521_test.go
deleted file mode 100644 (file)
index 2b374fa..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2021 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.
-
-package fiat_test
-
-import (
-       "crypto/elliptic/internal/fiat"
-       "crypto/rand"
-       "testing"
-)
-
-func p521Random(t *testing.T) *fiat.P521Element {
-       buf := make([]byte, 66)
-       if _, err := rand.Read(buf); err != nil {
-               t.Fatal(err)
-       }
-       buf[0] &= 1
-       e, err := new(fiat.P521Element).SetBytes(buf)
-       if err != nil {
-               t.Fatal(err)
-       }
-       return e
-}
-
-func TestP521Invert(t *testing.T) {
-       a := p521Random(t)
-       inv := new(fiat.P521Element).Invert(a)
-       one := new(fiat.P521Element).Mul(a, inv)
-       if new(fiat.P521Element).One().Equal(one) != 1 {
-               t.Errorf("a * 1/a != 1; got %x for %x", one.Bytes(), a.Bytes())
-       }
-       inv.Invert(new(fiat.P521Element))
-       if new(fiat.P521Element).Equal(inv) != 1 {
-               t.Errorf("1/0 != 0; got %x", inv.Bytes())
-       }
-}
diff --git a/src/crypto/elliptic/internal/nistec/nistec_test.go b/src/crypto/elliptic/internal/nistec/nistec_test.go
new file mode 100644 (file)
index 0000000..4eae998
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright 2021 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.
+
+package nistec_test
+
+import (
+       "crypto/elliptic/internal/nistec"
+       "math/rand"
+       "os"
+       "strings"
+       "testing"
+)
+
+func TestAllocations(t *testing.T) {
+       if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") {
+               t.Skip("skipping allocations test without relevant optimizations")
+       }
+       t.Run("P224", func(t *testing.T) {
+               if allocs := testing.AllocsPerRun(100, func() {
+                       p := nistec.NewP224Generator()
+                       scalar := make([]byte, 66)
+                       rand.Read(scalar)
+                       p.ScalarMult(p, scalar)
+                       out := p.Bytes()
+                       if _, err := p.SetBytes(out); err != nil {
+                               t.Fatal(err)
+                       }
+               }); allocs > 0 {
+                       t.Errorf("expected zero allocations, got %0.1f", allocs)
+               }
+       })
+       t.Run("P384", func(t *testing.T) {
+               if allocs := testing.AllocsPerRun(100, func() {
+                       p := nistec.NewP384Generator()
+                       scalar := make([]byte, 66)
+                       rand.Read(scalar)
+                       p.ScalarMult(p, scalar)
+                       out := p.Bytes()
+                       if _, err := p.SetBytes(out); err != nil {
+                               t.Fatal(err)
+                       }
+               }); allocs > 0 {
+                       t.Errorf("expected zero allocations, got %0.1f", allocs)
+               }
+       })
+       t.Run("P521", func(t *testing.T) {
+               if allocs := testing.AllocsPerRun(100, func() {
+                       p := nistec.NewP521Generator()
+                       scalar := make([]byte, 66)
+                       rand.Read(scalar)
+                       p.ScalarMult(p, scalar)
+                       out := p.Bytes()
+                       if _, err := p.SetBytes(out); err != nil {
+                               t.Fatal(err)
+                       }
+               }); allocs > 0 {
+                       t.Errorf("expected zero allocations, got %0.1f", allocs)
+               }
+       })
+}
+
+func BenchmarkScalarMult(b *testing.B) {
+       b.Run("P224", func(b *testing.B) {
+               scalar := make([]byte, 66)
+               rand.Read(scalar)
+               p := nistec.NewP224Generator()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       p.ScalarMult(p, scalar)
+               }
+       })
+       b.Run("P384", func(b *testing.B) {
+               scalar := make([]byte, 66)
+               rand.Read(scalar)
+               p := nistec.NewP384Generator()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       p.ScalarMult(p, scalar)
+               }
+       })
+       b.Run("P521", func(b *testing.B) {
+               scalar := make([]byte, 66)
+               rand.Read(scalar)
+               p := nistec.NewP521Generator()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       p.ScalarMult(p, scalar)
+               }
+       })
+}
diff --git a/src/crypto/elliptic/internal/nistec/p224.go b/src/crypto/elliptic/internal/nistec/p224.go
new file mode 100644 (file)
index 0000000..74dbc18
--- /dev/null
@@ -0,0 +1,293 @@
+// Copyright 2021 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.
+
+package nistec
+
+import (
+       "crypto/elliptic/internal/fiat"
+       "crypto/subtle"
+       "errors"
+)
+
+var p224B, _ = new(fiat.P224Element).SetBytes([]byte{0xb4, 0x05, 0x0a, 0x85,
+       0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7,
+       0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4})
+
+var p224G, _ = NewP224Point().SetBytes([]byte{0x04,
+       0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9,
+       0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
+       0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb,
+       0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64,
+       0x44, 0xd5, 0x81, 0x99, 0x85, 0x0, 0x7e, 0x34})
+
+const p224ElementLength = 28
+
+// P224Point is a P-224 point. The zero value is NOT valid.
+type P224Point struct {
+       // The point is represented in projective coordinates (X:Y:Z),
+       // where x = X/Z and y = Y/Z.
+       x, y, z *fiat.P224Element
+}
+
+// NewP224Point returns a new P224Point representing the point at infinity point.
+func NewP224Point() *P224Point {
+       return &P224Point{
+               x: new(fiat.P224Element),
+               y: new(fiat.P224Element).One(),
+               z: new(fiat.P224Element),
+       }
+}
+
+// NewP224Generator returns a new P224Point set to the canonical generator.
+func NewP224Generator() *P224Point {
+       return (&P224Point{
+               x: new(fiat.P224Element),
+               y: new(fiat.P224Element),
+               z: new(fiat.P224Element),
+       }).Set(p224G)
+}
+
+// Set sets p = q and returns p.
+func (p *P224Point) Set(q *P224Point) *P224Point {
+       p.x.Set(q.x)
+       p.y.Set(q.y)
+       p.z.Set(q.z)
+       return p
+}
+
+// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in
+// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on
+// the curve, it returns nil and an error, and the receiver is unchanged.
+// Otherwise, it returns p.
+func (p *P224Point) SetBytes(b []byte) (*P224Point, error) {
+       switch {
+       // Point at infinity.
+       case len(b) == 1 && b[0] == 0:
+               return p.Set(NewP224Point()), nil
+
+       // Uncompressed form.
+       case len(b) == 1+2*p224ElementLength && b[0] == 4:
+               x, err := new(fiat.P224Element).SetBytes(b[1 : 1+p224ElementLength])
+               if err != nil {
+                       return nil, err
+               }
+               y, err := new(fiat.P224Element).SetBytes(b[1+p224ElementLength:])
+               if err != nil {
+                       return nil, err
+               }
+               if err := p224CheckOnCurve(x, y); err != nil {
+                       return nil, err
+               }
+               p.x.Set(x)
+               p.y.Set(y)
+               p.z.One()
+               return p, nil
+
+       // Compressed form
+       case len(b) == 1+p224ElementLength && b[0] == 0:
+               return nil, errors.New("unimplemented") // TODO(filippo)
+
+       default:
+               return nil, errors.New("invalid P224 point encoding")
+       }
+}
+
+func p224CheckOnCurve(x, y *fiat.P224Element) error {
+       // x³ - 3x + b.
+       x3 := new(fiat.P224Element).Square(x)
+       x3.Mul(x3, x)
+
+       threeX := new(fiat.P224Element).Add(x, x)
+       threeX.Add(threeX, x)
+
+       x3.Sub(x3, threeX)
+       x3.Add(x3, p224B)
+
+       // y² = x³ - 3x + b
+       y2 := new(fiat.P224Element).Square(y)
+
+       if x3.Equal(y2) != 1 {
+               return errors.New("P224 point not on curve")
+       }
+       return nil
+}
+
+// Bytes returns the uncompressed or infinity encoding of p, as specified in
+// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at
+// infinity is shorter than all other encodings.
+func (p *P224Point) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [133]byte
+       return p.bytes(&out)
+}
+
+func (p *P224Point) bytes(out *[133]byte) []byte {
+       if p.z.IsZero() == 1 {
+               return append(out[:0], 0)
+       }
+
+       zinv := new(fiat.P224Element).Invert(p.z)
+       xx := new(fiat.P224Element).Mul(p.x, zinv)
+       yy := new(fiat.P224Element).Mul(p.y, zinv)
+
+       buf := append(out[:0], 4)
+       buf = append(buf, xx.Bytes()...)
+       buf = append(buf, yy.Bytes()...)
+       return buf
+}
+
+// Add sets q = p1 + p2, and returns q. The points may overlap.
+func (q *P224Point) Add(p1, p2 *P224Point) *P224Point {
+       // Complete addition formula for a = -3 from "Complete addition formulas for
+       // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2.
+
+       t0 := new(fiat.P224Element).Mul(p1.x, p2.x) // t0 := X1 * X2
+       t1 := new(fiat.P224Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2
+       t2 := new(fiat.P224Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2
+       t3 := new(fiat.P224Element).Add(p1.x, p1.y) // t3 := X1 + Y1
+       t4 := new(fiat.P224Element).Add(p2.x, p2.y) // t4 := X2 + Y2
+       t3.Mul(t3, t4)                              // t3 := t3 * t4
+       t4.Add(t0, t1)                              // t4 := t0 + t1
+       t3.Sub(t3, t4)                              // t3 := t3 - t4
+       t4.Add(p1.y, p1.z)                          // t4 := Y1 + Z1
+       x3 := new(fiat.P224Element).Add(p2.y, p2.z) // X3 := Y2 + Z2
+       t4.Mul(t4, x3)                              // t4 := t4 * X3
+       x3.Add(t1, t2)                              // X3 := t1 + t2
+       t4.Sub(t4, x3)                              // t4 := t4 - X3
+       x3.Add(p1.x, p1.z)                          // X3 := X1 + Z1
+       y3 := new(fiat.P224Element).Add(p2.x, p2.z) // Y3 := X2 + Z2
+       x3.Mul(x3, y3)                              // X3 := X3 * Y3
+       y3.Add(t0, t2)                              // Y3 := t0 + t2
+       y3.Sub(x3, y3)                              // Y3 := X3 - Y3
+       z3 := new(fiat.P224Element).Mul(p224B, t2)  // Z3 := b * t2
+       x3.Sub(y3, z3)                              // X3 := Y3 - Z3
+       z3.Add(x3, x3)                              // Z3 := X3 + X3
+       x3.Add(x3, z3)                              // X3 := X3 + Z3
+       z3.Sub(t1, x3)                              // Z3 := t1 - X3
+       x3.Add(t1, x3)                              // X3 := t1 + X3
+       y3.Mul(p224B, y3)                           // Y3 := b * Y3
+       t1.Add(t2, t2)                              // t1 := t2 + t2
+       t2.Add(t1, t2)                              // t2 := t1 + t2
+       y3.Sub(y3, t2)                              // Y3 := Y3 - t2
+       y3.Sub(y3, t0)                              // Y3 := Y3 - t0
+       t1.Add(y3, y3)                              // t1 := Y3 + Y3
+       y3.Add(t1, y3)                              // Y3 := t1 + Y3
+       t1.Add(t0, t0)                              // t1 := t0 + t0
+       t0.Add(t1, t0)                              // t0 := t1 + t0
+       t0.Sub(t0, t2)                              // t0 := t0 - t2
+       t1.Mul(t4, y3)                              // t1 := t4 * Y3
+       t2.Mul(t0, y3)                              // t2 := t0 * Y3
+       y3.Mul(x3, z3)                              // Y3 := X3 * Z3
+       y3.Add(y3, t2)                              // Y3 := Y3 + t2
+       x3.Mul(t3, x3)                              // X3 := t3 * X3
+       x3.Sub(x3, t1)                              // X3 := X3 - t1
+       z3.Mul(t4, z3)                              // Z3 := t4 * Z3
+       t1.Mul(t3, t0)                              // t1 := t3 * t0
+       z3.Add(z3, t1)                              // Z3 := Z3 + t1
+
+       q.x.Set(x3)
+       q.y.Set(y3)
+       q.z.Set(z3)
+       return q
+}
+
+// Double sets q = p + p, and returns q. The points may overlap.
+func (q *P224Point) Double(p *P224Point) *P224Point {
+       // Complete addition formula for a = -3 from "Complete addition formulas for
+       // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2.
+
+       t0 := new(fiat.P224Element).Square(p.x)    // t0 := X ^ 2
+       t1 := new(fiat.P224Element).Square(p.y)    // t1 := Y ^ 2
+       t2 := new(fiat.P224Element).Square(p.z)    // t2 := Z ^ 2
+       t3 := new(fiat.P224Element).Mul(p.x, p.y)  // t3 := X * Y
+       t3.Add(t3, t3)                             // t3 := t3 + t3
+       z3 := new(fiat.P224Element).Mul(p.x, p.z)  // Z3 := X * Z
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+       y3 := new(fiat.P224Element).Mul(p224B, t2) // Y3 := b * t2
+       y3.Sub(y3, z3)                             // Y3 := Y3 - Z3
+       x3 := new(fiat.P224Element).Add(y3, y3)    // X3 := Y3 + Y3
+       y3.Add(x3, y3)                             // Y3 := X3 + Y3
+       x3.Sub(t1, y3)                             // X3 := t1 - Y3
+       y3.Add(t1, y3)                             // Y3 := t1 + Y3
+       y3.Mul(x3, y3)                             // Y3 := X3 * Y3
+       x3.Mul(x3, t3)                             // X3 := X3 * t3
+       t3.Add(t2, t2)                             // t3 := t2 + t2
+       t2.Add(t2, t3)                             // t2 := t2 + t3
+       z3.Mul(p224B, z3)                          // Z3 := b * Z3
+       z3.Sub(z3, t2)                             // Z3 := Z3 - t2
+       z3.Sub(z3, t0)                             // Z3 := Z3 - t0
+       t3.Add(z3, z3)                             // t3 := Z3 + Z3
+       z3.Add(z3, t3)                             // Z3 := Z3 + t3
+       t3.Add(t0, t0)                             // t3 := t0 + t0
+       t0.Add(t3, t0)                             // t0 := t3 + t0
+       t0.Sub(t0, t2)                             // t0 := t0 - t2
+       t0.Mul(t0, z3)                             // t0 := t0 * Z3
+       y3.Add(y3, t0)                             // Y3 := Y3 + t0
+       t0.Mul(p.y, p.z)                           // t0 := Y * Z
+       t0.Add(t0, t0)                             // t0 := t0 + t0
+       z3.Mul(t0, z3)                             // Z3 := t0 * Z3
+       x3.Sub(x3, z3)                             // X3 := X3 - Z3
+       z3.Mul(t0, t1)                             // Z3 := t0 * t1
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+
+       q.x.Set(x3)
+       q.y.Set(y3)
+       q.z.Set(z3)
+       return q
+}
+
+// Select sets q to p1 if cond == 1, and to p2 if cond == 0.
+func (q *P224Point) Select(p1, p2 *P224Point, cond int) *P224Point {
+       q.x.Select(p1.x, p2.x, cond)
+       q.y.Select(p1.y, p2.y, cond)
+       q.z.Select(p1.z, p2.z, cond)
+       return q
+}
+
+// ScalarMult sets p = scalar * q, and returns p.
+func (p *P224Point) ScalarMult(q *P224Point, scalar []byte) *P224Point {
+       // table holds the first 16 multiples of q. The explicit newP224Point calls
+       // get inlined, letting the allocations live on the stack.
+       var table = [16]*P224Point{
+               NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
+               NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
+               NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
+               NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
+       }
+       for i := 1; i < 16; i++ {
+               table[i].Add(table[i-1], q)
+       }
+
+       // Instead of doing the classic double-and-add chain, we do it with a
+       // four-bit window: we double four times, and then add [0-15]P.
+       t := NewP224Point()
+       p.Set(NewP224Point())
+       for _, byte := range scalar {
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+
+               for i := uint8(0); i < 16; i++ {
+                       cond := subtle.ConstantTimeByteEq(byte>>4, i)
+                       t.Select(table[i], t, cond)
+               }
+               p.Add(p, t)
+
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+
+               for i := uint8(0); i < 16; i++ {
+                       cond := subtle.ConstantTimeByteEq(byte&0b1111, i)
+                       t.Select(table[i], t, cond)
+               }
+               p.Add(p, t)
+       }
+
+       return p
+}
diff --git a/src/crypto/elliptic/internal/nistec/p384.go b/src/crypto/elliptic/internal/nistec/p384.go
new file mode 100644 (file)
index 0000000..24a166d
--- /dev/null
@@ -0,0 +1,298 @@
+// Copyright 2021 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.
+
+package nistec
+
+import (
+       "crypto/elliptic/internal/fiat"
+       "crypto/subtle"
+       "errors"
+)
+
+var p384B, _ = new(fiat.P384Element).SetBytes([]byte{
+       0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b,
+       0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12,
+       0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d,
+       0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef})
+
+var p384G, _ = NewP384Point().SetBytes([]byte{0x4,
+       0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e,
+       0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98,
+       0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d,
+       0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7,
+       0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
+       0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
+       0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
+       0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f})
+
+const p384ElementLength = 48
+
+// P384Point is a P-384 point. The zero value is NOT valid.
+type P384Point struct {
+       // The point is represented in projective coordinates (X:Y:Z),
+       // where x = X/Z and y = Y/Z.
+       x, y, z *fiat.P384Element
+}
+
+// NewP384Point returns a new P384Point representing the point at infinity point.
+func NewP384Point() *P384Point {
+       return &P384Point{
+               x: new(fiat.P384Element),
+               y: new(fiat.P384Element).One(),
+               z: new(fiat.P384Element),
+       }
+}
+
+// NewP384Generator returns a new P384Point set to the canonical generator.
+func NewP384Generator() *P384Point {
+       return (&P384Point{
+               x: new(fiat.P384Element),
+               y: new(fiat.P384Element),
+               z: new(fiat.P384Element),
+       }).Set(p384G)
+}
+
+// Set sets p = q and returns p.
+func (p *P384Point) Set(q *P384Point) *P384Point {
+       p.x.Set(q.x)
+       p.y.Set(q.y)
+       p.z.Set(q.z)
+       return p
+}
+
+// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in
+// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on
+// the curve, it returns nil and an error, and the receiver is unchanged.
+// Otherwise, it returns p.
+func (p *P384Point) SetBytes(b []byte) (*P384Point, error) {
+       switch {
+       // Point at infinity.
+       case len(b) == 1 && b[0] == 0:
+               return p.Set(NewP384Point()), nil
+
+       // Uncompressed form.
+       case len(b) == 1+2*p384ElementLength && b[0] == 4:
+               x, err := new(fiat.P384Element).SetBytes(b[1 : 1+p384ElementLength])
+               if err != nil {
+                       return nil, err
+               }
+               y, err := new(fiat.P384Element).SetBytes(b[1+p384ElementLength:])
+               if err != nil {
+                       return nil, err
+               }
+               if err := p384CheckOnCurve(x, y); err != nil {
+                       return nil, err
+               }
+               p.x.Set(x)
+               p.y.Set(y)
+               p.z.One()
+               return p, nil
+
+       // Compressed form
+       case len(b) == 1+p384ElementLength && b[0] == 0:
+               return nil, errors.New("unimplemented") // TODO(filippo)
+
+       default:
+               return nil, errors.New("invalid P384 point encoding")
+       }
+}
+
+func p384CheckOnCurve(x, y *fiat.P384Element) error {
+       // x³ - 3x + b.
+       x3 := new(fiat.P384Element).Square(x)
+       x3.Mul(x3, x)
+
+       threeX := new(fiat.P384Element).Add(x, x)
+       threeX.Add(threeX, x)
+
+       x3.Sub(x3, threeX)
+       x3.Add(x3, p384B)
+
+       // y² = x³ - 3x + b
+       y2 := new(fiat.P384Element).Square(y)
+
+       if x3.Equal(y2) != 1 {
+               return errors.New("P384 point not on curve")
+       }
+       return nil
+}
+
+// Bytes returns the uncompressed or infinity encoding of p, as specified in
+// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at
+// infinity is shorter than all other encodings.
+func (p *P384Point) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [133]byte
+       return p.bytes(&out)
+}
+
+func (p *P384Point) bytes(out *[133]byte) []byte {
+       if p.z.IsZero() == 1 {
+               return append(out[:0], 0)
+       }
+
+       zinv := new(fiat.P384Element).Invert(p.z)
+       xx := new(fiat.P384Element).Mul(p.x, zinv)
+       yy := new(fiat.P384Element).Mul(p.y, zinv)
+
+       buf := append(out[:0], 4)
+       buf = append(buf, xx.Bytes()...)
+       buf = append(buf, yy.Bytes()...)
+       return buf
+}
+
+// Add sets q = p1 + p2, and returns q. The points may overlap.
+func (q *P384Point) Add(p1, p2 *P384Point) *P384Point {
+       // Complete addition formula for a = -3 from "Complete addition formulas for
+       // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2.
+
+       t0 := new(fiat.P384Element).Mul(p1.x, p2.x) // t0 := X1 * X2
+       t1 := new(fiat.P384Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2
+       t2 := new(fiat.P384Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2
+       t3 := new(fiat.P384Element).Add(p1.x, p1.y) // t3 := X1 + Y1
+       t4 := new(fiat.P384Element).Add(p2.x, p2.y) // t4 := X2 + Y2
+       t3.Mul(t3, t4)                              // t3 := t3 * t4
+       t4.Add(t0, t1)                              // t4 := t0 + t1
+       t3.Sub(t3, t4)                              // t3 := t3 - t4
+       t4.Add(p1.y, p1.z)                          // t4 := Y1 + Z1
+       x3 := new(fiat.P384Element).Add(p2.y, p2.z) // X3 := Y2 + Z2
+       t4.Mul(t4, x3)                              // t4 := t4 * X3
+       x3.Add(t1, t2)                              // X3 := t1 + t2
+       t4.Sub(t4, x3)                              // t4 := t4 - X3
+       x3.Add(p1.x, p1.z)                          // X3 := X1 + Z1
+       y3 := new(fiat.P384Element).Add(p2.x, p2.z) // Y3 := X2 + Z2
+       x3.Mul(x3, y3)                              // X3 := X3 * Y3
+       y3.Add(t0, t2)                              // Y3 := t0 + t2
+       y3.Sub(x3, y3)                              // Y3 := X3 - Y3
+       z3 := new(fiat.P384Element).Mul(p384B, t2)  // Z3 := b * t2
+       x3.Sub(y3, z3)                              // X3 := Y3 - Z3
+       z3.Add(x3, x3)                              // Z3 := X3 + X3
+       x3.Add(x3, z3)                              // X3 := X3 + Z3
+       z3.Sub(t1, x3)                              // Z3 := t1 - X3
+       x3.Add(t1, x3)                              // X3 := t1 + X3
+       y3.Mul(p384B, y3)                           // Y3 := b * Y3
+       t1.Add(t2, t2)                              // t1 := t2 + t2
+       t2.Add(t1, t2)                              // t2 := t1 + t2
+       y3.Sub(y3, t2)                              // Y3 := Y3 - t2
+       y3.Sub(y3, t0)                              // Y3 := Y3 - t0
+       t1.Add(y3, y3)                              // t1 := Y3 + Y3
+       y3.Add(t1, y3)                              // Y3 := t1 + Y3
+       t1.Add(t0, t0)                              // t1 := t0 + t0
+       t0.Add(t1, t0)                              // t0 := t1 + t0
+       t0.Sub(t0, t2)                              // t0 := t0 - t2
+       t1.Mul(t4, y3)                              // t1 := t4 * Y3
+       t2.Mul(t0, y3)                              // t2 := t0 * Y3
+       y3.Mul(x3, z3)                              // Y3 := X3 * Z3
+       y3.Add(y3, t2)                              // Y3 := Y3 + t2
+       x3.Mul(t3, x3)                              // X3 := t3 * X3
+       x3.Sub(x3, t1)                              // X3 := X3 - t1
+       z3.Mul(t4, z3)                              // Z3 := t4 * Z3
+       t1.Mul(t3, t0)                              // t1 := t3 * t0
+       z3.Add(z3, t1)                              // Z3 := Z3 + t1
+
+       q.x.Set(x3)
+       q.y.Set(y3)
+       q.z.Set(z3)
+       return q
+}
+
+// Double sets q = p + p, and returns q. The points may overlap.
+func (q *P384Point) Double(p *P384Point) *P384Point {
+       // Complete addition formula for a = -3 from "Complete addition formulas for
+       // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2.
+
+       t0 := new(fiat.P384Element).Square(p.x)    // t0 := X ^ 2
+       t1 := new(fiat.P384Element).Square(p.y)    // t1 := Y ^ 2
+       t2 := new(fiat.P384Element).Square(p.z)    // t2 := Z ^ 2
+       t3 := new(fiat.P384Element).Mul(p.x, p.y)  // t3 := X * Y
+       t3.Add(t3, t3)                             // t3 := t3 + t3
+       z3 := new(fiat.P384Element).Mul(p.x, p.z)  // Z3 := X * Z
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+       y3 := new(fiat.P384Element).Mul(p384B, t2) // Y3 := b * t2
+       y3.Sub(y3, z3)                             // Y3 := Y3 - Z3
+       x3 := new(fiat.P384Element).Add(y3, y3)    // X3 := Y3 + Y3
+       y3.Add(x3, y3)                             // Y3 := X3 + Y3
+       x3.Sub(t1, y3)                             // X3 := t1 - Y3
+       y3.Add(t1, y3)                             // Y3 := t1 + Y3
+       y3.Mul(x3, y3)                             // Y3 := X3 * Y3
+       x3.Mul(x3, t3)                             // X3 := X3 * t3
+       t3.Add(t2, t2)                             // t3 := t2 + t2
+       t2.Add(t2, t3)                             // t2 := t2 + t3
+       z3.Mul(p384B, z3)                          // Z3 := b * Z3
+       z3.Sub(z3, t2)                             // Z3 := Z3 - t2
+       z3.Sub(z3, t0)                             // Z3 := Z3 - t0
+       t3.Add(z3, z3)                             // t3 := Z3 + Z3
+       z3.Add(z3, t3)                             // Z3 := Z3 + t3
+       t3.Add(t0, t0)                             // t3 := t0 + t0
+       t0.Add(t3, t0)                             // t0 := t3 + t0
+       t0.Sub(t0, t2)                             // t0 := t0 - t2
+       t0.Mul(t0, z3)                             // t0 := t0 * Z3
+       y3.Add(y3, t0)                             // Y3 := Y3 + t0
+       t0.Mul(p.y, p.z)                           // t0 := Y * Z
+       t0.Add(t0, t0)                             // t0 := t0 + t0
+       z3.Mul(t0, z3)                             // Z3 := t0 * Z3
+       x3.Sub(x3, z3)                             // X3 := X3 - Z3
+       z3.Mul(t0, t1)                             // Z3 := t0 * t1
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+
+       q.x.Set(x3)
+       q.y.Set(y3)
+       q.z.Set(z3)
+       return q
+}
+
+// Select sets q to p1 if cond == 1, and to p2 if cond == 0.
+func (q *P384Point) Select(p1, p2 *P384Point, cond int) *P384Point {
+       q.x.Select(p1.x, p2.x, cond)
+       q.y.Select(p1.y, p2.y, cond)
+       q.z.Select(p1.z, p2.z, cond)
+       return q
+}
+
+// ScalarMult sets p = scalar * q, and returns p.
+func (p *P384Point) ScalarMult(q *P384Point, scalar []byte) *P384Point {
+       // table holds the first 16 multiples of q. The explicit newP384Point calls
+       // get inlined, letting the allocations live on the stack.
+       var table = [16]*P384Point{
+               NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
+               NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
+               NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
+               NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
+       }
+       for i := 1; i < 16; i++ {
+               table[i].Add(table[i-1], q)
+       }
+
+       // Instead of doing the classic double-and-add chain, we do it with a
+       // four-bit window: we double four times, and then add [0-15]P.
+       t := NewP384Point()
+       p.Set(NewP384Point())
+       for _, byte := range scalar {
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+
+               for i := uint8(0); i < 16; i++ {
+                       cond := subtle.ConstantTimeByteEq(byte>>4, i)
+                       t.Select(table[i], t, cond)
+               }
+               p.Add(p, t)
+
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+
+               for i := uint8(0); i < 16; i++ {
+                       cond := subtle.ConstantTimeByteEq(byte&0b1111, i)
+                       t.Select(table[i], t, cond)
+               }
+               p.Add(p, t)
+       }
+
+       return p
+}
index e5b4e46d4b6ae39e5cd1a2e3c911460353534581..cdbd195cf436a4bcd660e1f3c36845a839d0781f 100644 (file)
@@ -58,7 +58,11 @@ func NewP521Point() *P521Point {
 
 // NewP521Generator returns a new P521Point set to the canonical generator.
 func NewP521Generator() *P521Point {
-       return NewP521Point().Set(p521G)
+       return (&P521Point{
+               x: new(fiat.P521Element),
+               y: new(fiat.P521Element),
+               z: new(fiat.P521Element),
+       }).Set(p521G)
 }
 
 // Set sets p = q and returns p.
diff --git a/src/crypto/elliptic/internal/nistec/p521_test.go b/src/crypto/elliptic/internal/nistec/p521_test.go
deleted file mode 100644 (file)
index e62c1cb..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2021 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.
-
-package nistec_test
-
-import (
-       "crypto/elliptic/internal/nistec"
-       "math/rand"
-       "os"
-       "strings"
-       "testing"
-)
-
-func TestP521Allocations(t *testing.T) {
-       if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") {
-               t.Skip("skipping allocations test without relevant optimizations")
-       }
-       if allocs := testing.AllocsPerRun(100, func() {
-               p := nistec.NewP521Generator()
-               scalar := make([]byte, 66)
-               rand.Read(scalar)
-               p.ScalarMult(p, scalar)
-               out := p.Bytes()
-               if _, err := p.SetBytes(out); err != nil {
-                       t.Fatal(err)
-               }
-       }); allocs > 0 {
-               t.Errorf("expected zero allocations, got %0.1f", allocs)
-       }
-}
-
-func BenchmarkScalarMult(b *testing.B) {
-       b.Run("P521", func(b *testing.B) {
-               scalar := make([]byte, 66)
-               rand.Read(scalar)
-               p := nistec.NewP521Generator()
-               b.ReportAllocs()
-               b.ResetTimer()
-               for i := 0; i < b.N; i++ {
-                       p.ScalarMult(p, scalar)
-               }
-       })
-}
index 34079d14b12496c7ba375e7a1452ff0b67d1816e..a8533b85ff4c35f471374eed02752e6c22776f4e 100644 (file)
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2013 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.
 
 package elliptic
 
-// This is a constant-time, 32-bit implementation of P224. See FIPS 186-3,
-// section D.2.2.
-//
-// See https://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
-
 import (
-       "encoding/binary"
+       "crypto/elliptic/internal/nistec"
+       "crypto/rand"
        "math/big"
-       "math/bits"
 )
 
-var p224 p224Curve
-
-type p224Curve struct {
-       *CurveParams
-       gx, gy, b p224FieldElement
-}
-
-func initP224() {
-       // See FIPS 186-3, section D.2.2
-       p224.CurveParams = &CurveParams{Name: "P-224"}
-       p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10)
-       p224.N, _ = new(big.Int).SetString("26959946667150639794667015087019625940457807714424391721682722368061", 10)
-       p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16)
-       p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16)
-       p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16)
-       p224.BitSize = 224
-
-       p224FromBig(&p224.gx, p224.Gx)
-       p224FromBig(&p224.gy, p224.Gy)
-       p224FromBig(&p224.b, p224.B)
-}
-
-// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2).
-//
-// The cryptographic operations are implemented using constant-time algorithms.
-func P224() Curve {
-       initonce.Do(initAll)
-       return p224
-}
-
-func (curve p224Curve) Params() *CurveParams {
-       return curve.CurveParams
-}
-
-func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool {
-       if bigX.BitLen() > 224 || bigY.BitLen() > 224 {
-               return false
-       }
-
-       var x, y p224FieldElement
-       p224FromBig(&x, bigX)
-       p224FromBig(&y, bigY)
-
-       // y² = x³ - 3x + b
-       var tmp p224LargeFieldElement
-       var x3 p224FieldElement
-       p224Square(&x3, &x, &tmp)
-       p224Mul(&x3, &x3, &x, &tmp)
-
-       for i := 0; i < 8; i++ {
-               x[i] *= 3
-       }
-       p224Sub(&x3, &x3, &x)
-       p224Reduce(&x3)
-       p224Add(&x3, &x3, &curve.b)
-       p224Contract(&x3, &x3)
-
-       p224Square(&y, &y, &tmp)
-       p224Contract(&y, &y)
-
-       for i := 0; i < 8; i++ {
-               if y[i] != x3[i] {
-                       return false
-               }
-       }
-       return true
-}
-
-func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) {
-       var x1, y1, z1, x2, y2, z2, x3, y3, z3 p224FieldElement
-
-       p224FromBig(&x1, bigX1)
-       p224FromBig(&y1, bigY1)
-       if bigX1.Sign() != 0 || bigY1.Sign() != 0 {
-               z1[0] = 1
-       }
-       p224FromBig(&x2, bigX2)
-       p224FromBig(&y2, bigY2)
-       if bigX2.Sign() != 0 || bigY2.Sign() != 0 {
-               z2[0] = 1
-       }
-
-       p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2)
-       return p224ToAffine(&x3, &y3, &z3)
-}
-
-func (p224Curve) Double(bigX1, bigY1 *big.Int) (x, y *big.Int) {
-       var x1, y1, z1, x2, y2, z2 p224FieldElement
-
-       p224FromBig(&x1, bigX1)
-       p224FromBig(&y1, bigY1)
-       z1[0] = 1
-
-       p224DoubleJacobian(&x2, &y2, &z2, &x1, &y1, &z1)
-       return p224ToAffine(&x2, &y2, &z2)
-}
-
-func (p224Curve) ScalarMult(bigX1, bigY1 *big.Int, scalar []byte) (x, y *big.Int) {
-       var x1, y1, z1, x2, y2, z2 p224FieldElement
-
-       p224FromBig(&x1, bigX1)
-       p224FromBig(&y1, bigY1)
-       z1[0] = 1
-
-       p224ScalarMult(&x2, &y2, &z2, &x1, &y1, &z1, scalar)
-       return p224ToAffine(&x2, &y2, &z2)
-}
-
-func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
-       var z1, x2, y2, z2 p224FieldElement
-
-       z1[0] = 1
-       p224ScalarMult(&x2, &y2, &z2, &curve.gx, &curve.gy, &z1, scalar)
-       return p224ToAffine(&x2, &y2, &z2)
-}
-
-// Field element functions.
-//
-// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1.
-//
-// Field elements are represented by a FieldElement, which is a typedef to an
-// array of 8 uint32's. The value of a FieldElement, a, is:
-//   a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7]
-//
-// Using 28-bit limbs means that there's only 4 bits of headroom, which is less
-// than we would really like. But it has the useful feature that we hit 2**224
-// exactly, making the reflections during a reduce much nicer.
-type p224FieldElement [8]uint32
-
-// p224P is the order of the field, represented as a p224FieldElement.
-var p224P = p224FieldElement{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
-
-// p224IsZero returns 1 if a == 0 mod p and 0 otherwise.
+// p224Curve is a Curve implementation based on nistec.P224Point.
 //
-// a[i] < 2**29
-func p224IsZero(a *p224FieldElement) uint32 {
-       var minimal p224FieldElement
-       p224Contract(&minimal, a)
-
-       var acc uint32
-       for _, v := range minimal {
-               acc |= v
-       }
-       mask := ^maskIsNotZero(acc)
-
-       return 1 & mask
-}
-
-// p224Add computes *out = a+b
+// It's a wrapper that exposes the big.Int-based Curve interface and encodes the
+// legacy idiosyncrasies it requires, such as invalid and infinity point
+// handling.
 //
-// a[i] + b[i] < 2**32
-func p224Add(out, a, b *p224FieldElement) {
-       for i := 0; i < 8; i++ {
-               out[i] = a[i] + b[i]
-       }
-}
-
-const two31p3 = 1<<31 + 1<<3
-const two31m3 = 1<<31 - 1<<3
-const two31m15m3 = 1<<31 - 1<<15 - 1<<3
-
-// p224ZeroModP31 is 0 mod p where bit 31 is set in all limbs so that we can
-// subtract smaller amounts without underflow. See the section "Subtraction" in
-// [1] for reasoning.
-//
-// To calculate this value, start by adding 2³¹ to the lowest limb and
-// subtracting 2³ from the next one to compensate. Repeat for each next limb,
-// ending up with 2³¹ - 2³ in each of them, and a carry of -2³. Apply the
-// reduction identity, and we need to subtract 2³ * 2⁹⁶ - 2³ = 2¹⁵ * 2⁸⁴ - 2³ so
-// we subtract 2¹⁵ from the 4th limb and add 2³ to the first limb.
-var p224ZeroModP31 = []uint32{two31p3, two31m3, two31m3, two31m15m3, two31m3, two31m3, two31m3, two31m3}
-
-// p224Sub computes *out = a-b
-//
-// a[i], b[i] < 2**30
-// out[i] < 2**32
-func p224Sub(out, a, b *p224FieldElement) {
-       for i := 0; i < 8; i++ {
-               out[i] = a[i] + p224ZeroModP31[i] - b[i]
-       }
-}
-
-// LargeFieldElement also represents an element of the field. The limbs are
-// still spaced 28-bits apart and in little-endian order. So the limbs are at
-// 0, 28, 56, ..., 392 bits, each 64-bits wide.
-type p224LargeFieldElement [15]uint64
-
-const two63p35 = 1<<63 + 1<<35
-const two63m35 = 1<<63 - 1<<35
-const two63m35m19 = 1<<63 - 1<<35 - 1<<19
-
-// p224ZeroModP63 is 0 mod p where bit 63 is set in all limbs. See the section
-// "Subtraction" in [1] for why.
-var p224ZeroModP63 = [8]uint64{two63p35, two63m35, two63m35, two63m35, two63m35m19, two63m35, two63m35, two63m35}
-
-const bottom12Bits = 0xfff
-const bottom28Bits = 0xfffffff
-
-// p224Mul computes *out = a*b
-//
-// a[i] < 2**29, b[i] < 2**30 (or vice versa)
-// out[i] < 2**29
-func p224Mul(out, a, b *p224FieldElement, tmp *p224LargeFieldElement) {
-       for i := range tmp {
-               tmp[i] = 0
-       }
-
-       for i := 0; i < 8; i++ {
-               for j := 0; j < 8; j++ {
-                       tmp[i+j] += uint64(a[i]) * uint64(b[j])
-               }
-       }
-
-       p224ReduceLarge(out, tmp)
-}
-
-// Square computes *out = a*a
-//
-// a[i] < 2**29
-// out[i] < 2**29
-func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) {
-       for i := range tmp {
-               tmp[i] = 0
-       }
-
-       for i := 0; i < 8; i++ {
-               for j := 0; j <= i; j++ {
-                       r := uint64(a[i]) * uint64(a[j])
-                       if i == j {
-                               tmp[i+j] += r
-                       } else {
-                               tmp[i+j] += r * 2
-                       }
-               }
-       }
-
-       p224ReduceLarge(out, tmp)
+// To interact with the nistec package, points are encoded into and decoded from
+// properly formatted byte slices. All big.Int use is limited to this package.
+// Encoding and decoding is 1/1000th of the runtime of a scalar multiplication,
+// so the overhead is acceptable.
+type p224Curve struct {
+       params *CurveParams
 }
 
-// ReduceLarge converts a p224LargeFieldElement to a p224FieldElement.
-//
-// in[i] < 2**62
-// out[i] < 2**29
-func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) {
-       for i := 0; i < 8; i++ {
-               in[i] += p224ZeroModP63[i]
-       }
-
-       // Eliminate the coefficients at 2**224 and greater by applying the
-       // reduction identity.
-       //
-       //   a + top * 2²²⁴ = a + top * 2⁹⁶ - top
-       //
-       // Since top here is in[8..14], both the subtraction at offset 0 and the
-       // addition at offset 96 (3 * 28 + 16) span multiple limbs. The subtraction
-       // can't underflow because of the p224ZeroModP63 addition above, while the
-       // addition can't overflow because of the 62 bit input bounds.
-       for i := 14; i >= 8; i-- {
-               in[i-8] -= in[i]
-               in[i-5] += (in[i] & 0xffff) << 12
-               in[i-4] += in[i] >> 16
-       }
-       in[8] = 0
-       // in[0..7] < 2**64
-       // in[9..14] discarded
-
-       // Run a carry chain and light reduction. Keep [0] large so we can do the
-       // subtraction safely. As the values become small enough, we start to store
-       // them in out and use 32-bit operations.
-       for i := 1; i < 8; i++ {
-               in[i+1] += in[i] >> 28
-               out[i] = uint32(in[i] & bottom28Bits)
-       }
-       in[0] -= in[8]
-       out[3] += uint32(in[8]&0xffff) << 12
-       out[4] += uint32(in[8] >> 16)
-       // in[0] < 2**64
-       // out[3] < 2**29
-       // out[4] < 2**29
-       // out[1,2,5..7] < 2**28
-
-       // Carry the overflow of [0] into the short 28 bit limbs.
-       out[0] = uint32(in[0] & bottom28Bits)
-       out[1] += uint32((in[0] >> 28) & bottom28Bits)
-       out[2] += uint32(in[0] >> 56)
-       // out[0] < 2**28
-       // out[1..4] < 2**29
-       // out[5..7] < 2**28
-}
+var p224 p224Curve
+var _ Curve = p224
 
-// Reduce reduces the coefficients of a to smaller bounds.
-//
-// On entry: a[i] < 2**31 + 2**30
-// On exit: a[i] < 2**29
-func p224Reduce(a *p224FieldElement) {
-       for i := 0; i < 7; i++ {
-               a[i+1] += a[i] >> 28
-               a[i] &= bottom28Bits
+func initP224() {
+       p224.params = &CurveParams{
+               Name:    "P-224",
+               BitSize: 224,
+               // FIPS 186-4, section D.1.2.2
+               P:  bigFromDecimal("26959946667150639794667015087019630673557916260026308143510066298881"),
+               N:  bigFromDecimal("26959946667150639794667015087019625940457807714424391721682722368061"),
+               B:  bigFromHex("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"),
+               Gx: bigFromHex("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"),
+               Gy: bigFromHex("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"),
        }
-       top := a[7] >> 28
-       a[7] &= bottom28Bits
-
-       a[0] -= top
-       a[3] += top << 12
-
-       // We may have just made a[0] negative but if we did top must have been not
-       // zero, so a[3] is not zero, so we can carry down to a[0]. (Note that we
-       // don't actually check if a[0] went negative, like in p224Contract, nor we
-       // try to stop the carry at a[1] or a[2], because here we can afford to go
-       // above 28 bits, so instead we carry all the way down from a[3].)
-       mask := maskIsNotZero(top)
-       a[3] -= 1 & mask
-       a[2] += mask & (1<<28 - 1)
-       a[1] += mask & (1<<28 - 1)
-       a[0] += mask & (1 << 28)
 }
 
-// p224Invert calculates *out = in**-1 by using Fermat's little theorem and
-// computing in**(p-2) = in**(2**224 - 2**96 - 1).
-func p224Invert(out, in *p224FieldElement) {
-       var f1, f2, f3, f4 p224FieldElement
-       var c p224LargeFieldElement
-
-       p224Square(&f1, in, &c)    // 2
-       p224Mul(&f1, &f1, in, &c)  // 2**2 - 1
-       p224Square(&f1, &f1, &c)   // 2**3 - 2
-       p224Mul(&f1, &f1, in, &c)  // 2**3 - 1
-       p224Square(&f2, &f1, &c)   // 2**4 - 2
-       p224Square(&f2, &f2, &c)   // 2**5 - 4
-       p224Square(&f2, &f2, &c)   // 2**6 - 8
-       p224Mul(&f1, &f1, &f2, &c) // 2**6 - 1
-       p224Square(&f2, &f1, &c)   // 2**7 - 2
-       for i := 0; i < 5; i++ {   // 2**12 - 2**6
-               p224Square(&f2, &f2, &c)
-       }
-       p224Mul(&f2, &f2, &f1, &c) // 2**12 - 1
-       p224Square(&f3, &f2, &c)   // 2**13 - 2
-       for i := 0; i < 11; i++ {  // 2**24 - 2**12
-               p224Square(&f3, &f3, &c)
-       }
-       p224Mul(&f2, &f3, &f2, &c) // 2**24 - 1
-       p224Square(&f3, &f2, &c)   // 2**25 - 2
-       for i := 0; i < 23; i++ {  // 2**48 - 2**24
-               p224Square(&f3, &f3, &c)
-       }
-       p224Mul(&f3, &f3, &f2, &c) // 2**48 - 1
-       p224Square(&f4, &f3, &c)   // 2**49 - 2
-       for i := 0; i < 47; i++ {  // 2**96 - 2**48
-               p224Square(&f4, &f4, &c)
-       }
-       p224Mul(&f3, &f3, &f4, &c) // 2**96 - 1
-       p224Square(&f4, &f3, &c)   // 2**97 - 2
-       for i := 0; i < 23; i++ {  // 2**120 - 2**24
-               p224Square(&f4, &f4, &c)
-       }
-       p224Mul(&f2, &f4, &f2, &c) // 2**120 - 1
-       for i := 0; i < 6; i++ {   // 2**126 - 2**6
-               p224Square(&f2, &f2, &c)
-       }
-       p224Mul(&f1, &f1, &f2, &c) // 2**126 - 1
-       p224Square(&f1, &f1, &c)   // 2**127 - 2
-       p224Mul(&f1, &f1, in, &c)  // 2**127 - 1
-       for i := 0; i < 97; i++ {  // 2**224 - 2**97
-               p224Square(&f1, &f1, &c)
-       }
-       p224Mul(out, &f1, &f3, &c) // 2**224 - 2**96 - 1
+func (curve p224Curve) Params() *CurveParams {
+       return curve.params
 }
 
-// p224Contract converts a FieldElement to its unique, minimal form.
-//
-// On entry, in[i] < 2**29
-// On exit, out[i] < 2**28 and out < p
-func p224Contract(out, in *p224FieldElement) {
-       copy(out[:], in[:])
-
-       // First, carry the bits above 28 to the higher limb.
-       for i := 0; i < 7; i++ {
-               out[i+1] += out[i] >> 28
-               out[i] &= bottom28Bits
-       }
-       top := out[7] >> 28
-       out[7] &= bottom28Bits
-
-       // Use the reduction identity to carry the overflow.
-       //
-       //   a + top * 2²²⁴ = a + top * 2⁹⁶ - top
-       out[0] -= top
-       out[3] += top << 12
-
-       // We may just have made out[0] negative. So we carry down. If we made
-       // out[0] negative then we know that out[3] is sufficiently positive
-       // because we just added to it.
-       for i := 0; i < 3; i++ {
-               mask := maskIsNegative(out[i])
-               out[i] += (1 << 28) & mask
-               out[i+1] -= 1 & mask
-       }
-
-       // We might have pushed out[3] over 2**28 so we perform another, partial,
-       // carry chain; carry the overflow according to the reduction identity; and
-       // carry down in case we made out[0] negative.
-       for i := 3; i < 7; i++ {
-               out[i+1] += out[i] >> 28
-               out[i] &= bottom28Bits
-       }
-       top = out[7] >> 28
-       out[7] &= bottom28Bits
-
-       out[0] -= top
-       out[3] += top << 12
-
-       for i := 0; i < 3; i++ {
-               mask := maskIsNegative(out[i])
-               out[i] += (1 << 28) & mask
-               out[i+1] -= 1 & mask
-       }
-
-       // There are two cases to consider for out[3]:
-       //   1) The first time that we eliminated top, we didn't push out[3] over
-       //      2**28. In this case, the partial carry chain didn't change any values
-       //      and top is now zero.
-       //   2) We did push out[3] over 2**28 the first time that we eliminated top.
-       //      The first value of top was in [0..2], therefore, after overflowing
-       //      and being reduced by the second carry chain, out[3] <= 2<<12 - 1.
-       // In both cases, out[3] cannot have overflowed when we eliminated top for
-       // the second time.
-
-       // Now we need to subtract p if the value is >= p. To check, we subtract p
-       // with a borrow chain and look at the final borrow bit.
-       var b uint32
-       for i := 0; i < len(out); i++ {
-               _, b = bits.Sub32(out[i], p224P[i], b)
-       }
-       mask := ^maskIsNotZero(b)
-
-       out[0] -= 1 & mask
-       out[3] -= 0xffff000 & mask
-       out[4] -= 0xfffffff & mask
-       out[5] -= 0xfffffff & mask
-       out[6] -= 0xfffffff & mask
-       out[7] -= 0xfffffff & mask
-
-       // Do one final carry down, in case we made out[0] negative. One of
-       // out[0..3] needs to be positive and able to absorb the -1 or the value
-       // would have been < p, and the subtraction wouldn't have happened.
-       for i := 0; i < 3; i++ {
-               mask := maskIsNegative(out[i])
-               out[i] += (1 << 28) & mask
-               out[i+1] -= 1 & mask
+func (curve p224Curve) IsOnCurve(x, y *big.Int) bool {
+       // IsOnCurve is documented to reject (0, 0), the conventional point at
+       // infinity, which however is accepted by p224PointFromAffine.
+       if x.Sign() == 0 && y.Sign() == 0 {
+               return false
        }
+       _, ok := p224PointFromAffine(x, y)
+       return ok
 }
 
-// maskIsNegative returns 0xffffffff if the most significant bit of v is set,
-// and 0 otherwise.
-func maskIsNegative(v uint32) uint32 { return uint32(int32(v) >> 31) }
-
-// maskIfNegative returns 0xffffffff if v is not zero, and 0 otherwise.
-func maskIsNotZero(v uint32) uint32 {
-       v |= v >> 16
-       v |= v >> 8
-       v |= v >> 4
-       v |= v >> 2
-       v |= v >> 1
-       return uint32(int32(v<<31) >> 31)
-}
-
-// Group element functions.
-//
-// These functions deal with group elements. The group is an elliptic curve
-// group with a = -3 defined in FIPS 186-3, section D.2.2.
-
-// p224AddJacobian computes *out = a+b where a != b.
-func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
-       // 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
-
-       z1IsZero := p224IsZero(z1)
-       z2IsZero := p224IsZero(z2)
-
-       // Z1Z1 = Z1²
-       p224Square(&z1z1, z1, &c)
-       // Z2Z2 = Z2²
-       p224Square(&z2z2, z2, &c)
-       // U1 = X1*Z2Z2
-       p224Mul(&u1, x1, &z2z2, &c)
-       // U2 = X2*Z1Z1
-       p224Mul(&u2, x2, &z1z1, &c)
-       // S1 = Y1*Z2*Z2Z2
-       p224Mul(&s1, z2, &z2z2, &c)
-       p224Mul(&s1, y1, &s1, &c)
-       // S2 = Y2*Z1*Z1Z1
-       p224Mul(&s2, z1, &z1z1, &c)
-       p224Mul(&s2, y2, &s2, &c)
-       // H = U2-U1
-       p224Sub(&h, &u2, &u1)
-       p224Reduce(&h)
-       xEqual := p224IsZero(&h)
-       // I = (2*H)²
-       for j := 0; j < 8; j++ {
-               i[j] = h[j] << 1
-       }
-       p224Reduce(&i)
-       p224Square(&i, &i, &c)
-       // J = H*I
-       p224Mul(&j, &h, &i, &c)
-       // r = 2*(S2-S1)
-       p224Sub(&r, &s2, &s1)
-       p224Reduce(&r)
-       yEqual := p224IsZero(&r)
-       if xEqual == 1 && yEqual == 1 && z1IsZero == 0 && z2IsZero == 0 {
-               p224DoubleJacobian(x3, y3, z3, x1, y1, z1)
-               return
-       }
-       for i := 0; i < 8; i++ {
-               r[i] <<= 1
+func p224PointFromAffine(x, y *big.Int) (p *nistec.P224Point, ok bool) {
+       // (0, 0) is by convention the point at infinity, which can't be represented
+       // in affine coordinates. Marshal incorrectly encodes it as an uncompressed
+       // point, which SetBytes would correctly reject. See Issue 37294.
+       if x.Sign() == 0 && y.Sign() == 0 {
+               return nistec.NewP224Point(), true
        }
-       p224Reduce(&r)
-       // V = U1*I
-       p224Mul(&v, &u1, &i, &c)
-       // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H
-       p224Add(&z1z1, &z1z1, &z2z2)
-       p224Add(&z2z2, z1, z2)
-       p224Reduce(&z2z2)
-       p224Square(&z2z2, &z2z2, &c)
-       p224Sub(z3, &z2z2, &z1z1)
-       p224Reduce(z3)
-       p224Mul(z3, z3, &h, &c)
-       // X3 = r²-J-2*V
-       for i := 0; i < 8; i++ {
-               z1z1[i] = v[i] << 1
+       if x.BitLen() > 224 || y.BitLen() > 224 {
+               return nil, false
        }
-       p224Add(&z1z1, &j, &z1z1)
-       p224Reduce(&z1z1)
-       p224Square(x3, &r, &c)
-       p224Sub(x3, x3, &z1z1)
-       p224Reduce(x3)
-       // Y3 = r*(V-X3)-2*S1*J
-       for i := 0; i < 8; i++ {
-               s1[i] <<= 1
+       p, err := nistec.NewP224Point().SetBytes(Marshal(P224(), x, y))
+       if err != nil {
+               return nil, false
        }
-       p224Mul(&s1, &s1, &j, &c)
-       p224Sub(&z1z1, &v, x3)
-       p224Reduce(&z1z1)
-       p224Mul(&z1z1, &z1z1, &r, &c)
-       p224Sub(y3, &z1z1, &s1)
-       p224Reduce(y3)
-
-       p224CopyConditional(x3, x2, z1IsZero)
-       p224CopyConditional(x3, x1, z2IsZero)
-       p224CopyConditional(y3, y2, z1IsZero)
-       p224CopyConditional(y3, y1, z2IsZero)
-       p224CopyConditional(z3, z2, z1IsZero)
-       p224CopyConditional(z3, z1, z2IsZero)
+       return p, true
 }
 
-// p224DoubleJacobian computes *out = a+a.
-func p224DoubleJacobian(x3, y3, z3, x1, y1, z1 *p224FieldElement) {
-       var delta, gamma, beta, alpha, t p224FieldElement
-       var c p224LargeFieldElement
-
-       p224Square(&delta, z1, &c)
-       p224Square(&gamma, y1, &c)
-       p224Mul(&beta, x1, &gamma, &c)
-
-       // alpha = 3*(X1-delta)*(X1+delta)
-       p224Add(&t, x1, &delta)
-       for i := 0; i < 8; i++ {
-               t[i] += t[i] << 1
-       }
-       p224Reduce(&t)
-       p224Sub(&alpha, x1, &delta)
-       p224Reduce(&alpha)
-       p224Mul(&alpha, &alpha, &t, &c)
-
-       // Z3 = (Y1+Z1)²-gamma-delta
-       p224Add(z3, y1, z1)
-       p224Reduce(z3)
-       p224Square(z3, z3, &c)
-       p224Sub(z3, z3, &gamma)
-       p224Reduce(z3)
-       p224Sub(z3, z3, &delta)
-       p224Reduce(z3)
-
-       // X3 = alpha²-8*beta
-       for i := 0; i < 8; i++ {
-               delta[i] = beta[i] << 3
-       }
-       p224Reduce(&delta)
-       p224Square(x3, &alpha, &c)
-       p224Sub(x3, x3, &delta)
-       p224Reduce(x3)
-
-       // Y3 = alpha*(4*beta-X3)-8*gamma²
-       for i := 0; i < 8; i++ {
-               beta[i] <<= 2
+func p224PointToAffine(p *nistec.P224Point) (x, y *big.Int) {
+       out := p.Bytes()
+       if len(out) == 1 && out[0] == 0 {
+               // This is the correct encoding of the point at infinity, which
+               // Unmarshal does not support. See Issue 37294.
+               return new(big.Int), new(big.Int)
        }
-       p224Sub(&beta, &beta, x3)
-       p224Reduce(&beta)
-       p224Square(&gamma, &gamma, &c)
-       for i := 0; i < 8; i++ {
-               gamma[i] <<= 3
+       x, y = Unmarshal(P224(), out)
+       if x == nil {
+               panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding")
        }
-       p224Reduce(&gamma)
-       p224Mul(y3, &alpha, &beta, &c)
-       p224Sub(y3, y3, &gamma)
-       p224Reduce(y3)
+       return x, y
 }
 
-// p224CopyConditional sets *out = *in in constant time if control is not zero.
-func p224CopyConditional(out, in *p224FieldElement, control uint32) {
-       mask := maskIsNotZero(control)
-       for i := 0; i < 8; i++ {
-               out[i] ^= (out[i] ^ in[i]) & mask
+// p224RandomPoint returns a random point on the curve. It's used when Add,
+// Double, or ScalarMult are fed a point not on the curve, which is undefined
+// behavior. Originally, we used to do the math on it anyway (which allows
+// invalid curve attacks) and relied on the caller and Unmarshal to avoid this
+// happening in the first place. Now, we just can't construct a nistec.P224Point
+// for an invalid pair of coordinates, because that API is safer. If we panic,
+// we risk introducing a DoS. If we return nil, we risk a panic. If we return
+// the input, ecdsa.Verify might fail open. The safest course seems to be to
+// return a valid, random point, which hopefully won't help the attacker.
+func p224RandomPoint() (x, y *big.Int) {
+       _, x, y, err := GenerateKey(P224(), rand.Reader)
+       if err != nil {
+               panic("crypto/elliptic: failed to generate random point")
        }
+       return x, y
 }
 
-func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) {
-       var xx, yy, zz p224FieldElement
-       for i := 0; i < 8; i++ {
-               outX[i] = 0
-               outY[i] = 0
-               outZ[i] = 0
+func (p224Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+       p1, ok := p224PointFromAffine(x1, y1)
+       if !ok {
+               return p224RandomPoint()
        }
-
-       for _, byte := range scalar {
-               for bitNum := uint(0); bitNum < 8; bitNum++ {
-                       p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ)
-                       bit := uint32((byte >> (7 - bitNum)) & 1)
-                       p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ)
-                       p224CopyConditional(outX, &xx, bit)
-                       p224CopyConditional(outY, &yy, bit)
-                       p224CopyConditional(outZ, &zz, bit)
-               }
+       p2, ok := p224PointFromAffine(x2, y2)
+       if !ok {
+               return p224RandomPoint()
        }
+       return p224PointToAffine(p1.Add(p1, p2))
 }
 
-// p224ToAffine converts from Jacobian to affine form.
-func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) {
-       var zinv, zinvsq, outx, outy p224FieldElement
-       var tmp p224LargeFieldElement
-
-       if isPointAtInfinity := p224IsZero(z); isPointAtInfinity == 1 {
-               return new(big.Int), new(big.Int)
+func (p224Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+       p, ok := p224PointFromAffine(x1, y1)
+       if !ok {
+               return p224RandomPoint()
        }
-
-       p224Invert(&zinv, z)
-       p224Square(&zinvsq, &zinv, &tmp)
-       p224Mul(x, x, &zinvsq, &tmp)
-       p224Mul(&zinvsq, &zinvsq, &zinv, &tmp)
-       p224Mul(y, y, &zinvsq, &tmp)
-
-       p224Contract(&outx, x)
-       p224Contract(&outy, y)
-       return p224ToBig(&outx), p224ToBig(&outy)
+       return p224PointToAffine(p.Double(p))
 }
 
-// get28BitsFromEnd returns the least-significant 28 bits from buf>>shift,
-// where buf is interpreted as a big-endian number. shift must be at most
-// 4 bits higher than a multiple of 8.
-func get28BitsFromEnd(buf []byte, shift int) uint32 {
-       buf = buf[:len(buf)-shift/8]
-       shift = shift % 8
-       if shift > 4 {
-               panic("misuse of get28BitsFromEnd")
+func (p224Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+       p, ok := p224PointFromAffine(Bx, By)
+       if !ok {
+               return p224RandomPoint()
        }
-
-       ret := binary.BigEndian.Uint32(buf[len(buf)-4:])
-       ret >>= shift
-       ret &= bottom28Bits
-       return ret
+       return p224PointToAffine(p.ScalarMult(p, scalar))
 }
 
-// p224FromBig sets *out = *in.
-func p224FromBig(out *p224FieldElement, in *big.Int) {
-       bytes := in.FillBytes(make([]byte, 224/8))
-       for i := range out {
-               out[i] = get28BitsFromEnd(bytes, 28*i)
-       }
-}
-
-// p224ToBig returns in as a big.Int.
-func p224ToBig(in *p224FieldElement) *big.Int {
-       var buf [28]byte
-       buf[27] = byte(in[0])
-       buf[26] = byte(in[0] >> 8)
-       buf[25] = byte(in[0] >> 16)
-       buf[24] = byte(((in[0] >> 24) & 0x0f) | (in[1]<<4)&0xf0)
-
-       buf[23] = byte(in[1] >> 4)
-       buf[22] = byte(in[1] >> 12)
-       buf[21] = byte(in[1] >> 20)
-
-       buf[20] = byte(in[2])
-       buf[19] = byte(in[2] >> 8)
-       buf[18] = byte(in[2] >> 16)
-       buf[17] = byte(((in[2] >> 24) & 0x0f) | (in[3]<<4)&0xf0)
-
-       buf[16] = byte(in[3] >> 4)
-       buf[15] = byte(in[3] >> 12)
-       buf[14] = byte(in[3] >> 20)
-
-       buf[13] = byte(in[4])
-       buf[12] = byte(in[4] >> 8)
-       buf[11] = byte(in[4] >> 16)
-       buf[10] = byte(((in[4] >> 24) & 0x0f) | (in[5]<<4)&0xf0)
-
-       buf[9] = byte(in[5] >> 4)
-       buf[8] = byte(in[5] >> 12)
-       buf[7] = byte(in[5] >> 20)
-
-       buf[6] = byte(in[6])
-       buf[5] = byte(in[6] >> 8)
-       buf[4] = byte(in[6] >> 16)
-       buf[3] = byte(((in[6] >> 24) & 0x0f) | (in[7]<<4)&0xf0)
-
-       buf[2] = byte(in[7] >> 4)
-       buf[1] = byte(in[7] >> 12)
-       buf[0] = byte(in[7] >> 20)
-
-       return new(big.Int).SetBytes(buf[:])
+func (p224Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
+       p := nistec.NewP224Generator()
+       return p224PointToAffine(p.ScalarMult(p, scalar))
 }
index 3e0c78b0f9c0de2993efbb83832ff3cde161f75b..7971f631bf2a31b433d8c1bb0056c7cc59db9d02 100644 (file)
@@ -8,313 +8,9 @@ import (
        "encoding/hex"
        "fmt"
        "math/big"
-       "math/bits"
-       "math/rand"
-       "reflect"
        "testing"
-       "testing/quick"
 )
 
-var toFromBigTests = []string{
-       "0",
-       "1",
-       "23",
-       "b70e0cb46bb4bf7f321390b94a03c1d356c01122343280d6105c1d21",
-       "706a46d476dcb76798e6046d89474788d164c18032d268fd10704fa6",
-}
-
-func p224AlternativeToBig(in *p224FieldElement) *big.Int {
-       ret := new(big.Int)
-       tmp := new(big.Int)
-
-       for i := len(in) - 1; i >= 0; i-- {
-               ret.Lsh(ret, 28)
-               tmp.SetInt64(int64(in[i]))
-               ret.Add(ret, tmp)
-       }
-       ret.Mod(ret, P224().Params().P)
-       return ret
-}
-
-func TestP224ToFromBig(t *testing.T) {
-       for i, test := range toFromBigTests {
-               n, _ := new(big.Int).SetString(test, 16)
-               var x p224FieldElement
-               p224FromBig(&x, n)
-               m := p224ToBig(&x)
-               if n.Cmp(m) != 0 {
-                       t.Errorf("#%d: %x != %x", i, n, m)
-               }
-               q := p224AlternativeToBig(&x)
-               if n.Cmp(q) != 0 {
-                       t.Errorf("#%d: %x != %x (alternative)", i, n, q)
-               }
-       }
-}
-
-// quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks)
-// times. The default value of -quickchecks is 100.
-var quickCheckConfig32 = &quick.Config{MaxCountScale: 32}
-
-// weirdLimbs can be combined to generate a range of edge-case field elements.
-var weirdLimbs = [...]uint32{
-       0, 1, (1 << 29) - 1,
-       (1 << 12), (1 << 12) - 1,
-       (1 << 28), (1 << 28) - 1,
-}
-
-func generateLimb(rand *rand.Rand) uint32 {
-       const bottom29Bits = 0x1fffffff
-       n := rand.Intn(len(weirdLimbs) + 3)
-       switch n {
-       case len(weirdLimbs):
-               // Random value.
-               return uint32(rand.Int31n(1 << 29))
-       case len(weirdLimbs) + 1:
-               // Sum of two values.
-               k := generateLimb(rand) + generateLimb(rand)
-               return k & bottom29Bits
-       case len(weirdLimbs) + 2:
-               // Difference of two values.
-               k := generateLimb(rand) - generateLimb(rand)
-               return k & bottom29Bits
-       default:
-               return weirdLimbs[n]
-       }
-}
-
-func (p224FieldElement) Generate(rand *rand.Rand, size int) reflect.Value {
-       return reflect.ValueOf(p224FieldElement{
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-       })
-}
-
-func isInBounds(x *p224FieldElement) bool {
-       return bits.Len32(x[0]) <= 29 &&
-               bits.Len32(x[1]) <= 29 &&
-               bits.Len32(x[2]) <= 29 &&
-               bits.Len32(x[3]) <= 29 &&
-               bits.Len32(x[4]) <= 29 &&
-               bits.Len32(x[5]) <= 29 &&
-               bits.Len32(x[6]) <= 29 &&
-               bits.Len32(x[7]) <= 29
-}
-
-func TestP224Mul(t *testing.T) {
-       mulMatchesBigInt := func(a, b, out p224FieldElement) bool {
-               var tmp p224LargeFieldElement
-               p224Mul(&out, &a, &b, &tmp)
-
-               exp := new(big.Int).Mul(p224AlternativeToBig(&a), p224AlternativeToBig(&b))
-               exp.Mod(exp, P224().Params().P)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 || !isInBounds(&out) {
-                       t.Logf("a = %x", a)
-                       t.Logf("b = %x", b)
-                       t.Logf("p224Mul(a, b) = %x = %v", out, got)
-                       t.Logf("a * b = %v", exp)
-                       return false
-               }
-
-               return true
-       }
-
-       a := p224FieldElement{0xfffffff, 0xfffffff, 0xf00ffff, 0x20f, 0x0, 0x0, 0x0, 0x0}
-       b := p224FieldElement{1, 0, 0, 0, 0, 0, 0, 0}
-       if !mulMatchesBigInt(a, b, p224FieldElement{}) {
-               t.Fail()
-       }
-
-       if err := quick.Check(mulMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Square(t *testing.T) {
-       squareMatchesBigInt := func(a, out p224FieldElement) bool {
-               var tmp p224LargeFieldElement
-               p224Square(&out, &a, &tmp)
-
-               exp := p224AlternativeToBig(&a)
-               exp.Mul(exp, exp)
-               exp.Mod(exp, P224().Params().P)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 || !isInBounds(&out) {
-                       t.Logf("a = %x", a)
-                       t.Logf("p224Square(a, b) = %x = %v", out, got)
-                       t.Logf("a * a = %v", exp)
-                       return false
-               }
-
-               return true
-       }
-
-       if err := quick.Check(squareMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Add(t *testing.T) {
-       addMatchesBigInt := func(a, b, out p224FieldElement) bool {
-               p224Add(&out, &a, &b)
-
-               exp := new(big.Int).Add(p224AlternativeToBig(&a), p224AlternativeToBig(&b))
-               exp.Mod(exp, P224().Params().P)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 {
-                       t.Logf("a = %x", a)
-                       t.Logf("b = %x", b)
-                       t.Logf("p224Add(a, b) = %x = %v", out, got)
-                       t.Logf("a + b = %v", exp)
-                       return false
-               }
-
-               return true
-       }
-
-       if err := quick.Check(addMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Reduce(t *testing.T) {
-       reduceMatchesBigInt := func(a p224FieldElement) bool {
-               out := a
-               // TODO: generate higher values for functions like p224Reduce that are
-               // expected to work with higher input bounds.
-               p224Reduce(&out)
-
-               exp := p224AlternativeToBig(&a)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 || !isInBounds(&out) {
-                       t.Logf("a = %x = %v", a, exp)
-                       t.Logf("p224Reduce(a) = %x = %v", out, got)
-                       return false
-               }
-
-               return true
-       }
-
-       if err := quick.Check(reduceMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Contract(t *testing.T) {
-       contractMatchesBigInt := func(a, out p224FieldElement) bool {
-               p224Contract(&out, &a)
-
-               exp := p224AlternativeToBig(&a)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 {
-                       t.Logf("a = %x = %v", a, exp)
-                       t.Logf("p224Contract(a) = %x = %v", out, got)
-                       return false
-               }
-
-               // Check that out < P.
-               for i := range p224P {
-                       k := 8 - i - 1
-                       if out[k] > p224P[k] {
-                               t.Logf("p224Contract(a) = %x", out)
-                               return false
-                       }
-                       if out[k] < p224P[k] {
-                               return true
-                       }
-               }
-               t.Logf("p224Contract(a) = %x", out)
-               return false
-       }
-
-       if !contractMatchesBigInt(p224P, p224FieldElement{}) {
-               t.Error("p224Contract(p) is broken")
-       }
-       pMinus1 := p224FieldElement{0, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
-       if !contractMatchesBigInt(pMinus1, p224FieldElement{}) {
-               t.Error("p224Contract(p - 1) is broken")
-       }
-       // Check that we can handle input above p, but lowest limb zero.
-       a := p224FieldElement{0, 1, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
-       if !contractMatchesBigInt(a, p224FieldElement{}) {
-               t.Error("p224Contract(p + 2²⁸) is broken")
-       }
-       // Check that we can handle input above p, but lowest three limbs zero.
-       b := p224FieldElement{0, 0, 0, 0xffff001, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
-       if !contractMatchesBigInt(b, p224FieldElement{}) {
-               t.Error("p224Contract(p + 2⁸⁴) is broken")
-       }
-
-       if err := quick.Check(contractMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224IsZero(t *testing.T) {
-       if got := p224IsZero(&p224FieldElement{}); got != 1 {
-               t.Errorf("p224IsZero(0) = %d, expected 1", got)
-       }
-       if got := p224IsZero(&p224P); got != 1 {
-               t.Errorf("p224IsZero(p) = %d, expected 1", got)
-       }
-       if got := p224IsZero(&p224FieldElement{1}); got != 0 {
-               t.Errorf("p224IsZero(1) = %d, expected 0", got)
-       }
-
-       isZeroMatchesBigInt := func(a p224FieldElement) bool {
-               isZero := p224IsZero(&a)
-
-               big := p224AlternativeToBig(&a)
-               if big.Sign() == 0 && isZero != 1 {
-                       return false
-               }
-               if big.Sign() != 0 && isZero != 0 {
-                       return false
-               }
-               return true
-       }
-
-       if err := quick.Check(isZeroMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Invert(t *testing.T) {
-       var out p224FieldElement
-
-       p224Invert(&out, &p224FieldElement{})
-       if got := p224IsZero(&out); got != 1 {
-               t.Errorf("p224Invert(0) = %x, expected 0", out)
-       }
-
-       p224Invert(&out, &p224P)
-       if got := p224IsZero(&out); got != 1 {
-               t.Errorf("p224Invert(p) = %x, expected 0", out)
-       }
-
-       p224Invert(&out, &p224FieldElement{1})
-       p224Contract(&out, &out)
-       if out != (p224FieldElement{1}) {
-               t.Errorf("p224Invert(1) = %x, expected 1", out)
-       }
-
-       var tmp p224LargeFieldElement
-       a := p224FieldElement{1, 2, 3, 4, 5, 6, 7, 8}
-       p224Invert(&out, &a)
-       p224Mul(&out, &out, &a, &tmp)
-       p224Contract(&out, &out)
-       if out != (p224FieldElement{1}) {
-               t.Errorf("p224Invert(a) * a = %x, expected 1", out)
-       }
-}
-
 type baseMultTest struct {
        k    string
        x, y string
@@ -602,7 +298,7 @@ func TestP224BaseMult(t *testing.T) {
 
 func TestP224GenericBaseMult(t *testing.T) {
        // We use the P224 CurveParams directly in order to test the generic implementation.
-       p224 := P224().Params()
+       p224 := genericParamsForCurve(P224())
        for i, e := range p224BaseMultTests {
                k, ok := new(big.Int).SetString(e.k, 10)
                if !ok {
index 7747de7a50bb3855800576f391f8b9c3678a81f4..7ff7e335487509e54a11cc5c6720e80103bd0d1c 100644 (file)
@@ -209,6 +209,8 @@ var p256Precomputed = [p256Limbs * 2 * 15 * 2]uint32{
 
 // Field element operations:
 
+const bottom28Bits = 0xfffffff
+
 // nonZeroToAllOnes returns:
 //   0xffffffff for 0 < x <= 2**31
 //   0 for x == 0 or x > 2**31.
@@ -269,6 +271,7 @@ const (
        two30m2    = 1<<30 - 1<<2
        two30p13m2 = 1<<30 + 1<<13 - 1<<2
        two31m2    = 1<<31 - 1<<2
+       two31m3    = 1<<31 - 1<<3
        two31p24m2 = 1<<31 + 1<<24 - 1<<2
        two30m27m2 = 1<<30 - 1<<27 - 1<<2
 )
index 1435f5e1a58a8f9a7f1a9cffe7d5ca03f08f79c7..c6862d95476c6fb8d40b247dfad1aa1fba531fac 100644 (file)
@@ -34,7 +34,7 @@ var p256MultTests = []scalarMultTest{
 
 func TestP256BaseMult(t *testing.T) {
        p256 := P256()
-       p256Generic := p256.Params()
+       p256Generic := genericParamsForCurve(p256)
 
        scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1)
        for _, e := range p224BaseMultTests {
@@ -60,23 +60,6 @@ func TestP256BaseMult(t *testing.T) {
 
 func TestP256Mult(t *testing.T) {
        p256 := P256()
-       p256Generic := p256.Params()
-
-       for i, e := range p224BaseMultTests {
-               x, _ := new(big.Int).SetString(e.x, 16)
-               y, _ := new(big.Int).SetString(e.y, 16)
-               k, _ := new(big.Int).SetString(e.k, 10)
-
-               xx, yy := p256.ScalarMult(x, y, k.Bytes())
-               xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes())
-               if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 {
-                       t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2)
-               }
-               if testing.Short() && i > 5 {
-                       break
-               }
-       }
-
        for i, e := range p256MultTests {
                x, _ := new(big.Int).SetString(e.xIn, 16)
                y, _ := new(big.Int).SetString(e.yIn, 16)
diff --git a/src/crypto/elliptic/p384.go b/src/crypto/elliptic/p384.go
new file mode 100644 (file)
index 0000000..0fb7471
--- /dev/null
@@ -0,0 +1,141 @@
+// Copyright 2013 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.
+
+package elliptic
+
+import (
+       "crypto/elliptic/internal/nistec"
+       "crypto/rand"
+       "math/big"
+)
+
+// p384Curve is a Curve implementation based on nistec.P384Point.
+//
+// It's a wrapper that exposes the big.Int-based Curve interface and encodes the
+// legacy idiosyncrasies it requires, such as invalid and infinity point
+// handling.
+//
+// To interact with the nistec package, points are encoded into and decoded from
+// properly formatted byte slices. All big.Int use is limited to this package.
+// Encoding and decoding is 1/1000th of the runtime of a scalar multiplication,
+// so the overhead is acceptable.
+type p384Curve struct {
+       params *CurveParams
+}
+
+var p384 p384Curve
+var _ Curve = p384
+
+func initP384() {
+       p384.params = &CurveParams{
+               Name:    "P-384",
+               BitSize: 384,
+               // FIPS 186-4, section D.1.2.4
+               P: bigFromDecimal("394020061963944792122790401001436138050797392704654" +
+                       "46667948293404245721771496870329047266088258938001861606973112319"),
+               N: bigFromDecimal("394020061963944792122790401001436138050797392704654" +
+                       "46667946905279627659399113263569398956308152294913554433653942643"),
+               B: bigFromHex("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088" +
+                       "f5013875ac656398d8a2ed19d2a85c8edd3ec2aef"),
+               Gx: bigFromHex("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741" +
+                       "e082542a385502f25dbf55296c3a545e3872760ab7"),
+               Gy: bigFromHex("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da31" +
+                       "13b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"),
+       }
+}
+
+func (curve p384Curve) Params() *CurveParams {
+       return curve.params
+}
+
+func (curve p384Curve) IsOnCurve(x, y *big.Int) bool {
+       // IsOnCurve is documented to reject (0, 0), the conventional point at
+       // infinity, which however is accepted by p384PointFromAffine.
+       if x.Sign() == 0 && y.Sign() == 0 {
+               return false
+       }
+       _, ok := p384PointFromAffine(x, y)
+       return ok
+}
+
+func p384PointFromAffine(x, y *big.Int) (p *nistec.P384Point, ok bool) {
+       // (0, 0) is by convention the point at infinity, which can't be represented
+       // in affine coordinates. Marshal incorrectly encodes it as an uncompressed
+       // point, which SetBytes would correctly reject. See Issue 37294.
+       if x.Sign() == 0 && y.Sign() == 0 {
+               return nistec.NewP384Point(), true
+       }
+       if x.BitLen() > 384 || y.BitLen() > 384 {
+               return nil, false
+       }
+       p, err := nistec.NewP384Point().SetBytes(Marshal(P384(), x, y))
+       if err != nil {
+               return nil, false
+       }
+       return p, true
+}
+
+func p384PointToAffine(p *nistec.P384Point) (x, y *big.Int) {
+       out := p.Bytes()
+       if len(out) == 1 && out[0] == 0 {
+               // This is the correct encoding of the point at infinity, which
+               // Unmarshal does not support. See Issue 37294.
+               return new(big.Int), new(big.Int)
+       }
+       x, y = Unmarshal(P384(), out)
+       if x == nil {
+               panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding")
+       }
+       return x, y
+}
+
+// p384RandomPoint returns a random point on the curve. It's used when Add,
+// Double, or ScalarMult are fed a point not on the curve, which is undefined
+// behavior. Originally, we used to do the math on it anyway (which allows
+// invalid curve attacks) and relied on the caller and Unmarshal to avoid this
+// happening in the first place. Now, we just can't construct a nistec.P384Point
+// for an invalid pair of coordinates, because that API is safer. If we panic,
+// we risk introducing a DoS. If we return nil, we risk a panic. If we return
+// the input, ecdsa.Verify might fail open. The safest course seems to be to
+// return a valid, random point, which hopefully won't help the attacker.
+func p384RandomPoint() (x, y *big.Int) {
+       _, x, y, err := GenerateKey(P384(), rand.Reader)
+       if err != nil {
+               panic("crypto/elliptic: failed to generate random point")
+       }
+       return x, y
+}
+
+func (p384Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+       p1, ok := p384PointFromAffine(x1, y1)
+       if !ok {
+               return p384RandomPoint()
+       }
+       p2, ok := p384PointFromAffine(x2, y2)
+       if !ok {
+               return p384RandomPoint()
+       }
+       return p384PointToAffine(p1.Add(p1, p2))
+}
+
+func (p384Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+       p, ok := p384PointFromAffine(x1, y1)
+       if !ok {
+               return p384RandomPoint()
+       }
+       return p384PointToAffine(p.Double(p))
+}
+
+func (p384Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+       p, ok := p384PointFromAffine(Bx, By)
+       if !ok {
+               return p384RandomPoint()
+       }
+       return p384PointToAffine(p.ScalarMult(p, scalar))
+}
+
+func (p384Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
+       p := nistec.NewP384Generator()
+       return p384PointToAffine(p.ScalarMult(p, scalar))
+}
index e64007dfe35aad3a17906a054953a6d68280be88..6c9eed30e536cd715a28bfe6a7e50bf2183172fd 100644 (file)
@@ -112,7 +112,7 @@ func p521RandomPoint() (x, y *big.Int) {
        return x, y
 }
 
-func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+func (p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
        p1, ok := p521PointFromAffine(x1, y1)
        if !ok {
                return p521RandomPoint()
@@ -124,7 +124,7 @@ func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
        return p521PointToAffine(p1.Add(p1, p2))
 }
 
-func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+func (p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
        p, ok := p521PointFromAffine(x1, y1)
        if !ok {
                return p521RandomPoint()
@@ -132,7 +132,7 @@ func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
        return p521PointToAffine(p.Double(p))
 }
 
-func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+func (p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
        p, ok := p521PointFromAffine(Bx, By)
        if !ok {
                return p521RandomPoint()
@@ -140,7 +140,7 @@ func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *bi
        return p521PointToAffine(p.ScalarMult(p, scalar))
 }
 
-func (curve p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
+func (p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
        p := nistec.NewP521Generator()
        return p521PointToAffine(p.ScalarMult(p, scalar))
 }