From: Sergey Matveev Date: Wed, 16 Jul 2025 14:25:33 +0000 (+0300) Subject: Post-quantum handshake authentication X-Git-Tag: v5.0.0 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=a1ce20f6167d66b74c1322de8ddb3657045988cec4fc9a8c38d4604ed5d020cf;p=vors.git Post-quantum handshake authentication --- diff --git a/cmd/client/audio.go b/cmd/client/audio.go index 44031a0..57b3a9c 100644 --- a/cmd/client/audio.go +++ b/cmd/client/audio.go @@ -19,7 +19,7 @@ import ( "log" "go.stargrave.org/opus/v2" - vors "go.stargrave.org/vors/v4/internal" + vors "go.stargrave.org/vors/v5/internal" ) func newOpusEnc() *opus.Encoder { @@ -43,7 +43,7 @@ func newOpusEnc() *opus.Encoder { } func pcmConv(buf []byte, pcm []int16) { - for i := 0; i < len(pcm); i++ { + for i := range len(pcm) { buf[i*2+0] = byte((uint16(pcm[i]) & 0x00FF) >> 0) buf[i*2+1] = byte((uint16(pcm[i]) & 0xFF00) >> 8) } diff --git a/cmd/client/gui.go b/cmd/client/gui.go index 6a6d866..cc7a253 100644 --- a/cmd/client/gui.go +++ b/cmd/client/gui.go @@ -21,7 +21,7 @@ import ( "sort" "github.com/jroimartin/gocui" - vors "go.stargrave.org/vors/v4/internal" + vors "go.stargrave.org/vors/v5/internal" ) var ( diff --git a/cmd/client/main.go b/cmd/client/main.go index 134d84d..56ca240 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -17,8 +17,9 @@ package main import ( "bytes" + "crypto/cipher" + "crypto/sha3" "crypto/subtle" - "encoding/base64" "encoding/binary" "flag" "fmt" @@ -35,11 +36,10 @@ import ( "github.com/aead/chacha20" "github.com/dchest/siphash" "github.com/jroimartin/gocui" - "github.com/katzenpost/noise" - "go.cypherpunks.su/netstring/v3" "go.stargrave.org/opus/v2" - vors "go.stargrave.org/vors/v4/internal" - "golang.org/x/crypto/blake2b" + vors "go.stargrave.org/vors/v5/internal" + "go.stargrave.org/vors/v5/pqhs" + "golang.org/x/crypto/chacha20poly1305" ) type Stream struct { @@ -63,16 +63,6 @@ var ( Ctrl = make(chan []byte) ) -func incr(data []byte) { - for i := len(data) - 1; i >= 0; i-- { - data[i]++ - if data[i] != 0 { - return - } - } - panic("overflow") -} - func muteToggle() (muted bool) { Muted = !Muted if Ctrl != nil { @@ -90,7 +80,7 @@ func muteToggle() (muted bool) { func main() { srvAddr := flag.String("srv", "vors.home.arpa:"+strconv.Itoa(vors.DefaultPort), "host:TCP/UDP port to connect to") - srvPubB64 := flag.String("pub", "", "server's public key, Base64") + srvPubPth := flag.String("pub", "", "Path to server's public key") recCmd := flag.String("rec", "rec "+vors.SoxParams, "rec command") playCmd := flag.String("play", "play "+vors.SoxParams, "play command") vadRaw := flag.Uint("vad", 0, "VAD threshold") @@ -135,11 +125,11 @@ Magenta "S" means that peer is locally muted.`) var passwdHsh []byte if *passwd != "" { - hsh := blake2b.Sum256([]byte(*passwd)) + hsh := sha3.SumSHAKE128([]byte(*passwd), 32) passwdHsh = hsh[:] } - srvPub, err := base64.RawURLEncoding.DecodeString(*srvPubB64) + srvPub, err := os.ReadFile(*srvPubPth) if err != nil { log.Fatal(err) } @@ -182,6 +172,11 @@ Magenta "S" means that peer is locally muted.`) } vors.PreferIPv4 = *prefer4 + hs, buf, err := pqhs.NewClient(pqhs.KeyDecombine(srvPub)) + if err != nil { + log.Fatalln("pqhs.NewClient:", err) + } + ctrlConn, err := net.DialTCP("tcp", nil, vors.MustResolveTCP(*srvAddr)) if err != nil { log.Fatalln("dial server:", err) @@ -190,40 +185,50 @@ Magenta "S" means that peer is locally muted.`) if err = ctrlConn.SetNoDelay(true); err != nil { log.Fatalln("nodelay:", err) } - ctrl := vors.NewNSConn(ctrlConn) - - hs, err := noise.NewHandshakeState(noise.Config{ - CipherSuite: vors.NoiseCipherSuite, - Pattern: noise.HandshakeNK, - Initiator: true, - PeerStatic: srvPub, - Prologue: []byte(vors.NoisePrologue), - }) - if err != nil { - log.Fatalln("noise.NewHandshakeState:", err) + + ctrl := vors.NewNSConn(ctrlConn, 1<<16) + if err = ctrl.Tx([]byte(vors.Magic)); err != nil { + log.Fatalln("write handshake magic:", err) } - buf, _, _, err := hs.WriteMessage(nil, vors.ArgsEncode( + if err = ctrl.Tx(buf); err != nil { + log.Fatalln("write handshake hello:", err) + } + buf = <-ctrl.Rx + if buf == nil { + log.Fatalln("read handshake hello:", ctrl.Err) + } + buf, err = hs.Read(buf, vors.ArgsEncode( []byte(*Name), []byte(*Room), passwdHsh, )) if err != nil { - log.Fatalln("handshake encrypt:", err) + log.Fatalln("process handshake:", err) } - { - var w bytes.Buffer - w.WriteString(vors.NoisePrologue) - netstring.NewWriter(&w).WriteChunk(buf) - buf = w.Bytes() + if err = ctrl.Tx(buf); err != nil { + log.Fatalln("write handshake finish:", err) } - _, err = io.Copy(ctrlConn, bytes.NewReader(buf)) + + var txKey, rxKey, keyCiphOur, keyMACOur []byte + var txAEAD, rxAEAD cipher.AEAD + keys := hs.Binding(3*chacha20poly1305.KeySize + vors.SipHash24KeySize) + txKey, keys = keys[:chacha20poly1305.KeySize], keys[chacha20poly1305.KeySize:] + rxKey, keys = keys[:chacha20poly1305.KeySize], keys[chacha20poly1305.KeySize:] + keyCiphOur, keyMACOur = keys[:vors.ChaCha20KeySize], keys[vors.ChaCha20KeySize:] + txAEAD, err = chacha20poly1305.New(txKey) if err != nil { - log.Fatalln("write handshake:", err) - return + log.Fatal(err) + } + rxAEAD, err = chacha20poly1305.New(rxKey) + if err != nil { + log.Fatal(err) } + txNonce := make([]byte, chacha20poly1305.NonceSize) + rxNonce := make([]byte, chacha20poly1305.NonceSize) + buf = <-ctrl.Rx if buf == nil { - log.Fatalln("read handshake:", ctrl.Err) + log.Fatalln("read handshake finish:", ctrl.Err) } - buf, txCS, rxCS, err := hs.ReadMessage(nil, buf) + buf, err = rxAEAD.Open(buf[:0], rxNonce, buf, nil) if err != nil { log.Fatalln("handshake decrypt:", err) } @@ -231,12 +236,13 @@ Magenta "S" means that peer is locally muted.`) rx := make(chan []byte) go func() { for buf := range ctrl.Rx { - buf, err = rxCS.Decrypt(buf[:0], nil, buf) + buf, err = rxAEAD.Open(buf[:0], rxNonce, buf, nil) if err != nil { log.Println("rx decrypt", err) break } rx <- buf + vors.Incr(rxNonce) } Finish <- struct{}{} }() @@ -312,23 +318,6 @@ Magenta "S" means that peer is locally muted.`) } } - var keyCiphOur []byte - var keyMACOur []byte - { - var xof blake2b.XOF - xof, err = blake2b.NewXOF(vors.ChaCha20KeySize+vors.SipHash24KeySize, nil) - if err != nil { - log.Fatalln(err) - } - xof.Write([]byte(vors.NoisePrologue)) - xof.Write(hs.ChannelBinding()) - buf := make([]byte, vors.ChaCha20KeySize+vors.SipHash24KeySize) - if _, err = io.ReadFull(xof, buf); err != nil { - log.Fatalln(err) - } - keyCiphOur, keyMACOur = buf[:vors.ChaCha20KeySize], buf[vors.ChaCha20KeySize:] - } - seen := time.Now() LoggerReady := make(chan struct{}) @@ -387,13 +376,11 @@ Magenta "S" means that peer is locally muted.`) go func() { for buf := range Ctrl { - buf, err = txCS.Encrypt(nil, nil, buf) - if err != nil { - log.Fatalln("tx encrypt:", err) - } + buf = txAEAD.Seal(nil, txNonce, buf, nil) if err = ctrl.Tx(buf); err != nil { log.Fatalln("tx:", err) } + vors.Incr(txNonce) } }() @@ -686,11 +673,11 @@ Magenta "S" means that peer is locally muted.`) log.Println("mic:", err) break } - incr(actr[:]) + vors.Incr(actr[:]) if Muted { continue } - for i = 0; i < vors.FrameLen; i++ { + for i = range vors.FrameLen { pcm[i] = int16(uint16(buf[i*2+0]) | (uint16(buf[i*2+1]) << 8)) } if vad != 0 && vors.RMS(pcm) < vad { @@ -705,7 +692,7 @@ Magenta "S" means that peer is locally muted.`) continue } - incr(nonce[len(nonce)-3:]) + vors.Incr(nonce[len(nonce)-3:]) copy(buf, nonce[len(nonce)-4:]) copy(buf[4:], actr) chacha20.XORKeyStream( diff --git a/cmd/client/stats.go b/cmd/client/stats.go index a7b03be..cba958a 100644 --- a/cmd/client/stats.go +++ b/cmd/client/stats.go @@ -24,7 +24,7 @@ import ( "github.com/dustin/go-humanize" "github.com/jroimartin/gocui" - vors "go.stargrave.org/vors/v4/internal" + vors "go.stargrave.org/vors/v5/internal" ) type Stats struct { diff --git a/cmd/keygen/main.go b/cmd/keygen/main.go index 31c06b3..ea611f0 100644 --- a/cmd/keygen/main.go +++ b/cmd/keygen/main.go @@ -1,22 +1,26 @@ package main import ( - "crypto/rand" - "encoding/base64" + "bytes" "flag" "fmt" "io" "log" "os" - "github.com/katzenpost/noise" - vors "go.stargrave.org/vors/v4/internal" + vors "go.stargrave.org/vors/v5/internal" + "go.stargrave.org/vors/v5/pqhs" ) +func usage() { + fmt.Fprintf(os.Stderr, "Usage: vors-keygen 5>pub 9>prv\n") + flag.PrintDefaults() +} + func main() { - pub := flag.Bool("pub", false, "print Base64 public key") version := flag.Bool("version", false, "print version") warranty := flag.Bool("warranty", false, "print warranty information") + flag.Usage = usage flag.Parse() if *warranty { fmt.Println(vors.Warranty) @@ -26,21 +30,16 @@ func main() { fmt.Println(vors.GetVersion()) return } - if *pub { - data, err := io.ReadAll(os.Stdin) - if err != nil { - log.Fatal(err) - } - if len(data) != 2*32 { - log.Fatal("wrong length") - } - fmt.Printf("%s\n", base64.RawURLEncoding.EncodeToString(data[32:])) - return - } - kp, err := noise.DH25519.GenerateKeypair(rand.Reader) + prvMcEliece, pubMcEliece, prvX25519, pubX25519, err := pqhs.KeyGen() if err != nil { log.Fatal(err) } - os.Stdout.Write(kp.Private[:]) - os.Stdout.Write(kp.Public[:]) + fdPubW := os.NewFile(5, "pub-out") + if _, err = io.Copy(fdPubW, bytes.NewReader(pqhs.KeyCombine(pubMcEliece, pubX25519))); err != nil { + log.Fatal(err) + } + fdPrvW := os.NewFile(9, "prv-out") + if _, err = io.Copy(fdPrvW, bytes.NewReader(pqhs.KeyCombine(prvMcEliece, prvX25519))); err != nil { + log.Fatal(err) + } } diff --git a/cmd/server/main.go b/cmd/server/main.go index 6c62117..2087dd5 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -17,8 +17,8 @@ package main import ( "crypto/rand" + "crypto/sha3" "crypto/subtle" - "encoding/base64" "flag" "fmt" "io" @@ -33,14 +33,16 @@ import ( "github.com/dchest/siphash" "github.com/jroimartin/gocui" - "github.com/katzenpost/noise" - vors "go.stargrave.org/vors/v4/internal" - "golang.org/x/crypto/blake2b" + vors "go.stargrave.org/vors/v5/internal" + "go.stargrave.org/vors/v5/pqhs" + "golang.org/x/crypto/chacha20poly1305" ) var ( - Prv, Pub []byte - Cookies = map[vors.Cookie]chan *net.UDPAddr{} + PrvMcEliece []byte + PrvX25519 []byte + PubHash []byte + Cookies = map[vors.Cookie]chan *net.UDPAddr{} ) func newPeer(conn *net.TCPConn) { @@ -51,31 +53,35 @@ func newPeer(conn *net.TCPConn) { if err != nil { log.Fatalln("nodelay:", err) } - buf := make([]byte, len(vors.NoisePrologue)) - - if _, err = io.ReadFull(conn, buf); err != nil { - logger.Error("handshake: read prologue", "err", err) + nsConn := vors.NewNSConn(conn, 1<<16) + buf := <-nsConn.Rx + if buf == nil { + logger.Error("read magic", "err", nsConn.Err) return } - if string(buf) != vors.NoisePrologue { - logger.Error("handshake: wrong prologue", "err", err) + if string(buf) != vors.Magic { + logger.Error("handshake: wrong magic") return } - - hs, err := noise.NewHandshakeState(noise.Config{ - CipherSuite: vors.NoiseCipherSuite, - Pattern: noise.HandshakeNK, - Initiator: false, - StaticKeypair: noise.DHKey{Private: Prv, Public: Pub}, - Prologue: []byte(vors.NoisePrologue), - }) + buf = <-nsConn.Rx + if buf == nil { + logger.Error("handshake: read hello", "err", nsConn.Err) + return + } + hs, buf, err := pqhs.NewServer(PrvMcEliece, PrvX25519, PubHash, buf) if err != nil { - log.Fatalln("noise.NewHandshakeState:", err) + logger.Error("handshake: process hello", "err", err) + return } - nsConn := vors.NewNSConn(conn) + nsConn.Tx(buf) buf = <-nsConn.Rx if buf == nil { - logger.Error("read handshake", "err", nsConn.Err) + logger.Error("handshake: read finish", "err", nsConn.Err) + return + } + buf, err = hs.Read(buf) + if err != nil { + logger.Error("handshake: process finish", "err", err) return } peer := &Peer{ @@ -86,16 +92,27 @@ func newPeer(conn *net.TCPConn) { tx: make(chan []byte, 10), alive: make(chan struct{}), } - var room *Room { - var argsRaw []byte - argsRaw, _, _, err = hs.ReadMessage(nil, buf) + var rxKey, txKey []byte + keys := hs.Binding(3*chacha20poly1305.KeySize + vors.SipHash24KeySize) + rxKey, keys = keys[:chacha20poly1305.KeySize], keys[chacha20poly1305.KeySize:] + txKey, peer.key = keys[:chacha20poly1305.KeySize], keys[chacha20poly1305.KeySize:] + peer.mac = siphash.New(peer.key[vors.ChaCha20KeySize:]) + peer.rxAEAD, err = chacha20poly1305.New(rxKey) if err != nil { - logger.Error("handshake: decrypt", "err", err) - return + log.Fatal(err) + } + peer.txAEAD, err = chacha20poly1305.New(txKey) + if err != nil { + log.Fatal(err) } + } + peer.rxNonce = make([]byte, chacha20poly1305.NonceSize) + peer.txNonce = make([]byte, chacha20poly1305.NonceSize) + var room *Room + { var args [][]byte - args, err = vors.ArgsDecode(argsRaw) + args, err = vors.ArgsDecode(buf) if err != nil { logger.Error("handshake: decode args", "err", err) return @@ -141,13 +158,9 @@ func newPeer(conn *net.TCPConn) { } if room.key != key { logger.Error("wrong password") - buf, _, _, err = hs.WriteMessage(nil, vors.ArgsEncode( + nsConn.Tx(peer.txAEAD.Seal(nil, peer.txNonce, vors.ArgsEncode( []byte(vors.CmdErr), []byte("wrong password"), - )) - if err != nil { - log.Fatal(err) - } - nsConn.Tx(buf) + ), nil)) return } } @@ -159,14 +172,10 @@ func newPeer(conn *net.TCPConn) { continue } logger.Error("name already taken") - buf, _, _, err = hs.WriteMessage(nil, vors.ArgsEncode( + nsConn.Tx(peer.txAEAD.Seal(nil, peer.txNonce, vors.ArgsEncode( []byte(vors.CmdErr), []byte("name already taken"), - )) - if err != nil { - log.Fatal(err) - } + ), nil)) room.peersM.RUnlock() - nsConn.Tx(buf) return } room.peersM.RUnlock() @@ -189,13 +198,9 @@ func newPeer(conn *net.TCPConn) { } PeersM.Unlock() if !found { - buf, _, _, err = hs.WriteMessage(nil, vors.ArgsEncode( + nsConn.Tx(peer.txAEAD.Seal(nil, peer.txNonce, vors.ArgsEncode( []byte(vors.CmdErr), []byte("too many users"), - )) - if err != nil { - log.Fatal(err) - } - nsConn.Tx(buf) + ), nil)) return } } @@ -229,18 +234,14 @@ func newPeer(conn *net.TCPConn) { gotCookie := make(chan *net.UDPAddr) Cookies[cookie] = gotCookie - var txCS, rxCS *noise.CipherState - buf, txCS, rxCS, err := hs.WriteMessage(nil, - vors.ArgsEncode([]byte(vors.CmdCookie), cookie[:])) + err = nsConn.Tx(peer.txAEAD.Seal(nil, peer.txNonce, vors.ArgsEncode( + []byte(vors.CmdCookie), cookie[:], + ), nil)) if err != nil { - log.Fatalln("hs.WriteMessage:", err) - } - if err = nsConn.Tx(buf); err != nil { logger.Error("handshake write", "err", err) delete(Cookies, cookie) return } - peer.rxCS, peer.txCS = txCS, rxCS timeout := time.NewTimer(vors.PingTime) select { @@ -268,20 +269,6 @@ func newPeer(conn *net.TCPConn) { } room.peersM.RUnlock() - { - xof, err := blake2b.NewXOF(vors.ChaCha20KeySize+vors.SipHash24KeySize, nil) - if err != nil { - log.Fatalln(err) - } - xof.Write([]byte(vors.NoisePrologue)) - xof.Write(hs.ChannelBinding()) - peer.key = make([]byte, vors.ChaCha20KeySize+vors.SipHash24KeySize) - if _, err = io.ReadFull(xof, peer.key); err != nil { - log.Fatalln(err) - } - peer.mac = siphash.New(peer.key[vors.ChaCha20KeySize:]) - } - { s := vors.ArgsEncode( []byte(vors.CmdAdd), []byte{peer.sid}, []byte(peer.name), peer.key) @@ -368,13 +355,14 @@ func newPeer(conn *net.TCPConn) { func main() { bind := flag.String("bind", "[::1]:"+strconv.Itoa(vors.DefaultPort), "host:TCP/UDP port to listen on") - kpFile := flag.String("key", "key", "path to keypair file") + pubFile := flag.String("pub", "pub", "path to file with public key") + prvFile := flag.String("prv", "prv", "path to file with private key") prefer4 := flag.Bool("4", false, "Prefer obsolete legacy IPv4 address during name resolution") version := flag.Bool("version", false, "print version") warranty := flag.Bool("warranty", false, "print warranty information") flag.Usage = func() { - fmt.Fprintln(os.Stderr, "Usage: vors-server [opts] -bind HOST:PORT -key PATH -srv HOST:PORT") + fmt.Fprintln(os.Stderr, "Usage: vors-server [opts] -bind HOST:PORT -prv PRV -pub PUB -srv HOST:PORT") flag.PrintDefaults() fmt.Fprintln(os.Stderr, ` List of known rooms is shown by default. If room requires password @@ -399,11 +387,16 @@ Press F10 to quit.`) } { - data, err := os.ReadFile(*kpFile) + prv, err := os.ReadFile(*prvFile) + if err != nil { + log.Fatal(err) + } + PrvMcEliece, PrvX25519 = pqhs.KeyDecombine(prv) + pub, err := os.ReadFile(*pubFile) if err != nil { log.Fatal(err) } - Prv, Pub = data[:len(data)/2], data[len(data)/2:] + PubHash = sha3.SumSHAKE256(pub, 64) } vors.PreferIPv4 = *prefer4 @@ -542,9 +535,7 @@ Press F10 to quit.`) go func() { <-LoggerReady - slog.Info("listening", - "bind", *bind, - "pub", base64.RawURLEncoding.EncodeToString(Pub)) + slog.Info("listening", "bind", *bind) for { conn, errConn := lnTCP.AcceptTCP() if err != nil { diff --git a/cmd/server/peer.go b/cmd/server/peer.go index 288b4d6..dbb5542 100644 --- a/cmd/server/peer.go +++ b/cmd/server/peer.go @@ -1,14 +1,14 @@ package main import ( + "crypto/cipher" "hash" "log/slog" "net" "sync" "time" - "github.com/katzenpost/noise" - vors "go.stargrave.org/vors/v4/internal" + vors "go.stargrave.org/vors/v5/internal" ) var ( @@ -35,12 +35,15 @@ type Peer struct { muted bool sid byte - logger *slog.Logger - conn *vors.NSConn - rxCS, txCS *noise.CipherState - rx, tx chan []byte - alive chan struct{} - aliveOnce sync.Once + logger *slog.Logger + conn *vors.NSConn + rxAEAD cipher.AEAD + txAEAD cipher.AEAD + rxNonce []byte + txNonce []byte + rx, tx chan []byte + alive chan struct{} + aliveOnce sync.Once } func (peer *Peer) Close() { @@ -55,12 +58,13 @@ func (peer *Peer) Close() { func (peer *Peer) Rx() { var err error for buf := range peer.conn.Rx { - buf, err = peer.rxCS.Decrypt(buf[:0], nil, buf) + buf, err = peer.rxAEAD.Open(buf[:0], peer.rxNonce, buf, nil) if err != nil { peer.logger.Error("rx decrypt", "err", err) break } peer.rx <- buf + vors.Incr(peer.rxNonce) } peer.Close() } @@ -68,18 +72,12 @@ func (peer *Peer) Rx() { func (peer *Peer) Tx() { var err error for buf := range peer.tx { - if peer.txCS == nil { - continue - } - buf, err = peer.txCS.Encrypt(buf[:0], nil, buf) - if err != nil { - peer.logger.Error("tx encrypt", "err", err) - break - } + buf = peer.txAEAD.Seal(buf[:0], peer.txNonce, buf, nil) if err = peer.conn.Tx(buf); err != nil { peer.logger.Error("tx write", "err", err) break } + vors.Incr(peer.txNonce) } peer.Close() } diff --git a/cmd/server/room.go b/cmd/server/room.go index 5e40cac..f55e596 100644 --- a/cmd/server/room.go +++ b/cmd/server/room.go @@ -8,7 +8,7 @@ import ( "time" "github.com/dustin/go-humanize" - vors "go.stargrave.org/vors/v4/internal" + vors "go.stargrave.org/vors/v5/internal" ) var ( diff --git a/cmd/vad/main.go b/cmd/vad/main.go index dc44b39..b1ae146 100644 --- a/cmd/vad/main.go +++ b/cmd/vad/main.go @@ -23,7 +23,7 @@ import ( "os" "strconv" - vors "go.stargrave.org/vors/v4/internal" + vors "go.stargrave.org/vors/v5/internal" ) func usage() { @@ -62,7 +62,7 @@ func main() { if err != nil { log.Fatal(err) } - for i = 0; i < vors.FrameLen; i++ { + for i = range vors.FrameLen { pcm[i] = int16(uint16(buf[i*2+0]) | (uint16(buf[i*2+1]) << 8)) } rms = vors.RMS(pcm) diff --git a/doc/Features b/doc/Features index fe75832..5d59638 100644 --- a/doc/Features +++ b/doc/Features @@ -5,11 +5,11 @@ and DTX (discontinuous transmission) features enabled. Optional [VAD] (voice activity detection). => https://opus-codec.org/ Opus codec -* Noise-NKhfs protocol-based 0-RTT single round-trip handshake over TCP - between client and server for creating authenticated encrypted channel - and authentication based on server's public key knowledge. +* PQConnect and Noise inspired post-quantum secure handshake protocol + over TCP between client and server. Authentication is based on + server's public key knowledge. + => https://www.pqconnect.net/ PQConnect => http://noiseprotocol.org/ Noise protocol framework - => https://github.com/noiseprotocol/noise_hfs_spec KEM-based hybrid forward secrecy * Fast ChaCha20 encryption with SipHash24 message authentication. * Rooms, optionally password protected. Peers are able to broadcast text message to everyone in the room. diff --git a/doc/INSTALL b/doc/INSTALL index 7f3a47a..ea7ac86 100644 --- a/doc/INSTALL +++ b/doc/INSTALL @@ -1,4 +1,4 @@ -VoRS is written on Go (at least 1.21 version is required), but also uses +VoRS is written on Go (at least 1.24 version is required), but also uses wrapper on libopus library. Provided tarballs include its source code and a fork of the gopkg.in/hraban/opus.v2 with the added ability to use Decoder.SetComplexity call, that is required for ML-related optimisations. @@ -16,7 +16,7 @@ them with -rec and -play options to vors-client. => https://sourceforge.net/projects/sox/ SoX - $ version=4.0.0 + $ version=5.0.0 $ [fetch|wget] http://www.vors.stargrave.org/download/vors-$version.tar.zst $ [fetch|wget] http://www.vors.stargrave.org/download/vors-$version.tar.zst.sig [verify signature] diff --git a/doc/PQHS b/doc/PQHS new file mode 100644 index 0000000..128147c --- /dev/null +++ b/doc/PQHS @@ -0,0 +1,51 @@ +Server has a long-term static Classic McEliece 6960-119 and X25519 +keypairs. They are transferred to client outside the connection. + +Client: + * has: serverStaticPubMcEliece, serverStaticPubX25519 + * clientEphPrvX25519, clientEphPubX25519 = Generate() + * ctMcElice, ssMcEliece = Encapsulate(serverStaticPubMcEliece) + * H = SHAKE256("VoRS v5") + * H = SHAKE256(H || serverStaticPubMcEliece || serverStaticPubX25519) + * H = SHAKE256(H || ctMcElice) + * CK = HKDF-Extract(SHAKE256, ikm=ssMcEliece, salt="") + * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 client x25519") + * ctX25519 = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=clientEphPubX25519) + * H = SHAKE256(H || ctX25519) + * ssX25519 = X25519(clientEphPrvX25519, serverStaticPubX25519) + * CK = HKDF-Extract(SHAKE256, ikm=ssX25519, salt=CK) + * sends: ctMcElice || ctX25519 + +Server: + * ... + * serverEphPrvX25519, serverEphPubX25519 = Generate() + * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 server x25519") + * ctX25519 = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=serverEphPubX25519) + * H = SHAKE256(H || ctX25519) + * ssX25519 = X25519(serverEphPrvX25519, clientEphPubX25519) + * CK = HKDF-Extract(SHAKE256, ikm=ssX25519, salt=CK) + * serverEphPrvSNTRUP761, serverEphPubSNTRUP761 = Generate() + * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 server sntrup761") + * ctSNTRUP = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=serverEphPubSNTRUP761) + * H = SHAKE256(H || ctSNTRUP) + * sends: ctX25519 || ctSNTRUP + +Client: + * has: prefinish message payload + * ... + * ctSNTRUP, ssSNTRUP = Encapsulate(serverEphPubSNTRUP761) + * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 client sntrup761") + * ctSNTRUP = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=ctSNTRUP) + * H = SHAKE256(H || ctSNTRUP) + * CK = HKDF-Extract(SHAKE256, ikm=ssSNTRUP, salt=CK) + * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 client prefinish") + * ctPrefinish = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=prefinish) + * H = SHAKE256(H || ctPrefinish) + * sends: ctPrefinish + +Server: + * ... + +Both: + clientChaPolyKey, serverChaPolyKey, VoIPKey = + HKDF-Expand(SHAKE256, ikm=CK, salt=H) diff --git a/doc/Protocol b/doc/Protocol index 09d8030..2537487 100644 --- a/doc/Protocol +++ b/doc/Protocol @@ -13,30 +13,41 @@ ability to distinguish jitters and delays from lack of audio transmission. Each packet is encrypted with ChaCha20 and authenticated with SipHash24. -Their keys are generated from BLAKE2b-XOF, which is fed with completed -handshake's binding value. Then they are shared among the other -participants. The stream identifier together with the packet counter is -used as a nonce. +Their keys are generated with HKDF taken on handshake's state. Then they +are shared among the other participants. The stream identifier together +with the packet counter is used as a nonce. It is tuned for 24Kbps bandwidth. But remember that it has additional 8B of MAC tag, 7B VoRS, 8B UDP and 40B IPv6 headers. Each client handshakes with the server over TCP connection using the -Noise-NKhfs protocol pattern with curve25519, Kyber-1024, ChaCha20-Poly1305 -and BLAKE2b algorithms. -=> http://noiseprotocol.org/ Noise protocol framework -=> https://github.com/noiseprotocol/noise_hfs_spec KEM-based hybrid forward secrecy - -* Client sends "VoRS v4" to the socket. Just a magic number. +PQConnect, Noise, Chempat inspired protocol. It consists of hybrid key +exchange, using static Classic McEliece 6960-119 server's public key, +static X25519, ephemeral X25519 and ephemeral Streamlined NTRU Prime 761 +ones. With HKDF as a KDF and SHAKE as a hash function. -* All next messages are Netstring encoded strings. Most of them contain +=> https://www.pqconnect.net/ PQConnect +=> http://noiseprotocol.org/ Noise protocol framework +=> https://datatracker.ietf.org/doc/draft-josefsson-chempat/ Chempat +=> https://classic.mceliece.org/ Classic McEliece +=> https://ntruprime.cr.yp.to/ Streamlined NTRU Prime +=> https://datatracker.ietf.org/doc/html/rfc7748 X25519 +=> https://datatracker.ietf.org/doc/html/rfc5869.html HKDF +=> https://keccak.team/ SHAKE + +* All messages are Netstring encoded strings. Most of them contain netstring encoded sequence of netstrings if multiple values are expected: NS(NS(arg0) || NS(arg1) || ...) => http://cr.yp.to/proto/netstrings.txt Netstring -* Client sends initial Noise handshake message with his username, room - name and optional BLAKE2b-256 hash of the room's password (or an empty - string) as a payload: [USERNAME, ROOM, hash(PASSWD)]. +* Client sends NS("VoRS v5") to the socket. Just a magic number. + +* Then it performs [PQHS]. + +* Client sends initial handshake message. Its prefinish payload message + contains his username, room name and optional SHAKE256 hash of the + room's password (or an empty string) as a payload: + [USERNAME, ROOM, hash(PASSWD)]. * Server answers with final noise handshake message with the ["COOKIE", COOKIE], or ["ERR", MSG] failure message. It may reject a @@ -56,10 +67,14 @@ and BLAKE2b algorithms. * Server replies with ["SID", SID], where SID is single byte stream number client must use. +TODO + * ["PING"] and ["PONG"] messages are then sent every ten seconds as a heartbeat. - S <- C : e, es, e1, NS(NS(USERNAME) || NS(ROOM) || NS(hash(PASSWD))) - S -> C : e, ee, ekem1, NS(NS("COOKIE") || NS(COOKIE)) + S <- C : hello + S -> C : hello + S <- C : finish, NS(NS(USERNAME) || NS(ROOM) || NS(hash(PASSWD))) + S -> C : NS(NS("COOKIE") || NS(COOKIE)) S <- C : UDP(COOKIE) S -> C : NS(NS("SID") || NS(SID)) diff --git a/doc/Usage b/doc/Usage index a3252a0..dabe006 100644 --- a/doc/Usage +++ b/doc/Usage @@ -1,8 +1,8 @@ * Generate server's keypair. And share its public key among users. Fact of server's public key knowledge means ability to connect to it. - $ vors-keygen | tee key | vors-keygen -pub | read pub - $ vors-server -key key -bind [2001:db8::1]:12978 + $ vors-keygen 5>pub 9>prv + $ vors-server -prv prv -pub pub -bind [2001:db8::1]:12978 * Client uses external commands for reading from microphone and playing it back. By default it uses SoX'es "rec" and "play" commands. @@ -16,7 +16,7 @@ * Start the client, providing server's public key and our username: - $ vors-client -srv "[2001:db8::1]:12978" -pub $pub -name NAME + $ vors-client -srv "[2001:db8::1]:12978" -pub pub -name NAME Pressing F10 in server/client TUIs means quitting. Pressing F1 in client means "mute" toggling. diff --git a/doc/index b/doc/index index 6438376..37c12eb 100644 --- a/doc/index +++ b/doc/index @@ -27,7 +27,7 @@ the key to just immediately talk with someone. application? But a fancy real-time refreshing TUI would be desirable. Mumble tends to output no information, sometimes hiding the fact of a problem and that everything stopped working. -* Mono-cypher, mono-codec protocol. +* Mono-codec, mono-cypher, post-quantum ready protocol. * Maximal easiness of usage: here is your address, key, do me good. VoRS is copylefted free software licenced under GNU Affero GPLv3. diff --git a/go.mod b/go.mod index b2177e7..20341b5 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,20 @@ -module go.stargrave.org/vors/v4 +module go.stargrave.org/vors/v5 -go 1.23.0 +go 1.24.0 -toolchain go1.24.3 +toolchain go1.24.5 require ( github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da github.com/dchest/siphash v1.2.3 github.com/dustin/go-humanize v1.0.1 github.com/jroimartin/gocui v0.5.0 - github.com/katzenpost/noise v0.0.3 go.cypherpunks.su/netstring/v3 v3.0.0 go.stargrave.org/opus/v2 v2.1.0 golang.org/x/term v0.32.0 ) require ( - github.com/cloudflare/circl v1.6.1 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/nsf/termbox-go v1.1.1 // indirect ) diff --git a/go.sum b/go.sum index 1cbbddf..34e5b3f 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,11 @@ github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= -github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/cloudflare/circl v1.0.1-0.20210824050549-9b4298fa53ce/go.mod h1:wqo+yhCGS0T5Ldpb0f4hdJqVGwsEBYDE3MrO6W/RACc= -github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= -github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/jroimartin/gocui v0.5.0 h1:DCZc97zY9dMnHXJSJLLmx9VqiEnAj0yh0eTNpuEtG/4= github.com/jroimartin/gocui v0.5.0/go.mod h1:l7Hz8DoYoL6NoYnlnaX6XCNR62G7J5FfSW5jEogzaxE= -github.com/katzenpost/noise v0.0.3 h1:bpYnozkk8j0XE1FAX9iRYgKtfIywuAINF+vMdBOidrM= -github.com/katzenpost/noise v0.0.3/go.mod h1:+3UhOI7g4gXPlAdRKdgMKmxZmK/PP1/3sCnX20SA/vQ= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY= @@ -25,21 +14,9 @@ go.cypherpunks.su/netstring/v3 v3.0.0 h1:wwFjxTb/LZM8cQN/UiOPMO5wcuq4xCQWdLAYz74 go.cypherpunks.su/netstring/v3 v3.0.0/go.mod h1:S9pYNVqT6kL2uXbdHz+yxc+A4sAFxBkjSzu+g6KD0QE= go.stargrave.org/opus/v2 v2.1.0 h1:WwyMf76wcIWEPIQlU2UI5V9YkqXRHQhq6wfZGslcMFc= go.stargrave.org/opus/v2 v2.1.0/go.mod h1:Y57qgcaXH7jBvKW89fscWOT/Wd3MYfhXUbYUcOMV0A8= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/incr.go b/internal/incr.go new file mode 100644 index 0000000..5b501e7 --- /dev/null +++ b/internal/incr.go @@ -0,0 +1,11 @@ +package internal + +func Incr(data []byte) { + for i := len(data) - 1; i >= 0; i-- { + data[i]++ + if data[i] != 0 { + return + } + } + panic("overflow") +} diff --git a/internal/noise.go b/internal/noise.go deleted file mode 100644 index 36e7eb8..0000000 --- a/internal/noise.go +++ /dev/null @@ -1,14 +0,0 @@ -package internal - -import ( - "github.com/katzenpost/noise" -) - -const NoisePrologue = "VoRS v4" - -var NoiseCipherSuite = noise.NewCipherSuiteHFS( - noise.DH25519, - noise.CipherChaChaPoly, - noise.HashBLAKE2b, - noise.HFSKyber, -) diff --git a/internal/ns.go b/internal/ns.go index 4c271bf..b23a1de 100644 --- a/internal/ns.go +++ b/internal/ns.go @@ -45,14 +45,15 @@ func ArgsDecode(buf []byte) (args [][]byte, err error) { } type NSConn struct { - Conn net.Conn - Rx chan []byte - Err error + Conn net.Conn + Rx chan []byte + Err error + MaxLen uint64 sync.Mutex } -func NewNSConn(conn net.Conn) *NSConn { - c := NSConn{Conn: conn, Rx: make(chan []byte)} +func NewNSConn(conn net.Conn, maxLen int) *NSConn { + c := NSConn{Conn: conn, Rx: make(chan []byte), MaxLen: uint64(maxLen)} go func() { r := netstring.NewReader(conn) var n uint64 @@ -61,6 +62,10 @@ func NewNSConn(conn net.Conn) *NSConn { if c.Err != nil { break } + if n >= c.MaxLen { + c.Err = errors.New("exceeds MaxLen") + break + } buf := make([]byte, int(n)) if _, c.Err = io.ReadFull(r, buf); c.Err != nil { break diff --git a/internal/var.go b/internal/var.go index 2cb501d..cd35424 100644 --- a/internal/var.go +++ b/internal/var.go @@ -6,6 +6,7 @@ import ( ) const ( + Magic = "VoRS v5" CmdErr = "ERR" CmdCookie = "COOKIE" CmdSID = "SID" diff --git a/makedist b/makedist index e5a5dc3..61beb15 100755 --- a/makedist +++ b/makedist @@ -46,7 +46,6 @@ meta4ra-create -fn "$tarball" -mtime "$tarball" \ size=$(( $(stat -f %z $tarball) / 1024 )) release_date=$(date "+%Y-%m-%d") -release_underscored=`echo $release | tr . _` cat <= 0; iter-- { + for i := 0; i < 64; i++ { + bIntV[i] = load8(bitsPtr) + bitsPtr = bitsPtr[8:] + } + layerIn(&rIntV, &bIntV, iter) + } + + transpose64x64(&rIntH[0], &rIntV[0]) + transpose64x64(&rIntH[1], &rIntV[1]) + + for iter := 6; iter >= 0; iter-- { + for i := 0; i < 64; i++ { + bIntV[i] = load8(bitsPtr) + bitsPtr = bitsPtr[8:] + } + transpose64x64(&bIntH, &bIntV) + layerEx(&rIntH, &bIntH, iter) + } + + transpose64x64(&rIntV[0], &rIntH[0]) + transpose64x64(&rIntV[1], &rIntH[1]) + + for i := 0; i < 64; i++ { + store8(r[i*16+0:], rIntV[0][i]) + store8(r[i*16+8:], rIntV[1][i]) + } +} diff --git a/pqhs/mceliece6960119/fft.go b/pqhs/mceliece6960119/fft.go new file mode 100644 index 0000000..1d117de --- /dev/null +++ b/pqhs/mceliece6960119/fft.go @@ -0,0 +1,208 @@ +// Code generated from fft_other.templ.go. DO NOT EDIT. + +// The following code is translated from the C `vec` Additional Implementation +// from the NIST round 4 submission package. + +package mceliece6960119 + +import "go.stargrave.org/vors/v5/pqhs/mceliece6960119/internal" + +func fft(out *[exponent][gfBits]uint64, in *[2][gfBits]uint64) { + radixConversions(in) + butterflies(out, in) +} + +func radixConversions(in *[2][gfBits]uint64) { + for j := 0; j <= 5; j++ { + for i := 0; i < gfBits; i++ { + in[1][i] ^= in[1][i] >> 32 + in[0][i] ^= in[1][i] << 32 + } + + for i := 0; i < gfBits; i++ { + for k := 4; k >= j; k-- { + in[0][i] ^= (in[0][i] & internal.RadixConversionsMask[k][0]) >> (1 << k) + in[0][i] ^= (in[0][i] & internal.RadixConversionsMask[k][1]) >> (1 << k) + in[1][i] ^= (in[1][i] & internal.RadixConversionsMask[k][0]) >> (1 << k) + in[1][i] ^= (in[1][i] & internal.RadixConversionsMask[k][1]) >> (1 << k) + } + } + + if j < 5 { + vecMul(&in[0], &in[0], &internal.RadixConversionsS[j][0]) + vecMul(&in[1], &in[1], &internal.RadixConversionsS[j][1]) + } + } +} + +func butterflies(out *[exponent][gfBits]uint64, in *[2][gfBits]uint64) { + tmp := [gfBits]uint64{} + pre := [8][gfBits]uint64{} + buf := [128]uint64{} + constsPtr := 2 + for i := 0; i < 7; i++ { + for j := 0; j < gfBits; j++ { + pre[i][j] = uint64(internal.ButterfliesBeta[i]>>j) & 1 + pre[i][j] = -pre[i][j] + } + + vecMul(&pre[i], &in[1], &pre[i]) + } + for i := 0; i < gfBits; i++ { + buf[0] = in[0][i] + + buf[1] = buf[0] ^ pre[0][i] + buf[32] = in[0][i] ^ pre[5][i] + buf[3] = buf[1] ^ pre[1][i] + buf[96] = buf[32] ^ pre[6][i] + buf[97] = buf[96] ^ pre[0][i] + buf[2] = in[0][i] ^ pre[1][i] + buf[99] = buf[97] ^ pre[1][i] + buf[6] = buf[2] ^ pre[2][i] + buf[98] = buf[99] ^ pre[0][i] + buf[7] = buf[6] ^ pre[0][i] + buf[102] = buf[98] ^ pre[2][i] + buf[5] = buf[7] ^ pre[1][i] + buf[103] = buf[102] ^ pre[0][i] + buf[101] = buf[103] ^ pre[1][i] + buf[4] = in[0][i] ^ pre[2][i] + buf[100] = buf[101] ^ pre[0][i] + buf[12] = buf[4] ^ pre[3][i] + buf[108] = buf[100] ^ pre[3][i] + buf[13] = buf[12] ^ pre[0][i] + buf[109] = buf[108] ^ pre[0][i] + buf[15] = buf[13] ^ pre[1][i] + buf[111] = buf[109] ^ pre[1][i] + buf[14] = buf[15] ^ pre[0][i] + buf[110] = buf[111] ^ pre[0][i] + buf[10] = buf[14] ^ pre[2][i] + buf[106] = buf[110] ^ pre[2][i] + buf[11] = buf[10] ^ pre[0][i] + buf[107] = buf[106] ^ pre[0][i] + buf[9] = buf[11] ^ pre[1][i] + buf[105] = buf[107] ^ pre[1][i] + buf[104] = buf[105] ^ pre[0][i] + buf[8] = in[0][i] ^ pre[3][i] + buf[120] = buf[104] ^ pre[4][i] + buf[24] = buf[8] ^ pre[4][i] + buf[121] = buf[120] ^ pre[0][i] + buf[25] = buf[24] ^ pre[0][i] + buf[123] = buf[121] ^ pre[1][i] + buf[27] = buf[25] ^ pre[1][i] + buf[122] = buf[123] ^ pre[0][i] + buf[26] = buf[27] ^ pre[0][i] + buf[126] = buf[122] ^ pre[2][i] + buf[30] = buf[26] ^ pre[2][i] + buf[127] = buf[126] ^ pre[0][i] + buf[31] = buf[30] ^ pre[0][i] + buf[125] = buf[127] ^ pre[1][i] + buf[29] = buf[31] ^ pre[1][i] + buf[124] = buf[125] ^ pre[0][i] + buf[28] = buf[29] ^ pre[0][i] + buf[116] = buf[124] ^ pre[3][i] + buf[20] = buf[28] ^ pre[3][i] + buf[117] = buf[116] ^ pre[0][i] + buf[21] = buf[20] ^ pre[0][i] + buf[119] = buf[117] ^ pre[1][i] + buf[23] = buf[21] ^ pre[1][i] + buf[118] = buf[119] ^ pre[0][i] + buf[22] = buf[23] ^ pre[0][i] + buf[114] = buf[118] ^ pre[2][i] + buf[18] = buf[22] ^ pre[2][i] + buf[115] = buf[114] ^ pre[0][i] + buf[19] = buf[18] ^ pre[0][i] + buf[113] = buf[115] ^ pre[1][i] + buf[17] = buf[19] ^ pre[1][i] + buf[112] = buf[113] ^ pre[0][i] + buf[80] = buf[112] ^ pre[5][i] + buf[16] = in[0][i] ^ pre[4][i] + buf[81] = buf[80] ^ pre[0][i] + buf[48] = buf[16] ^ pre[5][i] + buf[83] = buf[81] ^ pre[1][i] + buf[49] = buf[48] ^ pre[0][i] + buf[82] = buf[83] ^ pre[0][i] + buf[51] = buf[49] ^ pre[1][i] + buf[86] = buf[82] ^ pre[2][i] + buf[50] = buf[51] ^ pre[0][i] + buf[87] = buf[86] ^ pre[0][i] + buf[54] = buf[50] ^ pre[2][i] + buf[85] = buf[87] ^ pre[1][i] + buf[55] = buf[54] ^ pre[0][i] + buf[84] = buf[85] ^ pre[0][i] + buf[53] = buf[55] ^ pre[1][i] + buf[92] = buf[84] ^ pre[3][i] + buf[52] = buf[53] ^ pre[0][i] + buf[93] = buf[92] ^ pre[0][i] + buf[60] = buf[52] ^ pre[3][i] + buf[95] = buf[93] ^ pre[1][i] + buf[61] = buf[60] ^ pre[0][i] + buf[94] = buf[95] ^ pre[0][i] + buf[63] = buf[61] ^ pre[1][i] + buf[90] = buf[94] ^ pre[2][i] + buf[62] = buf[63] ^ pre[0][i] + buf[91] = buf[90] ^ pre[0][i] + buf[58] = buf[62] ^ pre[2][i] + buf[89] = buf[91] ^ pre[1][i] + buf[59] = buf[58] ^ pre[0][i] + buf[88] = buf[89] ^ pre[0][i] + buf[57] = buf[59] ^ pre[1][i] + buf[72] = buf[88] ^ pre[4][i] + buf[56] = buf[57] ^ pre[0][i] + buf[73] = buf[72] ^ pre[0][i] + buf[40] = buf[56] ^ pre[4][i] + buf[75] = buf[73] ^ pre[1][i] + buf[41] = buf[40] ^ pre[0][i] + buf[74] = buf[75] ^ pre[0][i] + buf[43] = buf[41] ^ pre[1][i] + buf[78] = buf[74] ^ pre[2][i] + buf[42] = buf[43] ^ pre[0][i] + buf[79] = buf[78] ^ pre[0][i] + buf[46] = buf[42] ^ pre[2][i] + buf[77] = buf[79] ^ pre[1][i] + buf[47] = buf[46] ^ pre[0][i] + buf[76] = buf[77] ^ pre[0][i] + buf[45] = buf[47] ^ pre[1][i] + buf[68] = buf[76] ^ pre[3][i] + buf[44] = buf[45] ^ pre[0][i] + buf[69] = buf[68] ^ pre[0][i] + buf[36] = buf[44] ^ pre[3][i] + buf[71] = buf[69] ^ pre[1][i] + buf[37] = buf[36] ^ pre[0][i] + buf[70] = buf[71] ^ pre[0][i] + buf[39] = buf[37] ^ pre[1][i] + buf[66] = buf[70] ^ pre[2][i] + buf[38] = buf[39] ^ pre[0][i] + buf[67] = buf[66] ^ pre[0][i] + buf[34] = buf[38] ^ pre[2][i] + buf[65] = buf[67] ^ pre[1][i] + buf[35] = buf[34] ^ pre[0][i] + buf[33] = buf[35] ^ pre[1][i] + buf[64] = in[0][i] ^ pre[6][i] + + transpose64x64((*[64]uint64)(buf[:64]), (*[64]uint64)(buf[:64])) + transpose64x64((*[64]uint64)(buf[64:]), (*[64]uint64)(buf[64:])) + + for j := 0; j < 128; j++ { + out[internal.ButterfliesReversal[j]][i] = buf[j] + } + } + + for i := 1; i <= 6; i++ { + s := 1 << i + + for j := 0; j < 128; j += 2 * s { + for k := j; k < j+s; k++ { + vecMul(&tmp, &out[k+s], &internal.ButterfliesConst[constsPtr+(k-j)]) + + for b := 0; b < gfBits; b++ { + out[k][b] ^= tmp[b] + } + for b := 0; b < gfBits; b++ { + out[k+s][b] ^= out[k][b] + } + } + } + + constsPtr += 1 << i + } +} diff --git a/pqhs/mceliece6960119/internal/controlbits.go b/pqhs/mceliece6960119/internal/controlbits.go new file mode 100644 index 0000000..d49a7a4 --- /dev/null +++ b/pqhs/mceliece6960119/internal/controlbits.go @@ -0,0 +1,248 @@ +// This file is for implementing the Nassimi-Sahni algorithm +// See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" +// See also https://cr.yp.to/papers/controlbits-20200923.pdf + +package internal + +import ( + "unsafe" +) + +// layer implements one layer of the Beneš network. +// It permutes elements `p` according to control bits `cb` in-place. +// Thus, one layer of the Beneš network is created and if some control bits are set +// the corresponding transposition is applied. Parameter `s` equals `n.len()` and +// `s` configures `stride-2^s` conditional swaps. +func layer(p []int16, cb []byte, s, n int) { + stride := 1 << s + index := 0 + for i := int(0); i < n; i += stride * 2 { + for j := int(0); j < stride; j++ { + d := p[i+j] ^ p[i+j+stride] + m := int16(cb[index>>3]>>(index&7)) & 1 + m = -m + d &= m + p[i+j] ^= d + p[i+j+stride] ^= d + index++ + } + } +} + +// cbRecursion implements a recursion step of controlbitsfrompermutation. +// Pick `w ∈ {1, 2, …, 14}. Let `n = 2^w`. +// `out` must be a reference to a slice with `((2*w-1)*(1<<(w-1))+7)/8` or more bytes. +// It must zero-initialized before the first recursive call. +// `step` is initialized with 0 and doubles in each recursion step. +// `pi_offset` is an offset within temp slice ref (or aux in the first recursive call). +// `temp` is an intermediate reference to a slice used for recursive computation and +// temporarily stores values. It must be able to carry at least 2・n elements. +// `aux` is an auxiliary reference to a slice. It points to the elements to be permuted. +// After the first recursive iterations, the elements are stored in `temp` and thus `aux` +// won't be read anymore. The first `n/2` elements are read. +// nolint:funlen +func cbRecursion(out []byte, pos, step int, pi []int16, w, n int32, temp []int32) { + A := temp + B := temp[n:] + if w == 1 { + out[pos>>3] ^= byte(pi[0] << (pos & 7)) + return + } + + for x := int32(0); x < n; x++ { + A[x] = (int32(pi[x]^1) << 16) | int32(pi[x^1]) + } + int32Sort(A, n) // A = (id<<16)+pibar + + for x := int32(0); x < n; x++ { + Ax := A[x] + px := Ax & 0xffff + cx := px + if x < cx { + cx = x + } + B[x] = (px << 16) | cx + } + // B = (p<<16)+c + + for x := int32(0); x < n; x++ { + A[x] = (A[x] << 16) | x + } + int32Sort(A, n) // A = (id<<16)+pibar^-1 + + for x := int32(0); x < n; x++ { + // A = (pibar^(-1)<<16)+pibar + A[x] = (A[x] << 16) + (B[x] >> 16) + } + int32Sort(A, n) // A = (id<<16)+pibar^2 + + if w <= 10 { + for x := int32(0); x < n; x++ { + B[x] = ((A[x] & 0xffff) << 10) | (B[x] & 0x3ff) + } + + for i := int32(1); i < w-1; i++ { + /* B = (p<<10)+c */ + + for x := int32(0); x < n; x++ { + A[x] = ((B[x] & ^0x3ff) << 6) | x /* A = (p<<16)+id */ + } + int32Sort(A, n) /* A = (id<<16)+p^{-1} */ + + for x := int32(0); x < n; x++ { + A[x] = (A[x] << 20) | B[x] /* A = (p^{-1}<<20)+(p<<10)+c */ + } + int32Sort(A, n) /* A = (id<<20)+(pp<<10)+cp */ + + for x := int32(0); x < n; x++ { + ppcpx := A[x] & 0xfffff + ppcx := (A[x] & 0xffc00) | (B[x] & 0x3ff) + if ppcpx < ppcx { + ppcx = ppcpx + } + B[x] = ppcx + } + } + + for x := int32(0); x < n; x++ { + B[x] &= 0x3ff + } + } else { + for x := int32(0); x < n; x++ { + B[x] = (A[x] << 16) | (B[x] & 0xffff) + } + + for i := int32(1); i < w-1; i++ { + /* B = (p<<16)+c */ + + for x := int32(0); x < n; x++ { + A[x] = (B[x] &^ 0xffff) | x + } + int32Sort(A, n) /* A = (id<<16)+p^(-1) */ + + for x := int32(0); x < n; x++ { + A[x] = (A[x] << 16) | (B[x] & 0xffff) + } + /* A = p^(-1)<<16+c */ + + if i < w-2 { + for x := int32(0); x < n; x++ { + B[x] = (A[x] & ^0xffff) | (B[x] >> 16) + } + /* B = (p^(-1)<<16)+p */ + int32Sort(B, n) /* B = (id<<16)+p^(-2) */ + for x := int32(0); x < n; x++ { + B[x] = (B[x] << 16) | (A[x] & 0xffff) + } + /* B = (p^(-2)<<16)+c */ + } + + int32Sort(A, n) + /* A = id<<16+cp */ + for x := int32(0); x < n; x++ { + cpx := (B[x] & ^0xffff) | (A[x] & 0xffff) + if cpx < B[x] { + B[x] = cpx + } + } + } + + for x := int32(0); x < n; x++ { + B[x] &= 0xffff + } + } + + for x := int32(0); x < n; x++ { + A[x] = (int32(pi[x]) << 16) + x + } + int32Sort(A, n) /* A = (id<<16)+pi^(-1) */ + + for j := int32(0); j < n/2; j++ { + x := 2 * j + fj := B[x] & 1 /* f[j] */ + Fx := x + fj /* F[x] */ + Fx1 := Fx ^ 1 /* F[x+1] */ + + out[pos>>3] ^= byte(fj << (pos & 7)) + pos += step + + B[x] = (A[x] << 16) | Fx + B[x+1] = (A[x+1] << 16) | Fx1 + } + /* B = (pi^(-1)<<16)+F */ + + int32Sort(B, n) /* B = (id<<16)+F(pi) */ + + pos += int(2*w-3) * step * int(n/2) + + for k := int32(0); k < n/2; k++ { + y := 2 * k + lk := B[y] & 1 /* l[k] */ + Ly := y + lk /* L[y] */ + Ly1 := Ly ^ 1 /* L[y+1] */ + + out[pos>>3] ^= byte(lk << (pos & 7)) + pos += step + + A[y] = (Ly << 16) | (B[y] & 0xffff) + A[y+1] = (Ly1 << 16) | (B[y+1] & 0xffff) + } + /* A = (L<<16)+F(pi) */ + + int32Sort(A, n) /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= int(2*w-2) * step * int(n/2) + + p := (*int16)(unsafe.Pointer(&temp[n+n/4])) + q := unsafe.Slice(p, n) // q can start anywhere between temp+n and temp+n/2 + for j := int32(0); j < n/2; j++ { + q[j] = int16(A[2*j]&0xffff) >> 1 + q[j+n/2] = int16(A[2*j+1]&0xffff) >> 1 + } + + cbRecursion(out, pos, step*2, q, w-1, n/2, temp) + cbRecursion(out, pos+step, step*2, q[n/2:], w-1, n/2, temp) +} + +// ControlBitsFromPermutation computes control bits +// parameters: 1 <= w <= 14; n = 2^w +// input: permutation pi of {0,1,...,n-1} +// output: (2m-1)n/2 control bits at positions 0,1,... +// output position pos is by definition 1&(out[pos/8]>>(pos&7)) +func ControlBitsFromPermutation(out []byte, pi []int16, w, n int32) { + temp := make([]int32, 2*n) + piTest := make([]int16, n) + var ptr []byte + for { + for i := 0; i < int(((2*w-1)*n/2)+7)/8; i++ { + out[i] = 0 + } + + cbRecursion(out, 0, 1, pi[:], w, n, temp) + // check for correctness + + for i := int32(0); i < n; i++ { + piTest[i] = int16(i) + } + + ptr = out + for i := 0; i < int(w); i++ { + layer(piTest, ptr, i, int(n)) + ptr = ptr[n>>4:] + } + + for i := int(w - 2); i >= 0; i-- { + layer(piTest, ptr, i, int(n)) + ptr = ptr[n>>4:] + } + + diff := int16(0) + for i := int32(0); i < n; i++ { + diff |= pi[i] ^ piTest[i] + } + + if diff == 0 { + break + } + } +} diff --git a/pqhs/mceliece6960119/internal/djbsort.go b/pqhs/mceliece6960119/internal/djbsort.go new file mode 100644 index 0000000..72210b8 --- /dev/null +++ b/pqhs/mceliece6960119/internal/djbsort.go @@ -0,0 +1,92 @@ +package internal + +// Returns (min(a, b), max(a, b)), executes in constant time +func minMaxI32(a, b *int32) { + ab := *b ^ *a + c := *b - *a + c ^= ab & (c ^ *b) + c >>= 31 + c &= ab + *a ^= c + *b ^= c +} + +// Returns (min(a, b), max(a, b)), executes in constant time +// +// This differs from the C implementation, because the C implementation +// only works for 63-bit integers. +// +// Instead this implementation is based on +// “side-channel effective overflow check of variable c” +// from the book “Hacker's Delight” 2–13 Overflow Detection, +// Section Unsigned Add/Subtract p. 40 +func minMaxU64(a, b *uint64) { + c := (^*b & *a) | ((^*b | *a) & (*b - *a)) + c = -(c >> 63) + c &= *a ^ *b + *a ^= c + *b ^= c +} + +// Reference: [djbsort](https://sorting.cr.yp.to/). +func int32Sort(x []int32, n int32) { + if n < 2 { + return + } + top := int32(1) + for top < n-top { + top += top + } + for p := top; p > 0; p >>= 1 { + for i := int32(0); i < n-p; i++ { + if (i & p) == 0 { + minMaxI32(&x[i], &x[i+p]) + } + } + + i := int32(0) + for q := top; q > p; q >>= 1 { + for ; i < n-q; i++ { + if (i & p) == 0 { + a := x[i+p] + for r := q; r > p; r >>= 1 { + minMaxI32(&a, &x[i+r]) + } + x[i+p] = a + } + } + } + } +} + +// UInt64Sort sorts a slice of uint64 +// Reference: [djbsort](https://sorting.cr.yp.to/). +func UInt64Sort(x []uint64, n int) { + if n < 2 { + return + } + top := 1 + for top < n-top { + top += top + } + for p := top; p > 0; p >>= 1 { + for i := 0; i < n-p; i++ { + if (i & p) == 0 { + minMaxU64(&x[i], &x[i+p]) + } + } + + i := 0 + for q := top; q > p; q >>= 1 { + for ; i < n-q; i++ { + if (i & p) == 0 { + a := x[i+p] + for r := q; r > p; r >>= 1 { + minMaxU64(&a, &x[i+r]) + } + x[i+p] = a + } + } + } + } +} diff --git a/pqhs/mceliece6960119/internal/fft_const.go b/pqhs/mceliece6960119/internal/fft_const.go new file mode 100644 index 0000000..476eb3f --- /dev/null +++ b/pqhs/mceliece6960119/internal/fft_const.go @@ -0,0 +1,3096 @@ +package internal + +import ( + "go.stargrave.org/vors/v5/pqhs/mceliece6960119/math/gf2e12" + "go.stargrave.org/vors/v5/pqhs/mceliece6960119/math/gf2e13" +) + +var ButterfliesReversal4096 = [64]byte{ + 0, 32, 16, 48, 8, 40, 24, 56, + 4, 36, 20, 52, 12, 44, 28, 60, + 2, 34, 18, 50, 10, 42, 26, 58, + 6, 38, 22, 54, 14, 46, 30, 62, + 1, 33, 17, 49, 9, 41, 25, 57, + 5, 37, 21, 53, 13, 45, 29, 61, + 3, 35, 19, 51, 11, 43, 27, 59, + 7, 39, 23, 55, 15, 47, 31, 63, +} + +var ButterfliesReversal = [128]byte{ + 0, 64, 32, 96, 16, 80, 48, 112, + 8, 72, 40, 104, 24, 88, 56, 120, + 4, 68, 36, 100, 20, 84, 52, 116, + 12, 76, 44, 108, 28, 92, 60, 124, + 2, 66, 34, 98, 18, 82, 50, 114, + 10, 74, 42, 106, 26, 90, 58, 122, + 6, 70, 38, 102, 22, 86, 54, 118, + 14, 78, 46, 110, 30, 94, 62, 126, + 1, 65, 33, 97, 17, 81, 49, 113, + 9, 73, 41, 105, 25, 89, 57, 121, + 5, 69, 37, 101, 21, 85, 53, 117, + 13, 77, 45, 109, 29, 93, 61, 125, + 3, 67, 35, 99, 19, 83, 51, 115, + 11, 75, 43, 107, 27, 91, 59, 123, + 7, 71, 39, 103, 23, 87, 55, 119, + 15, 79, 47, 111, 31, 95, 63, 127, +} + +var ButterfliesBeta = [7]uint16{2522, 7827, 7801, 8035, 6897, 8167, 3476} + +var RadixConversionsMask = [5][2]uint64{ + {0x8888888888888888, 0x4444444444444444}, + {0xC0C0C0C0C0C0C0C0, 0x3030303030303030}, + {0xF000F000F000F000, 0x0F000F000F000F00}, + {0xFF000000FF000000, 0x00FF000000FF0000}, + {0xFFFF000000000000, 0x0000FFFF00000000}, +} + +var ButterfliesConst = [128][gf2e13.Bits]uint64{ + { + 0x6969969669699696, + 0x9966669966999966, + 0x9966669966999966, + 0xFF0000FF00FFFF00, + 0xCC3333CCCC3333CC, + 0x9966669966999966, + 0x6666666666666666, + 0xA55AA55AA55AA55A, + 0xCCCC33333333CCCC, + 0x5A5A5A5A5A5A5A5A, + 0x55AAAA55AA5555AA, + 0x0FF0F00FF00F0FF0, + 0x5AA55AA5A55AA55A, + }, + { + 0x6969969669699696, + 0x9966669966999966, + 0x9966669966999966, + 0xFF0000FF00FFFF00, + 0xCC3333CCCC3333CC, + 0x9966669966999966, + 0x6666666666666666, + 0xA55AA55AA55AA55A, + 0xCCCC33333333CCCC, + 0x5A5A5A5A5A5A5A5A, + 0x55AAAA55AA5555AA, + 0x0FF0F00FF00F0FF0, + 0x5AA55AA5A55AA55A, + }, + { + 0xA55A5AA55AA5A55A, + 0x6969696996969696, + 0x5AA55AA5A55AA55A, + 0x9999999966666666, + 0x3C3CC3C3C3C33C3C, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xCC33CC3333CC33CC, + 0x0000000000000000, + 0x3C3C3C3C3C3C3C3C, + 0xAA5555AAAA5555AA, + 0xC33C3CC33CC3C33C, + 0x00FFFF0000FFFF00, + }, + { + 0xA55A5AA55AA5A55A, + 0x6969696996969696, + 0x5AA55AA5A55AA55A, + 0x6666666699999999, + 0xC3C33C3C3C3CC3C3, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x33CC33CCCC33CC33, + 0x0000000000000000, + 0x3C3C3C3C3C3C3C3C, + 0xAA5555AAAA5555AA, + 0xC33C3CC33CC3C33C, + 0xFF0000FFFF0000FF, + }, + { + 0xFFFFFFFF00000000, + 0xA5A5A5A55A5A5A5A, + 0x0FF0F00FF00F0FF0, + 0x9669966969966996, + 0x0000FFFFFFFF0000, + 0x33333333CCCCCCCC, + 0xA55A5AA55AA5A55A, + 0x00FFFF0000FFFF00, + 0x0000000000000000, + 0xC33CC33CC33CC33C, + 0x0F0FF0F00F0FF0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAA55555555AAAA, + }, + { + 0xFFFFFFFF00000000, + 0xA5A5A5A55A5A5A5A, + 0x0FF0F00FF00F0FF0, + 0x6996699696699669, + 0xFFFF00000000FFFF, + 0x33333333CCCCCCCC, + 0x5AA5A55AA55A5AA5, + 0xFF0000FFFF0000FF, + 0xFFFFFFFFFFFFFFFF, + 0xC33CC33CC33CC33C, + 0x0F0FF0F00F0FF0F0, + 0xCCCCCCCCCCCCCCCC, + 0x5555AAAAAAAA5555, + }, + { + 0xFFFFFFFF00000000, + 0x5A5A5A5AA5A5A5A5, + 0xF00F0FF00FF0F00F, + 0x6996699696699669, + 0x0000FFFFFFFF0000, + 0x33333333CCCCCCCC, + 0x5AA5A55AA55A5AA5, + 0xFF0000FFFF0000FF, + 0xFFFFFFFFFFFFFFFF, + 0xC33CC33CC33CC33C, + 0x0F0FF0F00F0FF0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAA55555555AAAA, + }, + { + 0xFFFFFFFF00000000, + 0x5A5A5A5AA5A5A5A5, + 0xF00F0FF00FF0F00F, + 0x9669966969966996, + 0xFFFF00000000FFFF, + 0x33333333CCCCCCCC, + 0xA55A5AA55AA5A55A, + 0x00FFFF0000FFFF00, + 0x0000000000000000, + 0xC33CC33CC33CC33C, + 0x0F0FF0F00F0FF0F0, + 0xCCCCCCCCCCCCCCCC, + 0x5555AAAAAAAA5555, + }, + { + 0xC33C3CC33CC3C33C, + 0x9966669966999966, + 0x9966996699669966, + 0x6969969669699696, + 0xAA55AA5555AA55AA, + 0x9966996699669966, + 0x5AA5A55A5AA5A55A, + 0xC3C3C3C33C3C3C3C, + 0x3CC33CC3C33CC33C, + 0x3333CCCC3333CCCC, + 0x9999999966666666, + 0xC33CC33CC33CC33C, + 0x6666999999996666, + }, + { + 0x3CC3C33CC33C3CC3, + 0x6699996699666699, + 0x6699669966996699, + 0x6969969669699696, + 0xAA55AA5555AA55AA, + 0x9966996699669966, + 0xA55A5AA5A55A5AA5, + 0xC3C3C3C33C3C3C3C, + 0x3CC33CC3C33CC33C, + 0x3333CCCC3333CCCC, + 0x6666666699999999, + 0x3CC33CC33CC33CC3, + 0x9999666666669999, + }, + { + 0xC33C3CC33CC3C33C, + 0x9966669966999966, + 0x6699669966996699, + 0x6969969669699696, + 0xAA55AA5555AA55AA, + 0x6699669966996699, + 0x5AA5A55A5AA5A55A, + 0x3C3C3C3CC3C3C3C3, + 0xC33CC33C3CC33CC3, + 0xCCCC3333CCCC3333, + 0x6666666699999999, + 0xC33CC33CC33CC33C, + 0x9999666666669999, + }, + { + 0x3CC3C33CC33C3CC3, + 0x6699996699666699, + 0x9966996699669966, + 0x6969969669699696, + 0xAA55AA5555AA55AA, + 0x6699669966996699, + 0xA55A5AA5A55A5AA5, + 0x3C3C3C3CC3C3C3C3, + 0xC33CC33C3CC33CC3, + 0xCCCC3333CCCC3333, + 0x9999999966666666, + 0x3CC33CC33CC33CC3, + 0x6666999999996666, + }, + { + 0xC33C3CC33CC3C33C, + 0x6699996699666699, + 0x6699669966996699, + 0x6969969669699696, + 0x55AA55AAAA55AA55, + 0x9966996699669966, + 0x5AA5A55A5AA5A55A, + 0xC3C3C3C33C3C3C3C, + 0xC33CC33C3CC33CC3, + 0x3333CCCC3333CCCC, + 0x9999999966666666, + 0xC33CC33CC33CC33C, + 0x6666999999996666, + }, + { + 0x3CC3C33CC33C3CC3, + 0x9966669966999966, + 0x9966996699669966, + 0x6969969669699696, + 0x55AA55AAAA55AA55, + 0x9966996699669966, + 0xA55A5AA5A55A5AA5, + 0xC3C3C3C33C3C3C3C, + 0xC33CC33C3CC33CC3, + 0x3333CCCC3333CCCC, + 0x6666666699999999, + 0x3CC33CC33CC33CC3, + 0x9999666666669999, + }, + { + 0xC33C3CC33CC3C33C, + 0x6699996699666699, + 0x9966996699669966, + 0x6969969669699696, + 0x55AA55AAAA55AA55, + 0x6699669966996699, + 0x5AA5A55A5AA5A55A, + 0x3C3C3C3CC3C3C3C3, + 0x3CC33CC3C33CC33C, + 0xCCCC3333CCCC3333, + 0x6666666699999999, + 0xC33CC33CC33CC33C, + 0x9999666666669999, + }, + { + 0x3CC3C33CC33C3CC3, + 0x9966669966999966, + 0x6699669966996699, + 0x6969969669699696, + 0x55AA55AAAA55AA55, + 0x6699669966996699, + 0xA55A5AA5A55A5AA5, + 0x3C3C3C3CC3C3C3C3, + 0x3CC33CC3C33CC33C, + 0xCCCC3333CCCC3333, + 0x9999999966666666, + 0x3CC33CC33CC33CC3, + 0x6666999999996666, + }, + { + 0x3C3CC3C3C3C33C3C, + 0x55555555AAAAAAAA, + 0xF00FF00F0FF00FF0, + 0x5AA55AA5A55AA55A, + 0x55AAAA55AA5555AA, + 0xF00F0FF0F00F0FF0, + 0x9669699696696996, + 0xA55AA55AA55AA55A, + 0x55555555AAAAAAAA, + 0xCCCC33333333CCCC, + 0x0000FFFFFFFF0000, + 0xFF0000FF00FFFF00, + 0x6996699669966996, + }, + { + 0xC3C33C3C3C3CC3C3, + 0x55555555AAAAAAAA, + 0x0FF00FF0F00FF00F, + 0x5AA55AA5A55AA55A, + 0x55AAAA55AA5555AA, + 0xF00F0FF0F00F0FF0, + 0x9669699696696996, + 0x5AA55AA55AA55AA5, + 0x55555555AAAAAAAA, + 0x3333CCCCCCCC3333, + 0x0000FFFFFFFF0000, + 0x00FFFF00FF0000FF, + 0x9669966996699669, + }, + { + 0x3C3CC3C3C3C33C3C, + 0x55555555AAAAAAAA, + 0xF00FF00F0FF00FF0, + 0xA55AA55A5AA55AA5, + 0xAA5555AA55AAAA55, + 0x0FF0F00F0FF0F00F, + 0x9669699696696996, + 0x5AA55AA55AA55AA5, + 0xAAAAAAAA55555555, + 0x3333CCCCCCCC3333, + 0xFFFF00000000FFFF, + 0xFF0000FF00FFFF00, + 0x9669966996699669, + }, + { + 0xC3C33C3C3C3CC3C3, + 0x55555555AAAAAAAA, + 0x0FF00FF0F00FF00F, + 0xA55AA55A5AA55AA5, + 0xAA5555AA55AAAA55, + 0x0FF0F00F0FF0F00F, + 0x9669699696696996, + 0xA55AA55AA55AA55A, + 0xAAAAAAAA55555555, + 0xCCCC33333333CCCC, + 0xFFFF00000000FFFF, + 0x00FFFF00FF0000FF, + 0x6996699669966996, + }, + { + 0x3C3CC3C3C3C33C3C, + 0x55555555AAAAAAAA, + 0x0FF00FF0F00FF00F, + 0xA55AA55A5AA55AA5, + 0xAA5555AA55AAAA55, + 0x0FF0F00F0FF0F00F, + 0x6996966969969669, + 0xA55AA55AA55AA55A, + 0xAAAAAAAA55555555, + 0xCCCC33333333CCCC, + 0x0000FFFFFFFF0000, + 0xFF0000FF00FFFF00, + 0x6996699669966996, + }, + { + 0xC3C33C3C3C3CC3C3, + 0x55555555AAAAAAAA, + 0xF00FF00F0FF00FF0, + 0xA55AA55A5AA55AA5, + 0xAA5555AA55AAAA55, + 0x0FF0F00F0FF0F00F, + 0x6996966969969669, + 0x5AA55AA55AA55AA5, + 0xAAAAAAAA55555555, + 0x3333CCCCCCCC3333, + 0x0000FFFFFFFF0000, + 0x00FFFF00FF0000FF, + 0x9669966996699669, + }, + { + 0x3C3CC3C3C3C33C3C, + 0x55555555AAAAAAAA, + 0x0FF00FF0F00FF00F, + 0x5AA55AA5A55AA55A, + 0x55AAAA55AA5555AA, + 0xF00F0FF0F00F0FF0, + 0x6996966969969669, + 0x5AA55AA55AA55AA5, + 0x55555555AAAAAAAA, + 0x3333CCCCCCCC3333, + 0xFFFF00000000FFFF, + 0xFF0000FF00FFFF00, + 0x9669966996699669, + }, + { + 0xC3C33C3C3C3CC3C3, + 0x55555555AAAAAAAA, + 0xF00FF00F0FF00FF0, + 0x5AA55AA5A55AA55A, + 0x55AAAA55AA5555AA, + 0xF00F0FF0F00F0FF0, + 0x6996966969969669, + 0xA55AA55AA55AA55A, + 0x55555555AAAAAAAA, + 0xCCCC33333333CCCC, + 0xFFFF00000000FFFF, + 0x00FFFF00FF0000FF, + 0x6996699669966996, + }, + { + 0x3C3CC3C3C3C33C3C, + 0xAAAAAAAA55555555, + 0x0FF00FF0F00FF00F, + 0x5AA55AA5A55AA55A, + 0xAA5555AA55AAAA55, + 0xF00F0FF0F00F0FF0, + 0x9669699696696996, + 0xA55AA55AA55AA55A, + 0x55555555AAAAAAAA, + 0xCCCC33333333CCCC, + 0x0000FFFFFFFF0000, + 0xFF0000FF00FFFF00, + 0x6996699669966996, + }, + { + 0xC3C33C3C3C3CC3C3, + 0xAAAAAAAA55555555, + 0xF00FF00F0FF00FF0, + 0x5AA55AA5A55AA55A, + 0xAA5555AA55AAAA55, + 0xF00F0FF0F00F0FF0, + 0x9669699696696996, + 0x5AA55AA55AA55AA5, + 0x55555555AAAAAAAA, + 0x3333CCCCCCCC3333, + 0x0000FFFFFFFF0000, + 0x00FFFF00FF0000FF, + 0x9669966996699669, + }, + { + 0x3C3CC3C3C3C33C3C, + 0xAAAAAAAA55555555, + 0x0FF00FF0F00FF00F, + 0xA55AA55A5AA55AA5, + 0x55AAAA55AA5555AA, + 0x0FF0F00F0FF0F00F, + 0x9669699696696996, + 0x5AA55AA55AA55AA5, + 0xAAAAAAAA55555555, + 0x3333CCCCCCCC3333, + 0xFFFF00000000FFFF, + 0xFF0000FF00FFFF00, + 0x9669966996699669, + }, + { + 0xC3C33C3C3C3CC3C3, + 0xAAAAAAAA55555555, + 0xF00FF00F0FF00FF0, + 0xA55AA55A5AA55AA5, + 0x55AAAA55AA5555AA, + 0x0FF0F00F0FF0F00F, + 0x9669699696696996, + 0xA55AA55AA55AA55A, + 0xAAAAAAAA55555555, + 0xCCCC33333333CCCC, + 0xFFFF00000000FFFF, + 0x00FFFF00FF0000FF, + 0x6996699669966996, + }, + { + 0x3C3CC3C3C3C33C3C, + 0xAAAAAAAA55555555, + 0xF00FF00F0FF00FF0, + 0xA55AA55A5AA55AA5, + 0x55AAAA55AA5555AA, + 0x0FF0F00F0FF0F00F, + 0x6996966969969669, + 0xA55AA55AA55AA55A, + 0xAAAAAAAA55555555, + 0xCCCC33333333CCCC, + 0x0000FFFFFFFF0000, + 0xFF0000FF00FFFF00, + 0x6996699669966996, + }, + { + 0xC3C33C3C3C3CC3C3, + 0xAAAAAAAA55555555, + 0x0FF00FF0F00FF00F, + 0xA55AA55A5AA55AA5, + 0x55AAAA55AA5555AA, + 0x0FF0F00F0FF0F00F, + 0x6996966969969669, + 0x5AA55AA55AA55AA5, + 0xAAAAAAAA55555555, + 0x3333CCCCCCCC3333, + 0x0000FFFFFFFF0000, + 0x00FFFF00FF0000FF, + 0x9669966996699669, + }, + { + 0x3C3CC3C3C3C33C3C, + 0xAAAAAAAA55555555, + 0xF00FF00F0FF00FF0, + 0x5AA55AA5A55AA55A, + 0xAA5555AA55AAAA55, + 0xF00F0FF0F00F0FF0, + 0x6996966969969669, + 0x5AA55AA55AA55AA5, + 0x55555555AAAAAAAA, + 0x3333CCCCCCCC3333, + 0xFFFF00000000FFFF, + 0xFF0000FF00FFFF00, + 0x9669966996699669, + }, + { + 0xC3C33C3C3C3CC3C3, + 0xAAAAAAAA55555555, + 0x0FF00FF0F00FF00F, + 0x5AA55AA5A55AA55A, + 0xAA5555AA55AAAA55, + 0xF00F0FF0F00F0FF0, + 0x6996966969969669, + 0xA55AA55AA55AA55A, + 0x55555555AAAAAAAA, + 0xCCCC33333333CCCC, + 0xFFFF00000000FFFF, + 0x00FFFF00FF0000FF, + 0x6996699669966996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0xAAAAAAAAAAAAAAAA, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0x0000FFFF0000FFFF, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0xC33C3CC3C33C3CC3, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0x55AA55AA55AA55AA, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0xFFFF0000FFFF0000, + 0x0F0F0F0FF0F0F0F0, + 0x00FFFF00FF0000FF, + 0xCC3333CC33CCCC33, + 0xFF0000FF00FFFF00, + 0x6996966996696996, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x3CC3C33C3CC3C33C, + 0x5555555555555555, + 0xFFFF0000FFFF0000, + 0x3CC3C33C3CC3C33C, + 0xAA55AA55AA55AA55, + 0x0000FFFF0000FFFF, + 0xF0F0F0F00F0F0F0F, + 0xFF0000FF00FFFF00, + 0x33CCCC33CC3333CC, + 0x00FFFF00FF0000FF, + 0x9669699669969669, + 0xA55A5AA55AA5A55A, + 0x6996966996696996, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, +} + +var RadixConversionsS = [5][2][gf2e13.Bits]uint64{ + { + { + 0x3C3CF30C0000C003, + 0x0CCCC3F333C0000C, + 0x03C33F33FCC0C03C, + 0x0003000F3C03C0C0, + 0xF33FF33030CF03F0, + 0x0CF0303300F0CCC0, + 0xFF3F0C0CC0FF3CC0, + 0xCF3CF0FF003FC000, + 0xC00FF3CF0303F300, + 0x3CCC0CC00CF0CC00, + 0xF30FFC3C3FCCFC00, + 0x3F0FC3F0CCF0C000, + 0x3000FF33CCF0F000, + }, + { + 0x0C0F0FCF0F0CF330, + 0xF0000FC33C3CCF3C, + 0x3C0F3F00C3C300FC, + 0x3C33CCC0F0F3CC30, + 0xC0CFFFFFCCCC30CC, + 0x3FC3F3CCFFFC033F, + 0xFC3030CCCCC0CFCF, + 0x0FCF0C00CCF333C3, + 0xCFFCF33000CFF030, + 0x00CFFCC330F30FCC, + 0x3CCC3FCCC0F3FFF3, + 0xF00F0C3FC003C0FF, + 0x330CCFCC03C0FC33, + }, + }, + { + { + 0x0F0F0FF0F000000F, + 0x00FFFFFFFF0000F0, + 0xFFFF00FF00000F00, + 0xFFF000F00F0FF000, + 0xFFF0000F0FF000F0, + 0x00FF000FFF000000, + 0xFF0F0FFF0F0FF000, + 0x0FFF0000000F0000, + 0x00F000F0FFF00F00, + 0x00F00FF00F00F000, + 0xFFF000F000F00000, + 0x00F00F000FF00000, + 0x0000FF0F0000F000, + }, + { + 0xF0FFFFFFF0F00F00, + 0x00FFF0FFFF0000FF, + 0x00FF00000F0F0FFF, + 0xF000F0000F00FF0F, + 0xFF000000FFF00000, + 0xF0FF000FF00F0FF0, + 0x0F0F0F00FF000F0F, + 0x0F0F00F0F0F0F000, + 0x00F00F00F00F000F, + 0x00F0F0F00000FFF0, + 0xFFFFFF0FF00F0FFF, + 0x0F0FFFF00FFFFFFF, + 0xFFFF0F0FFF0FFF00, + }, + }, + { + { + 0x00FF0000000000FF, + 0xFFFFFFFFFF00FF00, + 0xFF0000FF00FF0000, + 0xFFFF000000FF0000, + 0xFF00000000FF0000, + 0x00FFFFFFFF000000, + 0xFF0000FFFFFF0000, + 0xFF00FF00FFFF0000, + 0x00FFFFFFFF00FF00, + 0xFFFF000000000000, + 0x00FF0000FF000000, + 0xFF00FF00FF000000, + 0x00FF00FFFF000000, + }, + { + 0x00FF00FF00FF0000, + 0xFF00FFFF000000FF, + 0x0000FFFF000000FF, + 0x00FFFF00FF000000, + 0xFFFFFF0000FF00FF, + 0x0000FFFF00FFFF00, + 0xFF00FF0000FFFF00, + 0x00000000FFFFFFFF, + 0x0000FF0000000000, + 0xFF00FFFF00FFFF00, + 0x00FFFF00000000FF, + 0x0000FF00FF00FFFF, + 0xFF0000FFFFFF0000, + }, + }, + { + { + 0x000000000000FFFF, + 0xFFFFFFFFFFFF0000, + 0x0000000000000000, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFF0000, + 0x0000FFFF00000000, + 0x0000FFFFFFFF0000, + 0xFFFF0000FFFF0000, + 0x0000FFFF00000000, + 0xFFFF000000000000, + 0xFFFF000000000000, + 0xFFFF000000000000, + 0xFFFFFFFF00000000, + }, + { + 0x0000FFFF00000000, + 0xFFFFFFFF0000FFFF, + 0x00000000FFFFFFFF, + 0x0000000000000000, + 0x0000FFFF00000000, + 0xFFFF0000FFFF0000, + 0x0000FFFFFFFF0000, + 0x0000FFFF0000FFFF, + 0xFFFFFFFF0000FFFF, + 0x00000000FFFF0000, + 0xFFFF0000FFFFFFFF, + 0xFFFF0000FFFFFFFF, + 0x0000000000000000, + }, + }, + { + { + 0x00000000FFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFFFFFF00000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x00000000FFFFFFFF, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x00000000FFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + }, + }, +} + +var RadixConversionsS4096 = [5][gf2e12.Bits]uint64{ + { + 0xF3CFC030FC30F003, + 0x3FCF0F003C00C00C, + 0x30033CC300C0C03C, + 0xCCFF0F3C0F30F0C0, + 0x0300C03FF303C3F0, + 0x3FFF3C0FF0CCCCC0, + 0xF3FFF0C00F3C3CC0, + 0x3003333FFFC3C000, + 0x0FF30FFFC3FFF300, + 0xFFC0F300F0F0CC00, + 0xC0CFF3FCCC3CFC00, + 0xFC3C03F0F330C000, + }, + { + 0x000F00000000F00F, + 0x00000F00F00000F0, + 0x0F00000F00000F00, + 0xF00F00F00F000000, + 0x00F00000000000F0, + 0x0000000F00000000, + 0xF00000000F00F000, + 0x00F00F00000F0000, + 0x0000F00000F00F00, + 0x000F00F00F00F000, + 0x00F00F0000000000, + 0x0000000000F00000, + }, + { + 0x0000FF00FF0000FF, + 0x0000FF000000FF00, + 0xFF0000FF00FF0000, + 0xFFFF0000FF000000, + 0x00FF00FF00FF0000, + 0x0000FFFFFF000000, + 0x00FFFF00FF000000, + 0xFFFFFF0000FF0000, + 0xFFFF00FFFF00FF00, + 0x0000FF0000000000, + 0xFFFFFF00FF000000, + 0x00FF000000000000, + }, + { + 0x000000000000FFFF, + 0x00000000FFFF0000, + 0x0000000000000000, + 0xFFFF000000000000, + 0x00000000FFFF0000, + 0x0000FFFF00000000, + 0x0000000000000000, + 0x00000000FFFF0000, + 0x0000FFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + }, + { + 0x00000000FFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + }, +} + +var ButterfliesConsts4096 = [63][gf2e12.Bits]uint64{ + // 64 + { + 0xF00F0FF0F00F0FF0, + 0xF0F00F0F0F0FF0F0, + 0x0FF00FF00FF00FF0, + 0xAA5555AAAA5555AA, + 0xF00F0FF0F00F0FF0, + 0x33CCCC33CC3333CC, + 0xFFFF0000FFFF0000, + 0xCC33CC3333CC33CC, + 0x33CC33CC33CC33CC, + 0x5A5A5A5A5A5A5A5A, + 0xFF00FF00FF00FF00, + 0xF00F0FF0F00F0FF0, + }, + // 128 + { + 0x3C3C3C3C3C3C3C3C, + 0xF0F0F0F0F0F0F0F0, + 0x5555AAAA5555AAAA, + 0xCC3333CCCC3333CC, + 0xC33CC33CC33CC33C, + 0x55555555AAAAAAAA, + 0x33333333CCCCCCCC, + 0x00FF00FFFF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x0000FFFFFFFF0000, + 0xF0F00F0F0F0FF0F0, + }, + { + 0x3C3C3C3C3C3C3C3C, + 0x0F0F0F0F0F0F0F0F, + 0xAAAA5555AAAA5555, + 0xCC3333CCCC3333CC, + 0xC33CC33CC33CC33C, + 0x55555555AAAAAAAA, + 0x33333333CCCCCCCC, + 0xFF00FF0000FF00FF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x0000FFFFFFFF0000, + 0xF0F00F0F0F0FF0F0, + }, + // 256 + { + 0xAA55AA5555AA55AA, + 0xCC33CC3333CC33CC, + 0x33CCCC33CC3333CC, + 0x55555555AAAAAAAA, + 0xFF0000FF00FFFF00, + 0x3CC33CC3C33CC33C, + 0x5555AAAA5555AAAA, + 0x0FF00FF00FF00FF0, + 0xCCCC33333333CCCC, + 0xF0F0F0F0F0F0F0F0, + 0x00FFFF0000FFFF00, + 0xC33CC33CC33CC33C, + }, + { + 0x55AA55AAAA55AA55, + 0xCC33CC3333CC33CC, + 0xCC3333CC33CCCC33, + 0x55555555AAAAAAAA, + 0xFF0000FF00FFFF00, + 0xC33CC33C3CC33CC3, + 0xAAAA5555AAAA5555, + 0xF00FF00FF00FF00F, + 0x3333CCCCCCCC3333, + 0x0F0F0F0F0F0F0F0F, + 0xFF0000FFFF0000FF, + 0xC33CC33CC33CC33C, + }, + { + 0xAA55AA5555AA55AA, + 0x33CC33CCCC33CC33, + 0xCC3333CC33CCCC33, + 0x55555555AAAAAAAA, + 0x00FFFF00FF0000FF, + 0x3CC33CC3C33CC33C, + 0x5555AAAA5555AAAA, + 0x0FF00FF00FF00FF0, + 0x3333CCCCCCCC3333, + 0xF0F0F0F0F0F0F0F0, + 0x00FFFF0000FFFF00, + 0xC33CC33CC33CC33C, + }, + { + 0x55AA55AAAA55AA55, + 0x33CC33CCCC33CC33, + 0x33CCCC33CC3333CC, + 0x55555555AAAAAAAA, + 0x00FFFF00FF0000FF, + 0xC33CC33C3CC33CC3, + 0xAAAA5555AAAA5555, + 0xF00FF00FF00FF00F, + 0xCCCC33333333CCCC, + 0x0F0F0F0F0F0F0F0F, + 0xFF0000FFFF0000FF, + 0xC33CC33CC33CC33C, + }, + // 512 + { + 0x6699669999669966, + 0x33CCCC33CC3333CC, + 0xA5A5A5A55A5A5A5A, + 0x3C3CC3C3C3C33C3C, + 0xF00FF00F0FF00FF0, + 0x55AA55AA55AA55AA, + 0x3C3CC3C3C3C33C3C, + 0x0F0F0F0FF0F0F0F0, + 0x55AA55AA55AA55AA, + 0x33CCCC33CC3333CC, + 0xF0F0F0F0F0F0F0F0, + 0xA55A5AA55AA5A55A, + }, + { + 0x9966996666996699, + 0x33CCCC33CC3333CC, + 0xA5A5A5A55A5A5A5A, + 0x3C3CC3C3C3C33C3C, + 0x0FF00FF0F00FF00F, + 0xAA55AA55AA55AA55, + 0x3C3CC3C3C3C33C3C, + 0xF0F0F0F00F0F0F0F, + 0xAA55AA55AA55AA55, + 0xCC3333CC33CCCC33, + 0x0F0F0F0F0F0F0F0F, + 0xA55A5AA55AA5A55A, + }, + { + 0x6699669999669966, + 0x33CCCC33CC3333CC, + 0x5A5A5A5AA5A5A5A5, + 0xC3C33C3C3C3CC3C3, + 0x0FF00FF0F00FF00F, + 0xAA55AA55AA55AA55, + 0xC3C33C3C3C3CC3C3, + 0x0F0F0F0FF0F0F0F0, + 0xAA55AA55AA55AA55, + 0x33CCCC33CC3333CC, + 0xF0F0F0F0F0F0F0F0, + 0xA55A5AA55AA5A55A, + }, + { + 0x9966996666996699, + 0x33CCCC33CC3333CC, + 0x5A5A5A5AA5A5A5A5, + 0xC3C33C3C3C3CC3C3, + 0xF00FF00F0FF00FF0, + 0x55AA55AA55AA55AA, + 0xC3C33C3C3C3CC3C3, + 0xF0F0F0F00F0F0F0F, + 0x55AA55AA55AA55AA, + 0xCC3333CC33CCCC33, + 0x0F0F0F0F0F0F0F0F, + 0xA55A5AA55AA5A55A, + }, + { + 0x6699669999669966, + 0xCC3333CC33CCCC33, + 0x5A5A5A5AA5A5A5A5, + 0x3C3CC3C3C3C33C3C, + 0x0FF00FF0F00FF00F, + 0x55AA55AA55AA55AA, + 0x3C3CC3C3C3C33C3C, + 0x0F0F0F0FF0F0F0F0, + 0x55AA55AA55AA55AA, + 0x33CCCC33CC3333CC, + 0xF0F0F0F0F0F0F0F0, + 0xA55A5AA55AA5A55A, + }, + { + 0x9966996666996699, + 0xCC3333CC33CCCC33, + 0x5A5A5A5AA5A5A5A5, + 0x3C3CC3C3C3C33C3C, + 0xF00FF00F0FF00FF0, + 0xAA55AA55AA55AA55, + 0x3C3CC3C3C3C33C3C, + 0xF0F0F0F00F0F0F0F, + 0xAA55AA55AA55AA55, + 0xCC3333CC33CCCC33, + 0x0F0F0F0F0F0F0F0F, + 0xA55A5AA55AA5A55A, + }, + { + 0x6699669999669966, + 0xCC3333CC33CCCC33, + 0xA5A5A5A55A5A5A5A, + 0xC3C33C3C3C3CC3C3, + 0xF00FF00F0FF00FF0, + 0xAA55AA55AA55AA55, + 0xC3C33C3C3C3CC3C3, + 0x0F0F0F0FF0F0F0F0, + 0xAA55AA55AA55AA55, + 0x33CCCC33CC3333CC, + 0xF0F0F0F0F0F0F0F0, + 0xA55A5AA55AA5A55A, + }, + { + 0x9966996666996699, + 0xCC3333CC33CCCC33, + 0xA5A5A5A55A5A5A5A, + 0xC3C33C3C3C3CC3C3, + 0x0FF00FF0F00FF00F, + 0x55AA55AA55AA55AA, + 0xC3C33C3C3C3CC3C3, + 0xF0F0F0F00F0F0F0F, + 0x55AA55AA55AA55AA, + 0xCC3333CC33CCCC33, + 0x0F0F0F0F0F0F0F0F, + 0xA55A5AA55AA5A55A, + }, + // 1024 + { + 0x9669699696696996, + 0x6996699669966996, + 0x6996699669966996, + 0x00FFFF0000FFFF00, + 0xFF00FF00FF00FF00, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x6996699669966996, + 0x00FFFF0000FFFF00, + 0x00FF00FF00FF00FF, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x6996699669966996, + 0xFF0000FFFF0000FF, + 0x00FF00FF00FF00FF, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x6996699669966996, + 0xFF0000FFFF0000FF, + 0xFF00FF00FF00FF00, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x9669966996699669, + 0xFF0000FFFF0000FF, + 0x00FF00FF00FF00FF, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x9669966996699669, + 0xFF0000FFFF0000FF, + 0xFF00FF00FF00FF00, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x9669966996699669, + 0x00FFFF0000FFFF00, + 0xFF00FF00FF00FF00, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x6996699669966996, + 0x9669966996699669, + 0x00FFFF0000FFFF00, + 0x00FF00FF00FF00FF, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x9669966996699669, + 0x00FFFF0000FFFF00, + 0xFF00FF00FF00FF00, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x9669966996699669, + 0x00FFFF0000FFFF00, + 0x00FF00FF00FF00FF, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x9669966996699669, + 0xFF0000FFFF0000FF, + 0x00FF00FF00FF00FF, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x9669966996699669, + 0xFF0000FFFF0000FF, + 0xFF00FF00FF00FF00, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x6996699669966996, + 0xFF0000FFFF0000FF, + 0x00FF00FF00FF00FF, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x6996699669966996, + 0xFF0000FFFF0000FF, + 0xFF00FF00FF00FF00, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x6996699669966996, + 0x00FFFF0000FFFF00, + 0xFF00FF00FF00FF00, + 0x0FF00FF0F00FF00F, + 0x0F0FF0F0F0F00F0F, + 0xC33C3CC33CC3C33C, + 0xC33C3CC33CC3C33C, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + { + 0x9669699696696996, + 0x9669966996699669, + 0x6996699669966996, + 0x00FFFF0000FFFF00, + 0x00FF00FF00FF00FF, + 0xF00FF00F0FF00FF0, + 0xF0F00F0F0F0FF0F0, + 0x3CC3C33CC33C3CC3, + 0x3CC3C33CC33C3CC3, + 0xA55A5AA55AA5A55A, + 0xC33C3CC33CC3C33C, + 0x3CC3C33C3CC3C33C, + }, + // 2048 + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0000000000000000, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFF00000000, + 0xFFFF0000FFFF0000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCCCCCCCCCCCCCC, + 0xAAAAAAAAAAAAAAAA, + }, +} diff --git a/pqhs/mceliece6960119/internal/powers.go b/pqhs/mceliece6960119/internal/powers.go new file mode 100644 index 0000000..2d4c391 --- /dev/null +++ b/pqhs/mceliece6960119/internal/powers.go @@ -0,0 +1,2828 @@ +package internal + +import ( + "go.stargrave.org/vors/v5/pqhs/mceliece6960119/math/gf2e12" + "go.stargrave.org/vors/v5/pqhs/mceliece6960119/math/gf2e13" +) + +var Powers4096 = [64][gf2e12.Bits]uint64{ + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0x3333CCCC3333CCCC, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0x0000000000000000, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0xFF00FF00FF00FF00, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0xAAAAAAAAAAAAAAAA, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0xF0F0F0F00F0F0F0F, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0xF0F0F0F0F0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0xFFFF0000FFFF0000, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0x0000000000000000, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0xFFFFFFFFFFFFFFFF, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0xAA55AA55AA55AA55, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, + { + 0x0F0F0F0FF0F0F0F0, + 0x0000FFFF0000FFFF, + 0xFFFFFFFFFFFFFFFF, + 0x0F0F0F0F0F0F0F0F, + 0xFFFFFFFFFFFFFFFF, + 0x55AA55AA55AA55AA, + 0x0F0F0F0FF0F0F0F0, + 0x0000000000000000, + 0x00FF00FF00FF00FF, + 0xF0F0F0F0F0F0F0F0, + 0xCCCC3333CCCC3333, + 0x5555555555555555, + }, +} + +var Powers8192 = [128][gf2e13.Bits]uint64{ + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0x00000000FFFFFFFF, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0xCC33CC33CC33CC33, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0xCC33CC33CC33CC33, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x9696969669696969, + 0xA5A5A5A5A5A5A5A5, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0x0F0FF0F00F0FF0F0, + }, + { + 0xA55AA55A5AA55AA5, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0x5A5A5A5A5A5A5A5A, + 0xA5A5A5A55A5A5A5A, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0x3CC33CC3C33CC33C, + 0xA5A55A5AA5A55A5A, + 0x0000FFFF0000FFFF, + 0x33CC33CC33CC33CC, + 0xF00FF00F0FF00FF0, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0x5555AAAAAAAA5555, + 0xF00FF00FF00FF00F, + 0xF0F00F0FF0F00F0F, + }, + { + 0x5AA55AA5A55AA55A, + 0xC33CC33C3CC33CC3, + 0xA5A55A5AA5A55A5A, + 0xFFFF0000FFFF0000, + 0x33CC33CC33CC33CC, + 0x0FF00FF0F00FF00F, + 0xFFFFFFFF00000000, + 0x6969696996969696, + 0xA5A5A5A5A5A5A5A5, + 0x5A5A5A5AA5A5A5A5, + 0xAAAA55555555AAAA, + 0x0FF00FF00FF00FF0, + 0x0F0FF0F00F0FF0F0, + }, +} diff --git a/pqhs/mceliece6960119/math/gf2e12/gf4096.go b/pqhs/mceliece6960119/math/gf2e12/gf4096.go new file mode 100644 index 0000000..e0f84fa --- /dev/null +++ b/pqhs/mceliece6960119/math/gf2e12/gf4096.go @@ -0,0 +1,83 @@ +// Package gf2e12 provides finite field arithmetic over GF(2^12). +package gf2e12 + +// Elt is a field element of characteristic 2 modulo z^12 + z^3 + 1 +type Elt = uint16 + +const ( + Bits = 12 + Mask = (1 << Bits) - 1 +) + +// Add two Elt elements together. Since an addition in Elt(2) is the same as XOR, +// this implementation uses a simple XOR for addition. +func Add(a, b Elt) Elt { + return a ^ b +} + +// Mul calculate the product of two Elt elements. +func Mul(a, b Elt) Elt { + a64 := uint64(a) + b64 := uint64(b) + + // if the LSB of b is 1, set tmp to a64, and 0 otherwise + tmp := a64 & -(b64 & 1) + + // check if i-th bit of b64 is set, add a64 shifted by i bits if so + for i := 1; i < Bits; i++ { + tmp ^= a64 * (b64 & (1 << i)) + } + + // polynomial reduction + t := tmp & 0x7FC000 + tmp ^= t >> 9 + tmp ^= t >> 12 + + t = tmp & 0x3000 + tmp ^= t >> 9 + tmp ^= t >> 12 + + return Elt(tmp & Mask) +} + +// sqr calculates the square of Elt element a +func sqr(a Elt) Elt { + a32 := uint32(a) + a32 = (a32 | (a32 << 8)) & 0x00FF00FF + a32 = (a32 | (a32 << 4)) & 0x0F0F0F0F + a32 = (a32 | (a32 << 2)) & 0x33333333 + a32 = (a32 | (a32 << 1)) & 0x55555555 + + t := a32 & 0x7FC000 + a32 ^= t >> 9 + a32 ^= t >> 12 + + t = a32 & 0x3000 + a32 ^= t >> 9 + a32 ^= t >> 12 + + return uint16(a32 & Mask) +} + +// Inv calculates the multiplicative inverse of Elt element a +func Inv(a Elt) Elt { + out := sqr(a) + tmp3 := Mul(out, a) // a^3 + + out = sqr(sqr(tmp3)) + tmp15 := Mul(out, tmp3) // a^15 = a^(3*2*2 + 3) + + out = sqr(sqr(sqr(sqr(tmp15)))) + out = Mul(out, tmp15) // a^255 = a^(15*2*2*2*2 + 15) + + out = sqr(sqr(out)) + out = Mul(out, tmp3) // a^1023 = a^(255*2*2 + 3) + + out = Mul(sqr(out), a) // a^2047 = a^(1023*2 + 1) + return sqr(out) // a^4094 = a^(2047 * 2) +} + +// Div calculates a / b +func Div(a, b Elt) Elt { + return Mul(Inv(b), a) +} diff --git a/pqhs/mceliece6960119/math/gf2e13/gf8192.go b/pqhs/mceliece6960119/math/gf2e13/gf8192.go new file mode 100644 index 0000000..c2efcf2 --- /dev/null +++ b/pqhs/mceliece6960119/math/gf2e13/gf8192.go @@ -0,0 +1,130 @@ +// Package gf2e13 provides finite field arithmetic over GF(2^13). +package gf2e13 + +// Elt is a field element of characteristic 2 modulo z^13 + z^4 + z^3 + z + 1 +type Elt = uint16 + +const ( + Bits = 13 + Mask = (1 << Bits) - 1 +) + +// Add two Elt elements together. Since an addition in Elt(2) is the same as XOR, +// this implementation uses a simple XOR for addition. +func Add(a, b Elt) Elt { + return a ^ b +} + +// Mul calculate the product of two Elt elements. +func Mul(a, b Elt) Elt { + a64 := uint64(a) + b64 := uint64(b) + + // if the LSB of b is 1, set tmp to a64, and 0 otherwise + tmp := a64 & -(b64 & 1) + + // check if i-th bit of b64 is set, add a64 shifted by i bits if so + for i := 1; i < Bits; i++ { + tmp ^= a64 * (b64 & (1 << i)) + } + + // polynomial reduction + t := tmp & 0x1FF0000 + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + t = tmp & 0x000E000 + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + return uint16(tmp & Mask) +} + +// sqr2 calculates a^4 +func sqr2(a Elt) Elt { + a64 := uint64(a) + a64 = (a64 | (a64 << 24)) & 0x000000FF000000FF + a64 = (a64 | (a64 << 12)) & 0x000F000F000F000F + a64 = (a64 | (a64 << 6)) & 0x0303030303030303 + a64 = (a64 | (a64 << 3)) & 0x1111111111111111 + + t := a64 & 0x0001FF0000000000 + a64 ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = a64 & 0x000000FF80000000 + a64 ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = a64 & 0x000000007FC00000 + a64 ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = a64 & 0x00000000003FE000 + a64 ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + return uint16(a64 & Mask) +} + +// sqrMul calculates the product of a^2 and b +func sqrMul(a, b Elt) Elt { + a64 := uint64(a) + b64 := uint64(b) + + x := (b64 << 6) * (a64 & (1 << 6)) + a64 ^= a64 << 7 + x ^= b64 * (a64 & (0x04001)) + x ^= (b64 * (a64 & (0x08002))) << 1 + x ^= (b64 * (a64 & (0x10004))) << 2 + x ^= (b64 * (a64 & (0x20008))) << 3 + x ^= (b64 * (a64 & (0x40010))) << 4 + x ^= (b64 * (a64 & (0x80020))) << 5 + + t := x & 0x0000001FF0000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000000000FF80000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000000000007E000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + return uint16(x & Mask) +} + +// sqr2Mul calculates the product of a^4 and b +func sqr2Mul(a, b Elt) Elt { + a64 := uint64(a) + b64 := uint64(b) + + x := (b64 << 18) * (a64 & (1 << 6)) + a64 ^= a64 << 21 + x ^= b64 * (a64 & (0x010000001)) + x ^= (b64 * (a64 & (0x020000002))) << 3 + x ^= (b64 * (a64 & (0x040000004))) << 6 + x ^= (b64 * (a64 & (0x080000008))) << 9 + x ^= (b64 * (a64 & (0x100000010))) << 12 + x ^= (b64 * (a64 & (0x200000020))) << 15 + + t := x & 0x1FF0000000000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000FF80000000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000007FC00000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x00000003FE000000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x0000000001FE0000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + t = x & 0x000000000001E000 + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13) + + return uint16(x & Mask) +} + +// Inv calculates the multiplicative inverse of Elt element a +func Inv(a Elt) Elt { + return Div(1, a) +} + +// Div calculates a / b +func Div(a, b Elt) Elt { + tmp3 := sqrMul(b, b) // b^3 + tmp15 := sqr2Mul(tmp3, tmp3) // b^15 = b^(3*2*2+3) + out := sqr2(tmp15) + out = sqr2Mul(out, tmp15) // b^255 = b^(15*4*4+15) + out = sqr2(out) + out = sqr2Mul(out, tmp15) // b^4095 = b^(255*2*2*2*2+15) + + return sqrMul(out, a) // b^8190 = b^(4095*2) = b^-1 +} diff --git a/pqhs/mceliece6960119/mceliece.go b/pqhs/mceliece6960119/mceliece.go new file mode 100644 index 0000000..eba3b34 --- /dev/null +++ b/pqhs/mceliece6960119/mceliece.go @@ -0,0 +1,733 @@ +// Code generated from mceliece.templ.go. DO NOT EDIT. + +// Package mceliece6960119 implements the IND-CCA2 secure key encapsulation mechanism +// mceliece6960119 as submitted to round 4 of the NIST PQC competition and +// described in +// +// https://classic.mceliece.org/nist/mceliece-20201010.pdf +// +// The following code is translated from the C reference implementation, and +// from a Rust implementation by Bernhard Berg, Lukas Prokop, Daniel Kales +// where direct translation from C is not applicable. +// +// https://github.com/Colfenor/classic-mceliece-rust +package mceliece6960119 + +import ( + cryptoRand "crypto/rand" + "crypto/sha3" + "errors" + "fmt" + "io" + + "go.stargrave.org/vors/v5/pqhs/mceliece6960119/internal" + "go.stargrave.org/vors/v5/pqhs/mceliece6960119/math/gf2e13" +) + +const ( + sysT = 119 // F(y) is 64 degree + gfBits = gf2e13.Bits + gfMask = gf2e13.Mask + unusedBits = 16 - gfBits + sysN = 6960 + condBytes = (1 << (gfBits - 4)) * (2*gfBits - 1) + irrBytes = sysT * 2 + pkNRows = sysT * gfBits + pkNCols = sysN - pkNRows + pkRowBytes = (pkNCols + 7) / 8 + syndBytes = (pkNRows + 7) / 8 + PublicKeySize = 1047319 + PrivateKeySize = 13948 + CiphertextSize = 194 + SharedKeySize = 32 + seedSize = 32 + encapsulationSeedSize = 48 +) + +var ( + ErrCiphertextSize = errors.New("wrong size for ciphertext") + ErrPubKeySize = errors.New("wrong size for public key") + ErrPrivKeySize = errors.New("wrong size for private key") +) + +type PublicKey struct { + pk [PublicKeySize]byte +} + +type PrivateKey struct { + sk [PrivateKeySize]byte +} + +type ( + gf = gf2e13.Elt + randFunc = func(pool []byte) error +) + +// KEM Keypair generation. +// +// The structure of the secret key is given by the following segments: +// (32 bytes seed, 8 bytes pivots, IRR_BYTES bytes, COND_BYTES bytes, SYS_N/8 bytes). +// The structure of the public key is simple: a matrix of PK_NROWS times PK_ROW_BYTES bytes. +// +// `entropy` corresponds to the l-bit input seed in SeededKeyGen from the specification. +// The keypair is deterministically generated from `entropy`. +// If the generated keypair is invalid, a new seed will be generated by hashing `entropy` to try again. +func deriveKeyPair(entropy []byte) (*PublicKey, *PrivateKey) { + const ( + irrPolys = sysN/8 + (1<>= 8 + + preimage[0] = byte(m & 1) + for i := 0; i < sysN/8; i++ { + preimage[1+i] = (byte(^m) & s[i]) | (byte(m) & e[i]) + } + + copy(preimage[1+sysN/8:][:syndBytes], c[0:syndBytes]) + err := shake256(key[0:32], preimage[:]) + if err != nil { + return err + } + + // clear outputs (set to all 1's) if padding bits are not all zero + mask := paddingOk + for i := 0; i < 32; i++ { + key[i] |= mask + } + + if paddingOk == 0 { + return nil + } + return fmt.Errorf("public key padding error %d", paddingOk) +} + +// Generates `e`, a random error vector of weight `t`. +// If generation of pseudo-random numbers fails, an error is returned +func genE(e *[sysN / 8]byte, rand randFunc) error { + ind := [sysT]uint16{} + val := [sysT]byte{} + for { + buf := make([]byte, sysT*4) + err := rand(buf) + if err != nil { + return err + } + + nums := [sysT * 2]uint16{} + for i := 0; i < sysT*2; i++ { + nums[i] = loadGf(buf[:]) + buf = buf[2:] + } + + count := 0 + for i := 0; i < sysT*2 && count < sysT; i++ { + if nums[i] < sysN { + ind[count] = nums[i] + count++ + } + } + if count < sysT { + continue + } + + eq := false + for i := 1; i < sysT; i++ { + for j := 0; j < i; j++ { + if ind[i] == ind[j] { + eq = true + } + } + } + + if !eq { + break + } + } + + for j := 0; j < sysT; j++ { + val[j] = 1 << (ind[j] & 7) + } + + for i := uint16(0); i < sysN/8; i++ { + e[i] = 0 + + for j := 0; j < sysT; j++ { + mask := sameMask(i, ind[j]>>3) + e[i] |= val[j] & mask + } + } + return nil +} + +// Takes two 16-bit integers and determines whether they are equal +// Return byte with all bit set if equal, 0 otherwise +func sameMask(x uint16, y uint16) byte { + mask := uint32(x ^ y) + mask -= 1 + mask >>= 31 + mask = -mask + + return byte(mask & 0xFF) +} + +// Given condition bits `c`, returns the support `s`. +func supportGen(s *[sysN]gf, c *[condBytes]byte) { + L := [gfBits][(1 << gfBits) / 8]byte{} + for i := 0; i < (1 << gfBits); i++ { + a := bitRev(gf(i)) + for j := 0; j < gfBits; j++ { + L[j][i/8] |= byte(((a >> j) & 1) << (i % 8)) + } + } + for j := 0; j < gfBits; j++ { + applyBenes(&L[j], c) + } + for i := 0; i < sysN; i++ { + s[i] = 0 + for j := gfBits - 1; j >= 0; j-- { + s[i] <<= 1 + s[i] |= uint16(L[j][i/8]>>(i%8)) & 1 + } + } +} + +// Given Goppa polynomial `f`, support `l`, and received word `r` +// compute `out`, the syndrome of length 2t +func synd(out *[sysT * 2]gf, f *[sysT + 1]gf, L *[sysN]gf, r *[sysN / 8]byte) { + for j := 0; j < 2*sysT; j++ { + out[j] = 0 + } + + for i := 0; i < sysN; i++ { + c := uint16(r[i/8]>>(i%8)) & 1 + e := eval(f, L[i]) + eInv := gf2e13.Inv(gf2e13.Mul(e, e)) + for j := 0; j < 2*sysT; j++ { + out[j] = gf2e13.Add(out[j], gf2e13.Mul(eInv, c)) + eInv = gf2e13.Mul(eInv, L[i]) + } + } +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} + +// The Berlekamp-Massey algorithm. +// Uses `s` as input (sequence of field elements) +// and `out` as output (minimal polynomial of `s`) +func bm(out *[sysT + 1]gf, s *[2 * sysT]gf) { + var L, mle, mne uint16 + T := [sysT + 1]gf{} + C := [sysT + 1]gf{} + B := [sysT + 1]gf{} + var b, d, f gf + b = 1 + B[1] = 1 + C[0] = 1 + for N := 0; N < 2*sysT; N++ { + d = 0 + for i := 0; i <= min(N, sysT); i++ { + d ^= gf2e13.Mul(C[i], s[N-i]) + } + mne = d + mne -= 1 + mne >>= 15 + mne -= 1 + mle = uint16(N) + mle -= 2 * L + mle >>= 15 + mle -= 1 + mle &= mne + for i := 0; i <= sysT; i++ { + T[i] = C[i] + } + f = gf2e13.Div(d, b) + for i := 0; i <= sysT; i++ { + C[i] ^= gf2e13.Mul(f, B[i]) & mne + } + L = (L & ^mle) | ((uint16(N) + 1 - L) & mle) + + for i := 0; i <= sysT; i++ { + B[i] = (B[i] & ^mle) | (T[i] & mle) + } + + b = (b & ^mle) | (d & mle) + + for i := sysT; i >= 1; i-- { + B[i] = B[i-1] + } + B[0] = 0 + } + + for i := 0; i <= sysT; i++ { + out[i] = C[sysT-i] + } +} + +// Niederreiter decryption with the Berlekamp decoder. +// +// It takes as input the secret key `sk` and a ciphertext `c`. +// It returns an error vector in `e` and the return value indicates success (0) or failure (1) +func decrypt(e *[sysN / 8]byte, sk []byte, c *[syndBytes]byte) uint16 { + var check uint16 + w := 0 + r := [sysN / 8]byte{} + + g := [sysT + 1]gf{} + L := [sysN]gf{} + + s := [sysT * 2]gf{} + sCmp := [sysT * 2]gf{} + locator := [sysT + 1]gf{} + images := [sysN]gf{} + + copy(r[:syndBytes], c[:syndBytes]) + for i := 0; i < sysT; i++ { + g[i] = loadGf(sk) + sk = sk[2:] + } + g[sysT] = 1 + + supportGen(&L, (*[condBytes]byte)(sk[:condBytes])) + + synd(&s, &g, &L, &r) + bm(&locator, &s) + root(&images, &locator, &L) + + for i := 0; i < sysN/8; i++ { + e[i] = 0 + } + for i := 0; i < sysN; i++ { + t := isZeroMask(images[i]) & 1 + + e[i/8] |= byte(t << (i % 8)) + w += int(t) + } + + synd(&sCmp, &g, &L, e) + check = uint16(w) ^ sysT + for i := 0; i < sysT*2; i++ { + check |= s[i] ^ sCmp[i] + } + + check -= 1 + check >>= 15 + + return check ^ 1 +} + +// check if element is 0, returns a mask with all bits set if so, and 0 otherwise +func isZeroMask(element gf) uint16 { + t := uint32(element) - 1 + t >>= 19 + return uint16(t) +} + +// calculate the minimal polynomial of f and store it in out +func minimalPolynomial(out *[sysT]gf, f *[sysT]gf) bool { + mat := [sysT + 1][sysT]gf{} + mat[0][0] = 1 + for i := 1; i < sysT; i++ { + mat[0][i] = 0 + } + + for i := 0; i < sysT; i++ { + mat[1][i] = f[i] + } + + for i := 2; i <= sysT; i++ { + polyMul(&mat[i], &mat[i-1], f) + } + + for j := 0; j < sysT; j++ { + for k := j + 1; k < sysT; k++ { + mask := isZeroMask(mat[j][j]) + // if mat[j][j] is not zero, add mat[c..sysT+1][k] to mat[c][j] + // do nothing otherwise + for c := j; c <= sysT; c++ { + mat[c][j] ^= mat[c][k] & mask + } + } + + if mat[j][j] == 0 { + return false + } + + inv := gf2e13.Inv(mat[j][j]) + for c := 0; c <= sysT; c++ { + mat[c][j] = gf2e13.Mul(mat[c][j], inv) + } + + for k := 0; k < sysT; k++ { + if k != j { + t := mat[j][k] + for c := 0; c <= sysT; c++ { + mat[c][k] ^= gf2e13.Mul(mat[c][j], t) + } + } + } + } + + for i := 0; i < sysT; i++ { + out[i] = mat[sysT][i] + } + + return true +} + +// calculate the product of a and b in Fq^t +func polyMul(out *[sysT]gf, a *[sysT]gf, b *[sysT]gf) { + product := [sysT*2 - 1]gf{} + for i := 0; i < sysT; i++ { + for j := 0; j < sysT; j++ { + product[i+j] ^= gf2e13.Mul(a[i], b[j]) + } + } + + for i := (sysT - 1) * 2; i >= sysT; i-- { + // polynomial reduction + + product[i-sysT+8] ^= product[i] + product[i-sysT+0] ^= product[i] + + } + + for i := 0; i < sysT; i++ { + out[i] = product[i] + } +} + +// Compute transposition of `in` and store it in `out` +func transpose64x64(out, in *[64]uint64) { + masks := [6][2]uint64{ + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000}, + } + copy(out[:], in[:]) + + for d := 5; d >= 0; d-- { + s := 1 << d + for i := 0; i < 64; i += s * 2 { + for j := i; j < i+s; j++ { + x := (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s) + y := ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]) + + out[j+0] = x + out[j+s] = y + } + } + } +} + +// given polynomial `f`, evaluate `f` at `a` +func eval(f *[sysT + 1]gf, a gf) gf { + r := f[sysT] + for i := sysT - 1; i >= 0; i-- { + r = gf2e13.Mul(r, a) + r = gf2e13.Add(r, f[i]) + } + return r +} + +// Given polynomial `f` and a list of field elements `l`, +// return the roots `out` satisfying `[ f(a) for a in L ]` +func root(out *[sysN]gf, f *[sysT + 1]gf, l *[sysN]gf) { + for i := 0; i < sysN; i++ { + out[i] = eval(f, l[i]) + } +} + +// performs SHAKE-256 on `input` and store the hash in `output` +func shake256(output []byte, input []byte) error { + shake := sha3.NewSHAKE256() + _, err := shake.Write(input) + if err != nil { + return err + } + _, err = shake.Read(output) + if err != nil { + return err + } + return nil +} + +// store field element `a` in the first 2 bytes of `dest` +func storeGf(dest []byte, a gf) { + dest[0] = byte(a & 0xFF) + dest[1] = byte(a >> 8) +} + +// load a field element from the first 2 bytes of `src` +func loadGf(src []byte) gf { + a := uint16(src[1]) + a <<= 8 + a |= uint16(src[0]) + return a & gfMask +} + +// load a 32-bit little endian integer from `in` +func load4(in []byte) uint32 { + ret := uint32(in[3]) + for i := 2; i >= 0; i-- { + ret <<= 8 + ret |= uint32(in[i]) + } + return ret +} + +// store a 64-bit integer to `out` in little endian +func store8(out []byte, in uint64) { + out[0] = byte((in >> 0x00) & 0xFF) + out[1] = byte((in >> 0x08) & 0xFF) + out[2] = byte((in >> 0x10) & 0xFF) + out[3] = byte((in >> 0x18) & 0xFF) + out[4] = byte((in >> 0x20) & 0xFF) + out[5] = byte((in >> 0x28) & 0xFF) + out[6] = byte((in >> 0x30) & 0xFF) + out[7] = byte((in >> 0x38) & 0xFF) +} + +// load a 64-bit little endian integer from `in` +func load8(in []byte) uint64 { + ret := uint64(in[7]) + for i := 6; i >= 0; i-- { + ret <<= 8 + ret |= uint64(in[i]) + } + return ret +} + +// reverse the bits in the field element `a` +func bitRev(a gf) gf { + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8) + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4) + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2) + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1) + + return a >> unusedBits +} + +func SeedSize() int { return seedSize } +func EncapsulationSeedSize() int { return encapsulationSeedSize } + +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + var ret [PrivateKeySize]byte + copy(ret[:], sk.sk[:]) + return ret[:], nil +} + +// MarshalCompressedBinary returns a 32-byte seed that can be used to regenerate +// the key pair when passed to DeriveKeyPair +func (sk *PrivateKey) MarshalCompressedBinary() []byte { + seed := [32]byte{} + copy(seed[:], sk.sk[:32]) + return seed[:] +} + +func (sk *PrivateKey) Public() *PublicKey { + pk, _ := DeriveKeyPair(sk.MarshalCompressedBinary()) + return pk +} + +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + var ret [PublicKeySize]byte + copy(ret[:], pk.pk[:]) + return ret[:], nil +} + +func GenerateKeyPair() (*PublicKey, *PrivateKey, error) { + seed := [32]byte{} + _, err := io.ReadFull(cryptoRand.Reader, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := deriveKeyPair(seed[:]) + return pk, sk, nil +} + +func DeriveKeyPair(seed []byte) (*PublicKey, *PrivateKey) { + if len(seed) != seedSize { + panic("seed must be of length EncapsulationSeedSize") + } + return deriveKeyPair(seed) +} + +func encapsulate(pk *PublicKey, rand randFunc) (ct, ss []byte, err error) { + ciphertext := [CiphertextSize]byte{} + sharedSecret := [SharedKeySize]byte{} + err = kemEncapsulate(&ciphertext, &sharedSecret, &pk.pk, rand) + if err != nil { + return nil, nil, err + } + return ciphertext[:], sharedSecret[:], nil +} + +func Encapsulate(pk *PublicKey) (ct, ss []byte, err error) { + return encapsulate(pk, func(pool []byte) error { + _, err2 := io.ReadFull(cryptoRand.Reader, pool) + return err2 + }) +} + +func Decapsulate(sk *PrivateKey, ct []byte) ([]byte, error) { + if len(ct) != CiphertextSize { + return nil, ErrCiphertextSize + } + ss := [SharedKeySize]byte{} + err := kemDecapsulate(&ss, (*[CiphertextSize]byte)(ct), &sk.sk) + if err != nil { + return nil, err + } + return ss[:], nil +} + +func UnmarshalBinaryPublicKey(buf []byte) (*PublicKey, error) { + if len(buf) != PublicKeySize { + return nil, ErrPubKeySize + } + pk := [PublicKeySize]byte{} + copy(pk[:], buf) + return &PublicKey{pk: pk}, nil +} + +func UnmarshalBinaryPrivateKey(buf []byte) (*PrivateKey, error) { + if len(buf) != PrivateKeySize { + return nil, ErrPrivKeySize + } + sk := [PrivateKeySize]byte{} + copy(sk[:], buf) + return &PrivateKey{sk: sk}, nil +} diff --git a/pqhs/mceliece6960119/operations.go b/pqhs/mceliece6960119/operations.go new file mode 100644 index 0000000..d6a527b --- /dev/null +++ b/pqhs/mceliece6960119/operations.go @@ -0,0 +1,57 @@ +// Code generated from operations_6960119.templ.go. DO NOT EDIT. + +package mceliece6960119 + +// This function determines (in a constant-time manner) whether the padding bits of `pk` are all zero. +func checkPkPadding(pk *[PublicKeySize]byte) byte { + b := byte(0) + for i := 0; i < pkNRows; i++ { + b |= pk[i*pkRowBytes+pkRowBytes-1] + } + b >>= pkNCols % 8 + b -= 1 + b >>= 7 + return b - 1 +} + +// This function determines (in a constant-time manner) whether the padding bits of `c` are all zero. +func checkCPadding(c *[CiphertextSize]byte) byte { + b := c[syndBytes-1] >> (pkNRows % 8) + b -= 1 + b >>= 7 + return b - 1 +} + +// input: public key pk, error vector e +// output: syndrome s +func syndrome(s *[CiphertextSize]byte, pk *[PublicKeySize]byte, e *[sysN / 8]byte) { + row := [sysN / 8]byte{} + tail := pkNRows % 8 + for i := 0; i < syndBytes; i++ { + s[i] = 0 + } + for i := 0; i < pkNRows; i++ { + for j := 0; j < sysN/8; j++ { + row[j] = 0 + } + for j := 0; j < pkRowBytes; j++ { + row[sysN/8-pkRowBytes+j] = pk[i*pkRowBytes+j] + } + for j := sysN/8 - 1; j >= sysN/8-pkRowBytes; j-- { + row[j] = (row[j] << tail) | (row[j-1] >> (8 - tail)) + } + row[i/8] |= 1 << (i % 8) + + b := byte(0) + for j := 0; j < sysN/8; j++ { + b ^= row[j] & e[j] + } + + b ^= b >> 4 + b ^= b >> 2 + b ^= b >> 1 + b &= 1 + + s[i/8] |= b << (i % 8) + } +} diff --git a/pqhs/mceliece6960119/pk_gen.go b/pqhs/mceliece6960119/pk_gen.go new file mode 100644 index 0000000..a505a8a --- /dev/null +++ b/pqhs/mceliece6960119/pk_gen.go @@ -0,0 +1,280 @@ +// Code generated from pk_gen_vec.templ.go. DO NOT EDIT. + +// The following code is translated from the C `vec` Additional Implementation +// from the NIST round 4 submission package. + +package mceliece6960119 + +import "go.stargrave.org/vors/v5/pqhs/mceliece6960119/internal" + +const exponent = 128 + +func storeI(out []byte, in uint64, i int) { + for j := 0; j < i; j++ { + out[j] = byte((in >> (j * 8)) & 0xFF) + } +} + +func deBitSlicing(out *[1 << gfBits]uint64, in *[exponent][gfBits]uint64) { + for i := 0; i < (1 << gfBits); i++ { + out[i] = 0 + } + + for i := 0; i < exponent; i++ { + for j := gfBits - 1; j >= 0; j-- { + for r := 0; r < 64; r++ { + out[i*64+r] <<= 1 + out[i*64+r] |= (in[i][j] >> r) & 1 + } + } + } +} + +func toBitslicing2x(out0 *[exponent][gfBits]uint64, out1 *[exponent][gfBits]uint64, in *[1 << gfBits]uint64) { + for i := 0; i < exponent; i++ { + for j := gfBits - 1; j >= 0; j-- { + for r := 63; r >= 0; r-- { + out1[i][j] <<= 1 + out1[i][j] |= (in[i*64+r] >> (j + gfBits)) & 1 + } + } + + for j := gfBits - 1; j >= 0; j-- { + for r := 63; r >= 0; r-- { + out0[i][gfBits-1-j] <<= 1 + out0[i][gfBits-1-j] |= (in[i*64+r] >> j) & 1 + } + } + } +} + +func irrLoad(out *[2][gfBits]uint64, in []byte) { + irr := [sysT + 1]uint16{} + + for i := 0; i < sysT; i++ { + irr[i] = loadGf(in[i*2:]) + } + + irr[sysT] = 1 + + v := [2]uint64{} + for i := 0; i < gfBits; i++ { + v[0] = 0 + v[1] = 0 + + for j := 63; j >= 0; j-- { + v[0] <<= 1 + v[0] |= uint64(irr[j]>>i) & 1 + } + for j := sysT; j >= 64; j-- { + v[1] <<= 1 + v[1] |= uint64(irr[j]>>i) & 1 + } + + out[0][i] = v[0] + out[1][i] = v[1] + } +} + +// nolint:unparam +// Public key generation. Generate the public key `pk`, +// permutation `pi` and pivot element `pivots` based on the +// secret key `sk` and permutation `perm` provided. +// `pk` has `max(1 << GFBITS, SYS_N)` elements which is +// 4096 for mceliece348864 and 8192 for mceliece8192128. +// `sk` has `2 * SYS_T` elements and perm `1 << GFBITS`. +func pkGen(pk *[pkNRows * pkRowBytes]byte, irr []byte, perm *[1 << gfBits]uint32, pi *[1 << gfBits]int16, pivots *uint64) bool { + const ( + nblocksH = (sysN + 63) / 64 + nblocksI = (pkNRows + 63) / 64 + + blockIdx = nblocksI - 1 + tail = pkNRows % 64 + ) + mat := [pkNRows][nblocksH]uint64{} + var mask uint64 + + irrInt := [2][gfBits]uint64{} + + consts := [exponent][gfBits]uint64{} + eval := [exponent][gfBits]uint64{} + prod := [exponent][gfBits]uint64{} + tmp := [gfBits]uint64{} + list := [1 << gfBits]uint64{} + + ops := [pkNRows][nblocksI]uint64{} + + oneRow := [exponent]uint64{} + + // compute the inverses + irrLoad(&irrInt, irr) + fft(&eval, &irrInt) + vecCopy(&prod[0], &eval[0]) + for i := 1; i < exponent; i++ { + vecMul(&prod[i], &prod[i-1], &eval[i]) + } + vecInv(&tmp, &prod[exponent-1]) + for i := exponent - 2; i >= 0; i-- { + vecMul(&prod[i+1], &prod[i], &tmp) + vecMul(&tmp, &tmp, &eval[i+1]) + } + vecCopy(&prod[0], &tmp) + + // fill matrix + deBitSlicing(&list, &prod) + for i := uint64(0); i < (1 << gfBits); i++ { + list[i] <<= gfBits + list[i] |= i + list[i] |= (uint64(perm[i])) << 31 + } + internal.UInt64Sort(list[:], 1<> 31) == (list[i] >> 31) { + return false + } + } + toBitslicing2x(&consts, &prod, &list) + + for i := 0; i < (1 << gfBits); i++ { + pi[i] = int16(list[i] & gfMask) + } + + for j := 0; j < nblocksI; j++ { + for k := 0; k < gfBits; k++ { + mat[k][j] = prod[j][k] + } + } + + for i := 1; i < sysT; i++ { + for j := 0; j < nblocksI; j++ { + vecMul(&prod[j], &prod[j], &consts[j]) + for k := 0; k < gfBits; k++ { + mat[i*gfBits+k][j] = prod[j][k] + } + } + } + + // gaussian elimination to obtain an upper triangular matrix + // and keep track of the operations in ops + + for i := 0; i < pkNRows; i++ { + for j := 0; j < nblocksI; j++ { + ops[i][j] = 0 + } + } + for i := 0; i < pkNRows; i++ { + ops[i][i/64] = 1 + ops[i][i/64] <<= (i % 64) + } + + column := [pkNRows]uint64{} + for i := 0; i < pkNRows; i++ { + column[i] = mat[i][blockIdx] + } + + for row := 0; row < pkNRows; row++ { + i := row >> 6 + j := row & 63 + + for k := row + 1; k < pkNRows; k++ { + mask = mat[row][i] >> j + mask &= 1 + mask -= 1 + + for c := 0; c < nblocksI; c++ { + mat[row][c] ^= mat[k][c] & mask + ops[row][c] ^= ops[k][c] & mask + } + + } + // return if not systematic + if ((mat[row][i] >> j) & 1) == 0 { + return false + } + + for k := row + 1; k < pkNRows; k++ { + mask = mat[k][i] >> j + mask &= 1 + mask = -mask + + for c := 0; c < nblocksI; c++ { + mat[k][c] ^= mat[row][c] & mask + + ops[k][c] ^= ops[row][c] & mask + + } + } + } + + pkp := pk[:] + + // computing the lineaer map required to obatin the systematic form + + for row := pkNRows - 1; row >= 0; row-- { + for k := 0; k < row; k++ { + mask = mat[k][row/64] >> (row & 63) + mask &= 1 + mask = -mask + + for c := 0; c < nblocksI; c++ { + ops[k][c] ^= ops[row][c] & mask + } + } + } + + // apply the linear map to the non-systematic part + for j := nblocksI; j < nblocksH; j++ { + for k := 0; k < gfBits; k++ { + mat[k][j] = prod[j][k] + } + } + + for i := 1; i < sysT; i++ { + for j := nblocksI; j < nblocksH; j++ { + vecMul(&prod[j], &prod[j], &consts[j]) + for k := 0; k < gfBits; k++ { + mat[i*gfBits+k][j] = prod[j][k] + } + } + } + + for i := 0; i < pkNRows; i++ { + mat[i][blockIdx] = column[i] + } + + for row := 0; row < pkNRows; row++ { + for k := 0; k < nblocksH; k++ { + oneRow[k] = 0 + } + + for c := 0; c < pkNRows; c++ { + mask = ops[row][c>>6] >> (c & 63) + mask &= 1 + mask = -mask + + for k := blockIdx; k < nblocksH; k++ { + oneRow[k] ^= mat[c][k] & mask + } + } + + var k int + for k = blockIdx; k < nblocksH-1; k++ { + + oneRow[k] = (oneRow[k] >> tail) | (oneRow[k+1] << (64 - tail)) + + store8(pkp, oneRow[k]) + pkp = pkp[8:] + } + + oneRow[k] >>= tail + + storeI(pkp, oneRow[k], pkRowBytes%8) + + pkp[(pkRowBytes%8)-1] &= (1 << (pkNCols % 8)) - 1 // removing redundant bits + + pkp = pkp[pkRowBytes%8:] + } + + return true +} diff --git a/pqhs/mceliece6960119/vec.go b/pqhs/mceliece6960119/vec.go new file mode 100644 index 0000000..74a7469 --- /dev/null +++ b/pqhs/mceliece6960119/vec.go @@ -0,0 +1,132 @@ +// Code generated from vec.templ.go. DO NOT EDIT. + +// The following code is translated from the C `vec` Additional Implementation +// from the NIST round 4 submission package. + +package mceliece6960119 + +func vecMul(h, f, g *[gfBits]uint64) { + buf := [2*gfBits - 1]uint64{} + + for i := 0; i < 2*gfBits-1; i++ { + buf[i] = 0 + } + + for i := 0; i < gfBits; i++ { + for j := 0; j < gfBits; j++ { + buf[i+j] ^= f[i] & g[j] + } + } + + for i := 2*gfBits - 2; i >= gfBits; i-- { + + buf[i-gfBits+4] ^= buf[i] + buf[i-gfBits+3] ^= buf[i] + buf[i-gfBits+1] ^= buf[i] + buf[i-gfBits+0] ^= buf[i] + + } + + for i := 0; i < gfBits; i++ { + h[i] = buf[i] + } +} + +// bitsliced field squarings +func vecSq(out, in *[gfBits]uint64) { + result := [gfBits]uint64{} + + t := in[11] ^ in[12] + + result[0] = in[0] ^ in[11] + result[1] = in[7] ^ t + result[2] = in[1] ^ in[7] + result[3] = in[8] ^ t + result[4] = in[2] ^ in[7] + result[4] = result[4] ^ in[8] + result[4] = result[4] ^ t + result[5] = in[7] ^ in[9] + result[6] = in[3] ^ in[8] + result[6] = result[6] ^ in[9] + result[6] = result[6] ^ in[12] + result[7] = in[8] ^ in[10] + result[8] = in[4] ^ in[9] + result[8] = result[8] ^ in[10] + result[9] = in[9] ^ in[11] + result[10] = in[5] ^ in[10] + result[10] = result[10] ^ in[11] + result[11] = in[10] ^ in[12] + result[12] = in[6] ^ t + + for i := 0; i < gfBits; i++ { + out[i] = result[i] + } +} + +// bitsliced field inverses +func vecInv(out, in *[gfBits]uint64) { + tmp11 := [gfBits]uint64{} + tmp1111 := [gfBits]uint64{} + + vecCopy(out, in) + + vecSq(out, out) + vecMul(&tmp11, out, in) // ^11 + + vecSq(out, &tmp11) + vecSq(out, out) + vecMul(&tmp1111, out, &tmp11) // ^1111 + + vecSq(out, &tmp1111) + vecSq(out, out) + vecSq(out, out) + vecSq(out, out) + vecMul(out, out, &tmp1111) // ^11111111 + + vecSq(out, out) + vecSq(out, out) + vecSq(out, out) + vecSq(out, out) + vecMul(out, out, &tmp1111) // ^111111111111 + + vecSq(out, out) // ^1111111111110 +} + +func vecSetBits(b uint64) uint64 { + ret := -b + return ret +} + +func vecSet116b(v uint16) uint64 { + ret := uint64(v) + ret |= ret << 16 + ret |= ret << 32 + + return ret +} + +func vecCopy(out, in *[gfBits]uint64) { + for i := 0; i < gfBits; i++ { + out[i] = in[i] + } +} + +func vecOrReduce(a *[gfBits]uint64) uint64 { + ret := a[0] + for i := 1; i < gfBits; i++ { + ret |= a[i] + } + + return ret +} + +func vecTestZ(a uint64) int { + a |= a >> 32 + a |= a >> 16 + a |= a >> 8 + a |= a >> 4 + a |= a >> 2 + a |= a >> 1 + + return int((a & 1) ^ 1) +} diff --git a/pqhs/server.go b/pqhs/server.go new file mode 100644 index 0000000..2c16506 --- /dev/null +++ b/pqhs/server.go @@ -0,0 +1,101 @@ +package pqhs + +import ( + "crypto/ecdh" + "crypto/rand" + + vors "go.stargrave.org/vors/v5/internal" + "go.stargrave.org/vors/v5/pqhs/mceliece6960119" + sntrup761kem "go.stargrave.org/vors/v5/pqhs/sntrup761/kem" + sntrup761 "go.stargrave.org/vors/v5/pqhs/sntrup761/kem/ntruprime/sntrup761" + "golang.org/x/crypto/chacha20poly1305" +) + +type Server struct { + ephPrvSNTRUP sntrup761kem.PrivateKey + SymmetricState +} + +func NewServer( + serverStaticPrvMcElieceRaw, serverStaticPrvX25519Raw, + serverStaticPubHash, clientPayload []byte, +) (s *Server, payload []byte, err error) { + var serverStaticPrvMcEliece *mceliece6960119.PrivateKey + serverStaticPrvMcEliece, err = mceliece6960119.UnmarshalBinaryPrivateKey( + serverStaticPrvMcElieceRaw) + if err != nil { + return + } + x25519 := ecdh.X25519() + var serverStaticPrvX25519 *ecdh.PrivateKey + serverStaticPrvX25519, err = x25519.NewPrivateKey(serverStaticPrvX25519Raw) + if err != nil { + return + } + ctMcEliece := clientPayload[:mceliece6960119.CiphertextSize] + ctX25519 := clientPayload[mceliece6960119.CiphertextSize:] + var k []byte + k, err = mceliece6960119.Decapsulate(serverStaticPrvMcEliece, ctMcEliece) + if err != nil { + return + } + s = &Server{} + s.CK(k) + s.H([]byte(vors.Magic)) + s.H(serverStaticPubHash) + s.H(ctMcEliece) + var clientEphPubX25519Raw []byte + clientEphPubX25519Raw, err = s.Open(CtxClientX25519, ctX25519) + if err != nil { + return + } + var clientEphPubX25519 *ecdh.PublicKey + clientEphPubX25519, k, err = DH(serverStaticPrvX25519, clientEphPubX25519Raw) + if err != nil { + return + } + s.CK(k) + var serverEphPrvX25519 *ecdh.PrivateKey + serverEphPrvX25519, err = x25519.GenerateKey(rand.Reader) + if err != nil { + return + } + ctX25519 = s.Seal(CtxServerX25519, serverEphPrvX25519.PublicKey().Bytes()) + k, err = serverEphPrvX25519.ECDH(clientEphPubX25519) + if err != nil { + return + } + s.CK(k) + var serverEphPubSNTRUP sntrup761kem.PublicKey + serverEphPubSNTRUP, s.ephPrvSNTRUP, err = sntrup761.Scheme().GenerateKeyPair() + if err != nil { + return + } + var serverEphPubSNTRUPRaw []byte + serverEphPubSNTRUPRaw, err = serverEphPubSNTRUP.MarshalBinary() + if err != nil { + return + } + payload = append(ctX25519, s.Seal(CtxServerSNTRUP761, serverEphPubSNTRUPRaw)...) + return +} + +func (s *Server) Read(reply []byte) (prefinish []byte, err error) { + sntrup761s := sntrup761.Scheme() + clientEphCTSNTRUPRaw := reply[:sntrup761s.CiphertextSize()+chacha20poly1305.Overhead] + prefinish = reply[len(clientEphCTSNTRUPRaw):] + { + clientEphCTSNTRUPRaw, err = s.Open(CtxClientSNTRUP761, clientEphCTSNTRUPRaw) + if err != nil { + return + } + var k []byte + k, err = sntrup761s.Decapsulate(s.ephPrvSNTRUP, clientEphCTSNTRUPRaw) + if err != nil { + return + } + s.CK(k) + } + prefinish, err = s.Open(CtxClientPrefinish, prefinish) + return +} diff --git a/pqhs/shake.go b/pqhs/shake.go new file mode 100644 index 0000000..f0560fd --- /dev/null +++ b/pqhs/shake.go @@ -0,0 +1,39 @@ +package pqhs + +import ( + "crypto/sha3" + "hash" + "io" +) + +type SHAKE struct { + xof *sha3.SHAKE +} + +func (h SHAKE) Size() int { + return 64 +} + +func (h SHAKE) BlockSize() int { + return h.xof.BlockSize() +} + +func (h SHAKE) Reset() { + h.xof.Reset() +} + +func (h SHAKE) Write(p []byte) (int, error) { + return h.xof.Write(p) +} + +func (h SHAKE) Sum(b []byte) []byte { + buf := make([]byte, 64) + if _, err := io.ReadFull(h.xof, buf); err != nil { + panic(err) + } + return append(b, buf...) +} + +func NewSHAKE256() hash.Hash { + return SHAKE{xof: sha3.NewSHAKE256()} +} diff --git a/pqhs/sntrup761/README b/pqhs/sntrup761/README new file mode 100644 index 0000000..e7b08a2 --- /dev/null +++ b/pqhs/sntrup761/README @@ -0,0 +1,4 @@ +Go/Git is unable to fetch (https://github.com/cloudflare/circl) +pull-request's commit (e8d7edb133624b7fa80e66fd9f6eb97f3f1cd361) to +github.com/cloudflare/circl containing NTRU prime implementation +(https://github.com/cloudflare/circl/pull/384). So copy it here. diff --git a/pqhs/sntrup761/kem/kem.go b/pqhs/sntrup761/kem/kem.go new file mode 100644 index 0000000..ede6fee --- /dev/null +++ b/pqhs/sntrup761/kem/kem.go @@ -0,0 +1,118 @@ +// Package kem provides a unified interface for KEM schemes. +// +// A register of schemes is available in the package +// +// github.com/cloudflare/circl/kem/schemes +package kem + +import ( + "encoding" + "errors" +) + +// A KEM public key +type PublicKey interface { + // Returns the scheme for this public key + Scheme() Scheme + + encoding.BinaryMarshaler + Equal(PublicKey) bool +} + +// A KEM private key +type PrivateKey interface { + // Returns the scheme for this private key + Scheme() Scheme + + encoding.BinaryMarshaler + Equal(PrivateKey) bool + Public() PublicKey +} + +// A Scheme represents a specific instance of a KEM. +type Scheme interface { + // Name of the scheme + Name() string + + // GenerateKeyPair creates a new key pair. + GenerateKeyPair() (PublicKey, PrivateKey, error) + + // Encapsulate generates a shared key ss for the public key and + // encapsulates it into a ciphertext ct. + Encapsulate(pk PublicKey) (ct, ss []byte, err error) + + // Returns the shared key encapsulated in ciphertext ct for the + // private key sk. + Decapsulate(sk PrivateKey, ct []byte) ([]byte, error) + + // Unmarshals a PublicKey from the provided buffer. + UnmarshalBinaryPublicKey([]byte) (PublicKey, error) + + // Unmarshals a PrivateKey from the provided buffer. + UnmarshalBinaryPrivateKey([]byte) (PrivateKey, error) + + // Size of encapsulated keys. + CiphertextSize() int + + // Size of established shared keys. + SharedKeySize() int + + // Size of packed private keys. + PrivateKeySize() int + + // Size of packed public keys. + PublicKeySize() int + + // DeriveKeyPair deterministicallly derives a pair of keys from a seed. + // Panics if the length of seed is not equal to the value returned by + // SeedSize. + DeriveKeyPair(seed []byte) (PublicKey, PrivateKey) + + // Size of seed used in DeriveKey + SeedSize() int + + // EncapsulateDeterministically generates a shared key ss for the public + // key deterministically from the given seed and encapsulates it into + // a ciphertext ct. If unsure, you're better off using Encapsulate(). + EncapsulateDeterministically(pk PublicKey, seed []byte) ( + ct, ss []byte, err error) + + // Size of seed used in EncapsulateDeterministically(). + EncapsulationSeedSize() int +} + +// AuthScheme represents a KEM that supports authenticated key encapsulation. +type AuthScheme interface { + Scheme + AuthEncapsulate(pkr PublicKey, sks PrivateKey) (ct, ss []byte, err error) + AuthEncapsulateDeterministically(pkr PublicKey, sks PrivateKey, seed []byte) (ct, ss []byte, err error) + AuthDecapsulate(skr PrivateKey, ct []byte, pks PublicKey) ([]byte, error) +} + +var ( + // ErrTypeMismatch is the error used if types of, for instance, private + // and public keys don't match + ErrTypeMismatch = errors.New("types mismatch") + + // ErrSeedSize is the error used if the provided seed is of the wrong + // size. + ErrSeedSize = errors.New("wrong seed size") + + // ErrPubKeySize is the error used if the provided public key is of + // the wrong size. + ErrPubKeySize = errors.New("wrong size for public key") + + // ErrCiphertextSize is the error used if the provided ciphertext + // is of the wrong size. + ErrCiphertextSize = errors.New("wrong size for ciphertext") + + // ErrPrivKeySize is the error used if the provided private key is of + // the wrong size. + ErrPrivKeySize = errors.New("wrong size for private key") + + // ErrPubKey is the error used if the provided public key is invalid. + ErrPubKey = errors.New("invalid public key") + + // ErrCipherText is the error used if the provided ciphertext is invalid. + ErrCipherText = errors.New("invalid ciphertext") +) diff --git a/pqhs/sntrup761/kem/ntruprime/doc.go b/pqhs/sntrup761/kem/ntruprime/doc.go new file mode 100644 index 0000000..b55c96f --- /dev/null +++ b/pqhs/sntrup761/kem/ntruprime/doc.go @@ -0,0 +1,10 @@ +//go:generate go run gen.go + +// Package ntruprime implements the NTRU Prime IND-CCA2 secure +// key encapsulation mechanism (KEM) as submitted to round 3 of the NIST PQC +// competition and described in +// +// https://ntruprime.cr.yp.to/nist/ntruprime-20201007.pdf +// +// The code is translated from the C reference implementation. +package ntruprime diff --git a/pqhs/sntrup761/kem/ntruprime/internal/Decode.go b/pqhs/sntrup761/kem/ntruprime/internal/Decode.go new file mode 100644 index 0000000..7d15e1b --- /dev/null +++ b/pqhs/sntrup761/kem/ntruprime/internal/Decode.go @@ -0,0 +1,67 @@ +package internal + +// TO DO: Optimize the Decode function +/* Decode(R,s,M,len) */ +/* assumes 0 < M[i] < 16384 */ +/* produces 0 <= R[i] < M[i] */ +func Decode(out []uint16, S []uint8, M []uint16, len int) { + index := 0 + if len == 1 { + if M[0] == 1 { + out[index] = 0 + } else if M[0] <= 256 { + out[index] = Uint32ModUint14(uint32(S[0]), M[0]) + } else { + out[index] = Uint32ModUint14(uint32(uint16(S[0])+((uint16(S[1]))<<8)), M[0]) + } + } + if len > 1 { + R2 := make([]uint16, (len+1)/2) + M2 := make([]uint16, (len+1)/2) + bottomr := make([]uint16, len/2) + bottomt := make([]uint32, len/2) + i := 0 + for i = 0; i < len-1; i += 2 { + m := uint32(M[i]) * uint32(M[i+1]) + + if m > 256*16383 { + bottomt[i/2] = 256 * 256 + bottomr[i/2] = uint16(S[0]) + 256*uint16(S[1]) + S = S[2:] + M2[i/2] = uint16((((m + 255) >> 8) + 255) >> 8) + } else if m >= 16384 { + bottomt[i/2] = 256 + bottomr[i/2] = uint16(S[0]) + S = S[1:] + M2[i/2] = uint16((m + 255) >> 8) + } else { + bottomt[i/2] = 1 + bottomr[i/2] = 0 + M2[i/2] = uint16(m) + } + } + if i < len { + M2[i/2] = M[i] + } + + Decode(R2, S, M2, (len+1)/2) + + for i = 0; i < len-1; i += 2 { + r := uint32(bottomr[i/2]) + var r1 uint32 + var r0 uint16 + + r += bottomt[i/2] * uint32(R2[i/2]) + Uint32DivmodUint14(&r1, &r0, r, M[i]) + r1 = uint32(Uint32ModUint14(r1, M[i+1])) /* only needed for invalid inputs */ + + out[index] = r0 + index++ + out[index] = uint16(r1) + index++ + } + if i < len { + out[index] = R2[i/2] + } + } +} diff --git a/pqhs/sntrup761/kem/ntruprime/internal/Divmod.go b/pqhs/sntrup761/kem/ntruprime/internal/Divmod.go new file mode 100644 index 0000000..f84cc43 --- /dev/null +++ b/pqhs/sntrup761/kem/ntruprime/internal/Divmod.go @@ -0,0 +1,102 @@ +package internal + +/* +CPU division instruction typically takes time depending on x. +This software is designed to take time independent of x. +Time still varies depending on m; user must ensure that m is constant. +Time also varies on CPUs where multiplication is variable-time. +There could be more CPU issues. +There could also be compiler issues. +*/ +// q, r = x/m +// Returns quotient and remainder +func Uint32DivmodUint14(q *uint32, r *uint16, x uint32, m uint16) { + var v uint32 = 0x80000000 + + v /= uint32(m) + + *q = 0 + + qpart := uint32(uint64(x) * uint64(v) >> 31) + + x -= qpart * uint32(m) + *q += qpart + + qpart = uint32(uint64(x) * uint64(v) >> 31) + x -= qpart * uint32(m) + *q += qpart + + x -= uint32(m) + *q += 1 + mask := -(x >> 31) + x += mask & uint32(m) + *q += mask + + *r = uint16(x) +} + +// Returns the quotient of x/m +func Uint32DivUint14(x uint32, m uint16) uint32 { + var q uint32 + var r uint16 + Uint32DivmodUint14(&q, &r, x, m) + return q +} + +// Returns the remainder of x/m +func Uint32ModUint14(x uint32, m uint16) uint16 { + var q uint32 + var r uint16 + Uint32DivmodUint14(&q, &r, x, m) + return r +} + +// Calculates quotient and remainder +func Int32DivmodUint14(q *int32, r *uint16, x int32, m uint16) { + var uq, uq2 uint32 + var ur, ur2 uint16 + var mask uint32 + + Uint32DivmodUint14(&uq, &ur, 0x80000000+uint32(x), m) + Uint32DivmodUint14(&uq2, &ur2, 0x80000000, m) + + ur -= ur2 + uq -= uq2 + mask = -(uint32)(ur >> 15) + ur += uint16(mask & uint32(m)) + uq += mask + *r = ur + *q = int32(uq) +} + +// Returns quotient of x/m +func Int32DivUint14(x int32, m uint16) int32 { + var q int32 + var r uint16 + Int32DivmodUint14(&q, &r, x, m) + return q +} + +// Returns remainder of x/m +func Int32ModUint14(x int32, m uint16) uint16 { + var q int32 + var r uint16 + Int32DivmodUint14(&q, &r, x, m) + return r +} + +// Returns -1 if x!=0; else return 0 +func Int16NonzeroMask(x int16) int { + u := uint16(x) /* 0, else 1...65535 */ + v := uint32(u) /* 0, else 1...65535 */ + v = -v /* 0, else 2^32-65535...2^32-1 */ + v >>= 31 /* 0, else 1 */ + return -int(v) /* 0, else -1 */ +} + +// Returns -1 if x<0; otherwise return 0 +func Int16NegativeMask(x int16) int { + u := uint16(x) + u >>= 15 + return -(int)(u) +} diff --git a/pqhs/sntrup761/kem/ntruprime/internal/Encode.go b/pqhs/sntrup761/kem/ntruprime/internal/Encode.go new file mode 100644 index 0000000..6c11fbd --- /dev/null +++ b/pqhs/sntrup761/kem/ntruprime/internal/Encode.go @@ -0,0 +1,42 @@ +package internal + +/* 0 <= R[i] < M[i] < 16384 */ +func Encode(out []uint8, R, M []uint16, len int) { + if len > 1 { + R2 := make([]uint16, (len+1)/2) + M2 := make([]uint16, (len+1)/2) + var i int + for ; len > 1; len = (len + 1) / 2 { + for i = 0; i < len-1; i += 2 { + m0 := uint32(M[i]) + r := uint32(R[i]) + uint32(R[i+1])*m0 + m := uint32(M[i+1]) * m0 + for m >= 16384 { + out[0] = uint8(r) + out = out[1:] + + r >>= 8 + m = (m + 255) >> 8 + } + R2[i/2] = uint16(r) + M2[i/2] = uint16(m) + } + if i < len { + R2[i/2] = R[i] + M2[i/2] = M[i] + } + copy(R, R2) + copy(M, M2) + } + } + if len == 1 { + r := R[0] + m := M[0] + for m > 1 { + out[0] = uint8(r) + out = out[1:] + r >>= 8 + m = (m + 255) >> 8 + } + } +} diff --git a/pqhs/sntrup761/kem/ntruprime/sntrup761/ntruprime.go b/pqhs/sntrup761/kem/ntruprime/sntrup761/ntruprime.go new file mode 100644 index 0000000..b03c744 --- /dev/null +++ b/pqhs/sntrup761/kem/ntruprime/sntrup761/ntruprime.go @@ -0,0 +1,971 @@ +// Code generated from sntrup.templ.go. DO NOT EDIT. + +// Package sntrup761 implements the IND-CCA2 secure key encapsulation mechanism +// sntrup761 as submitted to round 3 of the NIST PQC competition and +// described in +// +// https://ntruprime.cr.yp.to/nist/ntruprime-20201007.pdf +package sntrup761 + +import ( + "bytes" + cryptoRand "crypto/rand" + "crypto/sha512" + "io" + + "go.stargrave.org/vors/v5/pqhs/sntrup761/kem" + "go.stargrave.org/vors/v5/pqhs/sntrup761/kem/ntruprime/internal" + sntrupKem "go.stargrave.org/vors/v5/pqhs/sntrup761/pke/ntruprime/kem" + ntrup "go.stargrave.org/vors/v5/pqhs/sntrup761/pke/ntruprime/sntrup761" +) + +type ( + small int8 + Fq int16 + Inputs [p]small +) + +const ( + p = ntrup.P + q = ntrup.Q + q12 = ((q - 1) / 2) + roundedBytes = ntrup.RoundedBytes + rqBytes = ntrup.RqBytes + w = ntrup.W + + hashBytes = 32 + + smallBytes = ((p + 3) / 4) + + inputsBytes = smallBytes + ciphertextsBytes = roundedBytes + secretKeysBytes = (2 * smallBytes) + publicKeysBytes = rqBytes + + confirmBytes = 32 +) + +const ( + // Size of seed for NewKeyFromSeed + // Note that during keyGen, a random small is generated until a valid one (whose reciprocal succeeds) is found + // The size of keySeed depends on the number of times the reciprocal fails + // This is why DeriveKeyPairFromGen is used to deterministically derive key pair instead of using seed + KeySeedSize = 4*p + p*4 + inputsBytes + + // Size of seed for EncapsulateTo. + EncapsulationSeedSize = 4 * p + + // Size of the established shared key. + SharedKeySize = ntrup.SharedKeySize + + // Size of the encapsulated shared key. + CiphertextSize = ntrup.CiphertextSize + + // Size of a packed public key. + PublicKeySize = ntrup.PublicKeySize + + // Size of a packed private key. + PrivateKeySize = ntrup.PrivateKeySize +) + +// Arithmetic operations over GF(3) + +// A polynomial of R has all of its coefficients in (-1,0,1) +// F3 is always represented as -1,0,1 +// so ZZ_fromF3 is a no-op + +// x must not be close to top int16 +func f3Freeze(x int16) small { + return small(internal.Int32ModUint14(int32(x)+1, 3)) - 1 +} + +// Arithmetic operations over GF(q) + +/* always represented as -q12...q12 */ +/* so ZZ_fromFq is a no-op */ + +/* x must not be close to top int32 */ +func fqFreeze(x int32) Fq { + return Fq(internal.Int32ModUint14(x+q12, q) - q12) +} + +// Calculates reciprocal of Fq +func fqRecip(a1 Fq) Fq { + var i int = 1 + ai := a1 + + for i < (q - 2) { + ai = fqFreeze(int32(a1) * int32(ai)) + i += 1 + } + return ai +} + +// Returns 0 if the weight w is equal to r +// otherwise returns -1 +func weightwMask(r []small) int { + var weight int = 0 + + for i := 0; i < p; i++ { + weight += int(r[i]) & 1 + } + + // returns -1 if non zero + // otherwise returns 0 if weight==w + return internal.Int16NonzeroMask(int16(weight - w)) + +} + +/* R3_fromR(R_fromRq(r)) */ +func r3FromRq(out []small, r []Fq) { + for i := 0; i < p; i++ { + out[i] = small(f3Freeze(int16(r[i]))) + } +} + +// h = f*g in the ring R3 +func r3Mult(h []small, f []small, g []small) { + fg := make([]small, p+p-1) + var result small + var i, j int + + for i = 0; i < p; i++ { + result = 0 + for j = 0; j <= i; j++ { + result = f3Freeze(int16(result + f[j]*g[i-j])) + } + fg[i] = result + } + + for i = p; i < p+p-1; i++ { + result = 0 + for j = i - p + 1; j < p; j++ { + result = f3Freeze(int16(result + f[j]*g[i-j])) + } + fg[i] = result + } + + for i = p + p - 2; i >= p; i-- { + fg[i-p] = f3Freeze(int16(fg[i-p] + fg[i])) + fg[i-p+1] = f3Freeze(int16(fg[i-p+1] + fg[i])) + } + + for i = 0; i < p; i++ { + h[i] = fg[i] + } +} + +// Calculates the reciprocal of R3 polynomials +// Returns 0 if recip succeeded; else -1 +func r3Recip(out []small, in []small) int { + // out := make([]small, p) + f := make([]small, p+1) + g := make([]small, p+1) + v := make([]small, p+1) + r := make([]small, p+1) + + var sign int + + r[0] = 1 + f[0] = 1 + + f[p-1] = -1 + f[p] = -1 + + for i := 0; i < p; i++ { + g[p-1-i] = in[i] + } + + g[p] = 0 + + delta := 1 + + for loop := 0; loop < 2*p-1; loop++ { + for i := p; i > 0; i-- { + v[i] = v[i-1] + } + v[0] = 0 + + sign = int(-g[0] * f[0]) + var swap int = int(internal.Int16NegativeMask(int16(-delta)) & internal.Int16NonzeroMask(int16(g[0]))) + delta ^= swap & int(delta^-delta) + delta += 1 + + for i := 0; i < p+1; i++ { + t := swap & int(f[i]^g[i]) + f[i] ^= small(t) + g[i] ^= small(t) + t = swap & int(v[i]^r[i]) + v[i] ^= small(t) + r[i] ^= small(t) + } + for i := 0; i < p+1; i++ { + g[i] = f3Freeze(int16(int(g[i]) + sign*int(f[i]))) + } + + for i := 0; i < p+1; i++ { + r[i] = f3Freeze(int16(int(r[i]) + sign*int(v[i]))) + } + + for i := 0; i < p; i++ { + g[i] = g[i+1] + } + + g[p] = 0 + + } + sign = int(f[0]) + + for i := 0; i < p; i++ { + + out[i] = small(sign * int(v[p-1-i])) + } + + return internal.Int16NonzeroMask(int16(delta)) + +} + +// Polynomials mod q + +// h = f*g in the ring Rq */ +func rqMultSmall(h []Fq, f []Fq, g []small) { + fg := make([]Fq, p+p-1) + var result Fq + + for i := 0; i < p; i++ { + result = 0 + for j := 0; j <= i; j++ { + result = fqFreeze(int32(result) + int32(f[j])*(int32)(g[i-j])) + } + fg[i] = result + } + + for i := p; i < p+p-1; i++ { + result = 0 + for j := i - p + 1; j < p; j++ { + result = fqFreeze(int32(result) + int32(f[j])*(int32)(g[i-j])) + } + fg[i] = result + } + + for i := p + p - 2; i >= p; i-- { + fg[i-p] = fqFreeze(int32(fg[i-p] + fg[i])) + fg[i-p+1] = fqFreeze(int32(fg[i-p+1] + fg[i])) + + } + + for i := 0; i < p; i++ { + h[i] = fg[i] + } +} + +// h = 3f in Rq +func rqMult3(h []Fq, f []Fq) { + for i := 0; i < p; i++ { + h[i] = fqFreeze(int32(3 * f[i])) + } +} + +// Returns 0 if recip succeeded; else -1 +// out = 1/(3*in) in Rq +func rqRecip3(out []Fq, in []small) int { + f := make([]Fq, p+1) + g := make([]Fq, p+1) + v := make([]Fq, p+1) + r := make([]Fq, p+1) + + var swap, t int + var f0, g0 int32 + + r[0] = fqRecip(3) + f[0] = 1 + f[p-1] = -1 + f[p] = -1 + + for i := 0; i < p; i++ { + g[p-1-i] = Fq(in[i]) + } + g[p] = 0 + + delta := 1 + + for loop := 0; loop < 2*p-1; loop++ { + for i := p; i > 0; i-- { + v[i] = v[i-1] + } + v[0] = 0 + + swap = internal.Int16NegativeMask(int16(-delta)) & internal.Int16NonzeroMask(int16(g[0])) + delta ^= swap & (delta ^ -delta) + delta += 1 + + for i := 0; i < p+1; i++ { + t = swap & int(f[i]^g[i]) + f[i] ^= Fq(t) + g[i] ^= Fq(t) + t = swap & int(v[i]^r[i]) + v[i] ^= Fq(t) + r[i] ^= Fq(t) + } + + f0 = int32(f[0]) + g0 = int32(g[0]) + + for i := 0; i < p+1; i++ { + g[i] = fqFreeze(f0*int32(g[i]) - g0*int32(f[i])) + } + for i := 0; i < p+1; i++ { + r[i] = fqFreeze(f0*int32(r[i]) - g0*int32(v[i])) + } + + for i := 0; i < p; i++ { + g[i] = g[i+1] + } + g[p] = 0 + } + + scale := Fq(fqRecip(f[0])) + for i := 0; i < p; i++ { + out[i] = fqFreeze(int32(scale) * (int32)(v[p-1-i])) + } + + return internal.Int16NonzeroMask(int16(delta)) + +} + +// Rounding all coefficients of a polynomial to the nearest multiple of 3 +// Rounded polynomials mod q +func round(out []Fq, a []Fq) { + for i := 0; i < p; i++ { + out[i] = a[i] - Fq(f3Freeze(int16(a[i]))) + } +} + +// Returns (min(x, y), max(x, y)), executes in constant time +func minmax(x, y *uint32) { + var xi uint32 = *x + var yi uint32 = *y + var xy uint32 = xi ^ yi + var c uint32 = yi - xi + c ^= xy & (c ^ yi ^ 0x80000000) + c >>= 31 + c = -c + c &= xy + *x = xi ^ c + *y = yi ^ c +} + +// Sorts the array of unsigned integers +func cryptoSortUint32(x []uint32, 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 { + minmax(&x[i], &x[i+p]) + } + } + for q := top; q > p; q >>= 1 { + for i := 0; i < n-q; i++ { + if i&p == 0 { + minmax(&x[i+p], &x[i+q]) + } + } + } + } +} + +// Sorting to generate short polynomial +func shortFromList(out []small, in []int32) { + L := make([]uint32, p) + + var neg2, neg3 int = -2, -3 + + for i := 0; i < w; i++ { + L[i] = uint32(in[i]) & uint32((neg2)) + } + + for i := w; i < p; i++ { + L[i] = (uint32(in[i]) & uint32((neg3))) | 1 + } + + cryptoSortUint32(L, p) + + for i := 0; i < p; i++ { + out[i] = small((L[i] & 3) - 1) + } +} + +// Underlying hash function + +// The input byte array, in, is prepended by the byte b +// and its SHA-512 hash is calculated +// Only the first 32 bytes of the hash are returned +// e.g., b = 0 means out = Hash0(in) +func hashPrefix(out []byte, b int, in []byte, inlen int) { + x := make([]byte, inlen+1) + h := make([]byte, 64) + + x[0] = byte(b) + copy(x[1:], in) + + hash := sha512.New() + hash.Write([]byte(x)) + h = hash.Sum(nil) + + copy(out, h[:32]) + +} + +// Higher level randomness +// Returns a random unsigned integer +func urandom32(seed []byte) uint32 { + var out [4]uint32 + + out[0] = uint32(seed[0]) + out[1] = uint32(seed[1]) << 8 + out[2] = uint32(seed[2]) << 16 + out[3] = uint32(seed[3]) << 24 + return out[0] + out[1] + out[2] + out[3] +} + +// Generates a random short polynomial +func shortRandom(out []small, seed []byte) { + + L := make([]uint32, p) + + for i := 0; i < p; i++ { + L[i] = urandom32(seed[4*i : 4*i+4]) + } + + // Converts uint32 array to int32 array + L_int32 := make([]int32, p) + for i := 0; i < len(L); i++ { + L_int32[i] = int32(L[i]) + } + shortFromList(out, L_int32) +} + +// Generates a random list of small +func smallRandom(out []small, seed []byte) { + for i := 0; i < p; i++ { + out[i] = small(((urandom32(seed[4*i:4*i+4])&0x3fffffff)*3)>>30) - 1 + } +} + +// Streamlined NTRU Prime Core + +// h,(f,ginv) = keyGen() +func keyGen(h []Fq, f []small, ginv []small, gen *io.Reader) { + g := make([]small, p) + seed := make([]byte, 4*p+4*p) + + if gen == nil { + for { + cryptoRand.Read(seed[:4*p]) + smallRandom(g, seed[:4*p]) + if r3Recip(ginv, g) == 0 { + break + } + } + cryptoRand.Read(seed[4*p:]) + } else { + for { + for i := 0; i < p; i++ { + (*gen).Read(seed[4*i : 4*i+4]) + } + smallRandom(g, seed[:4*p]) + if r3Recip(ginv, g) == 0 { + break + } + } + for i := 0; i < p; i++ { + (*gen).Read(seed[4*p+4*i : 4*p+4*i+4]) + } + } + shortRandom(f, seed[4*p:]) + + finv := make([]Fq, p) + + rqRecip3(finv, f) /* always works */ + rqMultSmall(h, finv, g) +} + +// c = encrypt(r,h) +func encrypt(c []Fq, r []small, h []Fq) { + hr := make([]Fq, p) + + rqMultSmall(hr, h, r) + round(c, hr) +} + +// r = decrypt(c,(f,ginv)) +func decrypt(r []small, c []Fq, f []small, ginv []small) { + cf := make([]Fq, p) + cf3 := make([]Fq, p) + e := make([]small, p) + ev := make([]small, p) + + rqMultSmall(cf, c, f) + rqMult3(cf3, cf) + r3FromRq(e, cf3) + r3Mult(ev, e, ginv) + + mask := weightwMask(ev) /* 0 if weight w, else -1 */ + for i := 0; i < w; i++ { + r[i] = ((ev[i] ^ 1) & small(^mask)) ^ 1 + } + + for i := w; i < p; i++ { + r[i] = ev[i] & small(^mask) + } +} + +// Encoding small polynomials (including short polynomials) + +// Transform polynomial in R to bytes +// these are the only functions that rely on p mod 4 = 1 */ +func smallEncode(s []byte, f []small) { + var x small + var index int = 0 + for i := 0; i < p/4; i++ { + x = f[index] + 1 + index++ + + x += (f[index] + 1) << 2 + index++ + x += (f[index] + 1) << 4 + index++ + x += (f[index] + 1) << 6 + index++ + + s[0] = byte(x) + s = s[1:] + } + x = f[index] + 1 + + s[0] = byte(x) +} + +// Transform bytes into polynomial in R +func smallDecode(f []small, s []byte) { + var index int = 0 + var x byte + + for i := 0; i < p/4; i++ { + x = s[0] + s = s[1:] + + f[index] = ((small)(x & 3)) - 1 + x >>= 2 + index++ + f[index] = ((small)(x & 3)) - 1 + x >>= 2 + index++ + f[index] = ((small)(x & 3)) - 1 + x >>= 2 + index++ + f[index] = ((small)(x & 3)) - 1 + index++ + } + x = s[0] + f[index] = ((small)(x & 3)) - 1 +} + +// Encoding general polynomials + +// Transform polynomials in R/q to bytes +func rqEncode(s []byte, r []Fq) { + R := make([]uint16, p) + M := make([]uint16, p) + + for i := 0; i < p; i++ { + R[i] = uint16(r[i] + q12) + M[i] = q + } + internal.Encode(s, R, M, p) +} + +// Transform polynomials in R/q from bytes +func rqDecode(r []Fq, s []byte) { + R := make([]uint16, p) + M := make([]uint16, p) + + for i := 0; i < p; i++ { + M[i] = q + } + internal.Decode(R, s, M, p) + for i := 0; i < p; i++ { + r[i] = ((Fq)(R[i])) - q12 + } + +} + +// Encoding rounded polynomials + +// Transform rounded polynomials to bytes +func roundedEncode(s []byte, r []Fq) { + + R := make([]uint16, p) + M := make([]uint16, p) + + for i := 0; i < p; i++ { + R[i] = uint16((int32((r[i])+q12) * 10923) >> 15) + M[i] = (q + 2) / 3 + } + internal.Encode(s, R, M, p) +} + +// Transform bytes to rounded polynomials +func roundedDecode(r []Fq, s []byte) { + R := make([]uint16, p) + M := make([]uint16, p) + + for i := 0; i < p; i++ { + M[i] = (q + 2) / 3 + } + internal.Decode(R, s, M, p) + for i := 0; i < p; i++ { + r[i] = Fq(R[i]*3 - q12) + } + +} + +// Streamlined NTRU Prime Core plus encoding + +// Generates public key and private key +// pk,sk = zKeyGen() +func zKeyGen(pk []byte, sk []byte, gen *io.Reader) { + + h := make([]Fq, p) + f := make([]small, p) + v := make([]small, p) + keyGen(h, f, v, gen) + + rqEncode(pk, h) + smallEncode(sk, f) + sk = sk[smallBytes:] + smallEncode(sk, v) + +} + +// C = zEncrypt(r,pk) +func zEncrypt(C []byte, r Inputs, pk []byte) { + h := make([]Fq, p) + c := make([]Fq, p) + rqDecode(h, pk) + encrypt(c, r[:], h) + roundedEncode(C, c) +} + +// r = zDecrypt(C,sk) +func zDecrypt(r *Inputs, C []byte, sk []byte) { + f := make([]small, p) + v := make([]small, p) + c := make([]Fq, p) + + smallDecode(f, sk) + sk = sk[smallBytes:] + smallDecode(v, sk) + roundedDecode(c, C) + + decrypt(r[:], c, f, v) +} + +// Confirmation hash + +// h = hashConfirm(r,pk,cache); cache is Hash4(pk) +func hashConfirm(h []byte, r []byte, pk []byte, cache []byte) { + x := make([]byte, hashBytes*2) + + hashPrefix(x, 3, r, inputsBytes) + + copy(x[hashBytes:], cache[:hashBytes]) + + hashPrefix(h, 2, x, len(x)) + +} + +// Session-key hash + +// k = hashSession(b,y,z) +func hashSession(k []byte, b int, y []byte, z []byte) { + x := make([]byte, hashBytes+ciphertextsBytes+confirmBytes) + + hashPrefix(x, 3, y, inputsBytes) + + copy(x[hashBytes:], z[:ciphertextsBytes+confirmBytes]) + + hashPrefix(k, b, x, len(x)) + +} + +// Streamlined NTRU Prime + +// pk,sk = kemKeyGen() +func kemKeyGen(pk []byte, sk []byte, gen *io.Reader) { + zKeyGen(pk, sk, gen) + sk = sk[secretKeysBytes:] + + copy(sk, pk) + sk = sk[publicKeysBytes:] + + if gen != nil { + (*gen).Read(sk[:inputsBytes]) + + } else { + cryptoRand.Read(sk[:inputsBytes]) + } + sk = sk[inputsBytes:] + hashPrefix(sk, 4, pk, publicKeysBytes) + +} + +// c,r_enc = hide(r,pk,cache); cache is Hash4(pk) +func hide(c []byte, r_enc []byte, r Inputs, pk []byte, cache []byte) { + smallEncode(r_enc, r[:]) + zEncrypt(c, r, pk) + c = c[ciphertextsBytes:] + hashConfirm(c, r_enc, pk, cache) + +} + +// Takes as input a public key +// Returns ciphertext and shared key +// c,k = encap(pk) +func (pub PublicKey) EncapsulateTo(c []byte, k []byte, seed []byte) { + if seed == nil { + seed = make([]byte, 4*p) + cryptoRand.Read(seed) + } + if len(seed) != 4*p { + panic("seed must be of length EncapsulationSeedSize") + } + if len(c) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + if len(k) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + pk := pub.pk[:] + + var r Inputs + r_enc := make([]byte, inputsBytes) + cache := make([]byte, hashBytes) + + hashPrefix(cache, 4, pk, publicKeysBytes) + shortRandom(r[:], seed) + hide(c, r_enc, r, pk, cache) + hashSession(k, 1, r_enc, c) + +} + +// Returns 0 if matching ciphertext+confirm, else -1 +func ciphertexts_diff_mask(c []byte, c2 []byte) int { + var differentbits uint16 = 0 + var len int = ciphertextsBytes + confirmBytes + + for i := 0; i < len; i++ { + differentbits |= uint16((c[i]) ^ (c2[i])) + } + return int((1 & ((differentbits - 1) >> 8)) - 1) + +} + +// Returns shared key from ciphertext and private key +// k = decap(c,sk) +func (priv *PrivateKey) DecapsulateTo(k []byte, c []byte) { + if len(c) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + + if len(k) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + sk := priv.sk[:] + + pk := sk[secretKeysBytes:] + rho := pk[publicKeysBytes:] + cache := rho[inputsBytes:] + var r Inputs + + r_enc := make([]byte, inputsBytes) + cnew := make([]byte, ciphertextsBytes+confirmBytes) + + zDecrypt(&r, c, sk) + hide(cnew, r_enc, r, pk, cache) + var mask int = ciphertexts_diff_mask(c, cnew) + + for i := 0; i < inputsBytes; i++ { + r_enc[i] ^= byte(mask & int(r_enc[i]^rho[i])) + } + hashSession(k, 1+mask, r_enc, c) +} + +// The structure of the private key is given by the following segments: +// The secret key, the public key, entropy and the hash of the public key +type PrivateKey struct { + sk [PrivateKeySize]byte +} + +type PublicKey struct { + pk [PublicKeySize]byte +} + +type scheme struct{} + +var sch sntrupKem.Scheme = &scheme{} + +// Scheme returns a KEM interface. +func Scheme() kem.Scheme { return sch } + +// SntrupScheme returns a sntrup.KEM interface +func SntrupScheme() sntrupKem.Scheme { return sch } + +func (*scheme) Name() string { return "sntrup761" } +func (*scheme) PublicKeySize() int { return PublicKeySize } +func (*scheme) PrivateKeySize() int { return PrivateKeySize } +func (*scheme) SeedSize() int { return KeySeedSize } +func (*scheme) SharedKeySize() int { return SharedKeySize } +func (*scheme) CiphertextSize() int { return CiphertextSize } +func (*scheme) EncapsulationSeedSize() int { return EncapsulationSeedSize } + +func (sk *PrivateKey) Scheme() kem.Scheme { return sch } +func (pk *PublicKey) Scheme() kem.Scheme { return sch } + +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + var ret [PrivateKeySize]byte + copy(ret[:], sk.sk[:]) + return ret[:], nil +} + +func (sk *PrivateKey) Equal(other kem.PrivateKey) bool { + oth, ok := other.(*PrivateKey) + if !ok { + return false + } + return bytes.Equal(sk.sk[:], oth.sk[:]) +} + +func (pk *PublicKey) Equal(other kem.PublicKey) bool { + oth, ok := other.(*PublicKey) + if !ok { + return false + } + return bytes.Equal(pk.pk[:], oth.pk[:]) +} + +func (sk *PrivateKey) Public() kem.PublicKey { + var pk [PublicKeySize]byte + skey, _ := sk.MarshalBinary() + ppk := skey[secretKeysBytes : secretKeysBytes+publicKeysBytes] + copy(pk[:], ppk[:]) + return &PublicKey{pk: pk} +} + +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + var ret [PublicKeySize]byte + copy(ret[:], pk.pk[:]) + return ret[:], nil +} + +func (*scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + var pk [PublicKeySize]byte + var sk [PrivateKeySize]byte + kemKeyGen(pk[:], sk[:], nil) + + return &PublicKey{pk: pk}, &PrivateKey{sk: sk}, nil + +} + +// Not used +func (*scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + return nil, nil +} + +func (*scheme) DeriveKeyPairFromGen(gen *io.Reader) (kem.PublicKey, kem.PrivateKey) { + + if gen == nil { + panic("A nist DRBG must be provided") + } + + var pk [PublicKeySize]byte + var sk [PrivateKeySize]byte + + kemKeyGen(pk[:], sk[:], gen) + + return &PublicKey{pk: pk}, &PrivateKey{sk: sk} +} + +func (*scheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) { + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + + pub.EncapsulateTo(ct, ss, nil) + + return ct, ss, nil + +} + +func (*scheme) EncapsulateDeterministically(pk kem.PublicKey, seed []byte) (ct, ss []byte, err error) { + + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + + pub.EncapsulateTo(ct, ss, seed) + + return ct, ss, nil +} + +func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { + ssk, ok := sk.(*PrivateKey) + if !ok { + return nil, kem.ErrTypeMismatch + } + + if len(ct) != CiphertextSize { + return nil, kem.ErrCiphertextSize + } + ss := [SharedKeySize]byte{} + + ssk.DecapsulateTo(ss[:], ct) + + return ss[:], nil +} + +func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + if len(buf) != PublicKeySize { + return nil, kem.ErrPubKeySize + } + pk := [PublicKeySize]byte{} + copy(pk[:], buf) + return &PublicKey{pk: pk}, nil +} + +func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) { + if len(buf) != PrivateKeySize { + return nil, kem.ErrPrivKeySize + } + sk := [PrivateKeySize]byte{} + copy(sk[:], buf) + return &PrivateKey{sk: sk}, nil +} diff --git a/pqhs/sntrup761/pke/ntruprime/kem/kem.go b/pqhs/sntrup761/pke/ntruprime/kem/kem.go new file mode 100644 index 0000000..2b6309a --- /dev/null +++ b/pqhs/sntrup761/pke/ntruprime/kem/kem.go @@ -0,0 +1,17 @@ +// Package kem provides a unified interface for Streamlined NTRU Prime KEM schemes. +package kem + +import ( + "io" + + "go.stargrave.org/vors/v5/pqhs/sntrup761/kem" +) + +// A Scheme represents a specific instance of a NTRU PRIME KEM. +type Scheme interface { + kem.Scheme + + // DeriveKeyPairFromGen deterministicallly derives a pair of keys from a nist DRBG. + // Only used for deterministic testing + DeriveKeyPairFromGen(gen *io.Reader) (kem.PublicKey, kem.PrivateKey) +} diff --git a/pqhs/sntrup761/pke/ntruprime/kem/schemes/sntrup/schemes.go b/pqhs/sntrup761/pke/ntruprime/kem/schemes/sntrup/schemes.go new file mode 100644 index 0000000..b0b411a --- /dev/null +++ b/pqhs/sntrup761/pke/ntruprime/kem/schemes/sntrup/schemes.go @@ -0,0 +1,39 @@ +// Package schemes contains a register of Streamlined NTRU Prime KEM schemes. +// +// # Schemes Implemented +// +// Post-quantum kems: +// +// SNTRUP653, SNTRUP761, SNTRUP857, SNTRUP953, SNTRUP1013, SNTRUP1277 +package sntrupSchemes + +import ( + "strings" + + "go.stargrave.org/vors/v5/pqhs/sntrup761/kem/ntruprime/sntrup761" + "go.stargrave.org/vors/v5/pqhs/sntrup761/pke/ntruprime/kem" +) + +var allSchemes = [...]kem.Scheme{ + sntrup761.SntrupScheme(), +} + +var allSchemeNames map[string]kem.Scheme + +func init() { + allSchemeNames = make(map[string]kem.Scheme) + for _, scheme := range allSchemes { + allSchemeNames[strings.ToLower(scheme.Name())] = scheme + } +} + +// ByName returns the scheme with the given name and nil if it is not +// supported. +// +// Names are case insensitive. +func ByName(name string) kem.Scheme { + return allSchemeNames[strings.ToLower(name)] +} + +// All returns all KEM schemes supported. +func All() []kem.Scheme { a := allSchemes; return a[:] } diff --git a/pqhs/sntrup761/pke/ntruprime/sntrup761/params.go b/pqhs/sntrup761/pke/ntruprime/sntrup761/params.go new file mode 100644 index 0000000..4e01822 --- /dev/null +++ b/pqhs/sntrup761/pke/ntruprime/sntrup761/params.go @@ -0,0 +1,25 @@ +// Code generated from sntrup.params.templ.go. DO NOT EDIT. +package ntruprime + +const ( + P = 761 + Q = 4591 + RoundedBytes = 1007 + RqBytes = 1158 + W = 286 +) + +const ( + + // Size of the established shared key. + SharedKeySize = 32 + + // Size of the encapsulated shared key. + CiphertextSize = 1039 + + // Size of a packed public key. + PublicKeySize = 1158 + + // Size of a packed private key. + PrivateKeySize = 1763 +) diff --git a/pqhs/state.go b/pqhs/state.go new file mode 100644 index 0000000..35cbe65 --- /dev/null +++ b/pqhs/state.go @@ -0,0 +1,64 @@ +package pqhs + +import ( + "crypto/cipher" + "crypto/hkdf" + "crypto/sha3" + + "golang.org/x/crypto/chacha20poly1305" +) + +type SymmetricState struct { + h, ck []byte +} + +func (state *SymmetricState) K(ctx string) []byte { + k, err := hkdf.Expand(NewSHAKE256, state.ck, ctx, chacha20poly1305.KeySize) + if err != nil { + panic(err) + } + return k +} + +func (state *SymmetricState) H(data []byte) { + state.h = sha3.SumSHAKE256(append(state.h, data...), 64) +} + +func (state *SymmetricState) CK(key []byte) { + var err error + state.ck, err = hkdf.Extract(NewSHAKE256, key, state.ck) + if err != nil { + panic(err) + } +} + +func (state *SymmetricState) Seal(ctx string, data []byte) []byte { + aead, err := chacha20poly1305.New(state.K(ctx)) + if err != nil { + panic(err) + } + ct := aead.Seal(nil, make([]byte, aead.NonceSize()), data, state.h) + state.H(ct) + return ct +} + +func (state *SymmetricState) Open(ctx string, ct []byte) (pt []byte, err error) { + var aead cipher.AEAD + aead, err = chacha20poly1305.New(state.K(ctx)) + if err != nil { + panic(err) + } + pt, err = aead.Open(nil, make([]byte, aead.NonceSize()), ct, state.h) + if err == nil { + state.H(ct) + } + return +} + +func (state *SymmetricState) Binding(l int) []byte { + binding, err := hkdf.Expand(NewSHAKE256, state.ck, string(state.h), l) + if err != nil { + panic(err) + } + return binding +}