From 44898a8c91e5bfdb597ba3337e453566f63ca51aa8381e937ed6b2d1e5ea68c4 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 13 Feb 2025 18:34:33 +0300 Subject: [PATCH] Reorganise code, import third-parties --- go/cm/algo.go | 44 - go/cm/av.go | 52 - go/cm/cmd/enctool/main.go | 77 +- go/cm/cmd/hshtool/main.go | 6 +- go/cm/cmd/keytool/main.go | 89 +- go/cm/cmd/sigtool/main.go | 39 +- go/cm/ed25519-blake2b/.gitignore | 4 - go/cm/ed25519-blake2b/clean | 4 - .../ed25519-blake2b/ed25519-to-blake2b.patch | 153 - go/cm/ed25519-blake2b/mk-from-go | 30 - go/cm/{encrypted => enc}/balloon.go | 0 go/cm/enc/dem.go | 6 + go/cm/{encrypted => enc}/kem.go | 0 go/cm/enc/magic.go | 5 + go/cm/enc/mceliece6960119-x25519/README | 4 + .../{ => enc}/mceliece6960119-x25519/algo.go | 0 go/cm/{ => enc}/mceliece6960119-x25519/kp.go | 10 +- .../mceliece6960119/benes.go | 133 + .../mceliece6960119/fft.go | 208 ++ .../mceliece6960119/internal/controlbits.go | 248 ++ .../mceliece6960119/internal/djbsort.go | 92 + .../mceliece6960119/internal/fft_const.go | 3096 +++++++++++++++++ .../mceliece6960119/internal/powers.go | 2828 +++++++++++++++ .../mceliece6960119/math/gf2e12/gf4096.go | 83 + .../mceliece6960119/math/gf2e13/gf8192.go | 130 + .../mceliece6960119/mceliece.go | 733 ++++ .../mceliece6960119/operations.go | 57 + .../mceliece6960119/pk_gen.go | 280 ++ .../mceliece6960119/vec.go | 132 + go/cm/{ => enc}/sntrup4591761-x25519/algo.go | 0 go/cm/{ => enc}/sntrup4591761-x25519/kp.go | 0 go/cm/go.mod | 12 +- go/cm/go.sum | 12 + go/cm/hash/algo.go | 10 +- .../{ed25519-blake2b => hash/blake2b}/algo.go | 0 .../blake2b}/hasher.go | 0 go/cm/hash/gost/algo.go | 8 + go/cm/{ => hash}/gost/hasher.go | 5 - go/cm/hash/magic.go | 5 + go/cm/mceliece6960119-x25519/SOURCE | 3 - go/cm/sign/ed25519-blake2b/README | 4 + go/cm/sign/ed25519-blake2b/algo.go | 7 + go/cm/sign/ed25519-blake2b/ed25519/ed25519.go | 325 ++ .../edwards25519/alias/alias.go | 30 + .../edwards25519/byteorder/byteorder.go | 149 + .../sign/ed25519-blake2b/edwards25519/doc.go | 22 + .../edwards25519/edwards25519.go | 430 +++ .../edwards25519/field/_asm/fe_amd64_asm.go | 294 ++ .../edwards25519/field/_asm/go.mod | 12 + .../edwards25519/field/_asm/go.sum | 32 + .../ed25519-blake2b/edwards25519/field/fe.go | 423 +++ .../edwards25519/field/fe_amd64.go | 15 + .../edwards25519/field/fe_amd64.s | 378 ++ .../edwards25519/field/fe_amd64_noasm.go | 11 + .../edwards25519/field/fe_arm64.go | 15 + .../edwards25519/field/fe_arm64.s | 42 + .../edwards25519/field/fe_arm64_noasm.go | 11 + .../edwards25519/field/fe_generic.go | 266 ++ .../ed25519-blake2b/edwards25519/scalar.go | 349 ++ .../edwards25519/scalar_fiat.go | 1147 ++++++ .../edwards25519/scalarmult.go | 214 ++ .../edwards25519/subtle/constant_time.go | 60 + .../edwards25519/subtle/xor.go | 30 + .../edwards25519/subtle/xor_amd64.go | 10 + .../edwards25519/subtle/xor_amd64.s | 58 + .../edwards25519/subtle/xor_arm64.go | 10 + .../edwards25519/subtle/xor_arm64.s | 69 + .../edwards25519/subtle/xor_generic.go | 64 + .../edwards25519/subtle/xor_loong64.go | 10 + .../edwards25519/subtle/xor_loong64.s | 166 + .../edwards25519/subtle/xor_ppc64x.go | 10 + .../edwards25519/subtle/xor_ppc64x.s | 142 + .../ed25519-blake2b/edwards25519/tables.go | 129 + go/cm/{ => sign}/ed25519-blake2b/kp.go | 11 +- go/cm/{ => sign}/ed25519-blake2b/signer.go | 48 +- go/cm/{ => sign}/ed25519-blake2b/verify.go | 32 +- go/cm/{ => sign}/gost/gost.go | 6 +- go/cm/{ => sign}/gost/kp.go | 0 go/cm/{ => sign}/gost/signer.go | 25 +- go/cm/{ => sign}/gost/verify.go | 8 +- go/cm/sign/iface.go | 6 +- go/cm/sign/mode.go | 11 - go/cm/sign/mode/mode.go | 11 + go/cm/{ => sign}/prv.go | 18 +- go/cm/{ => sign}/pub.go | 31 +- go/cm/{ => sign}/signed.go | 11 +- go/cm/sntrup4591761-x25519/go.mod | 5 - go/cm/sntrup4591761-x25519/go.sum | 2 - go/cm/utils/utils.go | 40 - go/go.mod | 7 +- go/go.sum | 8 +- 91 files changed, 13260 insertions(+), 552 deletions(-) delete mode 100644 go/cm/algo.go delete mode 100644 go/cm/ed25519-blake2b/.gitignore delete mode 100755 go/cm/ed25519-blake2b/clean delete mode 100644 go/cm/ed25519-blake2b/ed25519-to-blake2b.patch delete mode 100755 go/cm/ed25519-blake2b/mk-from-go rename go/cm/{encrypted => enc}/balloon.go (100%) create mode 100644 go/cm/enc/dem.go rename go/cm/{encrypted => enc}/kem.go (100%) create mode 100644 go/cm/enc/magic.go create mode 100644 go/cm/enc/mceliece6960119-x25519/README rename go/cm/{ => enc}/mceliece6960119-x25519/algo.go (100%) rename go/cm/{ => enc}/mceliece6960119-x25519/kp.go (83%) create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/benes.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/fft.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/controlbits.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/djbsort.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/fft_const.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/powers.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e12/gf4096.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e13/gf8192.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/mceliece.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/operations.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/pk_gen.go create mode 100644 go/cm/enc/mceliece6960119-x25519/mceliece6960119/vec.go rename go/cm/{ => enc}/sntrup4591761-x25519/algo.go (100%) rename go/cm/{ => enc}/sntrup4591761-x25519/kp.go (100%) rename go/cm/{ed25519-blake2b => hash/blake2b}/algo.go (100%) rename go/cm/{ed25519-blake2b => hash/blake2b}/hasher.go (100%) create mode 100644 go/cm/hash/gost/algo.go rename go/cm/{ => hash}/gost/hasher.go (90%) create mode 100644 go/cm/hash/magic.go delete mode 100644 go/cm/mceliece6960119-x25519/SOURCE create mode 100644 go/cm/sign/ed25519-blake2b/README create mode 100644 go/cm/sign/ed25519-blake2b/algo.go create mode 100644 go/cm/sign/ed25519-blake2b/ed25519/ed25519.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/alias/alias.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/byteorder/byteorder.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/doc.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/edwards25519.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/fe_amd64_asm.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/go.mod create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/go.sum create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/fe.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64.s create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64_noasm.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64.s create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64_noasm.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/field/fe_generic.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/scalar.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/scalar_fiat.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/scalarmult.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/constant_time.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_amd64.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_amd64.s create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_arm64.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_arm64.s create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_generic.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_loong64.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_loong64.s create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_ppc64x.go create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_ppc64x.s create mode 100644 go/cm/sign/ed25519-blake2b/edwards25519/tables.go rename go/cm/{ => sign}/ed25519-blake2b/kp.go (82%) rename go/cm/{ => sign}/ed25519-blake2b/signer.go (70%) rename go/cm/{ => sign}/ed25519-blake2b/verify.go (69%) rename go/cm/{ => sign}/gost/gost.go (86%) rename go/cm/{ => sign}/gost/kp.go (100%) rename go/cm/{ => sign}/gost/signer.go (86%) rename go/cm/{ => sign}/gost/verify.go (94%) delete mode 100644 go/cm/sign/mode.go create mode 100644 go/cm/sign/mode/mode.go rename go/cm/{ => sign}/prv.go (80%) rename go/cm/{ => sign}/pub.go (93%) rename go/cm/{ => sign}/signed.go (94%) delete mode 100644 go/cm/sntrup4591761-x25519/go.mod delete mode 100644 go/cm/sntrup4591761-x25519/go.sum delete mode 100644 go/cm/utils/utils.go diff --git a/go/cm/algo.go b/go/cm/algo.go deleted file mode 100644 index 94b0da7..0000000 --- a/go/cm/algo.go +++ /dev/null @@ -1,44 +0,0 @@ -// GoKEKS/CM -- KEKS-encoded cryptographic messages -// Copyright (C) 2024-2025 Sergey Matveev -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, version 3 of the License. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this program. If not, see . - -package cm - -import ( - "go.cypherpunks.su/keks" - ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b" - "go.cypherpunks.su/keks/cm/gost" - mceliece6960119x25519 "go.cypherpunks.su/keks/cm/mceliece6960119-x25519" - sntrup4591761x25519 "go.cypherpunks.su/keks/cm/sntrup4591761-x25519" -) - -const ( - BalloonBLAKE2bHKDF = "balloon-blake2b-hkdf" - ChaCha20Poly1305 = "chacha20poly1305" - ClassicMcEliece6960119X25519 = mceliece6960119x25519.ClassicMcEliece6960119X25519 - ClassicMcEliece6960119X25519HKDFSHAKE256 = mceliece6960119x25519.ClassicMcEliece6960119X25519HKDFSHAKE256 - Ed25519BLAKE2b = ed25519blake2b.Ed25519BLAKE2b - Ed25519PhBLAKE2b = ed25519blake2b.Ed25519PhBLAKE2b - Ed25519PhBLAKE2bMerkle = ed25519blake2b.Ed25519PhBLAKE2bMerkle - GOST3410256A = gost.GOST3410256A - GOST3410256AMerkle = gost.GOST3410256AMerkle - GOST3410512C = gost.GOST3410512C - GOST3410512CMerkle = gost.GOST3410512CMerkle - SNTRUP4591761X25519 = sntrup4591761x25519.SNTRUP4591761X25519 - SNTRUP4591761X25519HKDFBLAKE2b = sntrup4591761x25519.SNTRUP4591761X25519HKDFBLAKE2b - - EncryptedMagic = keks.Magic("cm/encrypted") - HashedMagic = keks.Magic("cm/hashed") - PrvMagic = keks.Magic("cm/prv") -) diff --git a/go/cm/av.go b/go/cm/av.go index fa920cb..3e4d05a 100644 --- a/go/cm/av.go +++ b/go/cm/av.go @@ -1,59 +1,7 @@ -// GoKEKS/CM -- KEKS-encoded cryptographic messages -// Copyright (C) 2024-2025 Sergey Matveev -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, version 3 of the License. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this program. If not, see . - package cm -import ( - "bytes" - "hash" - - "github.com/google/uuid" - - "go.cypherpunks.su/keks" - cmhash "go.cypherpunks.su/keks/cm/hash" -) - // Algorithm-value often used structure. type AV struct { A string `keks:"a"` V []byte `keks:"v"` } - -// Calculate UUID of the AV. UUIDv4 is generated from the hash output of -// the av structure. Hash algorithm selection depends on av.A. uuid.Nil -// is returned if algorithm is not supported. -func (av *AV) Id() (id uuid.UUID) { - var hasher hash.Hash - switch av.A { - case Ed25519BLAKE2b, SNTRUP4591761X25519: - hasher = cmhash.ByName(cmhash.BLAKE2b256) - case GOST3410256A, GOST3410512C: - hasher = cmhash.ByName(cmhash.Streebog256) - case ClassicMcEliece6960119X25519: - hasher = cmhash.ByName(cmhash.SHAKE128) - default: - id = uuid.Nil - return - } - _, err := keks.Encode(hasher, av, nil) - if err != nil { - panic(err) - } - id, err = uuid.NewRandomFromReader(bytes.NewReader(hasher.Sum(nil))) - if err != nil { - panic(err) - } - return -} diff --git a/go/cm/cmd/enctool/main.go b/go/cm/cmd/enctool/main.go index e5213a4..c9c12fd 100644 --- a/go/cm/cmd/enctool/main.go +++ b/go/cm/cmd/enctool/main.go @@ -28,8 +28,6 @@ import ( "log" "os" - circlkem "github.com/cloudflare/circl/kem" - "github.com/cloudflare/circl/kem/mceliece/mceliece6960119" "github.com/companyzero/sntrup4591761" "github.com/google/uuid" "go.cypherpunks.su/balloon/v3" @@ -39,9 +37,12 @@ import ( "go.cypherpunks.su/keks" "go.cypherpunks.su/keks/cm" - cmenc "go.cypherpunks.su/keks/cm/encrypted" + cmenc "go.cypherpunks.su/keks/cm/enc" + mceliece6960119x25519 "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519" + mceliece6960119 "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119" + sntrup4591761x25519 "go.cypherpunks.su/keks/cm/enc/sntrup4591761-x25519" cmhash "go.cypherpunks.su/keks/cm/hash" - "go.cypherpunks.su/keks/cm/utils" + "go.cypherpunks.su/keks/cm/sign" "go.cypherpunks.su/keks/types" ) @@ -53,6 +54,14 @@ func blake2bHash() hash.Hash { return h } +func mustReadFile(p string) []byte { + data, err := os.ReadFile(p) + if err != nil { + log.Fatalln("read:", p, err) + } + return data +} + func readPasswd(prompt string) (passwd []byte) { if raw := os.Getenv("ENCTOOL_PASSPHRASE"); raw != "" { return []byte(raw) @@ -87,9 +96,9 @@ func main() { balloonT := flag.Int("balloon-t", 3, "Balloon's time cost") balloonP := flag.Int("balloon-p", 2, "Balloon's number of threads") doDecrypt := flag.Bool("d", false, "Decrypt") - var pubs []*cm.Pub + var pubs []*sign.Pub flag.Func("pub", "Path to public key to encrypt to", func(v string) error { - signed, err := cm.PubParse(utils.MustReadFile(v)) + signed, err := sign.PubParse(mustReadFile(v)) if err != nil { return err } @@ -97,8 +106,8 @@ func main() { if load.KU == nil { log.Println(v, "does not have key usages") } else { - if _, ok := (*load.KU)[cm.KUKEM]; !ok { - log.Println(v, "does not have", cm.KUKEM, "key usage") + if _, ok := (*load.KU)[sign.KUKEM]; !ok { + log.Println(v, "does not have", sign.KUKEM, "key usage") } } if len(load.Pub) != 1 { @@ -109,8 +118,8 @@ func main() { }) var prvs []*cm.AV flag.Func("prv", "Our private keys for decryption", func(v string) (err error) { - magic, data := keks.StripMagic(utils.MustReadFile(v)) - if magic == "" || magic != cm.PrvMagic { + magic, data := keks.StripMagic(mustReadFile(v)) + if magic == "" || magic != sign.PrvMagic { return errors.New("wrong magic") } var av cm.AV @@ -136,7 +145,7 @@ func main() { if t != types.Magic { log.Fatal("no magic met") } - if d.Iter().Magic() != cm.EncryptedMagic { + if d.Iter().Magic() != cmenc.Magic { log.Fatal("wrong magic") } } @@ -148,7 +157,7 @@ func main() { log.Fatal(err) } } - if encrypted.DEM.A != cm.ChaCha20Poly1305 { + if encrypted.DEM.A != cmenc.ChaCha20Poly1305 { log.Fatalln("unsupported DEM:", encrypted.DEM.A) } if len(encrypted.KEM) == 0 { @@ -156,7 +165,7 @@ func main() { } for kemIdx, kem := range encrypted.KEM { switch kem.A { - case cm.BalloonBLAKE2bHKDF: + case cmenc.BalloonBLAKE2bHKDF: if !*passphrase { log.Println(kemIdx, kem.A, "skipping because no -passwd") continue @@ -195,7 +204,7 @@ func main() { } cek = cekp } - case cm.SNTRUP4591761X25519HKDFBLAKE2b: + case sntrup4591761x25519.SNTRUP4591761X25519HKDFBLAKE2b: if len(prvs) == 0 { log.Println(kemIdx, kem.A, "skipping because no -prv") continue @@ -207,7 +216,7 @@ func main() { log.Fatalln("invalid encap len") } for _, prv := range prvs { - if prv.A != cm.SNTRUP4591761X25519 { + if prv.A != sntrup4591761x25519.SNTRUP4591761X25519 { continue } if len(prv.V) != sntrup4591761.PrivateKeySize+32 { @@ -279,7 +288,7 @@ func main() { break } } - case cm.ClassicMcEliece6960119X25519HKDFSHAKE256: + case mceliece6960119x25519.ClassicMcEliece6960119X25519HKDFSHAKE256: if len(prvs) == 0 { log.Println(kemIdx, kem.A, "skipping because no -prv") continue @@ -287,19 +296,18 @@ func main() { if kem.Encap == nil { log.Fatalln("missing encap") } - scheme := mceliece6960119.Scheme() - if len(*kem.Encap) != scheme.CiphertextSize()+32 { + if len(*kem.Encap) != mceliece6960119.CiphertextSize+32 { log.Fatalln("invalid encap len") } for _, prv := range prvs { - if prv.A != cm.ClassicMcEliece6960119X25519 { + if prv.A != mceliece6960119x25519.ClassicMcEliece6960119X25519 { continue } - if len(prv.V) != scheme.PrivateKeySize()+32 { + if len(prv.V) != mceliece6960119.PrivateKeySize+32 { log.Fatalln("invalid private keys len") } - var ourMcEliece circlkem.PrivateKey - ourMcEliece, err = scheme.UnmarshalBinaryPrivateKey( + var ourMcEliece *mceliece6960119.PrivateKey + ourMcEliece, err = mceliece6960119.UnmarshalBinaryPrivateKey( prv.V[:len(prv.V)-32], ) if err != nil { @@ -313,7 +321,7 @@ func main() { } theirMcEliece := (*kem.Encap)[:len(*kem.Encap)-32] var keyMcEliece []byte - keyMcEliece, err = scheme.Decapsulate(ourMcEliece, theirMcEliece) + keyMcEliece, err = mceliece6960119.Decapsulate(ourMcEliece, theirMcEliece) if err != nil { log.Fatal(err) } @@ -418,7 +426,7 @@ func main() { log.Fatal(err) } kem := cmenc.KEM{ - A: cm.BalloonBLAKE2bHKDF, + A: cmenc.BalloonBLAKE2bHKDF, Salt: &bSalt, Cost: &cmenc.BalloonCost{ S: uint64(*balloonS), @@ -450,7 +458,7 @@ func main() { } for _, pub := range pubs { switch pub.A { - case cm.SNTRUP4591761X25519: + case sntrup4591761x25519.SNTRUP4591761X25519: if len(pub.V) != sntrup4591761.PublicKeySize+32 { log.Fatalln("invalid public keys len") } @@ -483,7 +491,7 @@ func main() { if err != nil { log.Fatal(err) } - kem := cmenc.KEM{A: cm.SNTRUP4591761X25519HKDFBLAKE2b} + kem := cmenc.KEM{A: sntrup4591761x25519.SNTRUP4591761X25519HKDFBLAKE2b} encap := append(ciphertext[:], ourPubX25519.Bytes()...) kem.Encap = &encap { @@ -515,13 +523,12 @@ func main() { kem.To = &pub.Id } kems = append(kems, kem) - case cm.ClassicMcEliece6960119X25519: - scheme := mceliece6960119.Scheme() - if len(pub.V) != scheme.PublicKeySize()+32 { + case mceliece6960119x25519.ClassicMcEliece6960119X25519: + if len(pub.V) != mceliece6960119.PublicKeySize+32 { log.Fatalln("invalid public keys len") } - var theirMcEliece circlkem.PublicKey - theirMcEliece, err = scheme.UnmarshalBinaryPublicKey( + var theirMcEliece *mceliece6960119.PublicKey + theirMcEliece, err = mceliece6960119.UnmarshalBinaryPublicKey( pub.V[:len(pub.V)-32], ) if err != nil { @@ -535,7 +542,7 @@ func main() { } var ciphertext []byte var keyMcEliece []byte - ciphertext, keyMcEliece, err = scheme.Encapsulate(theirMcEliece) + ciphertext, keyMcEliece, err = mceliece6960119.Encapsulate(theirMcEliece) if err != nil { log.Fatal(err) } @@ -550,7 +557,7 @@ func main() { if err != nil { log.Fatal(err) } - kem := cmenc.KEM{A: cm.ClassicMcEliece6960119X25519HKDFSHAKE256} + kem := cmenc.KEM{A: mceliece6960119x25519.ClassicMcEliece6960119X25519HKDFSHAKE256} encap := append(ciphertext[:], ourPubX25519.Bytes()...) kem.Encap = &encap { @@ -591,13 +598,13 @@ func main() { } { var hdr bytes.Buffer - if _, err = keks.Encode(&hdr, cm.EncryptedMagic, nil); err != nil { + if _, err = keks.Encode(&hdr, cmenc.Magic, nil); err != nil { log.Fatal(err) } if _, err = keks.Encode(&hdr, &cmenc.Encrypted{ Salt: salt, KEM: kems, - DEM: cmenc.DEM{A: cm.ChaCha20Poly1305}, + DEM: cmenc.DEM{A: cmenc.ChaCha20Poly1305}, }, nil); err != nil { log.Fatal(err) } diff --git a/go/cm/cmd/hshtool/main.go b/go/cm/cmd/hshtool/main.go index eab2399..6c2b9e3 100644 --- a/go/cm/cmd/hshtool/main.go +++ b/go/cm/cmd/hshtool/main.go @@ -11,9 +11,9 @@ import ( "go.cypherpunks.su/gogost/v6/gost34112012256" "go.cypherpunks.su/gogost/v6/gost34112012512" - ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b" - "go.cypherpunks.su/keks/cm/gost" cmhash "go.cypherpunks.su/keks/cm/hash" + cmblake2b "go.cypherpunks.su/keks/cm/hash/blake2b" + "go.cypherpunks.su/keks/cm/hash/gost" "go.cypherpunks.su/keks/cm/hash/merkle" ) @@ -37,7 +37,7 @@ func main() { var hasher *merkle.Hasher switch *algo { case cmhash.BLAKE2bMerkle: - hasher = ed25519blake2b.NewMerkleHasher(chunkLen, *workers).(*merkle.Hasher) + hasher = cmblake2b.NewMerkleHasher(chunkLen, *workers).(*merkle.Hasher) case cmhash.SHA2512 + "-merkle": hasher = merkle.NewHasherPrefixed(sha512.New, chunkLen, *workers) case cmhash.SHAKE128Merkle: diff --git a/go/cm/cmd/keytool/main.go b/go/cm/cmd/keytool/main.go index 5822ace..1b74bfc 100644 --- a/go/cm/cmd/keytool/main.go +++ b/go/cm/cmd/keytool/main.go @@ -20,22 +20,32 @@ import ( "errors" "flag" "fmt" + "hash" "log" "os" "sort" "strings" "time" + "github.com/google/uuid" "go.cypherpunks.su/keks" "go.cypherpunks.su/keks/cm" - ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b" - "go.cypherpunks.su/keks/cm/gost" - mceliece6960119x25519 "go.cypherpunks.su/keks/cm/mceliece6960119-x25519" + mceliece6960119x25519 "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519" + sntrup4591761x25519 "go.cypherpunks.su/keks/cm/enc/sntrup4591761-x25519" + cmhash "go.cypherpunks.su/keks/cm/hash" "go.cypherpunks.su/keks/cm/sign" - sntrup4591761x25519 "go.cypherpunks.su/keks/cm/sntrup4591761-x25519" - "go.cypherpunks.su/keks/cm/utils" + ed25519blake2b "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b" + "go.cypherpunks.su/keks/cm/sign/gost" ) +func mustReadFile(p string) []byte { + data, err := os.ReadFile(p) + if err != nil { + log.Fatalln("read:", p, err) + } + return data +} + func main() { flag.Usage = usage ku := make(map[string]*struct{}) @@ -73,7 +83,8 @@ func main() { "Optional notBefore, \"2006-01-02 15:04:05\" format") lifetime := flag.Uint("lifetime", 365, "Lifetime of the certification, days") - algo := flag.String("algo", cm.Ed25519BLAKE2b, "Public key algorithm") + algo := flag.String("algo", ed25519blake2b.Ed25519BLAKE2b, + "Public key algorithm") issuingPrv := flag.String("ca-prv", "", "Path to private key file for issuing with") prvPath := flag.String("prv", "", "Path to private key file") @@ -86,11 +97,11 @@ func main() { if *doList { algos := []string{ - cm.Ed25519BLAKE2b, - cm.GOST3410256A, - cm.GOST3410512C, - cm.SNTRUP4591761X25519, - cm.ClassicMcEliece6960119X25519, + ed25519blake2b.Ed25519BLAKE2b, + gost.GOST3410256A, + gost.GOST3410512C, + sntrup4591761x25519.SNTRUP4591761X25519, + mceliece6960119x25519.ClassicMcEliece6960119X25519, } sort.Strings(algos) for _, s := range algos { @@ -116,10 +127,10 @@ func main() { till := since.Add(time.Duration(*lifetime) * 24 * time.Hour) var caPrv sign.Iface - var caPubs []*cm.Signed + var caPubs []*sign.Signed for _, issuingPub := range issuingPubs { - var signed *cm.Signed - signed, err = cm.PubParse(utils.MustReadFile(issuingPub)) + var signed *sign.Signed + signed, err = sign.PubParse(mustReadFile(issuingPub)) if err != nil { log.Fatal(err) } @@ -129,15 +140,15 @@ func main() { if *issuingPrv == "" { log.Fatal("no -ca-prv is set") } - caPrv, _, err = cm.PrvParse(utils.MustReadFile(*issuingPrv)) + caPrv, _, err = sign.PrvParse(mustReadFile(*issuingPrv)) if err != nil { log.Fatal(err) } } if *verify { - var signed *cm.Signed - signed, err = cm.PubParse(utils.MustReadFile(*pubPath)) + var signed *sign.Signed + signed, err = sign.PubParse(mustReadFile(*pubPath)) if err != nil { log.Fatal(err) } @@ -149,10 +160,10 @@ func main() { } var prvRaw []byte - var pubLoad *cm.PubLoad - var signed *cm.Signed + var pubLoad *sign.PubLoad + var signed *sign.Signed if caPrv != nil { - signed, err = cm.PubParse(utils.MustReadFile(*pubPath)) + signed, err = sign.PubParse(mustReadFile(*pubPath)) if err != nil { log.Fatal(err) } @@ -166,13 +177,13 @@ func main() { log.Fatal("no -prv is set") } switch *algo { - case cm.Ed25519BLAKE2b: + case ed25519blake2b.Ed25519BLAKE2b: _, prvRaw, pub, err = ed25519blake2b.NewKeypair() - case cm.GOST3410256A, cm.GOST3410512C: + case gost.GOST3410256A, gost.GOST3410512C: _, prvRaw, pub, err = gost.NewKeypair(*algo) - case cm.SNTRUP4591761X25519: + case sntrup4591761x25519.SNTRUP4591761X25519: prvRaw, pub, err = sntrup4591761x25519.NewKeypair() - case cm.ClassicMcEliece6960119X25519: + case mceliece6960119x25519.ClassicMcEliece6960119X25519: prvRaw, pub, err = mceliece6960119x25519.NewKeypair() default: err = errors.New("unknown -algo specified") @@ -182,7 +193,7 @@ func main() { } { var buf bytes.Buffer - if _, err = keks.Encode(&buf, cm.PrvMagic, nil); err != nil { + if _, err = keks.Encode(&buf, sign.PrvMagic, nil); err != nil { log.Fatal(err) } if _, err = keks.Encode(&buf, cm.AV{A: *algo, V: prvRaw}, nil); err != nil { @@ -194,12 +205,30 @@ func main() { } } { - pubMap := cm.Pub{A: *algo, V: pub} + pubMap := sign.Pub{A: *algo, V: pub} { av := cm.AV{A: *algo, V: pub} - pubMap.Id = av.Id() + var hasher hash.Hash + switch av.A { + case ed25519blake2b.Ed25519BLAKE2b, sntrup4591761x25519.SNTRUP4591761X25519: + hasher = cmhash.ByName(cmhash.BLAKE2b256) + case gost.GOST3410256A, gost.GOST3410512C: + hasher = cmhash.ByName(cmhash.Streebog256) + case mceliece6960119x25519.ClassicMcEliece6960119X25519: + hasher = cmhash.ByName(cmhash.SHAKE128) + default: + log.Fatal("unsupported algorithm") + } + _, err = keks.Encode(hasher, av, nil) + if err != nil { + log.Fatal(err) + } + pubMap.Id, err = uuid.NewRandomFromReader(bytes.NewReader(hasher.Sum(nil))) + if err != nil { + log.Fatal(err) + } } - pubLoad = &cm.PubLoad{Subj: subj, Pub: []cm.Pub{pubMap}} + pubLoad = &sign.PubLoad{Subj: subj, Pub: []sign.Pub{pubMap}} } if len(ku) > 0 { pubLoad.KU = &ku @@ -208,7 +237,7 @@ func main() { { pubLoadAny := any(pubLoad) - signed = &cm.Signed{Load: cm.SignedLoad{T: "pub", V: &pubLoadAny}} + signed = &sign.Signed{Load: sign.SignedLoad{T: "pub", V: &pubLoadAny}} } if caPrv != nil { @@ -221,7 +250,7 @@ func main() { { var buf bytes.Buffer - if _, err = keks.Encode(&buf, cm.PubMagic, nil); err != nil { + if _, err = keks.Encode(&buf, sign.PubMagic, nil); err != nil { log.Fatal(err) } if _, err = keks.Encode(&buf, signed, nil); err != nil { diff --git a/go/cm/cmd/sigtool/main.go b/go/cm/cmd/sigtool/main.go index afc9192..92c64f5 100644 --- a/go/cm/cmd/sigtool/main.go +++ b/go/cm/cmd/sigtool/main.go @@ -29,15 +29,22 @@ import ( "github.com/google/uuid" "go.cypherpunks.su/keks" - "go.cypherpunks.su/keks/cm" cmhash "go.cypherpunks.su/keks/cm/hash" "go.cypherpunks.su/keks/cm/sign" - "go.cypherpunks.su/keks/cm/utils" + "go.cypherpunks.su/keks/cm/sign/mode" "go.cypherpunks.su/keks/types" ) const BlobChunkLen = 128 * 1024 +func mustReadFile(p string) []byte { + data, err := os.ReadFile(p) + if err != nil { + log.Fatalln("read:", p, err) + } + return data +} + func main() { log.SetFlags(log.Lshortfile) flag.Usage = usage @@ -62,7 +69,7 @@ func main() { if *pubPath == "" { log.Fatal("no -pub is set") } - pub, err := cm.PubParse(utils.MustReadFile(*pubPath)) + pub, err := sign.PubParse(mustReadFile(*pubPath)) if err != nil { log.Fatal(err) } @@ -75,18 +82,18 @@ func main() { if err != nil { log.Fatal(err) } - if t != types.Magic || decoder.Iter().Magic() != cm.SignedMagic { + if t != types.Magic || decoder.Iter().Magic() != sign.SignedMagic { log.Fatal("wrong magic") } decoder = keks.NewDecoderFromReader(stdin, nil) if _, err = decoder.Parse(); err != nil { log.Fatal(err) } - var prehash cm.SignedPrehash - var signed cm.Signed + var prehash sign.SignedPrehash + var signed sign.Signed err = decoder.UnmarshalStruct(&prehash) var hasher hash.Hash - if err == nil && prehash.T == sign.PrehashT { + if err == nil && prehash.T == mode.PrehashT { if len(prehash.Sigs) == 0 { log.Fatal("prehash: no sigs") } @@ -126,7 +133,7 @@ func main() { if err != nil { log.Fatal(err) } - if err = cm.SignedValidate(&signed); err != nil { + if err = sign.SignedValidate(&signed); err != nil { log.Fatal(err) } if len(signed.Sigs) == 0 { @@ -169,20 +176,20 @@ func main() { log.Fatal("no -prv is set") } var signer sign.Iface - signer, _, err = cm.PrvParse(utils.MustReadFile(*prvPath)) + signer, _, err = sign.PrvParse(mustReadFile(*prvPath)) if err != nil { log.Fatal(err) } if *doMerkle { - err = signer.SetMode(sign.ModeMerkle) + err = signer.SetMode(mode.Merkle) } else { - err = signer.SetMode(sign.ModePrehash) + err = signer.SetMode(mode.Prehash) } if err != nil { log.Fatal(err) } - if _, err = keks.Encode(os.Stdout, cm.SignedMagic, nil); err != nil { + if _, err = keks.Encode(os.Stdout, sign.SignedMagic, nil); err != nil { log.Fatal(err) } if *detached { @@ -190,8 +197,8 @@ func main() { log.Fatal(err) } } else { - if _, err = keks.Encode(os.Stdout, cm.SignedPrehash{ - T: sign.PrehashT, + if _, err = keks.Encode(os.Stdout, sign.SignedPrehash{ + T: mode.PrehashT, Sigs: map[string]*struct{}{signer.Algo(): nil}, }, nil); err != nil { log.Fatal(err) @@ -212,9 +219,9 @@ func main() { log.Fatal(err) } } - var signed cm.Signed + var signed sign.Signed signed.Load.T = *typ - var sigTbs cm.SigTBS + var sigTbs sign.SigTBS if !*noWhen { when := time.Now().UTC().Truncate(time.Millisecond) sigTbs.When = &when diff --git a/go/cm/ed25519-blake2b/.gitignore b/go/cm/ed25519-blake2b/.gitignore deleted file mode 100644 index ca24282..0000000 --- a/go/cm/ed25519-blake2b/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -byteorder/ -ed25519/ -edwards25519/ -go.mod diff --git a/go/cm/ed25519-blake2b/clean b/go/cm/ed25519-blake2b/clean deleted file mode 100755 index 6132ba6..0000000 --- a/go/cm/ed25519-blake2b/clean +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -e - -cd "$(dirname "$(realpath -- "$0")")" -exec rm -rf byteorder ed25519 edwards25519 go.mod diff --git a/go/cm/ed25519-blake2b/ed25519-to-blake2b.patch b/go/cm/ed25519-blake2b/ed25519-to-blake2b.patch deleted file mode 100644 index 80d2a25..0000000 --- a/go/cm/ed25519-blake2b/ed25519-to-blake2b.patch +++ /dev/null @@ -1,153 +0,0 @@ ---- ed25519/ed25519.go 2024-12-03 10:59:27.811011000 +0300 -+++ ed25519/ed25519.go 2024-12-03 11:07:51.892841000 +0300 -@@ -20,11 +20,12 @@ - "crypto" - "go.cypherpunks.su/keks/cm/ed25519-blake2b/edwards25519" - cryptorand "crypto/rand" -- "crypto/sha512" - "crypto/subtle" - "errors" - "io" - "strconv" -+ -+ "golang.org/x/crypto/blake2b" - ) - - const ( -@@ -81,13 +82,13 @@ - - // Sign signs the given message with priv. rand is ignored and can be nil. - // --// If opts.HashFunc() is [crypto.SHA512], the pre-hashed variant Ed25519ph is used --// and message is expected to be a SHA-512 hash, otherwise opts.HashFunc() must -+// If opts.HashFunc() is [crypto.BLAKE2b_512], the pre-hashed variant Ed25519ph is used -+// and message is expected to be a BLAKE2b-512 hash, otherwise opts.HashFunc() must - // be [crypto.Hash](0) and the message must not be hashed, as Ed25519 performs two - // passes over messages to be signed. - // - // A value of type [Options] can be used as opts, or crypto.Hash(0) or --// crypto.SHA512 directly to select plain Ed25519 or Ed25519ph, respectively. -+// crypto.BLAKE2b_512 directly to select plain Ed25519 or Ed25519ph, respectively. - func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { - hash := opts.HashFunc() - context := "" -@@ -95,8 +96,8 @@ - context = opts.Context - } - switch { -- case hash == crypto.SHA512: // Ed25519ph -- if l := len(message); l != sha512.Size { -+ case hash == crypto.BLAKE2b_512: // Ed25519ph -+ if l := len(message); l != blake2b.Size { - return nil, errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l)) - } - if l := len(context); l > 255 { -@@ -122,7 +123,7 @@ - // Options can be used with [PrivateKey.Sign] or [VerifyWithOptions] - // to select Ed25519 variants. - type Options struct { -- // Hash can be zero for regular Ed25519, or crypto.SHA512 for Ed25519ph. -+ // Hash can be zero for regular Ed25519, or crypto.BLAKE2b_512 for Ed25519ph. - Hash crypto.Hash - - // Context, if not empty, selects Ed25519ctx or provides the context string -@@ -171,7 +172,7 @@ - panic("ed25519: bad seed length: " + strconv.Itoa(l)) - } - -- h := sha512.Sum512(seed) -+ h := blake2b.Sum512(seed) - s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) - if err != nil { - panic("ed25519: internal error: setting scalar failed") -@@ -213,14 +214,17 @@ - } - seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:] - -- h := sha512.Sum512(seed) -+ h := blake2b.Sum512(seed) - s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) - if err != nil { - panic("ed25519: internal error: setting scalar failed") - } - prefix := h[32:] - -- mh := sha512.New() -+ mh, err := blake2b.New512(nil) -+ if err != nil { -+ panic(err) -+ } - if domPrefix != domPrefixPure { - mh.Write([]byte(domPrefix)) - mh.Write([]byte{byte(len(context))}) -@@ -228,7 +232,7 @@ - } - mh.Write(prefix) - mh.Write(message) -- messageDigest := make([]byte, 0, sha512.Size) -+ messageDigest := make([]byte, 0, blake2b.Size) - messageDigest = mh.Sum(messageDigest) - r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest) - if err != nil { -@@ -237,7 +241,10 @@ - - R := (&edwards25519.Point{}).ScalarBaseMult(r) - -- kh := sha512.New() -+ kh, err := blake2b.New512(nil) -+ if err != nil { -+ panic(err) -+ } - if domPrefix != domPrefixPure { - kh.Write([]byte(domPrefix)) - kh.Write([]byte{byte(len(context))}) -@@ -246,7 +253,7 @@ - kh.Write(R.Bytes()) - kh.Write(publicKey) - kh.Write(message) -- hramDigest := make([]byte, 0, sha512.Size) -+ hramDigest := make([]byte, 0, blake2b.Size) - hramDigest = kh.Sum(hramDigest) - k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) - if err != nil { -@@ -272,7 +279,7 @@ - // publicKey. A valid signature is indicated by returning a nil error. It will - // panic if len(publicKey) is not [PublicKeySize]. - // --// If opts.Hash is [crypto.SHA512], the pre-hashed variant Ed25519ph is used and -+// If opts.Hash is [crypto.BLAKE2b_512], the pre-hashed variant Ed25519ph is used and - // message is expected to be a SHA-512 hash, otherwise opts.Hash must be - // [crypto.Hash](0) and the message must not be hashed, as Ed25519 performs two - // passes over messages to be signed. -@@ -281,8 +288,8 @@ - // channels, or if an attacker has control of part of the inputs. - func VerifyWithOptions(publicKey PublicKey, message, sig []byte, opts *Options) error { - switch { -- case opts.Hash == crypto.SHA512: // Ed25519ph -- if l := len(message); l != sha512.Size { -+ case opts.Hash == crypto.BLAKE2b_512: // Ed25519ph -+ if l := len(message); l != blake2b.Size { - return errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l)) - } - if l := len(opts.Context); l > 255 { -@@ -324,7 +331,10 @@ - return false - } - -- kh := sha512.New() -+ kh, err := blake2b.New512(nil) -+ if err != nil { -+ panic(err) -+ } - if domPrefix != domPrefixPure { - kh.Write([]byte(domPrefix)) - kh.Write([]byte{byte(len(context))}) -@@ -333,7 +343,7 @@ - kh.Write(sig[:32]) - kh.Write(publicKey) - kh.Write(message) -- hramDigest := make([]byte, 0, sha512.Size) -+ hramDigest := make([]byte, 0, blake2b.Size) - hramDigest = kh.Sum(hramDigest) - k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) - if err != nil { diff --git a/go/cm/ed25519-blake2b/mk-from-go b/go/cm/ed25519-blake2b/mk-from-go deleted file mode 100755 index 1c9408c..0000000 --- a/go/cm/ed25519-blake2b/mk-from-go +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -e -# Unfortunately native crypto/ed25519 is not flexible enough and does -# not give ability to use different hash in Ed25519. -# That script copies the library (tested on 1.23.3) and patches it to -# use BLAKE2b hash. - -modname=go.cypherpunks.su/keks/cm/ed25519-blake2b -go mod init $modname -dst=$PWD -cd $(go env GOROOT)/src -cp -r crypto/ed25519 crypto/internal/edwards25519 internal/byteorder $dst -cd $dst - -cd ed25519 -rm -r testdata -rm *_test.go -cd .. - -cd edwards25519 -rm doc.go *_test.go -cd .. - -find . -name "*.go" -exec perl -i -npe 's#^(\s+)".*/?internal/(.*)"#$1"'$modname'/$2"#' {} + - -cd edwards25519/field/_asm -go mod edit -module $modname/edwards25519/field/_asm -perl -i -npe "s#crypto/internal#$modname#" fe_amd64_asm.go - -cd $dst -patch = 0; iter-- { + for i := 0; i < 64; i++ { + bIntV[i] = load8(bitsPtr) + bitsPtr = bitsPtr[8:] + } + layerIn(&rIntV, &bIntV, iter) + } + + transpose64x64(&rIntH[0], &rIntV[0]) + transpose64x64(&rIntH[1], &rIntV[1]) + + for iter := 6; iter >= 0; iter-- { + for i := 0; i < 64; i++ { + bIntV[i] = load8(bitsPtr) + bitsPtr = bitsPtr[8:] + } + transpose64x64(&bIntH, &bIntV) + layerEx(&rIntH, &bIntH, iter) + } + + transpose64x64(&rIntV[0], &rIntH[0]) + transpose64x64(&rIntV[1], &rIntH[1]) + + for i := 0; i < 64; i++ { + store8(r[i*16+0:], rIntV[0][i]) + store8(r[i*16+8:], rIntV[1][i]) + } +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/fft.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/fft.go new file mode 100644 index 0000000..270331c --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/fft.go @@ -0,0 +1,208 @@ +// Code generated from fft_other.templ.go. DO NOT EDIT. + +// The following code is translated from the C `vec` Additional Implementation +// from the NIST round 4 submission package. + +package mceliece6960119 + +import "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119/internal" + +func fft(out *[exponent][gfBits]uint64, in *[2][gfBits]uint64) { + radixConversions(in) + butterflies(out, in) +} + +func radixConversions(in *[2][gfBits]uint64) { + for j := 0; j <= 5; j++ { + for i := 0; i < gfBits; i++ { + in[1][i] ^= in[1][i] >> 32 + in[0][i] ^= in[1][i] << 32 + } + + for i := 0; i < gfBits; i++ { + for k := 4; k >= j; k-- { + in[0][i] ^= (in[0][i] & internal.RadixConversionsMask[k][0]) >> (1 << k) + in[0][i] ^= (in[0][i] & internal.RadixConversionsMask[k][1]) >> (1 << k) + in[1][i] ^= (in[1][i] & internal.RadixConversionsMask[k][0]) >> (1 << k) + in[1][i] ^= (in[1][i] & internal.RadixConversionsMask[k][1]) >> (1 << k) + } + } + + if j < 5 { + vecMul(&in[0], &in[0], &internal.RadixConversionsS[j][0]) + vecMul(&in[1], &in[1], &internal.RadixConversionsS[j][1]) + } + } +} + +func butterflies(out *[exponent][gfBits]uint64, in *[2][gfBits]uint64) { + tmp := [gfBits]uint64{} + pre := [8][gfBits]uint64{} + buf := [128]uint64{} + constsPtr := 2 + for i := 0; i < 7; i++ { + for j := 0; j < gfBits; j++ { + pre[i][j] = uint64(internal.ButterfliesBeta[i]>>j) & 1 + pre[i][j] = -pre[i][j] + } + + vecMul(&pre[i], &in[1], &pre[i]) + } + for i := 0; i < gfBits; i++ { + buf[0] = in[0][i] + + buf[1] = buf[0] ^ pre[0][i] + buf[32] = in[0][i] ^ pre[5][i] + buf[3] = buf[1] ^ pre[1][i] + buf[96] = buf[32] ^ pre[6][i] + buf[97] = buf[96] ^ pre[0][i] + buf[2] = in[0][i] ^ pre[1][i] + buf[99] = buf[97] ^ pre[1][i] + buf[6] = buf[2] ^ pre[2][i] + buf[98] = buf[99] ^ pre[0][i] + buf[7] = buf[6] ^ pre[0][i] + buf[102] = buf[98] ^ pre[2][i] + buf[5] = buf[7] ^ pre[1][i] + buf[103] = buf[102] ^ pre[0][i] + buf[101] = buf[103] ^ pre[1][i] + buf[4] = in[0][i] ^ pre[2][i] + buf[100] = buf[101] ^ pre[0][i] + buf[12] = buf[4] ^ pre[3][i] + buf[108] = buf[100] ^ pre[3][i] + buf[13] = buf[12] ^ pre[0][i] + buf[109] = buf[108] ^ pre[0][i] + buf[15] = buf[13] ^ pre[1][i] + buf[111] = buf[109] ^ pre[1][i] + buf[14] = buf[15] ^ pre[0][i] + buf[110] = buf[111] ^ pre[0][i] + buf[10] = buf[14] ^ pre[2][i] + buf[106] = buf[110] ^ pre[2][i] + buf[11] = buf[10] ^ pre[0][i] + buf[107] = buf[106] ^ pre[0][i] + buf[9] = buf[11] ^ pre[1][i] + buf[105] = buf[107] ^ pre[1][i] + buf[104] = buf[105] ^ pre[0][i] + buf[8] = in[0][i] ^ pre[3][i] + buf[120] = buf[104] ^ pre[4][i] + buf[24] = buf[8] ^ pre[4][i] + buf[121] = buf[120] ^ pre[0][i] + buf[25] = buf[24] ^ pre[0][i] + buf[123] = buf[121] ^ pre[1][i] + buf[27] = buf[25] ^ pre[1][i] + buf[122] = buf[123] ^ pre[0][i] + buf[26] = buf[27] ^ pre[0][i] + buf[126] = buf[122] ^ pre[2][i] + buf[30] = buf[26] ^ pre[2][i] + buf[127] = buf[126] ^ pre[0][i] + buf[31] = buf[30] ^ pre[0][i] + buf[125] = buf[127] ^ pre[1][i] + buf[29] = buf[31] ^ pre[1][i] + buf[124] = buf[125] ^ pre[0][i] + buf[28] = buf[29] ^ pre[0][i] + buf[116] = buf[124] ^ pre[3][i] + buf[20] = buf[28] ^ pre[3][i] + buf[117] = buf[116] ^ pre[0][i] + buf[21] = buf[20] ^ pre[0][i] + buf[119] = buf[117] ^ pre[1][i] + buf[23] = buf[21] ^ pre[1][i] + buf[118] = buf[119] ^ pre[0][i] + buf[22] = buf[23] ^ pre[0][i] + buf[114] = buf[118] ^ pre[2][i] + buf[18] = buf[22] ^ pre[2][i] + buf[115] = buf[114] ^ pre[0][i] + buf[19] = buf[18] ^ pre[0][i] + buf[113] = buf[115] ^ pre[1][i] + buf[17] = buf[19] ^ pre[1][i] + buf[112] = buf[113] ^ pre[0][i] + buf[80] = buf[112] ^ pre[5][i] + buf[16] = in[0][i] ^ pre[4][i] + buf[81] = buf[80] ^ pre[0][i] + buf[48] = buf[16] ^ pre[5][i] + buf[83] = buf[81] ^ pre[1][i] + buf[49] = buf[48] ^ pre[0][i] + buf[82] = buf[83] ^ pre[0][i] + buf[51] = buf[49] ^ pre[1][i] + buf[86] = buf[82] ^ pre[2][i] + buf[50] = buf[51] ^ pre[0][i] + buf[87] = buf[86] ^ pre[0][i] + buf[54] = buf[50] ^ pre[2][i] + buf[85] = buf[87] ^ pre[1][i] + buf[55] = buf[54] ^ pre[0][i] + buf[84] = buf[85] ^ pre[0][i] + buf[53] = buf[55] ^ pre[1][i] + buf[92] = buf[84] ^ pre[3][i] + buf[52] = buf[53] ^ pre[0][i] + buf[93] = buf[92] ^ pre[0][i] + buf[60] = buf[52] ^ pre[3][i] + buf[95] = buf[93] ^ pre[1][i] + buf[61] = buf[60] ^ pre[0][i] + buf[94] = buf[95] ^ pre[0][i] + buf[63] = buf[61] ^ pre[1][i] + buf[90] = buf[94] ^ pre[2][i] + buf[62] = buf[63] ^ pre[0][i] + buf[91] = buf[90] ^ pre[0][i] + buf[58] = buf[62] ^ pre[2][i] + buf[89] = buf[91] ^ pre[1][i] + buf[59] = buf[58] ^ pre[0][i] + buf[88] = buf[89] ^ pre[0][i] + buf[57] = buf[59] ^ pre[1][i] + buf[72] = buf[88] ^ pre[4][i] + buf[56] = buf[57] ^ pre[0][i] + buf[73] = buf[72] ^ pre[0][i] + buf[40] = buf[56] ^ pre[4][i] + buf[75] = buf[73] ^ pre[1][i] + buf[41] = buf[40] ^ pre[0][i] + buf[74] = buf[75] ^ pre[0][i] + buf[43] = buf[41] ^ pre[1][i] + buf[78] = buf[74] ^ pre[2][i] + buf[42] = buf[43] ^ pre[0][i] + buf[79] = buf[78] ^ pre[0][i] + buf[46] = buf[42] ^ pre[2][i] + buf[77] = buf[79] ^ pre[1][i] + buf[47] = buf[46] ^ pre[0][i] + buf[76] = buf[77] ^ pre[0][i] + buf[45] = buf[47] ^ pre[1][i] + buf[68] = buf[76] ^ pre[3][i] + buf[44] = buf[45] ^ pre[0][i] + buf[69] = buf[68] ^ pre[0][i] + buf[36] = buf[44] ^ pre[3][i] + buf[71] = buf[69] ^ pre[1][i] + buf[37] = buf[36] ^ pre[0][i] + buf[70] = buf[71] ^ pre[0][i] + buf[39] = buf[37] ^ pre[1][i] + buf[66] = buf[70] ^ pre[2][i] + buf[38] = buf[39] ^ pre[0][i] + buf[67] = buf[66] ^ pre[0][i] + buf[34] = buf[38] ^ pre[2][i] + buf[65] = buf[67] ^ pre[1][i] + buf[35] = buf[34] ^ pre[0][i] + buf[33] = buf[35] ^ pre[1][i] + buf[64] = in[0][i] ^ pre[6][i] + + transpose64x64((*[64]uint64)(buf[:64]), (*[64]uint64)(buf[:64])) + transpose64x64((*[64]uint64)(buf[64:]), (*[64]uint64)(buf[64:])) + + for j := 0; j < 128; j++ { + out[internal.ButterfliesReversal[j]][i] = buf[j] + } + } + + for i := 1; i <= 6; i++ { + s := 1 << i + + for j := 0; j < 128; j += 2 * s { + for k := j; k < j+s; k++ { + vecMul(&tmp, &out[k+s], &internal.ButterfliesConst[constsPtr+(k-j)]) + + for b := 0; b < gfBits; b++ { + out[k][b] ^= tmp[b] + } + for b := 0; b < gfBits; b++ { + out[k+s][b] ^= out[k][b] + } + } + } + + constsPtr += 1 << i + } +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/controlbits.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/controlbits.go new file mode 100644 index 0000000..d49a7a4 --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/controlbits.go @@ -0,0 +1,248 @@ +// This file is for implementing the Nassimi-Sahni algorithm +// See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" +// See also https://cr.yp.to/papers/controlbits-20200923.pdf + +package internal + +import ( + "unsafe" +) + +// layer implements one layer of the Beneš network. +// It permutes elements `p` according to control bits `cb` in-place. +// Thus, one layer of the Beneš network is created and if some control bits are set +// the corresponding transposition is applied. Parameter `s` equals `n.len()` and +// `s` configures `stride-2^s` conditional swaps. +func layer(p []int16, cb []byte, s, n int) { + stride := 1 << s + index := 0 + for i := int(0); i < n; i += stride * 2 { + for j := int(0); j < stride; j++ { + d := p[i+j] ^ p[i+j+stride] + m := int16(cb[index>>3]>>(index&7)) & 1 + m = -m + d &= m + p[i+j] ^= d + p[i+j+stride] ^= d + index++ + } + } +} + +// cbRecursion implements a recursion step of controlbitsfrompermutation. +// Pick `w ∈ {1, 2, …, 14}. Let `n = 2^w`. +// `out` must be a reference to a slice with `((2*w-1)*(1<<(w-1))+7)/8` or more bytes. +// It must zero-initialized before the first recursive call. +// `step` is initialized with 0 and doubles in each recursion step. +// `pi_offset` is an offset within temp slice ref (or aux in the first recursive call). +// `temp` is an intermediate reference to a slice used for recursive computation and +// temporarily stores values. It must be able to carry at least 2・n elements. +// `aux` is an auxiliary reference to a slice. It points to the elements to be permuted. +// After the first recursive iterations, the elements are stored in `temp` and thus `aux` +// won't be read anymore. The first `n/2` elements are read. +// nolint:funlen +func cbRecursion(out []byte, pos, step int, pi []int16, w, n int32, temp []int32) { + A := temp + B := temp[n:] + if w == 1 { + out[pos>>3] ^= byte(pi[0] << (pos & 7)) + return + } + + for x := int32(0); x < n; x++ { + A[x] = (int32(pi[x]^1) << 16) | int32(pi[x^1]) + } + int32Sort(A, n) // A = (id<<16)+pibar + + for x := int32(0); x < n; x++ { + Ax := A[x] + px := Ax & 0xffff + cx := px + if x < cx { + cx = x + } + B[x] = (px << 16) | cx + } + // B = (p<<16)+c + + for x := int32(0); x < n; x++ { + A[x] = (A[x] << 16) | x + } + int32Sort(A, n) // A = (id<<16)+pibar^-1 + + for x := int32(0); x < n; x++ { + // A = (pibar^(-1)<<16)+pibar + A[x] = (A[x] << 16) + (B[x] >> 16) + } + int32Sort(A, n) // A = (id<<16)+pibar^2 + + if w <= 10 { + for x := int32(0); x < n; x++ { + B[x] = ((A[x] & 0xffff) << 10) | (B[x] & 0x3ff) + } + + for i := int32(1); i < w-1; i++ { + /* B = (p<<10)+c */ + + for x := int32(0); x < n; x++ { + A[x] = ((B[x] & ^0x3ff) << 6) | x /* A = (p<<16)+id */ + } + int32Sort(A, n) /* A = (id<<16)+p^{-1} */ + + for x := int32(0); x < n; x++ { + A[x] = (A[x] << 20) | B[x] /* A = (p^{-1}<<20)+(p<<10)+c */ + } + int32Sort(A, n) /* A = (id<<20)+(pp<<10)+cp */ + + for x := int32(0); x < n; x++ { + ppcpx := A[x] & 0xfffff + ppcx := (A[x] & 0xffc00) | (B[x] & 0x3ff) + if ppcpx < ppcx { + ppcx = ppcpx + } + B[x] = ppcx + } + } + + for x := int32(0); x < n; x++ { + B[x] &= 0x3ff + } + } else { + for x := int32(0); x < n; x++ { + B[x] = (A[x] << 16) | (B[x] & 0xffff) + } + + for i := int32(1); i < w-1; i++ { + /* B = (p<<16)+c */ + + for x := int32(0); x < n; x++ { + A[x] = (B[x] &^ 0xffff) | x + } + int32Sort(A, n) /* A = (id<<16)+p^(-1) */ + + for x := int32(0); x < n; x++ { + A[x] = (A[x] << 16) | (B[x] & 0xffff) + } + /* A = p^(-1)<<16+c */ + + if i < w-2 { + for x := int32(0); x < n; x++ { + B[x] = (A[x] & ^0xffff) | (B[x] >> 16) + } + /* B = (p^(-1)<<16)+p */ + int32Sort(B, n) /* B = (id<<16)+p^(-2) */ + for x := int32(0); x < n; x++ { + B[x] = (B[x] << 16) | (A[x] & 0xffff) + } + /* B = (p^(-2)<<16)+c */ + } + + int32Sort(A, n) + /* A = id<<16+cp */ + for x := int32(0); x < n; x++ { + cpx := (B[x] & ^0xffff) | (A[x] & 0xffff) + if cpx < B[x] { + B[x] = cpx + } + } + } + + for x := int32(0); x < n; x++ { + B[x] &= 0xffff + } + } + + for x := int32(0); x < n; x++ { + A[x] = (int32(pi[x]) << 16) + x + } + int32Sort(A, n) /* A = (id<<16)+pi^(-1) */ + + for j := int32(0); j < n/2; j++ { + x := 2 * j + fj := B[x] & 1 /* f[j] */ + Fx := x + fj /* F[x] */ + Fx1 := Fx ^ 1 /* F[x+1] */ + + out[pos>>3] ^= byte(fj << (pos & 7)) + pos += step + + B[x] = (A[x] << 16) | Fx + B[x+1] = (A[x+1] << 16) | Fx1 + } + /* B = (pi^(-1)<<16)+F */ + + int32Sort(B, n) /* B = (id<<16)+F(pi) */ + + pos += int(2*w-3) * step * int(n/2) + + for k := int32(0); k < n/2; k++ { + y := 2 * k + lk := B[y] & 1 /* l[k] */ + Ly := y + lk /* L[y] */ + Ly1 := Ly ^ 1 /* L[y+1] */ + + out[pos>>3] ^= byte(lk << (pos & 7)) + pos += step + + A[y] = (Ly << 16) | (B[y] & 0xffff) + A[y+1] = (Ly1 << 16) | (B[y+1] & 0xffff) + } + /* A = (L<<16)+F(pi) */ + + int32Sort(A, n) /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= int(2*w-2) * step * int(n/2) + + p := (*int16)(unsafe.Pointer(&temp[n+n/4])) + q := unsafe.Slice(p, n) // q can start anywhere between temp+n and temp+n/2 + for j := int32(0); j < n/2; j++ { + q[j] = int16(A[2*j]&0xffff) >> 1 + q[j+n/2] = int16(A[2*j+1]&0xffff) >> 1 + } + + cbRecursion(out, pos, step*2, q, w-1, n/2, temp) + cbRecursion(out, pos+step, step*2, q[n/2:], w-1, n/2, temp) +} + +// ControlBitsFromPermutation computes control bits +// parameters: 1 <= w <= 14; n = 2^w +// input: permutation pi of {0,1,...,n-1} +// output: (2m-1)n/2 control bits at positions 0,1,... +// output position pos is by definition 1&(out[pos/8]>>(pos&7)) +func ControlBitsFromPermutation(out []byte, pi []int16, w, n int32) { + temp := make([]int32, 2*n) + piTest := make([]int16, n) + var ptr []byte + for { + for i := 0; i < int(((2*w-1)*n/2)+7)/8; i++ { + out[i] = 0 + } + + cbRecursion(out, 0, 1, pi[:], w, n, temp) + // check for correctness + + for i := int32(0); i < n; i++ { + piTest[i] = int16(i) + } + + ptr = out + for i := 0; i < int(w); i++ { + layer(piTest, ptr, i, int(n)) + ptr = ptr[n>>4:] + } + + for i := int(w - 2); i >= 0; i-- { + layer(piTest, ptr, i, int(n)) + ptr = ptr[n>>4:] + } + + diff := int16(0) + for i := int32(0); i < n; i++ { + diff |= pi[i] ^ piTest[i] + } + + if diff == 0 { + break + } + } +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/djbsort.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/djbsort.go new file mode 100644 index 0000000..72210b8 --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/djbsort.go @@ -0,0 +1,92 @@ +package internal + +// Returns (min(a, b), max(a, b)), executes in constant time +func minMaxI32(a, b *int32) { + ab := *b ^ *a + c := *b - *a + c ^= ab & (c ^ *b) + c >>= 31 + c &= ab + *a ^= c + *b ^= c +} + +// Returns (min(a, b), max(a, b)), executes in constant time +// +// This differs from the C implementation, because the C implementation +// only works for 63-bit integers. +// +// Instead this implementation is based on +// “side-channel effective overflow check of variable c” +// from the book “Hacker's Delight” 2–13 Overflow Detection, +// Section Unsigned Add/Subtract p. 40 +func minMaxU64(a, b *uint64) { + c := (^*b & *a) | ((^*b | *a) & (*b - *a)) + c = -(c >> 63) + c &= *a ^ *b + *a ^= c + *b ^= c +} + +// Reference: [djbsort](https://sorting.cr.yp.to/). +func int32Sort(x []int32, n int32) { + if n < 2 { + return + } + top := int32(1) + for top < n-top { + top += top + } + for p := top; p > 0; p >>= 1 { + for i := int32(0); i < n-p; i++ { + if (i & p) == 0 { + minMaxI32(&x[i], &x[i+p]) + } + } + + i := int32(0) + for q := top; q > p; q >>= 1 { + for ; i < n-q; i++ { + if (i & p) == 0 { + a := x[i+p] + for r := q; r > p; r >>= 1 { + minMaxI32(&a, &x[i+r]) + } + x[i+p] = a + } + } + } + } +} + +// UInt64Sort sorts a slice of uint64 +// Reference: [djbsort](https://sorting.cr.yp.to/). +func UInt64Sort(x []uint64, n int) { + if n < 2 { + return + } + top := 1 + for top < n-top { + top += top + } + for p := top; p > 0; p >>= 1 { + for i := 0; i < n-p; i++ { + if (i & p) == 0 { + minMaxU64(&x[i], &x[i+p]) + } + } + + i := 0 + for q := top; q > p; q >>= 1 { + for ; i < n-q; i++ { + if (i & p) == 0 { + a := x[i+p] + for r := q; r > p; r >>= 1 { + minMaxU64(&a, &x[i+r]) + } + x[i+p] = a + } + } + } + } +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/fft_const.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/fft_const.go new file mode 100644 index 0000000..95eba56 --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/fft_const.go @@ -0,0 +1,3096 @@ +package internal + +import ( + "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e12" + "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e13" +) + +var ButterfliesReversal4096 = [64]byte{ + 0, 32, 16, 48, 8, 40, 24, 56, + 4, 36, 20, 52, 12, 44, 28, 60, + 2, 34, 18, 50, 10, 42, 26, 58, + 6, 38, 22, 54, 14, 46, 30, 62, + 1, 33, 17, 49, 9, 41, 25, 57, + 5, 37, 21, 53, 13, 45, 29, 61, + 3, 35, 19, 51, 11, 43, 27, 59, + 7, 39, 23, 55, 15, 47, 31, 63, +} + +var ButterfliesReversal = [128]byte{ + 0, 64, 32, 96, 16, 80, 48, 112, + 8, 72, 40, 104, 24, 88, 56, 120, + 4, 68, 36, 100, 20, 84, 52, 116, + 12, 76, 44, 108, 28, 92, 60, 124, + 2, 66, 34, 98, 18, 82, 50, 114, + 10, 74, 42, 106, 26, 90, 58, 122, + 6, 70, 38, 102, 22, 86, 54, 118, + 14, 78, 46, 110, 30, 94, 62, 126, + 1, 65, 33, 97, 17, 81, 49, 113, + 9, 73, 41, 105, 25, 89, 57, 121, + 5, 69, 37, 101, 21, 85, 53, 117, + 13, 77, 45, 109, 29, 93, 61, 125, + 3, 67, 35, 99, 19, 83, 51, 115, + 11, 75, 43, 107, 27, 91, 59, 123, + 7, 71, 39, 103, 23, 87, 55, 119, + 15, 79, 47, 111, 31, 95, 63, 127, +} + +var ButterfliesBeta = [7]uint16{2522, 7827, 7801, 8035, 6897, 8167, 3476} + +var RadixConversionsMask = [5][2]uint64{ + {0x8888888888888888, 0x4444444444444444}, + {0xC0C0C0C0C0C0C0C0, 0x3030303030303030}, + {0xF000F000F000F000, 0x0F000F000F000F00}, + {0xFF000000FF000000, 0x00FF000000FF0000}, + {0xFFFF000000000000, 0x0000FFFF00000000}, +} + +var ButterfliesConst = [128][gf2e13.Bits]uint64{ + { + 0x6969969669699696, + 0x9966669966999966, + 0x9966669966999966, + 0xFF0000FF00FFFF00, + 0xCC3333CCCC3333CC, + 0x9966669966999966, + 0x6666666666666666, + 0xA55AA55AA55AA55A, + 0xCCCC33333333CCCC, + 0x5A5A5A5A5A5A5A5A, + 0x55AAAA55AA5555AA, + 0x0FF0F00FF00F0FF0, + 0x5AA55AA5A55AA55A, + }, + { + 0x6969969669699696, + 0x9966669966999966, + 0x9966669966999966, + 0xFF0000FF00FFFF00, + 0xCC3333CCCC3333CC, + 0x9966669966999966, + 0x6666666666666666, + 0xA55AA55AA55AA55A, + 0xCCCC33333333CCCC, + 0x5A5A5A5A5A5A5A5A, + 0x55AAAA55AA5555AA, + 0x0FF0F00FF00F0FF0, + 0x5AA55AA5A55AA55A, + }, + { + 0xA55A5AA55AA5A55A, + 0x6969696996969696, + 0x5AA55AA5A55AA55A, + 0x9999999966666666, + 0x3C3CC3C3C3C33C3C, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xCC33CC3333CC33CC, + 0x0000000000000000, + 0x3C3C3C3C3C3C3C3C, + 0xAA5555AAAA5555AA, + 0xC33C3CC33CC3C33C, + 0x00FFFF0000FFFF00, + }, + { + 0xA55A5AA55AA5A55A, + 0x6969696996969696, + 0x5AA55AA5A55AA55A, + 0x6666666699999999, + 0xC3C33C3C3C3CC3C3, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x33CC33CCCC33CC33, + 0x0000000000000000, + 0x3C3C3C3C3C3C3C3C, + 0xAA5555AAAA5555AA, + 0xC33C3CC33CC3C33C, + 0xFF0000FFFF0000FF, + }, + { + 0xFFFFFFFF00000000, + 0xA5A5A5A55A5A5A5A, + 0x0FF0F00FF00F0FF0, + 0x9669966969966996, + 0x0000FFFFFFFF0000, + 0x33333333CCCCCCCC, + 0xA55A5AA55AA5A55A, + 0x00FFFF0000FFFF00, + 0x0000000000000000, + 0xC33CC33CC33CC33C, + 0x0F0FF0F00F0FF0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAA55555555AAAA, + }, + { + 0xFFFFFFFF00000000, + 0xA5A5A5A55A5A5A5A, + 0x0FF0F00FF00F0FF0, + 0x6996699696699669, + 0xFFFF00000000FFFF, + 0x33333333CCCCCCCC, + 0x5AA5A55AA55A5AA5, + 0xFF0000FFFF0000FF, + 0xFFFFFFFFFFFFFFFF, + 0xC33CC33CC33CC33C, + 0x0F0FF0F00F0FF0F0, + 0xCCCCCCCCCCCCCCCC, + 0x5555AAAAAAAA5555, + }, + { + 0xFFFFFFFF00000000, + 0x5A5A5A5AA5A5A5A5, + 0xF00F0FF00FF0F00F, + 0x6996699696699669, + 0x0000FFFFFFFF0000, + 0x33333333CCCCCCCC, + 0x5AA5A55AA55A5AA5, + 0xFF0000FFFF0000FF, + 0xFFFFFFFFFFFFFFFF, + 0xC33CC33CC33CC33C, + 0x0F0FF0F00F0FF0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAA55555555AAAA, + }, + { + 0xFFFFFFFF00000000, + 0x5A5A5A5AA5A5A5A5, + 0xF00F0FF00FF0F00F, + 0x9669966969966996, + 0xFFFF00000000FFFF, + 0x33333333CCCCCCCC, + 0xA55A5AA55AA5A55A, + 0x00FFFF0000FFFF00, + 0x0000000000000000, + 0xC33CC33CC33CC33C, + 0x0F0FF0F00F0FF0F0, + 0xCCCCCCCCCCCCCCCC, + 0x5555AAAAAAAA5555, + }, + { + 0xC33C3CC33CC3C33C, + 0x9966669966999966, + 0x9966996699669966, + 0x6969969669699696, + 0xAA55AA5555AA55AA, + 0x9966996699669966, + 0x5AA5A55A5AA5A55A, + 0xC3C3C3C33C3C3C3C, + 0x3CC33CC3C33CC33C, + 0x3333CCCC3333CCCC, + 0x9999999966666666, + 0xC33CC33CC33CC33C, + 0x6666999999996666, + }, + { + 0x3CC3C33CC33C3CC3, + 0x6699996699666699, + 0x6699669966996699, + 0x6969969669699696, + 0xAA55AA5555AA55AA, + 0x9966996699669966, + 0xA55A5AA5A55A5AA5, + 0xC3C3C3C33C3C3C3C, + 0x3CC33CC3C33CC33C, + 0x3333CCCC3333CCCC, + 0x6666666699999999, + 0x3CC33CC33CC33CC3, + 0x9999666666669999, + }, + { + 0xC33C3CC33CC3C33C, + 0x9966669966999966, + 0x6699669966996699, + 0x6969969669699696, + 0xAA55AA5555AA55AA, + 0x6699669966996699, + 0x5AA5A55A5AA5A55A, + 0x3C3C3C3CC3C3C3C3, + 0xC33CC33C3CC33CC3, + 0xCCCC3333CCCC3333, + 0x6666666699999999, + 0xC33CC33CC33CC33C, + 0x9999666666669999, + }, + { + 0x3CC3C33CC33C3CC3, + 0x6699996699666699, + 0x9966996699669966, + 0x6969969669699696, + 0xAA55AA5555AA55AA, + 0x6699669966996699, + 0xA55A5AA5A55A5AA5, + 0x3C3C3C3CC3C3C3C3, + 0xC33CC33C3CC33CC3, + 0xCCCC3333CCCC3333, + 0x9999999966666666, + 0x3CC33CC33CC33CC3, + 0x6666999999996666, + }, + { + 0xC33C3CC33CC3C33C, + 0x6699996699666699, + 0x6699669966996699, + 0x6969969669699696, + 0x55AA55AAAA55AA55, + 0x9966996699669966, + 0x5AA5A55A5AA5A55A, + 0xC3C3C3C33C3C3C3C, + 0xC33CC33C3CC33CC3, + 0x3333CCCC3333CCCC, + 0x9999999966666666, + 0xC33CC33CC33CC33C, + 0x6666999999996666, + }, + { + 0x3CC3C33CC33C3CC3, + 0x9966669966999966, + 0x9966996699669966, + 0x6969969669699696, + 0x55AA55AAAA55AA55, + 0x9966996699669966, + 0xA55A5AA5A55A5AA5, + 0xC3C3C3C33C3C3C3C, + 0xC33CC33C3CC33CC3, + 0x3333CCCC3333CCCC, + 0x6666666699999999, + 0x3CC33CC33CC33CC3, + 0x9999666666669999, + }, + { + 0xC33C3CC33CC3C33C, + 0x6699996699666699, + 0x9966996699669966, + 0x6969969669699696, + 0x55AA55AAAA55AA55, + 0x6699669966996699, + 0x5AA5A55A5AA5A55A, + 0x3C3C3C3CC3C3C3C3, + 0x3CC33CC3C33CC33C, + 0xCCCC3333CCCC3333, + 0x6666666699999999, + 0xC33CC33CC33CC33C, + 0x9999666666669999, + }, + { + 0x3CC3C33CC33C3CC3, + 0x9966669966999966, + 0x6699669966996699, + 0x6969969669699696, + 0x55AA55AAAA55AA55, + 0x6699669966996699, + 0xA55A5AA5A55A5AA5, + 0x3C3C3C3CC3C3C3C3, + 0x3CC33CC3C33CC33C, + 0xCCCC3333CCCC3333, + 0x9999999966666666, + 0x3CC33CC33CC33CC3, + 0x6666999999996666, + }, + { + 0x3C3CC3C3C3C33C3C, + 0x55555555AAAAAAAA, + 0xF00FF00F0FF00FF0, + 0x5AA55AA5A55AA55A, + 0x55AAAA55AA5555AA, + 0xF00F0FF0F00F0FF0, + 0x9669699696696996, + 0xA55AA55AA55AA55A, + 0x55555555AAAAAAAA, + 0xCCCC33333333CCCC, + 0x0000FFFFFFFF0000, + 0xFF0000FF00FFFF00, + 0x6996699669966996, + }, + { + 0xC3C33C3C3C3CC3C3, + 0x55555555AAAAAAAA, + 0x0FF00FF0F00FF00F, + 0x5AA55AA5A55AA55A, + 0x55AAAA55AA5555AA, + 0xF00F0FF0F00F0FF0, + 0x9669699696696996, + 0x5AA55AA55AA55AA5, + 0x55555555AAAAAAAA, + 0x3333CCCCCCCC3333, + 0x0000FFFFFFFF0000, + 0x00FFFF00FF0000FF, + 0x9669966996699669, + }, + { + 0x3C3CC3C3C3C33C3C, + 0x55555555AAAAAAAA, + 0xF00FF00F0FF00FF0, + 0xA55AA55A5AA55AA5, + 0xAA5555AA55AAAA55, + 0x0FF0F00F0FF0F00F, + 0x9669699696696996, + 0x5AA55AA55AA55AA5, + 0xAAAAAAAA55555555, + 0x3333CCCCCCCC3333, + 0xFFFF00000000FFFF, + 0xFF0000FF00FFFF00, + 0x9669966996699669, + }, + { + 0xC3C33C3C3C3CC3C3, + 0x55555555AAAAAAAA, + 0x0FF00FF0F00FF00F, + 0xA55AA55A5AA55AA5, + 0xAA5555AA55AAAA55, + 0x0FF0F00F0FF0F00F, + 0x9669699696696996, + 0xA55AA55AA55AA55A, + 0xAAAAAAAA55555555, + 0xCCCC33333333CCCC, + 0xFFFF00000000FFFF, + 0x00FFFF00FF0000FF, + 0x6996699669966996, + }, + { + 0x3C3CC3C3C3C33C3C, + 0x55555555AAAAAAAA, + 0x0FF00FF0F00FF00F, + 0xA55AA55A5AA55AA5, + 0xAA5555AA55AAAA55, + 0x0FF0F00F0FF0F00F, + 0x6996966969969669, + 0xA55AA55AA55AA55A, + 0xAAAAAAAA55555555, + 0xCCCC33333333CCCC, + 0x0000FFFFFFFF0000, + 0xFF0000FF00FFFF00, + 0x6996699669966996, + }, + { + 0xC3C33C3C3C3CC3C3, + 0x55555555AAAAAAAA, + 0xF00FF00F0FF00FF0, + 0xA55AA55A5AA55AA5, + 0xAA5555AA55AAAA55, + 0x0FF0F00F0FF0F00F, + 0x6996966969969669, + 0x5AA55AA55AA55AA5, + 0xAAAAAAAA55555555, + 0x3333CCCCCCCC3333, + 0x0000FFFFFFFF0000, + 0x00FFFF00FF0000FF, + 0x9669966996699669, + }, + { + 0x3C3CC3C3C3C33C3C, + 0x55555555AAAAAAAA, + 0x0FF00FF0F00FF00F, + 0x5AA55AA5A55AA55A, + 0x55AAAA55AA5555AA, + 0xF00F0FF0F00F0FF0, + 0x6996966969969669, + 0x5AA55AA55AA55AA5, + 0x55555555AAAAAAAA, + 0x3333CCCCCCCC3333, + 0xFFFF00000000FFFF, + 0xFF0000FF00FFFF00, + 0x9669966996699669, + }, + { + 0xC3C33C3C3C3CC3C3, + 0x55555555AAAAAAAA, + 0xF00FF00F0FF00FF0, + 0x5AA55AA5A55AA55A, + 0x55AAAA55AA5555AA, + 0xF00F0FF0F00F0FF0, + 0x6996966969969669, + 0xA55AA55AA55AA55A, + 0x55555555AAAAAAAA, + 0xCCCC33333333CCCC, + 0xFFFF00000000FFFF, + 0x00FFFF00FF0000FF, + 0x6996699669966996, + }, + { + 0x3C3CC3C3C3C33C3C, + 0xAAAAAAAA55555555, + 0x0FF00FF0F00FF00F, + 0x5AA55AA5A55AA55A, + 0xAA5555AA55AAAA55, + 0xF00F0FF0F00F0FF0, + 0x9669699696696996, + 0xA55AA55AA55AA55A, + 0x55555555AAAAAAAA, + 0xCCCC33333333CCCC, + 0x0000FFFFFFFF0000, + 0xFF0000FF00FFFF00, + 0x6996699669966996, + }, + { + 0xC3C33C3C3C3CC3C3, + 0xAAAAAAAA55555555, + 0xF00FF00F0FF00FF0, + 0x5AA55AA5A55AA55A, + 0xAA5555AA55AAAA55, + 0xF00F0FF0F00F0FF0, + 0x9669699696696996, + 0x5AA55AA55AA55AA5, + 0x55555555AAAAAAAA, + 0x3333CCCCCCCC3333, + 0x0000FFFFFFFF0000, + 0x00FFFF00FF0000FF, + 0x9669966996699669, + }, + { + 0x3C3CC3C3C3C33C3C, + 0xAAAAAAAA55555555, + 0x0FF00FF0F00FF00F, + 0xA55AA55A5AA55AA5, + 0x55AAAA55AA5555AA, + 0x0FF0F00F0FF0F00F, + 0x9669699696696996, + 0x5AA55AA55AA55AA5, + 0xAAAAAAAA55555555, + 0x3333CCCCCCCC3333, + 0xFFFF00000000FFFF, + 0xFF0000FF00FFFF00, + 0x9669966996699669, + }, + { + 0xC3C33C3C3C3CC3C3, + 0xAAAAAAAA55555555, + 0xF00FF00F0FF00FF0, + 0xA55AA55A5AA55AA5, + 0x55AAAA55AA5555AA, + 0x0FF0F00F0FF0F00F, + 0x9669699696696996, + 0xA55AA55AA55AA55A, + 0xAAAAAAAA55555555, + 0xCCCC33333333CCCC, + 0xFFFF00000000FFFF, + 0x00FFFF00FF0000FF, + 0x6996699669966996, + }, + { + 0x3C3CC3C3C3C33C3C, + 0xAAAAAAAA55555555, + 0xF00FF00F0FF00FF0, + 0xA55AA55A5AA55AA5, + 0x55AAAA55AA5555AA, + 0x0FF0F00F0FF0F00F, + 0x6996966969969669, + 0xA55AA55AA55AA55A, + 0xAAAAAAAA55555555, + 0xCCCC33333333CCCC, + 0x0000FFFFFFFF0000, + 0xFF0000FF00FFFF00, + 0x6996699669966996, + }, + { + 0xC3C33C3C3C3CC3C3, + 0xAAAAAAAA55555555, + 0x0FF00FF0F00FF00F, + 0xA55AA55A5AA55AA5, + 0x55AAAA55AA5555AA, + 0x0FF0F00F0FF0F00F, + 0x6996966969969669, + 0x5AA55AA55AA55AA5, + 0xAAAAAAAA55555555, + 0x3333CCCCCCCC3333, + 0x0000FFFFFFFF0000, + 0x00FFFF00FF0000FF, + 0x9669966996699669, + }, + { + 0x3C3CC3C3C3C33C3C, + 0xAAAAAAAA55555555, + 0xF00FF00F0FF00FF0, + 0x5AA55AA5A55AA55A, + 0xAA5555AA55AAAA55, + 0xF00F0FF0F00F0FF0, + 0x6996966969969669, + 0x5AA55AA55AA55AA5, + 0x55555555AAAAAAAA, + 0x3333CCCCCCCC3333, + 0xFFFF00000000FFFF, + 0xFF0000FF00FFFF00, + 0x9669966996699669, + }, + { + 0xC3C33C3C3C3CC3C3, + 0xAAAAAAAA55555555, + 0x0FF00FF0F00FF00F, + 0x5AA55AA5A55AA55A, + 0xAA5555AA55AAAA55, + 0xF00F0FF0F00F0FF0, + 0x6996966969969669, + 0xA55AA55AA55AA55A, + 0x55555555AAAAAAAA, + 0xCCCC33333333CCCC, + 0xFFFF00000000FFFF, + 0x00FFFF00FF0000FF, + 0x6996699669966996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, +} + +var RadixConversionsS = [5][2][gf2e13.Bits]uint64{ + { + { + 0x3C3CF30C0000C003, + 0x0CCCC3F333C0000C, + 0x03C33F33FCC0C03C, + 0x0003000F3C03C0C0, + 0xF33FF33030CF03F0, + 0x0CF0303300F0CCC0, + 0xFF3F0C0CC0FF3CC0, + 0xCF3CF0FF003FC000, + 0xC00FF3CF0303F300, + 0x3CCC0CC00CF0CC00, + 0xF30FFC3C3FCCFC00, + 0x3F0FC3F0CCF0C000, + 0x3000FF33CCF0F000, + }, + { + 0x0C0F0FCF0F0CF330, + 0xF0000FC33C3CCF3C, + 0x3C0F3F00C3C300FC, + 0x3C33CCC0F0F3CC30, + 0xC0CFFFFFCCCC30CC, + 0x3FC3F3CCFFFC033F, + 0xFC3030CCCCC0CFCF, + 0x0FCF0C00CCF333C3, + 0xCFFCF33000CFF030, + 0x00CFFCC330F30FCC, + 0x3CCC3FCCC0F3FFF3, + 0xF00F0C3FC003C0FF, + 0x330CCFCC03C0FC33, + }, + }, + { + { + 0x0F0F0FF0F000000F, + 0x00FFFFFFFF0000F0, + 0xFFFF00FF00000F00, + 0xFFF000F00F0FF000, + 0xFFF0000F0FF000F0, + 0x00FF000FFF000000, + 0xFF0F0FFF0F0FF000, + 0x0FFF0000000F0000, + 0x00F000F0FFF00F00, + 0x00F00FF00F00F000, + 0xFFF000F000F00000, + 0x00F00F000FF00000, + 0x0000FF0F0000F000, + }, + { + 0xF0FFFFFFF0F00F00, + 0x00FFF0FFFF0000FF, + 0x00FF00000F0F0FFF, + 0xF000F0000F00FF0F, + 0xFF000000FFF00000, + 0xF0FF000FF00F0FF0, + 0x0F0F0F00FF000F0F, + 0x0F0F00F0F0F0F000, + 0x00F00F00F00F000F, + 0x00F0F0F00000FFF0, + 0xFFFFFF0FF00F0FFF, + 0x0F0FFFF00FFFFFFF, + 0xFFFF0F0FFF0FFF00, + }, + }, + { + { + 0x00FF0000000000FF, + 0xFFFFFFFFFF00FF00, + 0xFF0000FF00FF0000, + 0xFFFF000000FF0000, + 0xFF00000000FF0000, + 0x00FFFFFFFF000000, + 0xFF0000FFFFFF0000, + 0xFF00FF00FFFF0000, + 0x00FFFFFFFF00FF00, + 0xFFFF000000000000, + 0x00FF0000FF000000, + 0xFF00FF00FF000000, + 0x00FF00FFFF000000, + }, + { + 0x00FF00FF00FF0000, + 0xFF00FFFF000000FF, + 0x0000FFFF000000FF, + 0x00FFFF00FF000000, + 0xFFFFFF0000FF00FF, + 0x0000FFFF00FFFF00, + 0xFF00FF0000FFFF00, + 0x00000000FFFFFFFF, + 0x0000FF0000000000, + 0xFF00FFFF00FFFF00, + 0x00FFFF00000000FF, + 0x0000FF00FF00FFFF, + 0xFF0000FFFFFF0000, + }, + }, + { + { + 0x000000000000FFFF, + 0xFFFFFFFFFFFF0000, + 0x0000000000000000, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFF0000, + 0x0000FFFF00000000, + 0x0000FFFFFFFF0000, + 0xFFFF0000FFFF0000, + 0x0000FFFF00000000, + 0xFFFF000000000000, + 0xFFFF000000000000, + 0xFFFF000000000000, + 0xFFFFFFFF00000000, + }, + { + 0x0000FFFF00000000, + 0xFFFFFFFF0000FFFF, + 0x00000000FFFFFFFF, + 0x0000000000000000, + 0x0000FFFF00000000, + 0xFFFF0000FFFF0000, + 0x0000FFFFFFFF0000, + 0x0000FFFF0000FFFF, + 0xFFFFFFFF0000FFFF, + 0x00000000FFFF0000, + 0xFFFF0000FFFFFFFF, + 0xFFFF0000FFFFFFFF, + 0x0000000000000000, + }, + }, + { + { + 0x00000000FFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFFFFFF00000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x00000000FFFFFFFF, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x00000000FFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + }, + }, +} + +var RadixConversionsS4096 = [5][gf2e12.Bits]uint64{ + { + 0xF3CFC030FC30F003, + 0x3FCF0F003C00C00C, + 0x30033CC300C0C03C, + 0xCCFF0F3C0F30F0C0, + 0x0300C03FF303C3F0, + 0x3FFF3C0FF0CCCCC0, + 0xF3FFF0C00F3C3CC0, + 0x3003333FFFC3C000, + 0x0FF30FFFC3FFF300, + 0xFFC0F300F0F0CC00, + 0xC0CFF3FCCC3CFC00, + 0xFC3C03F0F330C000, + }, + { + 0x000F00000000F00F, + 0x00000F00F00000F0, + 0x0F00000F00000F00, + 0xF00F00F00F000000, + 0x00F00000000000F0, + 0x0000000F00000000, + 0xF00000000F00F000, + 0x00F00F00000F0000, + 0x0000F00000F00F00, + 0x000F00F00F00F000, + 0x00F00F0000000000, + 0x0000000000F00000, + }, + { + 0x0000FF00FF0000FF, + 0x0000FF000000FF00, + 0xFF0000FF00FF0000, + 0xFFFF0000FF000000, + 0x00FF00FF00FF0000, + 0x0000FFFFFF000000, + 0x00FFFF00FF000000, + 0xFFFFFF0000FF0000, + 0xFFFF00FFFF00FF00, + 0x0000FF0000000000, + 0xFFFFFF00FF000000, + 0x00FF000000000000, + }, + { + 0x000000000000FFFF, + 0x00000000FFFF0000, + 0x0000000000000000, + 0xFFFF000000000000, + 0x00000000FFFF0000, + 0x0000FFFF00000000, + 0x0000000000000000, + 0x00000000FFFF0000, + 0x0000FFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + }, + { + 0x00000000FFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + }, +} + +var ButterfliesConsts4096 = [63][gf2e12.Bits]uint64{ + // 64 + { + 0xF00F0FF0F00F0FF0, + 0xF0F00F0F0F0FF0F0, + 0x0FF00FF00FF00FF0, + 0xAA5555AAAA5555AA, + 0xF00F0FF0F00F0FF0, + 0x33CCCC33CC3333CC, + 0xFFFF0000FFFF0000, + 0xCC33CC3333CC33CC, + 0x33CC33CC33CC33CC, + 0x5A5A5A5A5A5A5A5A, + 0xFF00FF00FF00FF00, + 0xF00F0FF0F00F0FF0, + }, + // 128 + { + 0x3C3C3C3C3C3C3C3C, + 0xF0F0F0F0F0F0F0F0, + 0x5555AAAA5555AAAA, + 0xCC3333CCCC3333CC, + 0xC33CC33CC33CC33C, + 0x55555555AAAAAAAA, + 0x33333333CCCCCCCC, + 0x00FF00FFFF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x0000FFFFFFFF0000, + 0xF0F00F0F0F0FF0F0, + }, + { + 0x3C3C3C3C3C3C3C3C, + 0x0F0F0F0F0F0F0F0F, + 0xAAAA5555AAAA5555, + 0xCC3333CCCC3333CC, + 0xC33CC33CC33CC33C, + 0x55555555AAAAAAAA, + 0x33333333CCCCCCCC, + 0xFF00FF0000FF00FF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x0000FFFFFFFF0000, + 0xF0F00F0F0F0FF0F0, + }, + // 256 + { + 0xAA55AA5555AA55AA, + 0xCC33CC3333CC33CC, + 0x33CCCC33CC3333CC, + 0x55555555AAAAAAAA, + 0xFF0000FF00FFFF00, + 0x3CC33CC3C33CC33C, + 0x5555AAAA5555AAAA, + 0x0FF00FF00FF00FF0, + 0xCCCC33333333CCCC, + 0xF0F0F0F0F0F0F0F0, + 0x00FFFF0000FFFF00, + 0xC33CC33CC33CC33C, + }, + { + 0x55AA55AAAA55AA55, + 0xCC33CC3333CC33CC, + 0xCC3333CC33CCCC33, + 0x55555555AAAAAAAA, + 0xFF0000FF00FFFF00, + 0xC33CC33C3CC33CC3, + 0xAAAA5555AAAA5555, + 0xF00FF00FF00FF00F, + 0x3333CCCCCCCC3333, + 0x0F0F0F0F0F0F0F0F, + 0xFF0000FFFF0000FF, + 0xC33CC33CC33CC33C, + }, + { + 0xAA55AA5555AA55AA, + 0x33CC33CCCC33CC33, + 0xCC3333CC33CCCC33, + 0x55555555AAAAAAAA, + 0x00FFFF00FF0000FF, + 0x3CC33CC3C33CC33C, + 0x5555AAAA5555AAAA, + 0x0FF00FF00FF00FF0, + 0x3333CCCCCCCC3333, + 0xF0F0F0F0F0F0F0F0, + 0x00FFFF0000FFFF00, + 0xC33CC33CC33CC33C, + }, + { + 0x55AA55AAAA55AA55, + 0x33CC33CCCC33CC33, + 0x33CCCC33CC3333CC, + 0x55555555AAAAAAAA, + 0x00FFFF00FF0000FF, + 0xC33CC33C3CC33CC3, + 0xAAAA5555AAAA5555, + 0xF00FF00FF00FF00F, + 0xCCCC33333333CCCC, + 0x0F0F0F0F0F0F0F0F, + 0xFF0000FFFF0000FF, + 0xC33CC33CC33CC33C, + }, + // 512 + { + 0x6699669999669966, + 0x33CCCC33CC3333CC, + 0xA5A5A5A55A5A5A5A, + 0x3C3CC3C3C3C33C3C, + 0xF00FF00F0FF00FF0, + 0x55AA55AA55AA55AA, + 0x3C3CC3C3C3C33C3C, + 0x0F0F0F0FF0F0F0F0, + 0x55AA55AA55AA55AA, + 0x33CCCC33CC3333CC, + 0xF0F0F0F0F0F0F0F0, + 0xA55A5AA55AA5A55A, + }, + { + 0x9966996666996699, + 0x33CCCC33CC3333CC, + 0xA5A5A5A55A5A5A5A, + 0x3C3CC3C3C3C33C3C, + 0x0FF00FF0F00FF00F, + 0xAA55AA55AA55AA55, + 0x3C3CC3C3C3C33C3C, + 0xF0F0F0F00F0F0F0F, + 0xAA55AA55AA55AA55, + 0xCC3333CC33CCCC33, + 0x0F0F0F0F0F0F0F0F, + 0xA55A5AA55AA5A55A, + }, + { + 0x6699669999669966, + 0x33CCCC33CC3333CC, + 0x5A5A5A5AA5A5A5A5, + 0xC3C33C3C3C3CC3C3, + 0x0FF00FF0F00FF00F, + 0xAA55AA55AA55AA55, + 0xC3C33C3C3C3CC3C3, + 0x0F0F0F0FF0F0F0F0, + 0xAA55AA55AA55AA55, + 0x33CCCC33CC3333CC, + 0xF0F0F0F0F0F0F0F0, + 0xA55A5AA55AA5A55A, + }, + { + 0x9966996666996699, + 0x33CCCC33CC3333CC, + 0x5A5A5A5AA5A5A5A5, + 0xC3C33C3C3C3CC3C3, + 0xF00FF00F0FF00FF0, + 0x55AA55AA55AA55AA, + 0xC3C33C3C3C3CC3C3, + 0xF0F0F0F00F0F0F0F, + 0x55AA55AA55AA55AA, + 0xCC3333CC33CCCC33, + 0x0F0F0F0F0F0F0F0F, + 0xA55A5AA55AA5A55A, + }, + { + 0x6699669999669966, + 0xCC3333CC33CCCC33, + 0x5A5A5A5AA5A5A5A5, + 0x3C3CC3C3C3C33C3C, + 0x0FF00FF0F00FF00F, + 0x55AA55AA55AA55AA, + 0x3C3CC3C3C3C33C3C, + 0x0F0F0F0FF0F0F0F0, + 0x55AA55AA55AA55AA, + 0x33CCCC33CC3333CC, + 0xF0F0F0F0F0F0F0F0, + 0xA55A5AA55AA5A55A, + }, + { + 0x9966996666996699, + 0xCC3333CC33CCCC33, + 0x5A5A5A5AA5A5A5A5, + 0x3C3CC3C3C3C33C3C, + 0xF00FF00F0FF00FF0, + 0xAA55AA55AA55AA55, + 0x3C3CC3C3C3C33C3C, + 0xF0F0F0F00F0F0F0F, + 0xAA55AA55AA55AA55, + 0xCC3333CC33CCCC33, + 0x0F0F0F0F0F0F0F0F, + 0xA55A5AA55AA5A55A, + }, + { + 0x6699669999669966, + 0xCC3333CC33CCCC33, + 0xA5A5A5A55A5A5A5A, + 0xC3C33C3C3C3CC3C3, + 0xF00FF00F0FF00FF0, + 0xAA55AA55AA55AA55, + 0xC3C33C3C3C3CC3C3, + 0x0F0F0F0FF0F0F0F0, + 0xAA55AA55AA55AA55, + 0x33CCCC33CC3333CC, + 0xF0F0F0F0F0F0F0F0, + 0xA55A5AA55AA5A55A, + }, + { + 0x9966996666996699, + 0xCC3333CC33CCCC33, + 0xA5A5A5A55A5A5A5A, + 0xC3C33C3C3C3CC3C3, + 0x0FF00FF0F00FF00F, + 0x55AA55AA55AA55AA, + 0xC3C33C3C3C3CC3C3, + 0xF0F0F0F00F0F0F0F, + 0x55AA55AA55AA55AA, + 0xCC3333CC33CCCC33, + 0x0F0F0F0F0F0F0F0F, + 0xA55A5AA55AA5A55A, + }, + // 1024 + { + 0x9669699696696996, + 0x6996699669966996, + 0x6996699669966996, + 0x00FFFF0000FFFF00, + 0xFF00FF00FF00FF00, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x6996699669966996, + 0x00FFFF0000FFFF00, + 0x00FF00FF00FF00FF, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x6996699669966996, + 0xFF0000FFFF0000FF, + 0x00FF00FF00FF00FF, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x6996699669966996, + 0xFF0000FFFF0000FF, + 0xFF00FF00FF00FF00, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x9669966996699669, + 0xFF0000FFFF0000FF, + 0x00FF00FF00FF00FF, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x9669966996699669, + 0xFF0000FFFF0000FF, + 0xFF00FF00FF00FF00, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x9669966996699669, + 0x00FFFF0000FFFF00, + 0xFF00FF00FF00FF00, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x9669966996699669, + 0x00FFFF0000FFFF00, + 0x00FF00FF00FF00FF, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x9669966996699669, + 0x00FFFF0000FFFF00, + 0xFF00FF00FF00FF00, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x9669966996699669, + 0x00FFFF0000FFFF00, + 0x00FF00FF00FF00FF, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x9669966996699669, + 0xFF0000FFFF0000FF, + 0x00FF00FF00FF00FF, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x9669966996699669, + 0xFF0000FFFF0000FF, + 0xFF00FF00FF00FF00, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x6996699669966996, + 0xFF0000FFFF0000FF, + 0x00FF00FF00FF00FF, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x6996699669966996, + 0xFF0000FFFF0000FF, + 0xFF00FF00FF00FF00, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x6996699669966996, + 0x00FFFF0000FFFF00, + 0xFF00FF00FF00FF00, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x6996699669966996, + 0x00FFFF0000FFFF00, + 0x00FF00FF00FF00FF, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + // 2048 + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/powers.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/powers.go new file mode 100644 index 0000000..c48d860 --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/internal/powers.go @@ -0,0 +1,2828 @@ +package internal + +import ( + "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e12" + "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e13" +) + +var Powers4096 = [64][gf2e12.Bits]uint64{ + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, +} + +var Powers8192 = [128][gf2e13.Bits]uint64{ + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e12/gf4096.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e12/gf4096.go new file mode 100644 index 0000000..e0f84fa --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e12/gf4096.go @@ -0,0 +1,83 @@ +// Package gf2e12 provides finite field arithmetic over GF(2^12). +package gf2e12 + +// Elt is a field element of characteristic 2 modulo z^12 + z^3 + 1 +type Elt = uint16 + +const ( + Bits = 12 + Mask = (1 << Bits) - 1 +) + +// Add two Elt elements together. Since an addition in Elt(2) is the same as XOR, +// this implementation uses a simple XOR for addition. +func Add(a, b Elt) Elt { + return a ^ b +} + +// Mul calculate the product of two Elt elements. +func Mul(a, b Elt) Elt { + a64 := uint64(a) + b64 := uint64(b) + + // if the LSB of b is 1, set tmp to a64, and 0 otherwise + tmp := a64 & -(b64 & 1) + + // check if i-th bit of b64 is set, add a64 shifted by i bits if so + for i := 1; i < Bits; i++ { + tmp ^= a64 * (b64 & (1 << i)) + } + + // polynomial reduction + t := tmp & 0x7FC000 + tmp ^= t >> 9 + tmp ^= t >> 12 + + t = tmp & 0x3000 + tmp ^= t >> 9 + tmp ^= t >> 12 + + return Elt(tmp & Mask) +} + +// sqr calculates the square of Elt element a +func sqr(a Elt) Elt { + a32 := uint32(a) + a32 = (a32 | (a32 << 8)) & 0x00FF00FF + a32 = (a32 | (a32 << 4)) & 0x0F0F0F0F + a32 = (a32 | (a32 << 2)) & 0x33333333 + a32 = (a32 | (a32 << 1)) & 0x55555555 + + t := a32 & 0x7FC000 + a32 ^= t >> 9 + a32 ^= t >> 12 + + t = a32 & 0x3000 + a32 ^= t >> 9 + a32 ^= t >> 12 + + return uint16(a32 & Mask) +} + +// Inv calculates the multiplicative inverse of Elt element a +func Inv(a Elt) Elt { + out := sqr(a) + tmp3 := Mul(out, a) // a^3 + + out = sqr(sqr(tmp3)) + tmp15 := Mul(out, tmp3) // a^15 = a^(3*2*2 + 3) + + out = sqr(sqr(sqr(sqr(tmp15)))) + out = Mul(out, tmp15) // a^255 = a^(15*2*2*2*2 + 15) + + out = sqr(sqr(out)) + out = Mul(out, tmp3) // a^1023 = a^(255*2*2 + 3) + + out = Mul(sqr(out), a) // a^2047 = a^(1023*2 + 1) + return sqr(out) // a^4094 = a^(2047 * 2) +} + +// Div calculates a / b +func Div(a, b Elt) Elt { + return Mul(Inv(b), a) +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e13/gf8192.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e13/gf8192.go new file mode 100644 index 0000000..c2efcf2 --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e13/gf8192.go @@ -0,0 +1,130 @@ +// Package gf2e13 provides finite field arithmetic over GF(2^13). +package gf2e13 + +// Elt is a field element of characteristic 2 modulo z^13 + z^4 + z^3 + z + 1 +type Elt = uint16 + +const ( + Bits = 13 + Mask = (1 << Bits) - 1 +) + +// Add two Elt elements together. Since an addition in Elt(2) is the same as XOR, +// this implementation uses a simple XOR for addition. +func Add(a, b Elt) Elt { + return a ^ b +} + +// Mul calculate the product of two Elt elements. +func Mul(a, b Elt) Elt { + a64 := uint64(a) + b64 := uint64(b) + + // if the LSB of b is 1, set tmp to a64, and 0 otherwise + tmp := a64 & -(b64 & 1) + + // check if i-th bit of b64 is set, add a64 shifted by i bits if so + for i := 1; i < Bits; i++ { + tmp ^= a64 * (b64 & (1 << i)) + } + + // polynomial reduction + t := tmp & 0x1FF0000 + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + t = tmp & 0x000E000 + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + return uint16(tmp & Mask) +} + +// sqr2 calculates a^4 +func sqr2(a Elt) Elt { + a64 := uint64(a) + a64 = (a64 | (a64 << 24)) & 0x000000FF000000FF + a64 = (a64 | (a64 << 12)) & 0x000F000F000F000F + a64 = (a64 | (a64 << 6)) & 0x0303030303030303 + a64 = (a64 | (a64 << 3)) & 0x1111111111111111 + + t := a64 & 0x0001FF0000000000 + a64 ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = a64 & 0x000000FF80000000 + a64 ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = a64 & 0x000000007FC00000 + a64 ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = a64 & 0x00000000003FE000 + a64 ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + return uint16(a64 & Mask) +} + +// sqrMul calculates the product of a^2 and b +func sqrMul(a, b Elt) Elt { + a64 := uint64(a) + b64 := uint64(b) + + x := (b64 << 6) * (a64 & (1 << 6)) + a64 ^= a64 << 7 + x ^= b64 * (a64 & (0x04001)) + x ^= (b64 * (a64 & (0x08002))) << 1 + x ^= (b64 * (a64 & (0x10004))) << 2 + x ^= (b64 * (a64 & (0x20008))) << 3 + x ^= (b64 * (a64 & (0x40010))) << 4 + x ^= (b64 * (a64 & (0x80020))) << 5 + + t := x & 0x0000001FF0000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000000000FF80000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000000000007E000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + return uint16(x & Mask) +} + +// sqr2Mul calculates the product of a^4 and b +func sqr2Mul(a, b Elt) Elt { + a64 := uint64(a) + b64 := uint64(b) + + x := (b64 << 18) * (a64 & (1 << 6)) + a64 ^= a64 << 21 + x ^= b64 * (a64 & (0x010000001)) + x ^= (b64 * (a64 & (0x020000002))) << 3 + x ^= (b64 * (a64 & (0x040000004))) << 6 + x ^= (b64 * (a64 & (0x080000008))) << 9 + x ^= (b64 * (a64 & (0x100000010))) << 12 + x ^= (b64 * (a64 & (0x200000020))) << 15 + + t := x & 0x1FF0000000000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000FF80000000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000007FC00000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x00000003FE000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x0000000001FE0000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000000000001E000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + return uint16(x & Mask) +} + +// Inv calculates the multiplicative inverse of Elt element a +func Inv(a Elt) Elt { + return Div(1, a) +} + +// Div calculates a / b +func Div(a, b Elt) Elt { + tmp3 := sqrMul(b, b) // b^3 + tmp15 := sqr2Mul(tmp3, tmp3) // b^15 = b^(3*2*2+3) + out := sqr2(tmp15) + out = sqr2Mul(out, tmp15) // b^255 = b^(15*4*4+15) + out = sqr2(out) + out = sqr2Mul(out, tmp15) // b^4095 = b^(255*2*2*2*2+15) + + return sqrMul(out, a) // b^8190 = b^(4095*2) = b^-1 +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/mceliece.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/mceliece.go new file mode 100644 index 0000000..7b11661 --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/mceliece.go @@ -0,0 +1,733 @@ +// Code generated from mceliece.templ.go. DO NOT EDIT. + +// Package mceliece6960119 implements the IND-CCA2 secure key encapsulation mechanism +// mceliece6960119 as submitted to round 4 of the NIST PQC competition and +// described in +// +// https://classic.mceliece.org/nist/mceliece-20201010.pdf +// +// The following code is translated from the C reference implementation, and +// from a Rust implementation by Bernhard Berg, Lukas Prokop, Daniel Kales +// where direct translation from C is not applicable. +// +// https://github.com/Colfenor/classic-mceliece-rust +package mceliece6960119 + +import ( + cryptoRand "crypto/rand" + "crypto/sha3" + "errors" + "fmt" + "io" + + "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119/internal" + "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119/math/gf2e13" +) + +const ( + sysT = 119 // F(y) is 64 degree + gfBits = gf2e13.Bits + gfMask = gf2e13.Mask + unusedBits = 16 - gfBits + sysN = 6960 + condBytes = (1 << (gfBits - 4)) * (2*gfBits - 1) + irrBytes = sysT * 2 + pkNRows = sysT * gfBits + pkNCols = sysN - pkNRows + pkRowBytes = (pkNCols + 7) / 8 + syndBytes = (pkNRows + 7) / 8 + PublicKeySize = 1047319 + PrivateKeySize = 13948 + CiphertextSize = 194 + SharedKeySize = 32 + seedSize = 32 + encapsulationSeedSize = 48 +) + +var ( + ErrCiphertextSize = errors.New("wrong size for ciphertext") + ErrPubKeySize = errors.New("wrong size for public key") + ErrPrivKeySize = errors.New("wrong size for private key") +) + +type PublicKey struct { + pk [PublicKeySize]byte +} + +type PrivateKey struct { + sk [PrivateKeySize]byte +} + +type ( + gf = gf2e13.Elt + randFunc = func(pool []byte) error +) + +// KEM Keypair generation. +// +// The structure of the secret key is given by the following segments: +// (32 bytes seed, 8 bytes pivots, IRR_BYTES bytes, COND_BYTES bytes, SYS_N/8 bytes). +// The structure of the public key is simple: a matrix of PK_NROWS times PK_ROW_BYTES bytes. +// +// `entropy` corresponds to the l-bit input seed in SeededKeyGen from the specification. +// The keypair is deterministically generated from `entropy`. +// If the generated keypair is invalid, a new seed will be generated by hashing `entropy` to try again. +func deriveKeyPair(entropy []byte) (*PublicKey, *PrivateKey) { + const ( + irrPolys = sysN/8 + (1<>= 8 + + preimage[0] = byte(m & 1) + for i := 0; i < sysN/8; i++ { + preimage[1+i] = (byte(^m) & s[i]) | (byte(m) & e[i]) + } + + copy(preimage[1+sysN/8:][:syndBytes], c[0:syndBytes]) + err := shake256(key[0:32], preimage[:]) + if err != nil { + return err + } + + // clear outputs (set to all 1's) if padding bits are not all zero + mask := paddingOk + for i := 0; i < 32; i++ { + key[i] |= mask + } + + if paddingOk == 0 { + return nil + } + return fmt.Errorf("public key padding error %d", paddingOk) +} + +// Generates `e`, a random error vector of weight `t`. +// If generation of pseudo-random numbers fails, an error is returned +func genE(e *[sysN / 8]byte, rand randFunc) error { + ind := [sysT]uint16{} + val := [sysT]byte{} + for { + buf := make([]byte, sysT*4) + err := rand(buf) + if err != nil { + return err + } + + nums := [sysT * 2]uint16{} + for i := 0; i < sysT*2; i++ { + nums[i] = loadGf(buf[:]) + buf = buf[2:] + } + + count := 0 + for i := 0; i < sysT*2 && count < sysT; i++ { + if nums[i] < sysN { + ind[count] = nums[i] + count++ + } + } + if count < sysT { + continue + } + + eq := false + for i := 1; i < sysT; i++ { + for j := 0; j < i; j++ { + if ind[i] == ind[j] { + eq = true + } + } + } + + if !eq { + break + } + } + + for j := 0; j < sysT; j++ { + val[j] = 1 << (ind[j] & 7) + } + + for i := uint16(0); i < sysN/8; i++ { + e[i] = 0 + + for j := 0; j < sysT; j++ { + mask := sameMask(i, ind[j]>>3) + e[i] |= val[j] & mask + } + } + return nil +} + +// Takes two 16-bit integers and determines whether they are equal +// Return byte with all bit set if equal, 0 otherwise +func sameMask(x uint16, y uint16) byte { + mask := uint32(x ^ y) + mask -= 1 + mask >>= 31 + mask = -mask + + return byte(mask & 0xFF) +} + +// Given condition bits `c`, returns the support `s`. +func supportGen(s *[sysN]gf, c *[condBytes]byte) { + L := [gfBits][(1 << gfBits) / 8]byte{} + for i := 0; i < (1 << gfBits); i++ { + a := bitRev(gf(i)) + for j := 0; j < gfBits; j++ { + L[j][i/8] |= byte(((a >> j) & 1) << (i % 8)) + } + } + for j := 0; j < gfBits; j++ { + applyBenes(&L[j], c) + } + for i := 0; i < sysN; i++ { + s[i] = 0 + for j := gfBits - 1; j >= 0; j-- { + s[i] <<= 1 + s[i] |= uint16(L[j][i/8]>>(i%8)) & 1 + } + } +} + +// Given Goppa polynomial `f`, support `l`, and received word `r` +// compute `out`, the syndrome of length 2t +func synd(out *[sysT * 2]gf, f *[sysT + 1]gf, L *[sysN]gf, r *[sysN / 8]byte) { + for j := 0; j < 2*sysT; j++ { + out[j] = 0 + } + + for i := 0; i < sysN; i++ { + c := uint16(r[i/8]>>(i%8)) & 1 + e := eval(f, L[i]) + eInv := gf2e13.Inv(gf2e13.Mul(e, e)) + for j := 0; j < 2*sysT; j++ { + out[j] = gf2e13.Add(out[j], gf2e13.Mul(eInv, c)) + eInv = gf2e13.Mul(eInv, L[i]) + } + } +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} + +// The Berlekamp-Massey algorithm. +// Uses `s` as input (sequence of field elements) +// and `out` as output (minimal polynomial of `s`) +func bm(out *[sysT + 1]gf, s *[2 * sysT]gf) { + var L, mle, mne uint16 + T := [sysT + 1]gf{} + C := [sysT + 1]gf{} + B := [sysT + 1]gf{} + var b, d, f gf + b = 1 + B[1] = 1 + C[0] = 1 + for N := 0; N < 2*sysT; N++ { + d = 0 + for i := 0; i <= min(N, sysT); i++ { + d ^= gf2e13.Mul(C[i], s[N-i]) + } + mne = d + mne -= 1 + mne >>= 15 + mne -= 1 + mle = uint16(N) + mle -= 2 * L + mle >>= 15 + mle -= 1 + mle &= mne + for i := 0; i <= sysT; i++ { + T[i] = C[i] + } + f = gf2e13.Div(d, b) + for i := 0; i <= sysT; i++ { + C[i] ^= gf2e13.Mul(f, B[i]) & mne + } + L = (L & ^mle) | ((uint16(N) + 1 - L) & mle) + + for i := 0; i <= sysT; i++ { + B[i] = (B[i] & ^mle) | (T[i] & mle) + } + + b = (b & ^mle) | (d & mle) + + for i := sysT; i >= 1; i-- { + B[i] = B[i-1] + } + B[0] = 0 + } + + for i := 0; i <= sysT; i++ { + out[i] = C[sysT-i] + } +} + +// Niederreiter decryption with the Berlekamp decoder. +// +// It takes as input the secret key `sk` and a ciphertext `c`. +// It returns an error vector in `e` and the return value indicates success (0) or failure (1) +func decrypt(e *[sysN / 8]byte, sk []byte, c *[syndBytes]byte) uint16 { + var check uint16 + w := 0 + r := [sysN / 8]byte{} + + g := [sysT + 1]gf{} + L := [sysN]gf{} + + s := [sysT * 2]gf{} + sCmp := [sysT * 2]gf{} + locator := [sysT + 1]gf{} + images := [sysN]gf{} + + copy(r[:syndBytes], c[:syndBytes]) + for i := 0; i < sysT; i++ { + g[i] = loadGf(sk) + sk = sk[2:] + } + g[sysT] = 1 + + supportGen(&L, (*[condBytes]byte)(sk[:condBytes])) + + synd(&s, &g, &L, &r) + bm(&locator, &s) + root(&images, &locator, &L) + + for i := 0; i < sysN/8; i++ { + e[i] = 0 + } + for i := 0; i < sysN; i++ { + t := isZeroMask(images[i]) & 1 + + e[i/8] |= byte(t << (i % 8)) + w += int(t) + } + + synd(&sCmp, &g, &L, e) + check = uint16(w) ^ sysT + for i := 0; i < sysT*2; i++ { + check |= s[i] ^ sCmp[i] + } + + check -= 1 + check >>= 15 + + return check ^ 1 +} + +// check if element is 0, returns a mask with all bits set if so, and 0 otherwise +func isZeroMask(element gf) uint16 { + t := uint32(element) - 1 + t >>= 19 + return uint16(t) +} + +// calculate the minimal polynomial of f and store it in out +func minimalPolynomial(out *[sysT]gf, f *[sysT]gf) bool { + mat := [sysT + 1][sysT]gf{} + mat[0][0] = 1 + for i := 1; i < sysT; i++ { + mat[0][i] = 0 + } + + for i := 0; i < sysT; i++ { + mat[1][i] = f[i] + } + + for i := 2; i <= sysT; i++ { + polyMul(&mat[i], &mat[i-1], f) + } + + for j := 0; j < sysT; j++ { + for k := j + 1; k < sysT; k++ { + mask := isZeroMask(mat[j][j]) + // if mat[j][j] is not zero, add mat[c..sysT+1][k] to mat[c][j] + // do nothing otherwise + for c := j; c <= sysT; c++ { + mat[c][j] ^= mat[c][k] & mask + } + } + + if mat[j][j] == 0 { + return false + } + + inv := gf2e13.Inv(mat[j][j]) + for c := 0; c <= sysT; c++ { + mat[c][j] = gf2e13.Mul(mat[c][j], inv) + } + + for k := 0; k < sysT; k++ { + if k != j { + t := mat[j][k] + for c := 0; c <= sysT; c++ { + mat[c][k] ^= gf2e13.Mul(mat[c][j], t) + } + } + } + } + + for i := 0; i < sysT; i++ { + out[i] = mat[sysT][i] + } + + return true +} + +// calculate the product of a and b in Fq^t +func polyMul(out *[sysT]gf, a *[sysT]gf, b *[sysT]gf) { + product := [sysT*2 - 1]gf{} + for i := 0; i < sysT; i++ { + for j := 0; j < sysT; j++ { + product[i+j] ^= gf2e13.Mul(a[i], b[j]) + } + } + + for i := (sysT - 1) * 2; i >= sysT; i-- { + // polynomial reduction + + product[i-sysT+8] ^= product[i] + product[i-sysT+0] ^= product[i] + + } + + for i := 0; i < sysT; i++ { + out[i] = product[i] + } +} + +// Compute transposition of `in` and store it in `out` +func transpose64x64(out, in *[64]uint64) { + masks := [6][2]uint64{ + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000}, + } + copy(out[:], in[:]) + + for d := 5; d >= 0; d-- { + s := 1 << d + for i := 0; i < 64; i += s * 2 { + for j := i; j < i+s; j++ { + x := (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s) + y := ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]) + + out[j+0] = x + out[j+s] = y + } + } + } +} + +// given polynomial `f`, evaluate `f` at `a` +func eval(f *[sysT + 1]gf, a gf) gf { + r := f[sysT] + for i := sysT - 1; i >= 0; i-- { + r = gf2e13.Mul(r, a) + r = gf2e13.Add(r, f[i]) + } + return r +} + +// Given polynomial `f` and a list of field elements `l`, +// return the roots `out` satisfying `[ f(a) for a in L ]` +func root(out *[sysN]gf, f *[sysT + 1]gf, l *[sysN]gf) { + for i := 0; i < sysN; i++ { + out[i] = eval(f, l[i]) + } +} + +// performs SHAKE-256 on `input` and store the hash in `output` +func shake256(output []byte, input []byte) error { + shake := sha3.NewSHAKE256() + _, err := shake.Write(input) + if err != nil { + return err + } + _, err = shake.Read(output) + if err != nil { + return err + } + return nil +} + +// store field element `a` in the first 2 bytes of `dest` +func storeGf(dest []byte, a gf) { + dest[0] = byte(a & 0xFF) + dest[1] = byte(a >> 8) +} + +// load a field element from the first 2 bytes of `src` +func loadGf(src []byte) gf { + a := uint16(src[1]) + a <<= 8 + a |= uint16(src[0]) + return a & gfMask +} + +// load a 32-bit little endian integer from `in` +func load4(in []byte) uint32 { + ret := uint32(in[3]) + for i := 2; i >= 0; i-- { + ret <<= 8 + ret |= uint32(in[i]) + } + return ret +} + +// store a 64-bit integer to `out` in little endian +func store8(out []byte, in uint64) { + out[0] = byte((in >> 0x00) & 0xFF) + out[1] = byte((in >> 0x08) & 0xFF) + out[2] = byte((in >> 0x10) & 0xFF) + out[3] = byte((in >> 0x18) & 0xFF) + out[4] = byte((in >> 0x20) & 0xFF) + out[5] = byte((in >> 0x28) & 0xFF) + out[6] = byte((in >> 0x30) & 0xFF) + out[7] = byte((in >> 0x38) & 0xFF) +} + +// load a 64-bit little endian integer from `in` +func load8(in []byte) uint64 { + ret := uint64(in[7]) + for i := 6; i >= 0; i-- { + ret <<= 8 + ret |= uint64(in[i]) + } + return ret +} + +// reverse the bits in the field element `a` +func bitRev(a gf) gf { + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8) + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4) + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2) + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1) + + return a >> unusedBits +} + +func SeedSize() int { return seedSize } +func EncapsulationSeedSize() int { return encapsulationSeedSize } + +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + var ret [PrivateKeySize]byte + copy(ret[:], sk.sk[:]) + return ret[:], nil +} + +// MarshalCompressedBinary returns a 32-byte seed that can be used to regenerate +// the key pair when passed to DeriveKeyPair +func (sk *PrivateKey) MarshalCompressedBinary() []byte { + seed := [32]byte{} + copy(seed[:], sk.sk[:32]) + return seed[:] +} + +func (sk *PrivateKey) Public() *PublicKey { + pk, _ := DeriveKeyPair(sk.MarshalCompressedBinary()) + return pk +} + +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + var ret [PublicKeySize]byte + copy(ret[:], pk.pk[:]) + return ret[:], nil +} + +func GenerateKeyPair() (*PublicKey, *PrivateKey, error) { + seed := [32]byte{} + _, err := io.ReadFull(cryptoRand.Reader, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := deriveKeyPair(seed[:]) + return pk, sk, nil +} + +func DeriveKeyPair(seed []byte) (*PublicKey, *PrivateKey) { + if len(seed) != seedSize { + panic("seed must be of length EncapsulationSeedSize") + } + return deriveKeyPair(seed) +} + +func encapsulate(pk *PublicKey, rand randFunc) (ct, ss []byte, err error) { + ciphertext := [CiphertextSize]byte{} + sharedSecret := [SharedKeySize]byte{} + err = kemEncapsulate(&ciphertext, &sharedSecret, &pk.pk, rand) + if err != nil { + return nil, nil, err + } + return ciphertext[:], sharedSecret[:], nil +} + +func Encapsulate(pk *PublicKey) (ct, ss []byte, err error) { + return encapsulate(pk, func(pool []byte) error { + _, err2 := io.ReadFull(cryptoRand.Reader, pool) + return err2 + }) +} + +func Decapsulate(sk *PrivateKey, ct []byte) ([]byte, error) { + if len(ct) != CiphertextSize { + return nil, ErrCiphertextSize + } + ss := [SharedKeySize]byte{} + err := kemDecapsulate(&ss, (*[CiphertextSize]byte)(ct), &sk.sk) + if err != nil { + return nil, err + } + return ss[:], nil +} + +func UnmarshalBinaryPublicKey(buf []byte) (*PublicKey, error) { + if len(buf) != PublicKeySize { + return nil, ErrPubKeySize + } + pk := [PublicKeySize]byte{} + copy(pk[:], buf) + return &PublicKey{pk: pk}, nil +} + +func UnmarshalBinaryPrivateKey(buf []byte) (*PrivateKey, error) { + if len(buf) != PrivateKeySize { + return nil, ErrPrivKeySize + } + sk := [PrivateKeySize]byte{} + copy(sk[:], buf) + return &PrivateKey{sk: sk}, nil +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/operations.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/operations.go new file mode 100644 index 0000000..d6a527b --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/operations.go @@ -0,0 +1,57 @@ +// Code generated from operations_6960119.templ.go. DO NOT EDIT. + +package mceliece6960119 + +// This function determines (in a constant-time manner) whether the padding bits of `pk` are all zero. +func checkPkPadding(pk *[PublicKeySize]byte) byte { + b := byte(0) + for i := 0; i < pkNRows; i++ { + b |= pk[i*pkRowBytes+pkRowBytes-1] + } + b >>= pkNCols % 8 + b -= 1 + b >>= 7 + return b - 1 +} + +// This function determines (in a constant-time manner) whether the padding bits of `c` are all zero. +func checkCPadding(c *[CiphertextSize]byte) byte { + b := c[syndBytes-1] >> (pkNRows % 8) + b -= 1 + b >>= 7 + return b - 1 +} + +// input: public key pk, error vector e +// output: syndrome s +func syndrome(s *[CiphertextSize]byte, pk *[PublicKeySize]byte, e *[sysN / 8]byte) { + row := [sysN / 8]byte{} + tail := pkNRows % 8 + for i := 0; i < syndBytes; i++ { + s[i] = 0 + } + for i := 0; i < pkNRows; i++ { + for j := 0; j < sysN/8; j++ { + row[j] = 0 + } + for j := 0; j < pkRowBytes; j++ { + row[sysN/8-pkRowBytes+j] = pk[i*pkRowBytes+j] + } + for j := sysN/8 - 1; j >= sysN/8-pkRowBytes; j-- { + row[j] = (row[j] << tail) | (row[j-1] >> (8 - tail)) + } + row[i/8] |= 1 << (i % 8) + + b := byte(0) + for j := 0; j < sysN/8; j++ { + b ^= row[j] & e[j] + } + + b ^= b >> 4 + b ^= b >> 2 + b ^= b >> 1 + b &= 1 + + s[i/8] |= b << (i % 8) + } +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/pk_gen.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/pk_gen.go new file mode 100644 index 0000000..742b6cc --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/pk_gen.go @@ -0,0 +1,280 @@ +// Code generated from pk_gen_vec.templ.go. DO NOT EDIT. + +// The following code is translated from the C `vec` Additional Implementation +// from the NIST round 4 submission package. + +package mceliece6960119 + +import "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119/internal" + +const exponent = 128 + +func storeI(out []byte, in uint64, i int) { + for j := 0; j < i; j++ { + out[j] = byte((in >> (j * 8)) & 0xFF) + } +} + +func deBitSlicing(out *[1 << gfBits]uint64, in *[exponent][gfBits]uint64) { + for i := 0; i < (1 << gfBits); i++ { + out[i] = 0 + } + + for i := 0; i < exponent; i++ { + for j := gfBits - 1; j >= 0; j-- { + for r := 0; r < 64; r++ { + out[i*64+r] <<= 1 + out[i*64+r] |= (in[i][j] >> r) & 1 + } + } + } +} + +func toBitslicing2x(out0 *[exponent][gfBits]uint64, out1 *[exponent][gfBits]uint64, in *[1 << gfBits]uint64) { + for i := 0; i < exponent; i++ { + for j := gfBits - 1; j >= 0; j-- { + for r := 63; r >= 0; r-- { + out1[i][j] <<= 1 + out1[i][j] |= (in[i*64+r] >> (j + gfBits)) & 1 + } + } + + for j := gfBits - 1; j >= 0; j-- { + for r := 63; r >= 0; r-- { + out0[i][gfBits-1-j] <<= 1 + out0[i][gfBits-1-j] |= (in[i*64+r] >> j) & 1 + } + } + } +} + +func irrLoad(out *[2][gfBits]uint64, in []byte) { + irr := [sysT + 1]uint16{} + + for i := 0; i < sysT; i++ { + irr[i] = loadGf(in[i*2:]) + } + + irr[sysT] = 1 + + v := [2]uint64{} + for i := 0; i < gfBits; i++ { + v[0] = 0 + v[1] = 0 + + for j := 63; j >= 0; j-- { + v[0] <<= 1 + v[0] |= uint64(irr[j]>>i) & 1 + } + for j := sysT; j >= 64; j-- { + v[1] <<= 1 + v[1] |= uint64(irr[j]>>i) & 1 + } + + out[0][i] = v[0] + out[1][i] = v[1] + } +} + +// nolint:unparam +// Public key generation. Generate the public key `pk`, +// permutation `pi` and pivot element `pivots` based on the +// secret key `sk` and permutation `perm` provided. +// `pk` has `max(1 << GFBITS, SYS_N)` elements which is +// 4096 for mceliece348864 and 8192 for mceliece8192128. +// `sk` has `2 * SYS_T` elements and perm `1 << GFBITS`. +func pkGen(pk *[pkNRows * pkRowBytes]byte, irr []byte, perm *[1 << gfBits]uint32, pi *[1 << gfBits]int16, pivots *uint64) bool { + const ( + nblocksH = (sysN + 63) / 64 + nblocksI = (pkNRows + 63) / 64 + + blockIdx = nblocksI - 1 + tail = pkNRows % 64 + ) + mat := [pkNRows][nblocksH]uint64{} + var mask uint64 + + irrInt := [2][gfBits]uint64{} + + consts := [exponent][gfBits]uint64{} + eval := [exponent][gfBits]uint64{} + prod := [exponent][gfBits]uint64{} + tmp := [gfBits]uint64{} + list := [1 << gfBits]uint64{} + + ops := [pkNRows][nblocksI]uint64{} + + oneRow := [exponent]uint64{} + + // compute the inverses + irrLoad(&irrInt, irr) + fft(&eval, &irrInt) + vecCopy(&prod[0], &eval[0]) + for i := 1; i < exponent; i++ { + vecMul(&prod[i], &prod[i-1], &eval[i]) + } + vecInv(&tmp, &prod[exponent-1]) + for i := exponent - 2; i >= 0; i-- { + vecMul(&prod[i+1], &prod[i], &tmp) + vecMul(&tmp, &tmp, &eval[i+1]) + } + vecCopy(&prod[0], &tmp) + + // fill matrix + deBitSlicing(&list, &prod) + for i := uint64(0); i < (1 << gfBits); i++ { + list[i] <<= gfBits + list[i] |= i + list[i] |= (uint64(perm[i])) << 31 + } + internal.UInt64Sort(list[:], 1<> 31) == (list[i] >> 31) { + return false + } + } + toBitslicing2x(&consts, &prod, &list) + + for i := 0; i < (1 << gfBits); i++ { + pi[i] = int16(list[i] & gfMask) + } + + for j := 0; j < nblocksI; j++ { + for k := 0; k < gfBits; k++ { + mat[k][j] = prod[j][k] + } + } + + for i := 1; i < sysT; i++ { + for j := 0; j < nblocksI; j++ { + vecMul(&prod[j], &prod[j], &consts[j]) + for k := 0; k < gfBits; k++ { + mat[i*gfBits+k][j] = prod[j][k] + } + } + } + + // gaussian elimination to obtain an upper triangular matrix + // and keep track of the operations in ops + + for i := 0; i < pkNRows; i++ { + for j := 0; j < nblocksI; j++ { + ops[i][j] = 0 + } + } + for i := 0; i < pkNRows; i++ { + ops[i][i/64] = 1 + ops[i][i/64] <<= (i % 64) + } + + column := [pkNRows]uint64{} + for i := 0; i < pkNRows; i++ { + column[i] = mat[i][blockIdx] + } + + for row := 0; row < pkNRows; row++ { + i := row >> 6 + j := row & 63 + + for k := row + 1; k < pkNRows; k++ { + mask = mat[row][i] >> j + mask &= 1 + mask -= 1 + + for c := 0; c < nblocksI; c++ { + mat[row][c] ^= mat[k][c] & mask + ops[row][c] ^= ops[k][c] & mask + } + + } + // return if not systematic + if ((mat[row][i] >> j) & 1) == 0 { + return false + } + + for k := row + 1; k < pkNRows; k++ { + mask = mat[k][i] >> j + mask &= 1 + mask = -mask + + for c := 0; c < nblocksI; c++ { + mat[k][c] ^= mat[row][c] & mask + + ops[k][c] ^= ops[row][c] & mask + + } + } + } + + pkp := pk[:] + + // computing the lineaer map required to obatin the systematic form + + for row := pkNRows - 1; row >= 0; row-- { + for k := 0; k < row; k++ { + mask = mat[k][row/64] >> (row & 63) + mask &= 1 + mask = -mask + + for c := 0; c < nblocksI; c++ { + ops[k][c] ^= ops[row][c] & mask + } + } + } + + // apply the linear map to the non-systematic part + for j := nblocksI; j < nblocksH; j++ { + for k := 0; k < gfBits; k++ { + mat[k][j] = prod[j][k] + } + } + + for i := 1; i < sysT; i++ { + for j := nblocksI; j < nblocksH; j++ { + vecMul(&prod[j], &prod[j], &consts[j]) + for k := 0; k < gfBits; k++ { + mat[i*gfBits+k][j] = prod[j][k] + } + } + } + + for i := 0; i < pkNRows; i++ { + mat[i][blockIdx] = column[i] + } + + for row := 0; row < pkNRows; row++ { + for k := 0; k < nblocksH; k++ { + oneRow[k] = 0 + } + + for c := 0; c < pkNRows; c++ { + mask = ops[row][c>>6] >> (c & 63) + mask &= 1 + mask = -mask + + for k := blockIdx; k < nblocksH; k++ { + oneRow[k] ^= mat[c][k] & mask + } + } + + var k int + for k = blockIdx; k < nblocksH-1; k++ { + + oneRow[k] = (oneRow[k] >> tail) | (oneRow[k+1] << (64 - tail)) + + store8(pkp, oneRow[k]) + pkp = pkp[8:] + } + + oneRow[k] >>= tail + + storeI(pkp, oneRow[k], pkRowBytes%8) + + pkp[(pkRowBytes%8)-1] &= (1 << (pkNCols % 8)) - 1 // removing redundant bits + + pkp = pkp[pkRowBytes%8:] + } + + return true +} diff --git a/go/cm/enc/mceliece6960119-x25519/mceliece6960119/vec.go b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/vec.go new file mode 100644 index 0000000..74a7469 --- /dev/null +++ b/go/cm/enc/mceliece6960119-x25519/mceliece6960119/vec.go @@ -0,0 +1,132 @@ +// Code generated from vec.templ.go. DO NOT EDIT. + +// The following code is translated from the C `vec` Additional Implementation +// from the NIST round 4 submission package. + +package mceliece6960119 + +func vecMul(h, f, g *[gfBits]uint64) { + buf := [2*gfBits - 1]uint64{} + + for i := 0; i < 2*gfBits-1; i++ { + buf[i] = 0 + } + + for i := 0; i < gfBits; i++ { + for j := 0; j < gfBits; j++ { + buf[i+j] ^= f[i] & g[j] + } + } + + for i := 2*gfBits - 2; i >= gfBits; i-- { + + buf[i-gfBits+4] ^= buf[i] + buf[i-gfBits+3] ^= buf[i] + buf[i-gfBits+1] ^= buf[i] + buf[i-gfBits+0] ^= buf[i] + + } + + for i := 0; i < gfBits; i++ { + h[i] = buf[i] + } +} + +// bitsliced field squarings +func vecSq(out, in *[gfBits]uint64) { + result := [gfBits]uint64{} + + t := in[11] ^ in[12] + + result[0] = in[0] ^ in[11] + result[1] = in[7] ^ t + result[2] = in[1] ^ in[7] + result[3] = in[8] ^ t + result[4] = in[2] ^ in[7] + result[4] = result[4] ^ in[8] + result[4] = result[4] ^ t + result[5] = in[7] ^ in[9] + result[6] = in[3] ^ in[8] + result[6] = result[6] ^ in[9] + result[6] = result[6] ^ in[12] + result[7] = in[8] ^ in[10] + result[8] = in[4] ^ in[9] + result[8] = result[8] ^ in[10] + result[9] = in[9] ^ in[11] + result[10] = in[5] ^ in[10] + result[10] = result[10] ^ in[11] + result[11] = in[10] ^ in[12] + result[12] = in[6] ^ t + + for i := 0; i < gfBits; i++ { + out[i] = result[i] + } +} + +// bitsliced field inverses +func vecInv(out, in *[gfBits]uint64) { + tmp11 := [gfBits]uint64{} + tmp1111 := [gfBits]uint64{} + + vecCopy(out, in) + + vecSq(out, out) + vecMul(&tmp11, out, in) // ^11 + + vecSq(out, &tmp11) + vecSq(out, out) + vecMul(&tmp1111, out, &tmp11) // ^1111 + + vecSq(out, &tmp1111) + vecSq(out, out) + vecSq(out, out) + vecSq(out, out) + vecMul(out, out, &tmp1111) // ^11111111 + + vecSq(out, out) + vecSq(out, out) + vecSq(out, out) + vecSq(out, out) + vecMul(out, out, &tmp1111) // ^111111111111 + + vecSq(out, out) // ^1111111111110 +} + +func vecSetBits(b uint64) uint64 { + ret := -b + return ret +} + +func vecSet116b(v uint16) uint64 { + ret := uint64(v) + ret |= ret << 16 + ret |= ret << 32 + + return ret +} + +func vecCopy(out, in *[gfBits]uint64) { + for i := 0; i < gfBits; i++ { + out[i] = in[i] + } +} + +func vecOrReduce(a *[gfBits]uint64) uint64 { + ret := a[0] + for i := 1; i < gfBits; i++ { + ret |= a[i] + } + + return ret +} + +func vecTestZ(a uint64) int { + a |= a >> 32 + a |= a >> 16 + a |= a >> 8 + a |= a >> 4 + a |= a >> 2 + a |= a >> 1 + + return int((a & 1) ^ 1) +} diff --git a/go/cm/sntrup4591761-x25519/algo.go b/go/cm/enc/sntrup4591761-x25519/algo.go similarity index 100% rename from go/cm/sntrup4591761-x25519/algo.go rename to go/cm/enc/sntrup4591761-x25519/algo.go diff --git a/go/cm/sntrup4591761-x25519/kp.go b/go/cm/enc/sntrup4591761-x25519/kp.go similarity index 100% rename from go/cm/sntrup4591761-x25519/kp.go rename to go/cm/enc/sntrup4591761-x25519/kp.go diff --git a/go/cm/go.mod b/go/cm/go.mod index e296bd9..c5fe918 100644 --- a/go/cm/go.mod +++ b/go/cm/go.mod @@ -3,11 +3,19 @@ module go.cypherpunks.su/keks/cm go 1.24 require ( + github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a github.com/google/uuid v1.6.0 + go.cypherpunks.su/balloon/v3 v3.0.0 go.cypherpunks.su/gogost/v6 v6.1.0 + go.cypherpunks.su/keks v0.0.0-00010101000000-000000000000 + golang.org/x/crypto v0.32.0 + golang.org/x/sys v0.29.0 + golang.org/x/term v0.28.0 ) require ( - go.cypherpunks.su/balloon/v3 v3.0.0 // indirect - golang.org/x/crypto v0.32.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + go.cypherpunks.su/tai64n/v4 v4.1.0 // indirect ) + +replace go.cypherpunks.su/keks => ../ diff --git a/go/cm/go.sum b/go/cm/go.sum index 55a7d0f..b05aeae 100644 --- a/go/cm/go.sum +++ b/go/cm/go.sum @@ -1,6 +1,18 @@ +github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a h1:clYxJ3Os0EQUKDDVU8M0oipllX0EkuFNBfhVQuIfyF0= +github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a/go.mod h1:z/9Ck1EDixEbBbZ2KH2qNHekEmDLTOZ+FyoIPWWSVOI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +go.cypherpunks.su/balloon/v3 v3.0.0 h1:80JUfOvjEgeuQlZ8biZarbuld0T9L/6gbC2DAZAZncI= go.cypherpunks.su/balloon/v3 v3.0.0/go.mod h1:ftUPgriajbLsU16feNNHht6cuOwxCK6MGnDK3lLQhgM= go.cypherpunks.su/gogost/v6 v6.1.0 h1:RJHFxDZ2j/TIfHXGn4AG0fTDg19GEX/oVFAgMvLCIPM= go.cypherpunks.su/gogost/v6 v6.1.0/go.mod h1:cj9i0r80PN7jrwMqBAWhaY8JetCeg4x5jjnZsVRkaPI= +go.cypherpunks.su/tai64n/v4 v4.1.0 h1:jW0EyklKXpSy9DSFMcDbu7XuLlMkn6kkpNWiMG6UT5c= +go.cypherpunks.su/tai64n/v4 v4.1.0/go.mod h1:/uKUdhLOy8UciRKpapPaFXSOoa/SiXjs3XsDDpAz7OA= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= diff --git a/go/cm/hash/algo.go b/go/cm/hash/algo.go index 7459fc3..3942c7b 100644 --- a/go/cm/hash/algo.go +++ b/go/cm/hash/algo.go @@ -23,8 +23,8 @@ import ( "go.cypherpunks.su/gogost/v6/gost34112012512" "golang.org/x/crypto/blake2b" - ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b" - "go.cypherpunks.su/keks/cm/gost" + cmblake2b "go.cypherpunks.su/keks/cm/hash/blake2b" + "go.cypherpunks.su/keks/cm/hash/gost" "go.cypherpunks.su/keks/cm/hash/merkle" ) @@ -56,14 +56,14 @@ func ByName(name string) hash.Hash { case Streebog512Merkle, gost.GOST3410512CMerkle: return gost.NewMerkleHasher(gost34112012512.New, merkle.DefaultChunkLen, runtime.NumCPU()) - case BLAKE2b, ed25519blake2b.Ed25519BLAKE2b, ed25519blake2b.Ed25519PhBLAKE2b: + case BLAKE2b, cmblake2b.Ed25519BLAKE2b, cmblake2b.Ed25519PhBLAKE2b: h, err := blake2b.New512(nil) if err != nil { panic(err) } return h - case BLAKE2bMerkle, ed25519blake2b.Ed25519PhBLAKE2bMerkle: - return ed25519blake2b.NewMerkleHasher( + case BLAKE2bMerkle, cmblake2b.Ed25519PhBLAKE2bMerkle: + return cmblake2b.NewMerkleHasher( merkle.DefaultChunkLen, runtime.NumCPU()) case BLAKE2b256: h, err := blake2b.New256(nil) diff --git a/go/cm/ed25519-blake2b/algo.go b/go/cm/hash/blake2b/algo.go similarity index 100% rename from go/cm/ed25519-blake2b/algo.go rename to go/cm/hash/blake2b/algo.go diff --git a/go/cm/ed25519-blake2b/hasher.go b/go/cm/hash/blake2b/hasher.go similarity index 100% rename from go/cm/ed25519-blake2b/hasher.go rename to go/cm/hash/blake2b/hasher.go diff --git a/go/cm/hash/gost/algo.go b/go/cm/hash/gost/algo.go new file mode 100644 index 0000000..910c9bb --- /dev/null +++ b/go/cm/hash/gost/algo.go @@ -0,0 +1,8 @@ +package gost + +const ( + GOST3410256A = "gost3410-256A" + GOST3410512C = "gost3410-512C" + GOST3410256AMerkle = "gost3410-256A-merkle" + GOST3410512CMerkle = "gost3410-512C-merkle" +) diff --git a/go/cm/gost/hasher.go b/go/cm/hash/gost/hasher.go similarity index 90% rename from go/cm/gost/hasher.go rename to go/cm/hash/gost/hasher.go index fcd729e..4ffae5b 100644 --- a/go/cm/gost/hasher.go +++ b/go/cm/hash/gost/hasher.go @@ -21,11 +21,6 @@ import ( "go.cypherpunks.su/keks/cm/hash/merkle" ) -const ( - GOST3410256AMerkle = "gost3410-256A-merkle" - GOST3410512CMerkle = "gost3410-512C-merkle" -) - func NewMerkleHasher(h func() hash.Hash, chunkLen, workers int) hash.Hash { return merkle.NewHasherPrefixed(h, chunkLen, workers) } diff --git a/go/cm/hash/magic.go b/go/cm/hash/magic.go new file mode 100644 index 0000000..dd385bb --- /dev/null +++ b/go/cm/hash/magic.go @@ -0,0 +1,5 @@ +package hash + +import "go.cypherpunks.su/keks" + +const Magic = keks.Magic("cm/hashed") diff --git a/go/cm/mceliece6960119-x25519/SOURCE b/go/cm/mceliece6960119-x25519/SOURCE deleted file mode 100644 index 4fa5970..0000000 --- a/go/cm/mceliece6960119-x25519/SOURCE +++ /dev/null @@ -1,3 +0,0 @@ -https://github.com/cloudflare/circl/pull/378 -https://github.com/cloudflare/circl.git -7dfc396c96830ed3601ace705e1612b9bcc447f9 diff --git a/go/cm/sign/ed25519-blake2b/README b/go/cm/sign/ed25519-blake2b/README new file mode 100644 index 0000000..24a6208 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/README @@ -0,0 +1,4 @@ +Unfortunately native crypto/internal/ed25519 is not flexible enough and +does not give ability to use different hash in Ed25519. So here is the +copied implementation from Go 1.24 with all dependencies and replaced +SHA2-512 with BLAKE2b-512. diff --git a/go/cm/sign/ed25519-blake2b/algo.go b/go/cm/sign/ed25519-blake2b/algo.go new file mode 100644 index 0000000..36b3f3f --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/algo.go @@ -0,0 +1,7 @@ +package ed25519blake2b + +const ( + Ed25519BLAKE2b = "ed25519-blake2b" + Ed25519PhBLAKE2b = "ed25519ph-blake2b" + Ed25519PhBLAKE2bMerkle = "ed25519ph-blake2b-merkle" +) diff --git a/go/cm/sign/ed25519-blake2b/ed25519/ed25519.go b/go/cm/sign/ed25519-blake2b/ed25519/ed25519.go new file mode 100644 index 0000000..db4d0ae --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/ed25519/ed25519.go @@ -0,0 +1,325 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ed25519 + +import ( + "bytes" + "crypto/rand" + "errors" + "strconv" + + "golang.org/x/crypto/blake2b" + + "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/edwards25519" +) + +// See https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/ for the +// components of the keys and the moving parts of the algorithm. + +const ( + seedSize = 32 + publicKeySize = 32 + privateKeySize = seedSize + publicKeySize + signatureSize = 64 +) + +type PrivateKey struct { + seed [seedSize]byte + pub [publicKeySize]byte + s edwards25519.Scalar + prefix [blake2b.Size / 2]byte +} + +func (priv *PrivateKey) Bytes() []byte { + k := make([]byte, 0, privateKeySize) + k = append(k, priv.seed[:]...) + k = append(k, priv.pub[:]...) + return k +} + +func (priv *PrivateKey) Seed() []byte { + seed := priv.seed + return seed[:] +} + +func (priv *PrivateKey) PublicKey() []byte { + pub := priv.pub + return pub[:] +} + +type PublicKey struct { + a edwards25519.Point + aBytes [32]byte +} + +func (pub *PublicKey) Bytes() []byte { + a := pub.aBytes + return a[:] +} + +// GenerateKey generates a new Ed25519 private key pair. +func GenerateKey() (*PrivateKey, error) { + priv := &PrivateKey{} + return generateKey(priv) +} + +func generateKey(priv *PrivateKey) (*PrivateKey, error) { + rand.Read(priv.seed[:]) + precomputePrivateKey(priv) + return priv, nil +} + +func NewPrivateKeyFromSeed(seed []byte) (*PrivateKey, error) { + priv := &PrivateKey{} + return newPrivateKeyFromSeed(priv, seed) +} + +func newPrivateKeyFromSeed(priv *PrivateKey, seed []byte) (*PrivateKey, error) { + if l := len(seed); l != seedSize { + return nil, errors.New("ed25519: bad seed length: " + strconv.Itoa(l)) + } + copy(priv.seed[:], seed) + precomputePrivateKey(priv) + return priv, nil +} + +func precomputePrivateKey(priv *PrivateKey) { + hs, err := blake2b.New512(nil) + if err != nil { + panic(err) + } + hs.Write(priv.seed[:]) + h := hs.Sum(make([]byte, 0, blake2b.Size)) + + s, err := priv.s.SetBytesWithClamping(h[:32]) + if err != nil { + panic("ed25519: internal error: setting scalar failed") + } + A := (&edwards25519.Point{}).ScalarBaseMult(s) + copy(priv.pub[:], A.Bytes()) + + copy(priv.prefix[:], h[32:]) +} + +func NewPrivateKey(priv []byte) (*PrivateKey, error) { + p := &PrivateKey{} + return newPrivateKey(p, priv) +} + +func newPrivateKey(priv *PrivateKey, privBytes []byte) (*PrivateKey, error) { + if l := len(privBytes); l != privateKeySize { + return nil, errors.New("ed25519: bad private key length: " + strconv.Itoa(l)) + } + + copy(priv.seed[:], privBytes[:32]) + + hs, err := blake2b.New512(nil) + if err != nil { + panic(err) + } + hs.Write(priv.seed[:]) + h := hs.Sum(make([]byte, 0, blake2b.Size)) + + if _, err := priv.s.SetBytesWithClamping(h[:32]); err != nil { + panic("ed25519: internal error: setting scalar failed") + } + // Note that we are not decompressing the public key point here, + // because it takes > 20% of the time of a signature generation. + // Signing doesn't use it as a point anyway. + copy(priv.pub[:], privBytes[32:]) + + copy(priv.prefix[:], h[32:]) + + return priv, nil +} + +func NewPublicKey(pub []byte) (*PublicKey, error) { + p := &PublicKey{} + return newPublicKey(p, pub) +} + +func newPublicKey(pub *PublicKey, pubBytes []byte) (*PublicKey, error) { + if l := len(pubBytes); l != publicKeySize { + return nil, errors.New("ed25519: bad public key length: " + strconv.Itoa(l)) + } + // SetBytes checks that the point is on the curve. + if _, err := pub.a.SetBytes(pubBytes); err != nil { + return nil, errors.New("ed25519: bad public key") + } + copy(pub.aBytes[:], pubBytes) + return pub, nil +} + +// Domain separation prefixes used to disambiguate Ed25519/Ed25519ph/Ed25519ctx. +// See RFC 8032, Section 2 and Section 5.1. +const ( + // domPrefixPure is empty for pure Ed25519. + domPrefixPure = "" + // domPrefixPh is dom2(phflag=1) for Ed25519ph. It must be followed by the + // uint8-length prefixed context. + domPrefixPh = "SigEd25519 no Ed25519 collisions\x01" + // domPrefixCtx is dom2(phflag=0) for Ed25519ctx. It must be followed by the + // uint8-length prefixed context. + domPrefixCtx = "SigEd25519 no Ed25519 collisions\x00" +) + +func Sign(priv *PrivateKey, message []byte) []byte { + // Outline the function body so that the returned signature can be + // stack-allocated. + signature := make([]byte, signatureSize) + return sign(signature, priv, message) +} + +func sign(signature []byte, priv *PrivateKey, message []byte) []byte { + return signWithDom(signature, priv, message, domPrefixPure, "") +} + +func SignPH(priv *PrivateKey, message []byte, context string) ([]byte, error) { + // Outline the function body so that the returned signature can be + // stack-allocated. + signature := make([]byte, signatureSize) + return signPH(signature, priv, message, context) +} + +func signPH(signature []byte, priv *PrivateKey, message []byte, context string) ([]byte, error) { + if l := len(message); l != blake2b.Size { + return nil, errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l)) + } + if l := len(context); l > 255 { + return nil, errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l)) + } + return signWithDom(signature, priv, message, domPrefixPh, context), nil +} + +func SignCtx(priv *PrivateKey, message []byte, context string) ([]byte, error) { + // Outline the function body so that the returned signature can be + // stack-allocated. + signature := make([]byte, signatureSize) + return signCtx(signature, priv, message, context) +} + +func signCtx(signature []byte, priv *PrivateKey, message []byte, context string) ([]byte, error) { + // Note that per RFC 8032, Section 5.1, the context SHOULD NOT be empty. + if l := len(context); l > 255 { + return nil, errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l)) + } + return signWithDom(signature, priv, message, domPrefixCtx, context), nil +} + +func signWithDom(signature []byte, priv *PrivateKey, message []byte, domPrefix, context string) []byte { + mh, err := blake2b.New512(nil) + if err != nil { + panic(err) + } + if domPrefix != domPrefixPure { + mh.Write([]byte(domPrefix)) + mh.Write([]byte{byte(len(context))}) + mh.Write([]byte(context)) + } + mh.Write(priv.prefix[:]) + mh.Write(message) + messageDigest := make([]byte, 0, blake2b.Size) + messageDigest = mh.Sum(messageDigest) + r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest) + if err != nil { + panic("ed25519: internal error: setting scalar failed") + } + + R := (&edwards25519.Point{}).ScalarBaseMult(r) + + kh, err := blake2b.New512(nil) + if err != nil { + panic(err) + } + if domPrefix != domPrefixPure { + kh.Write([]byte(domPrefix)) + kh.Write([]byte{byte(len(context))}) + kh.Write([]byte(context)) + } + kh.Write(R.Bytes()) + kh.Write(priv.pub[:]) + kh.Write(message) + hramDigest := make([]byte, 0, blake2b.Size) + hramDigest = kh.Sum(hramDigest) + k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) + if err != nil { + panic("ed25519: internal error: setting scalar failed") + } + + S := edwards25519.NewScalar().MultiplyAdd(k, &priv.s, r) + + copy(signature[:32], R.Bytes()) + copy(signature[32:], S.Bytes()) + + return signature +} + +func Verify(pub *PublicKey, message, sig []byte) error { + return verify(pub, message, sig) +} + +func verify(pub *PublicKey, message, sig []byte) error { + return verifyWithDom(pub, message, sig, domPrefixPure, "") +} + +func VerifyPH(pub *PublicKey, message, sig []byte, context string) error { + if l := len(message); l != blake2b.Size { + return errors.New("ed25519: bad Ed25519ph message hash length: " + strconv.Itoa(l)) + } + if l := len(context); l > 255 { + return errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l)) + } + return verifyWithDom(pub, message, sig, domPrefixPh, context) +} + +func VerifyCtx(pub *PublicKey, message, sig []byte, context string) error { + if l := len(context); l > 255 { + return errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l)) + } + return verifyWithDom(pub, message, sig, domPrefixCtx, context) +} + +func verifyWithDom(pub *PublicKey, message, sig []byte, domPrefix, context string) error { + if l := len(sig); l != signatureSize { + return errors.New("ed25519: bad signature length: " + strconv.Itoa(l)) + } + + if sig[63]&224 != 0 { + return errors.New("ed25519: invalid signature") + } + + kh, err := blake2b.New512(nil) + if err != nil { + panic(err) + } + if domPrefix != domPrefixPure { + kh.Write([]byte(domPrefix)) + kh.Write([]byte{byte(len(context))}) + kh.Write([]byte(context)) + } + kh.Write(sig[:32]) + kh.Write(pub.aBytes[:]) + kh.Write(message) + hramDigest := make([]byte, 0, blake2b.Size) + hramDigest = kh.Sum(hramDigest) + k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest) + if err != nil { + panic("ed25519: internal error: setting scalar failed") + } + + S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:]) + if err != nil { + return errors.New("ed25519: invalid signature") + } + + // [S]B = R + [k]A --> [k](-A) + [S]B = R + minusA := (&edwards25519.Point{}).Negate(&pub.a) + R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S) + + if !bytes.Equal(sig[:32], R.Bytes()) { + return errors.New("ed25519: invalid signature") + } + return nil +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/alias/alias.go b/go/cm/sign/ed25519-blake2b/edwards25519/alias/alias.go new file mode 100644 index 0000000..cd6dee9 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/alias/alias.go @@ -0,0 +1,30 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package alias implements memory aliasing tests. +// This code also exists as golang.org/x/crypto/internal/alias. +package alias + +import "unsafe" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && + uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/byteorder/byteorder.go b/go/cm/sign/ed25519-blake2b/edwards25519/byteorder/byteorder.go new file mode 100644 index 0000000..acf4f32 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/byteorder/byteorder.go @@ -0,0 +1,149 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package byteorder provides functions for decoding and encoding +// little and big endian integer types from/to byte slices. +package byteorder + +func LEUint16(b []byte) uint16 { + _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 + return uint16(b[0]) | uint16(b[1])<<8 +} + +func LEPutUint16(b []byte, v uint16) { + _ = b[1] // early bounds check to guarantee safety of writes below + b[0] = byte(v) + b[1] = byte(v >> 8) +} + +func LEAppendUint16(b []byte, v uint16) []byte { + return append(b, + byte(v), + byte(v>>8), + ) +} + +func LEUint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func LEPutUint32(b []byte, v uint32) { + _ = b[3] // early bounds check to guarantee safety of writes below + b[0] = byte(v) + b[1] = byte(v >> 8) + b[2] = byte(v >> 16) + b[3] = byte(v >> 24) +} + +func LEAppendUint32(b []byte, v uint32) []byte { + return append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24), + ) +} + +func LEUint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +func LEPutUint64(b []byte, v uint64) { + _ = b[7] // early bounds check to guarantee safety of writes below + b[0] = byte(v) + b[1] = byte(v >> 8) + b[2] = byte(v >> 16) + b[3] = byte(v >> 24) + b[4] = byte(v >> 32) + b[5] = byte(v >> 40) + b[6] = byte(v >> 48) + b[7] = byte(v >> 56) +} + +func LEAppendUint64(b []byte, v uint64) []byte { + return append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24), + byte(v>>32), + byte(v>>40), + byte(v>>48), + byte(v>>56), + ) +} + +func BEUint16(b []byte) uint16 { + _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 + return uint16(b[1]) | uint16(b[0])<<8 +} + +func BEPutUint16(b []byte, v uint16) { + _ = b[1] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 8) + b[1] = byte(v) +} + +func BEAppendUint16(b []byte, v uint16) []byte { + return append(b, + byte(v>>8), + byte(v), + ) +} + +func BEUint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 +} + +func BEPutUint32(b []byte, v uint32) { + _ = b[3] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 24) + b[1] = byte(v >> 16) + b[2] = byte(v >> 8) + b[3] = byte(v) +} + +func BEAppendUint32(b []byte, v uint32) []byte { + return append(b, + byte(v>>24), + byte(v>>16), + byte(v>>8), + byte(v), + ) +} + +func BEUint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 +} + +func BEPutUint64(b []byte, v uint64) { + _ = b[7] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 56) + b[1] = byte(v >> 48) + b[2] = byte(v >> 40) + b[3] = byte(v >> 32) + b[4] = byte(v >> 24) + b[5] = byte(v >> 16) + b[6] = byte(v >> 8) + b[7] = byte(v) +} + +func BEAppendUint64(b []byte, v uint64) []byte { + return append(b, + byte(v>>56), + byte(v>>48), + byte(v>>40), + byte(v>>32), + byte(v>>24), + byte(v>>16), + byte(v>>8), + byte(v), + ) +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/doc.go b/go/cm/sign/ed25519-blake2b/edwards25519/doc.go new file mode 100644 index 0000000..aec810c --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/doc.go @@ -0,0 +1,22 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package edwards25519 implements group logic for the twisted Edwards curve +// +// -x^2 + y^2 = 1 + -(121665/121666)*x^2*y^2 +// +// This is better known as the Edwards curve equivalent to Curve25519, and is +// the curve used by the Ed25519 signature scheme. +// +// Most users don't need this package, and should instead use crypto/ed25519 for +// signatures, golang.org/x/crypto/curve25519 for Diffie-Hellman, or +// github.com/gtank/ristretto255 for prime order group logic. +// +// However, developers who do need to interact with low-level edwards25519 +// operations can use filippo.io/edwards25519, an extended version of this +// package repackaged as an importable module. +// +// (Note that filippo.io/edwards25519 and github.com/gtank/ristretto255 are not +// maintained by the Go team and are not covered by the Go 1 Compatibility Promise.) +package edwards25519 diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/edwards25519.go b/go/cm/sign/ed25519-blake2b/edwards25519/edwards25519.go new file mode 100644 index 0000000..6d19b86 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/edwards25519.go @@ -0,0 +1,430 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "errors" + + "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/edwards25519/field" +) + +// Point types. + +type projP1xP1 struct { + X, Y, Z, T field.Element +} + +type projP2 struct { + X, Y, Z field.Element +} + +// Point represents a point on the edwards25519 curve. +// +// This type works similarly to math/big.Int, and all arguments and receivers +// are allowed to alias. +// +// The zero value is NOT valid, and it may be used only as a receiver. +type Point struct { + // Make the type not comparable (i.e. used with == or as a map key), as + // equivalent points can be represented by different Go values. + _ incomparable + + // The point is internally represented in extended coordinates (X, Y, Z, T) + // where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522. + x, y, z, t field.Element +} + +type incomparable [0]func() + +func checkInitialized(points ...*Point) { + for _, p := range points { + if p.x == (field.Element{}) && p.y == (field.Element{}) { + panic("edwards25519: use of uninitialized Point") + } + } +} + +type projCached struct { + YplusX, YminusX, Z, T2d field.Element +} + +type affineCached struct { + YplusX, YminusX, T2d field.Element +} + +// Constructors. + +func (v *projP2) Zero() *projP2 { + v.X.Zero() + v.Y.One() + v.Z.One() + return v +} + +// identity is the point at infinity. +var identity, _ = new(Point).SetBytes([]byte{ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}) + +// NewIdentityPoint returns a new Point set to the identity. +func NewIdentityPoint() *Point { + return new(Point).Set(identity) +} + +// generator is the canonical curve basepoint. See TestGenerator for the +// correspondence of this encoding with the values in RFC 8032. +var generator, _ = new(Point).SetBytes([]byte{ + 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +}) + +// NewGeneratorPoint returns a new Point set to the canonical generator. +func NewGeneratorPoint() *Point { + return new(Point).Set(generator) +} + +func (v *projCached) Zero() *projCached { + v.YplusX.One() + v.YminusX.One() + v.Z.One() + v.T2d.Zero() + return v +} + +func (v *affineCached) Zero() *affineCached { + v.YplusX.One() + v.YminusX.One() + v.T2d.Zero() + return v +} + +// Assignments. + +// Set sets v = u, and returns v. +func (v *Point) Set(u *Point) *Point { + *v = *u + return v +} + +// Encoding. + +// Bytes returns the canonical 32-byte encoding of v, according to RFC 8032, +// Section 5.1.2. +func (v *Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var buf [32]byte + return v.bytes(&buf) +} + +func (v *Point) bytes(buf *[32]byte) []byte { + checkInitialized(v) + + var zInv, x, y field.Element + zInv.Invert(&v.z) // zInv = 1 / Z + x.Multiply(&v.x, &zInv) // x = X / Z + y.Multiply(&v.y, &zInv) // y = Y / Z + + out := copyFieldElement(buf, &y) + out[31] |= byte(x.IsNegative() << 7) + return out +} + +var feOne = new(field.Element).One() + +// SetBytes sets v = x, where x is a 32-byte encoding of v. If x does not +// represent a valid point on the curve, SetBytes returns nil and an error and +// the receiver is unchanged. Otherwise, SetBytes returns v. +// +// Note that SetBytes accepts all non-canonical encodings of valid points. +// That is, it follows decoding rules that match most implementations in +// the ecosystem rather than RFC 8032. +func (v *Point) SetBytes(x []byte) (*Point, error) { + // Specifically, the non-canonical encodings that are accepted are + // 1) the ones where the field element is not reduced (see the + // (*field.Element).SetBytes docs) and + // 2) the ones where the x-coordinate is zero and the sign bit is set. + // + // Read more at https://hdevalence.ca/blog/2020-10-04-its-25519am, + // specifically the "Canonical A, R" section. + + y, err := new(field.Element).SetBytes(x) + if err != nil { + return nil, errors.New("edwards25519: invalid point encoding length") + } + + // -x² + y² = 1 + dx²y² + // x² + dx²y² = x²(dy² + 1) = y² - 1 + // x² = (y² - 1) / (dy² + 1) + + // u = y² - 1 + y2 := new(field.Element).Square(y) + u := new(field.Element).Subtract(y2, feOne) + + // v = dy² + 1 + vv := new(field.Element).Multiply(y2, d) + vv = vv.Add(vv, feOne) + + // x = +√(u/v) + xx, wasSquare := new(field.Element).SqrtRatio(u, vv) + if wasSquare == 0 { + return nil, errors.New("edwards25519: invalid point encoding") + } + + // Select the negative square root if the sign bit is set. + xxNeg := new(field.Element).Negate(xx) + xx = xx.Select(xxNeg, xx, int(x[31]>>7)) + + v.x.Set(xx) + v.y.Set(y) + v.z.One() + v.t.Multiply(xx, y) // xy = T / Z + + return v, nil +} + +func copyFieldElement(buf *[32]byte, v *field.Element) []byte { + copy(buf[:], v.Bytes()) + return buf[:] +} + +// Conversions. + +func (v *projP2) FromP1xP1(p *projP1xP1) *projP2 { + v.X.Multiply(&p.X, &p.T) + v.Y.Multiply(&p.Y, &p.Z) + v.Z.Multiply(&p.Z, &p.T) + return v +} + +func (v *projP2) FromP3(p *Point) *projP2 { + v.X.Set(&p.x) + v.Y.Set(&p.y) + v.Z.Set(&p.z) + return v +} + +func (v *Point) fromP1xP1(p *projP1xP1) *Point { + v.x.Multiply(&p.X, &p.T) + v.y.Multiply(&p.Y, &p.Z) + v.z.Multiply(&p.Z, &p.T) + v.t.Multiply(&p.X, &p.Y) + return v +} + +func (v *Point) fromP2(p *projP2) *Point { + v.x.Multiply(&p.X, &p.Z) + v.y.Multiply(&p.Y, &p.Z) + v.z.Square(&p.Z) + v.t.Multiply(&p.X, &p.Y) + return v +} + +// d is a constant in the curve equation. +var d, _ = new(field.Element).SetBytes([]byte{ + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, + 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, + 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52, +}) +var d2 = new(field.Element).Add(d, d) + +func (v *projCached) FromP3(p *Point) *projCached { + v.YplusX.Add(&p.y, &p.x) + v.YminusX.Subtract(&p.y, &p.x) + v.Z.Set(&p.z) + v.T2d.Multiply(&p.t, d2) + return v +} + +func (v *affineCached) FromP3(p *Point) *affineCached { + v.YplusX.Add(&p.y, &p.x) + v.YminusX.Subtract(&p.y, &p.x) + v.T2d.Multiply(&p.t, d2) + + var invZ field.Element + invZ.Invert(&p.z) + v.YplusX.Multiply(&v.YplusX, &invZ) + v.YminusX.Multiply(&v.YminusX, &invZ) + v.T2d.Multiply(&v.T2d, &invZ) + return v +} + +// (Re)addition and subtraction. + +// Add sets v = p + q, and returns v. +func (v *Point) Add(p, q *Point) *Point { + checkInitialized(p, q) + qCached := new(projCached).FromP3(q) + result := new(projP1xP1).Add(p, qCached) + return v.fromP1xP1(result) +} + +// Subtract sets v = p - q, and returns v. +func (v *Point) Subtract(p, q *Point) *Point { + checkInitialized(p, q) + qCached := new(projCached).FromP3(q) + result := new(projP1xP1).Sub(p, qCached) + return v.fromP1xP1(result) +} + +func (v *projP1xP1) Add(p *Point, q *projCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YplusX) + MM.Multiply(&YminusX, &q.YminusX) + TT2d.Multiply(&p.t, &q.T2d) + ZZ2.Multiply(&p.z, &q.Z) + + ZZ2.Add(&ZZ2, &ZZ2) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Add(&ZZ2, &TT2d) + v.T.Subtract(&ZZ2, &TT2d) + return v +} + +func (v *projP1xP1) Sub(p *Point, q *projCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YminusX) // flipped sign + MM.Multiply(&YminusX, &q.YplusX) // flipped sign + TT2d.Multiply(&p.t, &q.T2d) + ZZ2.Multiply(&p.z, &q.Z) + + ZZ2.Add(&ZZ2, &ZZ2) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Subtract(&ZZ2, &TT2d) // flipped sign + v.T.Add(&ZZ2, &TT2d) // flipped sign + return v +} + +func (v *projP1xP1) AddAffine(p *Point, q *affineCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YplusX) + MM.Multiply(&YminusX, &q.YminusX) + TT2d.Multiply(&p.t, &q.T2d) + + Z2.Add(&p.z, &p.z) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Add(&Z2, &TT2d) + v.T.Subtract(&Z2, &TT2d) + return v +} + +func (v *projP1xP1) SubAffine(p *Point, q *affineCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YminusX) // flipped sign + MM.Multiply(&YminusX, &q.YplusX) // flipped sign + TT2d.Multiply(&p.t, &q.T2d) + + Z2.Add(&p.z, &p.z) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Subtract(&Z2, &TT2d) // flipped sign + v.T.Add(&Z2, &TT2d) // flipped sign + return v +} + +// Doubling. + +func (v *projP1xP1) Double(p *projP2) *projP1xP1 { + var XX, YY, ZZ2, XplusYsq field.Element + + XX.Square(&p.X) + YY.Square(&p.Y) + ZZ2.Square(&p.Z) + ZZ2.Add(&ZZ2, &ZZ2) + XplusYsq.Add(&p.X, &p.Y) + XplusYsq.Square(&XplusYsq) + + v.Y.Add(&YY, &XX) + v.Z.Subtract(&YY, &XX) + + v.X.Subtract(&XplusYsq, &v.Y) + v.T.Subtract(&ZZ2, &v.Z) + return v +} + +// Negation. + +// Negate sets v = -p, and returns v. +func (v *Point) Negate(p *Point) *Point { + checkInitialized(p) + v.x.Negate(&p.x) + v.y.Set(&p.y) + v.z.Set(&p.z) + v.t.Negate(&p.t) + return v +} + +// Equal returns 1 if v is equivalent to u, and 0 otherwise. +func (v *Point) Equal(u *Point) int { + checkInitialized(v, u) + + var t1, t2, t3, t4 field.Element + t1.Multiply(&v.x, &u.z) + t2.Multiply(&u.x, &v.z) + t3.Multiply(&v.y, &u.z) + t4.Multiply(&u.y, &v.z) + + return t1.Equal(&t2) & t3.Equal(&t4) +} + +// Constant-time operations + +// Select sets v to a if cond == 1 and to b if cond == 0. +func (v *projCached) Select(a, b *projCached, cond int) *projCached { + v.YplusX.Select(&a.YplusX, &b.YplusX, cond) + v.YminusX.Select(&a.YminusX, &b.YminusX, cond) + v.Z.Select(&a.Z, &b.Z, cond) + v.T2d.Select(&a.T2d, &b.T2d, cond) + return v +} + +// Select sets v to a if cond == 1 and to b if cond == 0. +func (v *affineCached) Select(a, b *affineCached, cond int) *affineCached { + v.YplusX.Select(&a.YplusX, &b.YplusX, cond) + v.YminusX.Select(&a.YminusX, &b.YminusX, cond) + v.T2d.Select(&a.T2d, &b.T2d, cond) + return v +} + +// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. +func (v *projCached) CondNeg(cond int) *projCached { + v.YplusX.Swap(&v.YminusX, cond) + v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond) + return v +} + +// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. +func (v *affineCached) CondNeg(cond int) *affineCached { + v.YplusX.Swap(&v.YminusX, cond) + v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond) + return v +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/fe_amd64_asm.go b/go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/fe_amd64_asm.go new file mode 100644 index 0000000..fe6abb0 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/fe_amd64_asm.go @@ -0,0 +1,294 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/gotypes" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" +) + +//go:generate go run . -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field + +func main() { + Package("go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/edwards25519/field") + ConstraintExpr("!purego") + feMul() + feSquare() + Generate() +} + +type namedComponent struct { + Component + name string +} + +func (c namedComponent) String() string { return c.name } + +type uint128 struct { + name string + hi, lo GPVirtual +} + +func (c uint128) String() string { return c.name } + +func feSquare() { + TEXT("feSquare", NOSPLIT, "func(out, a *Element)") + Doc("feSquare sets out = a * a. It works like feSquareGeneric.") + Pragma("noescape") + + a := Dereference(Param("a")) + l0 := namedComponent{a.Field("l0"), "l0"} + l1 := namedComponent{a.Field("l1"), "l1"} + l2 := namedComponent{a.Field("l2"), "l2"} + l3 := namedComponent{a.Field("l3"), "l3"} + l4 := namedComponent{a.Field("l4"), "l4"} + + // r0 = l0×l0 + 19×2×(l1×l4 + l2×l3) + r0 := uint128{"r0", GP64(), GP64()} + mul64(r0, 1, l0, l0) + addMul64(r0, 38, l1, l4) + addMul64(r0, 38, l2, l3) + + // r1 = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 + r1 := uint128{"r1", GP64(), GP64()} + mul64(r1, 2, l0, l1) + addMul64(r1, 38, l2, l4) + addMul64(r1, 19, l3, l3) + + // r2 = = 2×l0×l2 + l1×l1 + 19×2×l3×l4 + r2 := uint128{"r2", GP64(), GP64()} + mul64(r2, 2, l0, l2) + addMul64(r2, 1, l1, l1) + addMul64(r2, 38, l3, l4) + + // r3 = = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 + r3 := uint128{"r3", GP64(), GP64()} + mul64(r3, 2, l0, l3) + addMul64(r3, 2, l1, l2) + addMul64(r3, 19, l4, l4) + + // r4 = = 2×l0×l4 + 2×l1×l3 + l2×l2 + r4 := uint128{"r4", GP64(), GP64()} + mul64(r4, 2, l0, l4) + addMul64(r4, 2, l1, l3) + addMul64(r4, 1, l2, l2) + + Comment("First reduction chain") + maskLow51Bits := GP64() + MOVQ(Imm((1<<51)-1), maskLow51Bits) + c0, r0lo := shiftRightBy51(&r0) + c1, r1lo := shiftRightBy51(&r1) + c2, r2lo := shiftRightBy51(&r2) + c3, r3lo := shiftRightBy51(&r3) + c4, r4lo := shiftRightBy51(&r4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Second reduction chain (carryPropagate)") + // c0 = r0 >> 51 + MOVQ(r0lo, c0) + SHRQ(Imm(51), c0) + // c1 = r1 >> 51 + MOVQ(r1lo, c1) + SHRQ(Imm(51), c1) + // c2 = r2 >> 51 + MOVQ(r2lo, c2) + SHRQ(Imm(51), c2) + // c3 = r3 >> 51 + MOVQ(r3lo, c3) + SHRQ(Imm(51), c3) + // c4 = r4 >> 51 + MOVQ(r4lo, c4) + SHRQ(Imm(51), c4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Store output") + out := Dereference(Param("out")) + Store(r0lo, out.Field("l0")) + Store(r1lo, out.Field("l1")) + Store(r2lo, out.Field("l2")) + Store(r3lo, out.Field("l3")) + Store(r4lo, out.Field("l4")) + + RET() +} + +func feMul() { + TEXT("feMul", NOSPLIT, "func(out, a, b *Element)") + Doc("feMul sets out = a * b. It works like feMulGeneric.") + Pragma("noescape") + + a := Dereference(Param("a")) + a0 := namedComponent{a.Field("l0"), "a0"} + a1 := namedComponent{a.Field("l1"), "a1"} + a2 := namedComponent{a.Field("l2"), "a2"} + a3 := namedComponent{a.Field("l3"), "a3"} + a4 := namedComponent{a.Field("l4"), "a4"} + + b := Dereference(Param("b")) + b0 := namedComponent{b.Field("l0"), "b0"} + b1 := namedComponent{b.Field("l1"), "b1"} + b2 := namedComponent{b.Field("l2"), "b2"} + b3 := namedComponent{b.Field("l3"), "b3"} + b4 := namedComponent{b.Field("l4"), "b4"} + + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + r0 := uint128{"r0", GP64(), GP64()} + mul64(r0, 1, a0, b0) + addMul64(r0, 19, a1, b4) + addMul64(r0, 19, a2, b3) + addMul64(r0, 19, a3, b2) + addMul64(r0, 19, a4, b1) + + // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) + r1 := uint128{"r1", GP64(), GP64()} + mul64(r1, 1, a0, b1) + addMul64(r1, 1, a1, b0) + addMul64(r1, 19, a2, b4) + addMul64(r1, 19, a3, b3) + addMul64(r1, 19, a4, b2) + + // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) + r2 := uint128{"r2", GP64(), GP64()} + mul64(r2, 1, a0, b2) + addMul64(r2, 1, a1, b1) + addMul64(r2, 1, a2, b0) + addMul64(r2, 19, a3, b4) + addMul64(r2, 19, a4, b3) + + // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 + r3 := uint128{"r3", GP64(), GP64()} + mul64(r3, 1, a0, b3) + addMul64(r3, 1, a1, b2) + addMul64(r3, 1, a2, b1) + addMul64(r3, 1, a3, b0) + addMul64(r3, 19, a4, b4) + + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + r4 := uint128{"r4", GP64(), GP64()} + mul64(r4, 1, a0, b4) + addMul64(r4, 1, a1, b3) + addMul64(r4, 1, a2, b2) + addMul64(r4, 1, a3, b1) + addMul64(r4, 1, a4, b0) + + Comment("First reduction chain") + maskLow51Bits := GP64() + MOVQ(Imm((1<<51)-1), maskLow51Bits) + c0, r0lo := shiftRightBy51(&r0) + c1, r1lo := shiftRightBy51(&r1) + c2, r2lo := shiftRightBy51(&r2) + c3, r3lo := shiftRightBy51(&r3) + c4, r4lo := shiftRightBy51(&r4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Second reduction chain (carryPropagate)") + // c0 = r0 >> 51 + MOVQ(r0lo, c0) + SHRQ(Imm(51), c0) + // c1 = r1 >> 51 + MOVQ(r1lo, c1) + SHRQ(Imm(51), c1) + // c2 = r2 >> 51 + MOVQ(r2lo, c2) + SHRQ(Imm(51), c2) + // c3 = r3 >> 51 + MOVQ(r3lo, c3) + SHRQ(Imm(51), c3) + // c4 = r4 >> 51 + MOVQ(r4lo, c4) + SHRQ(Imm(51), c4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Store output") + out := Dereference(Param("out")) + Store(r0lo, out.Field("l0")) + Store(r1lo, out.Field("l1")) + Store(r2lo, out.Field("l2")) + Store(r3lo, out.Field("l3")) + Store(r4lo, out.Field("l4")) + + RET() +} + +// mul64 sets r to i * aX * bX. +func mul64(r uint128, i int, aX, bX namedComponent) { + switch i { + case 1: + Comment(fmt.Sprintf("%s = %s×%s", r, aX, bX)) + Load(aX, RAX) + case 2: + Comment(fmt.Sprintf("%s = 2×%s×%s", r, aX, bX)) + Load(aX, RAX) + SHLQ(Imm(1), RAX) + default: + panic("unsupported i value") + } + MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX + MOVQ(RAX, r.lo) + MOVQ(RDX, r.hi) +} + +// addMul64 sets r to r + i * aX * bX. +func addMul64(r uint128, i uint64, aX, bX namedComponent) { + switch i { + case 1: + Comment(fmt.Sprintf("%s += %s×%s", r, aX, bX)) + Load(aX, RAX) + default: + Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX)) + IMUL3Q(Imm(i), Load(aX, GP64()), RAX) + } + MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX + ADDQ(RAX, r.lo) + ADCQ(RDX, r.hi) +} + +// shiftRightBy51 returns r >> 51 and r.lo. +// +// After this function is called, the uint128 may not be used anymore. +func shiftRightBy51(r *uint128) (out, lo GPVirtual) { + out = r.hi + lo = r.lo + SHLQ(Imm(64-51), r.lo, r.hi) + r.lo, r.hi = nil, nil // make sure the uint128 is unusable + return +} + +// maskAndAdd sets r = r&mask + c*i. +func maskAndAdd(r, mask, c GPVirtual, i uint64) { + ANDQ(mask, r) + if i != 1 { + IMUL3Q(Imm(i), c, c) + } + ADDQ(c, r) +} + +func mustAddr(c Component) Op { + b, err := c.Resolve() + if err != nil { + panic(err) + } + return b.Addr +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/go.mod b/go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/go.mod new file mode 100644 index 0000000..b79d9f0 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/go.mod @@ -0,0 +1,12 @@ +module go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/edwards25519/field/_asm + +go 1.19 + +require github.com/mmcloughlin/avo v0.4.0 + +require ( + golang.org/x/mod v0.4.2 // indirect + golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 // indirect + golang.org/x/tools v0.1.7 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect +) diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/go.sum b/go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/go.sum new file mode 100644 index 0000000..40c7a0b --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/_asm/go.sum @@ -0,0 +1,32 @@ +github.com/mmcloughlin/avo v0.4.0 h1:jeHDRktVD+578ULxWpQHkilor6pkdLF7u7EiTzDbfcU= +github.com/mmcloughlin/avo v0.4.0/go.mod h1:RW9BfYA3TgO9uCdNrKU2h6J8cPD8ZLznvfgHAeszb1s= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 h1:giLT+HuUP/gXYrG2Plg9WTjj4qhfgaW424ZIFog3rlk= +golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/fe.go b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe.go new file mode 100644 index 0000000..821775c --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe.go @@ -0,0 +1,423 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package field implements fast arithmetic modulo 2^255-19. +package field + +import ( + "errors" + "math/bits" + + "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/edwards25519/byteorder" + "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/edwards25519/subtle" +) + +// Element represents an element of the field GF(2^255-19). Note that this +// is not a cryptographically secure group, and should only be used to interact +// with edwards25519.Point coordinates. +// +// This type works similarly to math/big.Int, and all arguments and receivers +// are allowed to alias. +// +// The zero value is a valid zero element. +type Element struct { + // An element t represents the integer + // t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204 + // + // Between operations, all limbs are expected to be lower than 2^52. + l0 uint64 + l1 uint64 + l2 uint64 + l3 uint64 + l4 uint64 +} + +const maskLow51Bits uint64 = (1 << 51) - 1 + +var feZero = &Element{0, 0, 0, 0, 0} + +// Zero sets v = 0, and returns v. +func (v *Element) Zero() *Element { + *v = *feZero + return v +} + +var feOne = &Element{1, 0, 0, 0, 0} + +// One sets v = 1, and returns v. +func (v *Element) One() *Element { + *v = *feOne + return v +} + +// reduce reduces v modulo 2^255 - 19 and returns it. +func (v *Element) reduce() *Element { + v.carryPropagate() + + // After the light reduction we now have a field element representation + // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. + + // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, + // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. + c := (v.l0 + 19) >> 51 + c = (v.l1 + c) >> 51 + c = (v.l2 + c) >> 51 + c = (v.l3 + c) >> 51 + c = (v.l4 + c) >> 51 + + // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's + // effectively applying the reduction identity to the carry. + v.l0 += 19 * c + + v.l1 += v.l0 >> 51 + v.l0 = v.l0 & maskLow51Bits + v.l2 += v.l1 >> 51 + v.l1 = v.l1 & maskLow51Bits + v.l3 += v.l2 >> 51 + v.l2 = v.l2 & maskLow51Bits + v.l4 += v.l3 >> 51 + v.l3 = v.l3 & maskLow51Bits + // no additional carry + v.l4 = v.l4 & maskLow51Bits + + return v +} + +// Add sets v = a + b, and returns v. +func (v *Element) Add(a, b *Element) *Element { + v.l0 = a.l0 + b.l0 + v.l1 = a.l1 + b.l1 + v.l2 = a.l2 + b.l2 + v.l3 = a.l3 + b.l3 + v.l4 = a.l4 + b.l4 + // Using the generic implementation here is actually faster than the + // assembly. Probably because the body of this function is so simple that + // the compiler can figure out better optimizations by inlining the carry + // propagation. + return v.carryPropagateGeneric() +} + +// Subtract sets v = a - b, and returns v. +func (v *Element) Subtract(a, b *Element) *Element { + // We first add 2 * p, to guarantee the subtraction won't underflow, and + // then subtract b (which can be up to 2^255 + 2^13 * 19). + v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0 + v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1 + v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2 + v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3 + v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 + return v.carryPropagate() +} + +// Negate sets v = -a, and returns v. +func (v *Element) Negate(a *Element) *Element { + return v.Subtract(feZero, a) +} + +// Invert sets v = 1/z mod p, and returns v. +// +// If z == 0, Invert returns v = 0. +func (v *Element) Invert(z *Element) *Element { + // Inversion is implemented as exponentiation with exponent p − 2. It uses the + // same sequence of 255 squarings and 11 multiplications as [Curve25519]. + var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element + + z2.Square(z) // 2 + t.Square(&z2) // 4 + t.Square(&t) // 8 + z9.Multiply(&t, z) // 9 + z11.Multiply(&z9, &z2) // 11 + t.Square(&z11) // 22 + z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 + + t.Square(&z2_5_0) // 2^6 - 2^1 + for i := 0; i < 4; i++ { + t.Square(&t) // 2^10 - 2^5 + } + z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 + + t.Square(&z2_10_0) // 2^11 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^20 - 2^10 + } + z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 + + t.Square(&z2_20_0) // 2^21 - 2^1 + for i := 0; i < 19; i++ { + t.Square(&t) // 2^40 - 2^20 + } + t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 + + t.Square(&t) // 2^41 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^50 - 2^10 + } + z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 + + t.Square(&z2_50_0) // 2^51 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^100 - 2^50 + } + z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 + + t.Square(&z2_100_0) // 2^101 - 2^1 + for i := 0; i < 99; i++ { + t.Square(&t) // 2^200 - 2^100 + } + t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 + + t.Square(&t) // 2^201 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^250 - 2^50 + } + t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 + + t.Square(&t) // 2^251 - 2^1 + t.Square(&t) // 2^252 - 2^2 + t.Square(&t) // 2^253 - 2^3 + t.Square(&t) // 2^254 - 2^4 + t.Square(&t) // 2^255 - 2^5 + + return v.Multiply(&t, &z11) // 2^255 - 21 +} + +// Set sets v = a, and returns v. +func (v *Element) Set(a *Element) *Element { + *v = *a + return v +} + +// SetBytes sets v to x, where x is a 32-byte little-endian encoding. If x is +// not of the right length, SetBytes returns nil and an error, and the +// receiver is unchanged. +// +// Consistent with RFC 7748, the most significant bit (the high bit of the +// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) +// are accepted. Note that this is laxer than specified by RFC 8032, but +// consistent with most Ed25519 implementations. +func (v *Element) SetBytes(x []byte) (*Element, error) { + if len(x) != 32 { + return nil, errors.New("edwards25519: invalid field element input size") + } + + // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). + v.l0 = byteorder.LEUint64(x[0:8]) + v.l0 &= maskLow51Bits + // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). + v.l1 = byteorder.LEUint64(x[6:14]) >> 3 + v.l1 &= maskLow51Bits + // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). + v.l2 = byteorder.LEUint64(x[12:20]) >> 6 + v.l2 &= maskLow51Bits + // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). + v.l3 = byteorder.LEUint64(x[19:27]) >> 1 + v.l3 &= maskLow51Bits + // Bits 204:255 (bytes 24:32, bits 192:256, shift 12, mask 51). + // Note: not bytes 25:33, shift 4, to avoid overread. + v.l4 = byteorder.LEUint64(x[24:32]) >> 12 + v.l4 &= maskLow51Bits + + return v, nil +} + +// Bytes returns the canonical 32-byte little-endian encoding of v. +func (v *Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [32]byte + return v.bytes(&out) +} + +func (v *Element) bytes(out *[32]byte) []byte { + t := *v + t.reduce() + + var buf [8]byte + for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { + bitsOffset := i * 51 + byteorder.LEPutUint64(buf[:], l<= len(out) { + break + } + out[off] |= bb + } + } + + return out[:] +} + +// Equal returns 1 if v and u are equal, and 0 otherwise. +func (v *Element) Equal(u *Element) int { + sa, sv := u.Bytes(), v.Bytes() + return subtle.ConstantTimeCompare(sa, sv) +} + +// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise. +func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) } + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *Element) Select(a, b *Element, cond int) *Element { + m := mask64Bits(cond) + v.l0 = (m & a.l0) | (^m & b.l0) + v.l1 = (m & a.l1) | (^m & b.l1) + v.l2 = (m & a.l2) | (^m & b.l2) + v.l3 = (m & a.l3) | (^m & b.l3) + v.l4 = (m & a.l4) | (^m & b.l4) + return v +} + +// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v. +func (v *Element) Swap(u *Element, cond int) { + m := mask64Bits(cond) + t := m & (v.l0 ^ u.l0) + v.l0 ^= t + u.l0 ^= t + t = m & (v.l1 ^ u.l1) + v.l1 ^= t + u.l1 ^= t + t = m & (v.l2 ^ u.l2) + v.l2 ^= t + u.l2 ^= t + t = m & (v.l3 ^ u.l3) + v.l3 ^= t + u.l3 ^= t + t = m & (v.l4 ^ u.l4) + v.l4 ^= t + u.l4 ^= t +} + +// IsNegative returns 1 if v is negative, and 0 otherwise. +func (v *Element) IsNegative() int { + return int(v.Bytes()[0] & 1) +} + +// Absolute sets v to |u|, and returns v. +func (v *Element) Absolute(u *Element) *Element { + return v.Select(new(Element).Negate(u), u, u.IsNegative()) +} + +// Multiply sets v = x * y, and returns v. +func (v *Element) Multiply(x, y *Element) *Element { + feMul(v, x, y) + return v +} + +// Square sets v = x * x, and returns v. +func (v *Element) Square(x *Element) *Element { + feSquare(v, x) + return v +} + +// Mult32 sets v = x * y, and returns v. +func (v *Element) Mult32(x *Element, y uint32) *Element { + x0lo, x0hi := mul51(x.l0, y) + x1lo, x1hi := mul51(x.l1, y) + x2lo, x2hi := mul51(x.l2, y) + x3lo, x3hi := mul51(x.l3, y) + x4lo, x4hi := mul51(x.l4, y) + v.l0 = x0lo + 19*x4hi // carried over per the reduction identity + v.l1 = x1lo + x0hi + v.l2 = x2lo + x1hi + v.l3 = x3lo + x2hi + v.l4 = x4lo + x3hi + // The hi portions are going to be only 32 bits, plus any previous excess, + // so we can skip the carry propagation. + return v +} + +// mul51 returns lo + hi * 2⁵¹ = a * b. +func mul51(a uint64, b uint32) (lo, hi uint64) { + mh, ml := bits.Mul64(a, uint64(b)) + lo = ml & maskLow51Bits + hi = (mh << 13) | (ml >> 51) + return +} + +// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3. +func (v *Element) Pow22523(x *Element) *Element { + var t0, t1, t2 Element + + t0.Square(x) // x^2 + t1.Square(&t0) // x^4 + t1.Square(&t1) // x^8 + t1.Multiply(x, &t1) // x^9 + t0.Multiply(&t0, &t1) // x^11 + t0.Square(&t0) // x^22 + t0.Multiply(&t1, &t0) // x^31 + t1.Square(&t0) // x^62 + for i := 1; i < 5; i++ { // x^992 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1 + t1.Square(&t0) // 2^11 - 2 + for i := 1; i < 10; i++ { // 2^20 - 2^10 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^20 - 1 + t2.Square(&t1) // 2^21 - 2 + for i := 1; i < 20; i++ { // 2^40 - 2^20 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^40 - 1 + t1.Square(&t1) // 2^41 - 2 + for i := 1; i < 10; i++ { // 2^50 - 2^10 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^50 - 1 + t1.Square(&t0) // 2^51 - 2 + for i := 1; i < 50; i++ { // 2^100 - 2^50 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^100 - 1 + t2.Square(&t1) // 2^101 - 2 + for i := 1; i < 100; i++ { // 2^200 - 2^100 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^200 - 1 + t1.Square(&t1) // 2^201 - 2 + for i := 1; i < 50; i++ { // 2^250 - 2^50 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^250 - 1 + t0.Square(&t0) // 2^251 - 2 + t0.Square(&t0) // 2^252 - 4 + return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3) +} + +// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion. +var sqrtM1 = &Element{ + 1718705420411056, 234908883556509, + 2233514472574048, 2117202627021982, 765476049583133, +} + +// SqrtRatio sets r to the non-negative square root of the ratio of u and v. +// +// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio +// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, +// and returns r and 0. +func (r *Element) SqrtRatio(u, v *Element) (R *Element, wasSquare int) { + t0 := new(Element) + + // r = (u * v3) * (u * v7)^((p-5)/8) + v2 := new(Element).Square(v) + uv3 := new(Element).Multiply(u, t0.Multiply(v2, v)) + uv7 := new(Element).Multiply(uv3, t0.Square(v2)) + rr := new(Element).Multiply(uv3, t0.Pow22523(uv7)) + + check := new(Element).Multiply(v, t0.Square(rr)) // check = v * r^2 + + uNeg := new(Element).Negate(u) + correctSignSqrt := check.Equal(u) + flippedSignSqrt := check.Equal(uNeg) + flippedSignSqrtI := check.Equal(t0.Multiply(uNeg, sqrtM1)) + + rPrime := new(Element).Multiply(rr, sqrtM1) // r_prime = SQRT_M1 * r + // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) + rr.Select(rPrime, rr, flippedSignSqrt|flippedSignSqrtI) + + r.Absolute(rr) // Choose the nonnegative square root. + return r, correctSignSqrt | flippedSignSqrt +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64.go b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64.go new file mode 100644 index 0000000..d45675a --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64.go @@ -0,0 +1,15 @@ +// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. + +//go:build !purego + +package field + +// feMul sets out = a * b. It works like feMulGeneric. +// +//go:noescape +func feMul(out *Element, a *Element, b *Element) + +// feSquare sets out = a * a. It works like feSquareGeneric. +// +//go:noescape +func feSquare(out *Element, a *Element) diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64.s b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64.s new file mode 100644 index 0000000..eaf2751 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64.s @@ -0,0 +1,378 @@ +// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. + +//go:build !purego + +#include "textflag.h" + +// func feMul(out *Element, a *Element, b *Element) +TEXT ·feMul(SB), NOSPLIT, $0-24 + MOVQ a+8(FP), CX + MOVQ b+16(FP), BX + + // r0 = a0×b0 + MOVQ (CX), AX + MULQ (BX) + MOVQ AX, DI + MOVQ DX, SI + + // r0 += 19×a1×b4 + MOVQ 8(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a2×b3 + MOVQ 16(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a3×b2 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 16(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a4×b1 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 8(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r1 = a0×b1 + MOVQ (CX), AX + MULQ 8(BX) + MOVQ AX, R9 + MOVQ DX, R8 + + // r1 += a1×b0 + MOVQ 8(CX), AX + MULQ (BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a2×b4 + MOVQ 16(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a3×b3 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a4×b2 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 16(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r2 = a0×b2 + MOVQ (CX), AX + MULQ 16(BX) + MOVQ AX, R11 + MOVQ DX, R10 + + // r2 += a1×b1 + MOVQ 8(CX), AX + MULQ 8(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += a2×b0 + MOVQ 16(CX), AX + MULQ (BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += 19×a3×b4 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += 19×a4×b3 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r3 = a0×b3 + MOVQ (CX), AX + MULQ 24(BX) + MOVQ AX, R13 + MOVQ DX, R12 + + // r3 += a1×b2 + MOVQ 8(CX), AX + MULQ 16(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += a2×b1 + MOVQ 16(CX), AX + MULQ 8(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += a3×b0 + MOVQ 24(CX), AX + MULQ (BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += 19×a4×b4 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r4 = a0×b4 + MOVQ (CX), AX + MULQ 32(BX) + MOVQ AX, R15 + MOVQ DX, R14 + + // r4 += a1×b3 + MOVQ 8(CX), AX + MULQ 24(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a2×b2 + MOVQ 16(CX), AX + MULQ 16(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a3×b1 + MOVQ 24(CX), AX + MULQ 8(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a4×b0 + MOVQ 32(CX), AX + MULQ (BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // First reduction chain + MOVQ $0x0007ffffffffffff, AX + SHLQ $0x0d, DI, SI + SHLQ $0x0d, R9, R8 + SHLQ $0x0d, R11, R10 + SHLQ $0x0d, R13, R12 + SHLQ $0x0d, R15, R14 + ANDQ AX, DI + IMUL3Q $0x13, R14, R14 + ADDQ R14, DI + ANDQ AX, R9 + ADDQ SI, R9 + ANDQ AX, R11 + ADDQ R8, R11 + ANDQ AX, R13 + ADDQ R10, R13 + ANDQ AX, R15 + ADDQ R12, R15 + + // Second reduction chain (carryPropagate) + MOVQ DI, SI + SHRQ $0x33, SI + MOVQ R9, R8 + SHRQ $0x33, R8 + MOVQ R11, R10 + SHRQ $0x33, R10 + MOVQ R13, R12 + SHRQ $0x33, R12 + MOVQ R15, R14 + SHRQ $0x33, R14 + ANDQ AX, DI + IMUL3Q $0x13, R14, R14 + ADDQ R14, DI + ANDQ AX, R9 + ADDQ SI, R9 + ANDQ AX, R11 + ADDQ R8, R11 + ANDQ AX, R13 + ADDQ R10, R13 + ANDQ AX, R15 + ADDQ R12, R15 + + // Store output + MOVQ out+0(FP), AX + MOVQ DI, (AX) + MOVQ R9, 8(AX) + MOVQ R11, 16(AX) + MOVQ R13, 24(AX) + MOVQ R15, 32(AX) + RET + +// func feSquare(out *Element, a *Element) +TEXT ·feSquare(SB), NOSPLIT, $0-16 + MOVQ a+8(FP), CX + + // r0 = l0×l0 + MOVQ (CX), AX + MULQ (CX) + MOVQ AX, SI + MOVQ DX, BX + + // r0 += 38×l1×l4 + MOVQ 8(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, SI + ADCQ DX, BX + + // r0 += 38×l2×l3 + MOVQ 16(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 24(CX) + ADDQ AX, SI + ADCQ DX, BX + + // r1 = 2×l0×l1 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 8(CX) + MOVQ AX, R8 + MOVQ DX, DI + + // r1 += 38×l2×l4 + MOVQ 16(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, R8 + ADCQ DX, DI + + // r1 += 19×l3×l3 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(CX) + ADDQ AX, R8 + ADCQ DX, DI + + // r2 = 2×l0×l2 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 16(CX) + MOVQ AX, R10 + MOVQ DX, R9 + + // r2 += l1×l1 + MOVQ 8(CX), AX + MULQ 8(CX) + ADDQ AX, R10 + ADCQ DX, R9 + + // r2 += 38×l3×l4 + MOVQ 24(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, R10 + ADCQ DX, R9 + + // r3 = 2×l0×l3 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 24(CX) + MOVQ AX, R12 + MOVQ DX, R11 + + // r3 += 2×l1×l2 + MOVQ 8(CX), AX + IMUL3Q $0x02, AX, AX + MULQ 16(CX) + ADDQ AX, R12 + ADCQ DX, R11 + + // r3 += 19×l4×l4 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(CX) + ADDQ AX, R12 + ADCQ DX, R11 + + // r4 = 2×l0×l4 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 32(CX) + MOVQ AX, R14 + MOVQ DX, R13 + + // r4 += 2×l1×l3 + MOVQ 8(CX), AX + IMUL3Q $0x02, AX, AX + MULQ 24(CX) + ADDQ AX, R14 + ADCQ DX, R13 + + // r4 += l2×l2 + MOVQ 16(CX), AX + MULQ 16(CX) + ADDQ AX, R14 + ADCQ DX, R13 + + // First reduction chain + MOVQ $0x0007ffffffffffff, AX + SHLQ $0x0d, SI, BX + SHLQ $0x0d, R8, DI + SHLQ $0x0d, R10, R9 + SHLQ $0x0d, R12, R11 + SHLQ $0x0d, R14, R13 + ANDQ AX, SI + IMUL3Q $0x13, R13, R13 + ADDQ R13, SI + ANDQ AX, R8 + ADDQ BX, R8 + ANDQ AX, R10 + ADDQ DI, R10 + ANDQ AX, R12 + ADDQ R9, R12 + ANDQ AX, R14 + ADDQ R11, R14 + + // Second reduction chain (carryPropagate) + MOVQ SI, BX + SHRQ $0x33, BX + MOVQ R8, DI + SHRQ $0x33, DI + MOVQ R10, R9 + SHRQ $0x33, R9 + MOVQ R12, R11 + SHRQ $0x33, R11 + MOVQ R14, R13 + SHRQ $0x33, R13 + ANDQ AX, SI + IMUL3Q $0x13, R13, R13 + ADDQ R13, SI + ANDQ AX, R8 + ADDQ BX, R8 + ANDQ AX, R10 + ADDQ DI, R10 + ANDQ AX, R12 + ADDQ R9, R12 + ANDQ AX, R14 + ADDQ R11, R14 + + // Store output + MOVQ out+0(FP), AX + MOVQ SI, (AX) + MOVQ R8, 8(AX) + MOVQ R10, 16(AX) + MOVQ R12, 24(AX) + MOVQ R14, 32(AX) + RET diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64_noasm.go b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64_noasm.go new file mode 100644 index 0000000..d12b017 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_amd64_noasm.go @@ -0,0 +1,11 @@ +// Copyright (c) 2019 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 !amd64 || purego + +package field + +func feMul(v, x, y *Element) { feMulGeneric(v, x, y) } + +func feSquare(v, x *Element) { feSquareGeneric(v, x) } diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64.go b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64.go new file mode 100644 index 0000000..5a1b958 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64.go @@ -0,0 +1,15 @@ +// Copyright (c) 2020 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 !purego + +package field + +//go:noescape +func carryPropagate(v *Element) + +func (v *Element) carryPropagate() *Element { + carryPropagate(v) + return v +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64.s b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64.s new file mode 100644 index 0000000..1b0528c --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64.s @@ -0,0 +1,42 @@ +// Copyright (c) 2020 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 !purego + +#include "textflag.h" + +// carryPropagate works exactly like carryPropagateGeneric and uses the +// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but +// avoids loading R0-R4 twice and uses LDP and STP. +// +// See https://golang.org/issues/43145 for the main compiler issue. +// +// func carryPropagate(v *Element) +TEXT ·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8 + MOVD v+0(FP), R20 + + LDP 0(R20), (R0, R1) + LDP 16(R20), (R2, R3) + MOVD 32(R20), R4 + + AND $0x7ffffffffffff, R0, R10 + AND $0x7ffffffffffff, R1, R11 + AND $0x7ffffffffffff, R2, R12 + AND $0x7ffffffffffff, R3, R13 + AND $0x7ffffffffffff, R4, R14 + + ADD R0>>51, R11, R11 + ADD R1>>51, R12, R12 + ADD R2>>51, R13, R13 + ADD R3>>51, R14, R14 + // R4>>51 * 19 + R10 -> R10 + LSR $51, R4, R21 + MOVD $19, R22 + MADD R22, R10, R21, R10 + + STP (R10, R11), 0(R20) + STP (R12, R13), 16(R20) + MOVD R14, 32(R20) + + RET diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64_noasm.go b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64_noasm.go new file mode 100644 index 0000000..a3c2e55 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_arm64_noasm.go @@ -0,0 +1,11 @@ +// Copyright (c) 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 !arm64 || purego + +package field + +func (v *Element) carryPropagate() *Element { + return v.carryPropagateGeneric() +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_generic.go b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_generic.go new file mode 100644 index 0000000..4272bf7 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/field/fe_generic.go @@ -0,0 +1,266 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import "math/bits" + +// uint128 holds a 128-bit number as two 64-bit limbs, for use with the +// bits.Mul64 and bits.Add64 intrinsics. +type uint128 struct { + lo, hi uint64 +} + +// mul64 returns a * b. +func mul64(a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + return uint128{lo, hi} +} + +// addMul64 returns v + a * b. +func addMul64(v uint128, a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + lo, c := bits.Add64(lo, v.lo, 0) + hi, _ = bits.Add64(hi, v.hi, c) + return uint128{lo, hi} +} + +// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. +func shiftRightBy51(a uint128) uint64 { + return (a.hi << (64 - 51)) | (a.lo >> 51) +} + +func feMulGeneric(v, a, b *Element) { + a0 := a.l0 + a1 := a.l1 + a2 := a.l2 + a3 := a.l3 + a4 := a.l4 + + b0 := b.l0 + b1 := b.l1 + b2 := b.l2 + b3 := b.l3 + b4 := b.l4 + + // Limb multiplication works like pen-and-paper columnar multiplication, but + // with 51-bit limbs instead of digits. + // + // a4 a3 a2 a1 a0 x + // b4 b3 b2 b1 b0 = + // ------------------------ + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a4b1 a3b1 a2b1 a1b1 a0b1 + + // a4b2 a3b2 a2b2 a1b2 a0b2 + + // a4b3 a3b3 a2b3 a1b3 a0b3 + + // a4b4 a3b4 a2b4 a1b4 a0b4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to + // reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5, + // r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc. + // + // Reduction can be carried out simultaneously to multiplication. For + // example, we do not compute r5: whenever the result of a multiplication + // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0. + // + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a3b1 a2b1 a1b1 a0b1 19×a4b1 + + // a2b2 a1b2 a0b2 19×a4b2 19×a3b2 + + // a1b3 a0b3 19×a4b3 19×a3b3 19×a2b3 + + // a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // Finally we add up the columns into wide, overlapping limbs. + + a1_19 := a1 * 19 + a2_19 := a2 * 19 + a3_19 := a3 * 19 + a4_19 := a4 * 19 + + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + r0 := mul64(a0, b0) + r0 = addMul64(r0, a1_19, b4) + r0 = addMul64(r0, a2_19, b3) + r0 = addMul64(r0, a3_19, b2) + r0 = addMul64(r0, a4_19, b1) + + // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) + r1 := mul64(a0, b1) + r1 = addMul64(r1, a1, b0) + r1 = addMul64(r1, a2_19, b4) + r1 = addMul64(r1, a3_19, b3) + r1 = addMul64(r1, a4_19, b2) + + // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) + r2 := mul64(a0, b2) + r2 = addMul64(r2, a1, b1) + r2 = addMul64(r2, a2, b0) + r2 = addMul64(r2, a3_19, b4) + r2 = addMul64(r2, a4_19, b3) + + // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 + r3 := mul64(a0, b3) + r3 = addMul64(r3, a1, b2) + r3 = addMul64(r3, a2, b1) + r3 = addMul64(r3, a3, b0) + r3 = addMul64(r3, a4_19, b4) + + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + r4 := mul64(a0, b4) + r4 = addMul64(r4, a1, b3) + r4 = addMul64(r4, a2, b2) + r4 = addMul64(r4, a3, b1) + r4 = addMul64(r4, a4, b0) + + // After the multiplication, we need to reduce (carry) the five coefficients + // to obtain a result with limbs that are at most slightly larger than 2⁵¹, + // to respect the Element invariant. + // + // Overall, the reduction works the same as carryPropagate, except with + // wider inputs: we take the carry for each coefficient by shifting it right + // by 51, and add it to the limb above it. The top carry is multiplied by 19 + // according to the reduction identity and added to the lowest limb. + // + // The largest coefficient (r0) will be at most 111 bits, which guarantees + // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64. + // + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + // r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²) + // r0 < (1 + 19 × 4) × 2⁵² × 2⁵² + // r0 < 2⁷ × 2⁵² × 2⁵² + // r0 < 2¹¹¹ + // + // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most + // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and + // allows us to easily apply the reduction identity. + // + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + // r4 < 5 × 2⁵² × 2⁵² + // r4 < 2¹⁰⁷ + // + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + // Now all coefficients fit into 64-bit registers but are still too large to + // be passed around as an Element. We therefore do one last carry chain, + // where the carries will be small enough to fit in the wiggle room above 2⁵¹. + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +func feSquareGeneric(v, a *Element) { + l0 := a.l0 + l1 := a.l1 + l2 := a.l2 + l3 := a.l3 + l4 := a.l4 + + // Squaring works precisely like multiplication above, but thanks to its + // symmetry we get to group a few terms together. + // + // l4 l3 l2 l1 l0 x + // l4 l3 l2 l1 l0 = + // ------------------------ + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l4l1 l3l1 l2l1 l1l1 l0l1 + + // l4l2 l3l2 l2l2 l1l2 l0l2 + + // l4l3 l3l3 l2l3 l1l3 l0l3 + + // l4l4 l3l4 l2l4 l1l4 l0l4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l3l1 l2l1 l1l1 l0l1 19×l4l1 + + // l2l2 l1l2 l0l2 19×l4l2 19×l3l2 + + // l1l3 l0l3 19×l4l3 19×l3l3 19×l2l3 + + // l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with + // only three Mul64 and four Add64, instead of five and eight. + + l0_2 := l0 * 2 + l1_2 := l1 * 2 + + l1_38 := l1 * 38 + l2_38 := l2 * 38 + l3_38 := l3 * 38 + + l3_19 := l3 * 19 + l4_19 := l4 * 19 + + // r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3) + r0 := mul64(l0, l0) + r0 = addMul64(r0, l1_38, l4) + r0 = addMul64(r0, l2_38, l3) + + // r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 + r1 := mul64(l0_2, l1) + r1 = addMul64(r1, l2_38, l4) + r1 = addMul64(r1, l3_19, l3) + + // r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4 + r2 := mul64(l0_2, l2) + r2 = addMul64(r2, l1, l1) + r2 = addMul64(r2, l3_38, l4) + + // r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 + r3 := mul64(l0_2, l3) + r3 = addMul64(r3, l1_2, l2) + r3 = addMul64(r3, l4_19, l4) + + // r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2 + r4 := mul64(l0_2, l4) + r4 = addMul64(r4, l1_2, l3) + r4 = addMul64(r4, l2, l2) + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +// carryPropagateGeneric brings the limbs below 52 bits by applying the reduction +// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. +func (v *Element) carryPropagateGeneric() *Element { + c0 := v.l0 >> 51 + c1 := v.l1 >> 51 + c2 := v.l2 >> 51 + c3 := v.l3 >> 51 + c4 := v.l4 >> 51 + + // c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and + // the final l0 will be at most 52 bits. Similarly for the rest. + v.l0 = v.l0&maskLow51Bits + c4*19 + v.l1 = v.l1&maskLow51Bits + c0 + v.l2 = v.l2&maskLow51Bits + c1 + v.l3 = v.l3&maskLow51Bits + c2 + v.l4 = v.l4&maskLow51Bits + c3 + + return v +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/scalar.go b/go/cm/sign/ed25519-blake2b/edwards25519/scalar.go new file mode 100644 index 0000000..07b90aa --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/scalar.go @@ -0,0 +1,349 @@ +// Copyright (c) 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "errors" + + "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/edwards25519/byteorder" +) + +// A Scalar is an integer modulo +// +// l = 2^252 + 27742317777372353535851937790883648493 +// +// which is the prime order of the edwards25519 group. +// +// This type works similarly to math/big.Int, and all arguments and +// receivers are allowed to alias. +// +// The zero value is a valid zero element. +type Scalar struct { + // s is the scalar in the Montgomery domain, in the format of the + // fiat-crypto implementation. + s fiatScalarMontgomeryDomainFieldElement +} + +// The field implementation in scalar_fiat.go is generated by the fiat-crypto +// project (https://github.com/mit-plv/fiat-crypto) at version v0.0.9 (23d2dbc) +// from a formally verified model. +// +// 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. +// + +// NewScalar returns a new zero Scalar. +func NewScalar() *Scalar { + return &Scalar{} +} + +// MultiplyAdd sets s = x * y + z mod l, and returns s. It is equivalent to +// using Multiply and then Add. +func (s *Scalar) MultiplyAdd(x, y, z *Scalar) *Scalar { + // Make a copy of z in case it aliases s. + zCopy := new(Scalar).Set(z) + return s.Multiply(x, y).Add(s, zCopy) +} + +// Add sets s = x + y mod l, and returns s. +func (s *Scalar) Add(x, y *Scalar) *Scalar { + // s = 1 * x + y mod l + fiatScalarAdd(&s.s, &x.s, &y.s) + return s +} + +// Subtract sets s = x - y mod l, and returns s. +func (s *Scalar) Subtract(x, y *Scalar) *Scalar { + // s = -1 * y + x mod l + fiatScalarSub(&s.s, &x.s, &y.s) + return s +} + +// Negate sets s = -x mod l, and returns s. +func (s *Scalar) Negate(x *Scalar) *Scalar { + // s = -1 * x + 0 mod l + fiatScalarOpp(&s.s, &x.s) + return s +} + +// Multiply sets s = x * y mod l, and returns s. +func (s *Scalar) Multiply(x, y *Scalar) *Scalar { + // s = x * y + 0 mod l + fiatScalarMul(&s.s, &x.s, &y.s) + return s +} + +// Set sets s = x, and returns s. +func (s *Scalar) Set(x *Scalar) *Scalar { + *s = *x + return s +} + +// SetUniformBytes sets s = x mod l, where x is a 64-byte little-endian integer. +// If x is not of the right length, SetUniformBytes returns nil and an error, +// and the receiver is unchanged. +// +// SetUniformBytes can be used to set s to a uniformly distributed value given +// 64 uniformly distributed random bytes. +func (s *Scalar) SetUniformBytes(x []byte) (*Scalar, error) { + if len(x) != 64 { + return nil, errors.New("edwards25519: invalid SetUniformBytes input length") + } + + // We have a value x of 512 bits, but our fiatScalarFromBytes function + // expects an input lower than l, which is a little over 252 bits. + // + // Instead of writing a reduction function that operates on wider inputs, we + // can interpret x as the sum of three shorter values a, b, and c. + // + // x = a + b * 2^168 + c * 2^336 mod l + // + // We then precompute 2^168 and 2^336 modulo l, and perform the reduction + // with two multiplications and two additions. + + s.setShortBytes(x[:21]) + t := new(Scalar).setShortBytes(x[21:42]) + s.Add(s, t.Multiply(t, scalarTwo168)) + t.setShortBytes(x[42:]) + s.Add(s, t.Multiply(t, scalarTwo336)) + + return s, nil +} + +// scalarTwo168 and scalarTwo336 are 2^168 and 2^336 modulo l, encoded as a +// fiatScalarMontgomeryDomainFieldElement, which is a little-endian 4-limb value +// in the 2^256 Montgomery domain. +var scalarTwo168 = &Scalar{s: [4]uint64{ + 0x5b8ab432eac74798, 0x38afddd6de59d5d7, + 0xa2c131b399411b7c, 0x6329a7ed9ce5a30, +}} + +var scalarTwo336 = &Scalar{s: [4]uint64{ + 0xbd3d108e2b35ecc5, 0x5c3a3718bdf9c90b, + 0x63aa97a331b4f2ee, 0x3d217f5be65cb5c, +}} + +// setShortBytes sets s = x mod l, where x is a little-endian integer shorter +// than 32 bytes. +func (s *Scalar) setShortBytes(x []byte) *Scalar { + if len(x) >= 32 { + panic("edwards25519: internal error: setShortBytes called with a long string") + } + var buf [32]byte + copy(buf[:], x) + fiatScalarFromBytes((*[4]uint64)(&s.s), &buf) + fiatScalarToMontgomery(&s.s, (*fiatScalarNonMontgomeryDomainFieldElement)(&s.s)) + return s +} + +// SetCanonicalBytes sets s = x, where x is a 32-byte little-endian encoding of +// s, and returns s. If x is not a canonical encoding of s, SetCanonicalBytes +// returns nil and an error, and the receiver is unchanged. +func (s *Scalar) SetCanonicalBytes(x []byte) (*Scalar, error) { + if len(x) != 32 { + return nil, errors.New("invalid scalar length") + } + if !isReduced(x) { + return nil, errors.New("invalid scalar encoding") + } + + fiatScalarFromBytes((*[4]uint64)(&s.s), (*[32]byte)(x)) + fiatScalarToMontgomery(&s.s, (*fiatScalarNonMontgomeryDomainFieldElement)(&s.s)) + + return s, nil +} + +// scalarMinusOneBytes is l - 1 in little endian. +var scalarMinusOneBytes = [32]byte{236, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, 222, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16} + +// isReduced returns whether the given scalar in 32-byte little endian encoded +// form is reduced modulo l. +func isReduced(s []byte) bool { + if len(s) != 32 { + return false + } + + for i := len(s) - 1; i >= 0; i-- { + switch { + case s[i] > scalarMinusOneBytes[i]: + return false + case s[i] < scalarMinusOneBytes[i]: + return true + } + } + return true +} + +// SetBytesWithClamping applies the buffer pruning described in RFC 8032, +// Section 5.1.5 (also known as clamping) and sets s to the result. The input +// must be 32 bytes, and it is not modified. If x is not of the right length, +// SetBytesWithClamping returns nil and an error, and the receiver is unchanged. +// +// Note that since Scalar values are always reduced modulo the prime order of +// the curve, the resulting value will not preserve any of the cofactor-clearing +// properties that clamping is meant to provide. It will however work as +// expected as long as it is applied to points on the prime order subgroup, like +// in Ed25519. In fact, it is lost to history why RFC 8032 adopted the +// irrelevant RFC 7748 clamping, but it is now required for compatibility. +func (s *Scalar) SetBytesWithClamping(x []byte) (*Scalar, error) { + // The description above omits the purpose of the high bits of the clamping + // for brevity, but those are also lost to reductions, and are also + // irrelevant to edwards25519 as they protect against a specific + // implementation bug that was once observed in a generic Montgomery ladder. + if len(x) != 32 { + return nil, errors.New("edwards25519: invalid SetBytesWithClamping input length") + } + + // We need to use the wide reduction from SetUniformBytes, since clamping + // sets the 2^254 bit, making the value higher than the order. + var wideBytes [64]byte + copy(wideBytes[:], x[:]) + wideBytes[0] &= 248 + wideBytes[31] &= 63 + wideBytes[31] |= 64 + return s.SetUniformBytes(wideBytes[:]) +} + +// Bytes returns the canonical 32-byte little-endian encoding of s. +func (s *Scalar) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var encoded [32]byte + return s.bytes(&encoded) +} + +func (s *Scalar) bytes(out *[32]byte) []byte { + var ss fiatScalarNonMontgomeryDomainFieldElement + fiatScalarFromMontgomery(&ss, &s.s) + fiatScalarToBytes(out, (*[4]uint64)(&ss)) + return out[:] +} + +// Equal returns 1 if s and t are equal, and 0 otherwise. +func (s *Scalar) Equal(t *Scalar) int { + var diff fiatScalarMontgomeryDomainFieldElement + fiatScalarSub(&diff, &s.s, &t.s) + var nonzero uint64 + fiatScalarNonzero(&nonzero, (*[4]uint64)(&diff)) + nonzero |= nonzero >> 32 + nonzero |= nonzero >> 16 + nonzero |= nonzero >> 8 + nonzero |= nonzero >> 4 + nonzero |= nonzero >> 2 + nonzero |= nonzero >> 1 + return int(^nonzero) & 1 +} + +// nonAdjacentForm computes a width-w non-adjacent form for this scalar. +// +// w must be between 2 and 8, or nonAdjacentForm will panic. +func (s *Scalar) nonAdjacentForm(w uint) [256]int8 { + // This implementation is adapted from the one + // in curve25519-dalek and is documented there: + // https://github.com/dalek-cryptography/curve25519-dalek/blob/f630041af28e9a405255f98a8a93adca18e4315b/src/scalar.rs#L800-L871 + b := s.Bytes() + if b[31] > 127 { + panic("scalar has high bit set illegally") + } + if w < 2 { + panic("w must be at least 2 by the definition of NAF") + } else if w > 8 { + panic("NAF digits must fit in int8") + } + + var naf [256]int8 + var digits [5]uint64 + + for i := 0; i < 4; i++ { + digits[i] = byteorder.LEUint64(b[i*8:]) + } + + width := uint64(1 << w) + windowMask := uint64(width - 1) + + pos := uint(0) + carry := uint64(0) + for pos < 256 { + indexU64 := pos / 64 + indexBit := pos % 64 + var bitBuf uint64 + if indexBit < 64-w { + // This window's bits are contained in a single u64 + bitBuf = digits[indexU64] >> indexBit + } else { + // Combine the current 64 bits with bits from the next 64 + bitBuf = (digits[indexU64] >> indexBit) | (digits[1+indexU64] << (64 - indexBit)) + } + + // Add carry into the current window + window := carry + (bitBuf & windowMask) + + if window&1 == 0 { + // If the window value is even, preserve the carry and continue. + // Why is the carry preserved? + // If carry == 0 and window & 1 == 0, + // then the next carry should be 0 + // If carry == 1 and window & 1 == 0, + // then bit_buf & 1 == 1 so the next carry should be 1 + pos += 1 + continue + } + + if window < width/2 { + carry = 0 + naf[pos] = int8(window) + } else { + carry = 1 + naf[pos] = int8(window) - int8(width) + } + + pos += w + } + return naf +} + +func (s *Scalar) signedRadix16() [64]int8 { + b := s.Bytes() + if b[31] > 127 { + panic("scalar has high bit set illegally") + } + + var digits [64]int8 + + // Compute unsigned radix-16 digits: + for i := 0; i < 32; i++ { + digits[2*i] = int8(b[i] & 15) + digits[2*i+1] = int8((b[i] >> 4) & 15) + } + + // Recenter coefficients: + for i := 0; i < 63; i++ { + carry := (digits[i] + 8) >> 4 + digits[i] -= carry << 4 + digits[i+1] += carry + } + + return digits +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/scalar_fiat.go b/go/cm/sign/ed25519-blake2b/edwards25519/scalar_fiat.go new file mode 100644 index 0000000..c863eb9 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/scalar_fiat.go @@ -0,0 +1,1147 @@ +// Code generated by Fiat Cryptography. DO NOT EDIT. +// +// Autogenerated: word_by_word_montgomery --lang Go --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --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 edwards25519 Scalar 64 '2^252 + 27742317777372353535851937790883648493' mul add sub opp nonzero from_montgomery to_montgomery to_bytes from_bytes +// +// curve description: Scalar +// +// machine_wordsize = 64 (from "64") +// +// requested operations: mul, add, sub, opp, nonzero, from_montgomery, to_montgomery, to_bytes, from_bytes +// +// m = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed (from "2^252 + 27742317777372353535851937790883648493") +// +// +// +// 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 edwards25519 + +import "math/bits" + +type fiatScalarUint1 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 fiatScalarInt1 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 fiatScalarMontgomeryDomainFieldElement is a field element in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type fiatScalarMontgomeryDomainFieldElement [4]uint64 + +// The type fiatScalarNonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type fiatScalarNonMontgomeryDomainFieldElement [4]uint64 + +// fiatScalarCmovznzU64 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 fiatScalarCmovznzU64(out1 *uint64, arg1 fiatScalarUint1, arg2 uint64, arg3 uint64) { + x1 := (uint64(arg1) * 0xffffffffffffffff) + x2 := ((x1 & arg3) | ((^x1) & arg2)) + *out1 = x2 +} + +// fiatScalarMul 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 fiatScalarMul(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement, arg2 *fiatScalarMontgomeryDomainFieldElement) { + 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(fiatScalarUint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(fiatScalarUint1(x16))) + x19 := (uint64(fiatScalarUint1(x18)) + x6) + var x20 uint64 + _, x20 = bits.Mul64(x11, 0xd2b51da312547e1b) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x20, 0x1000000000000000) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x20, 0x14def9dea2f79cd6) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(x20, 0x5812631a5cf5d3ed) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) + x30 := (uint64(fiatScalarUint1(x29)) + x25) + var x32 uint64 + _, x32 = bits.Add64(x11, x26, uint64(0x0)) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Add64(x13, x28, uint64(fiatScalarUint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x15, x30, uint64(fiatScalarUint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x17, x22, uint64(fiatScalarUint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x19, x23, uint64(fiatScalarUint1(x38))) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(x1, arg2[3]) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, arg2[2]) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, arg2[1]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, arg2[0]) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(x48, x45, uint64(0x0)) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x46, x43, uint64(fiatScalarUint1(x50))) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x44, x41, uint64(fiatScalarUint1(x52))) + x55 := (uint64(fiatScalarUint1(x54)) + x42) + var x56 uint64 + var x57 uint64 + x56, x57 = bits.Add64(x33, x47, uint64(0x0)) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64(x35, x49, uint64(fiatScalarUint1(x57))) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x37, x51, uint64(fiatScalarUint1(x59))) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x39, x53, uint64(fiatScalarUint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(uint64(fiatScalarUint1(x40)), x55, uint64(fiatScalarUint1(x63))) + var x66 uint64 + _, x66 = bits.Mul64(x56, 0xd2b51da312547e1b) + var x68 uint64 + var x69 uint64 + x69, x68 = bits.Mul64(x66, 0x1000000000000000) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x66, 0x14def9dea2f79cd6) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x66, 0x5812631a5cf5d3ed) + var x74 uint64 + var x75 uint64 + x74, x75 = bits.Add64(x73, x70, uint64(0x0)) + x76 := (uint64(fiatScalarUint1(x75)) + x71) + var x78 uint64 + _, x78 = bits.Add64(x56, x72, uint64(0x0)) + var x79 uint64 + var x80 uint64 + x79, x80 = bits.Add64(x58, x74, uint64(fiatScalarUint1(x78))) + var x81 uint64 + var x82 uint64 + x81, x82 = bits.Add64(x60, x76, uint64(fiatScalarUint1(x80))) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x62, x68, uint64(fiatScalarUint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x64, x69, uint64(fiatScalarUint1(x84))) + x87 := (uint64(fiatScalarUint1(x86)) + uint64(fiatScalarUint1(x65))) + var x88 uint64 + var x89 uint64 + x89, x88 = bits.Mul64(x2, arg2[3]) + var x90 uint64 + var x91 uint64 + x91, x90 = bits.Mul64(x2, arg2[2]) + var x92 uint64 + var x93 uint64 + x93, x92 = bits.Mul64(x2, arg2[1]) + var x94 uint64 + var x95 uint64 + x95, x94 = bits.Mul64(x2, arg2[0]) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x95, x92, uint64(0x0)) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x93, x90, uint64(fiatScalarUint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x91, x88, uint64(fiatScalarUint1(x99))) + x102 := (uint64(fiatScalarUint1(x101)) + x89) + var x103 uint64 + var x104 uint64 + x103, x104 = bits.Add64(x79, x94, uint64(0x0)) + var x105 uint64 + var x106 uint64 + x105, x106 = bits.Add64(x81, x96, uint64(fiatScalarUint1(x104))) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x83, x98, uint64(fiatScalarUint1(x106))) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Add64(x85, x100, uint64(fiatScalarUint1(x108))) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x87, x102, uint64(fiatScalarUint1(x110))) + var x113 uint64 + _, x113 = bits.Mul64(x103, 0xd2b51da312547e1b) + var x115 uint64 + var x116 uint64 + x116, x115 = bits.Mul64(x113, 0x1000000000000000) + var x117 uint64 + var x118 uint64 + x118, x117 = bits.Mul64(x113, 0x14def9dea2f79cd6) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(x113, 0x5812631a5cf5d3ed) + var x121 uint64 + var x122 uint64 + x121, x122 = bits.Add64(x120, x117, uint64(0x0)) + x123 := (uint64(fiatScalarUint1(x122)) + x118) + var x125 uint64 + _, x125 = bits.Add64(x103, x119, uint64(0x0)) + var x126 uint64 + var x127 uint64 + x126, x127 = bits.Add64(x105, x121, uint64(fiatScalarUint1(x125))) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x107, x123, uint64(fiatScalarUint1(x127))) + var x130 uint64 + var x131 uint64 + x130, x131 = bits.Add64(x109, x115, uint64(fiatScalarUint1(x129))) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x111, x116, uint64(fiatScalarUint1(x131))) + x134 := (uint64(fiatScalarUint1(x133)) + uint64(fiatScalarUint1(x112))) + var x135 uint64 + var x136 uint64 + x136, x135 = bits.Mul64(x3, arg2[3]) + var x137 uint64 + var x138 uint64 + x138, x137 = bits.Mul64(x3, arg2[2]) + var x139 uint64 + var x140 uint64 + x140, x139 = bits.Mul64(x3, arg2[1]) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x3, arg2[0]) + 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(fiatScalarUint1(x144))) + var x147 uint64 + var x148 uint64 + x147, x148 = bits.Add64(x138, x135, uint64(fiatScalarUint1(x146))) + x149 := (uint64(fiatScalarUint1(x148)) + x136) + var x150 uint64 + var x151 uint64 + x150, x151 = bits.Add64(x126, x141, uint64(0x0)) + var x152 uint64 + var x153 uint64 + x152, x153 = bits.Add64(x128, x143, uint64(fiatScalarUint1(x151))) + var x154 uint64 + var x155 uint64 + x154, x155 = bits.Add64(x130, x145, uint64(fiatScalarUint1(x153))) + var x156 uint64 + var x157 uint64 + x156, x157 = bits.Add64(x132, x147, uint64(fiatScalarUint1(x155))) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x134, x149, uint64(fiatScalarUint1(x157))) + var x160 uint64 + _, x160 = bits.Mul64(x150, 0xd2b51da312547e1b) + var x162 uint64 + var x163 uint64 + x163, x162 = bits.Mul64(x160, 0x1000000000000000) + var x164 uint64 + var x165 uint64 + x165, x164 = bits.Mul64(x160, 0x14def9dea2f79cd6) + var x166 uint64 + var x167 uint64 + x167, x166 = bits.Mul64(x160, 0x5812631a5cf5d3ed) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Add64(x167, x164, uint64(0x0)) + x170 := (uint64(fiatScalarUint1(x169)) + x165) + var x172 uint64 + _, x172 = bits.Add64(x150, x166, uint64(0x0)) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x152, x168, uint64(fiatScalarUint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x154, x170, uint64(fiatScalarUint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x156, x162, uint64(fiatScalarUint1(x176))) + var x179 uint64 + var x180 uint64 + x179, x180 = bits.Add64(x158, x163, uint64(fiatScalarUint1(x178))) + x181 := (uint64(fiatScalarUint1(x180)) + uint64(fiatScalarUint1(x159))) + var x182 uint64 + var x183 uint64 + x182, x183 = bits.Sub64(x173, 0x5812631a5cf5d3ed, uint64(0x0)) + var x184 uint64 + var x185 uint64 + x184, x185 = bits.Sub64(x175, 0x14def9dea2f79cd6, uint64(fiatScalarUint1(x183))) + var x186 uint64 + var x187 uint64 + x186, x187 = bits.Sub64(x177, uint64(0x0), uint64(fiatScalarUint1(x185))) + var x188 uint64 + var x189 uint64 + x188, x189 = bits.Sub64(x179, 0x1000000000000000, uint64(fiatScalarUint1(x187))) + var x191 uint64 + _, x191 = bits.Sub64(x181, uint64(0x0), uint64(fiatScalarUint1(x189))) + var x192 uint64 + fiatScalarCmovznzU64(&x192, fiatScalarUint1(x191), x182, x173) + var x193 uint64 + fiatScalarCmovznzU64(&x193, fiatScalarUint1(x191), x184, x175) + var x194 uint64 + fiatScalarCmovznzU64(&x194, fiatScalarUint1(x191), x186, x177) + var x195 uint64 + fiatScalarCmovznzU64(&x195, fiatScalarUint1(x191), x188, x179) + out1[0] = x192 + out1[1] = x193 + out1[2] = x194 + out1[3] = x195 +} + +// fiatScalarAdd 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 fiatScalarAdd(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement, arg2 *fiatScalarMontgomeryDomainFieldElement) { + 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(fiatScalarUint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(fiatScalarUint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(fiatScalarUint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(x1, 0x5812631a5cf5d3ed, uint64(0x0)) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(x3, 0x14def9dea2f79cd6, uint64(fiatScalarUint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Sub64(x5, uint64(0x0), uint64(fiatScalarUint1(x12))) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Sub64(x7, 0x1000000000000000, uint64(fiatScalarUint1(x14))) + var x18 uint64 + _, x18 = bits.Sub64(uint64(fiatScalarUint1(x8)), uint64(0x0), uint64(fiatScalarUint1(x16))) + var x19 uint64 + fiatScalarCmovznzU64(&x19, fiatScalarUint1(x18), x9, x1) + var x20 uint64 + fiatScalarCmovznzU64(&x20, fiatScalarUint1(x18), x11, x3) + var x21 uint64 + fiatScalarCmovznzU64(&x21, fiatScalarUint1(x18), x13, x5) + var x22 uint64 + fiatScalarCmovznzU64(&x22, fiatScalarUint1(x18), x15, x7) + out1[0] = x19 + out1[1] = x20 + out1[2] = x21 + out1[3] = x22 +} + +// fiatScalarSub 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 fiatScalarSub(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement, arg2 *fiatScalarMontgomeryDomainFieldElement) { + 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(fiatScalarUint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(fiatScalarUint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(fiatScalarUint1(x6))) + var x9 uint64 + fiatScalarCmovznzU64(&x9, fiatScalarUint1(x8), uint64(0x0), 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x1, (x9 & 0x5812631a5cf5d3ed), uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x3, (x9 & 0x14def9dea2f79cd6), uint64(fiatScalarUint1(x11))) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x5, uint64(0x0), uint64(fiatScalarUint1(x13))) + var x16 uint64 + x16, _ = bits.Add64(x7, (x9 & 0x1000000000000000), uint64(fiatScalarUint1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +// fiatScalarOpp negates a field element in the Montgomery domain. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// +// Postconditions: +// +// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m +// 0 ≤ eval out1 < m +func fiatScalarOpp(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(uint64(0x0), arg1[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(uint64(0x0), arg1[1], uint64(fiatScalarUint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(uint64(0x0), arg1[2], uint64(fiatScalarUint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(uint64(0x0), arg1[3], uint64(fiatScalarUint1(x6))) + var x9 uint64 + fiatScalarCmovznzU64(&x9, fiatScalarUint1(x8), uint64(0x0), 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x1, (x9 & 0x5812631a5cf5d3ed), uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x3, (x9 & 0x14def9dea2f79cd6), uint64(fiatScalarUint1(x11))) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x5, uint64(0x0), uint64(fiatScalarUint1(x13))) + var x16 uint64 + x16, _ = bits.Add64(x7, (x9 & 0x1000000000000000), uint64(fiatScalarUint1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +// fiatScalarNonzero outputs a single non-zero word if the input is non-zero and zero otherwise. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// +// Postconditions: +// +// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0 +// +// Input Bounds: +// +// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// +// Output Bounds: +// +// out1: [0x0 ~> 0xffffffffffffffff] +func fiatScalarNonzero(out1 *uint64, arg1 *[4]uint64) { + x1 := (arg1[0] | (arg1[1] | (arg1[2] | arg1[3]))) + *out1 = x1 +} + +// fiatScalarFromMontgomery 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 fiatScalarFromMontgomery(out1 *fiatScalarNonMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement) { + x1 := arg1[0] + var x2 uint64 + _, x2 = bits.Mul64(x1, 0xd2b51da312547e1b) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(x2, 0x1000000000000000) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(x2, 0x14def9dea2f79cd6) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(x2, 0x5812631a5cf5d3ed) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x9, x6, uint64(0x0)) + var x13 uint64 + _, x13 = bits.Add64(x1, x8, uint64(0x0)) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(uint64(0x0), x10, uint64(fiatScalarUint1(x13))) + var x16 uint64 + var x17 uint64 + x16, x17 = bits.Add64(x14, arg1[1], uint64(0x0)) + var x18 uint64 + _, x18 = bits.Mul64(x16, 0xd2b51da312547e1b) + var x20 uint64 + var x21 uint64 + x21, x20 = bits.Mul64(x18, 0x1000000000000000) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x18, 0x14def9dea2f79cd6) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x18, 0x5812631a5cf5d3ed) + var x26 uint64 + var x27 uint64 + x26, x27 = bits.Add64(x25, x22, uint64(0x0)) + var x29 uint64 + _, x29 = bits.Add64(x16, x24, uint64(0x0)) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64((uint64(fiatScalarUint1(x17)) + (uint64(fiatScalarUint1(x15)) + (uint64(fiatScalarUint1(x11)) + x7))), x26, uint64(fiatScalarUint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(x4, (uint64(fiatScalarUint1(x27)) + x23), uint64(fiatScalarUint1(x31))) + var x34 uint64 + var x35 uint64 + x34, x35 = bits.Add64(x5, x20, uint64(fiatScalarUint1(x33))) + var x36 uint64 + var x37 uint64 + x36, x37 = bits.Add64(x30, arg1[2], uint64(0x0)) + var x38 uint64 + var x39 uint64 + x38, x39 = bits.Add64(x32, uint64(0x0), uint64(fiatScalarUint1(x37))) + var x40 uint64 + var x41 uint64 + x40, x41 = bits.Add64(x34, uint64(0x0), uint64(fiatScalarUint1(x39))) + var x42 uint64 + _, x42 = bits.Mul64(x36, 0xd2b51da312547e1b) + var x44 uint64 + var x45 uint64 + x45, x44 = bits.Mul64(x42, 0x1000000000000000) + var x46 uint64 + var x47 uint64 + x47, x46 = bits.Mul64(x42, 0x14def9dea2f79cd6) + var x48 uint64 + var x49 uint64 + x49, x48 = bits.Mul64(x42, 0x5812631a5cf5d3ed) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x49, x46, uint64(0x0)) + var x53 uint64 + _, x53 = bits.Add64(x36, x48, uint64(0x0)) + var x54 uint64 + var x55 uint64 + x54, x55 = bits.Add64(x38, x50, uint64(fiatScalarUint1(x53))) + var x56 uint64 + var x57 uint64 + x56, x57 = bits.Add64(x40, (uint64(fiatScalarUint1(x51)) + x47), uint64(fiatScalarUint1(x55))) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64((uint64(fiatScalarUint1(x41)) + (uint64(fiatScalarUint1(x35)) + x21)), x44, uint64(fiatScalarUint1(x57))) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x54, arg1[3], uint64(0x0)) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x56, uint64(0x0), uint64(fiatScalarUint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x58, uint64(0x0), uint64(fiatScalarUint1(x63))) + var x66 uint64 + _, x66 = bits.Mul64(x60, 0xd2b51da312547e1b) + var x68 uint64 + var x69 uint64 + x69, x68 = bits.Mul64(x66, 0x1000000000000000) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x66, 0x14def9dea2f79cd6) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x66, 0x5812631a5cf5d3ed) + var x74 uint64 + var x75 uint64 + x74, x75 = bits.Add64(x73, x70, uint64(0x0)) + var x77 uint64 + _, x77 = bits.Add64(x60, x72, uint64(0x0)) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x62, x74, uint64(fiatScalarUint1(x77))) + var x80 uint64 + var x81 uint64 + x80, x81 = bits.Add64(x64, (uint64(fiatScalarUint1(x75)) + x71), uint64(fiatScalarUint1(x79))) + var x82 uint64 + var x83 uint64 + x82, x83 = bits.Add64((uint64(fiatScalarUint1(x65)) + (uint64(fiatScalarUint1(x59)) + x45)), x68, uint64(fiatScalarUint1(x81))) + x84 := (uint64(fiatScalarUint1(x83)) + x69) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Sub64(x78, 0x5812631a5cf5d3ed, uint64(0x0)) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Sub64(x80, 0x14def9dea2f79cd6, uint64(fiatScalarUint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Sub64(x82, uint64(0x0), uint64(fiatScalarUint1(x88))) + var x91 uint64 + var x92 uint64 + x91, x92 = bits.Sub64(x84, 0x1000000000000000, uint64(fiatScalarUint1(x90))) + var x94 uint64 + _, x94 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(fiatScalarUint1(x92))) + var x95 uint64 + fiatScalarCmovznzU64(&x95, fiatScalarUint1(x94), x85, x78) + var x96 uint64 + fiatScalarCmovznzU64(&x96, fiatScalarUint1(x94), x87, x80) + var x97 uint64 + fiatScalarCmovznzU64(&x97, fiatScalarUint1(x94), x89, x82) + var x98 uint64 + fiatScalarCmovznzU64(&x98, fiatScalarUint1(x94), x91, x84) + out1[0] = x95 + out1[1] = x96 + out1[2] = x97 + out1[3] = x98 +} + +// fiatScalarToMontgomery 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 fiatScalarToMontgomery(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarNonMontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, 0x399411b7c309a3d) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, 0xceec73d217f5be65) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, 0xd00e1ba768859347) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, 0xa40611e3449c0f01) + 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(fiatScalarUint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(fiatScalarUint1(x16))) + var x19 uint64 + _, x19 = bits.Mul64(x11, 0xd2b51da312547e1b) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(x19, 0x1000000000000000) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(x19, 0x14def9dea2f79cd6) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(x19, 0x5812631a5cf5d3ed) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x26, x23, uint64(0x0)) + var x30 uint64 + _, x30 = bits.Add64(x11, x25, uint64(0x0)) + var x31 uint64 + var x32 uint64 + x31, x32 = bits.Add64(x13, x27, uint64(fiatScalarUint1(x30))) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Add64(x15, (uint64(fiatScalarUint1(x28)) + x24), uint64(fiatScalarUint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x17, x21, uint64(fiatScalarUint1(x34))) + var x37 uint64 + var x38 uint64 + x38, x37 = bits.Mul64(x1, 0x399411b7c309a3d) + var x39 uint64 + var x40 uint64 + x40, x39 = bits.Mul64(x1, 0xceec73d217f5be65) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(x1, 0xd00e1ba768859347) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, 0xa40611e3449c0f01) + var x45 uint64 + var x46 uint64 + x45, x46 = bits.Add64(x44, x41, uint64(0x0)) + var x47 uint64 + var x48 uint64 + x47, x48 = bits.Add64(x42, x39, uint64(fiatScalarUint1(x46))) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(x40, x37, uint64(fiatScalarUint1(x48))) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x31, x43, uint64(0x0)) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x33, x45, uint64(fiatScalarUint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x35, x47, uint64(fiatScalarUint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(((uint64(fiatScalarUint1(x36)) + (uint64(fiatScalarUint1(x18)) + x6)) + x22), x49, uint64(fiatScalarUint1(x56))) + var x59 uint64 + _, x59 = bits.Mul64(x51, 0xd2b51da312547e1b) + var x61 uint64 + var x62 uint64 + x62, x61 = bits.Mul64(x59, 0x1000000000000000) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(x59, 0x14def9dea2f79cd6) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(x59, 0x5812631a5cf5d3ed) + var x67 uint64 + var x68 uint64 + x67, x68 = bits.Add64(x66, x63, uint64(0x0)) + var x70 uint64 + _, x70 = bits.Add64(x51, x65, uint64(0x0)) + var x71 uint64 + var x72 uint64 + x71, x72 = bits.Add64(x53, x67, uint64(fiatScalarUint1(x70))) + var x73 uint64 + var x74 uint64 + x73, x74 = bits.Add64(x55, (uint64(fiatScalarUint1(x68)) + x64), uint64(fiatScalarUint1(x72))) + var x75 uint64 + var x76 uint64 + x75, x76 = bits.Add64(x57, x61, uint64(fiatScalarUint1(x74))) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(x2, 0x399411b7c309a3d) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(x2, 0xceec73d217f5be65) + var x81 uint64 + var x82 uint64 + x82, x81 = bits.Mul64(x2, 0xd00e1ba768859347) + var x83 uint64 + var x84 uint64 + x84, x83 = bits.Mul64(x2, 0xa40611e3449c0f01) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x84, x81, uint64(0x0)) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x82, x79, uint64(fiatScalarUint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x80, x77, uint64(fiatScalarUint1(x88))) + var x91 uint64 + var x92 uint64 + x91, x92 = bits.Add64(x71, x83, uint64(0x0)) + var x93 uint64 + var x94 uint64 + x93, x94 = bits.Add64(x73, x85, uint64(fiatScalarUint1(x92))) + var x95 uint64 + var x96 uint64 + x95, x96 = bits.Add64(x75, x87, uint64(fiatScalarUint1(x94))) + var x97 uint64 + var x98 uint64 + x97, x98 = bits.Add64(((uint64(fiatScalarUint1(x76)) + (uint64(fiatScalarUint1(x58)) + (uint64(fiatScalarUint1(x50)) + x38))) + x62), x89, uint64(fiatScalarUint1(x96))) + var x99 uint64 + _, x99 = bits.Mul64(x91, 0xd2b51da312547e1b) + var x101 uint64 + var x102 uint64 + x102, x101 = bits.Mul64(x99, 0x1000000000000000) + var x103 uint64 + var x104 uint64 + x104, x103 = bits.Mul64(x99, 0x14def9dea2f79cd6) + var x105 uint64 + var x106 uint64 + x106, x105 = bits.Mul64(x99, 0x5812631a5cf5d3ed) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x106, x103, uint64(0x0)) + var x110 uint64 + _, x110 = bits.Add64(x91, x105, uint64(0x0)) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x93, x107, uint64(fiatScalarUint1(x110))) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x95, (uint64(fiatScalarUint1(x108)) + x104), uint64(fiatScalarUint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x97, x101, uint64(fiatScalarUint1(x114))) + var x117 uint64 + var x118 uint64 + x118, x117 = bits.Mul64(x3, 0x399411b7c309a3d) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(x3, 0xceec73d217f5be65) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(x3, 0xd00e1ba768859347) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x3, 0xa40611e3449c0f01) + var x125 uint64 + var x126 uint64 + x125, x126 = bits.Add64(x124, x121, uint64(0x0)) + var x127 uint64 + var x128 uint64 + x127, x128 = bits.Add64(x122, x119, uint64(fiatScalarUint1(x126))) + var x129 uint64 + var x130 uint64 + x129, x130 = bits.Add64(x120, x117, uint64(fiatScalarUint1(x128))) + var x131 uint64 + var x132 uint64 + x131, x132 = bits.Add64(x111, x123, uint64(0x0)) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x113, x125, uint64(fiatScalarUint1(x132))) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x115, x127, uint64(fiatScalarUint1(x134))) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(((uint64(fiatScalarUint1(x116)) + (uint64(fiatScalarUint1(x98)) + (uint64(fiatScalarUint1(x90)) + x78))) + x102), x129, uint64(fiatScalarUint1(x136))) + var x139 uint64 + _, x139 = bits.Mul64(x131, 0xd2b51da312547e1b) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x139, 0x1000000000000000) + var x143 uint64 + var x144 uint64 + x144, x143 = bits.Mul64(x139, 0x14def9dea2f79cd6) + var x145 uint64 + var x146 uint64 + x146, x145 = bits.Mul64(x139, 0x5812631a5cf5d3ed) + var x147 uint64 + var x148 uint64 + x147, x148 = bits.Add64(x146, x143, uint64(0x0)) + var x150 uint64 + _, x150 = bits.Add64(x131, x145, uint64(0x0)) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x133, x147, uint64(fiatScalarUint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x135, (uint64(fiatScalarUint1(x148)) + x144), uint64(fiatScalarUint1(x152))) + var x155 uint64 + var x156 uint64 + x155, x156 = bits.Add64(x137, x141, uint64(fiatScalarUint1(x154))) + x157 := ((uint64(fiatScalarUint1(x156)) + (uint64(fiatScalarUint1(x138)) + (uint64(fiatScalarUint1(x130)) + x118))) + x142) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Sub64(x151, 0x5812631a5cf5d3ed, uint64(0x0)) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Sub64(x153, 0x14def9dea2f79cd6, uint64(fiatScalarUint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Sub64(x155, uint64(0x0), uint64(fiatScalarUint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Sub64(x157, 0x1000000000000000, uint64(fiatScalarUint1(x163))) + var x167 uint64 + _, x167 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(fiatScalarUint1(x165))) + var x168 uint64 + fiatScalarCmovznzU64(&x168, fiatScalarUint1(x167), x158, x151) + var x169 uint64 + fiatScalarCmovznzU64(&x169, fiatScalarUint1(x167), x160, x153) + var x170 uint64 + fiatScalarCmovznzU64(&x170, fiatScalarUint1(x167), x162, x155) + var x171 uint64 + fiatScalarCmovznzU64(&x171, fiatScalarUint1(x167), x164, x157) + out1[0] = x168 + out1[1] = x169 + out1[2] = x170 + out1[3] = x171 +} + +// fiatScalarToBytes 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 ~> 0x1fffffffffffffff]] +// +// 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 ~> 0x1f]] +func fiatScalarToBytes(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 +} + +// fiatScalarFromBytes 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 ~> 0x1f]] +// +// Output Bounds: +// +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1fffffffffffffff]] +func fiatScalarFromBytes(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/go/cm/sign/ed25519-blake2b/edwards25519/scalarmult.go b/go/cm/sign/ed25519-blake2b/edwards25519/scalarmult.go new file mode 100644 index 0000000..55c3f0e --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/scalarmult.go @@ -0,0 +1,214 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import "sync" + +// basepointTable is a set of 32 affineLookupTables, where table i is generated +// from 256i * basepoint. It is precomputed the first time it's used. +func basepointTable() *[32]affineLookupTable { + basepointTablePrecomp.initOnce.Do(func() { + p := NewGeneratorPoint() + for i := 0; i < 32; i++ { + basepointTablePrecomp.table[i].FromP3(p) + for j := 0; j < 8; j++ { + p.Add(p, p) + } + } + }) + return &basepointTablePrecomp.table +} + +var basepointTablePrecomp struct { + table [32]affineLookupTable + initOnce sync.Once +} + +// ScalarBaseMult sets v = x * B, where B is the canonical generator, and +// returns v. +// +// The scalar multiplication is done in constant time. +func (v *Point) ScalarBaseMult(x *Scalar) *Point { + basepointTable := basepointTable() + + // Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i ) + // as described in the Ed25519 paper + // + // Group even and odd coefficients + // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B + // + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B + // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B + // + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B) + // + // We use a lookup table for each i to get x_i*16^(2*i)*B + // and do four doublings to multiply by 16. + digits := x.signedRadix16() + + multiple := &affineCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + + // Accumulate the odd components first + v.Set(NewIdentityPoint()) + for i := 1; i < 64; i += 2 { + basepointTable[i/2].SelectInto(multiple, digits[i]) + tmp1.AddAffine(v, multiple) + v.fromP1xP1(tmp1) + } + + // Multiply by 16 + tmp2.FromP3(v) // tmp2 = v in P2 coords + tmp1.Double(tmp2) // tmp1 = 2*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 2*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 4*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 4*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 8*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 8*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 16*v in P1xP1 coords + v.fromP1xP1(tmp1) // now v = 16*(odd components) + + // Accumulate the even components + for i := 0; i < 64; i += 2 { + basepointTable[i/2].SelectInto(multiple, digits[i]) + tmp1.AddAffine(v, multiple) + v.fromP1xP1(tmp1) + } + + return v +} + +// ScalarMult sets v = x * q, and returns v. +// +// The scalar multiplication is done in constant time. +func (v *Point) ScalarMult(x *Scalar, q *Point) *Point { + checkInitialized(q) + + var table projLookupTable + table.FromP3(q) + + // Write x = sum(x_i * 16^i) + // so x*Q = sum( Q*x_i*16^i ) + // = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... ) + // <------compute inside out--------- + // + // We use the lookup table to get the x_i*Q values + // and do four doublings to compute 16*Q + digits := x.signedRadix16() + + // Unwrap first loop iteration to save computing 16*identity + multiple := &projCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + table.SelectInto(multiple, digits[63]) + + v.Set(NewIdentityPoint()) + tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords + for i := 62; i >= 0; i-- { + tmp2.FromP1xP1(tmp1) // tmp2 = (prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords + v.fromP1xP1(tmp1) // v = 16*(prev) in P3 coords + table.SelectInto(multiple, digits[i]) + tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords + } + v.fromP1xP1(tmp1) + return v +} + +// basepointNafTable is the nafLookupTable8 for the basepoint. +// It is precomputed the first time it's used. +func basepointNafTable() *nafLookupTable8 { + basepointNafTablePrecomp.initOnce.Do(func() { + basepointNafTablePrecomp.table.FromP3(NewGeneratorPoint()) + }) + return &basepointNafTablePrecomp.table +} + +var basepointNafTablePrecomp struct { + table nafLookupTable8 + initOnce sync.Once +} + +// VarTimeDoubleScalarBaseMult sets v = a * A + b * B, where B is the canonical +// generator, and returns v. +// +// Execution time depends on the inputs. +func (v *Point) VarTimeDoubleScalarBaseMult(a *Scalar, A *Point, b *Scalar) *Point { + checkInitialized(A) + + // Similarly to the single variable-base approach, we compute + // digits and use them with a lookup table. However, because + // we are allowed to do variable-time operations, we don't + // need constant-time lookups or constant-time digit + // computations. + // + // So we use a non-adjacent form of some width w instead of + // radix 16. This is like a binary representation (one digit + // for each binary place) but we allow the digits to grow in + // magnitude up to 2^{w-1} so that the nonzero digits are as + // sparse as possible. Intuitively, this "condenses" the + // "mass" of the scalar onto sparse coefficients (meaning + // fewer additions). + + basepointNafTable := basepointNafTable() + var aTable nafLookupTable5 + aTable.FromP3(A) + // Because the basepoint is fixed, we can use a wider NAF + // corresponding to a bigger table. + aNaf := a.nonAdjacentForm(5) + bNaf := b.nonAdjacentForm(8) + + // Find the first nonzero coefficient. + i := 255 + for j := i; j >= 0; j-- { + if aNaf[j] != 0 || bNaf[j] != 0 { + break + } + } + + multA := &projCached{} + multB := &affineCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + tmp2.Zero() + + // Move from high to low bits, doubling the accumulator + // at each iteration and checking whether there is a nonzero + // coefficient to look up a multiple of. + for ; i >= 0; i-- { + tmp1.Double(tmp2) + + // Only update v if we have a nonzero coeff to add in. + if aNaf[i] > 0 { + v.fromP1xP1(tmp1) + aTable.SelectInto(multA, aNaf[i]) + tmp1.Add(v, multA) + } else if aNaf[i] < 0 { + v.fromP1xP1(tmp1) + aTable.SelectInto(multA, -aNaf[i]) + tmp1.Sub(v, multA) + } + + if bNaf[i] > 0 { + v.fromP1xP1(tmp1) + basepointNafTable.SelectInto(multB, bNaf[i]) + tmp1.AddAffine(v, multB) + } else if bNaf[i] < 0 { + v.fromP1xP1(tmp1) + basepointNafTable.SelectInto(multB, -bNaf[i]) + tmp1.SubAffine(v, multB) + } + + tmp2.FromP1xP1(tmp1) + } + + v.fromP2(tmp2) + return v +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/constant_time.go b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/constant_time.go new file mode 100644 index 0000000..563c1cf --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/constant_time.go @@ -0,0 +1,60 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle + +// ConstantTimeCompare returns 1 if the two slices, x and y, have equal contents +// and 0 otherwise. The time taken is a function of the length of the slices and +// is independent of the contents. If the lengths of x and y do not match it +// returns 0 immediately. +func ConstantTimeCompare(x, y []byte) int { + if len(x) != len(y) { + return 0 + } + + var v byte + + for i := 0; i < len(x); i++ { + v |= x[i] ^ y[i] + } + + return ConstantTimeByteEq(v, 0) +} + +// ConstantTimeSelect returns x if v == 1 and y if v == 0. +// Its behavior is undefined if v takes any other value. +func ConstantTimeSelect(v, x, y int) int { return ^(v-1)&x | (v-1)&y } + +// ConstantTimeByteEq returns 1 if x == y and 0 otherwise. +func ConstantTimeByteEq(x, y uint8) int { + return int((uint32(x^y) - 1) >> 31) +} + +// ConstantTimeEq returns 1 if x == y and 0 otherwise. +func ConstantTimeEq(x, y int32) int { + return int((uint64(uint32(x^y)) - 1) >> 63) +} + +// ConstantTimeCopy copies the contents of y into x (a slice of equal length) +// if v == 1. If v == 0, x is left unchanged. Its behavior is undefined if v +// takes any other value. +func ConstantTimeCopy(v int, x, y []byte) { + if len(x) != len(y) { + panic("subtle: slices have different lengths") + } + + xmask := byte(v - 1) + ymask := byte(^(v - 1)) + for i := 0; i < len(x); i++ { + x[i] = x[i]&xmask | y[i]&ymask + } +} + +// ConstantTimeLessOrEq returns 1 if x <= y and 0 otherwise. +// Its behavior is undefined if x or y are negative or > 2**31 - 1. +func ConstantTimeLessOrEq(x, y int) int { + x32 := int32(x) + y32 := int32(y) + return int(((x32 - y32 - 1) >> 31) & 1) +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor.go b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor.go new file mode 100644 index 0000000..9090a3f --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor.go @@ -0,0 +1,30 @@ +// 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. + +package subtle + +import "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/edwards25519/alias" + +// XORBytes sets dst[i] = x[i] ^ y[i] for all i < n = min(len(x), len(y)), +// returning n, the number of bytes written to dst. +// +// If dst does not have length at least n, +// XORBytes panics without writing anything to dst. +// +// dst and x or y may overlap exactly or not at all, +// otherwise XORBytes may panic. +func XORBytes(dst, x, y []byte) int { + n := min(len(x), len(y)) + if n == 0 { + return 0 + } + if n > len(dst) { + panic("subtle.XORBytes: dst too short") + } + if alias.InexactOverlap(dst[:n], x[:n]) || alias.InexactOverlap(dst[:n], y[:n]) { + panic("subtle.XORBytes: invalid overlap") + } + xorBytes(&dst[0], &x[0], &y[0], n) // arch-specific + return n +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_amd64.go b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_amd64.go new file mode 100644 index 0000000..314ebaf --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_amd64.go @@ -0,0 +1,10 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +package subtle + +//go:noescape +func xorBytes(dst, a, b *byte, n int) diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_amd64.s b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_amd64.s new file mode 100644 index 0000000..bcd93f4 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_amd64.s @@ -0,0 +1,58 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !purego + +#include "textflag.h" + +// func xorBytes(dst, a, b *byte, n int) +TEXT ·xorBytes(SB), NOSPLIT, $0 + MOVQ dst+0(FP), BX + MOVQ a+8(FP), SI + MOVQ b+16(FP), CX + MOVQ n+24(FP), DX + TESTQ $15, DX // AND 15 & len, if not zero jump to not_aligned. + JNZ not_aligned + +aligned: + MOVQ $0, AX // position in slices + + PCALIGN $16 +loop16b: + MOVOU (SI)(AX*1), X0 // XOR 16byte forwards. + MOVOU (CX)(AX*1), X1 + PXOR X1, X0 + MOVOU X0, (BX)(AX*1) + ADDQ $16, AX + CMPQ DX, AX + JNE loop16b + RET + + PCALIGN $16 +loop_1b: + SUBQ $1, DX // XOR 1byte backwards. + MOVB (SI)(DX*1), DI + MOVB (CX)(DX*1), AX + XORB AX, DI + MOVB DI, (BX)(DX*1) + TESTQ $7, DX // AND 7 & len, if not zero jump to loop_1b. + JNZ loop_1b + CMPQ DX, $0 // if len is 0, ret. + JE ret + TESTQ $15, DX // AND 15 & len, if zero jump to aligned. + JZ aligned + +not_aligned: + TESTQ $7, DX // AND $7 & len, if not zero jump to loop_1b. + JNE loop_1b + SUBQ $8, DX // XOR 8bytes backwards. + MOVQ (SI)(DX*1), DI + MOVQ (CX)(DX*1), AX + XORQ AX, DI + MOVQ DI, (BX)(DX*1) + CMPQ DX, $16 // if len is greater or equal 16 here, it must be aligned. + JGE aligned + +ret: + RET diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_arm64.go b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_arm64.go new file mode 100644 index 0000000..78a928c --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_arm64.go @@ -0,0 +1,10 @@ +// Copyright 2020 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 !purego + +package subtle + +//go:noescape +func xorBytes(dst, a, b *byte, n int) diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_arm64.s b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_arm64.s new file mode 100644 index 0000000..2864759 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_arm64.s @@ -0,0 +1,69 @@ +// Copyright 2020 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 !purego + +#include "textflag.h" + +// func xorBytes(dst, a, b *byte, n int) +TEXT ·xorBytes(SB), NOSPLIT|NOFRAME, $0 + MOVD dst+0(FP), R0 + MOVD a+8(FP), R1 + MOVD b+16(FP), R2 + MOVD n+24(FP), R3 + CMP $64, R3 + BLT tail +loop_64: + VLD1.P 64(R1), [V0.B16, V1.B16, V2.B16, V3.B16] + VLD1.P 64(R2), [V4.B16, V5.B16, V6.B16, V7.B16] + VEOR V0.B16, V4.B16, V4.B16 + VEOR V1.B16, V5.B16, V5.B16 + VEOR V2.B16, V6.B16, V6.B16 + VEOR V3.B16, V7.B16, V7.B16 + VST1.P [V4.B16, V5.B16, V6.B16, V7.B16], 64(R0) + SUBS $64, R3 + CMP $64, R3 + BGE loop_64 +tail: + // quick end + CBZ R3, end + TBZ $5, R3, less_than32 + VLD1.P 32(R1), [V0.B16, V1.B16] + VLD1.P 32(R2), [V2.B16, V3.B16] + VEOR V0.B16, V2.B16, V2.B16 + VEOR V1.B16, V3.B16, V3.B16 + VST1.P [V2.B16, V3.B16], 32(R0) +less_than32: + TBZ $4, R3, less_than16 + LDP.P 16(R1), (R11, R12) + LDP.P 16(R2), (R13, R14) + EOR R11, R13, R13 + EOR R12, R14, R14 + STP.P (R13, R14), 16(R0) +less_than16: + TBZ $3, R3, less_than8 + MOVD.P 8(R1), R11 + MOVD.P 8(R2), R12 + EOR R11, R12, R12 + MOVD.P R12, 8(R0) +less_than8: + TBZ $2, R3, less_than4 + MOVWU.P 4(R1), R13 + MOVWU.P 4(R2), R14 + EORW R13, R14, R14 + MOVWU.P R14, 4(R0) +less_than4: + TBZ $1, R3, less_than2 + MOVHU.P 2(R1), R15 + MOVHU.P 2(R2), R16 + EORW R15, R16, R16 + MOVHU.P R16, 2(R0) +less_than2: + TBZ $0, R3, end + MOVBU (R1), R17 + MOVBU (R2), R19 + EORW R17, R19, R19 + MOVBU R19, (R0) +end: + RET diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_generic.go b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_generic.go new file mode 100644 index 0000000..0a5ed8a --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_generic.go @@ -0,0 +1,64 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !arm64 && !loong64 && !ppc64 && !ppc64le) || purego + +package subtle + +import ( + "runtime" + "unsafe" +) + +const wordSize = unsafe.Sizeof(uintptr(0)) + +const supportsUnaligned = runtime.GOARCH == "386" || + runtime.GOARCH == "amd64" || + runtime.GOARCH == "ppc64" || + runtime.GOARCH == "ppc64le" || + runtime.GOARCH == "s390x" + +func xorBytes(dstb, xb, yb *byte, n int) { + // xorBytes assembly is written using pointers and n. Back to slices. + dst := unsafe.Slice(dstb, n) + x := unsafe.Slice(xb, n) + y := unsafe.Slice(yb, n) + + if supportsUnaligned || aligned(dstb, xb, yb) { + xorLoop(words(dst), words(x), words(y)) + if uintptr(n)%wordSize == 0 { + return + } + done := n &^ int(wordSize-1) + dst = dst[done:] + x = x[done:] + y = y[done:] + } + xorLoop(dst, x, y) +} + +// aligned reports whether dst, x, and y are all word-aligned pointers. +func aligned(dst, x, y *byte) bool { + return (uintptr(unsafe.Pointer(dst))|uintptr(unsafe.Pointer(x))|uintptr(unsafe.Pointer(y)))&(wordSize-1) == 0 +} + +// words returns a []uintptr pointing at the same data as x, +// with any trailing partial word removed. +func words(x []byte) []uintptr { + n := uintptr(len(x)) / wordSize + if n == 0 { + // Avoid creating a *uintptr that refers to data smaller than a uintptr; + // see issue 59334. + return nil + } + return unsafe.Slice((*uintptr)(unsafe.Pointer(&x[0])), n) +} + +func xorLoop[T byte | uintptr](dst, x, y []T) { + x = x[:len(dst)] // remove bounds check in loop + y = y[:len(dst)] // remove bounds check in loop + for i := range dst { + dst[i] = x[i] ^ y[i] + } +} diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_loong64.go b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_loong64.go new file mode 100644 index 0000000..f9d629d --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_loong64.go @@ -0,0 +1,10 @@ +// Copyright 2024 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 !purego + +package subtle + +//go:noescape +func xorBytes(dst, a, b *byte, n int) diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_loong64.s b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_loong64.s new file mode 100644 index 0000000..83ed000 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_loong64.s @@ -0,0 +1,166 @@ +// Copyright 2024 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 !purego + +#include "textflag.h" + +// func xorBytes(dst, a, b *byte, n int) +TEXT ·xorBytes(SB), NOSPLIT, $0 + MOVV dst+0(FP), R4 + MOVV a+8(FP), R5 + MOVV b+16(FP), R6 + MOVV n+24(FP), R7 + + MOVV $64, R9 + BGEU R7, R9, loop64 // n >= 64 +tail: + SRLV $1, R9 + BGEU R7, R9, xor_32 // n >= 32 && n < 64 + SRLV $1, R9 + BGEU R7, R9, xor_16 // n >= 16 && n < 32 + SRLV $1, R9 + BGEU R7, R9, xor_8 // n >= 8 && n < 16 + SRLV $1, R9 + BGEU R7, R9, xor_4 // n >= 4 && n < 8 + SRLV $1, R9 + BGEU R7, R9, xor_2 // n >= 2 && n < 4 + SRLV $1, R9 + BGEU R7, R9, xor_1 // n = 1 + +loop64: + MOVV (R5), R10 + MOVV 8(R5), R11 + MOVV 16(R5), R12 + MOVV 24(R5), R13 + MOVV (R6), R14 + MOVV 8(R6), R15 + MOVV 16(R6), R16 + MOVV 24(R6), R17 + XOR R10, R14 + XOR R11, R15 + XOR R12, R16 + XOR R13, R17 + MOVV R14, (R4) + MOVV R15, 8(R4) + MOVV R16, 16(R4) + MOVV R17, 24(R4) + MOVV 32(R5), R10 + MOVV 40(R5), R11 + MOVV 48(R5), R12 + MOVV 56(R5), R13 + MOVV 32(R6), R14 + MOVV 40(R6), R15 + MOVV 48(R6), R16 + MOVV 56(R6), R17 + XOR R10, R14 + XOR R11, R15 + XOR R12, R16 + XOR R13, R17 + MOVV R14, 32(R4) + MOVV R15, 40(R4) + MOVV R16, 48(R4) + MOVV R17, 56(R4) + ADDV $64, R5 + ADDV $64, R6 + ADDV $64, R4 + SUBV $64, R7 + // 64 in R9 + BGEU R7, R9, loop64 + BEQ R7, R0, end + +xor_32_check: + SRLV $1, R9 + BLT R7, R9, xor_16_check +xor_32: + MOVV (R5), R10 + MOVV 8(R5), R11 + MOVV 16(R5), R12 + MOVV 24(R5), R13 + MOVV (R6), R14 + MOVV 8(R6), R15 + MOVV 16(R6), R16 + MOVV 24(R6), R17 + XOR R10, R14 + XOR R11, R15 + XOR R12, R16 + XOR R13, R17 + MOVV R14, (R4) + MOVV R15, 8(R4) + MOVV R16, 16(R4) + MOVV R17, 24(R4) + ADDV $32, R5 + ADDV $32, R6 + ADDV $32, R4 + SUBV $32, R7 + BEQ R7, R0, end + +xor_16_check: + SRLV $1, R9 + BLT R7, R9, xor_8_check +xor_16: + MOVV (R5), R10 + MOVV 8(R5), R11 + MOVV (R6), R12 + MOVV 8(R6), R13 + XOR R10, R12 + XOR R11, R13 + MOVV R12, (R4) + MOVV R13, 8(R4) + ADDV $16, R5 + ADDV $16, R6 + ADDV $16, R4 + SUBV $16, R7 + BEQ R7, R0, end + +xor_8_check: + SRLV $1, R9 + BLT R7, R9, xor_4_check +xor_8: + MOVV (R5), R10 + MOVV (R6), R11 + XOR R10, R11 + MOVV R11, (R4) + ADDV $8, R5 + ADDV $8, R6 + ADDV $8, R4 + SUBV $8, R7 + BEQ R7, R0, end + +xor_4_check: + SRLV $1, R9 + BLT R7, R9, xor_2_check +xor_4: + MOVW (R5), R10 + MOVW (R6), R11 + XOR R10, R11 + MOVW R11, (R4) + ADDV $4, R5 + ADDV $4, R6 + ADDV $4, R4 + SUBV $4, R7 + BEQ R7, R0, end + +xor_2_check: + SRLV $1, R9 + BLT R7, R9, xor_1 +xor_2: + MOVH (R5), R10 + MOVH (R6), R11 + XOR R10, R11 + MOVH R11, (R4) + ADDV $2, R5 + ADDV $2, R6 + ADDV $2, R4 + SUBV $2, R7 + BEQ R7, R0, end + +xor_1: + MOVB (R5), R10 + MOVB (R6), R11 + XOR R10, R11 + MOVB R11, (R4) + +end: + RET diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_ppc64x.go b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_ppc64x.go new file mode 100644 index 0000000..2d8d355 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_ppc64x.go @@ -0,0 +1,10 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (ppc64 || ppc64le) && !purego + +package subtle + +//go:noescape +func xorBytes(dst, a, b *byte, n int) diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_ppc64x.s b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_ppc64x.s new file mode 100644 index 0000000..d54bc8b --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/subtle/xor_ppc64x.s @@ -0,0 +1,142 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (ppc64 || ppc64le) && !purego + +#include "textflag.h" + +// func xorBytes(dst, a, b *byte, n int) +TEXT ·xorBytes(SB), NOSPLIT, $0 + MOVD dst+0(FP), R3 // R3 = dst + MOVD a+8(FP), R4 // R4 = a + MOVD b+16(FP), R5 // R5 = b + MOVD n+24(FP), R6 // R6 = n + + CMPU R6, $64, CR7 // Check if n ≥ 64 bytes + MOVD R0, R8 // R8 = index + CMPU R6, $8, CR6 // Check if 8 ≤ n < 64 bytes + BLE CR6, small // <= 8 + BLT CR7, xor32 // Case for 32 ≤ n < 64 bytes + + // Case for n ≥ 64 bytes +preloop64: + SRD $6, R6, R7 // Set up loop counter + MOVD R7, CTR + MOVD $16, R10 + MOVD $32, R14 + MOVD $48, R15 + ANDCC $63, R6, R9 // Check for tailing bytes for later + PCALIGN $16 + // Case for >= 64 bytes + // Process 64 bytes per iteration + // Load 4 vectors of a and b + // XOR the corresponding vectors + // from a and b and store the result +loop64: + LXVD2X (R4)(R8), VS32 + LXVD2X (R4)(R10), VS34 + LXVD2X (R4)(R14), VS36 + LXVD2X (R4)(R15), VS38 + LXVD2X (R5)(R8), VS33 + LXVD2X (R5)(R10), VS35 + LXVD2X (R5)(R14), VS37 + LXVD2X (R5)(R15), VS39 + XXLXOR VS32, VS33, VS32 + XXLXOR VS34, VS35, VS34 + XXLXOR VS36, VS37, VS36 + XXLXOR VS38, VS39, VS38 + STXVD2X VS32, (R3)(R8) + STXVD2X VS34, (R3)(R10) + STXVD2X VS36, (R3)(R14) + STXVD2X VS38, (R3)(R15) + ADD $64, R8 + ADD $64, R10 + ADD $64, R14 + ADD $64, R15 + BDNZ loop64 + BC 12,2,LR // BEQLR + MOVD R9, R6 + CMP R6, $8 + BLE small + // Case for 8 <= n < 64 bytes + // Process 32 bytes if available +xor32: + CMP R6, $32 + BLT xor16 + ADD $16, R8, R9 + LXVD2X (R4)(R8), VS32 + LXVD2X (R4)(R9), VS33 + LXVD2X (R5)(R8), VS34 + LXVD2X (R5)(R9), VS35 + XXLXOR VS32, VS34, VS32 + XXLXOR VS33, VS35, VS33 + STXVD2X VS32, (R3)(R8) + STXVD2X VS33, (R3)(R9) + ADD $32, R8 + ADD $-32, R6 + CMP R6, $8 + BLE small + // Case for 8 <= n < 32 bytes + // Process 16 bytes if available +xor16: + CMP R6, $16 + BLT xor8 + LXVD2X (R4)(R8), VS32 + LXVD2X (R5)(R8), VS33 + XXLXOR VS32, VS33, VS32 + STXVD2X VS32, (R3)(R8) + ADD $16, R8 + ADD $-16, R6 +small: + CMP R6, $0 + BC 12,2,LR // BEQLR +xor8: +#ifdef GOPPC64_power10 + SLD $56,R6,R17 + ADD R4,R8,R18 + ADD R5,R8,R19 + ADD R3,R8,R20 + LXVL R18,R17,V0 + LXVL R19,R17,V1 + VXOR V0,V1,V1 + STXVL V1,R20,R17 + RET +#else + CMP R6, $8 + BLT xor4 + // Case for 8 ≤ n < 16 bytes + MOVD (R4)(R8), R14 // R14 = a[i,...,i+7] + MOVD (R5)(R8), R15 // R15 = b[i,...,i+7] + XOR R14, R15, R16 // R16 = a[] ^ b[] + SUB $8, R6 // n = n - 8 + MOVD R16, (R3)(R8) // Store to dst + ADD $8, R8 +xor4: + CMP R6, $4 + BLT xor2 + MOVWZ (R4)(R8), R14 + MOVWZ (R5)(R8), R15 + XOR R14, R15, R16 + MOVW R16, (R3)(R8) + ADD $4,R8 + ADD $-4,R6 +xor2: + CMP R6, $2 + BLT xor1 + MOVHZ (R4)(R8), R14 + MOVHZ (R5)(R8), R15 + XOR R14, R15, R16 + MOVH R16, (R3)(R8) + ADD $2,R8 + ADD $-2,R6 +xor1: + CMP R6, $0 + BC 12,2,LR // BEQLR + MOVBZ (R4)(R8), R14 // R14 = a[i] + MOVBZ (R5)(R8), R15 // R15 = b[i] + XOR R14, R15, R16 // R16 = a[i] ^ b[i] + MOVB R16, (R3)(R8) // Store to dst +#endif +done: + RET diff --git a/go/cm/sign/ed25519-blake2b/edwards25519/tables.go b/go/cm/sign/ed25519-blake2b/edwards25519/tables.go new file mode 100644 index 0000000..cdcc5d8 --- /dev/null +++ b/go/cm/sign/ed25519-blake2b/edwards25519/tables.go @@ -0,0 +1,129 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/edwards25519/subtle" +) + +// A dynamic lookup table for variable-base, constant-time scalar muls. +type projLookupTable struct { + points [8]projCached +} + +// A precomputed lookup table for fixed-base, constant-time scalar muls. +type affineLookupTable struct { + points [8]affineCached +} + +// A dynamic lookup table for variable-base, variable-time scalar muls. +type nafLookupTable5 struct { + points [8]projCached +} + +// A precomputed lookup table for fixed-base, variable-time scalar muls. +type nafLookupTable8 struct { + points [64]affineCached +} + +// Constructors. + +// Builds a lookup table at runtime. Fast. +func (v *projLookupTable) FromP3(q *Point) { + // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q + // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q + v.points[0].FromP3(q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + // Compute (i+1)*Q as Q + i*Q and convert to a projCached + // This is needlessly complicated because the API has explicit + // receivers instead of creating stack objects and relying on RVO + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(q, &v.points[i]))) + } +} + +// This is not optimised for speed; fixed-base tables should be precomputed. +func (v *affineLookupTable) FromP3(q *Point) { + // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q + // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q + v.points[0].FromP3(q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + // Compute (i+1)*Q as Q + i*Q and convert to affineCached + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(q, &v.points[i]))) + } +} + +// Builds a lookup table at runtime. Fast. +func (v *nafLookupTable5) FromP3(q *Point) { + // Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q + // This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q + v.points[0].FromP3(q) + q2 := Point{} + q2.Add(q, q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(&q2, &v.points[i]))) + } +} + +// This is not optimised for speed; fixed-base tables should be precomputed. +func (v *nafLookupTable8) FromP3(q *Point) { + v.points[0].FromP3(q) + q2 := Point{} + q2.Add(q, q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 63; i++ { + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(&q2, &v.points[i]))) + } +} + +// Selectors. + +// Set dest to x*Q, where -8 <= x <= 8, in constant time. +func (v *projLookupTable) SelectInto(dest *projCached, x int8) { + // Compute xabs = |x| + xmask := x >> 7 + xabs := uint8((x + xmask) ^ xmask) + + dest.Zero() + for j := 1; j <= 8; j++ { + // Set dest = j*Q if |x| = j + cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) + dest.Select(&v.points[j-1], dest, cond) + } + // Now dest = |x|*Q, conditionally negate to get x*Q + dest.CondNeg(int(xmask & 1)) +} + +// Set dest to x*Q, where -8 <= x <= 8, in constant time. +func (v *affineLookupTable) SelectInto(dest *affineCached, x int8) { + // Compute xabs = |x| + xmask := x >> 7 + xabs := uint8((x + xmask) ^ xmask) + + dest.Zero() + for j := 1; j <= 8; j++ { + // Set dest = j*Q if |x| = j + cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) + dest.Select(&v.points[j-1], dest, cond) + } + // Now dest = |x|*Q, conditionally negate to get x*Q + dest.CondNeg(int(xmask & 1)) +} + +// Given odd x with 0 < x < 2^4, return x*Q (in variable time). +func (v *nafLookupTable5) SelectInto(dest *projCached, x int8) { + *dest = v.points[x/2] +} + +// Given odd x with 0 < x < 2^7, return x*Q (in variable time). +func (v *nafLookupTable8) SelectInto(dest *affineCached, x int8) { + *dest = v.points[x/2] +} diff --git a/go/cm/ed25519-blake2b/kp.go b/go/cm/sign/ed25519-blake2b/kp.go similarity index 82% rename from go/cm/ed25519-blake2b/kp.go rename to go/cm/sign/ed25519-blake2b/kp.go index 7ec5892..e89b549 100644 --- a/go/cm/ed25519-blake2b/kp.go +++ b/go/cm/sign/ed25519-blake2b/kp.go @@ -16,20 +16,17 @@ package ed25519blake2b import ( - "crypto/rand" - - "go.cypherpunks.su/keks/cm/ed25519-blake2b/ed25519" + "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/ed25519" ) func NewKeypair() (signer *Signer, prv, pub []byte, err error) { - var prvEd ed25519.PrivateKey - var pubEd ed25519.PublicKey - pubEd, prvEd, err = ed25519.GenerateKey(rand.Reader) + var prvEd *ed25519.PrivateKey + prvEd, err = ed25519.GenerateKey() if err != nil { return } signer = &Signer{Prv: prvEd} prv = prvEd.Seed() - pub = pubEd[:] + pub = prvEd.PublicKey() return } diff --git a/go/cm/ed25519-blake2b/signer.go b/go/cm/sign/ed25519-blake2b/signer.go similarity index 70% rename from go/cm/ed25519-blake2b/signer.go rename to go/cm/sign/ed25519-blake2b/signer.go index 28acbdf..001ab45 100644 --- a/go/cm/ed25519-blake2b/signer.go +++ b/go/cm/sign/ed25519-blake2b/signer.go @@ -22,25 +22,25 @@ import ( "io" "runtime" - "go.cypherpunks.su/keks/cm/ed25519-blake2b/ed25519" + cmblake2b "go.cypherpunks.su/keks/cm/hash/blake2b" "go.cypherpunks.su/keks/cm/hash/merkle" + "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/ed25519" + "go.cypherpunks.su/keks/cm/sign/mode" "golang.org/x/crypto/blake2b" - - "go.cypherpunks.su/keks/cm/sign" ) type Signer struct { - Prv ed25519.PrivateKey - mode sign.Mode + Prv *ed25519.PrivateKey + mode mode.Mode prehasher *hash.Hash } -func (s *Signer) SetMode(m sign.Mode) error { +func (s *Signer) SetMode(m mode.Mode) error { switch m { - case sign.ModePure: + case mode.Pure: s.mode = m return nil - case sign.ModePrehash: + case mode.Prehash: s.mode = m h, err := blake2b.New512(nil) if err != nil { @@ -48,9 +48,9 @@ func (s *Signer) SetMode(m sign.Mode) error { } s.prehasher = &h return nil - case sign.ModeMerkle: + case mode.Merkle: s.mode = m - h := NewMerkleHasher(merkle.DefaultChunkLen, runtime.NumCPU()) + h := cmblake2b.NewMerkleHasher(merkle.DefaultChunkLen, runtime.NumCPU()) s.prehasher = &h return nil default: @@ -58,24 +58,24 @@ func (s *Signer) SetMode(m sign.Mode) error { } } -func (s *Signer) Mode() sign.Mode { +func (s *Signer) Mode() mode.Mode { return s.mode } func (s *Signer) Algo() string { switch s.mode { - case sign.ModePure: + case mode.Pure: return Ed25519BLAKE2b - case sign.ModePrehash: + case mode.Prehash: return Ed25519PhBLAKE2b - case sign.ModeMerkle: + case mode.Merkle: return Ed25519PhBLAKE2bMerkle } return "" } func (s *Signer) Public() crypto.PublicKey { - return s.Prv.Public() + return s.Prv.PublicKey() } func (s *Signer) Sign( @@ -84,10 +84,10 @@ func (s *Signer) Sign( opts crypto.SignerOpts, ) (signature []byte, err error) { switch s.mode { - case sign.ModePure: - return s.Prv.Sign(rand, msg, opts) - case sign.ModePrehash, sign.ModeMerkle: - return s.Prv.Sign(rand, msg, &ed25519.Options{Hash: crypto.BLAKE2b_512}) + case mode.Pure: + return ed25519.Sign(s.Prv, msg), nil + case mode.Prehash, mode.Merkle: + return ed25519.SignPH(s.Prv, msg, "") default: panic("unsupported mode") } @@ -98,12 +98,16 @@ func (s *Signer) Prehasher() *hash.Hash { } func NewSigner(v []byte) (prv *Signer, pub []byte, err error) { - if len(v) != ed25519.SeedSize { + if len(v) != 32 { err = errors.New("wrong ed25519 private key size") return } - p := ed25519.NewKeyFromSeed(v) - pub = p[ed25519.SeedSize:] + var p *ed25519.PrivateKey + p, err = ed25519.NewPrivateKeyFromSeed(v) + if err != nil { + return + } + pub = p.PublicKey() prv = &Signer{Prv: p} return } diff --git a/go/cm/ed25519-blake2b/verify.go b/go/cm/sign/ed25519-blake2b/verify.go similarity index 69% rename from go/cm/ed25519-blake2b/verify.go rename to go/cm/sign/ed25519-blake2b/verify.go index f80d501..dfa4264 100644 --- a/go/cm/ed25519-blake2b/verify.go +++ b/go/cm/sign/ed25519-blake2b/verify.go @@ -16,39 +16,35 @@ package ed25519blake2b import ( - "crypto" "errors" - "go.cypherpunks.su/keks/cm/ed25519-blake2b/ed25519" + "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b/ed25519" ) func Verify(pub, signed, signature []byte) (valid bool, err error) { - if len(pub) != ed25519.PublicKeySize { + if len(pub) != 32 { err = errors.New("invalid ed25519 public key size") return } - valid = ed25519.Verify(ed25519.PublicKey(pub), signed, signature) + var pk *ed25519.PublicKey + pk, err = ed25519.NewPublicKey(pub) + if err != nil { + return + } + valid = ed25519.Verify(pk, signed, signature) == nil return } func VerifyPrehash(pub, hsh, signature []byte) (valid bool, err error) { - if len(pub) != ed25519.PublicKeySize { + if len(pub) != 32 { err = errors.New("invalid ed25519 public key size") return } - err = ed25519.VerifyWithOptions( - ed25519.PublicKey(pub), - hsh, - signature, - &ed25519.Options{Hash: crypto.BLAKE2b_512}, - ) - if err == nil { - valid = true - } else { - if err.Error() == "ed25519: invalid signature" { - valid = false - err = nil - } + var pk *ed25519.PublicKey + pk, err = ed25519.NewPublicKey(pub) + if err != nil { + return } + valid = ed25519.VerifyPH(pk, hsh, signature, "") == nil return } diff --git a/go/cm/gost/gost.go b/go/cm/sign/gost/gost.go similarity index 86% rename from go/cm/gost/gost.go rename to go/cm/sign/gost/gost.go index 71487d2..8c67bd0 100644 --- a/go/cm/gost/gost.go +++ b/go/cm/sign/gost/gost.go @@ -20,8 +20,10 @@ import ( ) const ( - GOST3410256A = "gost3410-256A" - GOST3410512C = "gost3410-512C" + GOST3410256A = "gost3410-256A" + GOST3410512C = "gost3410-512C" + GOST3410256AMerkle = "gost3410-256A-merkle" + GOST3410512CMerkle = "gost3410-512C-merkle" ) func CurveByName(name string) (curve *gost3410.Curve) { diff --git a/go/cm/gost/kp.go b/go/cm/sign/gost/kp.go similarity index 100% rename from go/cm/gost/kp.go rename to go/cm/sign/gost/kp.go diff --git a/go/cm/gost/signer.go b/go/cm/sign/gost/signer.go similarity index 86% rename from go/cm/gost/signer.go rename to go/cm/sign/gost/signer.go index 785e248..99a3a3e 100644 --- a/go/cm/gost/signer.go +++ b/go/cm/sign/gost/signer.go @@ -26,30 +26,31 @@ import ( "go.cypherpunks.su/gogost/v6/gost34112012256" "go.cypherpunks.su/gogost/v6/gost34112012512" + hashgost "go.cypherpunks.su/keks/cm/hash/gost" "go.cypherpunks.su/keks/cm/hash/merkle" - "go.cypherpunks.su/keks/cm/sign" + "go.cypherpunks.su/keks/cm/sign/mode" ) type Signer struct { NewHasher func() hash.Hash Prv *gost3410.PrivateKey prehasher *hash.Hash - mode sign.Mode + mode mode.Mode } -func (s *Signer) SetMode(m sign.Mode) error { +func (s *Signer) SetMode(m mode.Mode) error { switch m { - case sign.ModePure: + case mode.Pure: s.mode = m return nil - case sign.ModePrehash: + case mode.Prehash: s.mode = m p := s.NewHasher() s.prehasher = &p return nil - case sign.ModeMerkle: + case mode.Merkle: s.mode = m - p := NewMerkleHasher(s.NewHasher, merkle.DefaultChunkLen, runtime.NumCPU()) + p := hashgost.NewMerkleHasher(s.NewHasher, merkle.DefaultChunkLen, runtime.NumCPU()) s.prehasher = &p return nil default: @@ -57,7 +58,7 @@ func (s *Signer) SetMode(m sign.Mode) error { } } -func (s *Signer) Mode() sign.Mode { +func (s *Signer) Mode() mode.Mode { return s.mode } @@ -68,12 +69,12 @@ func (s *Signer) Prehasher() *hash.Hash { func (s *Signer) Algo() string { switch s.Prv.C.PointSize() { case 32: - if s.mode == sign.ModeMerkle { + if s.mode == mode.Merkle { return GOST3410256AMerkle } return GOST3410256A case 64: - if s.mode == sign.ModeMerkle { + if s.mode == mode.Merkle { return GOST3410512CMerkle } return GOST3410512C @@ -93,11 +94,11 @@ func (s *Signer) Sign( ) (signature []byte, err error) { var hsh []byte switch s.mode { - case sign.ModePure: + case mode.Pure: h := s.NewHasher() h.Write(msg) hsh = h.Sum(nil) - case sign.ModePrehash, sign.ModeMerkle: + case mode.Prehash, mode.Merkle: hsh = msg default: panic("unsupported mode") diff --git a/go/cm/gost/verify.go b/go/cm/sign/gost/verify.go similarity index 94% rename from go/cm/gost/verify.go rename to go/cm/sign/gost/verify.go index f09ec74..1ca490a 100644 --- a/go/cm/gost/verify.go +++ b/go/cm/sign/gost/verify.go @@ -16,12 +16,13 @@ package gost import ( + "bytes" "hash" + "io" "go.cypherpunks.su/gogost/v6/gost3410" "go.cypherpunks.su/gogost/v6/gost34112012256" "go.cypherpunks.su/gogost/v6/gost34112012512" - "go.cypherpunks.su/keks/cm/utils" ) func Verify(algo string, pub, signed, signature []byte) (valid bool, err error) { @@ -37,7 +38,10 @@ func Verify(algo string, pub, signed, signature []byte) (valid bool, err error) case GOST3410512C: hasher = gost34112012512.New() } - utils.MustWrite(hasher, signed) + _, err = io.Copy(hasher, bytes.NewReader(signed)) + if err != nil { + return + } hsh := hasher.Sum(nil) valid, err = pk.VerifyDigest(hsh, append(signature[len(signature)/2:], signature[:len(signature)/2]...)) diff --git a/go/cm/sign/iface.go b/go/cm/sign/iface.go index b8b5ca1..a641bd2 100644 --- a/go/cm/sign/iface.go +++ b/go/cm/sign/iface.go @@ -3,12 +3,14 @@ package sign import ( "crypto" "hash" + + "go.cypherpunks.su/keks/cm/sign/mode" ) type Iface interface { crypto.Signer - SetMode(Mode) error + SetMode(mode.Mode) error Prehasher() *hash.Hash Algo() string - Mode() Mode + Mode() mode.Mode } diff --git a/go/cm/sign/mode.go b/go/cm/sign/mode.go deleted file mode 100644 index db6b94d..0000000 --- a/go/cm/sign/mode.go +++ /dev/null @@ -1,11 +0,0 @@ -package sign - -type Mode int - -const ( - ModePure Mode = 0 - ModePrehash = iota - ModeMerkle = iota - - PrehashT = "prehash" -) diff --git a/go/cm/sign/mode/mode.go b/go/cm/sign/mode/mode.go new file mode 100644 index 0000000..9c95af8 --- /dev/null +++ b/go/cm/sign/mode/mode.go @@ -0,0 +1,11 @@ +package mode + +type Mode int + +const ( + Pure Mode = 0 + Prehash = iota + Merkle = iota + + PrehashT = "prehash" +) diff --git a/go/cm/prv.go b/go/cm/sign/prv.go similarity index 80% rename from go/cm/prv.go rename to go/cm/sign/prv.go index 64ca636..e18331c 100644 --- a/go/cm/prv.go +++ b/go/cm/sign/prv.go @@ -13,20 +13,22 @@ // You should have received a copy of the GNU Lesser General Public // License along with this program. If not, see . -package cm +package sign import ( "errors" "fmt" "go.cypherpunks.su/keks" - ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b" - "go.cypherpunks.su/keks/cm/gost" - "go.cypherpunks.su/keks/cm/sign" + "go.cypherpunks.su/keks/cm" + ed25519blake2b "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b" + "go.cypherpunks.su/keks/cm/sign/gost" ) +const PrvMagic = keks.Magic("cm/prv") + // Parse private key contained in AV KEKS-encoded structure. -func PrvParse(data []byte) (prv sign.Iface, pub []byte, err error) { +func PrvParse(data []byte) (prv Iface, pub []byte, err error) { { var magic keks.Magic magic, data = keks.StripMagic(data) @@ -36,7 +38,7 @@ func PrvParse(data []byte) (prv sign.Iface, pub []byte, err error) { } } d := keks.NewDecoderFromBytes(data, &keks.DecodeOpts{MaxStrLen: 1 << 16}) - var av AV + var av cm.AV if err = d.DecodeStruct(&av); err != nil { return } @@ -45,9 +47,9 @@ func PrvParse(data []byte) (prv sign.Iface, pub []byte, err error) { return } switch av.A { - case Ed25519BLAKE2b: + case ed25519blake2b.Ed25519BLAKE2b: prv, pub, err = ed25519blake2b.NewSigner(av.V) - case GOST3410256A, GOST3410512C: + case gost.GOST3410256A, gost.GOST3410512C: prv, pub, err = gost.NewSigner(av.V) default: err = fmt.Errorf("unknown private key algo: %s", av.A) diff --git a/go/cm/pub.go b/go/cm/sign/pub.go similarity index 93% rename from go/cm/pub.go rename to go/cm/sign/pub.go index f2e11af..4b8a89b 100644 --- a/go/cm/pub.go +++ b/go/cm/sign/pub.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Lesser General Public // License along with this program. If not, see . -package cm +package sign import ( "bytes" @@ -25,9 +25,8 @@ import ( "github.com/google/uuid" "go.cypherpunks.su/keks" - ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b" - "go.cypherpunks.su/keks/cm/gost" - "go.cypherpunks.su/keks/cm/sign" + ed25519blake2b "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b" + "go.cypherpunks.su/keks/cm/sign/gost" ) const ( @@ -150,7 +149,7 @@ func (pub *PubLoad) Can(ku string) (yes bool) { // generated UUIDv7. since and till times must not have nanoseconds part. func (signed *Signed) CertifyWith( parent *PubLoad, - prv sign.Iface, + prv Iface, since, till time.Time, ) error { exp := []time.Time{since, till} @@ -171,15 +170,15 @@ func (pub *PubLoad) CheckSignature(algo string, signed, signature []byte) (err e key := pub.Pub[0] var valid bool switch key.A { - case Ed25519BLAKE2b: - if algo != Ed25519BLAKE2b { + case ed25519blake2b.Ed25519BLAKE2b: + if algo != ed25519blake2b.Ed25519BLAKE2b { return ErrBadSigAlgo } valid, err = ed25519blake2b.Verify(key.V, signed, signature) if !valid { err = ErrSigInvalid } - case GOST3410256A, GOST3410512C: + case gost.GOST3410256A, gost.GOST3410512C: if algo != key.A { return ErrBadSigAlgo } @@ -206,10 +205,10 @@ func (pub *PubLoad) CheckSignaturePrehash( key := pub.Pub[0] var valid bool switch key.A { - case Ed25519BLAKE2b: + case ed25519blake2b.Ed25519BLAKE2b: switch algo { - case Ed25519PhBLAKE2b: - case Ed25519PhBLAKE2bMerkle: + case ed25519blake2b.Ed25519PhBLAKE2b: + case ed25519blake2b.Ed25519PhBLAKE2bMerkle: default: return ErrBadSigAlgo } @@ -217,12 +216,12 @@ func (pub *PubLoad) CheckSignaturePrehash( if !valid { err = ErrSigInvalid } - case GOST3410256A, GOST3410512C: + case gost.GOST3410256A, gost.GOST3410512C: switch algo { - case GOST3410256A: - case GOST3410256AMerkle: - case GOST3410512C: - case GOST3410512CMerkle: + case gost.GOST3410256A: + case gost.GOST3410256AMerkle: + case gost.GOST3410512C: + case gost.GOST3410512CMerkle: default: return ErrBadSigAlgo } diff --git a/go/cm/signed.go b/go/cm/sign/signed.go similarity index 94% rename from go/cm/signed.go rename to go/cm/sign/signed.go index 7a67fb6..18dc57b 100644 --- a/go/cm/signed.go +++ b/go/cm/sign/signed.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Lesser General Public // License along with this program. If not, see . -package cm +package sign import ( "bytes" @@ -25,7 +25,8 @@ import ( "github.com/google/uuid" "go.cypherpunks.su/keks" - "go.cypherpunks.su/keks/cm/sign" + "go.cypherpunks.su/keks/cm" + "go.cypherpunks.su/keks/cm/sign/mode" ) const SignedMagic = keks.Magic("cm/signed") @@ -51,7 +52,7 @@ type SigTBS struct { type Sig struct { TBS SigTBS `keks:"tbs"` PubLoc *[]string `keks:"pub-loc,omitempty"` - Sign AV `keks:"sign"` + Sign cm.AV `keks:"sign"` } type Signed struct { @@ -118,13 +119,13 @@ func SignedParse(data []byte) (*Signed, error) { // Sign Signed's contents and sigTBS corresponding data with the // provided prv signer, having parent certififer. Signature is appended // to the signed.Sigs. parent must have "sig" key-usage. -func (signed *Signed) SignWith(parent *PubLoad, prv sign.Iface, sigTBS SigTBS) (err error) { +func (signed *Signed) SignWith(parent *PubLoad, prv Iface, sigTBS SigTBS) (err error) { if !parent.Can(KUSig) || len(parent.Pub) != 1 { return errors.New("parent can not sign") } sigTBS.SID = parent.Pub[0].Id var tbs []byte - if prv.Mode() == sign.ModePure { + if prv.Mode() == mode.Pure { var b bytes.Buffer if _, err = keks.Encode(&b, signed.Load, nil); err != nil { return diff --git a/go/cm/sntrup4591761-x25519/go.mod b/go/cm/sntrup4591761-x25519/go.mod deleted file mode 100644 index 4706ebb..0000000 --- a/go/cm/sntrup4591761-x25519/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module go.cypherpunks.su/keks/cm/sntrup4591761-x25519 - -go 1.24 - -require github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a diff --git a/go/cm/sntrup4591761-x25519/go.sum b/go/cm/sntrup4591761-x25519/go.sum deleted file mode 100644 index 18a1c89..0000000 --- a/go/cm/sntrup4591761-x25519/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a h1:clYxJ3Os0EQUKDDVU8M0oipllX0EkuFNBfhVQuIfyF0= -github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a/go.mod h1:z/9Ck1EDixEbBbZ2KH2qNHekEmDLTOZ+FyoIPWWSVOI= diff --git a/go/cm/utils/utils.go b/go/cm/utils/utils.go deleted file mode 100644 index c4bec88..0000000 --- a/go/cm/utils/utils.go +++ /dev/null @@ -1,40 +0,0 @@ -// GoKEKS/CM -- KEKS-encoded cryptographic messages -// Copyright (C) 2024-2025 Sergey Matveev -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, version 3 of the License. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this program. If not, see . - -package utils - -import ( - "fmt" - "io" - "os" -) - -func MustWrite(w io.Writer, data []byte) { - n, err := w.Write(data) - if err != nil { - panic(err) - } - if n != len(data) { - panic("not full write") - } -} - -func MustReadFile(p string) []byte { - data, err := os.ReadFile(p) - if err != nil { - panic(fmt.Errorf("read %s: %v", p, err)) - } - return data -} diff --git a/go/go.mod b/go/go.mod index 540eec2..8240e2d 100644 --- a/go/go.mod +++ b/go/go.mod @@ -2,12 +2,11 @@ module go.cypherpunks.su/keks go 1.24 -require go.cypherpunks.su/tai64n/v4 v4.1.0 - require ( github.com/google/uuid v1.6.0 github.com/mitchellh/mapstructure v1.5.0 - golang.org/x/term v0.27.0 + go.cypherpunks.su/tai64n/v4 v4.1.0 + golang.org/x/term v0.28.0 ) -require golang.org/x/sys v0.28.0 // indirect +require golang.org/x/sys v0.29.0 // indirect diff --git a/go/go.sum b/go/go.sum index 6790579..268b767 100644 --- a/go/go.sum +++ b/go/go.sum @@ -4,7 +4,7 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= go.cypherpunks.su/tai64n/v4 v4.1.0 h1:jW0EyklKXpSy9DSFMcDbu7XuLlMkn6kkpNWiMG6UT5c= go.cypherpunks.su/tai64n/v4 v4.1.0/go.mod h1:/uKUdhLOy8UciRKpapPaFXSOoa/SiXjs3XsDDpAz7OA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= -- 2.48.1