diff --git a/vendor/git.autistici.org/ai3/go-common/pwhash/password.go b/vendor/git.autistici.org/ai3/go-common/pwhash/password.go index 5f3abea1647b26793a766907807aab6f5a60c118..f8f84e36a180e2d6634cf0cb7eb0071a548d5f6c 100644 --- a/vendor/git.autistici.org/ai3/go-common/pwhash/password.go +++ b/vendor/git.autistici.org/ai3/go-common/pwhash/password.go @@ -15,7 +15,8 @@ import ( "golang.org/x/crypto/scrypt" ) -// PasswordHash is a convenience interface common to all types in this package. +// PasswordHash is the interface for a password hashing algorithm +// implementation. type PasswordHash interface { // ComparePassword returns true if the given password matches // the encrypted one. @@ -25,12 +26,20 @@ type PasswordHash interface { Encrypt(string) string } -// SystemCryptPasswordHash uses the glibc crypt function. -type SystemCryptPasswordHash struct{} +// systemCryptPasswordHash uses the glibc crypt function. +type systemCryptPasswordHash struct { + hashStr string +} + +// NewSystemCrypt returns a PasswordHash that uses the system crypt(3) +// function, specifically glibc with its SHA512 algorithm. +func NewSystemCrypt() PasswordHash { + return &systemCryptPasswordHash{"$6$"} +} // ComparePassword returns true if the given password matches the // encrypted one. -func (s *SystemCryptPasswordHash) ComparePassword(encrypted, password string) bool { +func (s *systemCryptPasswordHash) ComparePassword(encrypted, password string) bool { enc2, err := crypt.Crypt(password, encrypted) if err != nil { return false @@ -39,8 +48,8 @@ func (s *SystemCryptPasswordHash) ComparePassword(encrypted, password string) bo } // Encrypt the given password using glibc crypt. -func (s *SystemCryptPasswordHash) Encrypt(password string) string { - salt := fmt.Sprintf("$6$%x$", getRandomBytes(16)) +func (s *systemCryptPasswordHash) Encrypt(password string) string { + salt := fmt.Sprintf("%s%x$", s.hashStr, getRandomBytes(16)) enc, err := crypt.Crypt(password, salt) if err != nil { panic(err) @@ -54,28 +63,48 @@ var ( ) // Argon2PasswordHash uses the Argon2 hashing algorithm. -type Argon2PasswordHash struct{} +type argon2PasswordHash struct { + // Encoding parameters. + params argon2Params +} + +// NewArgon2 returns an Argon2i-based PasswordHash using the default parameters. +func NewArgon2() PasswordHash { + return NewArgon2WithParams( + defaultArgon2Params.Time, + defaultArgon2Params.Memory, + defaultArgon2Params.Threads, + ) +} + +// NewArgon2WithParams returns an Argon2i-based PasswordHash using the +// specified parameters for time, memory, and number of threads. +func NewArgon2WithParams(time, mem uint32, threads uint8) PasswordHash { + return &argon2PasswordHash{ + params: argon2Params{ + Time: time, + Memory: mem, + Threads: threads, + }, + } +} // ComparePassword returns true if the given password matches the // encrypted one. -func (s *Argon2PasswordHash) ComparePassword(encrypted, password string) bool { +func (s *argon2PasswordHash) ComparePassword(encrypted, password string) bool { params, salt, dk, err := decodeArgon2Hash(encrypted) if err != nil { return false } dk2 := argon2.Key([]byte(password), salt, params.Time, params.Memory, params.Threads, argonKeyLen) - //log.Printf("params=%+v, salt=%+v, dk=%v, dk2=%v", params, salt, dk, dk2) return subtle.ConstantTimeCompare(dk, dk2) == 1 } // Encrypt the given password with the Argon2 algorithm. -func (s *Argon2PasswordHash) Encrypt(password string) string { +func (s *argon2PasswordHash) Encrypt(password string) string { salt := getRandomBytes(argonSaltLen) - params := defaultArgon2Params - - dk := argon2.Key([]byte(password), salt, params.Time, params.Memory, params.Threads, argonKeyLen) - - return encodeArgon2Hash(params, salt, dk) + dk := argon2.Key([]byte(password), salt, s.params.Time, s.params.Memory, s.params.Threads, argonKeyLen) + return encodeArgon2Hash(s.params, salt, dk) } type argon2Params struct { @@ -84,13 +113,12 @@ type argon2Params struct { Threads uint8 } +// Default Argon2 parameters are tuned for a high-traffic +// authentication service (<1ms per operation). var defaultArgon2Params = argon2Params{ - Time: 4, - Memory: 32 * 1024, - Threads: 1, - - // Test fails with threads > 1 !! - //Threads: uint8(runtime.NumCPU()), + Time: 1, + Memory: 4 * 1024, + Threads: 4, } func encodeArgon2Hash(params argon2Params, salt, dk []byte) string { @@ -139,11 +167,35 @@ var ( ) // ScryptPasswordHash uses the scrypt hashing algorithm. -type ScryptPasswordHash struct{} +type scryptPasswordHash struct { + params scryptParams +} + +// NewScrypt returns a PasswordHash that uses the scrypt algorithm +// with the default parameters. +func NewScrypt() PasswordHash { + return NewScryptWithParams( + defaultScryptParams.N, + defaultScryptParams.R, + defaultScryptParams.P, + ) +} + +// NewScryptWithParams returns a PasswordHash that uses the scrypt +// algorithm with the specified parameters. +func NewScryptWithParams(n, r, p int) PasswordHash { + return &scryptPasswordHash{ + params: scryptParams{ + N: n, + R: r, + P: p, + }, + } +} // ComparePassword returns true if the given password matches // the encrypted one. -func (s *ScryptPasswordHash) ComparePassword(encrypted, password string) bool { +func (s *scryptPasswordHash) ComparePassword(encrypted, password string) bool { params, salt, dk, err := decodeScryptHash(encrypted) if err != nil { return false @@ -152,21 +204,19 @@ func (s *ScryptPasswordHash) ComparePassword(encrypted, password string) bool { if err != nil { return false } - //log.Printf("params=%+v, salt=%+v, dk=%v, dk2=%v", params, salt, dk, dk2) return subtle.ConstantTimeCompare(dk, dk2) == 1 } // Encrypt the given password with the scrypt algorithm. -func (s *ScryptPasswordHash) Encrypt(password string) string { +func (s *scryptPasswordHash) Encrypt(password string) string { salt := getRandomBytes(scryptSaltLen) - params := defaultScryptParams - dk, err := scrypt.Key([]byte(password), salt, params.N, params.R, params.P, scryptKeyLen) + dk, err := scrypt.Key([]byte(password), salt, s.params.N, s.params.R, s.params.P, scryptKeyLen) if err != nil { panic(err) } - return encodeScryptHash(params, salt, dk) + return encodeScryptHash(s.params, salt, dk) } type scryptParams struct { @@ -224,12 +274,13 @@ func getRandomBytes(n int) []byte { return b } +// A registry of default handlers for decoding passwords. var prefixRegistry = map[string]PasswordHash{ - "$1$": &SystemCryptPasswordHash{}, - "$5$": &SystemCryptPasswordHash{}, - "$6$": &SystemCryptPasswordHash{}, - "$s$": &ScryptPasswordHash{}, - "$a2$": &Argon2PasswordHash{}, + "$1$": NewSystemCrypt(), + "$5$": NewSystemCrypt(), + "$6$": NewSystemCrypt(), + "$s$": NewScrypt(), + "$a2$": NewArgon2(), } // ComparePassword returns true if the given password matches the @@ -245,7 +296,11 @@ func ComparePassword(encrypted, password string) bool { // DefaultEncryptAlgorithm is used by the Encrypt function to encrypt // passwords. -var DefaultEncryptAlgorithm PasswordHash = &Argon2PasswordHash{} +var DefaultEncryptAlgorithm PasswordHash + +func init() { + DefaultEncryptAlgorithm = NewArgon2() +} // Encrypt will encrypt a password with the default algorithm. func Encrypt(password string) string { diff --git a/vendor/git.autistici.org/ai3/go-common/serverutil/http.go b/vendor/git.autistici.org/ai3/go-common/serverutil/http.go index 7fbd69fe5693d7f33ca4a8c1faccd9ee073bc01c..32329492c8a490485b7094fd4e2d608246aa78d8 100644 --- a/vendor/git.autistici.org/ai3/go-common/serverutil/http.go +++ b/vendor/git.autistici.org/ai3/go-common/serverutil/http.go @@ -13,6 +13,7 @@ import ( "syscall" "time" + "github.com/coreos/go-systemd/daemon" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) @@ -82,7 +83,8 @@ func Serve(h http.Handler, config *ServerConfig, addr string) error { return err } - // Create the net.Listener, then notify systemd that we are ready to serve. + // Create the net.Listener first, so we can detect + // initialization-time errors safely. l, err := net.Listen("tcp", addr) if err != nil { return err @@ -113,6 +115,9 @@ func Serve(h http.Handler, config *ServerConfig, addr string) error { signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + // Notify systemd that we are ready to serve. + daemon.SdNotify(false, "READY=1") + err = srv.Serve(l) if err != http.ErrServerClosed { return err diff --git a/vendor/git.autistici.org/ai3/go-common/userenckey/container.go b/vendor/git.autistici.org/ai3/go-common/userenckey/container.go new file mode 100644 index 0000000000000000000000000000000000000000..5da01a946a5c634ede438071a93f5c61b12711da --- /dev/null +++ b/vendor/git.autistici.org/ai3/go-common/userenckey/container.go @@ -0,0 +1,125 @@ +package userenckey + +import ( + "bytes" + "crypto/rand" + "errors" + "io" + + "github.com/lunixbochs/struc" + "github.com/miscreant/miscreant/go" + "golang.org/x/crypto/argon2" +) + +// Current algorithm: Argon2 KDF + AES-SIV key encryption. +const algoArgon2AESSIV = 1 + +const aeadAlgo = "AES-SIV" + +// Struct members have stupid names to reduce the size of the resulting gob! +type argon2Params struct { + Time uint32 `struc:"uint32,little"` + Memory uint32 `struc:"uint32,little"` + Threads uint8 `struc:"uint8"` +} + +// Default Argon2 parameters are tuned for a high-traffic +// authentication service (<1ms per operation). +var defaultArgon2Params = argon2Params{ + Time: 1, + Memory: 4 * 1024, + Threads: 4, +} + +const ( + keyLen = 64 + saltLen = 32 +) + +func argon2KDF(params argon2Params, salt, pw []byte) []byte { + return argon2.Key(pw, salt, params.Time, params.Memory, params.Threads, keyLen) +} + +// An encrypted container stores an opaque blob of binary data along +// with metadata about the encryption itself, to allow for a +// controlled amount of algorithm malleability accounting for future +// updates. The structure is binary-packed (as opposed to using higher +// level serializations such as encoding/gob) because we'd like to be +// able to read it from other languages if necessary. +type container struct { // nolint: maligned + Algo uint8 `struc:"uint8"` + Params argon2Params + SaltLen uint8 `struc:"uint8,sizeof=Salt"` + Salt []byte + DataLen uint16 `struc:"uint16,little,sizeof=Data"` + Data []byte +} + +// Convert to an opaque encoded ("wire") representation. +func (c *container) Marshal() ([]byte, error) { + var buf bytes.Buffer + err := struc.Pack(&buf, c) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +// Parse a key object from the wire representation. +func unmarshalContainer(b []byte) (c container, err error) { + err = struc.Unpack(bytes.NewReader(b), &c) + return +} + +func newContainer(data, pw []byte) (container, error) { + return encryptArgon2AESSIV(data, pw) +} + +func (c container) decrypt(pw []byte) ([]byte, error) { + // Only one supported kdf/algo combination right now. + if c.Algo == algoArgon2AESSIV { + return c.decryptArgon2AESSIV(pw) + } + return nil, errors.New("unsupported algo") +} + +func (c container) decryptArgon2AESSIV(pw []byte) ([]byte, error) { + // Run the KDF and create the AEAD cipher. + dk := argon2KDF(c.Params, c.Salt, pw) + cipher, err := miscreant.NewAEAD(aeadAlgo, dk, 0) + if err != nil { + return nil, err + } + + // Decrypt the data and obtain the DER-encoded private key. + dec, err := cipher.Open(nil, nil, c.Data, nil) + return dec, err +} + +func encryptArgon2AESSIV(data, pw []byte) (container, error) { + c := container{ + Algo: algoArgon2AESSIV, + Params: defaultArgon2Params, + Salt: genRandomSalt(), + } + + // Run the KDF and create the AEAD cipher. + dk := argon2KDF(c.Params, c.Salt, pw) + cipher, err := miscreant.NewAEAD(aeadAlgo, dk, 0) + if err != nil { + return container{}, err + } + + // Encrypt the data (a DER-encoded ECDSA private key). + c.Data = cipher.Seal(nil, nil, data, nil) + return c, nil +} + +func genRandomSalt() []byte { + var b [saltLen]byte + if _, err := io.ReadFull(rand.Reader, b[:]); err != nil { + panic(err) + } + return b[:] +} diff --git a/vendor/git.autistici.org/ai3/go-common/userenckey/key.go b/vendor/git.autistici.org/ai3/go-common/userenckey/key.go new file mode 100644 index 0000000000000000000000000000000000000000..d10c4df0080a64c361dc0be62cb68fb7ae4f41ee --- /dev/null +++ b/vendor/git.autistici.org/ai3/go-common/userenckey/key.go @@ -0,0 +1,90 @@ +package userenckey + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "encoding/pem" + "errors" +) + +// ErrBadPassword is returned on decryption failure. +var ErrBadPassword = errors.New("could not decrypt key with password") + +func encodePublicKeyToPEM(pub *ecdsa.PublicKey) ([]byte, error) { + der, err := x509.MarshalPKIXPublicKey(pub) + if err != nil { + return nil, err + } + return pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: der}), nil +} + +// Key (unencrypted). +type Key struct { + rawBytes []byte +} + +// GenerateKey generates a new ECDSA key pair, and returns the +// PEM-encoded public and private key (in order). +func GenerateKey() ([]byte, *Key, error) { + priv, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) + if err != nil { + return nil, nil, err + } + + //privBytes, err := encodePrivateKeyToPEM(priv) + privBytes, err := x509.MarshalECPrivateKey(priv) + if err != nil { + return nil, nil, err + } + pubBytes, err := encodePublicKeyToPEM(&priv.PublicKey) + if err != nil { + return nil, nil, err + } + + return pubBytes, &Key{privBytes}, nil +} + +// PEM returns the key in PEM-encoded format. +func (k *Key) PEM() ([]byte, error) { + // Parse the ASN.1 data and encode it with PKCS8 (in PEM format). + priv, err := k.PrivateKey() + if err != nil { + return nil, err + } + + return encodePrivateKeyToPEM(priv) +} + +// PrivateKey parses the DER-encoded ASN.1 data in Key and returns the +// private key object. +func (k *Key) PrivateKey() (*ecdsa.PrivateKey, error) { + return x509.ParseECPrivateKey(k.rawBytes) +} + +// Encrypt a key with a password and a random salt. +func Encrypt(key *Key, pw []byte) ([]byte, error) { + c, err := newContainer(key.rawBytes, pw) + if err != nil { + return nil, err + } + return c.Marshal() +} + +// Decrypt one out of multiple keys with the specified password. The +// keys share the same cleartext, but have been encrypted with +// different passwords. +func Decrypt(encKeys [][]byte, pw []byte) (*Key, error) { + for _, encKey := range encKeys { + c, err := unmarshalContainer(encKey) + if err != nil { + //log.Printf("parse error: %v", err) + continue + } + if dec, err := c.decrypt(pw); err == nil { + return &Key{dec}, nil + } + } + return nil, ErrBadPassword +} diff --git a/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8.go b/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8.go new file mode 100644 index 0000000000000000000000000000000000000000..1e483e6e18d4b35dcffa82894a9a2ba5e3200d97 --- /dev/null +++ b/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8.go @@ -0,0 +1,18 @@ +// +build go1.10 + +package userenckey + +import ( + "crypto/ecdsa" + "crypto/x509" + "encoding/pem" +) + +// Encode a private key to PEM-encoded PKCS8. +func encodePrivateKeyToPEM(priv *ecdsa.PrivateKey) ([]byte, error) { + der, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + return nil, err + } + return pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: der}), nil +} diff --git a/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8_compat.go b/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8_compat.go new file mode 100644 index 0000000000000000000000000000000000000000..7f36efbad3fe773e862defe6f3e2508bc397c9cf --- /dev/null +++ b/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8_compat.go @@ -0,0 +1,28 @@ +// +build !go1.10 + +package userenckey + +import ( + "bytes" + "crypto/ecdsa" + "crypto/x509" + "encoding/pem" + "os/exec" +) + +// Encode a private key to PEM-encoded PKCS8. +// +// In Go versions prior to 1.10, we must shell out to openssl to +// convert the private key to PKCS8 format. +func encodePrivateKeyToPEM(priv *ecdsa.PrivateKey) ([]byte, error) { + der, err := x509.MarshalECPrivateKey(priv) + if err != nil { + return nil, err + } + pkcs1 := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: der}) + + /* #nosec */ + cmd := exec.Command("/usr/bin/openssl", "pkey") + cmd.Stdin = bytes.NewReader(pkcs1) + return cmd.Output() +} diff --git a/vendor/github.com/boombuler/barcode/README.md b/vendor/github.com/boombuler/barcode/README.md index 2a988db39992867a66208286429e141ed9b4e19e..e11f908525ab357a709fd0b1dbb16b58260aa4bc 100644 --- a/vendor/github.com/boombuler/barcode/README.md +++ b/vendor/github.com/boombuler/barcode/README.md @@ -1,7 +1,4 @@ -[](https://gitter.im/golang-barcode/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - ## Introduction ## - This is a package for GO which can be used to create different types of barcodes. ## Supported Barcode Types ## diff --git a/vendor/github.com/lunixbochs/struc/LICENSE b/vendor/github.com/lunixbochs/struc/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..42e82633f1948c8628e4dd39be98350a66692c5f --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Ryan Hileman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/lunixbochs/struc/README.md b/vendor/github.com/lunixbochs/struc/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c8134971438bdb7e6c0a5798d46aa3cb6d5845e3 --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/README.md @@ -0,0 +1,103 @@ +[](https://travis-ci.org/lunixbochs/struc) + +struc +==== + +Struc exists to pack and unpack C-style structures from bytes, which is useful for binary files and network protocols. It could be considered an alternative to `encoding/binary`, which requires massive boilerplate for some similar operations. + +Take a look at an [example comparing `struc` and `encoding/binary`](https://bochs.info/p/cxvm9) + +Struc considers usability first. That said, it does cache reflection data and aims to be competitive with `encoding/binary` struct packing in every way, including performance. + +Example struct +---- + +```Go +type Example struct { + Var int `struc:"int32,sizeof=Str"` + Str string + Weird []byte `struc:"[8]int64"` + Var []int `struc:"[]int32,little"` +} +``` + +Struct tag format +---- + + - ```Var []int `struc:"[]int32,little,sizeof=StringField"` ``` will pack Var as a slice of little-endian int32, and link it as the size of `StringField`. + - `sizeof=`: Indicates this field is a number used to track the length of a another field. `sizeof` fields are automatically updated on `Pack()` based on the current length of the tracked field, and are used to size the target field during `Unpack()`. + - Bare values will be parsed as type and endianness. + +Endian formats +---- + + - `big` (default) + - `little` + +Recognized types +---- + + - `pad` - this type ignores field contents and is backed by a `[length]byte` containing nulls + - `bool` + - `byte` + - `int8`, `uint8` + - `int16`, `uint16` + - `int32`, `uint32` + - `int64`, `uint64` + - `float32` + - `float64` + +Types can be indicated as arrays/slices using `[]` syntax. Example: `[]int64`, `[8]int32`. + +Bare slice types (those with no `[size]`) must have a linked `Sizeof` field. + +Private fields are ignored when packing and unpacking. + +Example code +---- + +```Go +package main + +import ( + "bytes" + "github.com/lunixbochs/struc" +) + +type Example struct { + A int `struc:"big"` + + // B will be encoded/decoded as a 16-bit int (a "short") + // but is stored as a native int in the struct + B int `struc:"int16"` + + // the sizeof key links a buffer's size to any int field + Size int `struc:"int8,little,sizeof=Str"` + Str string + + // you can get freaky if you want + Str2 string `struc:"[5]int64"` +} + +func main() { + var buf bytes.Buffer + t := &Example{1, 2, 0, "test", "test2"} + err := struc.Pack(&buf, t) + o := &Example{} + err = struc.Unpack(&buf, o) +} +``` + +Benchmark +---- + +`BenchmarkEncode` uses struc. `Stdlib` benchmarks use equivalent `encoding/binary` code. `Manual` encodes without any reflection, and should be considered an upper bound on performance (which generated code based on struc definitions should be able to achieve). + +``` +BenchmarkEncode 1000000 1265 ns/op +BenchmarkStdlibEncode 1000000 1855 ns/op +BenchmarkManualEncode 5000000 284 ns/op +BenchmarkDecode 1000000 1259 ns/op +BenchmarkStdlibDecode 1000000 1656 ns/op +BenchmarkManualDecode 20000000 89.0 ns/op +``` diff --git a/vendor/github.com/lunixbochs/struc/binary.go b/vendor/github.com/lunixbochs/struc/binary.go new file mode 100644 index 0000000000000000000000000000000000000000..4899d08fd2bacd81c14f32dc247817a824206c30 --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/binary.go @@ -0,0 +1,52 @@ +package struc + +import ( + "encoding/binary" + "io" + "reflect" +) + +type byteWriter struct { + buf []byte + pos int +} + +func (b byteWriter) Write(p []byte) (int, error) { + capacity := len(b.buf) - b.pos + if capacity < len(p) { + p = p[:capacity] + } + if len(p) > 0 { + copy(b.buf[b.pos:], p) + b.pos += len(p) + } + return len(p), nil +} + +type binaryFallback reflect.Value + +func (b binaryFallback) String() string { + return b.String() +} + +func (b binaryFallback) Sizeof(val reflect.Value, options *Options) int { + return binary.Size(val.Interface()) +} + +func (b binaryFallback) Pack(buf []byte, val reflect.Value, options *Options) (int, error) { + tmp := byteWriter{buf: buf} + var order binary.ByteOrder = binary.BigEndian + if options.Order != nil { + order = options.Order + } + err := binary.Write(tmp, order, val.Interface()) + return tmp.pos, err +} + +func (b binaryFallback) Unpack(r io.Reader, val reflect.Value, options *Options) error { + var order binary.ByteOrder = binary.BigEndian + if options.Order != nil { + order = options.Order + } + return binary.Read(r, order, val.Interface()) +} diff --git a/vendor/github.com/lunixbochs/struc/custom.go b/vendor/github.com/lunixbochs/struc/custom.go new file mode 100644 index 0000000000000000000000000000000000000000..c468dce5cb1ac51c04dc0f250ef97d97f21511af --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/custom.go @@ -0,0 +1,33 @@ +package struc + +import ( + "io" + "reflect" +) + +type Custom interface { + Pack(p []byte, opt *Options) (int, error) + Unpack(r io.Reader, length int, opt *Options) error + Size(opt *Options) int + String() string +} + +type customFallback struct { + custom Custom +} + +func (c customFallback) Pack(p []byte, val reflect.Value, opt *Options) (int, error) { + return c.custom.Pack(p, opt) +} + +func (c customFallback) Unpack(r io.Reader, val reflect.Value, opt *Options) error { + return c.custom.Unpack(r, 1, opt) +} + +func (c customFallback) Sizeof(val reflect.Value, opt *Options) int { + return c.custom.Size(opt) +} + +func (c customFallback) String() string { + return c.custom.String() +} diff --git a/vendor/github.com/lunixbochs/struc/custom_float16.go b/vendor/github.com/lunixbochs/struc/custom_float16.go new file mode 100644 index 0000000000000000000000000000000000000000..722be7657ae5171d1d2eee48cb68ccd0072d6344 --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/custom_float16.go @@ -0,0 +1,78 @@ +package struc + +import ( + "encoding/binary" + "io" + "math" + "strconv" +) + +type Float16 float64 + +func (f *Float16) Pack(p []byte, opt *Options) (int, error) { + order := opt.Order + if order == nil { + order = binary.BigEndian + } + sign := uint16(0) + if *f < 0 { + sign = 1 + } + var frac, exp uint16 + if math.IsInf(float64(*f), 0) { + exp = 0x1f + frac = 0 + } else if math.IsNaN(float64(*f)) { + exp = 0x1f + frac = 1 + } else { + bits := math.Float64bits(float64(*f)) + exp64 := (bits >> 52) & 0x7ff + if exp64 != 0 { + exp = uint16((exp64 - 1023 + 15) & 0x1f) + } + frac = uint16((bits >> 42) & 0x3ff) + } + var out uint16 + out |= sign << 15 + out |= exp << 10 + out |= frac & 0x3ff + order.PutUint16(p, out) + return 2, nil +} +func (f *Float16) Unpack(r io.Reader, length int, opt *Options) error { + order := opt.Order + if order == nil { + order = binary.BigEndian + } + var tmp [2]byte + if _, err := r.Read(tmp[:]); err != nil { + return err + } + val := order.Uint16(tmp[:2]) + sign := (val >> 15) & 1 + exp := int16((val >> 10) & 0x1f) + frac := val & 0x3ff + if exp == 0x1f { + if frac != 0 { + *f = Float16(math.NaN()) + } else { + *f = Float16(math.Inf(int(sign)*-2 + 1)) + } + } else { + var bits uint64 + bits |= uint64(sign) << 63 + bits |= uint64(frac) << 42 + if exp > 0 { + bits |= uint64(exp-15+1023) << 52 + } + *f = Float16(math.Float64frombits(bits)) + } + return nil +} +func (f *Float16) Size(opt *Options) int { + return 2 +} +func (f *Float16) String() string { + return strconv.FormatFloat(float64(*f), 'g', -1, 32) +} diff --git a/vendor/github.com/lunixbochs/struc/field.go b/vendor/github.com/lunixbochs/struc/field.go new file mode 100644 index 0000000000000000000000000000000000000000..6e59c2abcb8679034032462fc139cf2d95e3b799 --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/field.go @@ -0,0 +1,288 @@ +package struc + +import ( + "bytes" + "encoding/binary" + "fmt" + "math" + "reflect" +) + +type Field struct { + Name string + Ptr bool + Index int + Type Type + defType Type + Array bool + Slice bool + Len int + Order binary.ByteOrder + Sizeof []int + Sizefrom []int + Fields Fields + kind reflect.Kind +} + +func (f *Field) String() string { + var out string + if f.Type == Pad { + return fmt.Sprintf("{type: Pad, len: %d}", f.Len) + } else { + out = fmt.Sprintf("type: %s, order: %v", f.Type.String(), f.Order) + } + if f.Sizefrom != nil { + out += fmt.Sprintf(", sizefrom: %v", f.Sizefrom) + } else if f.Len > 0 { + out += fmt.Sprintf(", len: %d", f.Len) + } + if f.Sizeof != nil { + out += fmt.Sprintf(", sizeof: %v", f.Sizeof) + } + return "{" + out + "}" +} + +func (f *Field) Size(val reflect.Value, options *Options) int { + typ := f.Type.Resolve(options) + size := 0 + if typ == Struct { + vals := []reflect.Value{val} + if f.Slice { + vals = make([]reflect.Value, val.Len()) + for i := 0; i < val.Len(); i++ { + vals[i] = val.Index(i) + } + } + for _, val := range vals { + size += f.Fields.Sizeof(val, options) + } + } else if typ == Pad { + size = f.Len + } else if f.Slice || f.kind == reflect.String { + length := val.Len() + if f.Len > 1 { + length = f.Len + } + size = length * typ.Size() + } else if typ == CustomType { + return val.Addr().Interface().(Custom).Size(options) + } else { + size = typ.Size() + } + align := options.ByteAlign + if align > 0 && size < align { + size = align + } + return size +} + +func (f *Field) packVal(buf []byte, val reflect.Value, length int, options *Options) (size int, err error) { + order := f.Order + if options.Order != nil { + order = options.Order + } + if f.Ptr { + val = val.Elem() + } + typ := f.Type.Resolve(options) + switch typ { + case Struct: + return f.Fields.Pack(buf, val, options) + case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64: + size = typ.Size() + var n uint64 + switch f.kind { + case reflect.Bool: + if val.Bool() { + n = 1 + } else { + n = 0 + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n = uint64(val.Int()) + default: + n = val.Uint() + } + switch typ { + case Bool: + if n != 0 { + buf[0] = 1 + } else { + buf[0] = 0 + } + case Int8, Uint8: + buf[0] = byte(n) + case Int16, Uint16: + order.PutUint16(buf, uint16(n)) + case Int32, Uint32: + order.PutUint32(buf, uint32(n)) + case Int64, Uint64: + order.PutUint64(buf, uint64(n)) + } + case Float32, Float64: + size = typ.Size() + n := val.Float() + switch typ { + case Float32: + order.PutUint32(buf, math.Float32bits(float32(n))) + case Float64: + order.PutUint64(buf, math.Float64bits(n)) + } + case String: + switch f.kind { + case reflect.String: + size = val.Len() + copy(buf, []byte(val.String())) + default: + // TODO: handle kind != bytes here + size = val.Len() + copy(buf, val.Bytes()) + } + case CustomType: + return val.Addr().Interface().(Custom).Pack(buf, options) + default: + panic(fmt.Sprintf("no pack handler for type: %s", typ)) + } + return +} + +func (f *Field) Pack(buf []byte, val reflect.Value, length int, options *Options) (int, error) { + typ := f.Type.Resolve(options) + if typ == Pad { + for i := 0; i < length; i++ { + buf[i] = 0 + } + return length, nil + } + if f.Slice { + // special case strings and byte slices for performance + end := val.Len() + if !f.Array && typ == Uint8 && (f.defType == Uint8 || f.kind == reflect.String) { + var tmp []byte + if f.kind == reflect.String { + tmp = []byte(val.String()) + } else { + tmp = val.Bytes() + } + copy(buf, tmp) + if end < length { + // TODO: allow configuring pad byte? + rep := bytes.Repeat([]byte{0}, length-end) + copy(buf[end:], rep) + return length, nil + } + return val.Len(), nil + } + pos := 0 + var zero reflect.Value + if end < length { + zero = reflect.Zero(val.Type().Elem()) + } + for i := 0; i < length; i++ { + cur := zero + if i < end { + cur = val.Index(i) + } + if n, err := f.packVal(buf[pos:], cur, 1, options); err != nil { + return pos, err + } else { + pos += n + } + } + return pos, nil + } else { + return f.packVal(buf, val, length, options) + } +} + +func (f *Field) unpackVal(buf []byte, val reflect.Value, length int, options *Options) error { + order := f.Order + if options.Order != nil { + order = options.Order + } + if f.Ptr { + val = val.Elem() + } + typ := f.Type.Resolve(options) + switch typ { + case Float32, Float64: + var n float64 + switch typ { + case Float32: + n = float64(math.Float32frombits(order.Uint32(buf))) + case Float64: + n = math.Float64frombits(order.Uint64(buf)) + } + switch f.kind { + case reflect.Float32, reflect.Float64: + val.SetFloat(n) + default: + return fmt.Errorf("struc: refusing to unpack float into field %s of type %s", f.Name, f.kind.String()) + } + case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64: + var n uint64 + switch typ { + case Int8: + n = uint64(int64(int8(buf[0]))) + case Int16: + n = uint64(int64(int16(order.Uint16(buf)))) + case Int32: + n = uint64(int64(int32(order.Uint32(buf)))) + case Int64: + n = uint64(int64(order.Uint64(buf))) + case Bool, Uint8: + n = uint64(buf[0]) + case Uint16: + n = uint64(order.Uint16(buf)) + case Uint32: + n = uint64(order.Uint32(buf)) + case Uint64: + n = uint64(order.Uint64(buf)) + } + switch f.kind { + case reflect.Bool: + val.SetBool(n != 0) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + val.SetInt(int64(n)) + default: + val.SetUint(n) + } + default: + panic(fmt.Sprintf("no unpack handler for type: %s", typ)) + } + return nil +} + +func (f *Field) Unpack(buf []byte, val reflect.Value, length int, options *Options) error { + typ := f.Type.Resolve(options) + if typ == Pad || f.kind == reflect.String { + if typ == Pad { + return nil + } else { + val.SetString(string(buf)) + return nil + } + } else if f.Slice { + if val.Cap() < length { + val.Set(reflect.MakeSlice(val.Type(), length, length)) + } else if val.Len() < length { + val.Set(val.Slice(0, length)) + } + // special case byte slices for performance + if !f.Array && typ == Uint8 && f.defType == Uint8 { + copy(val.Bytes(), buf[:length]) + return nil + } + pos := 0 + size := typ.Size() + for i := 0; i < length; i++ { + if err := f.unpackVal(buf[pos:pos+size], val.Index(i), 1, options); err != nil { + return err + } + pos += size + } + return nil + } else { + return f.unpackVal(buf, val, length, options) + } +} diff --git a/vendor/github.com/lunixbochs/struc/fields.go b/vendor/github.com/lunixbochs/struc/fields.go new file mode 100644 index 0000000000000000000000000000000000000000..5d591bf0e97aa68d41e3ef7f8cdc2898bbae29b6 --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/fields.go @@ -0,0 +1,172 @@ +package struc + +import ( + "encoding/binary" + "fmt" + "io" + "reflect" + "strings" +) + +type Fields []*Field + +func (f Fields) SetByteOrder(order binary.ByteOrder) { + for _, field := range f { + if field != nil { + field.Order = order + } + } +} + +func (f Fields) String() string { + fields := make([]string, len(f)) + for i, field := range f { + if field != nil { + fields[i] = field.String() + } + } + return "{" + strings.Join(fields, ", ") + "}" +} + +func (f Fields) Sizeof(val reflect.Value, options *Options) int { + for val.Kind() == reflect.Ptr { + val = val.Elem() + } + size := 0 + for i, field := range f { + if field != nil { + size += field.Size(val.Field(i), options) + } + } + return size +} + +func (f Fields) sizefrom(val reflect.Value, index []int) int { + field := val.FieldByIndex(index) + switch field.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return int(field.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + n := int(field.Uint()) + // all the builtin array length types are native int + // so this guards against weird truncation + if n < 0 { + return 0 + } + return n + default: + name := val.Type().FieldByIndex(index).Name + panic(fmt.Sprintf("sizeof field %T.%s not an integer type", val.Interface(), name)) + } +} + +func (f Fields) Pack(buf []byte, val reflect.Value, options *Options) (int, error) { + for val.Kind() == reflect.Ptr { + val = val.Elem() + } + pos := 0 + for i, field := range f { + if field == nil { + continue + } + v := val.Field(i) + length := field.Len + if field.Sizefrom != nil { + length = f.sizefrom(val, field.Sizefrom) + } + if length <= 0 && field.Slice { + length = v.Len() + } + if field.Sizeof != nil { + length := val.FieldByIndex(field.Sizeof).Len() + switch field.kind { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + // allocating a new int here has fewer side effects (doesn't update the original struct) + // but it's a wasteful allocation + // the old method might work if we just cast the temporary int/uint to the target type + v = reflect.New(v.Type()).Elem() + v.SetInt(int64(length)) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + v = reflect.New(v.Type()).Elem() + v.SetUint(uint64(length)) + default: + panic(fmt.Sprintf("sizeof field is not int or uint type: %s, %s", field.Name, v.Type())) + } + } + if n, err := field.Pack(buf[pos:], v, length, options); err != nil { + return n, err + } else { + pos += n + } + } + return pos, nil +} + +func (f Fields) Unpack(r io.Reader, val reflect.Value, options *Options) error { + for val.Kind() == reflect.Ptr { + val = val.Elem() + } + var tmp [8]byte + var buf []byte + for i, field := range f { + if field == nil { + continue + } + v := val.Field(i) + length := field.Len + if field.Sizefrom != nil { + length = f.sizefrom(val, field.Sizefrom) + } + if v.Kind() == reflect.Ptr && !v.Elem().IsValid() { + v.Set(reflect.New(v.Type().Elem())) + } + if field.Type == Struct { + if field.Slice { + vals := reflect.MakeSlice(v.Type(), length, length) + for i := 0; i < length; i++ { + v := vals.Index(i) + fields, err := parseFields(v) + if err != nil { + return err + } + if err := fields.Unpack(r, v, options); err != nil { + return err + } + } + v.Set(vals) + } else { + // TODO: DRY (we repeat the inner loop above) + fields, err := parseFields(v) + if err != nil { + return err + } + if err := fields.Unpack(r, v, options); err != nil { + return err + } + } + continue + } else { + typ := field.Type.Resolve(options) + if typ == CustomType { + if err := v.Addr().Interface().(Custom).Unpack(r, length, options); err != nil { + return err + } + } else { + size := length * field.Type.Resolve(options).Size() + if size < 8 { + buf = tmp[:size] + } else { + buf = make([]byte, size) + } + if _, err := io.ReadFull(r, buf); err != nil { + return err + } + err := field.Unpack(buf[:size], v, length, options) + if err != nil { + return err + } + } + } + } + return nil +} diff --git a/vendor/github.com/lunixbochs/struc/legacy.go b/vendor/github.com/lunixbochs/struc/legacy.go new file mode 100644 index 0000000000000000000000000000000000000000..5baf70d987ee8970cc4182edceab8b589af58e8a --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/legacy.go @@ -0,0 +1,16 @@ +package struc + +import ( + "encoding/binary" + "io" +) + +// Deprecated. Use PackWithOptions. +func PackWithOrder(w io.Writer, data interface{}, order binary.ByteOrder) error { + return PackWithOptions(w, data, &Options{Order: order}) +} + +// Deprecated. Use UnpackWithOptions. +func UnpackWithOrder(r io.Reader, data interface{}, order binary.ByteOrder) error { + return UnpackWithOptions(r, data, &Options{Order: order}) +} diff --git a/vendor/github.com/lunixbochs/struc/packer.go b/vendor/github.com/lunixbochs/struc/packer.go new file mode 100644 index 0000000000000000000000000000000000000000..a3a91a228816dd3bd26421320e8dea74fc9d61e0 --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/packer.go @@ -0,0 +1,13 @@ +package struc + +import ( + "io" + "reflect" +) + +type Packer interface { + Pack(buf []byte, val reflect.Value, options *Options) (int, error) + Unpack(r io.Reader, val reflect.Value, options *Options) error + Sizeof(val reflect.Value, options *Options) int + String() string +} diff --git a/vendor/github.com/lunixbochs/struc/parse.go b/vendor/github.com/lunixbochs/struc/parse.go new file mode 100644 index 0000000000000000000000000000000000000000..43c5875f50e4534374d4925001ead59c57e91227 --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/parse.go @@ -0,0 +1,230 @@ +package struc + +import ( + "encoding/binary" + "errors" + "fmt" + "reflect" + "regexp" + "strconv" + "strings" + "sync" +) + +// struc:"int32,big,sizeof=Data,skip,sizefrom=Len" + +type strucTag struct { + Type string + Order binary.ByteOrder + Sizeof string + Skip bool + Sizefrom string +} + +func parseStrucTag(tag reflect.StructTag) *strucTag { + t := &strucTag{ + Order: binary.BigEndian, + } + tagStr := tag.Get("struc") + if tagStr == "" { + // someone's going to typo this (I already did once) + // sorry if you made a module actually using this tag + // and you're mad at me now + tagStr = tag.Get("struct") + } + for _, s := range strings.Split(tagStr, ",") { + if strings.HasPrefix(s, "sizeof=") { + tmp := strings.SplitN(s, "=", 2) + t.Sizeof = tmp[1] + } else if strings.HasPrefix(s, "sizefrom=") { + tmp := strings.SplitN(s, "=", 2) + t.Sizefrom = tmp[1] + } else if s == "big" { + t.Order = binary.BigEndian + } else if s == "little" { + t.Order = binary.LittleEndian + } else if s == "skip" { + t.Skip = true + } else { + t.Type = s + } + } + return t +} + +var typeLenRe = regexp.MustCompile(`^\[(\d*)\]`) + +func parseField(f reflect.StructField) (fd *Field, tag *strucTag, err error) { + tag = parseStrucTag(f.Tag) + var ok bool + fd = &Field{ + Name: f.Name, + Len: 1, + Order: tag.Order, + Slice: false, + kind: f.Type.Kind(), + } + switch fd.kind { + case reflect.Array: + fd.Slice = true + fd.Array = true + fd.Len = f.Type.Len() + fd.kind = f.Type.Elem().Kind() + case reflect.Slice: + fd.Slice = true + fd.Len = -1 + fd.kind = f.Type.Elem().Kind() + case reflect.Ptr: + fd.Ptr = true + fd.kind = f.Type.Elem().Kind() + } + // check for custom types + tmp := reflect.New(f.Type) + if _, ok := tmp.Interface().(Custom); ok { + fd.Type = CustomType + return + } + var defTypeOk bool + fd.defType, defTypeOk = reflectTypeMap[fd.kind] + // find a type in the struct tag + pureType := typeLenRe.ReplaceAllLiteralString(tag.Type, "") + if fd.Type, ok = typeLookup[pureType]; ok { + fd.Len = 1 + match := typeLenRe.FindAllStringSubmatch(tag.Type, -1) + if len(match) > 0 && len(match[0]) > 1 { + fd.Slice = true + first := match[0][1] + // Field.Len = -1 indicates a []slice + if first == "" { + fd.Len = -1 + } else { + fd.Len, err = strconv.Atoi(first) + } + } + return + } + // the user didn't specify a type + switch f.Type { + case reflect.TypeOf(Size_t(0)): + fd.Type = SizeType + case reflect.TypeOf(Off_t(0)): + fd.Type = OffType + default: + if defTypeOk { + fd.Type = fd.defType + } else { + err = errors.New("struc: Could not find field type.") + } + } + return +} + +func parseFieldsLocked(v reflect.Value) (Fields, error) { + // we need to repeat this logic because parseFields() below can't be recursively called due to locking + for v.Kind() == reflect.Ptr { + v = v.Elem() + } + t := v.Type() + if v.NumField() < 1 { + return nil, errors.New("struc: Struct has no fields.") + } + sizeofMap := make(map[string][]int) + fields := make(Fields, v.NumField()) + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + f, tag, err := parseField(field) + if tag.Skip { + continue + } + if err != nil { + return nil, err + } + if !v.Field(i).CanSet() { + continue + } + f.Index = i + if tag.Sizeof != "" { + target, ok := t.FieldByName(tag.Sizeof) + if !ok { + return nil, fmt.Errorf("struc: `sizeof=%s` field does not exist", tag.Sizeof) + } + f.Sizeof = target.Index + sizeofMap[tag.Sizeof] = field.Index + } + if sizefrom, ok := sizeofMap[field.Name]; ok { + f.Sizefrom = sizefrom + } + if tag.Sizefrom != "" { + source, ok := t.FieldByName(tag.Sizefrom) + if !ok { + return nil, fmt.Errorf("struc: `sizefrom=%s` field does not exist", tag.Sizefrom) + } + f.Sizefrom = source.Index + } + if f.Len == -1 && f.Sizefrom == nil { + return nil, fmt.Errorf("struc: field `%s` is a slice with no length or sizeof field", field.Name) + } + // recurse into nested structs + // TODO: handle loops (probably by indirecting the []Field and putting pointer in cache) + if f.Type == Struct { + typ := field.Type + if f.Ptr { + typ = typ.Elem() + } + if f.Slice { + typ = typ.Elem() + } + f.Fields, err = parseFieldsLocked(reflect.New(typ)) + if err != nil { + return nil, err + } + } + fields[i] = f + } + return fields, nil +} + +var fieldCache = make(map[reflect.Type]Fields) +var fieldCacheLock sync.RWMutex +var parseLock sync.Mutex + +func fieldCacheLookup(t reflect.Type) Fields { + fieldCacheLock.RLock() + defer fieldCacheLock.RUnlock() + if cached, ok := fieldCache[t]; ok { + return cached + } + return nil +} + +func parseFields(v reflect.Value) (Fields, error) { + for v.Kind() == reflect.Ptr { + v = v.Elem() + } + t := v.Type() + + // fast path: hopefully the field parsing is already cached + if cached := fieldCacheLookup(t); cached != nil { + return cached, nil + } + + // hold a global lock so multiple goroutines can't parse (the same) fields at once + parseLock.Lock() + defer parseLock.Unlock() + + // check cache a second time, in case parseLock was just released by + // another thread who filled the cache for us + if cached := fieldCacheLookup(t); cached != nil { + return cached, nil + } + + // no luck, time to parse and fill the cache ourselves + fields, err := parseFieldsLocked(v) + if err != nil { + return nil, err + } + fieldCacheLock.Lock() + fieldCache[t] = fields + fieldCacheLock.Unlock() + return fields, nil +} diff --git a/vendor/github.com/lunixbochs/struc/struc.go b/vendor/github.com/lunixbochs/struc/struc.go new file mode 100644 index 0000000000000000000000000000000000000000..3d85fe32140ed60178a459cf4617d1290b8f30a4 --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/struc.go @@ -0,0 +1,117 @@ +package struc + +import ( + "encoding/binary" + "fmt" + "io" + "reflect" +) + +type Options struct { + ByteAlign int + PtrSize int + Order binary.ByteOrder +} + +func (o *Options) Validate() error { + if o.PtrSize == 0 { + o.PtrSize = 32 + } else { + switch o.PtrSize { + case 8, 16, 32, 64: + default: + return fmt.Errorf("Invalid Options.PtrSize: %d. Must be in (8, 16, 32, 64)", o.PtrSize) + } + } + return nil +} + +var emptyOptions = &Options{} + +func prep(data interface{}) (reflect.Value, Packer, error) { + value := reflect.ValueOf(data) + for value.Kind() == reflect.Ptr { + next := value.Elem().Kind() + if next == reflect.Struct || next == reflect.Ptr { + value = value.Elem() + } else { + break + } + } + switch value.Kind() { + case reflect.Struct: + fields, err := parseFields(value) + return value, fields, err + default: + if !value.IsValid() { + return reflect.Value{}, nil, fmt.Errorf("Invalid reflect.Value for %+v", data) + } + if c, ok := data.(Custom); ok { + return value, customFallback{c}, nil + } + return value, binaryFallback(value), nil + } +} + +func Pack(w io.Writer, data interface{}) error { + return PackWithOptions(w, data, nil) +} + +func PackWithOptions(w io.Writer, data interface{}, options *Options) error { + if options == nil { + options = emptyOptions + } + if err := options.Validate(); err != nil { + return err + } + val, packer, err := prep(data) + if err != nil { + return err + } + if val.Type().Kind() == reflect.String { + val = val.Convert(reflect.TypeOf([]byte{})) + } + size := packer.Sizeof(val, options) + buf := make([]byte, size) + if _, err := packer.Pack(buf, val, options); err != nil { + return err + } + _, err = w.Write(buf) + return err +} + +func Unpack(r io.Reader, data interface{}) error { + return UnpackWithOptions(r, data, nil) +} + +func UnpackWithOptions(r io.Reader, data interface{}, options *Options) error { + if options == nil { + options = emptyOptions + } + if err := options.Validate(); err != nil { + return err + } + val, packer, err := prep(data) + if err != nil { + return err + } + return packer.Unpack(r, val, options) +} + +func Sizeof(data interface{}) (int, error) { + return SizeofWithOptions(data, nil) +} + +func SizeofWithOptions(data interface{}, options *Options) (int, error) { + if options == nil { + options = emptyOptions + } + if err := options.Validate(); err != nil { + return 0, err + } + val, packer, err := prep(data) + if err != nil { + return 0, err + } + return packer.Sizeof(val, options), nil +} diff --git a/vendor/github.com/lunixbochs/struc/types.go b/vendor/github.com/lunixbochs/struc/types.go new file mode 100644 index 0000000000000000000000000000000000000000..6ca97f48d2e81191bcf21495cfe155d5f6995544 --- /dev/null +++ b/vendor/github.com/lunixbochs/struc/types.go @@ -0,0 +1,136 @@ +package struc + +import ( + "fmt" + "reflect" +) + +type Type int + +const ( + Invalid Type = iota + Pad + Bool + Int + Int8 + Uint8 + Int16 + Uint16 + Int32 + Uint32 + Int64 + Uint64 + Float32 + Float64 + String + Struct + Ptr + + SizeType + OffType + CustomType +) + +func (t Type) Resolve(options *Options) Type { + switch t { + case OffType: + switch options.PtrSize { + case 8: + return Int8 + case 16: + return Int16 + case 32: + return Int32 + case 64: + return Int64 + default: + panic(fmt.Sprintf("unsupported ptr bits: %d", options.PtrSize)) + } + case SizeType: + switch options.PtrSize { + case 8: + return Uint8 + case 16: + return Uint16 + case 32: + return Uint32 + case 64: + return Uint64 + default: + panic(fmt.Sprintf("unsupported ptr bits: %d", options.PtrSize)) + } + } + return t +} + +func (t Type) String() string { + return typeNames[t] +} + +func (t Type) Size() int { + switch t { + case SizeType, OffType: + panic("Size_t/Off_t types must be converted to another type using options.PtrSize") + case Pad, String, Int8, Uint8, Bool: + return 1 + case Int16, Uint16: + return 2 + case Int32, Uint32, Float32: + return 4 + case Int64, Uint64, Float64: + return 8 + default: + panic("Cannot resolve size of type:" + t.String()) + } +} + +var typeLookup = map[string]Type{ + "pad": Pad, + "bool": Bool, + "byte": Uint8, + "int8": Int8, + "uint8": Uint8, + "int16": Int16, + "uint16": Uint16, + "int32": Int32, + "uint32": Uint32, + "int64": Int64, + "uint64": Uint64, + "float32": Float32, + "float64": Float64, + + "size_t": SizeType, + "off_t": OffType, +} + +var typeNames = map[Type]string{ + CustomType: "Custom", +} + +func init() { + for name, enum := range typeLookup { + typeNames[enum] = name + } +} + +type Size_t uint64 +type Off_t int64 + +var reflectTypeMap = map[reflect.Kind]Type{ + reflect.Bool: Bool, + reflect.Int8: Int8, + reflect.Int16: Int16, + reflect.Int: Int32, + reflect.Int32: Int32, + reflect.Int64: Int64, + reflect.Uint8: Uint8, + reflect.Uint16: Uint16, + reflect.Uint: Uint32, + reflect.Uint32: Uint32, + reflect.Uint64: Uint64, + reflect.Float32: Float32, + reflect.Float64: Float64, + reflect.String: String, + reflect.Struct: Struct, + reflect.Ptr: Ptr, +} diff --git a/vendor/github.com/miscreant/miscreant/LICENSE.txt b/vendor/github.com/miscreant/miscreant/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..90ea836a674cc3a86d0085c0c3564789516d3f88 --- /dev/null +++ b/vendor/github.com/miscreant/miscreant/LICENSE.txt @@ -0,0 +1,25 @@ +Copyright (c) 2017-2018 The Miscreant Developers. The canonical list of project +contributors who hold copyright over the project can be found at: + +https://github.com/miscreant/miscreant/blob/master/AUTHORS.md + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/miscreant/miscreant/go/README.md b/vendor/github.com/miscreant/miscreant/go/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8c03caef1d6286f9cd5b4c01a420be8715b191dc --- /dev/null +++ b/vendor/github.com/miscreant/miscreant/go/README.md @@ -0,0 +1,91 @@ +# miscreant.go [![Build Status][build-shield]][build-link] [![GoDoc][godoc-shield]][godoc-link] [![Go Report Card][goreport-shield]][goreport-link] [![MIT licensed][license-shield]][license-link] [![Gitter Chat][gitter-image]][gitter-link] + +[build-shield]: https://secure.travis-ci.org/miscreant/miscreant.svg?branch=master +[build-link]: https://travis-ci.org/miscreant/miscreant +[godoc-shield]: https://godoc.org/github.com/miscreant/miscreant/go?status.svg +[godoc-link]: https://godoc.org/github.com/miscreant/miscreant/go +[goreport-shield]: https://goreportcard.com/badge/github.com/miscreant/miscreant +[goreport-link]: https://goreportcard.com/report/github.com/miscreant/miscreant +[license-shield]: https://img.shields.io/badge/license-MIT-blue.svg +[license-link]: https://github.com/miscreant/miscreant/blob/master/LICENSE.txt +[gitter-image]: https://badges.gitter.im/badge.svg +[gitter-link]: https://gitter.im/miscreant/Lobby + +> The best crypto you've never heard of, brought to you by [Phil Rogaway] + +[Phil Rogaway]: https://en.wikipedia.org/wiki/Phillip_Rogaway + +Go implementation of **Miscreant**: Advanced symmetric encryption library +which provides the [AES-SIV] ([RFC 5297]), [AES-PMAC-SIV], and [STREAM] +constructions. These algorithms are easy-to-use (or rather, hard-to-misuse) +and support encryption of individual messages or message streams. + +[AES-SIV]: https://github.com/miscreant/miscreant/wiki/AES-SIV +[RFC 5297]: https://tools.ietf.org/html/rfc5297 +[AES-PMAC-SIV]: https://github.com/miscreant/miscreant/wiki/AES-PMAC-SIV +[STREAM]: https://github.com/miscreant/miscreant/wiki/STREAM + +**AES-SIV** provides [nonce-reuse misuse-resistance] (NRMR): accidentally +reusing a nonce with this construction is not a security catastrophe, +unlike it is with more popular AES encryption modes like [AES-GCM]. +With **AES-SIV**, the worst outcome of reusing a nonce is an attacker +can see you've sent the same plaintext twice, as opposed to almost all other +AES modes where it can facilitate [chosen ciphertext attacks] and/or +full plaintext recovery. + +For more information, see the [toplevel README.md]. + +[nonce-reuse misuse-resistance]: https://github.com/miscreant/miscreant/wiki/Nonce-Reuse-Misuse-Resistance +[AES-GCM]: https://en.wikipedia.org/wiki/Galois/Counter_Mode +[chosen ciphertext attacks]: https://en.wikipedia.org/wiki/Chosen-ciphertext_attack +[toplevel README.md]: https://github.com/miscreant/miscreant/blob/master/README.md + +## Help and Discussion + +Have questions? Want to suggest a feature or change? + +* [Gitter]: web-based chat about miscreant projects including **miscreant.go** +* [Google Group]: join via web or email ([miscreant-crypto+subscribe@googlegroups.com]) + +[Gitter]: https://gitter.im/miscreant/Lobby +[Google Group]: https://groups.google.com/forum/#!forum/miscreant-crypto +[miscreant-crypto+subscribe@googlegroups.com]: mailto:miscreant-crypto+subscribe@googlegroups.com?subject=subscribe + +## Documentation + +[Please see the Miscreant Wiki](https://github.com/miscreant/miscreant/wiki/Go-Documentation) +for API documentation. + +[godoc][godoc-link] documentation is also available. + +## Security Notice + +Though this library is written by cryptographic professionals, it has not +undergone a thorough security audit, and cryptographic professionals are still +humans that make mistakes. + +This library makes an effort to use constant time operations throughout its +implementation, however actual constant time behavior has not been verified. + +Use this library at your own risk. + +## Code of Conduct + +We abide by the [Contributor Covenant][cc] and ask that you do as well. + +For more information, please see [CODE_OF_CONDUCT.md]. + +[cc]: https://contributor-covenant.org +[CODE_OF_CONDUCT.md]: https://github.com/miscreant/miscreant/blob/master/CODE_OF_CONDUCT.md + +## Contributing + +Bug reports and pull requests are welcome on GitHub at https://github.com/miscreant/miscreant + +## Copyright + +Copyright (c) 2017-2018 [The Miscreant Developers][AUTHORS]. +See [LICENSE.txt] for further details. + +[AUTHORS]: https://github.com/miscreant/miscreant/blob/master/AUTHORS.md +[LICENSE.txt]: https://github.com/miscreant/miscreant/blob/master/LICENSE.txt diff --git a/vendor/github.com/miscreant/miscreant/go/aead.go b/vendor/github.com/miscreant/miscreant/go/aead.go new file mode 100644 index 0000000000000000000000000000000000000000..269af387073f148729a6f10c26329b23bff18682 --- /dev/null +++ b/vendor/github.com/miscreant/miscreant/go/aead.go @@ -0,0 +1,108 @@ +// Written in 2015 by Dmitry Chestnykh. + +package miscreant + +import ( + "crypto/cipher" + "crypto/rand" + "io" +) + +// Minimum nonce size for which we'll allow the generation of random nonces +const minimumRandomNonceSize = 16 + +// aead is a wrapper for Cipher implementing cipher.AEAD interface. +type aead struct { + // miscreant.Cipher instance underlying this AEAD + c *Cipher + + // Size of the nonce required + nonceSize int +} + +// GenerateKey generates a random 32-byte or 64-byte encryption key. +// Panics if the key size is unsupported or source of randomness fails. +func GenerateKey(length int) []byte { + if length != 32 && length != 64 { + panic("miscreant.GenerateKey: invalid key size: " + string(length)) + } + + key := make([]byte, length) + _, err := io.ReadFull(rand.Reader, key[:]) + if err != nil { + panic(err) + } + + return key +} + +// GenerateNonce generates a random nonce for the given `cipher.AEAD`. +// Panics if the configured nonce size is less than 16-bytes (128-bits) +func GenerateNonce(c cipher.AEAD) []byte { + if c.NonceSize() < minimumRandomNonceSize { + panic("miscreant.GenerateNonce: nonce size is too small: " + string(c.NonceSize())) + } + + nonce := make([]byte, c.NonceSize()) + _, err := io.ReadFull(rand.Reader, nonce[:]) + if err != nil { + panic(err) + } + + return nonce +} + +// NewAEAD returns an AES-SIV instance implementing cipher.AEAD interface, +// with the given cipher, nonce size, and a key which must be twice as long +// as an AES key, either 32 or 64 bytes to select AES-128 (AES-SIV-256) +// or AES-256 (AES-SIV-512). +// +// Unless the given nonce size is less than zero, Seal and Open will panic when +// passed nonce of a different size. +func NewAEAD(alg string, key []byte, nonceSize int) (cipher.AEAD, error) { + switch alg { + case "AES-SIV", "AES-CMAC-SIV": + c, err := NewAESCMACSIV(key) + if err != nil { + return nil, err + } + return &aead{c: c, nonceSize: nonceSize}, nil + case "AES-PMAC-SIV": + c, err := NewAESPMACSIV(key) + if err != nil { + return nil, err + } + return &aead{c: c, nonceSize: nonceSize}, nil + default: + panic("NewAEAD: unknown cipher: " + alg) + } +} + +func (a *aead) NonceSize() int { return a.nonceSize } +func (a *aead) Overhead() int { return a.c.Overhead() } + +func (a *aead) Seal(dst, nonce, plaintext, data []byte) (out []byte) { + if len(nonce) != a.nonceSize && a.nonceSize >= 0 { + panic("miscreant.AEAD: incorrect nonce length") + } + var err error + if data == nil { + out, err = a.c.Seal(dst, plaintext, nonce) + } else { + out, err = a.c.Seal(dst, plaintext, data, nonce) + } + if err != nil { + panic("miscreant.AEAD: " + err.Error()) + } + return out +} + +func (a *aead) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + if len(nonce) != a.nonceSize && a.nonceSize >= 0 { + panic("miscreant.AEAD: incorrect nonce length") + } + if data == nil { + return a.c.Open(dst, ciphertext, nonce) + } + return a.c.Open(dst, ciphertext, data, nonce) +} diff --git a/vendor/github.com/miscreant/miscreant/go/block/block.go b/vendor/github.com/miscreant/miscreant/go/block/block.go new file mode 100644 index 0000000000000000000000000000000000000000..9c16ed8191b9dc79a0123ebb5939ed70a581e2c1 --- /dev/null +++ b/vendor/github.com/miscreant/miscreant/go/block/block.go @@ -0,0 +1,49 @@ +// Common block cipher functionality shared across this library + +package block + +import ( + "crypto/cipher" + "crypto/subtle" +) + +const ( + // Size of an AES block in bytes + Size = 16 + + // R is the minimal irreducible polynomial for a 128-bit block size + R = 0x87 +) + +// Block is a 128-bit array used by certain block ciphers (i.e. AES) +type Block [Size]byte + +// Clear zeroes out the contents of the block +func (b *Block) Clear() { + // TODO: use a more secure zeroing method that won't be optimized away + for i := range b { + b[i] = 0 + } +} + +// Dbl performs a doubling of a block over GF(2^128): +// +// a<<1 if firstbit(a)=0 +// (a<<1) ⊕ 0¹²⁰10000111 if firstbit(a)=1 +// +func (b *Block) Dbl() { + var z byte + + for i := Size - 1; i >= 0; i-- { + zz := b[i] >> 7 + b[i] = b[i]<<1 | z + z = zz + } + + b[Size-1] ^= byte(subtle.ConstantTimeSelect(int(z), R, 0)) +} + +// Encrypt a block with the given block cipher +func (b *Block) Encrypt(c cipher.Block) { + c.Encrypt(b[:], b[:]) +} diff --git a/vendor/github.com/miscreant/miscreant/go/ci.sh b/vendor/github.com/miscreant/miscreant/go/ci.sh new file mode 100755 index 0000000000000000000000000000000000000000..05504c3e81426f8c593ffda66974fed3edd9f9f0 --- /dev/null +++ b/vendor/github.com/miscreant/miscreant/go/ci.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +go get -u github.com/golang/lint/golint +go get -u github.com/kisielk/errcheck +go vet ./... +go test -v ./... +golint -set_exit_status ./... +errcheck ./... \ No newline at end of file diff --git a/vendor/github.com/miscreant/miscreant/go/cmac/cmac.go b/vendor/github.com/miscreant/miscreant/go/cmac/cmac.go new file mode 100644 index 0000000000000000000000000000000000000000..acb92441e658c5fec5d1b6ed4148f36b850bc5f3 --- /dev/null +++ b/vendor/github.com/miscreant/miscreant/go/cmac/cmac.go @@ -0,0 +1,114 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// CMAC message authentication code, defined in +// NIST Special Publication SP 800-38B. + +package cmac + +import ( + "crypto/cipher" + "hash" + + "github.com/miscreant/miscreant/go/block" +) + +type cmac struct { + // c is the block cipher we're using (i.e. AES-128 or AES-256) + c cipher.Block + + // k1 and k2 are CMAC subkeys (for finishing the tag) + k1, k2 block.Block + + // digest contains the PMAC tag-in-progress + digest block.Block + + // buffer contains a part of the input message, processed a block-at-a-time + buf block.Block + + // pos marks the end of plaintext in the buffer + pos uint +} + +// New returns a new instance of a CMAC message authentication code +// digest using the given cipher.Block. +func New(c cipher.Block) hash.Hash { + if c.BlockSize() != block.Size { + panic("pmac: invalid cipher block size") + } + + d := new(cmac) + d.c = c + + // Subkey generation, p. 7 + d.k1.Encrypt(c) + d.k1.Dbl() + + copy(d.k2[:], d.k1[:]) + d.k2.Dbl() + + return d +} + +// Reset clears the digest state, starting a new digest. +func (d *cmac) Reset() { + d.digest.Clear() + d.buf.Clear() + d.pos = 0 +} + +// Write adds the given data to the digest state. +func (d *cmac) Write(p []byte) (nn int, err error) { + nn = len(p) + left := block.Size - d.pos + + if uint(len(p)) > left { + xor(d.buf[d.pos:], p[:left]) + p = p[left:] + d.buf.Encrypt(d.c) + d.pos = 0 + } + + for uint(len(p)) > block.Size { + xor(d.buf[:], p[:block.Size]) + p = p[block.Size:] + d.buf.Encrypt(d.c) + } + + if len(p) > 0 { + xor(d.buf[d.pos:], p) + d.pos += uint(len(p)) + } + return +} + +// Sum returns the CMAC digest, one cipher block in length, +// of the data written with Write. +func (d *cmac) Sum(in []byte) []byte { + // Finish last block, mix in key, encrypt. + // Don't edit ci, in case caller wants + // to keep digesting after call to Sum. + k := d.k1 + if d.pos < uint(len(d.digest)) { + k = d.k2 + } + for i := 0; i < len(d.buf); i++ { + d.digest[i] = d.buf[i] ^ k[i] + } + if d.pos < uint(len(d.digest)) { + d.digest[d.pos] ^= 0x80 + } + d.digest.Encrypt(d.c) + return append(in, d.digest[:]...) +} + +func (d *cmac) Size() int { return len(d.digest) } + +func (d *cmac) BlockSize() int { return d.c.BlockSize() } + +func xor(a, b []byte) { + for i, v := range b { + a[i] ^= v + } +} diff --git a/vendor/github.com/miscreant/miscreant/go/pmac/pmac.go b/vendor/github.com/miscreant/miscreant/go/pmac/pmac.go new file mode 100644 index 0000000000000000000000000000000000000000..65a74343ca54004dc3ab4c557a6482d7bc4ec063 --- /dev/null +++ b/vendor/github.com/miscreant/miscreant/go/pmac/pmac.go @@ -0,0 +1,201 @@ +// PMAC message authentication code, defined in +// http://web.cs.ucdavis.edu/~rogaway/ocb/pmac.pdf + +package pmac + +import ( + "crypto/cipher" + "crypto/subtle" + "hash" + "math/bits" + + "github.com/miscreant/miscreant/go/block" +) + +// Number of L blocks to precompute (i.e. µ in the PMAC paper) +// TODO: dynamically compute these as needed +const precomputedBlocks = 31 + +type pmac struct { + // c is the block cipher we're using (i.e. AES-128 or AES-256) + c cipher.Block + + // l is defined as follows (quoted from the PMAC paper): + // + // Equation 1: + // + // a · x = + // a<<1 if firstbit(a)=0 + // (a<<1) ⊕ 0¹²⁰10000111 if firstbit(a)=1 + // + // Equation 2: + // + // a · x⁻¹ = + // a>>1 if lastbit(a)=0 + // (a>>1) ⊕ 10¹²⁰1000011 if lastbit(a)=1 + // + // Let L(0) ← L. For i ∈ [1..µ], compute L(i) ← L(i − 1) · x by + // Equation (1) using a shift and a conditional xor. + // + // Compute L(−1) ← L · x⁻¹ by Equation (2), using a shift and a + // conditional xor. + // + // Save the values L(−1), L(0), L(1), L(2), ..., L(µ) in a table. + // (Alternatively, [ed: as we have done in this codebase] defer computing + // some or all of these L(i) values until the value is actually needed.) + l [precomputedBlocks]block.Block + + // lInv contains the multiplicative inverse (i.e. right shift) of the first + // l-value, computed as described above, and is XORed into the tag in the + // event the message length is a multiple of the block size + lInv block.Block + + // digest contains the PMAC tag-in-progress + digest block.Block + + // offset is a block specific tweak to the input message + offset block.Block + + // buf contains a part of the input message, processed a block-at-a-time + buf block.Block + + // pos marks the end of plaintext in the buf + pos uint + + // ctr is the number of blocks we have MAC'd so far + ctr uint + + // finished is set true when we are done processing a message, and forbids + // any subsequent writes until we reset the internal state + finished bool +} + +// New creates a new PMAC instance using the given cipher +func New(c cipher.Block) hash.Hash { + if c.BlockSize() != block.Size { + panic("pmac: invalid cipher block size") + } + + d := new(pmac) + d.c = c + + var tmp block.Block + tmp.Encrypt(c) + + for i := range d.l { + copy(d.l[i][:], tmp[:]) + tmp.Dbl() + } + + // Compute L(−1) ← L · x⁻¹: + // + // a>>1 if lastbit(a)=0 + // (a>>1) ⊕ 10¹²⁰1000011 if lastbit(a)=1 + // + copy(tmp[:], d.l[0][:]) + lastBit := int(tmp[block.Size-1] & 0x01) + + for i := block.Size - 1; i > 0; i-- { + carry := byte(subtle.ConstantTimeSelect(int(tmp[i-1]&1), 0x80, 0)) + tmp[i] = (tmp[i] >> 1) | carry + } + + tmp[0] >>= 1 + tmp[0] ^= byte(subtle.ConstantTimeSelect(lastBit, 0x80, 0)) + tmp[block.Size-1] ^= byte(subtle.ConstantTimeSelect(lastBit, block.R>>1, 0)) + copy(d.lInv[:], tmp[:]) + + return d +} + +// Reset clears the digest state, starting a new digest. +func (d *pmac) Reset() { + d.digest.Clear() + d.offset.Clear() + d.buf.Clear() + d.pos = 0 + d.ctr = 0 + d.finished = false +} + +// Write adds the given data to the digest state. +func (d *pmac) Write(msg []byte) (int, error) { + if d.finished { + panic("pmac: already finished") + } + + var msgPos, msgLen, remaining uint + msgLen = uint(len(msg)) + remaining = block.Size - d.pos + + // Finish filling the internal buf with the message + if msgLen > remaining { + copy(d.buf[d.pos:], msg[:remaining]) + + msgPos += remaining + msgLen -= remaining + + d.processBuffer() + } + + // So long as we have more than a blocks worth of data, compute + // whole-sized blocks at a time. + for msgLen > block.Size { + copy(d.buf[:], msg[msgPos:msgPos+block.Size]) + + msgPos += block.Size + msgLen -= block.Size + + d.processBuffer() + } + + if msgLen > 0 { + copy(d.buf[d.pos:d.pos+msgLen], msg[msgPos:]) + d.pos += msgLen + } + + return len(msg), nil +} + +// Sum returns the PMAC digest, one cipher block in length, +// of the data written with Write. +func (d *pmac) Sum(in []byte) []byte { + if d.finished { + panic("pmac: already finished") + } + + if d.pos == block.Size { + xor(d.digest[:], d.buf[:]) + xor(d.digest[:], d.lInv[:]) + } else { + xor(d.digest[:], d.buf[:d.pos]) + d.digest[d.pos] ^= 0x80 + } + + d.digest.Encrypt(d.c) + d.finished = true + + return append(in, d.digest[:]...) +} + +func (d *pmac) Size() int { return block.Size } + +func (d *pmac) BlockSize() int { return block.Size } + +// Update the internal tag state based on the buf contents +func (d *pmac) processBuffer() { + xor(d.offset[:], d.l[bits.TrailingZeros(d.ctr+1)][:]) + xor(d.buf[:], d.offset[:]) + d.ctr++ + + d.buf.Encrypt(d.c) + xor(d.digest[:], d.buf[:]) + d.pos = 0 +} + +// XOR the contents of b into a in-place +func xor(a, b []byte) { + for i, v := range b { + a[i] ^= v + } +} diff --git a/vendor/github.com/miscreant/miscreant/go/siv.go b/vendor/github.com/miscreant/miscreant/go/siv.go new file mode 100644 index 0000000000000000000000000000000000000000..9acff2992b4692fe64f9eba5d8c373afad637211 --- /dev/null +++ b/vendor/github.com/miscreant/miscreant/go/siv.go @@ -0,0 +1,243 @@ +// Originally written in 2015 by Dmitry Chestnykh. +// Modified in 2017 by Tony Arcieri. +// +// Miscreant implements Synthetic Initialization Vector (SIV)-based +// authenticated encryption using the AES block cipher (RFC 5297). + +package miscreant + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/subtle" + "errors" + "github.com/miscreant/miscreant/go/block" + "github.com/miscreant/miscreant/go/cmac" + "github.com/miscreant/miscreant/go/pmac" + "hash" +) + +// MaxAssociatedDataItems is the maximum number of associated data items +const MaxAssociatedDataItems = 126 + +var ( + // ErrKeySize indicates the given key size is not supported + ErrKeySize = errors.New("siv: bad key size") + + // ErrNotAuthentic indicates a ciphertext is malformed or corrupt + ErrNotAuthentic = errors.New("siv: authentication failed") + + // ErrTooManyAssociatedDataItems indicates more than MaxAssociatedDataItems were given + ErrTooManyAssociatedDataItems = errors.New("siv: too many associated data items") +) + +// Cipher is an instance of AES-SIV, configured with either AES-CMAC or +// AES-PMAC as a message authentication code. +type Cipher struct { + // MAC function used to derive a synthetic IV and authenticate the message + h hash.Hash + + // Block cipher function used to encrypt the message + b cipher.Block + + // Internal buffers + tmp1, tmp2 block.Block +} + +// NewAESCMACSIV returns a new AES-SIV cipher with the given key, which must be +// twice as long as an AES key, either 32 or 64 bytes to select AES-128 +// (AES-CMAC-SIV-256), or AES-256 (AES-CMAC-SIV-512). +func NewAESCMACSIV(key []byte) (c *Cipher, err error) { + n := len(key) + if n != 32 && n != 64 { + return nil, ErrKeySize + } + + macBlock, err := aes.NewCipher(key[:n/2]) + if err != nil { + return nil, err + } + + ctrBlock, err := aes.NewCipher(key[n/2:]) + if err != nil { + return nil, err + } + + c = new(Cipher) + c.h = cmac.New(macBlock) + c.b = ctrBlock + + return c, nil +} + +// NewAESPMACSIV returns a new AES-SIV cipher with the given key, which must be +// twice as long as an AES key, either 32 or 64 bytes to select AES-128 +// (AES-PMAC-SIV-256), or AES-256 (AES-PMAC-SIV-512). +func NewAESPMACSIV(key []byte) (c *Cipher, err error) { + n := len(key) + if n != 32 && n != 64 { + return nil, ErrKeySize + } + + macBlock, err := aes.NewCipher(key[:n/2]) + if err != nil { + return nil, err + } + + ctrBlock, err := aes.NewCipher(key[n/2:]) + if err != nil { + return nil, err + } + + c = new(Cipher) + c.h = pmac.New(macBlock) + c.b = ctrBlock + + return c, nil +} + +// Overhead returns the difference between plaintext and ciphertext lengths. +func (c *Cipher) Overhead() int { + return c.h.Size() +} + +// Seal encrypts and authenticates plaintext, authenticates the given +// associated data items, and appends the result to dst, returning the updated +// slice. +// +// The plaintext and dst may alias exactly or not at all. +// +// For nonce-based encryption, the nonce should be the last associated data item. +func (c *Cipher) Seal(dst []byte, plaintext []byte, data ...[]byte) ([]byte, error) { + if len(data) > MaxAssociatedDataItems { + return nil, ErrTooManyAssociatedDataItems + } + + // Authenticate + iv := c.s2v(data, plaintext) + ret, out := sliceForAppend(dst, len(iv)+len(plaintext)) + copy(out, iv) + + // Encrypt + zeroIVBits(iv) + ctr := cipher.NewCTR(c.b, iv) + ctr.XORKeyStream(out[len(iv):], plaintext) + + return ret, nil +} + +// Open decrypts ciphertext, authenticates the decrypted plaintext and the given +// associated data items and, if successful, appends the resulting plaintext +// to dst, returning the updated slice. The additional data items must match the +// items passed to Seal. +// +// The ciphertext and dst may alias exactly or not at all. +// +// For nonce-based encryption, the nonce should be the last associated data item. +func (c *Cipher) Open(dst []byte, ciphertext []byte, data ...[]byte) ([]byte, error) { + if len(data) > MaxAssociatedDataItems { + return nil, ErrTooManyAssociatedDataItems + } + if len(ciphertext) < c.Overhead() { + return nil, ErrNotAuthentic + } + + // Decrypt + iv := c.tmp1[:c.Overhead()] + copy(iv, ciphertext) + zeroIVBits(iv) + ctr := cipher.NewCTR(c.b, iv) + ret, out := sliceForAppend(dst, len(ciphertext)-len(iv)) + ctr.XORKeyStream(out, ciphertext[len(iv):]) + + // Authenticate + expected := c.s2v(data, out) + if subtle.ConstantTimeCompare(ciphertext[:len(iv)], expected) != 1 { + return nil, ErrNotAuthentic + } + return ret, nil +} + +func (c *Cipher) s2v(s [][]byte, sn []byte) []byte { + h := c.h + h.Reset() + + tmp, d := c.tmp1, c.tmp2 + tmp.Clear() + + // NOTE(dchest): The standalone S2V returns CMAC(1) if the number of + // passed vectors is zero, however in SIV construction this case is + // never triggered, since we always pass plaintext as the last vector + // (even if it's zero-length), so we omit this case. + + _, err := h.Write(tmp[:]) + if err != nil { + panic(err) + } + + copy(d[:], h.Sum(d[:0])) + h.Reset() + + for _, v := range s { + _, err := h.Write(v) + if err != nil { + panic(err) + } + + copy(tmp[:], h.Sum(tmp[:0])) + h.Reset() + d.Dbl() + xor(d[:], tmp[:]) + } + + tmp.Clear() + + if len(sn) >= h.BlockSize() { + n := len(sn) - len(d) + copy(tmp[:], sn[n:]) + _, err = h.Write(sn[:n]) + if err != nil { + panic(err) + } + } else { + copy(tmp[:], sn) + tmp[len(sn)] = 0x80 + d.Dbl() + } + xor(tmp[:], d[:]) + _, err = h.Write(tmp[:]) + if err != nil { + panic(err) + } + + return h.Sum(tmp[:0]) +} + +func xor(a, b []byte) { + for i, v := range b { + a[i] ^= v + } +} + +func zeroIVBits(iv []byte) { + // "We zero-out the top bit in each of the last two 32-bit words + // of the IV before assigning it to Ctr" + // — http://web.cs.ucdavis.edu/~rogaway/papers/siv.pdf + iv[len(iv)-8] &= 0x7f + iv[len(iv)-4] &= 0x7f +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} diff --git a/vendor/github.com/miscreant/miscreant/go/stream.go b/vendor/github.com/miscreant/miscreant/go/stream.go new file mode 100644 index 0000000000000000000000000000000000000000..bd2f51d14812dd94e9544b07fb14f991565e6ed5 --- /dev/null +++ b/vendor/github.com/miscreant/miscreant/go/stream.go @@ -0,0 +1,173 @@ +package miscreant + +import ( + "crypto/cipher" + "encoding/binary" +) + +// streamNoncePrefixSize is the user-supplied nonce size +const streamNoncePrefixSize = 8 + +// streamExtendedNonceSize is the nonce prefix + 32-bit counter + 1-byte last block flag +const streamExtendedNonceSize = streamNoncePrefixSize + 4 + 1 + +// lastBlockFlag indicates that a block is the last in the STREAM +const lastBlockFlag byte = 1 + +// counterMax is the maximum allowable value for the stream counter +const counterMax uint64 = 0xFFFFFFFF + +// StreamEncryptor encrypts message streams, selecting the nonces using a +// 32-bit counter, generalized for any cipher.AEAD algorithm +// +// This construction corresponds to the ℰ stream encryptor object as defined in +// the paper Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance +type StreamEncryptor struct { + // cipher.AEAD instance underlying this STREAM + a cipher.AEAD + + // Nonce encoder instance which computes per-message nonces + n *nonceEncoder32 +} + +// NewStreamEncryptor returns a STREAM encryptor instance with the given +// cipher, nonce, and a key which must be twice as long as an AES key, either +// 32 or 64 bytes to select AES-128 (AES-SIV-256) or AES-256 (AES-SIV-512). +func NewStreamEncryptor(alg string, key, nonce []byte) (*StreamEncryptor, error) { + aead, err := NewAEAD(alg, key, streamExtendedNonceSize) + if err != nil { + return nil, err + } + + nonceEncoder, err := newNonceEncoder32(nonce) + if err != nil { + return nil, err + } + + return &StreamEncryptor{a: aead, n: nonceEncoder}, nil +} + +// NonceSize returns the size of the nonce that must be passed to +// NewStreamEncryptor +func (e *StreamEncryptor) NonceSize() int { return streamNoncePrefixSize } + +// Overhead returns the maximum difference between the lengths of a +// plaintext and its ciphertext, which in the case of AES-SIV modes +// is the size of the initialization vector +func (e *StreamEncryptor) Overhead() int { return e.a.Overhead() } + +// Seal the next message in the STREAM, which encrypts and authenticates +// plaintext, authenticates the additional data and appends the result to dst, +// returning the updated slice. +// +// The plaintext and dst may alias exactly or not at all. To reuse +// plaintext's storage for the encrypted output, use plaintext[:0] as dst. +// +// The lastBlock argument should be set to true if this is the last message +// in the STREAM. No further messages can be encrypted after the last one +func (e *StreamEncryptor) Seal(dst, plaintext, aData []byte, lastBlock bool) []byte { + return e.a.Seal(dst, e.n.Next(lastBlock), plaintext, aData) +} + +// StreamDecryptor decrypts message streams, selecting the nonces using a +// 32-bit counter, generalized for any cipher.AEAD algorithm +// +// This construction corresponds to the ℰ stream encryptor object as defined in +// the paper Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance +type StreamDecryptor struct { + // cipher.AEAD instance underlying this STREAM + a cipher.AEAD + + // Nonce encoder instance which computes per-message nonces + n *nonceEncoder32 +} + +// NewStreamDecryptor returns a STREAM encryptor instance with the given +// cipher, nonce, and a key which must be twice as long as an AES key, either +// 32 or 64 bytes to select AES-128 (AES-SIV-256) or AES-256 (AES-SIV-512). +func NewStreamDecryptor(alg string, key, nonce []byte) (*StreamDecryptor, error) { + aead, err := NewAEAD(alg, key, streamExtendedNonceSize) + if err != nil { + return nil, err + + } + + nonceEncoder, err := newNonceEncoder32(nonce) + if err != nil { + return nil, err + } + + return &StreamDecryptor{a: aead, n: nonceEncoder}, nil +} + +// NonceSize returns the size of the nonce that must be passed to +// NewStreamDecryptor +func (d *StreamDecryptor) NonceSize() int { return streamNoncePrefixSize } + +// Overhead returns the maximum difference between the lengths of a +// plaintext and its ciphertext, which in the case of AES-SIV modes +// is the size of the initialization vector +func (d *StreamDecryptor) Overhead() int { return d.a.Overhead() } + +// Open decrypts and authenticates the next ciphertext in the STREAM, +// and also authenticates the additional data, ensuring it matches +// the value passed to Seal. +// +// If successful, it appends the resulting plaintext to dst and returns +// the updated slice. +// +// The ciphertext and dst may alias exactly or not at all. To reuse +// ciphertext's storage for the decrypted output, use ciphertext[:0] as dst. +// +// Even if the function fails, the contents of dst, up to its capacity, +// may be overwritten. +func (d *StreamDecryptor) Open(dst, ciphertext, aData []byte, lastBlock bool) ([]byte, error) { + return d.a.Open(dst, d.n.Next(lastBlock), ciphertext, aData) +} + +// Computes STREAM nonces based on the current position in the STREAM. +// +// Accepts a 64-bit nonce and uses a 32-bit counter internally. +// +// Panics if the nonce size is incorrect, or the 32-bit counter overflows +type nonceEncoder32 struct { + value [streamExtendedNonceSize]byte + counter uint64 + finished bool +} + +func newNonceEncoder32(noncePrefix []byte) (*nonceEncoder32, error) { + if len(noncePrefix) != streamNoncePrefixSize { + panic("miscreant.STREAM: incorrect nonce length") + } + + value := [streamExtendedNonceSize]byte{0} + copy(value[:streamNoncePrefixSize], noncePrefix) + + return &nonceEncoder32{ + value: value, + counter: 0, + finished: false, + }, nil +} + +func (n *nonceEncoder32) Next(lastBlock bool) []byte { + if n.finished { + panic("miscreant.STREAM: already finished") + } + + counterSlice := n.value[streamNoncePrefixSize : streamNoncePrefixSize+4] + binary.BigEndian.PutUint32(counterSlice, uint32(n.counter)) + + if lastBlock { + n.value[len(n.value)-1] = lastBlockFlag + n.finished = true + } else { + n.counter++ + if n.counter > counterMax { + panic("miscreant.STREAM: nonce counter overflowed") + } + } + + return n.value[:] +} diff --git a/vendor/github.com/pquerna/otp/otp.go b/vendor/github.com/pquerna/otp/otp.go index 5db93029cee1a6a1676c54c59ca5acdef634bbba..88d0da1d42c28ad4f0e6db7381cc6fe29f3710f2 100644 --- a/vendor/github.com/pquerna/otp/otp.go +++ b/vendor/github.com/pquerna/otp/otp.go @@ -138,11 +138,6 @@ func (k *Key) Secret() string { return q.Get("secret") } -// URL returns the OTP URL as a string -func (k *Key) URL() string { - return k.url.String() -} - // Algorithm represents the hashing function to use in the HMAC // operation needed for OTPs. type Algorithm int diff --git a/vendor/golang.org/x/crypto/argon2/argon2.go b/vendor/golang.org/x/crypto/argon2/argon2.go index 61216e83178983274e20057f9c67e6dd7b1936c1..b423feaea9f2e8fac5eead2a2d74d494ee07f2d6 100644 --- a/vendor/golang.org/x/crypto/argon2/argon2.go +++ b/vendor/golang.org/x/crypto/argon2/argon2.go @@ -5,7 +5,35 @@ // Package argon2 implements the key derivation function Argon2. // Argon2 was selected as the winner of the Password Hashing Competition and can // be used to derive cryptographic keys from passwords. -// Argon2 is specfifed at https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +// +// For a detailed specification of Argon2 see [1]. +// +// If you aren't sure which function you need, use Argon2id (IDKey) and +// the parameter recommendations for your scenario. +// +// +// Argon2i +// +// Argon2i (implemented by Key) is the side-channel resistant version of Argon2. +// It uses data-independent memory access, which is preferred for password +// hashing and password-based key derivation. Argon2i requires more passes over +// memory than Argon2id to protect from trade-off attacks. The recommended +// parameters (taken from [2]) for non-interactive operations are time=3 and to +// use the maximum available memory. +// +// +// Argon2id +// +// Argon2id (implemented by IDKey) is a hybrid version of Argon2 combining +// Argon2i and Argon2d. It uses data-independent memory access for the first +// half of the first iteration over the memory and data-dependent memory access +// for the rest. Argon2id is side-channel resistant and provides better brute- +// force cost savings due to time-memory tradeoffs than Argon2i. The recommended +// parameters for non-interactive operations (taken from [2]) are time=1 and to +// use the maximum available memory. +// +// [1] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +// [2] https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03#section-9.3 package argon2 import ( @@ -25,46 +53,79 @@ const ( ) // Key derives a key from the password, salt, and cost parameters using Argon2i -// returning a byte slice of length keyLen that can be used as cryptographic key. -// The CPU cost and parallism degree must be greater than zero. -// -// For example, you can get a derived key for e.g. AES-256 (which needs a 32-byte key) by doing: -// `key := argon2.Key([]byte("some password"), salt, 4, 32*1024, 4, 32)` -// -// The recommended parameters for interactive logins as of 2017 are time=4, memory=32*1024. -// The number of threads can be adjusted to the numbers of available CPUs. -// The time parameter specifies the number of passes over the memory and the memory -// parameter specifies the size of the memory in KiB. For example memory=32*1024 sets the -// memory cost to ~32 MB. -// The cost parameters should be increased as memory latency and CPU parallelism increases. -// Remember to get a good random salt. +// returning a byte slice of length keyLen that can be used as cryptographic +// key. The CPU cost and parallelism degree must be greater than zero. +// +// For example, you can get a derived key for e.g. AES-256 (which needs a +// 32-byte key) by doing: +// +// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32) +// +// The draft RFC recommends[2] time=3, and memory=32*1024 is a sensible number. +// If using that amount of memory (32 MB) is not possible in some contexts then +// the time parameter can be increased to compensate. +// +// The time parameter specifies the number of passes over the memory and the +// memory parameter specifies the size of the memory in KiB. For example +// memory=32*1024 sets the memory cost to ~32 MB. The number of threads can be +// adjusted to the number of available CPUs. The cost parameters should be +// increased as memory latency and CPU parallelism increases. Remember to get a +// good random salt. func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen) } +// IDKey derives a key from the password, salt, and cost parameters using +// Argon2id returning a byte slice of length keyLen that can be used as +// cryptographic key. The CPU cost and parallelism degree must be greater than +// zero. +// +// For example, you can get a derived key for e.g. AES-256 (which needs a +// 32-byte key) by doing: +// +// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32) +// +// The draft RFC recommends[2] time=1, and memory=64*1024 is a sensible number. +// If using that amount of memory (64 MB) is not possible in some contexts then +// the time parameter can be increased to compensate. +// +// The time parameter specifies the number of passes over the memory and the +// memory parameter specifies the size of the memory in KiB. For example +// memory=64*1024 sets the memory cost to ~64 MB. The number of threads can be +// adjusted to the numbers of available CPUs. The cost parameters should be +// increased as memory latency and CPU parallelism increases. Remember to get a +// good random salt. +func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { + return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen) +} + func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { if time < 1 { panic("argon2: number of rounds too small") } if threads < 1 { - panic("argon2: paralisim degree too low") + panic("argon2: parallelism degree too low") } - mem := memory / (4 * uint32(threads)) * (4 * uint32(threads)) - if mem < 8*uint32(threads) { - mem = 8 * uint32(threads) + h0 := initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode) + + memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads)) + if memory < 2*syncPoints*uint32(threads) { + memory = 2 * syncPoints * uint32(threads) } - B := initBlocks(password, salt, secret, data, time, mem, uint32(threads), keyLen, mode) - processBlocks(B, time, mem, uint32(threads), mode) - return extractKey(B, mem, uint32(threads), keyLen) + B := initBlocks(&h0, memory, uint32(threads)) + processBlocks(B, time, memory, uint32(threads), mode) + return extractKey(B, memory, uint32(threads), keyLen) } -const blockLength = 128 +const ( + blockLength = 128 + syncPoints = 4 +) type block [blockLength]uint64 -func initBlocks(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) []block { +func initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte { var ( - block0 [1024]byte h0 [blake2b.Size + 8]byte params [24]byte tmp [4]byte @@ -91,7 +152,11 @@ func initBlocks(password, salt, key, data []byte, time, memory, threads, keyLen b2.Write(tmp[:]) b2.Write(data) b2.Sum(h0[:0]) + return h0 +} +func initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block { + var block0 [1024]byte B := make([]block, memory) for lane := uint32(0); lane < threads; lane++ { j := lane * (memory / threads) @@ -99,13 +164,13 @@ func initBlocks(password, salt, key, data []byte, time, memory, threads, keyLen binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0) blake2bHash(block0[:], h0[:]) - for i := range B[0] { + for i := range B[j+0] { B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:]) } binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1) blake2bHash(block0[:], h0[:]) - for i := range B[0] { + for i := range B[j+1] { B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:]) } } @@ -113,7 +178,6 @@ func initBlocks(password, salt, key, data []byte, time, memory, threads, keyLen } func processBlocks(B []block, time, memory, threads uint32, mode int) { - const syncPoints = 4 lanes := memory / threads segments := lanes / syncPoints @@ -131,7 +195,7 @@ func processBlocks(B []block, time, memory, threads uint32, mode int) { index := uint32(0) if n == 0 && slice == 0 { index = 2 // we have already generated the first two blocks - if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { + if mode == argon2i || mode == argon2id { in[6]++ processBlock(&addresses, &in, &zero) processBlock(&addresses, &addresses, &zero) @@ -143,7 +207,7 @@ func processBlocks(B []block, time, memory, threads uint32, mode int) { for index < segments { prev := offset - 1 if index == 0 && slice == 0 { - prev = lane*lanes + lanes - 1 // last block in lane + prev += lanes // last block in lane } if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { if index%blockLength == 0 { @@ -194,8 +258,10 @@ func extractKey(B []block, memory, threads, keyLen uint32) []byte { func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 { refLane := uint32(rand>>32) % threads - - m, s := 3*segments, (slice+1)%4*segments + if n == 0 && slice == 0 { + refLane = lane + } + m, s := 3*segments, ((slice+1)%syncPoints)*segments if lane == refLane { m += index } diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.go b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go index 583ac4be2ae3fa24da031dd680a76d13617c9742..2fc1ec0312236a8e126d88cd002c300eb7e8052e 100644 --- a/vendor/golang.org/x/crypto/argon2/blamka_amd64.go +++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go @@ -2,15 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build amd64,!gccgo,!appengine + package argon2 +import "golang.org/x/sys/cpu" + func init() { - useSSE4 = supportsSSE4() + useSSE4 = cpu.X86.HasSSE41 } -//go:noescape -func supportsSSE4() bool - //go:noescape func mixBlocksSSE2(out, a, b, c *block) diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.s b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s index 8a83f7c73985a16a84fbf829d51cb93ef64b1532..74a6e7332a94a3383074e0e89aa23a8252f961ba 100644 --- a/vendor/golang.org/x/crypto/argon2/blamka_amd64.s +++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s @@ -241,12 +241,3 @@ loop: SUBQ $2, BP JA loop RET - -// func supportsSSE4() bool -TEXT ·supportsSSE4(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $19, CX // Bit 19 indicates SSE4 support - ANDL $1, CX // CX != 0 if support SSE4 - MOVB CX, ret+0(FP) - RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/golang.org/x/crypto/blake2b/blake2b.go index 6dedb89467ae18a9824fca2cc7874c590a128739..58ea8753618e5641cbbd31cec2a5ed0cb02da3c4 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2b.go +++ b/vendor/golang.org/x/crypto/blake2b/blake2b.go @@ -92,6 +92,8 @@ func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } // values equal or greater than: // - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). // - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). +// When the key is nil, the returned hash.Hash implements BinaryMarshaler +// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } func newDigest(hashSize int, key []byte) (*digest, error) { @@ -150,6 +152,50 @@ type digest struct { keyLen int } +const ( + magic = "b2b" + marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + if d.keyLen != 0 { + return nil, errors.New("crypto/blake2b: cannot marshal MACs") + } + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + for i := 0; i < 8; i++ { + b = appendUint64(b, d.h[i]) + } + b = appendUint64(b, d.c[0]) + b = appendUint64(b, d.c[1]) + // Maximum value for size is 64 + b = append(b, byte(d.size)) + b = append(b, d.block[:]...) + b = append(b, byte(d.offset)) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/blake2b: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/blake2b: invalid hash state size") + } + b = b[len(magic):] + for i := 0; i < 8; i++ { + b, d.h[i] = consumeUint64(b) + } + b, d.c[0] = consumeUint64(b) + b, d.c[1] = consumeUint64(b) + d.size = int(b[0]) + b = b[1:] + copy(d.block[:], b[:BlockSize]) + b = b[BlockSize:] + d.offset = int(b[0]) + return nil +} + func (d *digest) BlockSize() int { return BlockSize } func (d *digest) Size() int { return d.size } @@ -219,3 +265,25 @@ func (d *digest) finalize(hash *[Size]byte) { binary.LittleEndian.PutUint64(hash[8*i:], v) } } + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + x := binary.BigEndian.Uint64(b) + return b[8:], x +} + +func consumeUint32(b []byte) ([]byte, uint32) { + x := binary.BigEndian.Uint32(b) + return b[4:], x +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go index 8c41cf6c79ea75463e00b94c94b5b3f5f46b48e1..4d31dd0fdcd5db7bd47845e67a98662b080b6b0e 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go @@ -6,21 +6,14 @@ package blake2b +import "golang.org/x/sys/cpu" + func init() { - useAVX2 = supportsAVX2() - useAVX = supportsAVX() - useSSE4 = supportsSSE4() + useAVX2 = cpu.X86.HasAVX2 + useAVX = cpu.X86.HasAVX + useSSE4 = cpu.X86.HasSSE41 } -//go:noescape -func supportsSSE4() bool - -//go:noescape -func supportsAVX() bool - -//go:noescape -func supportsAVX2() bool - //go:noescape func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) @@ -31,13 +24,14 @@ func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { - if useAVX2 { + switch { + case useAVX2: hashBlocksAVX2(h, c, flag, blocks) - } else if useAVX { + case useAVX: hashBlocksAVX(h, c, flag, blocks) - } else if useSSE4 { + case useSSE4: hashBlocksSSE4(h, c, flag, blocks) - } else { + default: hashBlocksGeneric(h, c, flag, blocks) } } diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s index 784bce6a9c43c57aedc008747e90aefd240c485c..5593b1b3dce267af7eeab923a763cba6ab0428a0 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s @@ -748,15 +748,3 @@ noinc: MOVQ BP, SP RET - -// func supportsAVX2() bool -TEXT ·supportsAVX2(SB), 4, $0-1 - MOVQ runtime·support_avx2(SB), AX - MOVB AX, ret+0(FP) - RET - -// func supportsAVX() bool -TEXT ·supportsAVX(SB), 4, $0-1 - MOVQ runtime·support_avx(SB), AX - MOVB AX, ret+0(FP) - RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go index 2ab7c30fc2ba58eea0cdefdc24cd75a9fd6626c5..30e2fcd581fd5e57535ed0d1d275a6a8d19ea37e 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go @@ -6,13 +6,12 @@ package blake2b +import "golang.org/x/sys/cpu" + func init() { - useSSE4 = supportsSSE4() + useSSE4 = cpu.X86.HasSSE41 } -//go:noescape -func supportsSSE4() bool - //go:noescape func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s index 64530740b40f8407917af35a127c0c9739f339e3..578e947b3bf9058dc478e453cc10a650ef554737 100644 --- a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s @@ -279,12 +279,3 @@ noinc: MOVQ BP, SP RET - -// func supportsSSE4() bool -TEXT ·supportsSSE4(SB), 4, $0-1 - MOVL $1, AX - CPUID - SHRL $19, CX // Bit 19 indicates SSE4 support - ANDL $1, CX // CX != 0 if support SSE4 - MOVB CX, ret+0(FP) - RET diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt.go b/vendor/golang.org/x/crypto/scrypt/scrypt.go index ff28aaef6ff2f091efe8cdbae93da4c402908bd1..9b25b5ac255a8df66d676c177ab33af60819a265 100644 --- a/vendor/golang.org/x/crypto/scrypt/scrypt.go +++ b/vendor/golang.org/x/crypto/scrypt/scrypt.go @@ -218,7 +218,7 @@ func smix(b []byte, r, N int, v, xy []uint32) { // For example, you can get a derived key for e.g. AES-256 (which needs a // 32-byte key) by doing: // -// dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) +// dk, err := scrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32) // // The recommended parameters for interactive logins as of 2017 are N=32768, r=8 // and p=1. The parameters N, r, and p should be increased as memory latency and diff --git a/vendor/golang.org/x/net/publicsuffix/gen.go b/vendor/golang.org/x/net/publicsuffix/gen.go deleted file mode 100644 index f85a3c32b197aa8760bc269acce3e3629b43d7dc..0000000000000000000000000000000000000000 --- a/vendor/golang.org/x/net/publicsuffix/gen.go +++ /dev/null @@ -1,713 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// This program generates table.go and table_test.go based on the authoritative -// public suffix list at https://publicsuffix.org/list/effective_tld_names.dat -// -// The version is derived from -// https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat -// and a human-readable form is at -// https://github.com/publicsuffix/list/commits/master/public_suffix_list.dat -// -// To fetch a particular git revision, such as 5c70ccd250, pass -// -url "https://raw.githubusercontent.com/publicsuffix/list/5c70ccd250/public_suffix_list.dat" -// and -version "an explicit version string". - -import ( - "bufio" - "bytes" - "flag" - "fmt" - "go/format" - "io" - "io/ioutil" - "net/http" - "os" - "regexp" - "sort" - "strings" - - "golang.org/x/net/idna" -) - -const ( - // These sum of these four values must be no greater than 32. - nodesBitsChildren = 10 - nodesBitsICANN = 1 - nodesBitsTextOffset = 15 - nodesBitsTextLength = 6 - - // These sum of these four values must be no greater than 32. - childrenBitsWildcard = 1 - childrenBitsNodeType = 2 - childrenBitsHi = 14 - childrenBitsLo = 14 -) - -var ( - maxChildren int - maxTextOffset int - maxTextLength int - maxHi uint32 - maxLo uint32 -) - -func max(a, b int) int { - if a < b { - return b - } - return a -} - -func u32max(a, b uint32) uint32 { - if a < b { - return b - } - return a -} - -const ( - nodeTypeNormal = 0 - nodeTypeException = 1 - nodeTypeParentOnly = 2 - numNodeType = 3 -) - -func nodeTypeStr(n int) string { - switch n { - case nodeTypeNormal: - return "+" - case nodeTypeException: - return "!" - case nodeTypeParentOnly: - return "o" - } - panic("unreachable") -} - -const ( - defaultURL = "https://publicsuffix.org/list/effective_tld_names.dat" - gitCommitURL = "https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat" -) - -var ( - labelEncoding = map[string]uint32{} - labelsList = []string{} - labelsMap = map[string]bool{} - rules = []string{} - - // validSuffixRE is used to check that the entries in the public suffix - // list are in canonical form (after Punycode encoding). Specifically, - // capital letters are not allowed. - validSuffixRE = regexp.MustCompile(`^[a-z0-9_\!\*\-\.]+$`) - - shaRE = regexp.MustCompile(`"sha":"([^"]+)"`) - dateRE = regexp.MustCompile(`"committer":{[^{]+"date":"([^"]+)"`) - - comments = flag.Bool("comments", false, "generate table.go comments, for debugging") - subset = flag.Bool("subset", false, "generate only a subset of the full table, for debugging") - url = flag.String("url", defaultURL, "URL of the publicsuffix.org list. If empty, stdin is read instead") - v = flag.Bool("v", false, "verbose output (to stderr)") - version = flag.String("version", "", "the effective_tld_names.dat version") -) - -func main() { - if err := main1(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -func main1() error { - flag.Parse() - if nodesBitsTextLength+nodesBitsTextOffset+nodesBitsICANN+nodesBitsChildren > 32 { - return fmt.Errorf("not enough bits to encode the nodes table") - } - if childrenBitsLo+childrenBitsHi+childrenBitsNodeType+childrenBitsWildcard > 32 { - return fmt.Errorf("not enough bits to encode the children table") - } - if *version == "" { - if *url != defaultURL { - return fmt.Errorf("-version was not specified, and the -url is not the default one") - } - sha, date, err := gitCommit() - if err != nil { - return err - } - *version = fmt.Sprintf("publicsuffix.org's public_suffix_list.dat, git revision %s (%s)", sha, date) - } - var r io.Reader = os.Stdin - if *url != "" { - res, err := http.Get(*url) - if err != nil { - return err - } - if res.StatusCode != http.StatusOK { - return fmt.Errorf("bad GET status for %s: %d", *url, res.Status) - } - r = res.Body - defer res.Body.Close() - } - - var root node - icann := false - br := bufio.NewReader(r) - for { - s, err := br.ReadString('\n') - if err != nil { - if err == io.EOF { - break - } - return err - } - s = strings.TrimSpace(s) - if strings.Contains(s, "BEGIN ICANN DOMAINS") { - icann = true - continue - } - if strings.Contains(s, "END ICANN DOMAINS") { - icann = false - continue - } - if s == "" || strings.HasPrefix(s, "//") { - continue - } - s, err = idna.ToASCII(s) - if err != nil { - return err - } - if !validSuffixRE.MatchString(s) { - return fmt.Errorf("bad publicsuffix.org list data: %q", s) - } - - if *subset { - switch { - case s == "ac.jp" || strings.HasSuffix(s, ".ac.jp"): - case s == "ak.us" || strings.HasSuffix(s, ".ak.us"): - case s == "ao" || strings.HasSuffix(s, ".ao"): - case s == "ar" || strings.HasSuffix(s, ".ar"): - case s == "arpa" || strings.HasSuffix(s, ".arpa"): - case s == "cy" || strings.HasSuffix(s, ".cy"): - case s == "dyndns.org" || strings.HasSuffix(s, ".dyndns.org"): - case s == "jp": - case s == "kobe.jp" || strings.HasSuffix(s, ".kobe.jp"): - case s == "kyoto.jp" || strings.HasSuffix(s, ".kyoto.jp"): - case s == "om" || strings.HasSuffix(s, ".om"): - case s == "uk" || strings.HasSuffix(s, ".uk"): - case s == "uk.com" || strings.HasSuffix(s, ".uk.com"): - case s == "tw" || strings.HasSuffix(s, ".tw"): - case s == "zw" || strings.HasSuffix(s, ".zw"): - case s == "xn--p1ai" || strings.HasSuffix(s, ".xn--p1ai"): - // xn--p1ai is Russian-Cyrillic "рф". - default: - continue - } - } - - rules = append(rules, s) - - nt, wildcard := nodeTypeNormal, false - switch { - case strings.HasPrefix(s, "*."): - s, nt = s[2:], nodeTypeParentOnly - wildcard = true - case strings.HasPrefix(s, "!"): - s, nt = s[1:], nodeTypeException - } - labels := strings.Split(s, ".") - for n, i := &root, len(labels)-1; i >= 0; i-- { - label := labels[i] - n = n.child(label) - if i == 0 { - if nt != nodeTypeParentOnly && n.nodeType == nodeTypeParentOnly { - n.nodeType = nt - } - n.icann = n.icann && icann - n.wildcard = n.wildcard || wildcard - } - labelsMap[label] = true - } - } - labelsList = make([]string, 0, len(labelsMap)) - for label := range labelsMap { - labelsList = append(labelsList, label) - } - sort.Strings(labelsList) - - if err := generate(printReal, &root, "table.go"); err != nil { - return err - } - if err := generate(printTest, &root, "table_test.go"); err != nil { - return err - } - return nil -} - -func generate(p func(io.Writer, *node) error, root *node, filename string) error { - buf := new(bytes.Buffer) - if err := p(buf, root); err != nil { - return err - } - b, err := format.Source(buf.Bytes()) - if err != nil { - return err - } - return ioutil.WriteFile(filename, b, 0644) -} - -func gitCommit() (sha, date string, retErr error) { - res, err := http.Get(gitCommitURL) - if err != nil { - return "", "", err - } - if res.StatusCode != http.StatusOK { - return "", "", fmt.Errorf("bad GET status for %s: %d", gitCommitURL, res.Status) - } - defer res.Body.Close() - b, err := ioutil.ReadAll(res.Body) - if err != nil { - return "", "", err - } - if m := shaRE.FindSubmatch(b); m != nil { - sha = string(m[1]) - } - if m := dateRE.FindSubmatch(b); m != nil { - date = string(m[1]) - } - if sha == "" || date == "" { - retErr = fmt.Errorf("could not find commit SHA and date in %s", gitCommitURL) - } - return sha, date, retErr -} - -func printTest(w io.Writer, n *node) error { - fmt.Fprintf(w, "// generated by go run gen.go; DO NOT EDIT\n\n") - fmt.Fprintf(w, "package publicsuffix\n\nvar rules = [...]string{\n") - for _, rule := range rules { - fmt.Fprintf(w, "%q,\n", rule) - } - fmt.Fprintf(w, "}\n\nvar nodeLabels = [...]string{\n") - if err := n.walk(w, printNodeLabel); err != nil { - return err - } - fmt.Fprintf(w, "}\n") - return nil -} - -func printReal(w io.Writer, n *node) error { - const header = `// generated by go run gen.go; DO NOT EDIT - -package publicsuffix - -const version = %q - -const ( - nodesBitsChildren = %d - nodesBitsICANN = %d - nodesBitsTextOffset = %d - nodesBitsTextLength = %d - - childrenBitsWildcard = %d - childrenBitsNodeType = %d - childrenBitsHi = %d - childrenBitsLo = %d -) - -const ( - nodeTypeNormal = %d - nodeTypeException = %d - nodeTypeParentOnly = %d -) - -// numTLD is the number of top level domains. -const numTLD = %d - -` - fmt.Fprintf(w, header, *version, - nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength, - childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo, - nodeTypeNormal, nodeTypeException, nodeTypeParentOnly, len(n.children)) - - text := combineText(labelsList) - if text == "" { - return fmt.Errorf("internal error: makeText returned no text") - } - for _, label := range labelsList { - offset, length := strings.Index(text, label), len(label) - if offset < 0 { - return fmt.Errorf("internal error: could not find %q in text %q", label, text) - } - maxTextOffset, maxTextLength = max(maxTextOffset, offset), max(maxTextLength, length) - if offset >= 1<<nodesBitsTextOffset { - return fmt.Errorf("text offset %d is too large, or nodeBitsTextOffset is too small", offset) - } - if length >= 1<<nodesBitsTextLength { - return fmt.Errorf("text length %d is too large, or nodeBitsTextLength is too small", length) - } - labelEncoding[label] = uint32(offset)<<nodesBitsTextLength | uint32(length) - } - fmt.Fprintf(w, "// Text is the combined text of all labels.\nconst text = ") - for len(text) > 0 { - n, plus := len(text), "" - if n > 64 { - n, plus = 64, " +" - } - fmt.Fprintf(w, "%q%s\n", text[:n], plus) - text = text[n:] - } - - if err := n.walk(w, assignIndexes); err != nil { - return err - } - - fmt.Fprintf(w, ` - -// nodes is the list of nodes. Each node is represented as a uint32, which -// encodes the node's children, wildcard bit and node type (as an index into -// the children array), ICANN bit and text. -// -// If the table was generated with the -comments flag, there is a //-comment -// after each node's data. In it is the nodes-array indexes of the children, -// formatted as (n0x1234-n0x1256), with * denoting the wildcard bit. The -// nodeType is printed as + for normal, ! for exception, and o for parent-only -// nodes that have children but don't match a domain label in their own right. -// An I denotes an ICANN domain. -// -// The layout within the uint32, from MSB to LSB, is: -// [%2d bits] unused -// [%2d bits] children index -// [%2d bits] ICANN bit -// [%2d bits] text index -// [%2d bits] text length -var nodes = [...]uint32{ -`, - 32-nodesBitsChildren-nodesBitsICANN-nodesBitsTextOffset-nodesBitsTextLength, - nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength) - if err := n.walk(w, printNode); err != nil { - return err - } - fmt.Fprintf(w, `} - -// children is the list of nodes' children, the parent's wildcard bit and the -// parent's node type. If a node has no children then their children index -// will be in the range [0, 6), depending on the wildcard bit and node type. -// -// The layout within the uint32, from MSB to LSB, is: -// [%2d bits] unused -// [%2d bits] wildcard bit -// [%2d bits] node type -// [%2d bits] high nodes index (exclusive) of children -// [%2d bits] low nodes index (inclusive) of children -var children=[...]uint32{ -`, - 32-childrenBitsWildcard-childrenBitsNodeType-childrenBitsHi-childrenBitsLo, - childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo) - for i, c := range childrenEncoding { - s := "---------------" - lo := c & (1<<childrenBitsLo - 1) - hi := (c >> childrenBitsLo) & (1<<childrenBitsHi - 1) - if lo != hi { - s = fmt.Sprintf("n0x%04x-n0x%04x", lo, hi) - } - nodeType := int(c>>(childrenBitsLo+childrenBitsHi)) & (1<<childrenBitsNodeType - 1) - wildcard := c>>(childrenBitsLo+childrenBitsHi+childrenBitsNodeType) != 0 - if *comments { - fmt.Fprintf(w, "0x%08x, // c0x%04x (%s)%s %s\n", - c, i, s, wildcardStr(wildcard), nodeTypeStr(nodeType)) - } else { - fmt.Fprintf(w, "0x%x,\n", c) - } - } - fmt.Fprintf(w, "}\n\n") - fmt.Fprintf(w, "// max children %d (capacity %d)\n", maxChildren, 1<<nodesBitsChildren-1) - fmt.Fprintf(w, "// max text offset %d (capacity %d)\n", maxTextOffset, 1<<nodesBitsTextOffset-1) - fmt.Fprintf(w, "// max text length %d (capacity %d)\n", maxTextLength, 1<<nodesBitsTextLength-1) - fmt.Fprintf(w, "// max hi %d (capacity %d)\n", maxHi, 1<<childrenBitsHi-1) - fmt.Fprintf(w, "// max lo %d (capacity %d)\n", maxLo, 1<<childrenBitsLo-1) - return nil -} - -type node struct { - label string - nodeType int - icann bool - wildcard bool - // nodesIndex and childrenIndex are the index of this node in the nodes - // and the index of its children offset/length in the children arrays. - nodesIndex, childrenIndex int - // firstChild is the index of this node's first child, or zero if this - // node has no children. - firstChild int - // children are the node's children, in strictly increasing node label order. - children []*node -} - -func (n *node) walk(w io.Writer, f func(w1 io.Writer, n1 *node) error) error { - if err := f(w, n); err != nil { - return err - } - for _, c := range n.children { - if err := c.walk(w, f); err != nil { - return err - } - } - return nil -} - -// child returns the child of n with the given label. The child is created if -// it did not exist beforehand. -func (n *node) child(label string) *node { - for _, c := range n.children { - if c.label == label { - return c - } - } - c := &node{ - label: label, - nodeType: nodeTypeParentOnly, - icann: true, - } - n.children = append(n.children, c) - sort.Sort(byLabel(n.children)) - return c -} - -type byLabel []*node - -func (b byLabel) Len() int { return len(b) } -func (b byLabel) Swap(i, j int) { b[i], b[j] = b[j], b[i] } -func (b byLabel) Less(i, j int) bool { return b[i].label < b[j].label } - -var nextNodesIndex int - -// childrenEncoding are the encoded entries in the generated children array. -// All these pre-defined entries have no children. -var childrenEncoding = []uint32{ - 0 << (childrenBitsLo + childrenBitsHi), // Without wildcard bit, nodeTypeNormal. - 1 << (childrenBitsLo + childrenBitsHi), // Without wildcard bit, nodeTypeException. - 2 << (childrenBitsLo + childrenBitsHi), // Without wildcard bit, nodeTypeParentOnly. - 4 << (childrenBitsLo + childrenBitsHi), // With wildcard bit, nodeTypeNormal. - 5 << (childrenBitsLo + childrenBitsHi), // With wildcard bit, nodeTypeException. - 6 << (childrenBitsLo + childrenBitsHi), // With wildcard bit, nodeTypeParentOnly. -} - -var firstCallToAssignIndexes = true - -func assignIndexes(w io.Writer, n *node) error { - if len(n.children) != 0 { - // Assign nodesIndex. - n.firstChild = nextNodesIndex - for _, c := range n.children { - c.nodesIndex = nextNodesIndex - nextNodesIndex++ - } - - // The root node's children is implicit. - if firstCallToAssignIndexes { - firstCallToAssignIndexes = false - return nil - } - - // Assign childrenIndex. - maxChildren = max(maxChildren, len(childrenEncoding)) - if len(childrenEncoding) >= 1<<nodesBitsChildren { - return fmt.Errorf("children table size %d is too large, or nodeBitsChildren is too small", len(childrenEncoding)) - } - n.childrenIndex = len(childrenEncoding) - lo := uint32(n.firstChild) - hi := lo + uint32(len(n.children)) - maxLo, maxHi = u32max(maxLo, lo), u32max(maxHi, hi) - if lo >= 1<<childrenBitsLo { - return fmt.Errorf("children lo %d is too large, or childrenBitsLo is too small", lo) - } - if hi >= 1<<childrenBitsHi { - return fmt.Errorf("children hi %d is too large, or childrenBitsHi is too small", hi) - } - enc := hi<<childrenBitsLo | lo - enc |= uint32(n.nodeType) << (childrenBitsLo + childrenBitsHi) - if n.wildcard { - enc |= 1 << (childrenBitsLo + childrenBitsHi + childrenBitsNodeType) - } - childrenEncoding = append(childrenEncoding, enc) - } else { - n.childrenIndex = n.nodeType - if n.wildcard { - n.childrenIndex += numNodeType - } - } - return nil -} - -func printNode(w io.Writer, n *node) error { - for _, c := range n.children { - s := "---------------" - if len(c.children) != 0 { - s = fmt.Sprintf("n0x%04x-n0x%04x", c.firstChild, c.firstChild+len(c.children)) - } - encoding := labelEncoding[c.label] - if c.icann { - encoding |= 1 << (nodesBitsTextLength + nodesBitsTextOffset) - } - encoding |= uint32(c.childrenIndex) << (nodesBitsTextLength + nodesBitsTextOffset + nodesBitsICANN) - if *comments { - fmt.Fprintf(w, "0x%08x, // n0x%04x c0x%04x (%s)%s %s %s %s\n", - encoding, c.nodesIndex, c.childrenIndex, s, wildcardStr(c.wildcard), - nodeTypeStr(c.nodeType), icannStr(c.icann), c.label, - ) - } else { - fmt.Fprintf(w, "0x%x,\n", encoding) - } - } - return nil -} - -func printNodeLabel(w io.Writer, n *node) error { - for _, c := range n.children { - fmt.Fprintf(w, "%q,\n", c.label) - } - return nil -} - -func icannStr(icann bool) string { - if icann { - return "I" - } - return " " -} - -func wildcardStr(wildcard bool) string { - if wildcard { - return "*" - } - return " " -} - -// combineText combines all the strings in labelsList to form one giant string. -// Overlapping strings will be merged: "arpa" and "parliament" could yield -// "arparliament". -func combineText(labelsList []string) string { - beforeLength := 0 - for _, s := range labelsList { - beforeLength += len(s) - } - - text := crush(removeSubstrings(labelsList)) - if *v { - fmt.Fprintf(os.Stderr, "crushed %d bytes to become %d bytes\n", beforeLength, len(text)) - } - return text -} - -type byLength []string - -func (s byLength) Len() int { return len(s) } -func (s byLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s byLength) Less(i, j int) bool { return len(s[i]) < len(s[j]) } - -// removeSubstrings returns a copy of its input with any strings removed -// that are substrings of other provided strings. -func removeSubstrings(input []string) []string { - // Make a copy of input. - ss := append(make([]string, 0, len(input)), input...) - sort.Sort(byLength(ss)) - - for i, shortString := range ss { - // For each string, only consider strings higher than it in sort order, i.e. - // of equal length or greater. - for _, longString := range ss[i+1:] { - if strings.Contains(longString, shortString) { - ss[i] = "" - break - } - } - } - - // Remove the empty strings. - sort.Strings(ss) - for len(ss) > 0 && ss[0] == "" { - ss = ss[1:] - } - return ss -} - -// crush combines a list of strings, taking advantage of overlaps. It returns a -// single string that contains each input string as a substring. -func crush(ss []string) string { - maxLabelLen := 0 - for _, s := range ss { - if maxLabelLen < len(s) { - maxLabelLen = len(s) - } - } - - for prefixLen := maxLabelLen; prefixLen > 0; prefixLen-- { - prefixes := makePrefixMap(ss, prefixLen) - for i, s := range ss { - if len(s) <= prefixLen { - continue - } - mergeLabel(ss, i, prefixLen, prefixes) - } - } - - return strings.Join(ss, "") -} - -// mergeLabel merges the label at ss[i] with the first available matching label -// in prefixMap, where the last "prefixLen" characters in ss[i] match the first -// "prefixLen" characters in the matching label. -// It will merge ss[i] repeatedly until no more matches are available. -// All matching labels merged into ss[i] are replaced by "". -func mergeLabel(ss []string, i, prefixLen int, prefixes prefixMap) { - s := ss[i] - suffix := s[len(s)-prefixLen:] - for _, j := range prefixes[suffix] { - // Empty strings mean "already used." Also avoid merging with self. - if ss[j] == "" || i == j { - continue - } - if *v { - fmt.Fprintf(os.Stderr, "%d-length overlap at (%4d,%4d): %q and %q share %q\n", - prefixLen, i, j, ss[i], ss[j], suffix) - } - ss[i] += ss[j][prefixLen:] - ss[j] = "" - // ss[i] has a new suffix, so merge again if possible. - // Note: we only have to merge again at the same prefix length. Shorter - // prefix lengths will be handled in the next iteration of crush's for loop. - // Can there be matches for longer prefix lengths, introduced by the merge? - // I believe that any such matches would by necessity have been eliminated - // during substring removal or merged at a higher prefix length. For - // instance, in crush("abc", "cde", "bcdef"), combining "abc" and "cde" - // would yield "abcde", which could be merged with "bcdef." However, in - // practice "cde" would already have been elimintated by removeSubstrings. - mergeLabel(ss, i, prefixLen, prefixes) - return - } -} - -// prefixMap maps from a prefix to a list of strings containing that prefix. The -// list of strings is represented as indexes into a slice of strings stored -// elsewhere. -type prefixMap map[string][]int - -// makePrefixMap constructs a prefixMap from a slice of strings. -func makePrefixMap(ss []string, prefixLen int) prefixMap { - prefixes := make(prefixMap) - for i, s := range ss { - // We use < rather than <= because if a label matches on a prefix equal to - // its full length, that's actually a substring match handled by - // removeSubstrings. - if prefixLen < len(s) { - prefix := s[:prefixLen] - prefixes[prefix] = append(prefixes[prefix], i) - } - } - - return prefixes -} diff --git a/vendor/golang.org/x/sys/LICENSE b/vendor/golang.org/x/sys/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..6a66aea5eafe0ca6a688840c47219556c552488e --- /dev/null +++ b/vendor/golang.org/x/sys/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/sys/PATENTS b/vendor/golang.org/x/sys/PATENTS new file mode 100644 index 0000000000000000000000000000000000000000..733099041f84fa1e58611ab2e11af51c1f26d1d2 --- /dev/null +++ b/vendor/golang.org/x/sys/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go new file mode 100644 index 0000000000000000000000000000000000000000..3d88f866739e963f6f99a784d350ec14207feb66 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu.go @@ -0,0 +1,38 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cpu implements processor feature detection for +// various CPU architectures. +package cpu + +// CacheLinePad is used to pad structs to avoid false sharing. +type CacheLinePad struct{ _ [cacheLineSize]byte } + +// X86 contains the supported CPU features of the +// current X86/AMD64 platform. If the current platform +// is not X86/AMD64 then all feature flags are false. +// +// X86 is padded to avoid false sharing. Further the HasAVX +// and HasAVX2 are only set if the OS supports XMM and YMM +// registers in addition to the CPUID feature bit being set. +var X86 struct { + _ CacheLinePad + HasAES bool // AES hardware implementation (AES NI) + HasADX bool // Multi-precision add-carry instruction extensions + HasAVX bool // Advanced vector extension + HasAVX2 bool // Advanced vector extension 2 + HasBMI1 bool // Bit manipulation instruction set 1 + HasBMI2 bool // Bit manipulation instruction set 2 + HasERMS bool // Enhanced REP for MOVSB and STOSB + HasFMA bool // Fused-multiply-add instructions + HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. + HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM + HasPOPCNT bool // Hamming weight instruction POPCNT. + HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) + HasSSE3 bool // Streaming SIMD extension 3 + HasSSSE3 bool // Supplemental streaming SIMD extension 3 + HasSSE41 bool // Streaming SIMD extension 4 and 4.1 + HasSSE42 bool // Streaming SIMD extension 4 and 4.2 + _ CacheLinePad +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm.go b/vendor/golang.org/x/sys/cpu/cpu_arm.go new file mode 100644 index 0000000000000000000000000000000000000000..d93036f7522bf7f9545aa9dbb55be2afab36aabf --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_arm.go @@ -0,0 +1,7 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +const cacheLineSize = 32 diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_arm64.go new file mode 100644 index 0000000000000000000000000000000000000000..1d2ab2902a769684cfb8b7fb32b67d72e20f9014 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.go @@ -0,0 +1,7 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +const cacheLineSize = 64 diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go new file mode 100644 index 0000000000000000000000000000000000000000..f7cb46971cb051570ca190a86b277875f14f5cd8 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go @@ -0,0 +1,16 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build !gccgo + +package cpu + +// cpuid is implemented in cpu_x86.s for gc compiler +// and in cpu_gccgo.c for gccgo. +func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) + +// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler +// and in cpu_gccgo.c for gccgo. +func xgetbv() (eax, edx uint32) diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo.c b/vendor/golang.org/x/sys/cpu/cpu_gccgo.c new file mode 100644 index 0000000000000000000000000000000000000000..e363c7d1319782c7ea58c87367a4f99528ff4c32 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo.c @@ -0,0 +1,43 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build gccgo + +#include <cpuid.h> +#include <stdint.h> + +// Need to wrap __get_cpuid_count because it's declared as static. +int +gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); +} + +// xgetbv reads the contents of an XCR (Extended Control Register) +// specified in the ECX register into registers EDX:EAX. +// Currently, the only supported value for XCR is 0. +// +// TODO: Replace with a better alternative: +// +// #include <xsaveintrin.h> +// +// #pragma GCC target("xsave") +// +// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { +// unsigned long long x = _xgetbv(0); +// *eax = x & 0xffffffff; +// *edx = (x >> 32) & 0xffffffff; +// } +// +// Note that _xgetbv is defined starting with GCC 8. +void +gccgoXgetbv(uint32_t *eax, uint32_t *edx) +{ + __asm(" xorl %%ecx, %%ecx\n" + " xgetbv" + : "=a"(*eax), "=d"(*edx)); +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo.go new file mode 100644 index 0000000000000000000000000000000000000000..ba49b91bd398cd72c437e85af46655d204416794 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo.go @@ -0,0 +1,26 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build gccgo + +package cpu + +//extern gccgoGetCpuidCount +func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32) + +func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) { + var a, b, c, d uint32 + gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d) + return a, b, c, d +} + +//extern gccgoXgetbv +func gccgoXgetbv(eax, edx *uint32) + +func xgetbv() (eax, edx uint32) { + var a, d uint32 + gccgoXgetbv(&a, &d) + return a, d +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go new file mode 100644 index 0000000000000000000000000000000000000000..6165f121249abd4b272a6e7d35f9da50c9433532 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go @@ -0,0 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build mips64 mips64le + +package cpu + +const cacheLineSize = 32 diff --git a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go new file mode 100644 index 0000000000000000000000000000000000000000..1269eee88d00626c89276d04b371a8249e916eb5 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go @@ -0,0 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build mips mipsle + +package cpu + +const cacheLineSize = 32 diff --git a/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go new file mode 100644 index 0000000000000000000000000000000000000000..d10759a524f2858dc26cc7bfdcc81d7c595336e8 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go @@ -0,0 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ppc64 ppc64le + +package cpu + +const cacheLineSize = 128 diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_s390x.go new file mode 100644 index 0000000000000000000000000000000000000000..684c4f005d09eacd825ed1b68937f863fdaff519 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_s390x.go @@ -0,0 +1,7 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +const cacheLineSize = 256 diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go new file mode 100644 index 0000000000000000000000000000000000000000..71e288b06223d542f5dc4865015987be6e53f2f3 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -0,0 +1,55 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 + +package cpu + +const cacheLineSize = 64 + +func init() { + maxID, _, _, _ := cpuid(0, 0) + + if maxID < 1 { + return + } + + _, _, ecx1, edx1 := cpuid(1, 0) + X86.HasSSE2 = isSet(26, edx1) + + X86.HasSSE3 = isSet(0, ecx1) + X86.HasPCLMULQDQ = isSet(1, ecx1) + X86.HasSSSE3 = isSet(9, ecx1) + X86.HasFMA = isSet(12, ecx1) + X86.HasSSE41 = isSet(19, ecx1) + X86.HasSSE42 = isSet(20, ecx1) + X86.HasPOPCNT = isSet(23, ecx1) + X86.HasAES = isSet(25, ecx1) + X86.HasOSXSAVE = isSet(27, ecx1) + + osSupportsAVX := false + // For XGETBV, OSXSAVE bit is required and sufficient. + if X86.HasOSXSAVE { + eax, _ := xgetbv() + // Check if XMM and YMM registers have OS support. + osSupportsAVX = isSet(1, eax) && isSet(2, eax) + } + + X86.HasAVX = isSet(28, ecx1) && osSupportsAVX + + if maxID < 7 { + return + } + + _, ebx7, _, _ := cpuid(7, 0) + X86.HasBMI1 = isSet(3, ebx7) + X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX + X86.HasBMI2 = isSet(8, ebx7) + X86.HasERMS = isSet(9, ebx7) + X86.HasADX = isSet(19, ebx7) +} + +func isSet(bitpos uint, value uint32) bool { + return value&(1<<bitpos) != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.s b/vendor/golang.org/x/sys/cpu/cpu_x86.s new file mode 100644 index 0000000000000000000000000000000000000000..47f084128cc3f83b9a41743b6406f5031e5c2974 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_x86.s @@ -0,0 +1,27 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build !gccgo + +#include "textflag.h" + +// func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) +TEXT ·cpuid(SB), NOSPLIT, $0-24 + MOVL eaxArg+0(FP), AX + MOVL ecxArg+4(FP), CX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET + +// func xgetbv() (eax, edx uint32) +TEXT ·xgetbv(SB),NOSPLIT,$0-8 + MOVL $0, CX + XGETBV + MOVL AX, eax+0(FP) + MOVL DX, edx+4(FP) + RET diff --git a/vendor/vendor.json b/vendor/vendor.json index ba26192458651a214065ef56aa7bebfad53c26bd..ef2a8a816ad2cee56e1577bb06d47d3d454083f4 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -5,32 +5,38 @@ { "checksumSHA1": "raJx5BjBbVQG0ylGSjPpi+JvqjU=", "path": "git.autistici.org/ai3/go-common", - "revision": "c1ef74c73e037e2d729540077b90b751975de0ac", - "revisionTime": "2018-04-01T11:50:29Z" + "revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0", + "revisionTime": "2018-06-28T09:11:42Z" }, { "checksumSHA1": "o+rWKVQIDy79ZwrItwa5/whAL6g=", "path": "git.autistici.org/ai3/go-common/clientutil", - "revision": "c1ef74c73e037e2d729540077b90b751975de0ac", - "revisionTime": "2018-04-01T11:50:29Z" + "revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0", + "revisionTime": "2018-06-28T09:11:42Z" }, { "checksumSHA1": "udgeRdy83f6tJmhoKXFxCfwOIZw=", "path": "git.autistici.org/ai3/go-common/ldap", - "revision": "c1ef74c73e037e2d729540077b90b751975de0ac", - "revisionTime": "2018-04-01T11:50:29Z" + "revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0", + "revisionTime": "2018-06-28T09:11:42Z" }, { - "checksumSHA1": "z1034Bd8fOSLvtOP3VLf65YOQyA=", + "checksumSHA1": "mfFIqmwojDqQdJvjLI3y7YCQ+2c=", "path": "git.autistici.org/ai3/go-common/pwhash", - "revision": "c1ef74c73e037e2d729540077b90b751975de0ac", - "revisionTime": "2018-04-01T11:50:29Z" + "revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0", + "revisionTime": "2018-06-28T09:11:42Z" }, { - "checksumSHA1": "uwJs8DbmqNCMRAW5wbnVQqsFIOQ=", + "checksumSHA1": "7VBLbwaK1m/jwsk8sLsh4iD9T/s=", "path": "git.autistici.org/ai3/go-common/serverutil", - "revision": "c1ef74c73e037e2d729540077b90b751975de0ac", - "revisionTime": "2018-04-01T11:50:29Z" + "revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0", + "revisionTime": "2018-06-28T09:11:42Z" + }, + { + "checksumSHA1": "OY/kamdVCtqr00dhc+STq7ApbmA=", + "path": "git.autistici.org/ai3/go-common/userenckey", + "revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0", + "revisionTime": "2018-06-28T09:11:42Z" }, { "checksumSHA1": "QHzKyLU57jphYBzuhl4ELbCwVX0=", @@ -51,22 +57,22 @@ "revisionTime": "2016-08-04T10:47:26Z" }, { - "checksumSHA1": "Fnz7xSfgecNEaVi+I5a7HA1cl3I=", + "checksumSHA1": "uz40oH/u0lUXQPH+dMn1COrGr+o=", "path": "github.com/boombuler/barcode", - "revision": "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d", - "revisionTime": "2017-09-22T10:33:52Z" + "revision": "56ef0af91246fb5279df4f87bc3daf1bf7cb9e89", + "revisionTime": "2017-06-18T05:38:12Z" }, { "checksumSHA1": "jWsoIeAcg4+QlCJLZ8jXHiJ5a3s=", "path": "github.com/boombuler/barcode/qr", - "revision": "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d", - "revisionTime": "2017-09-22T10:33:52Z" + "revision": "56ef0af91246fb5279df4f87bc3daf1bf7cb9e89", + "revisionTime": "2017-06-18T05:38:12Z" }, { "checksumSHA1": "axe0OTdOjYa+XKDUYqzOv7FGaWo=", "path": "github.com/boombuler/barcode/utils", - "revision": "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d", - "revisionTime": "2017-09-22T10:33:52Z" + "revision": "56ef0af91246fb5279df4f87bc3daf1bf7cb9e89", + "revisionTime": "2017-06-18T05:38:12Z" }, { "checksumSHA1": "hTThB1Cw2ue02RD5Oig4eu1Dkzk=", @@ -92,6 +98,12 @@ "revision": "90663712d74cb411cbef281bc1e08c19d1a76145", "revisionTime": "2017-11-01T17:43:35Z" }, + { + "checksumSHA1": "D5EG5yMsbtHqKbzBVbxFMKEMDNY=", + "path": "github.com/lunixbochs/struc", + "revision": "02e4c2afbb2ac4bae6876f52c8273fc4cf5a4b0a", + "revisionTime": "2018-04-08T20:38:00Z" + }, { "checksumSHA1": "bKMZjd2wPw13VwoE7mBeSv5djFA=", "path": "github.com/matttproud/golang_protobuf_extensions/pbutil", @@ -99,22 +111,46 @@ "revisionTime": "2016-04-24T11:30:07Z" }, { - "checksumSHA1": "vCogt04lbcE8fUgvRCOaZQUo+Pk=", + "checksumSHA1": "42iE67lnxblPsQnllIZ+m2KJsvg=", + "path": "github.com/miscreant/miscreant/go", + "revision": "71d82ae9dd614c1ec09d4491e01d5d0ea762c398", + "revisionTime": "2018-06-23T00:14:59Z" + }, + { + "checksumSHA1": "LAN1Gs68UZhRbEUy25LfzDEjRT0=", + "path": "github.com/miscreant/miscreant/go/block", + "revision": "71d82ae9dd614c1ec09d4491e01d5d0ea762c398", + "revisionTime": "2018-06-23T00:14:59Z" + }, + { + "checksumSHA1": "Q1pe4LrL8CwfA/r+xYSl0/3AzPQ=", + "path": "github.com/miscreant/miscreant/go/cmac", + "revision": "71d82ae9dd614c1ec09d4491e01d5d0ea762c398", + "revisionTime": "2018-06-23T00:14:59Z" + }, + { + "checksumSHA1": "Xl/ZDNMfyC5t/HF2Ms+c519lGRk=", + "path": "github.com/miscreant/miscreant/go/pmac", + "revision": "71d82ae9dd614c1ec09d4491e01d5d0ea762c398", + "revisionTime": "2018-06-23T00:14:59Z" + }, + { + "checksumSHA1": "L3iXlt9SyaGtInA6xl2Uh5UA26s=", "path": "github.com/pquerna/otp", - "revision": "c70cbf6932991a11a553d1ee95d657f437e56c8a", - "revisionTime": "2017-09-13T14:24:48Z" + "revision": "b7b89250c468c06871d3837bee02e2d5c155ae19", + "revisionTime": "2017-08-07T03:07:00Z" }, { "checksumSHA1": "w6JFjO9IKPkzXj6laeeqApbilyY=", "path": "github.com/pquerna/otp/hotp", - "revision": "c70cbf6932991a11a553d1ee95d657f437e56c8a", - "revisionTime": "2017-09-13T14:24:48Z" + "revision": "b7b89250c468c06871d3837bee02e2d5c155ae19", + "revisionTime": "2017-08-07T03:07:00Z" }, { "checksumSHA1": "DHa0bNqkBRhm0bic9zMXC7KaYLM=", "path": "github.com/pquerna/otp/totp", - "revision": "c70cbf6932991a11a553d1ee95d657f437e56c8a", - "revisionTime": "2017-09-13T14:24:48Z" + "revision": "b7b89250c468c06871d3837bee02e2d5c155ae19", + "revisionTime": "2017-08-07T03:07:00Z" }, { "checksumSHA1": "hu0MsbTdFzZxNRyAxe2HmTFFFak=", @@ -177,16 +213,16 @@ "revisionTime": "2016-12-26T07:54:37Z" }, { - "checksumSHA1": "hiV2tg6uVcpyIlGgxvvdI4wXCL8=", + "checksumSHA1": "FwW3Vv4jW0Nv7V2SZC7x/Huj5M4=", "path": "golang.org/x/crypto/argon2", - "revision": "d585fd2cc9195196078f516b69daff6744ef5e84", - "revisionTime": "2017-12-16T04:08:15Z" + "revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602", + "revisionTime": "2018-06-20T09:14:27Z" }, { - "checksumSHA1": "ppPg0bIlBAVJy0Pn13BfBnkp9V4=", + "checksumSHA1": "ejjxT0+wDWWncfh0Rt3lSH4IbXQ=", "path": "golang.org/x/crypto/blake2b", - "revision": "d585fd2cc9195196078f516b69daff6744ef5e84", - "revisionTime": "2017-12-16T04:08:15Z" + "revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602", + "revisionTime": "2018-06-20T09:14:27Z" }, { "checksumSHA1": "X6Q8nYb+KXh+64AKHwWOOcyijHQ=", @@ -205,14 +241,14 @@ { "checksumSHA1": "1MGpGDQqnUoRpv7VEcQrXOBydXE=", "path": "golang.org/x/crypto/pbkdf2", - "revision": "d585fd2cc9195196078f516b69daff6744ef5e84", - "revisionTime": "2017-12-16T04:08:15Z" + "revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602", + "revisionTime": "2018-06-20T09:14:27Z" }, { - "checksumSHA1": "dHh6VeHcbNg11miGjGEl8LbPe7w=", + "checksumSHA1": "sx1nQShs40UKtcJZNJuvYtGesaI=", "path": "golang.org/x/crypto/scrypt", - "revision": "d585fd2cc9195196078f516b69daff6744ef5e84", - "revisionTime": "2017-12-16T04:08:15Z" + "revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602", + "revisionTime": "2018-06-20T09:14:27Z" }, { "checksumSHA1": "GtamqiJoL7PGHsN454AoffBFMa8=", @@ -221,10 +257,16 @@ "revisionTime": "2018-02-18T17:15:52Z" }, { - "checksumSHA1": "ZSIQuoAzHbZEPMSJFXNyjz0YC6g=", + "checksumSHA1": "Q165MxF3KQE3AaU3GGPsKFLEFCU=", "path": "golang.org/x/net/publicsuffix", - "revision": "f73e4c9ed3b7ebdd5f699a16a880c2b1994e50dd", - "revisionTime": "2018-05-08T00:58:03Z" + "revision": "cbe0f9307d0156177f9dd5dc85da1a31abc5f2fb", + "revisionTime": "2018-02-18T17:15:52Z" + }, + { + "checksumSHA1": "REkmyB368pIiip76LiqMLspgCRk=", + "path": "golang.org/x/sys/cpu", + "revision": "7138fd3d9dc8335c567ca206f4333fb75eb05d56", + "revisionTime": "2018-06-27T13:57:12Z" }, { "checksumSHA1": "xsaHqy6/sonLV6xIxTNh4FfkWbU=",