+++ /dev/null
-// GoKEKS/CM -- KEKS-encoded cryptographic messages
-// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
-//
-// 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 <http://www.gnu.org/licenses/>.
-
-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")
-)
-// GoKEKS/CM -- KEKS-encoded cryptographic messages
-// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
-//
-// 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 <http://www.gnu.org/licenses/>.
-
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
-}
"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"
"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"
)
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)
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
}
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 {
})
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
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")
}
}
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 {
}
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
}
cek = cekp
}
- case cm.SNTRUP4591761X25519HKDFBLAKE2b:
+ case sntrup4591761x25519.SNTRUP4591761X25519HKDFBLAKE2b:
if len(prvs) == 0 {
log.Println(kemIdx, kem.A, "skipping because no -prv")
continue
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 {
break
}
}
- case cm.ClassicMcEliece6960119X25519HKDFSHAKE256:
+ case mceliece6960119x25519.ClassicMcEliece6960119X25519HKDFSHAKE256:
if len(prvs) == 0 {
log.Println(kemIdx, kem.A, "skipping because no -prv")
continue
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 {
}
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)
}
log.Fatal(err)
}
kem := cmenc.KEM{
- A: cm.BalloonBLAKE2bHKDF,
+ A: cmenc.BalloonBLAKE2bHKDF,
Salt: &bSalt,
Cost: &cmenc.BalloonCost{
S: uint64(*balloonS),
}
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")
}
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
{
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 {
}
var ciphertext []byte
var keyMcEliece []byte
- ciphertext, keyMcEliece, err = scheme.Encapsulate(theirMcEliece)
+ ciphertext, keyMcEliece, err = mceliece6960119.Encapsulate(theirMcEliece)
if err != nil {
log.Fatal(err)
}
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
{
}
{
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)
}
"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"
)
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:
"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{})
"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")
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 {
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)
}
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)
}
}
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)
}
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")
}
{
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 {
}
}
{
- 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
{
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 {
{
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 {
"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
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)
}
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")
}
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 {
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 {
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)
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
+++ /dev/null
-byteorder/
-ed25519/
-edwards25519/
-go.mod
+++ /dev/null
-#!/bin/sh -e
-
-cd "$(dirname "$(realpath -- "$0")")"
-exec rm -rf byteorder ed25519 edwards25519 go.mod
+++ /dev/null
---- 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 {
+++ /dev/null
-#!/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 <ed25519-to-blake2b.patch
--- /dev/null
+package encrypted
+
+const (
+ BalloonBLAKE2bHKDF = "balloon-blake2b-hkdf"
+ ChaCha20Poly1305 = "chacha20poly1305"
+)
--- /dev/null
+package encrypted
+
+import "go.cypherpunks.su/keks"
+
+const Magic = keks.Magic("cm/encrypted")
--- /dev/null
+Go/Git is unable to fetch (https://github.com/cloudflare/circl.git)
+pull-request's commit (7dfc396c96830ed3601ace705e1612b9bcc447f9) to
+github.com/cloudflare/circl containing mceliece6960119 implementation
+(https://github.com/cloudflare/circl/pull/378). So copy it here.
"crypto/ecdh"
"crypto/rand"
- "github.com/cloudflare/circl/kem"
- "github.com/cloudflare/circl/kem/mceliece/mceliece6960119"
+ "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119"
)
func NewKeypair() (prv, pub []byte, err error) {
- var pubMcEliece kem.PublicKey
- var prvMcEliece kem.PrivateKey
- scheme := mceliece6960119.Scheme()
- pubMcEliece, prvMcEliece, err = scheme.GenerateKeyPair()
+ var pubMcEliece *mceliece6960119.PublicKey
+ var prvMcEliece *mceliece6960119.PrivateKey
+ pubMcEliece, prvMcEliece, err = mceliece6960119.GenerateKeyPair()
if err != nil {
return
}
--- /dev/null
+// Code generated from benes_other.templ.go. DO NOT EDIT.
+
+package mceliece6960119
+
+// Layers of the Beneš network. The required size of `data` and `bits` depends on the value `lgs`.
+func layerIn(data *[2][64]uint64, bits *[64]uint64, lgs int) {
+ s := 1 << lgs
+ index := 0
+ for i := 0; i < 64; i += s * 2 {
+ for j := i; j < i+s; j++ {
+ d := data[0][j+0] ^ data[0][j+s]
+ d &= bits[index]
+ data[0][j+0] ^= d
+ data[0][j+s] ^= d
+ index += 1
+
+ d = data[1][j+0] ^ data[1][j+s]
+ d &= bits[index]
+ data[1][j+0] ^= d
+ data[1][j+s] ^= d
+ index += 1
+ }
+ }
+}
+
+// Exterior layers of the Beneš network. The length of `bits` depends on the value of `lgs`.
+// Note that this implementation is quite different from the C implementation.
+// However, it does make sense. Whereas the C implementation uses pointer arithmetic to access
+// the entire array `data`, this implementation always considers `data` as two-dimensional array.
+// The C implementation uses 128 as upper bound (because the array contains 128 elements),
+// but this implementation has 64 elements per subarray and needs case distinctions at different places.
+func layerEx(data *[2][64]uint64, bits *[64]uint64, lgs int) {
+ data0Idx := 0
+ data1Idx := 32
+ s := 1 << lgs
+ if s == 64 {
+ for j := 0; j < 64; j++ {
+ d := data[0][j+0] ^ data[1][j]
+ d &= bits[data0Idx]
+ data0Idx += 1
+ data[0][j+0] ^= d
+ data[1][j] ^= d
+ }
+ } else {
+ for i := 0; i < 64; i += s * 2 {
+ for j := i; j < i+s; j++ {
+ d := data[0][j+0] ^ data[0][j+s]
+ d &= bits[data0Idx]
+ data0Idx += 1
+
+ data[0][j+0] ^= d
+ data[0][j+s] ^= d
+
+ // data[1] computations
+ d = data[1][j+0] ^ data[1][j+s]
+ d &= bits[data1Idx]
+ data1Idx += 1
+
+ data[1][j+0] ^= d
+ data[1][j+s] ^= d
+ }
+ }
+ }
+}
+
+// Apply Beneš network in-place to array `r` based on configuration `bits`.
+// Here, `r` is a sequence of bits to be permuted.
+// `bits` defines the condition bits configuring the Beneš network and
+// Note that this differs from the C implementation, missing the `rev` parameter.
+// This is because `rev` is not used throughout the entire codebase.
+func applyBenes(r *[1024]byte, bits *[condBytes]byte) {
+ rIntV := [2][64]uint64{}
+ rIntH := [2][64]uint64{}
+ bIntV := [64]uint64{}
+ bIntH := [64]uint64{}
+ bitsPtr := bits[:]
+
+ for i := 0; i < 64; i++ {
+ rIntV[0][i] = load8(r[i*16:])
+ rIntV[1][i] = load8(r[i*16+8:])
+ }
+
+ transpose64x64(&rIntH[0], &rIntV[0])
+ transpose64x64(&rIntH[1], &rIntV[1])
+
+ for iter := 0; iter <= 6; 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 iter := 0; iter <= 5; iter++ {
+ for i := 0; i < 64; i++ {
+ bIntV[i] = load8(bitsPtr)
+ bitsPtr = bitsPtr[8:]
+ }
+ layerIn(&rIntV, &bIntV, iter)
+ }
+
+ for iter := 4; iter >= 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])
+ }
+}
--- /dev/null
+// 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
+ }
+}
--- /dev/null
+// 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
+ }
+ }
+}
--- /dev/null
+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
+ }
+ }
+ }
+ }
+}
--- /dev/null
+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,
+ },
+}
--- /dev/null
+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,
+ },
+}
--- /dev/null
+// 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)
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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<<gfBits)*4
+ seedIndex = sysN/8 + (1<<gfBits)*4 + sysT*2
+ permIndex = sysN / 8
+ sBase = 32 + 8 + irrBytes + condBytes
+ )
+
+ var (
+ pk [PublicKeySize]byte
+ sk [PrivateKeySize]byte
+ )
+
+ seed := [33]byte{64}
+ r := [sysN/8 + (1<<gfBits)*4 + sysT*2 + 32]byte{}
+
+ f := [sysT]gf{}
+ irr := [sysT]gf{}
+ perm := [1 << gfBits]uint32{}
+ pi := [1 << gfBits]int16{}
+ pivots := uint64(0xFFFFFFFF)
+
+ copy(seed[1:], entropy[:])
+
+ for {
+ // expanding and updating the seed
+ err := shake256(r[:], seed[0:33])
+ if err != nil {
+ panic(err)
+ }
+
+ copy(sk[:32], seed[1:])
+ copy(seed[1:], r[len(r)-32:])
+
+ temp := r[irrPolys:seedIndex]
+ for i := 0; i < sysT; i++ {
+ f[i] = loadGf(temp)
+ temp = temp[2:]
+ }
+
+ if !minimalPolynomial(&irr, &f) {
+ continue
+ }
+
+ temp = sk[40 : 40+irrBytes]
+ for i := 0; i < sysT; i++ {
+ storeGf(temp, irr[i])
+ temp = temp[2:]
+ }
+
+ // generating permutation
+ temp = r[permIndex:irrPolys]
+ for i := 0; i < 1<<gfBits; i++ {
+ perm[i] = load4(temp)
+ temp = temp[4:]
+ }
+
+ if !pkGen(&pk, sk[40:40+irrBytes], &perm, &pi, &pivots) {
+ continue
+ }
+
+ internal.ControlBitsFromPermutation(sk[32+8+irrBytes:], pi[:], gfBits, 1<<gfBits)
+ copy(sk[sBase:sBase+sysN/8], r[0:sysN/8])
+ store8(sk[32:40], pivots)
+ return &PublicKey{pk: pk}, &PrivateKey{sk: sk}
+ }
+}
+
+// Encryption routine.
+// Takes a public key `pk` to compute error vector `e` and syndrome `s`.
+func encrypt(s *[CiphertextSize]byte, pk *[PublicKeySize]byte, e *[sysN / 8]byte, rand randFunc) error {
+ err := genE(e, rand)
+ if err != nil {
+ return err
+ }
+ syndrome(s, pk, e)
+ return nil
+}
+
+// KEM Encapsulation.
+//
+// Given a public key `pk`, sample a shared key.
+// This shared key is returned through parameter `key` whereas
+// the ciphertext (meant to be used for decapsulation) is returned as `c`.
+func kemEncapsulate(c *[CiphertextSize]byte, key *[SharedKeySize]byte, pk *[PublicKeySize]byte, rand randFunc) error {
+ e := [sysN / 8]byte{}
+ oneEC := [1 + sysN/8 + syndBytes]byte{1}
+
+ paddingOk := checkPkPadding(pk)
+
+ err := encrypt(c, pk, &e, rand)
+ if err != nil {
+ return err
+ }
+ copy(oneEC[1:1+sysN/8], e[:sysN/8])
+ copy(oneEC[1+sysN/8:1+sysN/8+syndBytes], c[:syndBytes])
+ err = shake256(key[0:32], oneEC[:])
+ if err != nil {
+ return err
+ }
+
+ mask := paddingOk ^ 0xFF
+ for i := 0; i < syndBytes; i++ {
+ c[i] &= mask
+ }
+ for i := 0; i < 32; i++ {
+ key[i] &= mask
+ }
+
+ if paddingOk == 0 {
+ return nil
+ }
+ return fmt.Errorf("public key padding error %d", paddingOk)
+}
+
+// KEM Decapsulation.
+//
+// Given a secret key `sk` and a ciphertext `c`,
+// determine the shared text `key` negotiated by both parties.
+func kemDecapsulate(key *[SharedKeySize]byte, c *[CiphertextSize]byte, sk *[PrivateKeySize]byte) error {
+ e := [sysN / 8]byte{}
+ preimage := [1 + sysN/8 + syndBytes]byte{}
+ s := sk[40+irrBytes+condBytes:]
+
+ paddingOk := checkCPadding(c)
+
+ retDecrypt := decrypt((*[sysN / 8]byte)(e[:sysN/8]), sk[40:], (*[syndBytes]byte)(c[:syndBytes]))
+ m := retDecrypt
+ m -= 1
+ m >>= 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. <http://crypto.stanford.edu/~mironov/cs359/massey.pdf>
+// 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
+}
--- /dev/null
+// 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)
+ }
+}
--- /dev/null
+// 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<<gfBits)
+
+ for i := 1; i < (1 << gfBits); i++ {
+ if (list[i-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
+}
--- /dev/null
+// 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)
+}
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 => ../
+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=
"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"
)
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)
--- /dev/null
+package gost
+
+const (
+ GOST3410256A = "gost3410-256A"
+ GOST3410512C = "gost3410-512C"
+ GOST3410256AMerkle = "gost3410-256A-merkle"
+ GOST3410512CMerkle = "gost3410-512C-merkle"
+)
"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)
}
--- /dev/null
+package hash
+
+import "go.cypherpunks.su/keks"
+
+const Magic = keks.Magic("cm/hashed")
+++ /dev/null
-https://github.com/cloudflare/circl/pull/378
-https://github.com/cloudflare/circl.git
-7dfc396c96830ed3601ace705e1612b9bcc447f9
--- /dev/null
+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.
--- /dev/null
+package ed25519blake2b
+
+const (
+ Ed25519BLAKE2b = "ed25519-blake2b"
+ Ed25519PhBLAKE2b = "ed25519ph-blake2b"
+ Ed25519PhBLAKE2bMerkle = "ed25519ph-blake2b-merkle"
+)
--- /dev/null
+// 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
+}
--- /dev/null
+// 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)
+}
--- /dev/null
+// 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),
+ )
+}
--- /dev/null
+// 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
--- /dev/null
+// 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
+}
--- /dev/null
+// 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
+}
--- /dev/null
+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
+)
--- /dev/null
+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=
--- /dev/null
+// 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<<uint(bitsOffset%8))
+ for i, bb := range buf {
+ off := bitsOffset/8 + i
+ if off >= 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
+}
--- /dev/null
+// 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)
--- /dev/null
+// 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
--- /dev/null
+// 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) }
--- /dev/null
+// 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
+}
--- /dev/null
+// 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
--- /dev/null
+// 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()
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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)
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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)
--- /dev/null
+// 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
--- /dev/null
+// 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)
--- /dev/null
+// 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
--- /dev/null
+// 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]
+ }
+}
--- /dev/null
+// 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)
--- /dev/null
+// 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
--- /dev/null
+// 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)
--- /dev/null
+// 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
--- /dev/null
+// 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]
+}
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
}
"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 {
}
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:
}
}
-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(
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")
}
}
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
}
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
}
)
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) {
"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:
}
}
-func (s *Signer) Mode() sign.Mode {
+func (s *Signer) Mode() mode.Mode {
return s.mode
}
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
) (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")
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) {
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]...))
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
}
+++ /dev/null
-package sign
-
-type Mode int
-
-const (
- ModePure Mode = 0
- ModePrehash = iota
- ModeMerkle = iota
-
- PrehashT = "prehash"
-)
--- /dev/null
+package mode
+
+type Mode int
+
+const (
+ Pure Mode = 0
+ Prehash = iota
+ Merkle = iota
+
+ PrehashT = "prehash"
+)
// You should have received a copy of the GNU Lesser General Public
// License along with this program. If not, see <http://www.gnu.org/licenses/>.
-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)
}
}
d := keks.NewDecoderFromBytes(data, &keks.DecodeOpts{MaxStrLen: 1 << 16})
- var av AV
+ var av cm.AV
if err = d.DecodeStruct(&av); err != nil {
return
}
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)
// You should have received a copy of the GNU Lesser General Public
// License along with this program. If not, see <http://www.gnu.org/licenses/>.
-package cm
+package sign
import (
"bytes"
"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 (
// 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}
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
}
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
}
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
}
// You should have received a copy of the GNU Lesser General Public
// License along with this program. If not, see <http://www.gnu.org/licenses/>.
-package cm
+package sign
import (
"bytes"
"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")
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 {
// 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
+++ /dev/null
-module go.cypherpunks.su/keks/cm/sntrup4591761-x25519
-
-go 1.24
-
-require github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a
+++ /dev/null
-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=
+++ /dev/null
-// GoKEKS/CM -- KEKS-encoded cryptographic messages
-// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
-//
-// 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 <http://www.gnu.org/licenses/>.
-
-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
-}
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
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=