From 8f7a7626baba61ba9c44371a71cd8bec0dbedc6f Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Fri, 2 Sep 2022 14:03:51 +0800 Subject: [PATCH] sm2: support ecdh mqv --- ecdh/ecdh.go | 5 +- ecdh/ecdh_test.go | 183 +++ ecdh/sm2ec.go | 97 ++ go.mod | 4 +- go.sum | 8 +- internal/sm2ec/fiat/sm2p256_order.go | 1299 +++++++++++++++++ internal/sm2ec/fiat/sm2p256_order_test.go | 136 ++ .../{p256_asm_ordinv.go => p256_asm_ord.go} | 43 +- ...56_asm_ordinv_test.go => p256_ord_test.go} | 3 - internal/sm2ec/sm2ec_test.go | 4 + internal/sm2ec/sm2p256_mqv.go | 78 + internal/sm2ec/sm2p256_mqv_test.go | 48 + internal/sm2ec/sm2p256_ord.go | 128 ++ sm2/sm2_keyexchange.go | 18 +- sm2/sm2_keyexchange_test.go | 100 +- sm2/sm2ec/sm2ec.go | 18 + sm2/sm2ec/sm2ec_asm.go | 28 - 17 files changed, 2141 insertions(+), 59 deletions(-) create mode 100644 internal/sm2ec/fiat/sm2p256_order.go create mode 100644 internal/sm2ec/fiat/sm2p256_order_test.go rename internal/sm2ec/{p256_asm_ordinv.go => p256_asm_ord.go} (75%) rename internal/sm2ec/{p256_asm_ordinv_test.go => p256_ord_test.go} (91%) create mode 100644 internal/sm2ec/sm2p256_mqv.go create mode 100644 internal/sm2ec/sm2p256_mqv_test.go create mode 100644 internal/sm2ec/sm2p256_ord.go delete mode 100644 sm2/sm2ec/sm2ec_asm.go diff --git a/ecdh/ecdh.go b/ecdh/ecdh.go index 38776c7..3648ca3 100644 --- a/ecdh/ecdh.go +++ b/ecdh/ecdh.go @@ -23,7 +23,10 @@ type Curve interface { ECDH(local *PrivateKey, remote *PublicKey) ([]byte, error) // SM2MQV performs a SM2 specific style ECMQV exchange and return the shared secret. - //SM2MQV(sLocal, eLocal *PrivateKey, sRemote, eRemote *PublicKey) (*PublicKey, error) + SM2MQV(sLocal, eLocal *PrivateKey, sRemote, eRemote *PublicKey) (*PublicKey, error) + + // SM2SharedKey performs SM2 key derivation to generate shared keying data, the uv was generated by SM2MQV. + SM2SharedKey(isResponder bool, kenLen int, uv, sPub, sRemote *PublicKey, uid []byte, remoteUID []byte) ([]byte, error) // GenerateKey generates a new PrivateKey from rand. GenerateKey(rand io.Reader) (*PrivateKey, error) diff --git a/ecdh/ecdh_test.go b/ecdh/ecdh_test.go index b6c12f9..8b2c3c9 100644 --- a/ecdh/ecdh_test.go +++ b/ecdh/ecdh_test.go @@ -5,6 +5,7 @@ import ( "crypto" "crypto/cipher" "crypto/rand" + "encoding/hex" "fmt" "io" "testing" @@ -23,6 +24,14 @@ var _ interface { Equal(x crypto.PrivateKey) bool } = &ecdh.PrivateKey{} +func hexDecode(t *testing.T, s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + t.Fatal("invalid hex string:", s) + } + return b +} + func TestECDH(t *testing.T) { aliceKey, err := ecdh.P256().GenerateKey(rand.Reader) if err != nil { @@ -69,6 +78,180 @@ func TestECDH(t *testing.T) { } } +func TestSM2MQV(t *testing.T) { + aliceSKey, err := ecdh.P256().GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + aliceEKey, err := ecdh.P256().GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + + bobSKey, err := ecdh.P256().GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + bobEKey, err := ecdh.P256().GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + + bobSecret, err := ecdh.P256().SM2MQV(bobSKey, bobEKey, aliceSKey.PublicKey(), aliceEKey.PublicKey()) + if err != nil { + t.Fatal(err) + } + + aliceSecret, err := ecdh.P256().SM2MQV(aliceSKey, aliceEKey, bobSKey.PublicKey(), bobEKey.PublicKey()) + if err != nil { + t.Fatal(err) + } + + if !aliceSecret.Equal(bobSecret) { + t.Error("two SM2MQV computations came out different") + } +} + +func TestSM2SharedKey(t *testing.T) { + aliceSKey, err := ecdh.P256().GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + aliceEKey, err := ecdh.P256().GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + + bobSKey, err := ecdh.P256().GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + bobEKey, err := ecdh.P256().GenerateKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + + bobSecret, err := ecdh.P256().SM2MQV(bobSKey, bobEKey, aliceSKey.PublicKey(), aliceEKey.PublicKey()) + if err != nil { + t.Fatal(err) + } + + aliceSecret, err := ecdh.P256().SM2MQV(aliceSKey, aliceEKey, bobSKey.PublicKey(), bobEKey.PublicKey()) + if err != nil { + t.Fatal(err) + } + + if !aliceSecret.Equal(bobSecret) { + t.Error("two SM2MQV computations came out different") + } + + bobKey, err := ecdh.P256().SM2SharedKey(true, 48, bobSecret, bobSKey.PublicKey(), aliceSKey.PublicKey(), []byte("Bob"), []byte("Alice")) + if err != nil { + t.Fatal(err) + } + + aliceKey, err := ecdh.P256().SM2SharedKey(false, 48, aliceSecret, aliceSKey.PublicKey(), bobSKey.PublicKey(), []byte("Alice"), []byte("Bob")) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(bobKey, aliceKey) { + t.Error("two SM2SharedKey computations came out different") + } +} + +var vectors = []struct { + LocalStaticPriv, LocalEphemeralPriv string + RemoteStaticPriv, RemoteEphemeralPriv string + SharedSecret, Key string +}{ + { + "e04c3fd77408b56a648ad439f673511a2ae248def3bab26bdfc9cdbd0ae9607e", + "6fe0bac5b09d3ab10f724638811c34464790520e4604e71e6cb0e5310623b5b1", + "7a1136f60d2c5531447e5a3093078c2a505abf74f33aefed927ac0a5b27e7dd7", + "d0233bdbb0b8a7bfe1aab66132ef06fc4efaedd5d5000692bc21185242a31f6f", + "046ab5c9709277837cedc515730d04751ef81c71e81e0e52357a98cf41796ab560508da6e858b40c6264f17943037434174284a847f32c4f54104a98af5148d89f", + "1ad809ebc56ddda532020c352e1e60b121ebeb7b4e632db4dd90a362cf844f8bba85140e30984ddb581199bf5a9dda22", + }, + { + "cb5ac204b38d0e5c9fc38a467075986754018f7dbb7cbbc5b4c78d56a88a8ad8", + "1681a66c02b67fdadfc53cba9b417b9499d0159435c86bb8760c3a03ae157539", + "4f54b10e0d8e9e2fe5cc79893e37fd0fd990762d1372197ed92dde464b2773ef", + "a2fe43dea141e9acc88226eaba8908ad17e81376c92102cb8186e8fef61a8700", + "04677d055355a1dcc9de4df00d3a80b6daa76bdf54ff7e0a3a6359fcd0c6f1e4b4697fffc41bbbcc3a28ea3aa1c6c380d1e92f142233afa4b430d02ab4cebc43b2", + "7a103ae61a30ed9df573a5febb35a9609cbed5681bcb98a8545351bf7d6824cc4635df5203712ea506e2e3c4ec9b12e7", + }, + { + "ee690a34a779ab48227a2f68b062a80f92e26d82835608dd01b7452f1e4fb296", + "2046c6cee085665e9f3abeba41fd38e17a26c08f2f5e8f0e1007afc0bf6a2a5d", + "8ef49ea427b13cc31151e1c96ae8a48cb7919063f2d342560fb7eaaffb93d8fe", + "9baf8d602e43fbae83fedb7368f98c969d378b8a647318f8cafb265296ae37de", + "04f7e9f1447968b284ff43548fcec3752063ea386b48bfabb9baf2f9c1caa05c2fb12c2cca37326ce27e68f8cc6414c2554895519c28da1ca21e61890d0bc525c4", + "b18e78e5072f301399dc1f4baf2956c0ed2d5f52f19abb1705131b0865b079031259ee6c629b4faed528bcfa1c5d2cbc", + }, +} + +func TestSM2SharedKeyVectors(t *testing.T) { + initiator := []byte("Alice") + responder := []byte("Bob") + kenLen := 48 + + for i, v := range vectors { + aliceSKey, err := ecdh.P256().NewPrivateKey(hexDecode(t, v.LocalStaticPriv)) + if err != nil { + t.Fatal(err) + } + aliceEKey, err := ecdh.P256().NewPrivateKey(hexDecode(t, v.LocalEphemeralPriv)) + if err != nil { + t.Fatal(err) + } + bobSKey, err := ecdh.P256().NewPrivateKey(hexDecode(t, v.RemoteStaticPriv)) + if err != nil { + t.Fatal(err) + } + bobEKey, err := ecdh.P256().NewPrivateKey(hexDecode(t, v.RemoteEphemeralPriv)) + if err != nil { + t.Fatal(err) + } + + bobSecret, err := ecdh.P256().SM2MQV(bobSKey, bobEKey, aliceSKey.PublicKey(), aliceEKey.PublicKey()) + if err != nil { + t.Fatal(err) + } + + aliceSecret, err := ecdh.P256().SM2MQV(aliceSKey, aliceEKey, bobSKey.PublicKey(), bobEKey.PublicKey()) + if err != nil { + t.Fatal(err) + } + + if !aliceSecret.Equal(bobSecret) { + t.Error("two SM2MQV computations came out different") + } + + if !bytes.Equal(aliceSecret.Bytes(), hexDecode(t, v.SharedSecret)) { + t.Errorf("%v shared secret is not expected.", i) + } + + bobKey, err := ecdh.P256().SM2SharedKey(true, kenLen, bobSecret, bobSKey.PublicKey(), aliceSKey.PublicKey(), responder, initiator) + if err != nil { + t.Fatal(err) + } + + aliceKey, err := ecdh.P256().SM2SharedKey(false, kenLen, aliceSecret, aliceSKey.PublicKey(), bobSKey.PublicKey(), initiator, responder) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(bobKey, aliceKey) { + t.Error("two SM2SharedKey computations came out different") + } + + if !bytes.Equal(bobKey, hexDecode(t, v.Key)) { + t.Errorf("%v keying data is not expected.", i) + } + } +} + type countingReader struct { r io.Reader n int diff --git a/ecdh/sm2ec.go b/ecdh/sm2ec.go index 9b6ff30..51a3236 100644 --- a/ecdh/sm2ec.go +++ b/ecdh/sm2ec.go @@ -3,18 +3,24 @@ package ecdh import ( "encoding/binary" "errors" + "hash" "io" "math/bits" "github.com/emmansun/gmsm/internal/randutil" sm2ec "github.com/emmansun/gmsm/internal/sm2ec" "github.com/emmansun/gmsm/internal/subtle" + "github.com/emmansun/gmsm/kdf" + "github.com/emmansun/gmsm/sm3" ) type sm2Curve struct { name string newPoint func() *sm2ec.SM2P256Point scalarOrder []byte + constantA []byte + constantB []byte + generator []byte } func (c *sm2Curve) String() string { @@ -107,6 +113,91 @@ func (c *sm2Curve) ECDH(local *PrivateKey, remote *PublicKey) ([]byte, error) { return p.BytesX() } +func (c *sm2Curve) sm2avf(secret *PublicKey) []byte { + bytes := secret.publicKey[1:33] + var result [32]byte + copy(result[16:], bytes[16:]) + result[16] = (result[16] & 0x7f) | 0x80 + + return result[:] +} + +func (c *sm2Curve) SM2MQV(sLocal, eLocal *PrivateKey, sRemote, eRemote *PublicKey) (*PublicKey, error) { + // implicitSig: (sLocal + avf(eLocal.Pub) * ePriv) mod N + x2 := c.sm2avf(eLocal.PublicKey()) + t, err := sm2ec.ImplicitSig(sLocal.privateKey, eLocal.privateKey, x2) + if err != nil { + return nil, err + } + + // new base point: peerPub + [x1](peerSecret) + x1 := c.sm2avf(eRemote) + p2, err := c.newPoint().SetBytes(eRemote.publicKey) + if err != nil { + return nil, err + } + if _, err := p2.ScalarMult(p2, x1); err != nil { + return nil, err + } + p1, err := c.newPoint().SetBytes(sRemote.publicKey) + if err != nil { + return nil, err + } + p2.Add(p1, p2) + + if _, err := p2.ScalarMult(p2, t); err != nil { + return nil, err + } + return c.NewPublicKey(p2.Bytes()) +} + +func (c *sm2Curve) SM2SharedKey(isResponder bool, kenLen int, uv, sPub, sRemote *PublicKey, uid []byte, remoteUID []byte) ([]byte, error) { + var buffer [128]byte + copy(buffer[:], uv.publicKey[1:]) + peerZ, err := c.sm2za(sm3.New(), sRemote, remoteUID) + if err != nil { + return nil, err + } + z, err := c.sm2za(sm3.New(), sPub, uid) + if err != nil { + return nil, err + } + if isResponder { + copy(buffer[64:], peerZ) + copy(buffer[96:], z) + } else { + copy(buffer[64:], z) + copy(buffer[96:], peerZ) + } + + return kdf.Kdf(sm3.New(), buffer[:], kenLen), nil +} + +var defaultUID = []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38} + +// CalculateZA ZA = H256(ENTLA || IDA || a || b || xG || yG || xA || yA). +// Compliance with GB/T 32918.2-2016 5.5 +func (c *sm2Curve) sm2za(md hash.Hash, pub *PublicKey, uid []byte) ([]byte, error) { + if len(uid) == 0 { + uid = defaultUID + } + uidLen := len(uid) + if uidLen >= 0x2000 { + return nil, errors.New("ecdh: the uid is too long") + } + entla := uint16(uidLen) << 3 + md.Write([]byte{byte(entla >> 8), byte(entla)}) + if uidLen > 0 { + md.Write(uid) + } + md.Write(c.constantA) + md.Write(c.constantB) + md.Write(c.generator) + md.Write(pub.publicKey[1:]) + + return md.Sum(nil), nil +} + // P256 returns a Curve which implements SM2, also known as sm2p256v1 // // Multiple invocations of this function will return the same value, so it can @@ -117,9 +208,15 @@ var sm2P256 = &sm2Curve{ name: "sm2p256v1", newPoint: sm2ec.NewSM2P256Point, scalarOrder: sm2P256Order, + generator: sm2Generator, + constantA: sm2ConstantA, + constantB: sm2ConstantB, } var sm2P256Order = []byte{0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b, 0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23} +var sm2Generator = []byte{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} +var sm2ConstantA = []byte{0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc} +var sm2ConstantB = []byte{0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b, 0xcf, 0x65, 0x09, 0xa7, 0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92, 0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0x0e, 0x93} // isLess returns whether a < b, where a and b are big-endian buffers of the // same length and shorter than 72 bytes. diff --git a/go.mod b/go.mod index 085d7c3..240942e 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,6 @@ module github.com/emmansun/gmsm go 1.16 require ( - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa - golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 + golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 + golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 ) diff --git a/go.sum b/go.sum index d581bfd..5ca3008 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM= +golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/internal/sm2ec/fiat/sm2p256_order.go b/internal/sm2ec/fiat/sm2p256_order.go new file mode 100644 index 0000000..6c1f97f --- /dev/null +++ b/internal/sm2ec/fiat/sm2p256_order.go @@ -0,0 +1,1299 @@ +package fiat + +import ( + "errors" + "math/bits" +) + +var orderK0 uint64 = 0x327f9e8872350975 + +// SM2P256OrderElement is an integer modulo 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123. +// +// The zero value is a valid zero element. +type SM2P256OrderElement struct { + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x sm2p256MontgomeryDomainFieldElement +} + +// One sets e = 1, and returns e. +func (e *SM2P256OrderElement) One() *SM2P256OrderElement { + e.x[0] = 0xac440bf6c62abedd + e.x[1] = 0x8dfc2094de39fad4 + e.x[2] = uint64(0x0) + e.x[3] = 0x100000000 + return e +} + +// Add sets e = t1 + t2, and returns e. +func (e *SM2P256OrderElement) Add(t1, t2 *SM2P256OrderElement) *SM2P256OrderElement { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Add64(t1.x[0], t2.x[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Add64(t1.x[1], t2.x[1], uint64(sm2p256Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(t1.x[2], t2.x[2], uint64(sm2p256Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(t1.x[3], t2.x[3], uint64(sm2p256Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(x1, 0x53bbf40939d54123, uint64(0x0)) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(x3, 0x7203df6b21c6052b, 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) + e.x[0] = x19 + e.x[1] = x20 + e.x[2] = x21 + e.x[3] = x22 + return e +} + +// Sub sets e = t1 - t2, and returns e. +func (e *SM2P256OrderElement) Sub(t1, t2 *SM2P256OrderElement) *SM2P256OrderElement { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(t1.x[0], t2.x[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(t1.x[1], t2.x[1], uint64(sm2p256Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(t1.x[2], t2.x[2], uint64(sm2p256Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(t1.x[3], t2.x[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 & 0x53bbf40939d54123), uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x3, (x9 & 0x7203df6b21c6052b), 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))) + e.x[0] = x10 + e.x[1] = x12 + e.x[2] = x14 + e.x[3] = x16 + return e +} + +// Mul sets e = t1 * t2, and returns e. +func (e *SM2P256OrderElement) Mul(t1, t2 *SM2P256OrderElement) *SM2P256OrderElement { + x1 := t1.x[1] + x2 := t1.x[2] + x3 := t1.x[3] + x4 := t1.x[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, t2.x[3]) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, t2.x[2]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, t2.x[1]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, t2.x[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 + _, y11 := bits.Mul64(x11, orderK0) + x21, x20 = bits.Mul64(y11, 0xfffffffeffffffff) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(y11, 0xffffffffffffffff) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(y11, 0x7203df6b21c6052b) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(y11, 0x53bbf40939d54123) + 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, t2.x[3]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, t2.x[2]) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, t2.x[1]) + var x51 uint64 + var x52 uint64 + x52, x51 = bits.Mul64(x1, t2.x[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 + _, y60 := bits.Mul64(x60, orderK0) + x71, x70 = bits.Mul64(y60, 0xfffffffeffffffff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(y60, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(y60, 0x7203df6b21c6052b) + var x76 uint64 + var x77 uint64 + x77, x76 = bits.Mul64(y60, 0x53bbf40939d54123) + 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, t2.x[3]) + var x98 uint64 + var x99 uint64 + x99, x98 = bits.Mul64(x2, t2.x[2]) + var x100 uint64 + var x101 uint64 + x101, x100 = bits.Mul64(x2, t2.x[1]) + var x102 uint64 + var x103 uint64 + x103, x102 = bits.Mul64(x2, t2.x[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 + _, y111 := bits.Mul64(x111, orderK0) + x122, x121 = bits.Mul64(y111, 0xfffffffeffffffff) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(y111, 0xffffffffffffffff) + var x125 uint64 + var x126 uint64 + x126, x125 = bits.Mul64(y111, 0x7203df6b21c6052b) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(y111, 0x53bbf40939d54123) + 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, t2.x[3]) + var x149 uint64 + var x150 uint64 + x150, x149 = bits.Mul64(x3, t2.x[2]) + var x151 uint64 + var x152 uint64 + x152, x151 = bits.Mul64(x3, t2.x[1]) + var x153 uint64 + var x154 uint64 + x154, x153 = bits.Mul64(x3, t2.x[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 + _, y162 := bits.Mul64(x162, orderK0) + x173, x172 = bits.Mul64(y162, 0xfffffffeffffffff) + var x174 uint64 + var x175 uint64 + x175, x174 = bits.Mul64(y162, 0xffffffffffffffff) + var x176 uint64 + var x177 uint64 + x177, x176 = bits.Mul64(y162, 0x7203df6b21c6052b) + var x178 uint64 + var x179 uint64 + x179, x178 = bits.Mul64(y162, 0x53bbf40939d54123) + 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, 0x53bbf40939d54123, uint64(0x0)) + var x200 uint64 + var x201 uint64 + x200, x201 = bits.Sub64(x191, 0x7203df6b21c6052b, 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) + e.x[0] = x208 + e.x[1] = x209 + e.x[2] = x210 + e.x[3] = x211 + + return e +} + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *SM2P256OrderElement) Select(a, b *SM2P256OrderElement, cond int) *SM2P256OrderElement { + sm2p256Selectznz((*sm2p256UntypedFieldElement)(&v.x), sm2p256Uint1(cond), + (*sm2p256UntypedFieldElement)(&b.x), (*sm2p256UntypedFieldElement)(&a.x)) + return v +} + +// Square sets e = t * t, and returns e. +func (e *SM2P256OrderElement) Square(t *SM2P256OrderElement) *SM2P256OrderElement { + x1 := t.x[1] + x2 := t.x[2] + x3 := t.x[3] + x4 := t.x[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, t.x[3]) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, t.x[2]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, t.x[1]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, t.x[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 + _, y11 := bits.Mul64(x11, orderK0) + x21, x20 = bits.Mul64(y11, 0xfffffffeffffffff) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(y11, 0xffffffffffffffff) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(y11, 0x7203df6b21c6052b) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(y11, 0x53bbf40939d54123) + 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, t.x[3]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, t.x[2]) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, t.x[1]) + var x51 uint64 + var x52 uint64 + x52, x51 = bits.Mul64(x1, t.x[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 + _, y60 := bits.Mul64(x60, orderK0) + x71, x70 = bits.Mul64(y60, 0xfffffffeffffffff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(y60, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(y60, 0x7203df6b21c6052b) + var x76 uint64 + var x77 uint64 + x77, x76 = bits.Mul64(y60, 0x53bbf40939d54123) + 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, t.x[3]) + var x98 uint64 + var x99 uint64 + x99, x98 = bits.Mul64(x2, t.x[2]) + var x100 uint64 + var x101 uint64 + x101, x100 = bits.Mul64(x2, t.x[1]) + var x102 uint64 + var x103 uint64 + x103, x102 = bits.Mul64(x2, t.x[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 + _, y111 := bits.Mul64(x111, orderK0) + x122, x121 = bits.Mul64(y111, 0xfffffffeffffffff) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(y111, 0xffffffffffffffff) + var x125 uint64 + var x126 uint64 + x126, x125 = bits.Mul64(y111, 0x7203df6b21c6052b) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(y111, 0x53bbf40939d54123) + 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, t.x[3]) + var x149 uint64 + var x150 uint64 + x150, x149 = bits.Mul64(x3, t.x[2]) + var x151 uint64 + var x152 uint64 + x152, x151 = bits.Mul64(x3, t.x[1]) + var x153 uint64 + var x154 uint64 + x154, x153 = bits.Mul64(x3, t.x[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 + _, y162 := bits.Mul64(x162, orderK0) + x173, x172 = bits.Mul64(y162, 0xfffffffeffffffff) + var x174 uint64 + var x175 uint64 + x175, x174 = bits.Mul64(y162, 0xffffffffffffffff) + var x176 uint64 + var x177 uint64 + x177, x176 = bits.Mul64(y162, 0x7203df6b21c6052b) + var x178 uint64 + var x179 uint64 + x179, x178 = bits.Mul64(y162, 0x53bbf40939d54123) + 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, 0x53bbf40939d54123, uint64(0x0)) + var x200 uint64 + var x201 uint64 + x200, x201 = bits.Sub64(x191, 0x7203df6b21c6052b, 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) + e.x[0] = x208 + e.x[1] = x209 + e.x[2] = x210 + e.x[3] = x211 + + return e +} + +// 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 *SM2P256OrderElement) SetBytes(v []byte) (*SM2P256OrderElement, error) { + if len(v) != sm2p256ElementLen { + return nil, errors.New("invalid SM2P256OrderElement encoding") + } +/* + // Check for non-canonical encodings (p + k, 2p + k, etc.) by comparing to + // the encoding of -1 mod p, so p - 1, the highest canonical encoding. + var minusOneEncoding = new(SM2P256OrderElement).Sub( + new(SM2P256OrderElement), new(SM2P256OrderElement).One()).Bytes() + for i := range v { + if v[i] < minusOneEncoding[i] { + break + } + if v[i] > minusOneEncoding[i] { + return nil, errors.New("invalid SM2P256OrderElement encoding") + } + } +*/ + var in [sm2p256ElementLen]byte + copy(in[:], v) + sm2p256InvertEndianness(in[:]) + var tmp sm2p256NonMontgomeryDomainFieldElement + sm2p256FromBytes((*sm2p256UntypedFieldElement)(&tmp), &in) + sm2p256OrderToMontgomery(&e.x, &tmp) + return e, nil +} + +// Bytes returns the 32-byte big-endian encoding of e. +func (e *SM2P256OrderElement) 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 *SM2P256OrderElement) bytes(out *[sm2p256ElementLen]byte) []byte { + var tmp sm2p256NonMontgomeryDomainFieldElement + sm2p256OrderFromMontgomery(&tmp, &e.x) + sm2p256ToBytes(out, (*sm2p256UntypedFieldElement)(&tmp)) + sm2p256InvertEndianness(out[:]) + return out[:] +} + +// sm2p256OrderFromMontgomery 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 sm2p256OrderFromMontgomery(out1 *sm2p256NonMontgomeryDomainFieldElement, arg1 *sm2p256MontgomeryDomainFieldElement) { + x1 := arg1[0] + _, y1 := bits.Mul64(arg1[0], orderK0) + var x2 uint64 + var x3 uint64 + x3, x2 = bits.Mul64(y1, 0xfffffffeffffffff) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(y1, 0xffffffffffffffff) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(y1, 0x7203df6b21c6052b) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(y1, 0x53bbf40939d54123) + 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 + _, y24 := bits.Mul64(x24, orderK0) + x31, x30 = bits.Mul64(y24, 0xfffffffeffffffff) + var x32 uint64 + var x33 uint64 + x33, x32 = bits.Mul64(y24, 0xffffffffffffffff) + var x34 uint64 + var x35 uint64 + x35, x34 = bits.Mul64(y24, 0x7203df6b21c6052b) + var x36 uint64 + var x37 uint64 + x37, x36 = bits.Mul64(y24, 0x53bbf40939d54123) + 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 + _, y52 := bits.Mul64(x52, orderK0) + x59, x58 = bits.Mul64(y52, 0xfffffffeffffffff) + var x60 uint64 + var x61 uint64 + x61, x60 = bits.Mul64(y52, 0xffffffffffffffff) + var x62 uint64 + var x63 uint64 + x63, x62 = bits.Mul64(y52, 0x7203df6b21c6052b) + var x64 uint64 + var x65 uint64 + x65, x64 = bits.Mul64(y52, 0x53bbf40939d54123) + 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 + _, y80 := bits.Mul64(x80, orderK0) + x87, x86 = bits.Mul64(y80, 0xfffffffeffffffff) + var x88 uint64 + var x89 uint64 + x89, x88 = bits.Mul64(y80, 0xffffffffffffffff) + var x90 uint64 + var x91 uint64 + x91, x90 = bits.Mul64(y80, 0x7203df6b21c6052b) + var x92 uint64 + var x93 uint64 + x93, x92 = bits.Mul64(y80, 0x53bbf40939d54123) + 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, 0x53bbf40939d54123, uint64(0x0)) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Sub64(x104, 0x7203df6b21c6052b, 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 +} + +// sm2p256OrderToMontgomery 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 sm2p256OrderToMontgomery(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, 0x1eb5e412a22b3d3b) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, 0x620fc84c3affe0d4) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, 0x3464504ade6fa2fa) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, 0x901192af7c114f20) + 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 + _, y11 := bits.Mul64(x11, orderK0) + x20, x19 = bits.Mul64(y11, 0xfffffffeffffffff) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(y11, 0xffffffffffffffff) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(y11, 0x7203df6b21c6052b) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(y11, 0x53bbf40939d54123) + 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, 0x1eb5e412a22b3d3b) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, 0x620fc84c3affe0d4) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, 0x3464504ade6fa2fa) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, 0x901192af7c114f20) + 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 + _, y57 := bits.Mul64(x57, orderK0) + x66, x65 = bits.Mul64(y57, 0xfffffffeffffffff) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(y57, 0xffffffffffffffff) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(y57, 0x7203df6b21c6052b) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(y57, 0x53bbf40939d54123) + 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, 0x1eb5e412a22b3d3b) + var x91 uint64 + var x92 uint64 + x92, x91 = bits.Mul64(x2, 0x620fc84c3affe0d4) + var x93 uint64 + var x94 uint64 + x94, x93 = bits.Mul64(x2, 0x3464504ade6fa2fa) + var x95 uint64 + var x96 uint64 + x96, x95 = bits.Mul64(x2, 0x901192af7c114f20) + 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 + _, y103 := bits.Mul64(x103, orderK0) + x112, x111 = bits.Mul64(y103, 0xfffffffeffffffff) + var x113 uint64 + var x114 uint64 + x114, x113 = bits.Mul64(y103, 0xffffffffffffffff) + var x115 uint64 + var x116 uint64 + x116, x115 = bits.Mul64(y103, 0x7203df6b21c6052b) + var x117 uint64 + var x118 uint64 + x118, x117 = bits.Mul64(y103, 0x53bbf40939d54123) + 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, 0x1eb5e412a22b3d3b) + var x137 uint64 + var x138 uint64 + x138, x137 = bits.Mul64(x3, 0x620fc84c3affe0d4) + var x139 uint64 + var x140 uint64 + x140, x139 = bits.Mul64(x3, 0x3464504ade6fa2fa) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x3, 0x901192af7c114f20) + 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 + _, y149 := bits.Mul64(x149, orderK0) + x158, x157 = bits.Mul64(y149, 0xfffffffeffffffff) + var x159 uint64 + var x160 uint64 + x160, x159 = bits.Mul64(y149, 0xffffffffffffffff) + var x161 uint64 + var x162 uint64 + x162, x161 = bits.Mul64(y149, 0x7203df6b21c6052b) + var x163 uint64 + var x164 uint64 + x164, x163 = bits.Mul64(y149, 0x53bbf40939d54123) + 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, 0x53bbf40939d54123, uint64(0x0)) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Sub64(x175, 0x7203df6b21c6052b, 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 +} diff --git a/internal/sm2ec/fiat/sm2p256_order_test.go b/internal/sm2ec/fiat/sm2p256_order_test.go new file mode 100644 index 0000000..2526b4f --- /dev/null +++ b/internal/sm2ec/fiat/sm2p256_order_test.go @@ -0,0 +1,136 @@ +package fiat_test + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "fmt" + "math/big" + "testing" + + "github.com/emmansun/gmsm/internal/sm2ec/fiat" +) + +var ordN *big.Int + +func init() { + // n=115792089210356248756420345214020892766061623724957744567843809356293439045923 + // p-n=188730266966446886577384576996245946076 + ordN, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16) +} + +var testValues = [20]string{ + "e576e1aefe41c42a634a6937982dd8ea60654c4d406ef141018072b8a8ee10ff", + "374bf8d3ed1a35a109ccc73276e4fa3697d942eafcd514a82a985d0820f02645", + "d62fd995bdc9ed6d405cad6a5cd48e0b92b465c2c8fbb7b14cc86e16e6dba6e8", + "a8c28fe4b2c4abad3759ac3cb97c23eb0440273277f8d8be794eea0a2561357d", + "f3bcfff783d0eb4de34bffd0c6290f75381bf715a1bc2b02ffbb58cc794ef1b7", + "a08b119bb9bf49b2cda951de57df6e95f413a609aefa51eefa554a4906963942", + "1b767aabebdf28a447de4c37b18d8c86e431c70acbb6d05eab459180e3731075", + "40616625f9dd4e7c396106e539ed7891636acfb3ba7f80e72dc305b8cb2955d8", + "3246e27330be55dc574e97a9e0c5ab6a476bb2b5422e8c47b2248a40504fc8a0", + "aa54dec0a14ee69417186ff2711e59282d5badc3faa1528c4171e14baa525865", + "408817dd964bd439aec08c3ebda707dc8ff969d25aef0ec0ba6085bc8da6996f", + "99ed1792abdda9f0e43fd50c59a57b7f9c3c60d69c8046c71b67a1a71d9f7d55", + "455705f9823bd5ba6f58c2a4dbdf6f10a0de1947a82c2653b00833ea39e26b5d", + "b43fdba6043be8524bcc4cd6ab7d71534fcaf42869ab838e98608d5e9d801cf9", + "c97498821b3b4db41239d1a3d47d49754e5e6b7bb7ae21d4eb0826bd5c0aeed6", + "c0213f02d06c935b798594c9c3b4feaebea881205733a21484a48df4643fbde7", + "313c9f7129eb1a09c385dc755aab9d88fcab79a7e4deaca68dd08d93fd68d252", + "eb7b96f239402bd494dc258672cd4a1643ae9fe092ddaaca54f9e909548eaa90", + "24567a167761a040aed80ea4655616b5aae5a0548b2a2a39a99bd4a6d7791610", + "c79886c5cd9de1f2a0deee1c76cd8c38da7dcd401f59ec4bebbaf815006f2f71", +} + +func TestGenerateValues(t *testing.T) { + p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16) + for i := 0; i < 20; i++ { + k, _ := rand.Int(rand.Reader, p) + if k.Sign() > 0 { + fmt.Printf("%v\n", hex.EncodeToString(k.Bytes())) + } + } +} + +func p256OrderMulTest(t *testing.T, x, y, n *big.Int) { + var scalar1 [32]byte + var scalar2 [32]byte + var scalar [32]byte + x1 := new(big.Int).Mod(x, n) + y1 := new(big.Int).Mod(y, n) + ax := new(fiat.SM2P256OrderElement) + ay := new(fiat.SM2P256OrderElement) + res := new(fiat.SM2P256OrderElement) + x1.FillBytes(scalar1[:]) + y1.FillBytes(scalar2[:]) + _, err := ax.SetBytes(scalar1[:]) + if err != nil { + t.Error(err) + } + if !bytes.Equal(scalar1[:], ax.Bytes()) { + t.Errorf("x SetBytes/Bytes error, expected %v, got %v\n", hex.EncodeToString(scalar1[:]), hex.EncodeToString(ax.Bytes())) + } + _, err = ay.SetBytes(scalar2[:]) + if err != nil { + t.Error(err) + } + if !bytes.Equal(scalar2[:], ay.Bytes()) { + t.Errorf("y SetBytes/Bytes error, expected %v, got %v\n", hex.EncodeToString(scalar2[:]), hex.EncodeToString(ay.Bytes())) + } + res = res.Mul(ax, ay) + expected := new(big.Int).Mul(x1, y1) + expected = expected.Mod(expected, n) + expected.FillBytes(scalar[:]) + if !bytes.Equal(res.Bytes(), scalar[:]) { + t.Errorf("expected %v, got %v\n", hex.EncodeToString(scalar[:]), hex.EncodeToString(res.Bytes())) + } +} + +func TestP256Mul(t *testing.T) { + for i := 0; i < 20; i += 2 { + x, _ := new(big.Int).SetString(testValues[i], 16) + y, _ := new(big.Int).SetString(testValues[i+1], 16) + p256OrderMulTest(t, x, y, ordN) + } +} + +func TestP256Square(t *testing.T) { + var scalar [32]byte + for i := 0; i < 20; i++ { + x, _ := new(big.Int).SetString(testValues[i], 16) + ax := new(fiat.SM2P256OrderElement) + ax.SetBytes(x.Bytes()) + res := new(fiat.SM2P256OrderElement) + res.Square(ax) + expected := new(big.Int).Mul(x, x) + expected = expected.Mod(expected, ordN) + expected.FillBytes(scalar[:]) + if !bytes.Equal(res.Bytes(), scalar[:]) { + t.Errorf("expected %v, got %v\n", hex.EncodeToString(scalar[:]), hex.EncodeToString(res.Bytes())) + } + } +} + +func TestP256Add(t *testing.T) { + var scalar [32]byte + for i := 0; i < 20; i += 2 { + x, _ := new(big.Int).SetString(testValues[i], 16) + y, _ := new(big.Int).SetString(testValues[i+1], 16) + expected := new(big.Int).Add(x, y) + expected = expected.Mod(expected, ordN) + expected.FillBytes(scalar[:]) + + ax := new(fiat.SM2P256OrderElement) + ax.SetBytes(x.Bytes()) + + ay := new(fiat.SM2P256OrderElement) + ay.SetBytes(y.Bytes()) + + res := new(fiat.SM2P256OrderElement) + res.Add(ax, ay) + + if !bytes.Equal(res.Bytes(), scalar[:]) { + t.Errorf("expected %v, got %v\n", hex.EncodeToString(scalar[:]), hex.EncodeToString(res.Bytes())) + } + } +} diff --git a/internal/sm2ec/p256_asm_ordinv.go b/internal/sm2ec/p256_asm_ord.go similarity index 75% rename from internal/sm2ec/p256_asm_ordinv.go rename to internal/sm2ec/p256_asm_ord.go index 31bf342..2210aa9 100644 --- a/internal/sm2ec/p256_asm_ordinv.go +++ b/internal/sm2ec/p256_asm_ord.go @@ -15,6 +15,13 @@ func p256OrdMul(res, in1, in2 *p256OrdElement) //go:noescape func p256OrdSqr(res, in *p256OrdElement, n int) +// This code operates in the Montgomery domain where R = 2²⁵⁶ mod n and n is +// the order of the scalar field. Elements in the Montgomery domain take the +// form a×R and p256OrdMul calculates (a × b × R⁻¹) mod n. RR is R in the +// domain, or R×R mod n, thus p256OrdMul(x, RR) gives x×R, i.e. converts x +// into the Montgomery domain. +var RR = &p256OrdElement{0x901192af7c114f20, 0x3464504ade6fa2fa, 0x620fc84c3affe0d4, 0x1eb5e412a22b3d3b} + // P256OrdInverse, sets out to in⁻¹ mod org(G). If in is zero, out will be zero. // n-2 = // 1111111111111111111111111111111011111111111111111111111111111111 @@ -43,13 +50,6 @@ func P256OrdInverse(k []byte) ([]byte, error) { t := new(p256OrdElement) m := new(p256OrdElement) - // This code operates in the Montgomery domain where R = 2²⁵⁶ mod n and n is - // the order of the scalar field. Elements in the Montgomery domain take the - // form a×R and p256OrdMul calculates (a × b × R⁻¹) mod n. RR is R in the - // domain, or R×R mod n, thus p256OrdMul(x, RR) gives x×R, i.e. converts x - // into the Montgomery domain. - RR := &p256OrdElement{0x901192af7c114f20, 0x3464504ade6fa2fa, 0x620fc84c3affe0d4, 0x1eb5e412a22b3d3b} - p256OrdMul(_1, x, RR) // _1 , 2^0 p256OrdSqr(m, _1, 1) // _10, 2^1 p256OrdMul(_11, m, _1) // _11, 2^1 + 2^0 @@ -98,12 +98,35 @@ func P256OrdInverse(k []byte) ([]byte, error) { p256OrdSqr(x, x, int(s)) p256OrdMul(x, x, muls[i]) } + return p256OrderFromMont(x), nil +} + +// P256OrdMul multiplication modulo org(G). +func P256OrdMul(in1, in2 []byte) ([]byte, error) { + if len(in1) != 32 || len(in2) != 32 { + return nil, errors.New("invalid scalar length") + } + x1 := new(p256OrdElement) + p256OrdBigToLittle(x1, toElementArray(in1)) + p256OrdMul(x1, x1, RR) + + x2 := new(p256OrdElement) + p256OrdBigToLittle(x2, toElementArray(in2)) + p256OrdMul(x2, x2, RR) + + res := new(p256OrdElement) + p256OrdMul(res, x1, x2) + + return p256OrderFromMont(res), nil +} + +func p256OrderFromMont(in *p256OrdElement) []byte { // Montgomery multiplication by R⁻¹, or 1 outside the domain as R⁻¹×R = 1, // converts a Montgomery value out of the domain. one := &p256OrdElement{1} - p256OrdMul(x, x, one) + p256OrdMul(in, in, one) var xOut [32]byte - p256OrdLittleToBig(&xOut, x) - return xOut[:], nil + p256OrdLittleToBig(&xOut, in) + return xOut[:] } diff --git a/internal/sm2ec/p256_asm_ordinv_test.go b/internal/sm2ec/p256_ord_test.go similarity index 91% rename from internal/sm2ec/p256_asm_ordinv_test.go rename to internal/sm2ec/p256_ord_test.go index d158288..c7303a9 100644 --- a/internal/sm2ec/p256_asm_ordinv_test.go +++ b/internal/sm2ec/p256_ord_test.go @@ -1,6 +1,3 @@ -//go:build (amd64 && !generic) || (arm64 && !generic) -// +build amd64,!generic arm64,!generic - package sm2ec_test import ( diff --git a/internal/sm2ec/sm2ec_test.go b/internal/sm2ec/sm2ec_test.go index a9d01e6..220b1e5 100644 --- a/internal/sm2ec/sm2ec_test.go +++ b/internal/sm2ec/sm2ec_test.go @@ -74,6 +74,10 @@ func TestSM2P256MontgomeryDomainN(t *testing.T) { in string out string }{ + { // One + "01", + "010000000000000000000000008dfc2094de39fad4ac440bf6c62abedd", + }, { // R "010000000000000000000000000000000000000000000000000000000000000000", "1eb5e412a22b3d3b620fc84c3affe0d43464504ade6fa2fa901192af7c114f20", diff --git a/internal/sm2ec/sm2p256_mqv.go b/internal/sm2ec/sm2p256_mqv.go new file mode 100644 index 0000000..51780a9 --- /dev/null +++ b/internal/sm2ec/sm2p256_mqv.go @@ -0,0 +1,78 @@ +package sm2ec + +import ( + "encoding/binary" + "errors" + "math/bits" +) + +var p256Order = [4]uint64{0x53bbf40939d54123, 0x7203df6b21c6052b, + 0xffffffffffffffff, 0xfffffffeffffffff} + +func fromBytes(bytes []byte) (*[4]uint64, error) { + if len(bytes) != 32 { + return nil, errors.New("invalid scalar length") + } + var t [4]uint64 + t[0] = binary.BigEndian.Uint64(bytes[24:]) + t[1] = binary.BigEndian.Uint64(bytes[16:]) + t[2] = binary.BigEndian.Uint64(bytes[8:]) + t[3] = binary.BigEndian.Uint64(bytes) + return &t, nil +} + +func toBytes(t *[4]uint64) []byte { + var bytes [32]byte + + binary.BigEndian.PutUint64(bytes[:], t[3]) + binary.BigEndian.PutUint64(bytes[8:], t[2]) + binary.BigEndian.PutUint64(bytes[16:], t[1]) + binary.BigEndian.PutUint64(bytes[24:], t[0]) + + return bytes[:] +} + +// p256OrdAdd sets res = x + y. +func p256OrdAdd(res, x, y *[4]uint64) { + var c, b uint64 + t1 := make([]uint64, 4) + t1[0], c = bits.Add64(x[0], y[0], 0) + t1[1], c = bits.Add64(x[1], y[1], c) + t1[2], c = bits.Add64(x[2], y[2], c) + t1[3], c = bits.Add64(x[3], y[3], c) + t2 := make([]uint64, 4) + t2[0], b = bits.Sub64(t1[0], p256Order[0], 0) + t2[1], b = bits.Sub64(t1[1], p256Order[1], b) + t2[2], b = bits.Sub64(t1[2], p256Order[2], b) + t2[3], b = bits.Sub64(t1[3], p256Order[3], b) + // Three options: + // - a+b < p + // then c is 0, b is 1, and t1 is correct + // - p <= a+b < 2^256 + // then c is 0, b is 0, and t2 is correct + // - 2^256 <= a+b + // then c is 1, b is 1, and t2 is correct + t2Mask := (c ^ b) - 1 + res[0] = (t1[0] & ^t2Mask) | (t2[0] & t2Mask) + res[1] = (t1[1] & ^t2Mask) | (t2[1] & t2Mask) + res[2] = (t1[2] & ^t2Mask) | (t2[2] & t2Mask) + res[3] = (t1[3] & ^t2Mask) | (t2[3] & t2Mask) +} + +func ImplicitSig(sPriv, ePriv, t []byte) ([]byte, error) { + mulRes, err := P256OrdMul(ePriv, t) + if err != nil { + return nil, err + } + t1, err := fromBytes(mulRes) + if err != nil { + return nil, err + } + t2, err := fromBytes(sPriv) + if err != nil { + return nil, err + } + var t3 [4]uint64 + p256OrdAdd(&t3, t1, t2) + return toBytes(&t3), nil +} diff --git a/internal/sm2ec/sm2p256_mqv_test.go b/internal/sm2ec/sm2p256_mqv_test.go new file mode 100644 index 0000000..c790975 --- /dev/null +++ b/internal/sm2ec/sm2p256_mqv_test.go @@ -0,0 +1,48 @@ +package sm2ec_test + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "io" + "math/big" + "testing" + + "github.com/emmansun/gmsm/internal/sm2ec" +) + +func randomK(r io.Reader, ord *big.Int) (k *big.Int, err error) { + for { + k, err = rand.Int(r, ord) + if k.Sign() > 0 || err != nil { + return + } + } +} + +func TestImplicitSig(t *testing.T) { + n, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16) + sPriv, err := randomK(rand.Reader, n) + if err != nil { + t.Fatal(err) + } + ePriv, err := randomK(rand.Reader, n) + if err != nil { + t.Fatal(err) + } + k, err := randomK(rand.Reader, n) + if err != nil { + t.Fatal(err) + } + res1, err := sm2ec.ImplicitSig(sPriv.Bytes(), ePriv.Bytes(), k.Bytes()) + if err != nil { + t.Fatal(err) + } + res2 := new(big.Int) + res2.Mul(ePriv, k) + res2.Add(res2, sPriv) + res2.Mod(res2, n) + if !bytes.Equal(res1, res2.Bytes()) { + t.Errorf("expected %s, got %s", hex.EncodeToString(res1), hex.EncodeToString(res2.Bytes())) + } +} diff --git a/internal/sm2ec/sm2p256_ord.go b/internal/sm2ec/sm2p256_ord.go new file mode 100644 index 0000000..a3aeac8 --- /dev/null +++ b/internal/sm2ec/sm2p256_ord.go @@ -0,0 +1,128 @@ +//go:build (!amd64 && !arm64) || generic +// +build !amd64,!arm64 generic + +package sm2ec + +import ( + "errors" + + "github.com/emmansun/gmsm/internal/sm2ec/fiat" +) + +// P256OrdInverse, sets out to in⁻¹ mod org(G). If in is zero, out will be zero. +// n-2 = +// 1111111111111111111111111111111011111111111111111111111111111111 +// 1111111111111111111111111111111111111111111111111111111111111111 +// 0111001000000011110111110110101100100001110001100000010100101011 +// 0101001110111011111101000000100100111001110101010100000100100001 +// +func P256OrdInverse(k []byte) ([]byte, error) { + if len(k) != 32 { + return nil, errors.New("invalid scalar length") + } + x := new(fiat.SM2P256OrderElement) + _1 := new(fiat.SM2P256OrderElement) + _, err := _1.SetBytes(k) + if err != nil { + return nil, err + } + + _11 := new(fiat.SM2P256OrderElement) + _101 := new(fiat.SM2P256OrderElement) + _111 := new(fiat.SM2P256OrderElement) + _1111 := new(fiat.SM2P256OrderElement) + _10101 := new(fiat.SM2P256OrderElement) + _101111 := new(fiat.SM2P256OrderElement) + t := new(fiat.SM2P256OrderElement) + m := new(fiat.SM2P256OrderElement) + + m.Square(_1) + _11.Mul(m, _1) + _101.Mul(m, _11) + _111.Mul(m, _101) + x.Square(_101) + _1111.Mul(_101, x) + + t.Square(x) + _10101.Mul(t, _1) + x.Square(_10101) + _101111.Mul(x, _101) + x.Mul(_10101, x) + t.Square(x) + t.Square(t) + + m.Mul(t, m) + t.Mul(t, _11) + x.Square(t) + for i := 1; i < 8; i++ { + x.Square(x) + } + m.Mul(x, m) + x.Mul(x, t) + + t.Square(x) + for i := 1; i < 16; i++ { + t.Square(t) + } + m.Mul(t, m) + t.Mul(t, x) + + x.Square(m) + for i := 1; i < 32; i++ { + x.Square(x) + } + x.Mul(x, t) + for i := 0; i < 32; i++ { + x.Square(x) + } + x.Mul(x, t) + for i := 0; i < 32; i++ { + x.Square(x) + } + x.Mul(x, t) + + sqrs := []uint8{ + 4, 3, 11, 5, 3, 5, 1, + 3, 7, 5, 9, 7, 5, 5, + 4, 5, 2, 2, 7, 3, 5, + 5, 6, 2, 6, 3, 5, + } + muls := []*fiat.SM2P256OrderElement{ + _111, _1, _1111, _1111, _101, _10101, _1, + _1, _111, _11, _101, _10101, _10101, _111, + _111, _1111, _11, _1, _1, _1, _111, + _111, _10101, _1, _1, _1, _1} + + for i, s := range sqrs { + for j := 0; j < int(s); j++ { + x.Square(x) + } + x.Mul(x, muls[i]) + } + + return x.Bytes(), nil + +} + +// P256OrdMul multiplication modulo org(G). +func P256OrdMul(in1, in2 []byte) ([]byte, error) { + if len(in1) != 32 || len(in2) != 32 { + return nil, errors.New("invalid scalar length") + } + ax := new(fiat.SM2P256OrderElement) + ay := new(fiat.SM2P256OrderElement) + res := new(fiat.SM2P256OrderElement) + + _, err := ax.SetBytes(in1) + if err != nil { + return nil, err + } + + _, err = ay.SetBytes(in2) + if err != nil { + return nil, err + } + + res = res.Mul(ax, ay) + return res.Bytes(), nil +} diff --git a/sm2/sm2_keyexchange.go b/sm2/sm2_keyexchange.go index f606bc4..f7436e4 100644 --- a/sm2/sm2_keyexchange.go +++ b/sm2/sm2_keyexchange.go @@ -214,7 +214,14 @@ func (ke *KeyExchange) mqv() { ke.v.X, ke.v.Y = ke.privateKey.ScalarMult(x, y, t.Bytes()) } -func respondKeyExchange(ke *KeyExchange, r *big.Int) (*ecdsa.PublicKey, []byte, error) { +func respondKeyExchange(ke *KeyExchange, rA *ecdsa.PublicKey, r *big.Int) (*ecdsa.PublicKey, []byte, error) { + if ke.peerPub == nil { + return nil, nil, errors.New("sm2: no peer public key given") + } + if !ke.privateKey.IsOnCurve(rA.X, rA.Y) { + return nil, nil, errors.New("sm2: invalid initiator's ephemeral public key") + } + ke.peerSecret = rA // secret = RB = [r]G ke.secret.X, ke.secret.Y = ke.privateKey.ScalarBaseMult(r.Bytes()) ke.r = r @@ -236,18 +243,11 @@ func respondKeyExchange(ke *KeyExchange, r *big.Int) (*ecdsa.PublicKey, []byte, // // It will check if there are peer's public key and validate the peer's Ephemeral Public Key. func (ke *KeyExchange) RepondKeyExchange(rand io.Reader, rA *ecdsa.PublicKey) (*ecdsa.PublicKey, []byte, error) { - if ke.peerPub == nil { - return nil, nil, errors.New("sm2: no peer public key given") - } - if !ke.privateKey.IsOnCurve(rA.X, rA.Y) { - return nil, nil, errors.New("sm2: invalid initiator's ephemeral public key") - } - ke.peerSecret = rA r, err := randFieldElement(ke.privateKey, rand) if err != nil { return nil, nil, err } - return respondKeyExchange(ke, r) + return respondKeyExchange(ke, rA, r) } // ConfirmResponder for initiator's step A4-A10, returns keying data and optional signature. diff --git a/sm2/sm2_keyexchange_test.go b/sm2/sm2_keyexchange_test.go index f3f7369..8ede3d2 100644 --- a/sm2/sm2_keyexchange_test.go +++ b/sm2/sm2_keyexchange_test.go @@ -1,22 +1,118 @@ package sm2 import ( + "bytes" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "encoding/hex" "errors" + "math/big" "testing" ) +var vectors = []struct { + LocalStaticPriv, LocalEphemeralPriv string + RemoteStaticPriv, RemoteEphemeralPriv string + SharedSecret, Key string +}{ + { + "e04c3fd77408b56a648ad439f673511a2ae248def3bab26bdfc9cdbd0ae9607e", + "6fe0bac5b09d3ab10f724638811c34464790520e4604e71e6cb0e5310623b5b1", + "7a1136f60d2c5531447e5a3093078c2a505abf74f33aefed927ac0a5b27e7dd7", + "d0233bdbb0b8a7bfe1aab66132ef06fc4efaedd5d5000692bc21185242a31f6f", + "046ab5c9709277837cedc515730d04751ef81c71e81e0e52357a98cf41796ab560508da6e858b40c6264f17943037434174284a847f32c4f54104a98af5148d89f", + "1ad809ebc56ddda532020c352e1e60b121ebeb7b4e632db4dd90a362cf844f8bba85140e30984ddb581199bf5a9dda22", + }, + { + "cb5ac204b38d0e5c9fc38a467075986754018f7dbb7cbbc5b4c78d56a88a8ad8", + "1681a66c02b67fdadfc53cba9b417b9499d0159435c86bb8760c3a03ae157539", + "4f54b10e0d8e9e2fe5cc79893e37fd0fd990762d1372197ed92dde464b2773ef", + "a2fe43dea141e9acc88226eaba8908ad17e81376c92102cb8186e8fef61a8700", + "04677d055355a1dcc9de4df00d3a80b6daa76bdf54ff7e0a3a6359fcd0c6f1e4b4697fffc41bbbcc3a28ea3aa1c6c380d1e92f142233afa4b430d02ab4cebc43b2", + "7a103ae61a30ed9df573a5febb35a9609cbed5681bcb98a8545351bf7d6824cc4635df5203712ea506e2e3c4ec9b12e7", + }, + { + "ee690a34a779ab48227a2f68b062a80f92e26d82835608dd01b7452f1e4fb296", + "2046c6cee085665e9f3abeba41fd38e17a26c08f2f5e8f0e1007afc0bf6a2a5d", + "8ef49ea427b13cc31151e1c96ae8a48cb7919063f2d342560fb7eaaffb93d8fe", + "9baf8d602e43fbae83fedb7368f98c969d378b8a647318f8cafb265296ae37de", + "04f7e9f1447968b284ff43548fcec3752063ea386b48bfabb9baf2f9c1caa05c2fb12c2cca37326ce27e68f8cc6414c2554895519c28da1ca21e61890d0bc525c4", + "b18e78e5072f301399dc1f4baf2956c0ed2d5f52f19abb1705131b0865b079031259ee6c629b4faed528bcfa1c5d2cbc", + }, +} + +func hexDecode(t *testing.T, s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + t.Fatal("invalid hex string:", s) + } + return b +} + func TestKeyExchangeSample(t *testing.T) { + initiatorUID := []byte("Alice") + responderUID := []byte("Bob") + kenLen := 48 + + for i, v := range vectors { + priv1 := new(PrivateKey) + priv1.D, _ = new(big.Int).SetString(v.LocalStaticPriv, 16) + priv1.Curve = P256() + priv1.X, priv1.Y = priv1.Curve.ScalarBaseMult(priv1.D.Bytes()) + + priv2 := new(PrivateKey) + priv2.D, _ = new(big.Int).SetString(v.RemoteStaticPriv, 16) + priv2.Curve = P256() + priv2.X, priv2.Y = priv1.Curve.ScalarBaseMult(priv2.D.Bytes()) + + initiator, err := NewKeyExchange(priv1, &priv2.PublicKey, initiatorUID, responderUID, kenLen, true) + if err != nil { + t.Fatal(err) + } + responder, err := NewKeyExchange(priv2, &priv1.PublicKey, responderUID, initiatorUID, 48, true) + if err != nil { + t.Fatal(err) + } + defer func() { + initiator.Destroy() + responder.Destroy() + }() + rA, _ := new(big.Int).SetString(v.LocalEphemeralPriv, 16) + initKeyExchange(initiator, rA) + + rB, _ := new(big.Int).SetString(v.RemoteEphemeralPriv, 16) + RB, s2, _ := respondKeyExchange(responder, initiator.secret, rB) + + key1, s1, err := initiator.ConfirmResponder(RB, s2) + if err != nil { + t.Fatal(err) + } + key2, err := responder.ConfirmInitiator(s1) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(key1, key2) { + t.Errorf("got different key") + } + if !bytes.Equal(key1, hexDecode(t, v.Key)) { + t.Errorf("case %v got unexpected keying data", i) + } + if !bytes.Equal(elliptic.Marshal(initiator.v.Curve, initiator.v.X, initiator.v.Y), hexDecode(t, v.SharedSecret)) { + t.Errorf("case %v got unexpected shared key", i) + } + } +} + +func TestKeyExchange(t *testing.T) { priv1, _ := GenerateKey(rand.Reader) priv2, _ := GenerateKey(rand.Reader) - initiator, err := NewKeyExchange(priv1, &priv2.PublicKey, []byte("Alice"), []byte("Bob"), 32, true) + initiator, err := NewKeyExchange(priv1, &priv2.PublicKey, []byte("Alice"), []byte("Bob"), 48, true) if err != nil { t.Fatal(err) } - responder, err := NewKeyExchange(priv2, &priv1.PublicKey, []byte("Bob"), []byte("Alice"), 32, true) + responder, err := NewKeyExchange(priv2, &priv1.PublicKey, []byte("Bob"), []byte("Alice"), 48, true) if err != nil { t.Fatal(err) } diff --git a/sm2/sm2ec/sm2ec.go b/sm2/sm2ec/sm2ec.go index da99f9e..1110dbc 100644 --- a/sm2/sm2ec/sm2ec.go +++ b/sm2/sm2ec/sm2ec.go @@ -174,3 +174,21 @@ func (curve *sm2Curve) UnmarshalCompressed(data []byte) (x, y *big.Int) { } return curve.pointToAffine(p) } + +// Inverse, implements invertible interface, used by Sign() +func (curve *sm2Curve) Inverse(k *big.Int) *big.Int { + if k.Sign() < 0 { + // This should never happen. + k = new(big.Int).Neg(k) + } + if k.Cmp(curve.params.N) >= 0 { + // This should never happen. + k = new(big.Int).Mod(k, curve.params.N) + } + scalar := k.FillBytes(make([]byte, 32)) + inverse, err := _sm2ec.P256OrdInverse(scalar) + if err != nil { + panic("sm2/elliptic: sm2 rejected normalized scalar") + } + return new(big.Int).SetBytes(inverse) +} diff --git a/sm2/sm2ec/sm2ec_asm.go b/sm2/sm2ec/sm2ec_asm.go deleted file mode 100644 index a6859fe..0000000 --- a/sm2/sm2ec/sm2ec_asm.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build (amd64 && !generic) || (arm64 && !generic) -// +build amd64,!generic arm64,!generic - -package sm2ec - -import ( - "math/big" - - _sm2ec "github.com/emmansun/gmsm/internal/sm2ec" -) - -// Inverse, implements invertible interface, used by Sign() -func (curve *sm2Curve) Inverse(k *big.Int) *big.Int { - if k.Sign() < 0 { - // This should never happen. - k = new(big.Int).Neg(k) - } - if k.Cmp(curve.params.N) >= 0 { - // This should never happen. - k = new(big.Int).Mod(k, curve.params.N) - } - scalar := k.FillBytes(make([]byte, 32)) - inverse, err := _sm2ec.P256OrdInverse(scalar) - if err != nil { - panic("sm2/elliptic: sm2 rejected normalized scalar") - } - return new(big.Int).SetBytes(inverse) -}