From ae9d85d2f0c20cbb77db537f7e70ee9223d9e39b Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Mon, 20 Jun 2022 11:15:09 +0800 Subject: [PATCH] sm2: use new implementation, part 1 --- internal/sm2ec/fiat/Dockerfile | 12 + internal/sm2ec/fiat/README | 34 + internal/sm2ec/fiat/generate.go | 277 +++++ internal/sm2ec/fiat/sm2p256.go | 114 ++ internal/sm2ec/fiat/sm2p256_fiat64.go | 1524 +++++++++++++++++++++++++ internal/sm2ec/fiat/sm2p256_invert.go | 94 ++ internal/sm2ec/generate.go | 552 +++++++++ internal/sm2ec/sm2ec.go | 11 + internal/sm2ec/sm2ec_test.go | 157 +++ internal/sm2ec/sm2p256.go | 485 ++++++++ 10 files changed, 3260 insertions(+) create mode 100644 internal/sm2ec/fiat/Dockerfile create mode 100644 internal/sm2ec/fiat/README create mode 100644 internal/sm2ec/fiat/generate.go create mode 100644 internal/sm2ec/fiat/sm2p256.go create mode 100644 internal/sm2ec/fiat/sm2p256_fiat64.go create mode 100644 internal/sm2ec/fiat/sm2p256_invert.go create mode 100644 internal/sm2ec/generate.go create mode 100644 internal/sm2ec/sm2ec.go create mode 100644 internal/sm2ec/sm2ec_test.go create mode 100644 internal/sm2ec/sm2p256.go diff --git a/internal/sm2ec/fiat/Dockerfile b/internal/sm2ec/fiat/Dockerfile new file mode 100644 index 0000000..fe31d36 --- /dev/null +++ b/internal/sm2ec/fiat/Dockerfile @@ -0,0 +1,12 @@ +# 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. + +FROM coqorg/coq:8.13.2 + +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 + +ENV PATH /home/coq/fiat-crypto/src/ExtractionOCaml:$PATH diff --git a/internal/sm2ec/fiat/README b/internal/sm2ec/fiat/README new file mode 100644 index 0000000..bce1a41 --- /dev/null +++ b/internal/sm2ec/fiat/README @@ -0,0 +1,34 @@ +The code in this package was autogenerated by the fiat-crypto project +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 + go run generate.go + +fiat-crypto code comes under the following license. + + Copyright (c) 2015-2020 The fiat-crypto Authors. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, + Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The authors are listed at + + https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS diff --git a/internal/sm2ec/fiat/generate.go b/internal/sm2ec/fiat/generate.go new file mode 100644 index 0000000..9d1e54a --- /dev/null +++ b/internal/sm2ec/fiat/generate.go @@ -0,0 +1,277 @@ +// 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 +// +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: "SM2P256Element", + Prime: "2^256 - 2^224 - 2^96 + 2^64 - 1", + Prefix: "sm2p256", + FiatType: "[4]uint64", + BytesLen: 32, + }, +} + +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/internal/sm2ec/fiat/sm2p256.go b/internal/sm2ec/fiat/sm2p256.go new file mode 100644 index 0000000..099f738 --- /dev/null +++ b/internal/sm2ec/fiat/sm2p256.go @@ -0,0 +1,114 @@ +// 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" +) +// SM2P256Element is an integer modulo 2^256 - 2^224 - 2^96 + 2^64 - 1. +// +// The zero value is a valid zero element. +type SM2P256Element struct { + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x sm2p256MontgomeryDomainFieldElement +} +const sm2p256ElementLen = 32 +type sm2p256UntypedFieldElement = [4]uint64 +// One sets e = 1, and returns e. +func (e *SM2P256Element) One() *SM2P256Element { + sm2p256SetOne(&e.x) + return e +} +// Equal returns 1 if e == t, and zero otherwise. +func (e *SM2P256Element) Equal(t *SM2P256Element) int { + eBytes := e.Bytes() + tBytes := t.Bytes() + return subtle.ConstantTimeCompare(eBytes, tBytes) +} +var sm2p256ZeroEncoding = new(SM2P256Element).Bytes() +// IsZero returns 1 if e == 0, and zero otherwise. +func (e *SM2P256Element) IsZero() int { + eBytes := e.Bytes() + return subtle.ConstantTimeCompare(eBytes, sm2p256ZeroEncoding) +} +// Set sets e = t, and returns e. +func (e *SM2P256Element) Set(t *SM2P256Element) *SM2P256Element { + e.x = t.x + return e +} +// Bytes returns the 32-byte big-endian encoding of e. +func (e *SM2P256Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [sm2p256ElementLen]byte + return e.bytes(&out) +} +func (e *SM2P256Element) bytes(out *[sm2p256ElementLen]byte) []byte { + var tmp sm2p256NonMontgomeryDomainFieldElement + sm2p256FromMontgomery(&tmp, &e.x) + sm2p256ToBytes(out, (*sm2p256UntypedFieldElement)(&tmp)) + sm2p256InvertEndianness(out[:]) + return out[:] +} +// sm2p256MinusOneEncoding 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 sm2p256MinusOneEncoding = new(SM2P256Element).Sub( + new(SM2P256Element), new(SM2P256Element).One()).Bytes() +// SetBytes sets e = v, where v is a big-endian 32-byte encoding, and returns e. +// If v is not 32 bytes or it encodes a value higher than 2^256 - 2^224 - 2^96 + 2^64 - 1, +// SetBytes returns nil and an error, and e is unchanged. +func (e *SM2P256Element) SetBytes(v []byte) (*SM2P256Element, error) { + if len(v) != sm2p256ElementLen { + return nil, errors.New("invalid SM2P256Element encoding") + } + for i := range v { + if v[i] < sm2p256MinusOneEncoding[i] { + break + } + if v[i] > sm2p256MinusOneEncoding[i] { + return nil, errors.New("invalid SM2P256Element encoding") + } + } + var in [sm2p256ElementLen]byte + copy(in[:], v) + sm2p256InvertEndianness(in[:]) + var tmp sm2p256NonMontgomeryDomainFieldElement + sm2p256FromBytes((*sm2p256UntypedFieldElement)(&tmp), &in) + sm2p256ToMontgomery(&e.x, &tmp) + return e, nil +} +// Add sets e = t1 + t2, and returns e. +func (e *SM2P256Element) Add(t1, t2 *SM2P256Element) *SM2P256Element { + sm2p256Add(&e.x, &t1.x, &t2.x) + return e +} +// Sub sets e = t1 - t2, and returns e. +func (e *SM2P256Element) Sub(t1, t2 *SM2P256Element) *SM2P256Element { + sm2p256Sub(&e.x, &t1.x, &t2.x) + return e +} +// Mul sets e = t1 * t2, and returns e. +func (e *SM2P256Element) Mul(t1, t2 *SM2P256Element) *SM2P256Element { + sm2p256Mul(&e.x, &t1.x, &t2.x) + return e +} +// Square sets e = t * t, and returns e. +func (e *SM2P256Element) Square(t *SM2P256Element) *SM2P256Element { + sm2p256Square(&e.x, &t.x) + return e +} +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *SM2P256Element) Select(a, b *SM2P256Element, cond int) *SM2P256Element { + sm2p256Selectznz((*sm2p256UntypedFieldElement)(&v.x), sm2p256Uint1(cond), + (*sm2p256UntypedFieldElement)(&b.x), (*sm2p256UntypedFieldElement)(&a.x)) + return v +} +func sm2p256InvertEndianness(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/internal/sm2ec/fiat/sm2p256_fiat64.go b/internal/sm2ec/fiat/sm2p256_fiat64.go new file mode 100644 index 0000000..a3d7f06 --- /dev/null +++ b/internal/sm2ec/fiat/sm2p256_fiat64.go @@ -0,0 +1,1524 @@ +// 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 sm2p256 64 '2^256 - 2^224 - 2^96 + 2^64 - 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes +// +// curve description: sm2p256 +// +// machine_wordsize = 64 (from "64") +// +// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes +// +// m = 0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff (from "2^256 - 2^224 - 2^96 + 2^64 - 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) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) +// +// 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 sm2p256Uint1 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 sm2p256Int1 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 sm2p256MontgomeryDomainFieldElement is a field element in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type sm2p256MontgomeryDomainFieldElement [4]uint64 + +// The type sm2p256NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type sm2p256NonMontgomeryDomainFieldElement [4]uint64 + +// sm2p256CmovznzU64 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 sm2p256CmovznzU64(out1 *uint64, arg1 sm2p256Uint1, arg2 uint64, arg3 uint64) { + x1 := (uint64(arg1) * 0xffffffffffffffff) + x2 := ((x1 & arg3) | ((^x1) & arg2)) + *out1 = x2 +} + +// sm2p256Mul 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 sm2p256Mul(out1 *sm2p256MontgomeryDomainFieldElement, arg1 *sm2p256MontgomeryDomainFieldElement, arg2 *sm2p256MontgomeryDomainFieldElement) { + 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(sm2p256Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(sm2p256Uint1(x16))) + x19 := (uint64(sm2p256Uint1(x18)) + x6) + var x20 uint64 + var x21 uint64 + x21, x20 = bits.Mul64(x11, 0xfffffffeffffffff) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x11, 0xffffffffffffffff) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x11, 0xffffffff00000000) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(x11, 0xffffffffffffffff) + 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(sm2p256Uint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(x23, x20, uint64(sm2p256Uint1(x31))) + x34 := (uint64(sm2p256Uint1(x33)) + x21) + var x36 uint64 + _, x36 = bits.Add64(x11, x26, uint64(0x0)) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x13, x28, uint64(sm2p256Uint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x15, x30, uint64(sm2p256Uint1(x38))) + var x41 uint64 + var x42 uint64 + x41, x42 = bits.Add64(x17, x32, uint64(sm2p256Uint1(x40))) + var x43 uint64 + var x44 uint64 + x43, x44 = bits.Add64(x19, x34, uint64(sm2p256Uint1(x42))) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, arg2[3]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, arg2[2]) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, arg2[1]) + var x51 uint64 + var x52 uint64 + x52, x51 = bits.Mul64(x1, arg2[0]) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x52, x49, uint64(0x0)) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x50, x47, uint64(sm2p256Uint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(x48, x45, uint64(sm2p256Uint1(x56))) + x59 := (uint64(sm2p256Uint1(x58)) + x46) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x37, x51, uint64(0x0)) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x39, x53, uint64(sm2p256Uint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x41, x55, uint64(sm2p256Uint1(x63))) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(x43, x57, uint64(sm2p256Uint1(x65))) + var x68 uint64 + var x69 uint64 + x68, x69 = bits.Add64(uint64(sm2p256Uint1(x44)), x59, uint64(sm2p256Uint1(x67))) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x60, 0xfffffffeffffffff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x60, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(x60, 0xffffffff00000000) + var x76 uint64 + var x77 uint64 + x77, x76 = bits.Mul64(x60, 0xffffffffffffffff) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x77, x74, uint64(0x0)) + var x80 uint64 + var x81 uint64 + x80, x81 = bits.Add64(x75, x72, uint64(sm2p256Uint1(x79))) + var x82 uint64 + var x83 uint64 + x82, x83 = bits.Add64(x73, x70, uint64(sm2p256Uint1(x81))) + x84 := (uint64(sm2p256Uint1(x83)) + x71) + var x86 uint64 + _, x86 = bits.Add64(x60, x76, uint64(0x0)) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x62, x78, uint64(sm2p256Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x64, x80, uint64(sm2p256Uint1(x88))) + var x91 uint64 + var x92 uint64 + x91, x92 = bits.Add64(x66, x82, uint64(sm2p256Uint1(x90))) + var x93 uint64 + var x94 uint64 + x93, x94 = bits.Add64(x68, x84, uint64(sm2p256Uint1(x92))) + x95 := (uint64(sm2p256Uint1(x94)) + uint64(sm2p256Uint1(x69))) + var x96 uint64 + var x97 uint64 + x97, x96 = bits.Mul64(x2, arg2[3]) + var x98 uint64 + var x99 uint64 + x99, x98 = bits.Mul64(x2, arg2[2]) + var x100 uint64 + var x101 uint64 + x101, x100 = bits.Mul64(x2, arg2[1]) + var x102 uint64 + var x103 uint64 + x103, x102 = bits.Mul64(x2, arg2[0]) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(x103, x100, uint64(0x0)) + var x106 uint64 + var x107 uint64 + x106, x107 = bits.Add64(x101, x98, uint64(sm2p256Uint1(x105))) + var x108 uint64 + var x109 uint64 + x108, x109 = bits.Add64(x99, x96, uint64(sm2p256Uint1(x107))) + x110 := (uint64(sm2p256Uint1(x109)) + x97) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x87, x102, uint64(0x0)) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x89, x104, uint64(sm2p256Uint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x91, x106, uint64(sm2p256Uint1(x114))) + var x117 uint64 + var x118 uint64 + x117, x118 = bits.Add64(x93, x108, uint64(sm2p256Uint1(x116))) + var x119 uint64 + var x120 uint64 + x119, x120 = bits.Add64(x95, x110, uint64(sm2p256Uint1(x118))) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(x111, 0xfffffffeffffffff) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x111, 0xffffffffffffffff) + var x125 uint64 + var x126 uint64 + x126, x125 = bits.Mul64(x111, 0xffffffff00000000) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(x111, 0xffffffffffffffff) + var x129 uint64 + var x130 uint64 + x129, x130 = bits.Add64(x128, x125, uint64(0x0)) + var x131 uint64 + var x132 uint64 + x131, x132 = bits.Add64(x126, x123, uint64(sm2p256Uint1(x130))) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x124, x121, uint64(sm2p256Uint1(x132))) + x135 := (uint64(sm2p256Uint1(x134)) + x122) + var x137 uint64 + _, x137 = bits.Add64(x111, x127, uint64(0x0)) + var x138 uint64 + var x139 uint64 + x138, x139 = bits.Add64(x113, x129, uint64(sm2p256Uint1(x137))) + var x140 uint64 + var x141 uint64 + x140, x141 = bits.Add64(x115, x131, uint64(sm2p256Uint1(x139))) + var x142 uint64 + var x143 uint64 + x142, x143 = bits.Add64(x117, x133, uint64(sm2p256Uint1(x141))) + var x144 uint64 + var x145 uint64 + x144, x145 = bits.Add64(x119, x135, uint64(sm2p256Uint1(x143))) + x146 := (uint64(sm2p256Uint1(x145)) + uint64(sm2p256Uint1(x120))) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(x3, arg2[3]) + var x149 uint64 + var x150 uint64 + x150, x149 = bits.Mul64(x3, arg2[2]) + var x151 uint64 + var x152 uint64 + x152, x151 = bits.Mul64(x3, arg2[1]) + var x153 uint64 + var x154 uint64 + x154, x153 = bits.Mul64(x3, arg2[0]) + var x155 uint64 + var x156 uint64 + x155, x156 = bits.Add64(x154, x151, uint64(0x0)) + var x157 uint64 + var x158 uint64 + x157, x158 = bits.Add64(x152, x149, uint64(sm2p256Uint1(x156))) + var x159 uint64 + var x160 uint64 + x159, x160 = bits.Add64(x150, x147, uint64(sm2p256Uint1(x158))) + x161 := (uint64(sm2p256Uint1(x160)) + x148) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x138, x153, uint64(0x0)) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x140, x155, uint64(sm2p256Uint1(x163))) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x142, x157, uint64(sm2p256Uint1(x165))) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Add64(x144, x159, uint64(sm2p256Uint1(x167))) + var x170 uint64 + var x171 uint64 + x170, x171 = bits.Add64(x146, x161, uint64(sm2p256Uint1(x169))) + var x172 uint64 + var x173 uint64 + x173, x172 = bits.Mul64(x162, 0xfffffffeffffffff) + var x174 uint64 + var x175 uint64 + x175, x174 = bits.Mul64(x162, 0xffffffffffffffff) + var x176 uint64 + var x177 uint64 + x177, x176 = bits.Mul64(x162, 0xffffffff00000000) + var x178 uint64 + var x179 uint64 + x179, x178 = bits.Mul64(x162, 0xffffffffffffffff) + var x180 uint64 + var x181 uint64 + x180, x181 = bits.Add64(x179, x176, uint64(0x0)) + var x182 uint64 + var x183 uint64 + x182, x183 = bits.Add64(x177, x174, uint64(sm2p256Uint1(x181))) + var x184 uint64 + var x185 uint64 + x184, x185 = bits.Add64(x175, x172, uint64(sm2p256Uint1(x183))) + x186 := (uint64(sm2p256Uint1(x185)) + x173) + var x188 uint64 + _, x188 = bits.Add64(x162, x178, uint64(0x0)) + var x189 uint64 + var x190 uint64 + x189, x190 = bits.Add64(x164, x180, uint64(sm2p256Uint1(x188))) + var x191 uint64 + var x192 uint64 + x191, x192 = bits.Add64(x166, x182, uint64(sm2p256Uint1(x190))) + var x193 uint64 + var x194 uint64 + x193, x194 = bits.Add64(x168, x184, uint64(sm2p256Uint1(x192))) + var x195 uint64 + var x196 uint64 + x195, x196 = bits.Add64(x170, x186, uint64(sm2p256Uint1(x194))) + x197 := (uint64(sm2p256Uint1(x196)) + uint64(sm2p256Uint1(x171))) + var x198 uint64 + var x199 uint64 + x198, x199 = bits.Sub64(x189, 0xffffffffffffffff, uint64(0x0)) + var x200 uint64 + var x201 uint64 + x200, x201 = bits.Sub64(x191, 0xffffffff00000000, uint64(sm2p256Uint1(x199))) + var x202 uint64 + var x203 uint64 + x202, x203 = bits.Sub64(x193, 0xffffffffffffffff, uint64(sm2p256Uint1(x201))) + var x204 uint64 + var x205 uint64 + x204, x205 = bits.Sub64(x195, 0xfffffffeffffffff, uint64(sm2p256Uint1(x203))) + var x207 uint64 + _, x207 = bits.Sub64(x197, uint64(0x0), uint64(sm2p256Uint1(x205))) + var x208 uint64 + sm2p256CmovznzU64(&x208, sm2p256Uint1(x207), x198, x189) + var x209 uint64 + sm2p256CmovznzU64(&x209, sm2p256Uint1(x207), x200, x191) + var x210 uint64 + sm2p256CmovznzU64(&x210, sm2p256Uint1(x207), x202, x193) + var x211 uint64 + sm2p256CmovznzU64(&x211, sm2p256Uint1(x207), x204, x195) + out1[0] = x208 + out1[1] = x209 + out1[2] = x210 + out1[3] = x211 +} + +// sm2p256Square 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 sm2p256Square(out1 *sm2p256MontgomeryDomainFieldElement, arg1 *sm2p256MontgomeryDomainFieldElement) { + 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(sm2p256Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(sm2p256Uint1(x16))) + x19 := (uint64(sm2p256Uint1(x18)) + x6) + var x20 uint64 + var x21 uint64 + x21, x20 = bits.Mul64(x11, 0xfffffffeffffffff) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x11, 0xffffffffffffffff) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x11, 0xffffffff00000000) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(x11, 0xffffffffffffffff) + 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(sm2p256Uint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(x23, x20, uint64(sm2p256Uint1(x31))) + x34 := (uint64(sm2p256Uint1(x33)) + x21) + var x36 uint64 + _, x36 = bits.Add64(x11, x26, uint64(0x0)) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x13, x28, uint64(sm2p256Uint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x15, x30, uint64(sm2p256Uint1(x38))) + var x41 uint64 + var x42 uint64 + x41, x42 = bits.Add64(x17, x32, uint64(sm2p256Uint1(x40))) + var x43 uint64 + var x44 uint64 + x43, x44 = bits.Add64(x19, x34, uint64(sm2p256Uint1(x42))) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, arg1[3]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, arg1[2]) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, arg1[1]) + var x51 uint64 + var x52 uint64 + x52, x51 = bits.Mul64(x1, arg1[0]) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x52, x49, uint64(0x0)) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x50, x47, uint64(sm2p256Uint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(x48, x45, uint64(sm2p256Uint1(x56))) + x59 := (uint64(sm2p256Uint1(x58)) + x46) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x37, x51, uint64(0x0)) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x39, x53, uint64(sm2p256Uint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x41, x55, uint64(sm2p256Uint1(x63))) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(x43, x57, uint64(sm2p256Uint1(x65))) + var x68 uint64 + var x69 uint64 + x68, x69 = bits.Add64(uint64(sm2p256Uint1(x44)), x59, uint64(sm2p256Uint1(x67))) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x60, 0xfffffffeffffffff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x60, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(x60, 0xffffffff00000000) + var x76 uint64 + var x77 uint64 + x77, x76 = bits.Mul64(x60, 0xffffffffffffffff) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x77, x74, uint64(0x0)) + var x80 uint64 + var x81 uint64 + x80, x81 = bits.Add64(x75, x72, uint64(sm2p256Uint1(x79))) + var x82 uint64 + var x83 uint64 + x82, x83 = bits.Add64(x73, x70, uint64(sm2p256Uint1(x81))) + x84 := (uint64(sm2p256Uint1(x83)) + x71) + var x86 uint64 + _, x86 = bits.Add64(x60, x76, uint64(0x0)) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x62, x78, uint64(sm2p256Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x64, x80, uint64(sm2p256Uint1(x88))) + var x91 uint64 + var x92 uint64 + x91, x92 = bits.Add64(x66, x82, uint64(sm2p256Uint1(x90))) + var x93 uint64 + var x94 uint64 + x93, x94 = bits.Add64(x68, x84, uint64(sm2p256Uint1(x92))) + x95 := (uint64(sm2p256Uint1(x94)) + uint64(sm2p256Uint1(x69))) + var x96 uint64 + var x97 uint64 + x97, x96 = bits.Mul64(x2, arg1[3]) + var x98 uint64 + var x99 uint64 + x99, x98 = bits.Mul64(x2, arg1[2]) + var x100 uint64 + var x101 uint64 + x101, x100 = bits.Mul64(x2, arg1[1]) + var x102 uint64 + var x103 uint64 + x103, x102 = bits.Mul64(x2, arg1[0]) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(x103, x100, uint64(0x0)) + var x106 uint64 + var x107 uint64 + x106, x107 = bits.Add64(x101, x98, uint64(sm2p256Uint1(x105))) + var x108 uint64 + var x109 uint64 + x108, x109 = bits.Add64(x99, x96, uint64(sm2p256Uint1(x107))) + x110 := (uint64(sm2p256Uint1(x109)) + x97) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x87, x102, uint64(0x0)) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x89, x104, uint64(sm2p256Uint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x91, x106, uint64(sm2p256Uint1(x114))) + var x117 uint64 + var x118 uint64 + x117, x118 = bits.Add64(x93, x108, uint64(sm2p256Uint1(x116))) + var x119 uint64 + var x120 uint64 + x119, x120 = bits.Add64(x95, x110, uint64(sm2p256Uint1(x118))) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(x111, 0xfffffffeffffffff) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x111, 0xffffffffffffffff) + var x125 uint64 + var x126 uint64 + x126, x125 = bits.Mul64(x111, 0xffffffff00000000) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(x111, 0xffffffffffffffff) + var x129 uint64 + var x130 uint64 + x129, x130 = bits.Add64(x128, x125, uint64(0x0)) + var x131 uint64 + var x132 uint64 + x131, x132 = bits.Add64(x126, x123, uint64(sm2p256Uint1(x130))) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x124, x121, uint64(sm2p256Uint1(x132))) + x135 := (uint64(sm2p256Uint1(x134)) + x122) + var x137 uint64 + _, x137 = bits.Add64(x111, x127, uint64(0x0)) + var x138 uint64 + var x139 uint64 + x138, x139 = bits.Add64(x113, x129, uint64(sm2p256Uint1(x137))) + var x140 uint64 + var x141 uint64 + x140, x141 = bits.Add64(x115, x131, uint64(sm2p256Uint1(x139))) + var x142 uint64 + var x143 uint64 + x142, x143 = bits.Add64(x117, x133, uint64(sm2p256Uint1(x141))) + var x144 uint64 + var x145 uint64 + x144, x145 = bits.Add64(x119, x135, uint64(sm2p256Uint1(x143))) + x146 := (uint64(sm2p256Uint1(x145)) + uint64(sm2p256Uint1(x120))) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(x3, arg1[3]) + var x149 uint64 + var x150 uint64 + x150, x149 = bits.Mul64(x3, arg1[2]) + var x151 uint64 + var x152 uint64 + x152, x151 = bits.Mul64(x3, arg1[1]) + var x153 uint64 + var x154 uint64 + x154, x153 = bits.Mul64(x3, arg1[0]) + var x155 uint64 + var x156 uint64 + x155, x156 = bits.Add64(x154, x151, uint64(0x0)) + var x157 uint64 + var x158 uint64 + x157, x158 = bits.Add64(x152, x149, uint64(sm2p256Uint1(x156))) + var x159 uint64 + var x160 uint64 + x159, x160 = bits.Add64(x150, x147, uint64(sm2p256Uint1(x158))) + x161 := (uint64(sm2p256Uint1(x160)) + x148) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x138, x153, uint64(0x0)) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x140, x155, uint64(sm2p256Uint1(x163))) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x142, x157, uint64(sm2p256Uint1(x165))) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Add64(x144, x159, uint64(sm2p256Uint1(x167))) + var x170 uint64 + var x171 uint64 + x170, x171 = bits.Add64(x146, x161, uint64(sm2p256Uint1(x169))) + var x172 uint64 + var x173 uint64 + x173, x172 = bits.Mul64(x162, 0xfffffffeffffffff) + var x174 uint64 + var x175 uint64 + x175, x174 = bits.Mul64(x162, 0xffffffffffffffff) + var x176 uint64 + var x177 uint64 + x177, x176 = bits.Mul64(x162, 0xffffffff00000000) + var x178 uint64 + var x179 uint64 + x179, x178 = bits.Mul64(x162, 0xffffffffffffffff) + var x180 uint64 + var x181 uint64 + x180, x181 = bits.Add64(x179, x176, uint64(0x0)) + var x182 uint64 + var x183 uint64 + x182, x183 = bits.Add64(x177, x174, uint64(sm2p256Uint1(x181))) + var x184 uint64 + var x185 uint64 + x184, x185 = bits.Add64(x175, x172, uint64(sm2p256Uint1(x183))) + x186 := (uint64(sm2p256Uint1(x185)) + x173) + var x188 uint64 + _, x188 = bits.Add64(x162, x178, uint64(0x0)) + var x189 uint64 + var x190 uint64 + x189, x190 = bits.Add64(x164, x180, uint64(sm2p256Uint1(x188))) + var x191 uint64 + var x192 uint64 + x191, x192 = bits.Add64(x166, x182, uint64(sm2p256Uint1(x190))) + var x193 uint64 + var x194 uint64 + x193, x194 = bits.Add64(x168, x184, uint64(sm2p256Uint1(x192))) + var x195 uint64 + var x196 uint64 + x195, x196 = bits.Add64(x170, x186, uint64(sm2p256Uint1(x194))) + x197 := (uint64(sm2p256Uint1(x196)) + uint64(sm2p256Uint1(x171))) + var x198 uint64 + var x199 uint64 + x198, x199 = bits.Sub64(x189, 0xffffffffffffffff, uint64(0x0)) + var x200 uint64 + var x201 uint64 + x200, x201 = bits.Sub64(x191, 0xffffffff00000000, uint64(sm2p256Uint1(x199))) + var x202 uint64 + var x203 uint64 + x202, x203 = bits.Sub64(x193, 0xffffffffffffffff, uint64(sm2p256Uint1(x201))) + var x204 uint64 + var x205 uint64 + x204, x205 = bits.Sub64(x195, 0xfffffffeffffffff, uint64(sm2p256Uint1(x203))) + var x207 uint64 + _, x207 = bits.Sub64(x197, uint64(0x0), uint64(sm2p256Uint1(x205))) + var x208 uint64 + sm2p256CmovznzU64(&x208, sm2p256Uint1(x207), x198, x189) + var x209 uint64 + sm2p256CmovznzU64(&x209, sm2p256Uint1(x207), x200, x191) + var x210 uint64 + sm2p256CmovznzU64(&x210, sm2p256Uint1(x207), x202, x193) + var x211 uint64 + sm2p256CmovznzU64(&x211, sm2p256Uint1(x207), x204, x195) + out1[0] = x208 + out1[1] = x209 + out1[2] = x210 + out1[3] = x211 +} + +// sm2p256Add 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 sm2p256Add(out1 *sm2p256MontgomeryDomainFieldElement, arg1 *sm2p256MontgomeryDomainFieldElement, arg2 *sm2p256MontgomeryDomainFieldElement) { + 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(sm2p256Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(sm2p256Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(sm2p256Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(x1, 0xffffffffffffffff, uint64(0x0)) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(x3, 0xffffffff00000000, uint64(sm2p256Uint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Sub64(x5, 0xffffffffffffffff, uint64(sm2p256Uint1(x12))) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Sub64(x7, 0xfffffffeffffffff, uint64(sm2p256Uint1(x14))) + var x18 uint64 + _, x18 = bits.Sub64(uint64(sm2p256Uint1(x8)), uint64(0x0), uint64(sm2p256Uint1(x16))) + var x19 uint64 + sm2p256CmovznzU64(&x19, sm2p256Uint1(x18), x9, x1) + var x20 uint64 + sm2p256CmovznzU64(&x20, sm2p256Uint1(x18), x11, x3) + var x21 uint64 + sm2p256CmovznzU64(&x21, sm2p256Uint1(x18), x13, x5) + var x22 uint64 + sm2p256CmovznzU64(&x22, sm2p256Uint1(x18), x15, x7) + out1[0] = x19 + out1[1] = x20 + out1[2] = x21 + out1[3] = x22 +} + +// sm2p256Sub 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 sm2p256Sub(out1 *sm2p256MontgomeryDomainFieldElement, arg1 *sm2p256MontgomeryDomainFieldElement, arg2 *sm2p256MontgomeryDomainFieldElement) { + 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(sm2p256Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(sm2p256Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(sm2p256Uint1(x6))) + var x9 uint64 + sm2p256CmovznzU64(&x9, sm2p256Uint1(x8), uint64(0x0), 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x1, x9, uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x3, (x9 & 0xffffffff00000000), uint64(sm2p256Uint1(x11))) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x5, x9, uint64(sm2p256Uint1(x13))) + var x16 uint64 + x16, _ = bits.Add64(x7, (x9 & 0xfffffffeffffffff), uint64(sm2p256Uint1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +// sm2p256SetOne returns the field element one in the Montgomery domain. +// +// Postconditions: +// eval (from_montgomery out1) mod m = 1 mod m +// 0 ≤ eval out1 < m +// +func sm2p256SetOne(out1 *sm2p256MontgomeryDomainFieldElement) { + out1[0] = uint64(0x1) + out1[1] = 0xffffffff + out1[2] = uint64(0x0) + out1[3] = 0x100000000 +} + +// sm2p256FromMontgomery 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 sm2p256FromMontgomery(out1 *sm2p256NonMontgomeryDomainFieldElement, arg1 *sm2p256MontgomeryDomainFieldElement) { + x1 := arg1[0] + var x2 uint64 + var x3 uint64 + x3, x2 = bits.Mul64(x1, 0xfffffffeffffffff) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(x1, 0xffffffffffffffff) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(x1, 0xffffffff00000000) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(x1, 0xffffffffffffffff) + 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(sm2p256Uint1(x11))) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x5, x2, uint64(sm2p256Uint1(x13))) + var x17 uint64 + _, x17 = bits.Add64(x1, x8, uint64(0x0)) + var x18 uint64 + var x19 uint64 + x18, x19 = bits.Add64(uint64(0x0), x10, uint64(sm2p256Uint1(x17))) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(uint64(0x0), x12, uint64(sm2p256Uint1(x19))) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(uint64(0x0), x14, uint64(sm2p256Uint1(x21))) + var x24 uint64 + var x25 uint64 + x24, x25 = bits.Add64(x18, arg1[1], uint64(0x0)) + var x26 uint64 + var x27 uint64 + x26, x27 = bits.Add64(x20, uint64(0x0), uint64(sm2p256Uint1(x25))) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x22, uint64(0x0), uint64(sm2p256Uint1(x27))) + var x30 uint64 + var x31 uint64 + x31, x30 = bits.Mul64(x24, 0xfffffffeffffffff) + var x32 uint64 + var x33 uint64 + x33, x32 = bits.Mul64(x24, 0xffffffffffffffff) + var x34 uint64 + var x35 uint64 + x35, x34 = bits.Mul64(x24, 0xffffffff00000000) + var x36 uint64 + var x37 uint64 + x37, x36 = bits.Mul64(x24, 0xffffffffffffffff) + var x38 uint64 + var x39 uint64 + x38, x39 = bits.Add64(x37, x34, uint64(0x0)) + var x40 uint64 + var x41 uint64 + x40, x41 = bits.Add64(x35, x32, uint64(sm2p256Uint1(x39))) + var x42 uint64 + var x43 uint64 + x42, x43 = bits.Add64(x33, x30, uint64(sm2p256Uint1(x41))) + var x45 uint64 + _, x45 = bits.Add64(x24, x36, uint64(0x0)) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64(x26, x38, uint64(sm2p256Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(x28, x40, uint64(sm2p256Uint1(x47))) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64((uint64(sm2p256Uint1(x29)) + (uint64(sm2p256Uint1(x23)) + (uint64(sm2p256Uint1(x15)) + x3))), x42, uint64(sm2p256Uint1(x49))) + var x52 uint64 + var x53 uint64 + x52, x53 = bits.Add64(x46, arg1[2], uint64(0x0)) + var x54 uint64 + var x55 uint64 + x54, x55 = bits.Add64(x48, uint64(0x0), uint64(sm2p256Uint1(x53))) + var x56 uint64 + var x57 uint64 + x56, x57 = bits.Add64(x50, uint64(0x0), uint64(sm2p256Uint1(x55))) + var x58 uint64 + var x59 uint64 + x59, x58 = bits.Mul64(x52, 0xfffffffeffffffff) + var x60 uint64 + var x61 uint64 + x61, x60 = bits.Mul64(x52, 0xffffffffffffffff) + var x62 uint64 + var x63 uint64 + x63, x62 = bits.Mul64(x52, 0xffffffff00000000) + var x64 uint64 + var x65 uint64 + x65, x64 = bits.Mul64(x52, 0xffffffffffffffff) + 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(sm2p256Uint1(x67))) + var x70 uint64 + var x71 uint64 + x70, x71 = bits.Add64(x61, x58, uint64(sm2p256Uint1(x69))) + var x73 uint64 + _, x73 = bits.Add64(x52, x64, uint64(0x0)) + var x74 uint64 + var x75 uint64 + x74, x75 = bits.Add64(x54, x66, uint64(sm2p256Uint1(x73))) + var x76 uint64 + var x77 uint64 + x76, x77 = bits.Add64(x56, x68, uint64(sm2p256Uint1(x75))) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64((uint64(sm2p256Uint1(x57)) + (uint64(sm2p256Uint1(x51)) + (uint64(sm2p256Uint1(x43)) + x31))), x70, uint64(sm2p256Uint1(x77))) + var x80 uint64 + var x81 uint64 + x80, x81 = bits.Add64(x74, arg1[3], uint64(0x0)) + var x82 uint64 + var x83 uint64 + x82, x83 = bits.Add64(x76, uint64(0x0), uint64(sm2p256Uint1(x81))) + var x84 uint64 + var x85 uint64 + x84, x85 = bits.Add64(x78, uint64(0x0), uint64(sm2p256Uint1(x83))) + var x86 uint64 + var x87 uint64 + x87, x86 = bits.Mul64(x80, 0xfffffffeffffffff) + var x88 uint64 + var x89 uint64 + x89, x88 = bits.Mul64(x80, 0xffffffffffffffff) + var x90 uint64 + var x91 uint64 + x91, x90 = bits.Mul64(x80, 0xffffffff00000000) + var x92 uint64 + var x93 uint64 + x93, x92 = bits.Mul64(x80, 0xffffffffffffffff) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x93, x90, uint64(0x0)) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x91, x88, uint64(sm2p256Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x89, x86, uint64(sm2p256Uint1(x97))) + var x101 uint64 + _, x101 = bits.Add64(x80, x92, uint64(0x0)) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x82, x94, uint64(sm2p256Uint1(x101))) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(x84, x96, uint64(sm2p256Uint1(x103))) + var x106 uint64 + var x107 uint64 + x106, x107 = bits.Add64((uint64(sm2p256Uint1(x85)) + (uint64(sm2p256Uint1(x79)) + (uint64(sm2p256Uint1(x71)) + x59))), x98, uint64(sm2p256Uint1(x105))) + x108 := (uint64(sm2p256Uint1(x107)) + (uint64(sm2p256Uint1(x99)) + x87)) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Sub64(x102, 0xffffffffffffffff, uint64(0x0)) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Sub64(x104, 0xffffffff00000000, uint64(sm2p256Uint1(x110))) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Sub64(x106, 0xffffffffffffffff, uint64(sm2p256Uint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Sub64(x108, 0xfffffffeffffffff, uint64(sm2p256Uint1(x114))) + var x118 uint64 + _, x118 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(sm2p256Uint1(x116))) + var x119 uint64 + sm2p256CmovznzU64(&x119, sm2p256Uint1(x118), x109, x102) + var x120 uint64 + sm2p256CmovznzU64(&x120, sm2p256Uint1(x118), x111, x104) + var x121 uint64 + sm2p256CmovznzU64(&x121, sm2p256Uint1(x118), x113, x106) + var x122 uint64 + sm2p256CmovznzU64(&x122, sm2p256Uint1(x118), x115, x108) + out1[0] = x119 + out1[1] = x120 + out1[2] = x121 + out1[3] = x122 +} + +// sm2p256ToMontgomery 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 sm2p256ToMontgomery(out1 *sm2p256MontgomeryDomainFieldElement, arg1 *sm2p256NonMontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, 0x400000002) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, 0x100000001) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, 0x2ffffffff) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, 0x200000003) + 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(sm2p256Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(sm2p256Uint1(x16))) + var x19 uint64 + var x20 uint64 + x20, x19 = bits.Mul64(x11, 0xfffffffeffffffff) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(x11, 0xffffffffffffffff) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(x11, 0xffffffff00000000) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(x11, 0xffffffffffffffff) + 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(sm2p256Uint1(x28))) + var x31 uint64 + var x32 uint64 + x31, x32 = bits.Add64(x22, x19, uint64(sm2p256Uint1(x30))) + var x34 uint64 + _, x34 = bits.Add64(x11, x25, uint64(0x0)) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x13, x27, uint64(sm2p256Uint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x15, x29, uint64(sm2p256Uint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x17, x31, uint64(sm2p256Uint1(x38))) + var x41 uint64 + var x42 uint64 + x41, x42 = bits.Add64((uint64(sm2p256Uint1(x18)) + x6), (uint64(sm2p256Uint1(x32)) + x20), uint64(sm2p256Uint1(x40))) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, 0x400000002) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, 0x100000001) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, 0x2ffffffff) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, 0x200000003) + 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(sm2p256Uint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x46, x43, uint64(sm2p256Uint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(x35, x49, uint64(0x0)) + var x59 uint64 + var x60 uint64 + x59, x60 = bits.Add64(x37, x51, uint64(sm2p256Uint1(x58))) + var x61 uint64 + var x62 uint64 + x61, x62 = bits.Add64(x39, x53, uint64(sm2p256Uint1(x60))) + var x63 uint64 + var x64 uint64 + x63, x64 = bits.Add64(x41, x55, uint64(sm2p256Uint1(x62))) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(x57, 0xfffffffeffffffff) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(x57, 0xffffffffffffffff) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(x57, 0xffffffff00000000) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(x57, 0xffffffffffffffff) + var x73 uint64 + var x74 uint64 + x73, x74 = bits.Add64(x72, x69, uint64(0x0)) + var x75 uint64 + var x76 uint64 + x75, x76 = bits.Add64(x70, x67, uint64(sm2p256Uint1(x74))) + var x77 uint64 + var x78 uint64 + x77, x78 = bits.Add64(x68, x65, uint64(sm2p256Uint1(x76))) + var x80 uint64 + _, x80 = bits.Add64(x57, x71, uint64(0x0)) + var x81 uint64 + var x82 uint64 + x81, x82 = bits.Add64(x59, x73, uint64(sm2p256Uint1(x80))) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x61, x75, uint64(sm2p256Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x63, x77, uint64(sm2p256Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(((uint64(sm2p256Uint1(x64)) + uint64(sm2p256Uint1(x42))) + (uint64(sm2p256Uint1(x56)) + x44)), (uint64(sm2p256Uint1(x78)) + x66), uint64(sm2p256Uint1(x86))) + var x89 uint64 + var x90 uint64 + x90, x89 = bits.Mul64(x2, 0x400000002) + var x91 uint64 + var x92 uint64 + x92, x91 = bits.Mul64(x2, 0x100000001) + var x93 uint64 + var x94 uint64 + x94, x93 = bits.Mul64(x2, 0x2ffffffff) + var x95 uint64 + var x96 uint64 + x96, x95 = bits.Mul64(x2, 0x200000003) + var x97 uint64 + var x98 uint64 + x97, x98 = bits.Add64(x96, x93, uint64(0x0)) + var x99 uint64 + var x100 uint64 + x99, x100 = bits.Add64(x94, x91, uint64(sm2p256Uint1(x98))) + var x101 uint64 + var x102 uint64 + x101, x102 = bits.Add64(x92, x89, uint64(sm2p256Uint1(x100))) + var x103 uint64 + var x104 uint64 + x103, x104 = bits.Add64(x81, x95, uint64(0x0)) + var x105 uint64 + var x106 uint64 + x105, x106 = bits.Add64(x83, x97, uint64(sm2p256Uint1(x104))) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x85, x99, uint64(sm2p256Uint1(x106))) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Add64(x87, x101, uint64(sm2p256Uint1(x108))) + var x111 uint64 + var x112 uint64 + x112, x111 = bits.Mul64(x103, 0xfffffffeffffffff) + var x113 uint64 + var x114 uint64 + x114, x113 = bits.Mul64(x103, 0xffffffffffffffff) + var x115 uint64 + var x116 uint64 + x116, x115 = bits.Mul64(x103, 0xffffffff00000000) + var x117 uint64 + var x118 uint64 + x118, x117 = bits.Mul64(x103, 0xffffffffffffffff) + var x119 uint64 + var x120 uint64 + x119, x120 = bits.Add64(x118, x115, uint64(0x0)) + var x121 uint64 + var x122 uint64 + x121, x122 = bits.Add64(x116, x113, uint64(sm2p256Uint1(x120))) + var x123 uint64 + var x124 uint64 + x123, x124 = bits.Add64(x114, x111, uint64(sm2p256Uint1(x122))) + var x126 uint64 + _, x126 = bits.Add64(x103, x117, uint64(0x0)) + var x127 uint64 + var x128 uint64 + x127, x128 = bits.Add64(x105, x119, uint64(sm2p256Uint1(x126))) + var x129 uint64 + var x130 uint64 + x129, x130 = bits.Add64(x107, x121, uint64(sm2p256Uint1(x128))) + var x131 uint64 + var x132 uint64 + x131, x132 = bits.Add64(x109, x123, uint64(sm2p256Uint1(x130))) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(((uint64(sm2p256Uint1(x110)) + uint64(sm2p256Uint1(x88))) + (uint64(sm2p256Uint1(x102)) + x90)), (uint64(sm2p256Uint1(x124)) + x112), uint64(sm2p256Uint1(x132))) + var x135 uint64 + var x136 uint64 + x136, x135 = bits.Mul64(x3, 0x400000002) + var x137 uint64 + var x138 uint64 + x138, x137 = bits.Mul64(x3, 0x100000001) + var x139 uint64 + var x140 uint64 + x140, x139 = bits.Mul64(x3, 0x2ffffffff) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x3, 0x200000003) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(x142, x139, uint64(0x0)) + var x145 uint64 + var x146 uint64 + x145, x146 = bits.Add64(x140, x137, uint64(sm2p256Uint1(x144))) + var x147 uint64 + var x148 uint64 + x147, x148 = bits.Add64(x138, x135, uint64(sm2p256Uint1(x146))) + var x149 uint64 + var x150 uint64 + x149, x150 = bits.Add64(x127, x141, uint64(0x0)) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x129, x143, uint64(sm2p256Uint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x131, x145, uint64(sm2p256Uint1(x152))) + var x155 uint64 + var x156 uint64 + x155, x156 = bits.Add64(x133, x147, uint64(sm2p256Uint1(x154))) + var x157 uint64 + var x158 uint64 + x158, x157 = bits.Mul64(x149, 0xfffffffeffffffff) + var x159 uint64 + var x160 uint64 + x160, x159 = bits.Mul64(x149, 0xffffffffffffffff) + var x161 uint64 + var x162 uint64 + x162, x161 = bits.Mul64(x149, 0xffffffff00000000) + var x163 uint64 + var x164 uint64 + x164, x163 = bits.Mul64(x149, 0xffffffffffffffff) + var x165 uint64 + var x166 uint64 + x165, x166 = bits.Add64(x164, x161, uint64(0x0)) + var x167 uint64 + var x168 uint64 + x167, x168 = bits.Add64(x162, x159, uint64(sm2p256Uint1(x166))) + var x169 uint64 + var x170 uint64 + x169, x170 = bits.Add64(x160, x157, uint64(sm2p256Uint1(x168))) + var x172 uint64 + _, x172 = bits.Add64(x149, x163, uint64(0x0)) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x151, x165, uint64(sm2p256Uint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x153, x167, uint64(sm2p256Uint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x155, x169, uint64(sm2p256Uint1(x176))) + var x179 uint64 + var x180 uint64 + x179, x180 = bits.Add64(((uint64(sm2p256Uint1(x156)) + uint64(sm2p256Uint1(x134))) + (uint64(sm2p256Uint1(x148)) + x136)), (uint64(sm2p256Uint1(x170)) + x158), uint64(sm2p256Uint1(x178))) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Sub64(x173, 0xffffffffffffffff, uint64(0x0)) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Sub64(x175, 0xffffffff00000000, uint64(sm2p256Uint1(x182))) + var x185 uint64 + var x186 uint64 + x185, x186 = bits.Sub64(x177, 0xffffffffffffffff, uint64(sm2p256Uint1(x184))) + var x187 uint64 + var x188 uint64 + x187, x188 = bits.Sub64(x179, 0xfffffffeffffffff, uint64(sm2p256Uint1(x186))) + var x190 uint64 + _, x190 = bits.Sub64(uint64(sm2p256Uint1(x180)), uint64(0x0), uint64(sm2p256Uint1(x188))) + var x191 uint64 + sm2p256CmovznzU64(&x191, sm2p256Uint1(x190), x181, x173) + var x192 uint64 + sm2p256CmovznzU64(&x192, sm2p256Uint1(x190), x183, x175) + var x193 uint64 + sm2p256CmovznzU64(&x193, sm2p256Uint1(x190), x185, x177) + var x194 uint64 + sm2p256CmovznzU64(&x194, sm2p256Uint1(x190), x187, x179) + out1[0] = x191 + out1[1] = x192 + out1[2] = x193 + out1[3] = x194 +} + +// sm2p256Selectznz 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 sm2p256Selectznz(out1 *[4]uint64, arg1 sm2p256Uint1, arg2 *[4]uint64, arg3 *[4]uint64) { + var x1 uint64 + sm2p256CmovznzU64(&x1, arg1, arg2[0], arg3[0]) + var x2 uint64 + sm2p256CmovznzU64(&x2, arg1, arg2[1], arg3[1]) + var x3 uint64 + sm2p256CmovznzU64(&x3, arg1, arg2[2], arg3[2]) + var x4 uint64 + sm2p256CmovznzU64(&x4, arg1, arg2[3], arg3[3]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +// sm2p256ToBytes 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..31] +// +// Input Bounds: +// arg1: [[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]] +func sm2p256ToBytes(out1 *[32]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 := (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 := uint8((x58 >> 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] = x53 + out1[28] = x55 + out1[29] = x57 + out1[30] = x59 + out1[31] = x60 +} + +// sm2p256FromBytes 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]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func sm2p256FromBytes(out1 *[4]uint64, arg1 *[32]uint8) { + x1 := (uint64(arg1[31]) << 56) + x2 := (uint64(arg1[30]) << 48) + x3 := (uint64(arg1[29]) << 40) + x4 := (uint64(arg1[28]) << 32) + x5 := (uint64(arg1[27]) << 24) + x6 := (uint64(arg1[26]) << 16) + x7 := (uint64(arg1[25]) << 8) + x8 := arg1[24] + x9 := (uint64(arg1[23]) << 56) + x10 := (uint64(arg1[22]) << 48) + x11 := (uint64(arg1[21]) << 40) + x12 := (uint64(arg1[20]) << 32) + x13 := (uint64(arg1[19]) << 24) + x14 := (uint64(arg1[18]) << 16) + x15 := (uint64(arg1[17]) << 8) + x16 := arg1[16] + x17 := (uint64(arg1[15]) << 56) + x18 := (uint64(arg1[14]) << 48) + x19 := (uint64(arg1[13]) << 40) + x20 := (uint64(arg1[12]) << 32) + x21 := (uint64(arg1[11]) << 24) + x22 := (uint64(arg1[10]) << 16) + x23 := (uint64(arg1[9]) << 8) + x24 := arg1[8] + x25 := (uint64(arg1[7]) << 56) + x26 := (uint64(arg1[6]) << 48) + x27 := (uint64(arg1[5]) << 40) + x28 := (uint64(arg1[4]) << 32) + x29 := (uint64(arg1[3]) << 24) + x30 := (uint64(arg1[2]) << 16) + x31 := (uint64(arg1[1]) << 8) + x32 := arg1[0] + x33 := (x31 + uint64(x32)) + x34 := (x30 + x33) + x35 := (x29 + x34) + x36 := (x28 + x35) + x37 := (x27 + x36) + x38 := (x26 + x37) + x39 := (x25 + x38) + x40 := (x23 + uint64(x24)) + x41 := (x22 + x40) + x42 := (x21 + x41) + x43 := (x20 + x42) + x44 := (x19 + x43) + x45 := (x18 + x44) + x46 := (x17 + x45) + x47 := (x15 + uint64(x16)) + x48 := (x14 + x47) + x49 := (x13 + x48) + x50 := (x12 + x49) + x51 := (x11 + x50) + x52 := (x10 + x51) + x53 := (x9 + x52) + x54 := (x7 + uint64(x8)) + x55 := (x6 + x54) + x56 := (x5 + x55) + x57 := (x4 + x56) + x58 := (x3 + x57) + x59 := (x2 + x58) + x60 := (x1 + x59) + out1[0] = x39 + out1[1] = x46 + out1[2] = x53 + out1[3] = x60 +} diff --git a/internal/sm2ec/fiat/sm2p256_invert.go b/internal/sm2ec/fiat/sm2p256_invert.go new file mode 100644 index 0000000..eef510e --- /dev/null +++ b/internal/sm2ec/fiat/sm2p256_invert.go @@ -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. +// 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 *SM2P256Element) Invert(x *SM2P256Element) *SM2P256Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of 14 multiplications and 255 squarings is derived from the + // following addition chain generated with github.com/mmcloughlin/addchain v0.4.0. + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // _1111110 = 2*_111111 + // _1111111 = 1 + _1111110 + // x12 = _1111110 << 5 + _111111 + // x24 = x12 << 12 + x12 + // x31 = x24 << 7 + _1111111 + // i39 = x31 << 2 + // i68 = i39 << 29 + // x62 = x31 + i68 + // i71 = i68 << 2 + // x64 = i39 + i71 + _11 + // i265 = ((i71 << 32 + x64) << 64 + x64) << 94 + // return (x62 + i265) << 2 + 1 + // + var z = new(SM2P256Element).Set(e) + var t0 = new(SM2P256Element) + var t1 = new(SM2P256Element) + var t2 = new(SM2P256Element) + + 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) + z.Mul(x, t2) + for s := 0; s < 5; s++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + t2.Square(t1) + for s := 1; s < 12; s++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + for s := 0; s < 7; s++ { + t1.Square(t1) + } + z.Mul(z, t1) + t2.Square(z) + for s := 1; s < 2; s++ { + t2.Square(t2) + } + t1.Square(t2) + for s := 1; s < 29; s++ { + t1.Square(t1) + } + z.Mul(z, t1) + for s := 0; s < 2; s++ { + t1.Square(t1) + } + t2.Mul(t2, t1) + t0.Mul(t0, t2) + for s := 0; s < 32; s++ { + t1.Square(t1) + } + t1.Mul(t0, t1) + for s := 0; s < 64; 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) +} diff --git a/internal/sm2ec/generate.go b/internal/sm2ec/generate.go new file mode 100644 index 0000000..7c9a5b6 --- /dev/null +++ b/internal/sm2ec/generate.go @@ -0,0 +1,552 @@ +// Copyright 2022 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 +// +build ignore + +package main + +// Running this generator requires addchain v0.4.0, which can be installed with +// +// go install github.com/mmcloughlin/addchain/cmd/addchain@v0.4.0 +// + +import ( + "bytes" + "crypto/elliptic" + "fmt" + "go/format" + "io" + "log" + "math/big" + "os" + "os/exec" + "strings" + "text/template" +) + +var curves = []struct { + P string + Element string + Params *elliptic.CurveParams + BuildTags string +}{ + { + P: "SM2P256", + Element: "fiat.SM2P256Element", + Params: &elliptic.CurveParams{ + Name: "sm2p256v1", + BitSize: 256, + P: bigFromHex("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"), + N: bigFromHex("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"), + B: bigFromHex("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"), + Gx: bigFromHex("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"), + Gy: bigFromHex("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"), + }, + BuildTags: "", + }, +} + +func main() { + t := template.Must(template.New("tmplNISTEC").Parse(tmplNISTEC)) + + 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 { + p := strings.ToLower(c.P) + elementLen := (c.Params.BitSize + 7) / 8 + B := fmt.Sprintf("%#v", c.Params.B.FillBytes(make([]byte, elementLen))) + G := fmt.Sprintf("%#v", elliptic.Marshal(c.Params, c.Params.Gx, c.Params.Gy)) + + log.Printf("Generating %s.go...", p) + f, err := os.Create(p + ".go") + if err != nil { + log.Fatal(err) + } + defer f.Close() + buf := &bytes.Buffer{} + if err := t.Execute(buf, map[string]interface{}{ + "P": c.P, "p": p, "B": B, "G": G, + "Element": c.Element, "ElementLen": elementLen, + "BuildTags": c.BuildTags, + }); err != nil { + log.Fatal(err) + } + out, err := format.Source(buf.Bytes()) + if err != nil { + log.Fatal(err) + } + if _, err := f.Write(out); err != nil { + log.Fatal(err) + } + + // If p = 3 mod 4, implement modular square root by exponentiation. + mod4 := new(big.Int).Mod(c.Params.P, big.NewInt(4)) + if mod4.Cmp(big.NewInt(3)) != 0 { + continue + } + + exp := new(big.Int).Add(c.Params.P, big.NewInt(1)) + exp.Div(exp, big.NewInt(4)) + + tmp, err := os.CreateTemp("", "addchain-"+p) + if err != nil { + log.Fatal(err) + } + defer os.Remove(tmp.Name()) + cmd := exec.Command("addchain", "search", fmt.Sprintf("%d", exp)) + cmd.Stderr = os.Stderr + cmd.Stdout = tmp + if err := cmd.Run(); err != nil { + log.Fatal(err) + } + if err := tmp.Close(); err != nil { + log.Fatal(err) + } + cmd = exec.Command("addchain", "gen", "-tmpl", tmplAddchainFile.Name(), tmp.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 = bytes.Replace(out, []byte("sqrtCandidate"), []byte(p+"SqrtCandidate"), -1) + out, err = format.Source(out) + if err != nil { + log.Fatal(err) + } + if _, err := f.Write(out); err != nil { + log.Fatal(err) + } + } +} + +const tmplNISTEC = `// Copyright 2022 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. +{{ if .BuildTags }} +//go:build {{ .BuildTags }} +// +build {{ .BuildTags }} +{{ end }} +package sm2ec +import ( + "github.com/emmansun/gmsm/sm2ec/fiat" + "crypto/subtle" + "errors" + "sync" +) +var {{.p}}B, _ = new({{.Element}}).SetBytes({{.B}}) +var {{.p}}G, _ = New{{.P}}Point().SetBytes({{.G}}) +// {{.p}}ElementLength is the length of an element of the base or scalar field, +// which have the same bytes length for all NIST P curves. +const {{.p}}ElementLength = {{ .ElementLen }} +// {{.P}}Point is a {{.P}} point. The zero value is NOT valid. +type {{.P}}Point struct { + // The point is represented in projective coordinates (X:Y:Z), + // where x = X/Z and y = Y/Z. + x, y, z *{{.Element}} +} +// New{{.P}}Point returns a new {{.P}}Point representing the point at infinity point. +func New{{.P}}Point() *{{.P}}Point { + return &{{.P}}Point{ + x: new({{.Element}}), + y: new({{.Element}}).One(), + z: new({{.Element}}), + } +} +// New{{.P}}Generator returns a new {{.P}}Point set to the canonical generator. +func New{{.P}}Generator() *{{.P}}Point { + return (&{{.P}}Point{ + x: new({{.Element}}), + y: new({{.Element}}), + z: new({{.Element}}), + }).Set({{.p}}G) +} +// Set sets p = q and returns p. +func (p *{{.P}}Point) Set(q *{{.P}}Point) *{{.P}}Point { + 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 *{{.P}}Point) SetBytes(b []byte) (*{{.P}}Point, error) { + switch { + // Point at infinity. + case len(b) == 1 && b[0] == 0: + return p.Set(New{{.P}}Point()), nil + // Uncompressed form. + case len(b) == 1+2*{{.p}}ElementLength && b[0] == 4: + x, err := new({{.Element}}).SetBytes(b[1 : 1+{{.p}}ElementLength]) + if err != nil { + return nil, err + } + y, err := new({{.Element}}).SetBytes(b[1+{{.p}}ElementLength:]) + if err != nil { + return nil, err + } + if err := {{.p}}CheckOnCurve(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+{{.p}}ElementLength && (b[0] == 2 || b[0] == 3): + x, err := new({{.Element}}).SetBytes(b[1:]) + if err != nil { + return nil, err + } + // y² = x³ - 3x + b + y := {{.p}}Polynomial(new({{.Element}}), x) + if !{{.p}}Sqrt(y, y) { + return nil, errors.New("invalid {{.P}} compressed point encoding") + } + // Select the positive or negative root, as indicated by the least + // significant bit, based on the encoding type byte. + otherRoot := new({{.Element}}) + otherRoot.Sub(otherRoot, y) + cond := y.Bytes()[{{.p}}ElementLength-1]&1 ^ b[0]&1 + y.Select(otherRoot, y, int(cond)) + p.x.Set(x) + p.y.Set(y) + p.z.One() + return p, nil + default: + return nil, errors.New("invalid {{.P}} point encoding") + } +} +// {{.p}}Polynomial sets y2 to x³ - 3x + b, and returns y2. +func {{.p}}Polynomial(y2, x *{{.Element}}) *{{.Element}} { + y2.Square(x) + y2.Mul(y2, x) + threeX := new({{.Element}}).Add(x, x) + threeX.Add(threeX, x) + y2.Sub(y2, threeX) + return y2.Add(y2, {{.p}}B) +} +func {{.p}}CheckOnCurve(x, y *{{.Element}}) error { + // y² = x³ - 3x + b + rhs := {{.p}}Polynomial(new({{.Element}}), x) + lhs := new({{.Element}}).Square(y) + if rhs.Equal(lhs) != 1 { + return errors.New("{{.P}} 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 *{{.P}}Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [1+2*{{.p}}ElementLength]byte + return p.bytes(&out) +} +func (p *{{.P}}Point) bytes(out *[1+2*{{.p}}ElementLength]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + zinv := new({{.Element}}).Invert(p.z) + x := new({{.Element}}).Mul(p.x, zinv) + y := new({{.Element}}).Mul(p.y, zinv) + buf := append(out[:0], 4) + buf = append(buf, x.Bytes()...) + buf = append(buf, y.Bytes()...) + return buf +} +// BytesCompressed returns the compressed 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 *{{.P}}Point) BytesCompressed() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [1 + {{.p}}ElementLength]byte + return p.bytesCompressed(&out) +} +func (p *{{.P}}Point) bytesCompressed(out *[1 + {{.p}}ElementLength]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + zinv := new({{.Element}}).Invert(p.z) + x := new({{.Element}}).Mul(p.x, zinv) + y := new({{.Element}}).Mul(p.y, zinv) + // Encode the sign of the y coordinate (indicated by the least significant + // bit) as the encoding type (2 or 3). + buf := append(out[:0], 2) + buf[0] |= y.Bytes()[{{.p}}ElementLength-1] & 1 + buf = append(buf, x.Bytes()...) + return buf +} +// Add sets q = p1 + p2, and returns q. The points may overlap. +func (q *{{.P}}Point) Add(p1, p2 *{{.P}}Point) *{{.P}}Point { + // 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({{.Element}}).Mul(p1.x, p2.x) // t0 := X1 * X2 + t1 := new({{.Element}}).Mul(p1.y, p2.y) // t1 := Y1 * Y2 + t2 := new({{.Element}}).Mul(p1.z, p2.z) // t2 := Z1 * Z2 + t3 := new({{.Element}}).Add(p1.x, p1.y) // t3 := X1 + Y1 + t4 := new({{.Element}}).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({{.Element}}).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({{.Element}}).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({{.Element}}).Mul({{.p}}B, 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({{.p}}B, 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 *{{.P}}Point) Double(p *{{.P}}Point) *{{.P}}Point { + // 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({{.Element}}).Square(p.x) // t0 := X ^ 2 + t1 := new({{.Element}}).Square(p.y) // t1 := Y ^ 2 + t2 := new({{.Element}}).Square(p.z) // t2 := Z ^ 2 + t3 := new({{.Element}}).Mul(p.x, p.y) // t3 := X * Y + t3.Add(t3, t3) // t3 := t3 + t3 + z3 := new({{.Element}}).Mul(p.x, p.z) // Z3 := X * Z + z3.Add(z3, z3) // Z3 := Z3 + Z3 + y3 := new({{.Element}}).Mul({{.p}}B, t2) // Y3 := b * t2 + y3.Sub(y3, z3) // Y3 := Y3 - Z3 + x3 := new({{.Element}}).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({{.p}}B, 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 *{{.P}}Point) Select(p1, p2 *{{.P}}Point, cond int) *{{.P}}Point { + 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 +} +// A {{.p}}Table holds the first 15 multiples of a point at offset -1, so [1]P +// is at table[0], [15]P is at table[14], and [0]P is implicitly the identity +// point. +type {{.p}}Table [15]*{{.P}}Point +// Select selects the n-th multiple of the table base point into p. It works in +// constant time by iterating over every entry of the table. n must be in [0, 15]. +func (table *{{.p}}Table) Select(p *{{.P}}Point, n uint8) { + if n >= 16 { + panic("nistec: internal error: {{.p}}Table called with out-of-bounds value") + } + p.Set(New{{.P}}Point()) + for i := uint8(1); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(i, n) + p.Select(table[i-1], p, cond) + } +} +// ScalarMult sets p = scalar * q, and returns p. +func (p *{{.P}}Point) ScalarMult(q *{{.P}}Point, scalar []byte) (*{{.P}}Point, error) { + // Compute a {{.p}}Table for the base point q. The explicit New{{.P}}Point + // calls get inlined, letting the allocations live on the stack. + var table = {{.p}}Table{New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(), + New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(), + New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(), + New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point()} + table[0].Set(q) + for i := 1; i < 15; i += 2 { + table[i].Double(table[i/2]) + table[i+1].Add(table[i], 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 := New{{.P}}Point() + p.Set(New{{.P}}Point()) + for i, byte := range scalar { + // No need to double on the first iteration, as p is the identity at + // this point, and [N]∞ = ∞. + if i != 0 { + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + } + windowValue := byte >> 4 + table.Select(t, windowValue) + p.Add(p, t) + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + windowValue = byte & 0b1111 + table.Select(t, windowValue) + p.Add(p, t) + } + return p, nil +} +var {{.p}}GeneratorTable *[{{.p}}ElementLength * 2]{{.p}}Table +var {{.p}}GeneratorTableOnce sync.Once +// generatorTable returns a sequence of {{.p}}Tables. The first table contains +// multiples of G. Each successive table is the previous table doubled four +// times. +func (p *{{.P}}Point) generatorTable() *[{{.p}}ElementLength * 2]{{.p}}Table { + {{.p}}GeneratorTableOnce.Do(func() { + {{.p}}GeneratorTable = new([{{.p}}ElementLength * 2]{{.p}}Table) + base := New{{.P}}Generator() + for i := 0; i < {{.p}}ElementLength*2; i++ { + {{.p}}GeneratorTable[i][0] = New{{.P}}Point().Set(base) + for j := 1; j < 15; j++ { + {{.p}}GeneratorTable[i][j] = New{{.P}}Point().Add({{.p}}GeneratorTable[i][j-1], base) + } + base.Double(base) + base.Double(base) + base.Double(base) + base.Double(base) + } + }) + return {{.p}}GeneratorTable +} +// ScalarBaseMult sets p = scalar * B, where B is the canonical generator, and +// returns p. +func (p *{{.P}}Point) ScalarBaseMult(scalar []byte) (*{{.P}}Point, error) { + if len(scalar) != {{.p}}ElementLength { + return nil, errors.New("invalid scalar length") + } + tables := p.generatorTable() + // This is also a scalar multiplication with a four-bit window like in + // ScalarMult, but in this case the doublings are precomputed. The value + // [windowValue]G added at iteration k would normally get doubled + // (totIterations-k)×4 times, but with a larger precomputation we can + // instead add [2^((totIterations-k)×4)][windowValue]G and avoid the + // doublings between iterations. + t := New{{.P}}Point() + p.Set(New{{.P}}Point()) + tableIndex := len(tables) - 1 + for _, byte := range scalar { + windowValue := byte >> 4 + tables[tableIndex].Select(t, windowValue) + p.Add(p, t) + tableIndex-- + windowValue = byte & 0b1111 + tables[tableIndex].Select(t, windowValue) + p.Add(p, t) + tableIndex-- + } + return p, nil +} +// {{.p}}Sqrt sets e to a square root of x. If x is not a square, {{.p}}Sqrt returns +// false and e is unchanged. e and x can overlap. +func {{.p}}Sqrt(e, x *{{ .Element }}) (isSquare bool) { + candidate := new({{ .Element }}) + {{.p}}SqrtCandidate(candidate, x) + square := new({{ .Element }}).Square(candidate) + if square.Equal(x) != 1 { + return false + } + e.Set(candidate) + return true +} +` + +const tmplAddchain = ` +// sqrtCandidate sets z to a square root candidate for x. z and x must not overlap. +func sqrtCandidate(z, x *Element) { + // Since p = 3 mod 4, exponentiation by (p + 1) / 4 yields a square root candidate. + // + // 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 }} + // + {{- 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 }} +} +` diff --git a/internal/sm2ec/sm2ec.go b/internal/sm2ec/sm2ec.go new file mode 100644 index 0000000..f5e0d17 --- /dev/null +++ b/internal/sm2ec/sm2ec.go @@ -0,0 +1,11 @@ +// Package sm2ec implements the SM2 Prime elliptic curves. +// +// This package uses fiat-crypto or specialized assembly and Go code for its +// backend field arithmetic (not math/big) and exposes constant-time, heap +// allocation-free, byte slice-based safe APIs. Group operations use modern and +// safe complete addition formulas where possible. The point at infinity is +// handled and encoded according to SEC 1, Version 2.0, and invalid curve points +// can't be represented. +package sm2ec + +//go:generate go run generate.go \ No newline at end of file diff --git a/internal/sm2ec/sm2ec_test.go b/internal/sm2ec/sm2ec_test.go new file mode 100644 index 0000000..20b35f4 --- /dev/null +++ b/internal/sm2ec/sm2ec_test.go @@ -0,0 +1,157 @@ +package sm2ec + +import ( + "encoding/hex" + "math/big" + "testing" +) + +// r = 2^256 +var r = bigFromHex("010000000000000000000000000000000000000000000000000000000000000000") +var r0 = bigFromHex("010000000000000000") +var sm2Prime = bigFromHex("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF") +var sm2n = bigFromHex("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123") +var nistP256Prime = bigFromDecimal("115792089210356248762697446949407573530086143415290314195533631308867097853951") + +func generateMontgomeryDomain(in *big.Int, p *big.Int) *big.Int { + tmp := new(big.Int) + tmp = tmp.Mul(in, r) + return tmp.Mod(tmp, p) +} + +func bigFromHex(s string) *big.Int { + b, ok := new(big.Int).SetString(s, 16) + if !ok { + panic("sm2ec: internal error: invalid encoding") + } + return b +} + +func bigFromDecimal(s string) *big.Int { + b, ok := new(big.Int).SetString(s, 10) + if !ok { + panic("sm2ec: internal error: invalid encoding") + } + return b +} + +func TestSM2P256MontgomeryDomain(t *testing.T) { + tests := []struct { + in string + out string + }{ + { // One + "01", + "0000000100000000000000000000000000000000ffffffff0000000000000001", + }, + { // Gx + "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", + "91167a5ee1c13b05d6a1ed99ac24c3c33e7981eddca6c05061328990f418029e", + }, + { // Gy + "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", + "63cd65d481d735bd8d4cfb066e2a48f8c1f5e5788d3295fac1354e593c2d0ddd", + }, + { // B + "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", + "240fe188ba20e2c8527981505ea51c3c71cf379ae9b537ab90d230632bc0dd42", + }, + { // R + "010000000000000000000000000000000000000000000000000000000000000000", + "0400000002000000010000000100000002ffffffff0000000200000003", + }, + } + for _, test := range tests { + out := generateMontgomeryDomain(bigFromHex(test.in), sm2Prime) + if out.Cmp(bigFromHex(test.out)) != 0 { + t.Errorf("expected %v, got %v", test.out, hex.EncodeToString(out.Bytes())) + } + } +} + +func TestSM2P256MontgomeryDomainN(t *testing.T) { + tests := []struct { + in string + out string + }{ + { // R + "010000000000000000000000000000000000000000000000000000000000000000", + "1eb5e412a22b3d3b620fc84c3affe0d43464504ade6fa2fa901192af7c114f20", + }, + } + for _, test := range tests { + out := generateMontgomeryDomain(bigFromHex(test.in), sm2n) + if out.Cmp(bigFromHex(test.out)) != 0 { + t.Errorf("expected %v, got %v", test.out, hex.EncodeToString(out.Bytes())) + } + } +} + +func TestSM2P256MontgomeryK0(t *testing.T) { + tests := []struct { + in *big.Int + out string + }{ + { + sm2n, + "327f9e8872350975", + }, + { + sm2Prime, + "0000000000000001", + }, + } + for _, test := range tests { + // k0 = -in^(-1) mod 2^64 + k0 := new(big.Int).ModInverse(test.in, r0) + k0.Neg(k0) + k0.Mod(k0, r0) + if k0.Cmp(bigFromHex(test.out)) != 0 { + t.Errorf("expected %v, got %v", test.out, hex.EncodeToString(k0.Bytes())) + } + } +} + +func TestNISTP256MontgomeryDomain(t *testing.T) { + tests := []struct { + in string + out string + }{ + { // One + "01", + "fffffffeffffffffffffffffffffffff000000000000000000000001", + }, + { // Gx + "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c", + }, + { // Gy + "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "8571ff1825885d85d2e88688dd21f3258b4ab8e4ba19e45cddf25357ce95560a", + }, + { // B + "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + "dc30061d04874834e5a220abf7212ed6acf005cd78843090d89cdf6229c4bddf", + }, + { // R + "010000000000000000000000000000000000000000000000000000000000000000", + "04fffffffdfffffffffffffffefffffffbffffffff0000000000000003", + }, + } + for _, test := range tests { + out := generateMontgomeryDomain(bigFromHex(test.in), nistP256Prime) + if out.Cmp(bigFromHex(test.out)) != 0 { + t.Errorf("expected %v, got %v", test.out, hex.EncodeToString(out.Bytes())) + } + } +} + +func TestForSqrt(t *testing.T) { + mod4 := new(big.Int).Mod(sm2Prime, big.NewInt(4)) + if mod4.Cmp(big.NewInt(3)) != 0 { + t.Fatal("sm2 prime is not fufill 3 mod 4") + } + + exp := new(big.Int).Add(sm2Prime, big.NewInt(1)) + exp.Div(exp, big.NewInt(4)) +} diff --git a/internal/sm2ec/sm2p256.go b/internal/sm2ec/sm2p256.go new file mode 100644 index 0000000..53ece0e --- /dev/null +++ b/internal/sm2ec/sm2p256.go @@ -0,0 +1,485 @@ +// Copyright 2022 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. +//go:build !amd64 && !arm64 || generic +// +build !amd64,!arm64 generic + +package sm2ec + +import ( + "crypto/subtle" + "errors" + "github.com/emmansun/gmsm/sm2ec/fiat" + "sync" +) + +var sm2p256B, _ = new(fiat.SM2P256Element).SetBytes([]byte{0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b, 0xcf, 0x65, 0x9, 0xa7, 0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92, 0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0xe, 0x93}) +var sm2p256G, _ = NewSM2P256Point().SetBytes([]byte{0x4, 0x32, 0xc4, 0xae, 0x2c, 0x1f, 0x19, 0x81, 0x19, 0x5f, 0x99, 0x4, 0x46, 0x6a, 0x39, 0xc9, 0x94, 0x8f, 0xe3, 0xb, 0xbf, 0xf2, 0x66, 0xb, 0xe1, 0x71, 0x5a, 0x45, 0x89, 0x33, 0x4c, 0x74, 0xc7, 0xbc, 0x37, 0x36, 0xa2, 0xf4, 0xf6, 0x77, 0x9c, 0x59, 0xbd, 0xce, 0xe3, 0x6b, 0x69, 0x21, 0x53, 0xd0, 0xa9, 0x87, 0x7c, 0xc6, 0x2a, 0x47, 0x40, 0x2, 0xdf, 0x32, 0xe5, 0x21, 0x39, 0xf0, 0xa0}) + +// sm2p256ElementLength is the length of an element of the base or scalar field, +// which have the same bytes length for all NIST P curves. +const sm2p256ElementLength = 32 + +// SM2P256Point is a SM2P256 point. The zero value is NOT valid. +type SM2P256Point struct { + // The point is represented in projective coordinates (X:Y:Z), + // where x = X/Z and y = Y/Z. + x, y, z *fiat.SM2P256Element +} + +// NewSM2P256Point returns a new SM2P256Point representing the point at infinity point. +func NewSM2P256Point() *SM2P256Point { + return &SM2P256Point{ + x: new(fiat.SM2P256Element), + y: new(fiat.SM2P256Element).One(), + z: new(fiat.SM2P256Element), + } +} + +// NewSM2P256Generator returns a new SM2P256Point set to the canonical generator. +func NewSM2P256Generator() *SM2P256Point { + return (&SM2P256Point{ + x: new(fiat.SM2P256Element), + y: new(fiat.SM2P256Element), + z: new(fiat.SM2P256Element), + }).Set(sm2p256G) +} + +// Set sets p = q and returns p. +func (p *SM2P256Point) Set(q *SM2P256Point) *SM2P256Point { + 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 *SM2P256Point) SetBytes(b []byte) (*SM2P256Point, error) { + switch { + // Point at infinity. + case len(b) == 1 && b[0] == 0: + return p.Set(NewSM2P256Point()), nil + // Uncompressed form. + case len(b) == 1+2*sm2p256ElementLength && b[0] == 4: + x, err := new(fiat.SM2P256Element).SetBytes(b[1 : 1+sm2p256ElementLength]) + if err != nil { + return nil, err + } + y, err := new(fiat.SM2P256Element).SetBytes(b[1+sm2p256ElementLength:]) + if err != nil { + return nil, err + } + if err := sm2p256CheckOnCurve(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+sm2p256ElementLength && (b[0] == 2 || b[0] == 3): + x, err := new(fiat.SM2P256Element).SetBytes(b[1:]) + if err != nil { + return nil, err + } + // y² = x³ - 3x + b + y := sm2p256Polynomial(new(fiat.SM2P256Element), x) + if !sm2p256Sqrt(y, y) { + return nil, errors.New("invalid SM2P256 compressed point encoding") + } + // Select the positive or negative root, as indicated by the least + // significant bit, based on the encoding type byte. + otherRoot := new(fiat.SM2P256Element) + otherRoot.Sub(otherRoot, y) + cond := y.Bytes()[sm2p256ElementLength-1]&1 ^ b[0]&1 + y.Select(otherRoot, y, int(cond)) + p.x.Set(x) + p.y.Set(y) + p.z.One() + return p, nil + default: + return nil, errors.New("invalid SM2P256 point encoding") + } +} + +// sm2p256Polynomial sets y2 to x³ - 3x + b, and returns y2. +func sm2p256Polynomial(y2, x *fiat.SM2P256Element) *fiat.SM2P256Element { + y2.Square(x) + y2.Mul(y2, x) + threeX := new(fiat.SM2P256Element).Add(x, x) + threeX.Add(threeX, x) + y2.Sub(y2, threeX) + return y2.Add(y2, sm2p256B) +} +func sm2p256CheckOnCurve(x, y *fiat.SM2P256Element) error { + // y² = x³ - 3x + b + rhs := sm2p256Polynomial(new(fiat.SM2P256Element), x) + lhs := new(fiat.SM2P256Element).Square(y) + if rhs.Equal(lhs) != 1 { + return errors.New("SM2P256 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 *SM2P256Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [1 + 2*sm2p256ElementLength]byte + return p.bytes(&out) +} +func (p *SM2P256Point) bytes(out *[1 + 2*sm2p256ElementLength]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + zinv := new(fiat.SM2P256Element).Invert(p.z) + x := new(fiat.SM2P256Element).Mul(p.x, zinv) + y := new(fiat.SM2P256Element).Mul(p.y, zinv) + buf := append(out[:0], 4) + buf = append(buf, x.Bytes()...) + buf = append(buf, y.Bytes()...) + return buf +} + +// BytesCompressed returns the compressed 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 *SM2P256Point) BytesCompressed() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [1 + sm2p256ElementLength]byte + return p.bytesCompressed(&out) +} +func (p *SM2P256Point) bytesCompressed(out *[1 + sm2p256ElementLength]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + zinv := new(fiat.SM2P256Element).Invert(p.z) + x := new(fiat.SM2P256Element).Mul(p.x, zinv) + y := new(fiat.SM2P256Element).Mul(p.y, zinv) + // Encode the sign of the y coordinate (indicated by the least significant + // bit) as the encoding type (2 or 3). + buf := append(out[:0], 2) + buf[0] |= y.Bytes()[sm2p256ElementLength-1] & 1 + buf = append(buf, x.Bytes()...) + return buf +} + +// Add sets q = p1 + p2, and returns q. The points may overlap. +func (q *SM2P256Point) Add(p1, p2 *SM2P256Point) *SM2P256Point { + // 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.SM2P256Element).Mul(p1.x, p2.x) // t0 := X1 * X2 + t1 := new(fiat.SM2P256Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2 + t2 := new(fiat.SM2P256Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2 + t3 := new(fiat.SM2P256Element).Add(p1.x, p1.y) // t3 := X1 + Y1 + t4 := new(fiat.SM2P256Element).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.SM2P256Element).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.SM2P256Element).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.SM2P256Element).Mul(sm2p256B, 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(sm2p256B, 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 *SM2P256Point) Double(p *SM2P256Point) *SM2P256Point { + // 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.SM2P256Element).Square(p.x) // t0 := X ^ 2 + t1 := new(fiat.SM2P256Element).Square(p.y) // t1 := Y ^ 2 + t2 := new(fiat.SM2P256Element).Square(p.z) // t2 := Z ^ 2 + t3 := new(fiat.SM2P256Element).Mul(p.x, p.y) // t3 := X * Y + t3.Add(t3, t3) // t3 := t3 + t3 + z3 := new(fiat.SM2P256Element).Mul(p.x, p.z) // Z3 := X * Z + z3.Add(z3, z3) // Z3 := Z3 + Z3 + y3 := new(fiat.SM2P256Element).Mul(sm2p256B, t2) // Y3 := b * t2 + y3.Sub(y3, z3) // Y3 := Y3 - Z3 + x3 := new(fiat.SM2P256Element).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(sm2p256B, 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 *SM2P256Point) Select(p1, p2 *SM2P256Point, cond int) *SM2P256Point { + 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 +} + +// A sm2p256Table holds the first 15 multiples of a point at offset -1, so [1]P +// is at table[0], [15]P is at table[14], and [0]P is implicitly the identity +// point. +type sm2p256Table [15]*SM2P256Point + +// Select selects the n-th multiple of the table base point into p. It works in +// constant time by iterating over every entry of the table. n must be in [0, 15]. +func (table *sm2p256Table) Select(p *SM2P256Point, n uint8) { + if n >= 16 { + panic("nistec: internal error: sm2p256Table called with out-of-bounds value") + } + p.Set(NewSM2P256Point()) + for i := uint8(1); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(i, n) + p.Select(table[i-1], p, cond) + } +} + +// ScalarMult sets p = scalar * q, and returns p. +func (p *SM2P256Point) ScalarMult(q *SM2P256Point, scalar []byte) (*SM2P256Point, error) { + // Compute a sm2p256Table for the base point q. The explicit NewSM2P256Point + // calls get inlined, letting the allocations live on the stack. + var table = sm2p256Table{NewSM2P256Point(), NewSM2P256Point(), NewSM2P256Point(), + NewSM2P256Point(), NewSM2P256Point(), NewSM2P256Point(), NewSM2P256Point(), + NewSM2P256Point(), NewSM2P256Point(), NewSM2P256Point(), NewSM2P256Point(), + NewSM2P256Point(), NewSM2P256Point(), NewSM2P256Point(), NewSM2P256Point()} + table[0].Set(q) + for i := 1; i < 15; i += 2 { + table[i].Double(table[i/2]) + table[i+1].Add(table[i], 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 := NewSM2P256Point() + p.Set(NewSM2P256Point()) + for i, byte := range scalar { + // No need to double on the first iteration, as p is the identity at + // this point, and [N]∞ = ∞. + if i != 0 { + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + } + windowValue := byte >> 4 + table.Select(t, windowValue) + p.Add(p, t) + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + windowValue = byte & 0b1111 + table.Select(t, windowValue) + p.Add(p, t) + } + return p, nil +} + +var sm2p256GeneratorTable *[sm2p256ElementLength * 2]sm2p256Table +var sm2p256GeneratorTableOnce sync.Once + +// generatorTable returns a sequence of sm2p256Tables. The first table contains +// multiples of G. Each successive table is the previous table doubled four +// times. +func (p *SM2P256Point) generatorTable() *[sm2p256ElementLength * 2]sm2p256Table { + sm2p256GeneratorTableOnce.Do(func() { + sm2p256GeneratorTable = new([sm2p256ElementLength * 2]sm2p256Table) + base := NewSM2P256Generator() + for i := 0; i < sm2p256ElementLength*2; i++ { + sm2p256GeneratorTable[i][0] = NewSM2P256Point().Set(base) + for j := 1; j < 15; j++ { + sm2p256GeneratorTable[i][j] = NewSM2P256Point().Add(sm2p256GeneratorTable[i][j-1], base) + } + base.Double(base) + base.Double(base) + base.Double(base) + base.Double(base) + } + }) + return sm2p256GeneratorTable +} + +// ScalarBaseMult sets p = scalar * B, where B is the canonical generator, and +// returns p. +func (p *SM2P256Point) ScalarBaseMult(scalar []byte) (*SM2P256Point, error) { + if len(scalar) != sm2p256ElementLength { + return nil, errors.New("invalid scalar length") + } + tables := p.generatorTable() + // This is also a scalar multiplication with a four-bit window like in + // ScalarMult, but in this case the doublings are precomputed. The value + // [windowValue]G added at iteration k would normally get doubled + // (totIterations-k)×4 times, but with a larger precomputation we can + // instead add [2^((totIterations-k)×4)][windowValue]G and avoid the + // doublings between iterations. + t := NewSM2P256Point() + p.Set(NewSM2P256Point()) + tableIndex := len(tables) - 1 + for _, byte := range scalar { + windowValue := byte >> 4 + tables[tableIndex].Select(t, windowValue) + p.Add(p, t) + tableIndex-- + windowValue = byte & 0b1111 + tables[tableIndex].Select(t, windowValue) + p.Add(p, t) + tableIndex-- + } + return p, nil +} + +// sm2p256Sqrt sets e to a square root of x. If x is not a square, sm2p256Sqrt returns +// false and e is unchanged. e and x can overlap. +func sm2p256Sqrt(e, x *fiat.SM2P256Element) (isSquare bool) { + candidate := new(fiat.SM2P256Element) + sm2p256SqrtCandidate(candidate, x) + square := new(fiat.SM2P256Element).Square(candidate) + if square.Equal(x) != 1 { + return false + } + e.Set(candidate) + return true +} + +// sm2p256SqrtCandidate sets z to a square root candidate for x. z and x must not overlap. +func sm2p256SqrtCandidate(z, x *fiat.SM2P256Element) { + // Since p = 3 mod 4, exponentiation by (p + 1) / 4 yields a square root candidate. + // + // The sequence of 13 multiplications and 253 squarings is derived from the + // following addition chain generated with github.com/mmcloughlin/addchain v0.4.0. + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _1110 = 2*_111 + // _1111 = 1 + _1110 + // _11110 = 2*_1111 + // _111100 = 2*_11110 + // _1111000 = 2*_111100 + // i19 = (_1111000 << 3 + _111100) << 5 + _1111000 + // x31 = (i19 << 2 + _11110) << 14 + i19 + _111 + // i42 = x31 << 4 + // i73 = i42 << 31 + // i74 = i42 + i73 + // i171 = (i73 << 32 + i74) << 62 + i74 + _1111 + // return (i171 << 32 + 1) << 62 + // + var t0 = new(fiat.SM2P256Element) + var t1 = new(fiat.SM2P256Element) + var t2 = new(fiat.SM2P256Element) + var t3 = new(fiat.SM2P256Element) + var t4 = new(fiat.SM2P256Element) + + z.Square(x) + z.Mul(x, z) + z.Square(z) + t0.Mul(x, z) + z.Square(t0) + z.Mul(x, z) + t2.Square(z) + t3.Square(t2) + t1.Square(t3) + t4.Square(t1) + for s := 1; s < 3; s++ { + t4.Square(t4) + } + t3.Mul(t3, t4) + for s := 0; s < 5; s++ { + t3.Square(t3) + } + t1.Mul(t1, t3) + t3.Square(t1) + for s := 1; s < 2; s++ { + t3.Square(t3) + } + t2.Mul(t2, t3) + for s := 0; s < 14; s++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + t0.Mul(t0, t1) + for s := 0; s < 4; s++ { + t0.Square(t0) + } + t1.Square(t0) + for s := 1; s < 31; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + for s := 0; s < 32; s++ { + t1.Square(t1) + } + t1.Mul(t0, t1) + for s := 0; s < 62; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + z.Mul(z, t0) + for s := 0; s < 32; s++ { + z.Square(z) + } + z.Mul(x, z) + for s := 0; s < 62; s++ { + z.Square(z) + } +}