diff --git a/go.mod b/go.mod index 9bd2da70..f1e4a3b9 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/docker/cli v28.4.0+incompatible github.com/docker/docker v28.5.2+incompatible github.com/docker/go-units v0.5.0 - github.com/go-git/go-git/v5 v5.19.2 + github.com/go-git/go-git/v5 v5.19.3 github.com/google/go-cmp v0.7.0 github.com/leonelquinteros/gotext v1.7.2 github.com/moby/sys/signal v0.7.1 @@ -59,7 +59,7 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.9.0 // indirect + github.com/go-git/go-billy/v5 v5.9.2 // indirect github.com/go-logfmt/logfmt v0.6.1 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -73,7 +73,6 @@ require ( github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/ssh_config v1.6.0 // indirect github.com/klauspost/compress v1.18.5 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/lucasb-eyer/go-colorful v1.4.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.22 // indirect @@ -95,7 +94,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/runc v1.1.13 // indirect github.com/opencontainers/runtime-spec v1.1.0 // indirect - github.com/pjbgf/sha1cd v0.6.0 // indirect + github.com/pjbgf/sha1cd v0.7.0 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.67.5 // indirect github.com/prometheus/procfs v0.20.1 // indirect @@ -122,10 +121,10 @@ require ( go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect - golang.org/x/crypto v0.53.0 // indirect + golang.org/x/crypto v0.56.0 // indirect golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect - golang.org/x/net v0.56.0 // indirect - golang.org/x/text v0.39.0 // indirect + golang.org/x/net v0.57.0 // indirect + golang.org/x/text v0.41.0 // indirect golang.org/x/time v0.15.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect diff --git a/go.sum b/go.sum index 7c62bd40..c570db25 100644 --- a/go.sum +++ b/go.sum @@ -388,12 +388,12 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA= -github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= +github.com/go-git/go-billy/v5 v5.9.2 h1:OXFSRyz4g20upsGDJgQG9Bak1l/ZEv8GHVYB52O71sE= +github.com/go-git/go-billy/v5 v5.9.2/go.mod h1:ExsU+jcGwXTBOnyilvAnEM1wug1IxHr4yP2ZXsNRtV0= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.19.2 h1:wkfn7vOlUBu8ivAWKBWisTiwJK4jYHzTF8Ndv1LyGqY= -github.com/go-git/go-git/v5 v5.19.2/go.mod h1:QqCBE1EFN5ddFmrliLQ3/ntRCUjZU3EJuwuB/jWEHjk= +github.com/go-git/go-git/v5 v5.19.3 h1:qHttbZ+Am7wEjdTpR1XMQ4rl42FK9SIXzZ4o9x7s6M4= +github.com/go-git/go-git/v5 v5.19.3/go.mod h1:Ye4C8dVigkqrv9UsB4NMdSLV4yAIkLiIhW61gcOyhl4= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -585,8 +585,6 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -752,8 +750,8 @@ github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuh github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU= -github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= +github.com/pjbgf/sha1cd v0.7.0 h1:ZRNPKHj+gfkLBf0KJv/p1Hmz+7bqCT5o311YX0nq+DA= +github.com/pjbgf/sha1cd v0.7.0/go.mod h1:pKR5Li+qTCo+ebqITZfwPlJGoCFCvSO00qxjbNtTUFQ= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -965,8 +963,8 @@ golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= -golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= +golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= +golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1042,8 +1040,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= -golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= +golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= +golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1154,8 +1152,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus= -golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/vendor/coopcloud.tech/tagcmp/.drone.yml b/vendor/coopcloud.tech/tagcmp/.drone.yml index 2aefe487..c5f78899 100644 --- a/vendor/coopcloud.tech/tagcmp/.drone.yml +++ b/vendor/coopcloud.tech/tagcmp/.drone.yml @@ -3,16 +3,16 @@ kind: pipeline name: coopcloud.tech/tagcmp steps: - name: gofmt - image: golang:1.27 + image: golang:1.26 commands: - test -z "$(gofmt -l .)" - name: go build - image: golang:1.27 + image: golang:1.26 commands: - go build -v . - name: go test - image: golang:1.27 + image: golang:1.26 commands: - go test . -cover diff --git a/vendor/github.com/go-git/go-git/v5/config/config.go b/vendor/github.com/go-git/go-git/v5/config/config.go index 3ae6a571..b9b753dc 100644 --- a/vendor/github.com/go-git/go-git/v5/config/config.go +++ b/vendor/github.com/go-git/go-git/v5/config/config.go @@ -329,6 +329,10 @@ func (c *Config) unmarshalCore() { if parsed := parseConfigBool(s.Options.Get(protectHFSKey)); parsed.IsSet() { c.Core.ProtectHFS = parsed } + + if s.Options.Get(repositoryFormatVersionKey) == string(format.Version_1) { + c.Core.RepositoryFormatVersion = format.Version_1 + } } func (c *Config) unmarshalUser() { diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_selector.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_selector.go index 4b60ff39..bf4f8d11 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_selector.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_selector.go @@ -139,8 +139,12 @@ func (dw *deltaSelector) fixAndBreakChains(objectsToPack []*ObjectToPack) error m[otp.Hash()] = otp } + // visiting holds the objects on the current resolution path, so that a + // delta chain looping back on itself can be detected and broken. + visiting := make(map[plumbing.Hash]bool) + for _, otp := range objectsToPack { - if err := dw.fixAndBreakChainsOne(m, otp); err != nil { + if err := dw.fixAndBreakChainsOne(m, otp, visiting); err != nil { return err } } @@ -148,7 +152,11 @@ func (dw *deltaSelector) fixAndBreakChains(objectsToPack []*ObjectToPack) error return nil } -func (dw *deltaSelector) fixAndBreakChainsOne(objectsToPack map[plumbing.Hash]*ObjectToPack, otp *ObjectToPack) error { +func (dw *deltaSelector) fixAndBreakChainsOne( + objectsToPack map[plumbing.Hash]*ObjectToPack, + otp *ObjectToPack, + visiting map[plumbing.Hash]bool, +) error { if !otp.Object.Type().IsDelta() { return nil } @@ -174,7 +182,21 @@ func (dw *deltaSelector) fixAndBreakChainsOne(objectsToPack map[plumbing.Hash]*O return dw.undeltify(otp) } - if err := dw.fixAndBreakChainsOne(objectsToPack, base); err != nil { + // Mark this object as being resolved before looking at its base, so that + // a delta based on itself is caught by the check below. + h := otp.Hash() + visiting[h] = true + defer delete(visiting, h) + + // A delta chain that loops back onto an object we are already resolving + // cannot be written: every delta needs its base written first. Break the + // chain here instead of following the cycle, which would recurse until + // the goroutine stack is exhausted. + if visiting[do.BaseHash()] { + return dw.undeltify(otp) + } + + if err := dw.fixAndBreakChainsOne(objectsToPack, base, visiting); err != nil { return err } diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go b/vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go index 3c004f5f..ffffc2b0 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go @@ -474,6 +474,14 @@ type TreeWalker struct { recursive bool seen map[plumbing.Hash]bool + // skipPathValidation disables the pathutil.ValidTreePath check in Next. + // It is set by inspection-only callers (e.g. the revlist object walk) + // that never funnel entry names into the filesystem and must enumerate + // trees faithfully, including entries with names upstream Git accepts + // but that are unsafe to materialise (control characters, `.git`-shaped + // names). + skipPathValidation bool + s storer.EncodedObjectStorer t *Tree } @@ -496,10 +504,32 @@ func NewTreeWalker(t *Tree, recursive bool, seen map[plumbing.Hash]bool) *TreeWa } } +// SkipPathValidation disables the pathutil.ValidTreePath check performed by +// Next, and must be called before the first Next. +// +// It is for inspection-only walks that never funnel an entry name into the +// filesystem — enumerating which objects exist, rather than materialising +// them — and that must therefore see the tree faithfully, including entries +// whose names upstream Git accepts but that are unsafe to check out. Callers +// that hand the returned name to filesystem or archive output must not use +// it; path safety for those is enforced at the materialisation boundaries +// (FindEntry, TreeEntryFile, archive, FileIter). +func (w *TreeWalker) SkipPathValidation() { + w.skipPathValidation = true +} + // Next returns the next object from the tree. Objects are returned in order // and subtrees are included. After the last object has been returned further // calls to Next() will return io.EOF. // +// Each entry's name is validated against pathutil.ValidTreePath as it +// surfaces, so callers that funnel the returned name into filesystem +// or archive output can trust it is free of `.git`-shaped components, +// HFS+/NTFS variants, Windows reserved names, and traversal sequences. +// A malformed entry stops the walk with the validator's error; +// inspection-only callers that need to enumerate raw, unvalidated +// names can read Tree.Entries directly or call SkipPathValidation. +// // In the current implementation any objects which cannot be found in the // underlying repository will be skipped automatically. It is possible that this // may change in future versions. @@ -536,8 +566,10 @@ func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) { continue } - if err := pathutil.ValidTreePath(entry.Name); err != nil { - return name, entry, err + if !w.skipPathValidation { + if err := pathutil.ValidTreePath(entry.Name); err != nil { + return name, entry, err + } } if entry.Mode == filemode.Dir { diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/object/treenoder.go b/vendor/github.com/go-git/go-git/v5/plumbing/object/treenoder.go index 2adb6452..b213c841 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/object/treenoder.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/object/treenoder.go @@ -106,6 +106,12 @@ func transformChildren(t *Tree) ([]noder.Noder, error) { ret := make([]noder.Noder, 0, len(t.Entries)) walker := NewTreeWalker(t, false, nil) // don't recurse + // The diff walk is read-only and never materialises entry names into the + // filesystem, so it must enumerate the tree faithfully — including entries + // with names that are unsafe to check out but valid per upstream Git (e.g. + // control characters). Path safety is enforced at materialisation + // boundaries (FindEntry, TreeEntryFile, archive, FileIter), not here. + walker.SkipPathValidation() // don't defer walker.Close() for efficiency reasons. for { _, e, err = walker.Next() diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/revlist/revlist.go b/vendor/github.com/go-git/go-git/v5/plumbing/revlist/revlist.go index b9109870..94bdf728 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/revlist/revlist.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/revlist/revlist.go @@ -187,6 +187,13 @@ func iterateCommitTrees( cb(tree.Hash) treeWalker := object.NewTreeWalker(tree, true, seen) + // This walk only enumerates which objects are reachable, to decide what + // to send; it never materialises an entry name into the filesystem. It + // must therefore enumerate the tree faithfully, including entries with + // names that are unsafe to check out but valid per upstream Git (e.g. + // control characters). Path safety is enforced at materialisation + // boundaries (FindEntry, TreeEntryFile, archive, FileIter), not here. + treeWalker.SkipPathValidation() for { _, e, err := treeWalker.Next() diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go index 83f93f16..7fc10afc 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go @@ -6,8 +6,12 @@ import ( "context" "crypto/tls" "crypto/x509" + "errors" "fmt" + "io" + "net" "net/http" + "net/netip" "net/url" "reflect" "strconv" @@ -73,7 +77,7 @@ func advertisedReferences(ctx context.Context, s *session, serviceName string) ( s.endpoint.String(), infoRefsPath, serviceName, ) - req, err := http.NewRequest(http.MethodGet, url, nil) + req, err := newRequest(http.MethodGet, url, nil) if err != nil { return nil, err } @@ -177,6 +181,24 @@ func NewClient(c *http.Client) transport.Transport { // and other custom options specific to the client. // If the net/http client is nil or empty, it will use a net/http client configured // with http.DefaultTransport. +// +// Credentials this client adds where the transport cannot see them are not +// subject to the redirect stripping described on AuthMethod: a RoundTripper +// injects after the hop is decided, and Client.Jar is consulted after +// CheckRedirect, so a domain cookie still follows a redirect to a subdomain +// the transport counts as another origin. Apply them in an AuthMethod instead +// if that is not wanted. A CheckRedirect hook set on this client runs +// alongside the transport's own, but any header it adds when a redirect +// leaves the repository's origin is discarded the same way. +// +// A RoundTripper is therefore also how to authenticate to a new origin a +// redirect has moved the repository to: match on the request URL and inject +// the credential only for that origin, so it is not sent anywhere else. The +// transport keeps its own CheckRedirect on the copy it makes of this client, +// so the policy and the origin checks still apply. +// +// None of this applies to a RoundTripper that follows redirects itself: +// CheckRedirect is not consulted then, so no stripping happens at all. func NewClientWithOptions(c *http.Client, opts *ClientOptions) transport.Transport { if c == nil { c = &http.Client{ @@ -370,11 +392,20 @@ func (s *session) ModifyEndpointIfRedirect(res *http.Response) error { if !strings.HasSuffix(r.URL.Path, infoRefsPath) { return fmt.Errorf("http redirect: target %q does not end with %s", r.URL.Path, infoRefsPath) } - if r.URL.Scheme != "http" && r.URL.Scheme != "https" { + // A scheme is case-insensitive per RFC 3986, and checkRedirect folds case + // when it reads the same hop, so fold here too rather than reject a + // spelling that check let through. url.Parse and transport.NewEndpoint + // both lowercase what they parse, so only a hand-built URL or Endpoint + // arrives uppercased. The folded form is what gets stored below, so every + // later request built from the endpoint carries the canonical spelling. + scheme := strings.ToLower(r.URL.Scheme) + if scheme != "http" && scheme != "https" { return fmt.Errorf("http redirect: unsupported scheme %q", r.URL.Scheme) } - if r.URL.Scheme != s.endpoint.Protocol && - !(s.endpoint.Protocol == "http" && r.URL.Scheme == "https") { + // schemeUpgrade rather than an inline comparison, so the one cross-scheme + // change go-git permits has a single definition shared with + // credentialsMayFollow. + if !strings.EqualFold(scheme, s.endpoint.Protocol) && !schemeUpgrade(s.endpoint.Protocol, scheme) { return fmt.Errorf("http redirect: changes scheme from %q to %q", s.endpoint.Protocol, r.URL.Scheme) } @@ -384,7 +415,20 @@ func (s *session) ModifyEndpointIfRedirect(res *http.Response) error { return err } - if host != s.endpoint.Host || effectivePort(r.URL.Scheme, port) != effectivePort(s.endpoint.Protocol, s.endpoint.Port) { + // The session stores the endpoint and re-applies its credentials on every + // later request, so clear them once the redirect has left the origin they + // were issued for. This uses the same predicate as stripCredentials, so + // both halves share one definition of an origin. + // + // The two are deliberately asymmetric in one respect: stripCredentials is + // sticky over the whole chain, so an origin -> evil -> origin redirect + // leaves the discovery GET's later hops unauthenticated even though the + // chain returned home. This compares the endpoint only against the final + // URL, so the same round trip leaves the session authenticated. That is + // not a leak - the final URL's origin is the original one - but it means + // such a chain can make the discovery GET anonymous while the session's + // POSTs are authenticated, which can surface as a confusing 401. + if !credentialsMayFollow(endpointURL(s.endpoint), r.URL) { s.endpoint.User = "" s.endpoint.Password = "" s.auth = nil @@ -393,7 +437,7 @@ func (s *session) ModifyEndpointIfRedirect(res *http.Response) error { s.endpoint.Host = host s.endpoint.Port = port - s.endpoint.Protocol = r.URL.Scheme + s.endpoint.Protocol = scheme s.endpoint.Path = r.URL.Path[:len(r.URL.Path)-len(infoRefsPath)] return nil } @@ -419,19 +463,132 @@ func endpointPort(port string) (int, error) { return parsed, nil } -func effectivePort(scheme string, port int) int { - if port != 0 { - return port - } +// schemeUpgrade reports whether the scheme transition from one URL to another +// is the one cross-scheme change go-git permits: a plain-http origin upgrading +// to https. It strictly improves confidentiality and is how servers steer +// clients off cleartext. +// +// Permitting it at all is a deliberate deviation: curl, git and the Fetch +// standard all count scheme as part of host identity and drop credentials on +// the upgrade. Auth is sent pre-emptively here, so an http origin has already +// spent its credential in cleartext on the first request and refusing the +// upgrade would break the clone without unspending it. The host is unchanged, +// where an on-path attacker needs a valid certificate to receive anything. +func schemeUpgrade(from, to string) bool { + return strings.EqualFold(from, "http") && strings.EqualFold(to, "https") +} - switch strings.ToLower(scheme) { - case "http": - return 80 - case "https": - return 443 - default: - return 0 +// canonicalHost returns u's hostname in the form origins are compared in. +// +// An address literal is normalised by netip, so the many spellings of one +// address are one origin. Two literals are the same origin exactly when netip +// parses them to the same Addr, which is also how the WHATWG URL Standard +// compares hosts. An IPv4-mapped literal is deliberately not unmapped onto +// the IPv4 it dials: reaching the same endpoint is not the same authority, +// since net/http sends the literal as written in Host and a server may route +// the two spellings to different virtual hosts. +// +// netip also keeps a scope zone verbatim, which is what origin comparison +// needs: net resolves a zone to an interface by exact name, so folding %eth0 +// onto %ETH0 would call two hosts the same origin that net dials down +// different interfaces. +// +// A registered name is ASCII-lowercased. That fold is the only liberty taken; +// every other difference in spelling is a different origin. +// +// A trailing root dot is one such difference and is kept, for the same reason +// as the IPv4-mapped literal: curl and the WHATWG URL Standard both hold +// "example.com." and "example.com" to be distinct hosts, and although +// crypto/tls and crypto/x509 fold the dot when they authenticate the peer, +// net/http sends the name as written in Host. +// +// The fold is deliberately ASCII-only. strings.ToLower and strings.EqualFold +// apply Unicode case mapping, which folds U+03C2 onto U+03C3 and so would +// call two hosts the same origin when they resolve to different servers. An +// ASCII-only fold cannot merge two names DNS keeps apart. +// +// No IDNA mapping is applied either, so a unicode hostname is a different +// origin from the punycode encoding of it, and from another Unicode case of +// itself, even though all three reach the same server. Mapping through +// golang.org/x/net/idna would join them, but it can only widen this equality, +// never narrow it, so leaving it out can cost a credential across such a +// redirect and cannot forward one. Against that cost, go-git pins x/net while +// net/http uses the copy vendored into the toolchain: the two are versioned +// separately, so a release that moves the Unicode tables under one and not +// the other would have this merge origins net/http still dials apart. That is +// the failure this comparison exists to prevent, and comparing bytes has no +// such mode. +func canonicalHost(u *url.URL) string { + host := u.Hostname() + if addr, err := netip.ParseAddr(host); err == nil { + return addr.String() } + b := []byte(host) + for i := range b { + if b[i] >= 'A' && b[i] <= 'Z' { + b[i] += 'a' - 'A' + } + } + return string(b) +} + +// effectivePort returns u's port as the connection will use it: the scheme's +// well-known port when the URL does not spell one out, and without leading +// zeroes, so "https://x", "https://x:443" and "https://x:0443" all agree. +func effectivePort(u *url.URL) string { + port := u.Port() + if port == "" { + switch strings.ToLower(u.Scheme) { + case "http": + return "80" + case "https": + return "443" + default: + return "" + } + } + if trimmed := strings.TrimLeft(port, "0"); trimmed != "" { + return trimmed + } + return "0" +} + +// credentialsMayFollow reports whether credentials issued for one URL may be +// sent to another. +// +// The relation is deliberately asymmetric: scheme, host and effective port +// must all match, except that a plain http origin may upgrade to https on the +// same host (see schemeUpgrade). That exception is confined to the two +// default ports: 80 to 443 is the upgrade servers actually steer clients +// through, whereas a non-default port carries no such convention, so +// http://host:8080 to https://host:8443 is a move to another origin like any +// other port change. +// +// Host matching is exact. Unlike Go's http.Client, which forwards credentials +// from a host to any subdomain of it, a subdomain is a different origin here — +// matching canonical git and libcurl. +func credentialsMayFollow(from, to *url.URL) bool { + if canonicalHost(from) != canonicalHost(to) { + return false + } + if strings.EqualFold(from.Scheme, to.Scheme) { + return effectivePort(from) == effectivePort(to) + } + return schemeUpgrade(from.Scheme, to.Scheme) && + effectivePort(from) == "80" && effectivePort(to) == "443" +} + +// endpointURL renders an Endpoint's origin as a URL, so that the session's +// credential clearing and the per-hop stripping share one definition of an +// origin and cannot drift apart. +func endpointURL(ep *transport.Endpoint) *url.URL { + host := strings.Trim(ep.Host, "[]") + if ep.Port != 0 { + host = net.JoinHostPort(host, strconv.Itoa(ep.Port)) + } else if strings.Contains(host, ":") { + host = "[" + host + "]" + } + return &url.URL{Scheme: ep.Protocol, Host: host} } func (c *client) cloneHTTPClient(transport http.RoundTripper) *http.Client { @@ -448,26 +605,215 @@ func wrapCheckRedirect(policy RedirectPolicy, next func(*http.Request, []*http.R if err := checkRedirect(req, via, policy); err != nil { return err } + // Strip before the caller's hook so it observes what will actually + // be sent, and again afterwards so a hook of the common "preserve + // my headers across redirects" shape - which copies from via[0], + // the original unsanitized request - cannot reinstate them. + // Carrying credentials across an origin boundary is deliberately + // unsupported. + stripCredentials(req, via) if next != nil { - return next(req, via) + if err := next(req, via); err != nil { + return err + } } + stripCredentials(req, via) return nil } } +// safeHeaders lists the headers go-git sets itself, none of which can carry a +// caller credential. stripCredentials keeps only these when a redirect leaves +// the credential's origin. Adding a name here makes it forwardable across an +// origin boundary - do not add anything a caller can put a secret in. +// +// This narrows rather than eliminates the exposure: an AuthMethod that writes +// a credential into one of these names directly - for example +// Header.Set("User-Agent", "token "+secret) - still survives a cross-origin +// redirect. Such a value is also sent to the origin and to any proxy in path, +// so it should not be placed there whether or not a redirect follows. +var safeHeaders = map[string]struct{}{ + "User-Agent": {}, + "Host": {}, + "Accept": {}, + "Content-Type": {}, + "Content-Length": {}, +} + +func filterHeaders(h http.Header) http.Header { + filtered := make(http.Header) + for key, values := range h { + if _, ok := safeHeaders[http.CanonicalHeaderKey(key)]; ok { + filtered[key] = values + } + } + return filtered +} + +// stripCredentials removes credentials from req once the redirect chain has +// left the origin of the original, credential-bearing request. +// +// CheckRedirect is the only hook that runs while a redirected request's +// headers are still mutable: http.Client.Do performs the entire chain +// internally, so anything the transport does after Do returns - including +// ModifyEndpointIfRedirect - is too late for the hops themselves. +// +// Two subtleties: +// +// - net/http rebuilds every redirect request from the original request's +// headers before calling this, so a header removed at one hop reappears +// at the next. The decision is therefore recomputed per hop. +// - The decision is sticky: once the chain has left the origin, credentials +// stay gone even if a later hop returns to it. Stickiness is derived from +// via rather than stored, because this closure is shared across a +// session's requests. +// +// Stripping keeps only the headers go-git sets itself (safeHeaders). An +// allowlist is used rather than a list of credential header names because +// caller credentials arrive under names that cannot be enumerated - +// PRIVATE-TOKEN, X-Api-Key, gateway headers - which is exactly what +// net/http's fixed list of sensitive header names gets wrong. It is also +// immune to header-name canonicalisation: an AuthMethod that writes a raw map +// key is still removed. +func stripCredentials(req *http.Request, via []*http.Request) { + if len(via) == 0 { + return + } + // net/http sets a URL on every request it builds, and req.URL is non-nil + // by construction: checkRedirect dereferences req.URL.Scheme on each path + // that returns nil, so it runs first or not at all. This nil check and + // the two in crossedOrigin are defensive, against a synthetic caller. + // Each treats a URL it cannot read as an origin crossing; removing one + // panics in canonicalHost rather than leaking. + if origin := via[0].URL; origin != nil && !crossedOrigin(origin, req, via) { + return + } + req.Header = filterHeaders(req.Header) + if req.URL != nil { + req.URL.User = nil + } +} + +// crossedOrigin reports whether any hop so far, including the pending one, has +// left origin. +func crossedOrigin(origin *url.URL, req *http.Request, via []*http.Request) bool { + if req.URL == nil || !credentialsMayFollow(origin, req.URL) { + return true + } + for _, prev := range via[1:] { + if prev.URL == nil || !credentialsMayFollow(origin, prev.URL) { + return true + } + } + return false +} + +// redactedURL returns the string form of u with the userinfo password +// replaced, for use in error messages. (*url.URL).String() renders the +// password verbatim, and request URLs are built from the endpoint, which +// carries whatever credentials the caller put in the clone URL. +func redactedURL(u *url.URL) string { + if u == nil { + return "" + } + if u.User == nil { + return u.String() + } + if _, hasPassword := u.User.Password(); !hasPassword { + return u.String() + } + redacted := *u + redacted.User = url.UserPassword(u.User.Username(), "REDACTED") + return redacted.String() +} + +// redactedRawURL is redactedURL for a string that may not parse. Request URLs +// are assembled from Endpoint.String(), which re-emits Endpoint.Path raw, so a +// path holding a stray percent produces a string url.Parse rejects. url.Parse +// reports the input verbatim and applies no redaction of its own; only +// http.Client strips a password, and only from errors it raises itself. +func redactedRawURL(raw string) string { + i := strings.Index(raw, "://") + if i < 0 { + return raw + } + authority := raw[i+3:] + if end := strings.IndexByte(authority, '/'); end >= 0 { + authority = authority[:end] + } + at := strings.LastIndexByte(authority, '@') + if at < 0 { + return raw + } + colon := strings.IndexByte(authority[:at], ':') + if colon < 0 { + // Username only, left alone, as redactedURL leaves it. + return raw + } + return raw[:i+3+colon+1] + "REDACTED" + raw[i+3+at:] +} + +// newRequest wraps http.NewRequest so that a URL it cannot parse does not +// reach the caller with the endpoint's credentials still in it. +func newRequest(method, rawURL string, body io.Reader) (*http.Request, error) { + req, err := http.NewRequest(method, rawURL, body) + if err != nil { + var uerr *url.Error + if errors.As(err, &uerr) { + uerr.URL = redactedRawURL(uerr.URL) + } + return nil, err + } + return req, nil +} + func checkRedirect(req *http.Request, via []*http.Request, policy RedirectPolicy) error { + // CheckRedirect is the only hook that runs before the next hop leaves + // the client. ModifyEndpointIfRedirect inspects the chain after + // client.Do has followed all of it, so a hop rejected there has already + // carried the request headers to its server. + // + // The wording matches the message ModifyEndpointIfRedirect produces for + // the same hop, which this check reaches first. + if len(via) != 0 { + // A hop whose scheme cannot be read cannot be shown not to have been + // https, so it is assumed to have been, and a cleartext target is + // rejected. Skipping the comparison instead would let an + // undeterminable hop turn the check off, which is the wrong default + // for a credential control; crossedOrigin fails closed the same way. + // An empty scheme is as unreadable as a nil URL, so both take the + // assumed-https default. + // + // The comparisons fold case because a scheme is case-insensitive per + // RFC 3986. net/url lowercases what it parses, so only a hand-built + // URL reaches here uppercased - the same synthetic caller the nil + // checks guard against - and for that caller "HTTPS" to "http" is + // still a downgrade. + prevScheme := "https" + if prev := via[len(via)-1]; prev.URL != nil && prev.URL.Scheme != "" { + prevScheme = prev.URL.Scheme + } + if strings.EqualFold(prevScheme, "https") && strings.EqualFold(req.URL.Scheme, "http") { + return fmt.Errorf("http redirect: changes scheme from %q to %q: %s", + prevScheme, req.URL.Scheme, redactedURL(req.URL)) + } + } + switch policy { case FollowRedirects: case NoFollowRedirects: - return fmt.Errorf("http redirect: redirects disabled to %s", req.URL) + return fmt.Errorf("http redirect: redirects disabled to %s", redactedURL(req.URL)) case "", FollowInitialRedirects: if !isInitialRequest(req) { - return fmt.Errorf("http redirect: redirect on non-initial request to %s", req.URL) + return fmt.Errorf("http redirect: redirect on non-initial request to %s", redactedURL(req.URL)) } default: return fmt.Errorf("http redirect: invalid redirect policy %q", policy) } - if req.URL.Scheme != "http" && req.URL.Scheme != "https" { + // Folded for the same reason as the guard above: a scheme is + // case-insensitive per RFC 3986, so a spelling the downgrade check read + // as https must not be rejected here as a scheme go-git cannot speak. + if !strings.EqualFold(req.URL.Scheme, "http") && !strings.EqualFold(req.URL.Scheme, "https") { return fmt.Errorf("http redirect: unsupported scheme %q", req.URL.Scheme) } if len(via) >= 10 { @@ -481,6 +827,17 @@ func (*session) Close() error { } // AuthMethod is concrete implementation of common.AuthMethod for HTTP services +// +// Headers SetAuth adds are dropped when a redirect leaves the repository's +// origin: only the headers the transport sets itself survive that boundary. +// This applies to non-credential headers too, so an implementation that adds a +// trace or tenant header loses it on such a hop. +// +// That filter matches header names, not values. An implementation that writes +// a credential into a name the transport also uses - User-Agent, Host, Accept, +// Content-Type, Content-Length - has that value carried across the boundary +// with the name. Such a credential is also sent to the origin and to any proxy +// in path, so it should not be placed there whether or not a redirect follows. type AuthMethod interface { transport.AuthMethod SetAuth(r *http.Request) @@ -598,6 +955,6 @@ func (e *Err) StatusCode() int { func (e *Err) Error() string { return fmt.Sprintf("unexpected requesting %q status code: %d", - e.Response.Request.URL, e.Response.StatusCode, + redactedURL(e.Response.Request.URL), e.Response.StatusCode, ) } diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/receive_pack.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/receive_pack.go index 3e736cd9..92556b44 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/receive_pack.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/receive_pack.go @@ -88,7 +88,7 @@ func (s *rpSession) doRequest( body = content } - req, err := http.NewRequest(method, url, body) + req, err := newRequest(method, url, body) if err != nil { return nil, plumbing.NewPermanentError(err) } diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/upload_pack.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/upload_pack.go index 3432618a..6e43198a 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/upload_pack.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/upload_pack.go @@ -86,7 +86,7 @@ func (s *upSession) doRequest( body = content } - req, err := http.NewRequest(method, url, body) + req, err := newRequest(method, url, body) if err != nil { return nil, plumbing.NewPermanentError(err) } diff --git a/vendor/github.com/go-git/go-git/v5/repository.go b/vendor/github.com/go-git/go-git/v5/repository.go index 12af1623..7a144fa7 100644 --- a/vendor/github.com/go-git/go-git/v5/repository.go +++ b/vendor/github.com/go-git/go-git/v5/repository.go @@ -433,6 +433,7 @@ func dotGitCommonDirectory(fs billy.Filesystem) (commonDir billy.Filesystem, err if err != nil { return nil, err } + defer ioutil.CheckClose(f, &err) b, err := io.ReadAll(f) if err != nil { diff --git a/vendor/github.com/klauspost/cpuid/v2/.gitignore b/vendor/github.com/klauspost/cpuid/v2/.gitignore deleted file mode 100644 index daf913b1..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml b/vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml deleted file mode 100644 index 1b695b62..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml +++ /dev/null @@ -1,57 +0,0 @@ -version: 2 - -builds: - - - id: "cpuid" - binary: cpuid - main: ./cmd/cpuid/main.go - env: - - CGO_ENABLED=0 - flags: - - -ldflags=-s -w - goos: - - aix - - linux - - freebsd - - netbsd - - windows - - darwin - goarch: - - 386 - - amd64 - - arm64 - goarm: - - 7 - -archives: - - - id: cpuid - name_template: "cpuid-{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - format_overrides: - - goos: windows - format: zip - files: - - LICENSE -checksum: - name_template: 'checksums.txt' -changelog: - sort: asc - filters: - exclude: - - '^doc:' - - '^docs:' - - '^test:' - - '^tests:' - - '^Update\sREADME.md' - -nfpms: - - - file_name_template: "cpuid_package_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - vendor: Klaus Post - homepage: https://github.com/klauspost/cpuid - maintainer: Klaus Post - description: CPUID Tool - license: BSD 3-Clause - formats: - - deb - - rpm diff --git a/vendor/github.com/klauspost/cpuid/v2/CONTRIBUTING.txt b/vendor/github.com/klauspost/cpuid/v2/CONTRIBUTING.txt deleted file mode 100644 index 2ef4714f..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/CONTRIBUTING.txt +++ /dev/null @@ -1,35 +0,0 @@ -Developer Certificate of Origin -Version 1.1 - -Copyright (C) 2015- Klaus Post & Contributors. -Email: klauspost@gmail.com - -Everyone is permitted to copy and distribute verbatim copies of this -license document, but changing it is not allowed. - - -Developer's Certificate of Origin 1.1 - -By making a contribution to this project, I certify that: - -(a) The contribution was created in whole or in part by me and I - have the right to submit it under the open source license - indicated in the file; or - -(b) The contribution is based upon previous work that, to the best - of my knowledge, is covered under an appropriate open source - license and I have the right under that license to submit that - work with modifications, whether created in whole or in part - by me, under the same open source license (unless I am - permitted to submit under a different license), as indicated - in the file; or - -(c) The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified - it. - -(d) I understand and agree that this project and the contribution - are public and that a record of the contribution (including all - personal information I submit with it, including my sign-off) is - maintained indefinitely and may be redistributed consistent with - this project or the open source license(s) involved. diff --git a/vendor/github.com/klauspost/cpuid/v2/LICENSE b/vendor/github.com/klauspost/cpuid/v2/LICENSE deleted file mode 100644 index 5cec7ee9..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Klaus Post - -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/klauspost/cpuid/v2/README.md b/vendor/github.com/klauspost/cpuid/v2/README.md deleted file mode 100644 index 88d68d52..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/README.md +++ /dev/null @@ -1,512 +0,0 @@ -# cpuid -Package cpuid provides information about the CPU running the current program. - -CPU features are detected on startup, and kept for fast access through the life of the application. -Currently x86 / x64 (AMD64/i386) and ARM (ARM64) is supported, and no external C (cgo) code is used, which should make the library very easy to use. - -You can access the CPU information by accessing the shared CPU variable of the cpuid library. - -Package home: https://github.com/klauspost/cpuid - -[![PkgGoDev](https://pkg.go.dev/badge/github.com/klauspost/cpuid)](https://pkg.go.dev/github.com/klauspost/cpuid/v2) -[![Go](https://github.com/klauspost/cpuid/actions/workflows/go.yml/badge.svg)](https://github.com/klauspost/cpuid/actions/workflows/go.yml) - -## installing - -`go get -u github.com/klauspost/cpuid/v2` using modules. -Drop `v2` for others. - -Installing binary: - -`go install github.com/klauspost/cpuid/v2/cmd/cpuid@latest` - -Or download binaries from release page: https://github.com/klauspost/cpuid/releases - -### Homebrew - -For macOS/Linux users, you can install via [brew](https://brew.sh/) - -```sh -$ brew install cpuid -``` - -## example - -```Go -package main - -import ( - "fmt" - "strings" - - . "github.com/klauspost/cpuid/v2" -) - -func main() { - // Print basic CPU information: - fmt.Println("Name:", CPU.BrandName) - fmt.Println("PhysicalCores:", CPU.PhysicalCores) - fmt.Println("ThreadsPerCore:", CPU.ThreadsPerCore) - fmt.Println("LogicalCores:", CPU.LogicalCores) - fmt.Println("Family", CPU.Family, "Model:", CPU.Model, "Vendor ID:", CPU.VendorID) - fmt.Println("Features:", strings.Join(CPU.FeatureSet(), ",")) - fmt.Println("Cacheline bytes:", CPU.CacheLine) - fmt.Println("L1 Data Cache:", CPU.Cache.L1D, "bytes") - fmt.Println("L1 Instruction Cache:", CPU.Cache.L1I, "bytes") - fmt.Println("L2 Cache:", CPU.Cache.L2, "bytes") - fmt.Println("L3 Cache:", CPU.Cache.L3, "bytes") - fmt.Println("Frequency", CPU.Hz, "hz") - - // Test if we have these specific features: - if CPU.Supports(SSE, SSE2) { - fmt.Println("We have Streaming SIMD 2 Extensions") - } -} -``` - -Sample output: -``` ->go run main.go -Name: AMD Ryzen 9 3950X 16-Core Processor -PhysicalCores: 16 -ThreadsPerCore: 2 -LogicalCores: 32 -Family 23 Model: 113 Vendor ID: AMD -Features: ADX,AESNI,AVX,AVX2,BMI1,BMI2,CLMUL,CMOV,CX16,F16C,FMA3,HTT,HYPERVISOR,LZCNT,MMX,MMXEXT,NX,POPCNT,RDRAND,RDSEED,RDTSCP,SHA,SSE,SSE2,SSE3,SSE4,SSE42,SSE4A,SSSE3 -Cacheline bytes: 64 -L1 Data Cache: 32768 bytes -L1 Instruction Cache: 32768 bytes -L2 Cache: 524288 bytes -L3 Cache: 16777216 bytes -Frequency 0 hz -We have Streaming SIMD 2 Extensions -``` - -# usage - -The `cpuid.CPU` provides access to CPU features. Use `cpuid.CPU.Supports()` to check for CPU features. -A faster `cpuid.CPU.Has()` is provided which will usually be inlined by the gc compiler. - -To test a larger number of features, they can be combined using `f := CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SYSCALL, SSE, SSE2)`, etc. -This can be using with `cpuid.CPU.HasAll(f)` to quickly test if all features are supported. - -Note that for some cpu/os combinations some features will not be detected. -`amd64` has rather good support and should work reliably on all platforms. - -Note that hypervisors may not pass through all CPU features through to the guest OS, -so even if your host supports a feature it may not be visible on guests. - -## arm64 feature detection - -Not all operating systems provide ARM features directly -and there is no safe way to do so for the rest. - -Currently `arm64/linux` and `arm64/freebsd` should be quite reliable. -`arm64/darwin` adds features expected from the M1 processor, but a lot remains undetected. - -A `DetectARM()` can be used if you are able to control your deployment, -it will detect CPU features, but may crash if the OS doesn't intercept the calls. -A `-cpu.arm` flag for detecting unsafe ARM features can be added. See below. - -Note that currently only features are detected on ARM, -no additional information is currently available. - -## flags - -It is possible to add flags that affects cpu detection. - -For this the `Flags()` command is provided. - -This must be called *before* `flag.Parse()` AND after the flags have been parsed `Detect()` must be called. - -This means that any detection used in `init()` functions will not contain these flags. - -Example: - -```Go -package main - -import ( - "flag" - "fmt" - "strings" - - "github.com/klauspost/cpuid/v2" -) - -func main() { - cpuid.Flags() - flag.Parse() - cpuid.Detect() - - // Test if we have these specific features: - if cpuid.CPU.Supports(cpuid.SSE, cpuid.SSE2) { - fmt.Println("We have Streaming SIMD 2 Extensions") - } -} -``` - -## commandline - -Download as binary from: https://github.com/klauspost/cpuid/releases - -Install from source: - -`go install github.com/klauspost/cpuid/v2/cmd/cpuid@latest` - -### Example - -``` -λ cpuid -Name: AMD Ryzen 9 3950X 16-Core Processor -Vendor String: AuthenticAMD -Vendor ID: AMD -PhysicalCores: 16 -Threads Per Core: 2 -Logical Cores: 32 -CPU Family 23 Model: 113 -Features: ADX,AESNI,AVX,AVX2,BMI1,BMI2,CLMUL,CLZERO,CMOV,CMPXCHG8,CPBOOST,CX16,F16C,FMA3,FXSR,FXSROPT,HTT,HYPERVISOR,LAHF,LZCNT,MCAOVERFLOW,MMX,MMXEXT,MOVBE,NX,OSXSAVE,POPCNT,RDRAND,RDSEED,RDTSCP,SCE,SHA,SSE,SSE2,SSE3,SSE4,SSE42,SSE4A,SSSE3,SUCCOR,X87,XSAVE -Microarchitecture level: 3 -Cacheline bytes: 64 -L1 Instruction Cache: 32768 bytes -L1 Data Cache: 32768 bytes -L2 Cache: 524288 bytes -L3 Cache: 16777216 bytes - -``` -### JSON Output: - -``` -λ cpuid --json -{ - "BrandName": "AMD Ryzen 9 3950X 16-Core Processor", - "VendorID": 2, - "VendorString": "AuthenticAMD", - "PhysicalCores": 16, - "ThreadsPerCore": 2, - "LogicalCores": 32, - "Family": 23, - "Model": 113, - "CacheLine": 64, - "Hz": 0, - "BoostFreq": 0, - "Cache": { - "L1I": 32768, - "L1D": 32768, - "L2": 524288, - "L3": 16777216 - }, - "SGX": { - "Available": false, - "LaunchControl": false, - "SGX1Supported": false, - "SGX2Supported": false, - "MaxEnclaveSizeNot64": 0, - "MaxEnclaveSize64": 0, - "EPCSections": null - }, - "Features": [ - "ADX", - "AESNI", - "AVX", - "AVX2", - "BMI1", - "BMI2", - "CLMUL", - "CLZERO", - "CMOV", - "CMPXCHG8", - "CPBOOST", - "CX16", - "F16C", - "FMA3", - "FXSR", - "FXSROPT", - "HTT", - "HYPERVISOR", - "LAHF", - "LZCNT", - "MCAOVERFLOW", - "MMX", - "MMXEXT", - "MOVBE", - "NX", - "OSXSAVE", - "POPCNT", - "RDRAND", - "RDSEED", - "RDTSCP", - "SCE", - "SHA", - "SSE", - "SSE2", - "SSE3", - "SSE4", - "SSE42", - "SSE4A", - "SSSE3", - "SUCCOR", - "X87", - "XSAVE" - ], - "X64Level": 3 -} -``` - -### Check CPU microarch level - -``` -λ cpuid --check-level=3 -2022/03/18 17:04:40 AMD Ryzen 9 3950X 16-Core Processor -2022/03/18 17:04:40 Microarchitecture level 3 is supported. Max level is 3. -Exit Code 0 - -λ cpuid --check-level=4 -2022/03/18 17:06:18 AMD Ryzen 9 3950X 16-Core Processor -2022/03/18 17:06:18 Microarchitecture level 4 not supported. Max level is 3. -Exit Code 1 -``` - - -## Available flags - -### x86 & amd64 - -| Feature Flag | Description | -|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| ADX | Intel ADX (Multi-Precision Add-Carry Instruction Extensions) | -| AESNI | Advanced Encryption Standard New Instructions | -| AMD3DNOW | AMD 3DNOW | -| AMD3DNOWEXT | AMD 3DNowExt | -| AMXBF16 | Tile computational operations on BFLOAT16 numbers | -| AMXINT8 | Tile computational operations on 8-bit integers | -| AMXFP16 | Tile computational operations on FP16 numbers | -| AMXFP8 | Tile computational operations on FP8 numbers | -| AMXCOMPLEX | Tile computational operations on complex numbers | -| AMXTILE | Tile architecture | -| AMXTF32 | Matrix Multiplication of TF32 Tiles into Packed Single Precision Tile | -| AMXTRANSPOSE | Tile multiply where the first operand is transposed | -| APX_F | Intel APX | -| AVX | AVX functions | -| AVX10 | If set the Intel AVX10 Converged Vector ISA is supported | -| AVX10_128 | If set indicates that AVX10 128-bit vector support is present | -| AVX10_256 | If set indicates that AVX10 256-bit vector support is present | -| AVX10_512 | If set indicates that AVX10 512-bit vector support is present | -| AVX2 | AVX2 functions | -| AVX512BF16 | AVX-512 BFLOAT16 Instructions | -| AVX512BITALG | AVX-512 Bit Algorithms | -| AVX512BW | AVX-512 Byte and Word Instructions | -| AVX512CD | AVX-512 Conflict Detection Instructions | -| AVX512DQ | AVX-512 Doubleword and Quadword Instructions | -| AVX512ER | AVX-512 Exponential and Reciprocal Instructions | -| AVX512F | AVX-512 Foundation | -| AVX512FP16 | AVX-512 FP16 Instructions | -| AVX512IFMA | AVX-512 Integer Fused Multiply-Add Instructions | -| AVX512PF | AVX-512 Prefetch Instructions | -| AVX512VBMI | AVX-512 Vector Bit Manipulation Instructions | -| AVX512VBMI2 | AVX-512 Vector Bit Manipulation Instructions, Version 2 | -| AVX512VL | AVX-512 Vector Length Extensions | -| AVX512VNNI | AVX-512 Vector Neural Network Instructions | -| AVX512VP2INTERSECT | AVX-512 Intersect for D/Q | -| AVX512VPOPCNTDQ | AVX-512 Vector Population Count Doubleword and Quadword | -| AVXIFMA | AVX-IFMA instructions | -| AVXNECONVERT | AVX-NE-CONVERT instructions | -| AVXSLOW | Indicates the CPU performs 2 128 bit operations instead of one | -| AVXVNNI | AVX (VEX encoded) VNNI neural network instructions | -| AVXVNNIINT8 | AVX-VNNI-INT8 instructions | -| AVXVNNIINT16 | AVX-VNNI-INT16 instructions | -| BHI_CTRL | Branch History Injection and Intra-mode Branch Target Injection / CVE-2022-0001, CVE-2022-0002 / INTEL-SA-00598 | -| BMI1 | Bit Manipulation Instruction Set 1 | -| BMI2 | Bit Manipulation Instruction Set 2 | -| CETIBT | Intel CET Indirect Branch Tracking | -| CETSS | Intel CET Shadow Stack | -| CLDEMOTE | Cache Line Demote | -| CLMUL | Carry-less Multiplication | -| CLZERO | CLZERO instruction supported | -| CMOV | i686 CMOV | -| CMPCCXADD | CMPCCXADD instructions | -| CMPSB_SCADBS_SHORT | Fast short CMPSB and SCASB | -| CMPXCHG8 | CMPXCHG8 instruction | -| CPBOOST | Core Performance Boost | -| CPPC | AMD: Collaborative Processor Performance Control | -| CX16 | CMPXCHG16B Instruction | -| EFER_LMSLE_UNS | AMD: =Core::X86::Msr::EFER[LMSLE] is not supported, and MBZ | -| ENQCMD | Enqueue Command | -| ERMS | Enhanced REP MOVSB/STOSB | -| F16C | Half-precision floating-point conversion | -| FLUSH_L1D | Flush L1D cache | -| FMA3 | Intel FMA 3. Does not imply AVX. | -| FMA4 | Bulldozer FMA4 functions | -| FP128 | AMD: When set, the internal FP/SIMD execution datapath is 128-bits wide | -| FP256 | AMD: When set, the internal FP/SIMD execution datapath is 256-bits wide | -| FSRM | Fast Short Rep Mov | -| FXSR | FXSAVE, FXRESTOR instructions, CR4 bit 9 | -| FXSROPT | FXSAVE/FXRSTOR optimizations | -| GFNI | Galois Field New Instructions. May require other features (AVX, AVX512VL,AVX512F) based on usage. | -| HLE | Hardware Lock Elision | -| HRESET | If set CPU supports history reset and the IA32_HRESET_ENABLE MSR | -| HTT | Hyperthreading (enabled) | -| HWA | Hardware assert supported. Indicates support for MSRC001_10 | -| HYBRID_CPU | This part has CPUs of more than one type. | -| HYPERVISOR | This bit has been reserved by Intel & AMD for use by hypervisors | -| IA32_ARCH_CAP | IA32_ARCH_CAPABILITIES MSR (Intel) | -| IA32_CORE_CAP | IA32_CORE_CAPABILITIES MSR | -| IBPB | Indirect Branch Restricted Speculation (IBRS) and Indirect Branch Predictor Barrier (IBPB) | -| IBRS | AMD: Indirect Branch Restricted Speculation | -| IBRS_PREFERRED | AMD: IBRS is preferred over software solution | -| IBRS_PROVIDES_SMP | AMD: IBRS provides Same Mode Protection | -| IBS | Instruction Based Sampling (AMD) | -| IBSBRNTRGT | Instruction Based Sampling Feature (AMD) | -| IBSFETCHSAM | Instruction Based Sampling Feature (AMD) | -| IBSFFV | Instruction Based Sampling Feature (AMD) | -| IBSOPCNT | Instruction Based Sampling Feature (AMD) | -| IBSOPCNTEXT | Instruction Based Sampling Feature (AMD) | -| IBSOPSAM | Instruction Based Sampling Feature (AMD) | -| IBSRDWROPCNT | Instruction Based Sampling Feature (AMD) | -| IBSRIPINVALIDCHK | Instruction Based Sampling Feature (AMD) | -| IBS_FETCH_CTLX | AMD: IBS fetch control extended MSR supported | -| IBS_OPDATA4 | AMD: IBS op data 4 MSR supported | -| IBS_OPFUSE | AMD: Indicates support for IbsOpFuse | -| IBS_PREVENTHOST | Disallowing IBS use by the host supported | -| IBS_ZEN4 | Fetch and Op IBS support IBS extensions added with Zen4 | -| IDPRED_CTRL | IPRED_DIS | -| INT_WBINVD | WBINVD/WBNOINVD are interruptible. | -| INVLPGB | NVLPGB and TLBSYNC instruction supported | -| KEYLOCKER | Key locker | -| KEYLOCKERW | Key locker wide | -| LAHF | LAHF/SAHF in long mode | -| LAM | If set, CPU supports Linear Address Masking | -| LBRVIRT | LBR virtualization | -| LZCNT | LZCNT instruction | -| MCAOVERFLOW | MCA overflow recovery support. | -| MCDT_NO | Processor do not exhibit MXCSR Configuration Dependent Timing behavior and do not need to mitigate it. | -| MCOMMIT | MCOMMIT instruction supported | -| MD_CLEAR | VERW clears CPU buffers | -| MMX | standard MMX | -| MMXEXT | SSE integer functions or AMD MMX ext | -| MOVBE | MOVBE instruction (big-endian) | -| MOVDIR64B | Move 64 Bytes as Direct Store | -| MOVDIRI | Move Doubleword as Direct Store | -| MOVSB_ZL | Fast Zero-Length MOVSB | -| MPX | Intel MPX (Memory Protection Extensions) | -| MOVU | MOVU SSE instructions are more efficient and should be preferred to SSE MOVL/MOVH. MOVUPS is more efficient than MOVLPS/MOVHPS. MOVUPD is more efficient than MOVLPD/MOVHPD | -| MSRIRC | Instruction Retired Counter MSR available | -| MSRLIST | Read/Write List of Model Specific Registers | -| MSR_PAGEFLUSH | Page Flush MSR available | -| NRIPS | Indicates support for NRIP save on VMEXIT | -| NX | NX (No-Execute) bit | -| OSXSAVE | XSAVE enabled by OS | -| PCONFIG | PCONFIG for Intel Multi-Key Total Memory Encryption | -| POPCNT | POPCNT instruction | -| PPIN | AMD: Protected Processor Inventory Number support. Indicates that Protected Processor Inventory Number (PPIN) capability can be enabled | -| PREFETCHI | PREFETCHIT0/1 instructions | -| PSFD | Predictive Store Forward Disable | -| RDPRU | RDPRU instruction supported | -| RDRAND | RDRAND instruction is available | -| RDSEED | RDSEED instruction is available | -| RDTSCP | RDTSCP Instruction | -| RRSBA_CTRL | Restricted RSB Alternate | -| RTM | Restricted Transactional Memory | -| RTM_ALWAYS_ABORT | Indicates that the loaded microcode is forcing RTM abort. | -| SERIALIZE | Serialize Instruction Execution | -| SEV | AMD Secure Encrypted Virtualization supported | -| SEV_64BIT | AMD SEV guest execution only allowed from a 64-bit host | -| SEV_ALTERNATIVE | AMD SEV Alternate Injection supported | -| SEV_DEBUGSWAP | Full debug state swap supported for SEV-ES guests | -| SEV_ES | AMD SEV Encrypted State supported | -| SEV_RESTRICTED | AMD SEV Restricted Injection supported | -| SEV_SNP | AMD SEV Secure Nested Paging supported | -| SGX | Software Guard Extensions | -| SGXLC | Software Guard Extensions Launch Control | -| SGXPQC | Software Guard Extensions 256-bit Encryption | -| SHA | Intel SHA Extensions | -| SME | AMD Secure Memory Encryption supported | -| SME_COHERENT | AMD Hardware cache coherency across encryption domains enforced | -| SM3_X86 | SM3 instructions | -| SM4_X86 | SM4 instructions | -| SPEC_CTRL_SSBD | Speculative Store Bypass Disable | -| SRBDS_CTRL | SRBDS mitigation MSR available | -| SSE | SSE functions | -| SSE2 | P4 SSE functions | -| SSE3 | Prescott SSE3 functions | -| SSE4 | Penryn SSE4.1 functions | -| SSE42 | Nehalem SSE4.2 functions | -| SSE4A | AMD Barcelona microarchitecture SSE4a instructions | -| SSSE3 | Conroe SSSE3 functions | -| STIBP | Single Thread Indirect Branch Predictors | -| STIBP_ALWAYSON | AMD: Single Thread Indirect Branch Prediction Mode has Enhanced Performance and may be left Always On | -| STOSB_SHORT | Fast short STOSB | -| SUCCOR | Software uncorrectable error containment and recovery capability. | -| SVM | AMD Secure Virtual Machine | -| SVMDA | Indicates support for the SVM decode assists. | -| SVMFBASID | SVM, Indicates that TLB flush events, including CR3 writes and CR4.PGE toggles, flush only the current ASID's TLB entries. Also indicates support for the extended VMCBTLB_Control | -| SVML | AMD SVM lock. Indicates support for SVM-Lock. | -| SVMNP | AMD SVM nested paging | -| SVMPF | SVM pause intercept filter. Indicates support for the pause intercept filter | -| SVMPFT | SVM PAUSE filter threshold. Indicates support for the PAUSE filter cycle count threshold | -| SYSCALL | System-Call Extension (SCE): SYSCALL and SYSRET instructions. | -| SYSEE | SYSENTER and SYSEXIT instructions | -| TBM | AMD Trailing Bit Manipulation | -| TDX_GUEST | Intel Trust Domain Extensions Guest | -| TLB_FLUSH_NESTED | AMD: Flushing includes all the nested translations for guest translations | -| TME | Intel Total Memory Encryption. The following MSRs are supported: IA32_TME_CAPABILITY, IA32_TME_ACTIVATE, IA32_TME_EXCLUDE_MASK, and IA32_TME_EXCLUDE_BASE. | -| TOPEXT | TopologyExtensions: topology extensions support. Indicates support for CPUID Fn8000_001D_EAX_x[N:0]-CPUID Fn8000_001E_EDX. | -| TSA_L1_NO | AMD only: Not vulnerable to TSA-L1 | -| TSA_SQ_NO | AMD only: Not vulnerable to TSA-SQ | -| TSA_VERW_CLEAR | AMD: If set, the memory form of the VERW instruction may be used to help mitigate TSA | -| TSCRATEMSR | MSR based TSC rate control. Indicates support for MSR TSC ratio MSRC000_0104 | -| TSXLDTRK | Intel TSX Suspend Load Address Tracking | -| VAES | Vector AES. AVX(512) versions requires additional checks. | -| VMCBCLEAN | VMCB clean bits. Indicates support for VMCB clean bits. | -| VMPL | AMD VM Permission Levels supported | -| VMSA_REGPROT | AMD VMSA Register Protection supported | -| VMX | Virtual Machine Extensions | -| VPCLMULQDQ | Carry-Less Multiplication Quadword. Requires AVX for 3 register versions. | -| VTE | AMD Virtual Transparent Encryption supported | -| WAITPKG | TPAUSE, UMONITOR, UMWAIT | -| WBNOINVD | Write Back and Do Not Invalidate Cache | -| WRMSRNS | Non-Serializing Write to Model Specific Register | -| X87 | FPU | -| XGETBV1 | Supports XGETBV with ECX = 1 | -| XOP | Bulldozer XOP functions | -| XSAVE | XSAVE, XRESTOR, XSETBV, XGETBV | -| XSAVEC | Supports XSAVEC and the compacted form of XRSTOR. | -| XSAVEOPT | XSAVEOPT available | -| XSAVES | Supports XSAVES/XRSTORS and IA32_XSS | - -# ARM features: - -| Feature Flag | Description | -|--------------|------------------------------------------------------------------| -| AESARM | AES instructions | -| ARMCPUID | Some CPU ID registers readable at user-level | -| ASIMD | Advanced SIMD | -| ASIMDDP | SIMD Dot Product | -| ASIMDHP | Advanced SIMD half-precision floating point | -| ASIMDRDM | Rounding Double Multiply Accumulate/Subtract (SQRDMLAH/SQRDMLSH) | -| ATOMICS | Large System Extensions (LSE) | -| CRC32 | CRC32/CRC32C instructions | -| DCPOP | Data cache clean to Point of Persistence (DC CVAP) | -| EVTSTRM | Generic timer | -| FCMA | Floatin point complex number addition and multiplication | -| FHM | FMLAL and FMLSL instructions | -| FP | Single-precision and double-precision floating point | -| FPHP | Half-precision floating point | -| GPA | Generic Pointer Authentication | -| JSCVT | Javascript-style double->int convert (FJCVTZS) | -| LRCPC | Weaker release consistency (LDAPR, etc) | -| PMULL | Polynomial Multiply instructions (PMULL/PMULL2) | -| RNDR | Random Number instructions | -| TLB | Outer Shareable and TLB range maintenance instructions | -| TS | Flag manipulation instructions | -| SHA1 | SHA-1 instructions (SHA1C, etc) | -| SHA2 | SHA-2 instructions (SHA256H, etc) | -| SHA3 | SHA-3 instructions (EOR3, RAXI, XAR, BCAX) | -| SHA512 | SHA512 instructions | -| SM3 | SM3 instructions | -| SM4 | SM4 instructions | -| SVE | Scalable Vector Extension | - -# license - -This code is published under an MIT license. See LICENSE file for more information. diff --git a/vendor/github.com/klauspost/cpuid/v2/cpuid.go b/vendor/github.com/klauspost/cpuid/v2/cpuid.go deleted file mode 100644 index 9cf7738a..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/cpuid.go +++ /dev/null @@ -1,1679 +0,0 @@ -// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. - -// Package cpuid provides information about the CPU running the current program. -// -// CPU features are detected on startup, and kept for fast access through the life of the application. -// Currently x86 / x64 (AMD64) as well as arm64 is supported. -// -// You can access the CPU information by accessing the shared CPU variable of the cpuid library. -// -// Package home: https://github.com/klauspost/cpuid -package cpuid - -import ( - "flag" - "fmt" - "math" - "math/bits" - "os" - "runtime" - "strings" -) - -// AMD refererence: https://www.amd.com/system/files/TechDocs/25481.pdf -// and Processor Programming Reference (PPR) - -// Vendor is a representation of a CPU vendor. -type Vendor int - -const ( - VendorUnknown Vendor = iota - Intel - AMD - VIA - Transmeta - NSC - KVM // Kernel-based Virtual Machine - MSVM // Microsoft Hyper-V or Windows Virtual PC - VMware - XenHVM - Bhyve - Hygon - SiS - RDC - - Ampere - ARM - Broadcom - Cavium - DEC - Fujitsu - Infineon - Motorola - NVIDIA - AMCC - Qualcomm - Marvell - - QEMU - QNX - ACRN - SRE - Apple - - lastVendor -) - -//go:generate stringer -type=FeatureID,Vendor - -// FeatureID is the ID of a specific cpu feature. -type FeatureID int - -const ( - // Keep index -1 as unknown - UNKNOWN = -1 - - // x86 features - ADX FeatureID = iota // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) - AESNI // Advanced Encryption Standard New Instructions - AMD3DNOW // AMD 3DNOW - AMD3DNOWEXT // AMD 3DNowExt - AMXBF16 // Tile computational operations on BFLOAT16 numbers - AMXFP16 // Tile computational operations on FP16 numbers - AMXINT8 // Tile computational operations on 8-bit integers - AMXFP8 // Tile computational operations on FP8 numbers - AMXTILE // Tile architecture - AMXTF32 // Tile architecture - AMXCOMPLEX // Matrix Multiplication of TF32 Tiles into Packed Single Precision Tile - AMXTRANSPOSE // Tile multiply where the first operand is transposed - APX_F // Intel APX - AVX // AVX functions - AVX10 // If set the Intel AVX10 Converged Vector ISA is supported - AVX10_128 // If set indicates that AVX10 128-bit vector support is present - AVX10_256 // If set indicates that AVX10 256-bit vector support is present - AVX10_512 // If set indicates that AVX10 512-bit vector support is present - AVX2 // AVX2 functions - AVX512BF16 // AVX-512 BFLOAT16 Instructions - AVX512BITALG // AVX-512 Bit Algorithms - AVX512BW // AVX-512 Byte and Word Instructions - AVX512CD // AVX-512 Conflict Detection Instructions - AVX512DQ // AVX-512 Doubleword and Quadword Instructions - AVX512ER // AVX-512 Exponential and Reciprocal Instructions - AVX512F // AVX-512 Foundation - AVX512FP16 // AVX-512 FP16 Instructions - AVX512IFMA // AVX-512 Integer Fused Multiply-Add Instructions - AVX512PF // AVX-512 Prefetch Instructions - AVX512VBMI // AVX-512 Vector Bit Manipulation Instructions - AVX512VBMI2 // AVX-512 Vector Bit Manipulation Instructions, Version 2 - AVX512VL // AVX-512 Vector Length Extensions - AVX512VNNI // AVX-512 Vector Neural Network Instructions - AVX512VP2INTERSECT // AVX-512 Intersect for D/Q - AVX512VPOPCNTDQ // AVX-512 Vector Population Count Doubleword and Quadword - AVXIFMA // AVX-IFMA instructions - AVXNECONVERT // AVX-NE-CONVERT instructions - AVXSLOW // Indicates the CPU performs 2 128 bit operations instead of one - AVXVNNI // AVX (VEX encoded) VNNI neural network instructions - AVXVNNIINT8 // AVX-VNNI-INT8 instructions - AVXVNNIINT16 // AVX-VNNI-INT16 instructions - BHI_CTRL // Branch History Injection and Intra-mode Branch Target Injection / CVE-2022-0001, CVE-2022-0002 / INTEL-SA-00598 - BMI1 // Bit Manipulation Instruction Set 1 - BMI2 // Bit Manipulation Instruction Set 2 - CETIBT // Intel CET Indirect Branch Tracking - CETSS // Intel CET Shadow Stack - CLDEMOTE // Cache Line Demote - CLMUL // Carry-less Multiplication - CLZERO // CLZERO instruction supported - CMOV // i686 CMOV - CMPCCXADD // CMPCCXADD instructions - CMPSB_SCADBS_SHORT // Fast short CMPSB and SCASB - CMPXCHG8 // CMPXCHG8 instruction - CPBOOST // Core Performance Boost - CPPC // AMD: Collaborative Processor Performance Control - CX16 // CMPXCHG16B Instruction - EFER_LMSLE_UNS // AMD: =Core::X86::Msr::EFER[LMSLE] is not supported, and MBZ - ENQCMD // Enqueue Command - ERMS // Enhanced REP MOVSB/STOSB - F16C // Half-precision floating-point conversion - FLUSH_L1D // Flush L1D cache - FMA3 // Intel FMA 3. Does not imply AVX. - FMA4 // Bulldozer FMA4 functions - FP128 // AMD: When set, the internal FP/SIMD execution datapath is no more than 128-bits wide - FP256 // AMD: When set, the internal FP/SIMD execution datapath is no more than 256-bits wide - FSRM // Fast Short Rep Mov - FXSR // FXSAVE, FXRESTOR instructions, CR4 bit 9 - FXSROPT // FXSAVE/FXRSTOR optimizations - GFNI // Galois Field New Instructions. May require other features (AVX, AVX512VL,AVX512F) based on usage. - HLE // Hardware Lock Elision - HRESET // If set CPU supports history reset and the IA32_HRESET_ENABLE MSR - HTT // Hyperthreading (enabled) - HWA // Hardware assert supported. Indicates support for MSRC001_10 - HYBRID_CPU // This part has CPUs of more than one type. - HYPERVISOR // This bit has been reserved by Intel & AMD for use by hypervisors - IA32_ARCH_CAP // IA32_ARCH_CAPABILITIES MSR (Intel) - IA32_CORE_CAP // IA32_CORE_CAPABILITIES MSR - IBPB // Indirect Branch Restricted Speculation (IBRS) and Indirect Branch Predictor Barrier (IBPB) - IBPB_BRTYPE // Indicates that MSR 49h (PRED_CMD) bit 0 (IBPB) flushes all branch type predictions from the CPU branch predictor - IBRS // AMD: Indirect Branch Restricted Speculation - IBRS_PREFERRED // AMD: IBRS is preferred over software solution - IBRS_PROVIDES_SMP // AMD: IBRS provides Same Mode Protection - IBS // Instruction Based Sampling (AMD) - IBSBRNTRGT // Instruction Based Sampling Feature (AMD) - IBSFETCHSAM // Instruction Based Sampling Feature (AMD) - IBSFFV // Instruction Based Sampling Feature (AMD) - IBSOPCNT // Instruction Based Sampling Feature (AMD) - IBSOPCNTEXT // Instruction Based Sampling Feature (AMD) - IBSOPSAM // Instruction Based Sampling Feature (AMD) - IBSRDWROPCNT // Instruction Based Sampling Feature (AMD) - IBSRIPINVALIDCHK // Instruction Based Sampling Feature (AMD) - IBS_FETCH_CTLX // AMD: IBS fetch control extended MSR supported - IBS_OPDATA4 // AMD: IBS op data 4 MSR supported - IBS_OPFUSE // AMD: Indicates support for IbsOpFuse - IBS_PREVENTHOST // Disallowing IBS use by the host supported - IBS_ZEN4 // AMD: Fetch and Op IBS support IBS extensions added with Zen4 - IDPRED_CTRL // IPRED_DIS - INT_WBINVD // WBINVD/WBNOINVD are interruptible. - INVLPGB // NVLPGB and TLBSYNC instruction supported - KEYLOCKER // Key locker - KEYLOCKERW // Key locker wide - LAHF // LAHF/SAHF in long mode - LAM // If set, CPU supports Linear Address Masking - LBRVIRT // LBR virtualization - LZCNT // LZCNT instruction - MCAOVERFLOW // MCA overflow recovery support. - MCDT_NO // Processor do not exhibit MXCSR Configuration Dependent Timing behavior and do not need to mitigate it. - MCOMMIT // MCOMMIT instruction supported - MD_CLEAR // VERW clears CPU buffers - MMX // standard MMX - MMXEXT // SSE integer functions or AMD MMX ext - MOVBE // MOVBE instruction (big-endian) - MOVDIR64B // Move 64 Bytes as Direct Store - MOVDIRI // Move Doubleword as Direct Store - MOVSB_ZL // Fast Zero-Length MOVSB - MOVU // AMD: MOVU SSE instructions are more efficient and should be preferred to SSE MOVL/MOVH. MOVUPS is more efficient than MOVLPS/MOVHPS. MOVUPD is more efficient than MOVLPD/MOVHPD - MPX // Intel MPX (Memory Protection Extensions) - MSRIRC // Instruction Retired Counter MSR available - MSRLIST // Read/Write List of Model Specific Registers - MSR_PAGEFLUSH // Page Flush MSR available - NRIPS // Indicates support for NRIP save on VMEXIT - NX // NX (No-Execute) bit - OSXSAVE // XSAVE enabled by OS - PCONFIG // PCONFIG for Intel Multi-Key Total Memory Encryption - POPCNT // POPCNT instruction - PPIN // AMD: Protected Processor Inventory Number support. Indicates that Protected Processor Inventory Number (PPIN) capability can be enabled - PREFETCHI // PREFETCHIT0/1 instructions - PSFD // Predictive Store Forward Disable - RDPRU // RDPRU instruction supported - RDRAND // RDRAND instruction is available - RDSEED // RDSEED instruction is available - RDTSCP // RDTSCP Instruction - RRSBA_CTRL // Restricted RSB Alternate - RTM // Restricted Transactional Memory - RTM_ALWAYS_ABORT // Indicates that the loaded microcode is forcing RTM abort. - SBPB // Indicates support for the Selective Branch Predictor Barrier - SERIALIZE // Serialize Instruction Execution - SEV // AMD Secure Encrypted Virtualization supported - SEV_64BIT // AMD SEV guest execution only allowed from a 64-bit host - SEV_ALTERNATIVE // AMD SEV Alternate Injection supported - SEV_DEBUGSWAP // Full debug state swap supported for SEV-ES guests - SEV_ES // AMD SEV Encrypted State supported - SEV_RESTRICTED // AMD SEV Restricted Injection supported - SEV_SNP // AMD SEV Secure Nested Paging supported - SGX // Software Guard Extensions - SGXLC // Software Guard Extensions Launch Control - SGXPQC // Software Guard Extensions 256-bit Encryption - SHA // Intel SHA Extensions - SME // AMD Secure Memory Encryption supported - SME_COHERENT // AMD Hardware cache coherency across encryption domains enforced - SM3_X86 // SM3 instructions - SM4_X86 // SM4 instructions - SPEC_CTRL_SSBD // Speculative Store Bypass Disable - SRBDS_CTRL // SRBDS mitigation MSR available - SRSO_MSR_FIX // Indicates that software may use MSR BP_CFG[BpSpecReduce] to mitigate SRSO. - SRSO_NO // Indicates the CPU is not subject to the SRSO vulnerability - SRSO_USER_KERNEL_NO // Indicates the CPU is not subject to the SRSO vulnerability across user/kernel boundaries - SSE // SSE functions - SSE2 // P4 SSE functions - SSE3 // Prescott SSE3 functions - SSE4 // Penryn SSE4.1 functions - SSE42 // Nehalem SSE4.2 functions - SSE4A // AMD Barcelona microarchitecture SSE4a instructions - SSSE3 // Conroe SSSE3 functions - STIBP // Single Thread Indirect Branch Predictors - STIBP_ALWAYSON // AMD: Single Thread Indirect Branch Prediction Mode has Enhanced Performance and may be left Always On - STOSB_SHORT // Fast short STOSB - SUCCOR // Software uncorrectable error containment and recovery capability. - SVM // AMD Secure Virtual Machine - SVMDA // Indicates support for the SVM decode assists. - SVMFBASID // SVM, Indicates that TLB flush events, including CR3 writes and CR4.PGE toggles, flush only the current ASID's TLB entries. Also indicates support for the extended VMCBTLB_Control - SVML // AMD SVM lock. Indicates support for SVM-Lock. - SVMNP // AMD SVM nested paging - SVMPF // SVM pause intercept filter. Indicates support for the pause intercept filter - SVMPFT // SVM PAUSE filter threshold. Indicates support for the PAUSE filter cycle count threshold - SYSCALL // System-Call Extension (SCE): SYSCALL and SYSRET instructions. - SYSEE // SYSENTER and SYSEXIT instructions - TBM // AMD Trailing Bit Manipulation - TDX_GUEST // Intel Trust Domain Extensions Guest - TLB_FLUSH_NESTED // AMD: Flushing includes all the nested translations for guest translations - TME // Intel Total Memory Encryption. The following MSRs are supported: IA32_TME_CAPABILITY, IA32_TME_ACTIVATE, IA32_TME_EXCLUDE_MASK, and IA32_TME_EXCLUDE_BASE. - TOPEXT // TopologyExtensions: topology extensions support. Indicates support for CPUID Fn8000_001D_EAX_x[N:0]-CPUID Fn8000_001E_EDX. - TSA_L1_NO // AMD only: Not vulnerable to TSA-L1 - TSA_SQ_NO // AM onlyD: Not vulnerable to TSA-SQ - TSA_VERW_CLEAR // If set, the memory form of the VERW instruction may be used to help mitigate TSA - TSCRATEMSR // MSR based TSC rate control. Indicates support for MSR TSC ratio MSRC000_0104 - TSXLDTRK // Intel TSX Suspend Load Address Tracking - VAES // Vector AES. AVX(512) versions requires additional checks. - VMCBCLEAN // VMCB clean bits. Indicates support for VMCB clean bits. - VMPL // AMD VM Permission Levels supported - VMSA_REGPROT // AMD VMSA Register Protection supported - VMX // Virtual Machine Extensions - VPCLMULQDQ // Carry-Less Multiplication Quadword. Requires AVX for 3 register versions. - VTE // AMD Virtual Transparent Encryption supported - WAITPKG // TPAUSE, UMONITOR, UMWAIT - WBNOINVD // Write Back and Do Not Invalidate Cache - WRMSRNS // Non-Serializing Write to Model Specific Register - X87 // FPU - XGETBV1 // Supports XGETBV with ECX = 1 - XOP // Bulldozer XOP functions - XSAVE // XSAVE, XRESTOR, XSETBV, XGETBV - XSAVEC // Supports XSAVEC and the compacted form of XRSTOR. - XSAVEOPT // XSAVEOPT available - XSAVES // Supports XSAVES/XRSTORS and IA32_XSS - - // ARM features: - AESARM // AES instructions - ARMCPUID // Some CPU ID registers readable at user-level - ASIMD // Advanced SIMD - ASIMDDP // SIMD Dot Product - ASIMDHP // Advanced SIMD half-precision floating point - ASIMDRDM // Rounding Double Multiply Accumulate/Subtract (SQRDMLAH/SQRDMLSH) - ATOMICS // Large System Extensions (LSE) - CRC32 // CRC32/CRC32C instructions - DCPOP // Data cache clean to Point of Persistence (DC CVAP) - EVTSTRM // Generic timer - FCMA // Floating point complex number addition and multiplication - FHM // FMLAL and FMLSL instructions - FP // Single-precision and double-precision floating point - FPHP // Half-precision floating point - GPA // Generic Pointer Authentication - JSCVT // Javascript-style double->int convert (FJCVTZS) - LRCPC // Weaker release consistency (LDAPR, etc) - PMULL // Polynomial Multiply instructions (PMULL/PMULL2) - RNDR // Random Number instructions - TLB // Outer Shareable and TLB range maintenance instructions - TS // Flag manipulation instructions - SHA1 // SHA-1 instructions (SHA1C, etc) - SHA2 // SHA-2 instructions (SHA256H, etc) - SHA3 // SHA-3 instructions (EOR3, RAXI, XAR, BCAX) - SHA512 // SHA512 instructions - SM3 // SM3 instructions - SM4 // SM4 instructions - SVE // Scalable Vector Extension - - // PMU - PMU_FIXEDCOUNTER_CYCLES - PMU_FIXEDCOUNTER_REFCYCLES - PMU_FIXEDCOUNTER_INSTRUCTIONS - PMU_FIXEDCOUNTER_TOPDOWN_SLOTS - - // Keep it last. It automatically defines the size of []flagSet - lastID - - firstID FeatureID = UNKNOWN + 1 -) - -// CPUInfo contains information about the detected system CPU. -type CPUInfo struct { - BrandName string // Brand name reported by the CPU - VendorID Vendor // Comparable CPU vendor ID - VendorString string // Raw vendor string. - HypervisorVendorID Vendor // Hypervisor vendor - HypervisorVendorString string // Raw hypervisor vendor string - featureSet flagSet // Features of the CPU - PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable. - ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable. - LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable. - Family int // CPU family number - Model int // CPU model number - Stepping int // CPU stepping info - CacheLine int // Cache line size in bytes. Will be 0 if undetectable. - Hz int64 // Clock speed, if known, 0 otherwise. Will attempt to contain base clock speed. - BoostFreq int64 // Max clock speed, if known, 0 otherwise - Cache struct { - L1I int // L1 Instruction Cache (per core or shared). Will be -1 if undetected - L1D int // L1 Data Cache (per core or shared). Will be -1 if undetected - L2 int // L2 Cache (per core or shared). Will be -1 if undetected - L3 int // L3 Cache (per core, per ccx or shared). Will be -1 if undetected - } - SGX SGXSupport - AMDMemEncryption AMDMemEncryptionSupport - AVX10Level uint8 - PMU PerformanceMonitoringInfo // holds information about the PMU - - maxFunc uint32 - maxExFunc uint32 -} - -// PerformanceMonitoringInfo holds information about CPU performance monitoring capabilities. -// This is primarily populated from CPUID leaf 0xAh on x86 -type PerformanceMonitoringInfo struct { - // VersionID (x86 only): Version ID of architectural performance monitoring. - // A value of 0 means architectural performance monitoring is not supported or information is unavailable. - VersionID uint8 - // NumGPPMC: Number of General-Purpose Performance Monitoring Counters per logical processor. - // On ARM, this is derived from PMCR_EL0.N (number of event counters). - NumGPCounters uint8 - // GPPMCWidth: Bit width of General-Purpose Performance Monitoring Counters. - // On ARM, typically 64 for PMU event counters. - GPPMCWidth uint8 - // NumFixedPMC: Number of Fixed-Function Performance Counters. - // Valid on x86 if VersionID > 1. On ARM, this typically includes at least the cycle counter (PMCCNTR_EL0). - NumFixedPMC uint8 - // FixedPMCWidth: Bit width of Fixed-Function Performance Counters. - // Valid on x86 if VersionID > 1. On ARM, the cycle counter (PMCCNTR_EL0) is 64-bit. - FixedPMCWidth uint8 - // Raw register output from CPUID leaf 0xAh. - RawEBX uint32 - RawEAX uint32 - RawEDX uint32 -} - -var cpuid func(op uint32) (eax, ebx, ecx, edx uint32) -var cpuidex func(op, op2 uint32) (eax, ebx, ecx, edx uint32) -var xgetbv func(index uint32) (eax, edx uint32) -var rdtscpAsm func() (eax, ebx, ecx, edx uint32) -var darwinHasAVX512 = func() bool { return false } - -// CPU contains information about the CPU as detected on startup, -// or when Detect last was called. -// -// Use this as the primary entry point to you data. -var CPU CPUInfo - -func init() { - initCPU() - Detect() -} - -// Detect will re-detect current CPU info. -// This will replace the content of the exported CPU variable. -// -// Unless you expect the CPU to change while you are running your program -// you should not need to call this function. -// If you call this, you must ensure that no other goroutine is accessing the -// exported CPU variable. -func Detect() { - // Set defaults - CPU.ThreadsPerCore = 1 - CPU.Cache.L1I = -1 - CPU.Cache.L1D = -1 - CPU.Cache.L2 = -1 - CPU.Cache.L3 = -1 - safe := true - if detectArmFlag != nil { - safe = !*detectArmFlag - } - addInfo(&CPU, safe) - if displayFeats != nil && *displayFeats { - fmt.Println("cpu features:", strings.Join(CPU.FeatureSet(), ",")) - // Exit with non-zero so tests will print value. - os.Exit(1) - } - if disableFlag != nil { - s := strings.Split(*disableFlag, ",") - for _, feat := range s { - feat := ParseFeature(strings.TrimSpace(feat)) - if feat != UNKNOWN { - CPU.featureSet.unset(feat) - } - } - } -} - -// DetectARM will detect ARM64 features. -// This is NOT done automatically since it can potentially crash -// if the OS does not handle the command. -// If in the future this can be done safely this function may not -// do anything. -func DetectARM() { - addInfo(&CPU, false) -} - -var detectArmFlag *bool -var displayFeats *bool -var disableFlag *string - -// Flags will enable flags. -// This must be called *before* flag.Parse AND -// Detect must be called after the flags have been parsed. -// Note that this means that any detection used in init() functions -// will not contain these flags. -func Flags() { - disableFlag = flag.String("cpu.disable", "", "disable cpu features; comma separated list") - displayFeats = flag.Bool("cpu.features", false, "lists cpu features and exits") - detectArmFlag = flag.Bool("cpu.arm", false, "allow ARM features to be detected; can potentially crash") -} - -// Supports returns whether the CPU supports all of the requested features. -func (c CPUInfo) Supports(ids ...FeatureID) bool { - for _, id := range ids { - if !c.featureSet.inSet(id) { - return false - } - } - return true -} - -// Has allows for checking a single feature. -// Should be inlined by the compiler. -func (c *CPUInfo) Has(id FeatureID) bool { - return c.featureSet.inSet(id) -} - -// AnyOf returns whether the CPU supports one or more of the requested features. -func (c CPUInfo) AnyOf(ids ...FeatureID) bool { - for _, id := range ids { - if c.featureSet.inSet(id) { - return true - } - } - return false -} - -// Features contains several features combined for a fast check using -// CpuInfo.HasAll -type Features *flagSet - -// CombineFeatures allows to combine several features for a close to constant time lookup. -func CombineFeatures(ids ...FeatureID) Features { - var v flagSet - for _, id := range ids { - v.set(id) - } - return &v -} - -func (c *CPUInfo) HasAll(f Features) bool { - return c.featureSet.hasSetP(f) -} - -// https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels -var oneOfLevel = CombineFeatures(SYSEE, SYSCALL) -var level1Features = CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SSE, SSE2) -var level2Features = CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3) -var level3Features = CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3, AVX, AVX2, BMI1, BMI2, F16C, FMA3, LZCNT, MOVBE, OSXSAVE) -var level4Features = CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3, AVX, AVX2, BMI1, BMI2, F16C, FMA3, LZCNT, MOVBE, OSXSAVE, AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL) - -// X64Level returns the microarchitecture level detected on the CPU. -// If features are lacking or non x64 mode, 0 is returned. -// See https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels -func (c CPUInfo) X64Level() int { - if !c.featureSet.hasOneOf(oneOfLevel) { - return 0 - } - if c.featureSet.hasSetP(level4Features) { - return 4 - } - if c.featureSet.hasSetP(level3Features) { - return 3 - } - if c.featureSet.hasSetP(level2Features) { - return 2 - } - if c.featureSet.hasSetP(level1Features) { - return 1 - } - return 0 -} - -// Disable will disable one or several features. -func (c *CPUInfo) Disable(ids ...FeatureID) bool { - for _, id := range ids { - c.featureSet.unset(id) - } - return true -} - -// Enable will disable one or several features even if they were undetected. -// This is of course not recommended for obvious reasons. -func (c *CPUInfo) Enable(ids ...FeatureID) bool { - for _, id := range ids { - c.featureSet.set(id) - } - return true -} - -// IsVendor returns true if vendor is recognized as Intel -func (c CPUInfo) IsVendor(v Vendor) bool { - return c.VendorID == v -} - -// FeatureSet returns all available features as strings. -func (c CPUInfo) FeatureSet() []string { - s := make([]string, 0, c.featureSet.nEnabled()) - s = append(s, c.featureSet.Strings()...) - return s -} - -// RTCounter returns the 64-bit time-stamp counter -// Uses the RDTSCP instruction. The value 0 is returned -// if the CPU does not support the instruction. -func (c CPUInfo) RTCounter() uint64 { - if !c.Has(RDTSCP) { - return 0 - } - a, _, _, d := rdtscpAsm() - return uint64(a) | (uint64(d) << 32) -} - -// Ia32TscAux returns the IA32_TSC_AUX part of the RDTSCP. -// This variable is OS dependent, but on Linux contains information -// about the current cpu/core the code is running on. -// If the RDTSCP instruction isn't supported on the CPU, the value 0 is returned. -func (c CPUInfo) Ia32TscAux() uint32 { - if !c.Has(RDTSCP) { - return 0 - } - _, _, ecx, _ := rdtscpAsm() - return ecx -} - -// SveLengths returns arm SVE vector and predicate lengths in bits. -// Will return 0, 0 if SVE is not enabled or otherwise unable to detect. -func (c CPUInfo) SveLengths() (vl, pl uint64) { - if !c.Has(SVE) { - return 0, 0 - } - return getVectorLength() -} - -// LogicalCPU will return the Logical CPU the code is currently executing on. -// This is likely to change when the OS re-schedules the running thread -// to another CPU. -// If the current core cannot be detected, -1 will be returned. -func (c CPUInfo) LogicalCPU() int { - if c.maxFunc < 1 { - return -1 - } - _, ebx, _, _ := cpuid(1) - return int(ebx >> 24) -} - -// frequencies tries to compute the clock speed of the CPU. If leaf 15 is -// supported, use it, otherwise parse the brand string. Yes, really. -func (c *CPUInfo) frequencies() { - c.Hz, c.BoostFreq = 0, 0 - mfi := maxFunctionID() - if mfi >= 0x15 { - eax, ebx, ecx, _ := cpuid(0x15) - if eax != 0 && ebx != 0 && ecx != 0 { - c.Hz = (int64(ecx) * int64(ebx)) / int64(eax) - } - } - if mfi >= 0x16 { - a, b, _, _ := cpuid(0x16) - // Base... - if a&0xffff > 0 { - c.Hz = int64(a&0xffff) * 1_000_000 - } - // Boost... - if b&0xffff > 0 { - c.BoostFreq = int64(b&0xffff) * 1_000_000 - } - } - if c.Hz > 0 { - return - } - - // computeHz determines the official rated speed of a CPU from its brand - // string. This insanity is *actually the official documented way to do - // this according to Intel*, prior to leaf 0x15 existing. The official - // documentation only shows this working for exactly `x.xx` or `xxxx` - // cases, e.g., `2.50GHz` or `1300MHz`; this parser will accept other - // sizes. - model := c.BrandName - hz := strings.LastIndex(model, "Hz") - if hz < 3 { - return - } - var multiplier int64 - switch model[hz-1] { - case 'M': - multiplier = 1000 * 1000 - case 'G': - multiplier = 1000 * 1000 * 1000 - case 'T': - multiplier = 1000 * 1000 * 1000 * 1000 - } - if multiplier == 0 { - return - } - freq := int64(0) - divisor := int64(0) - decimalShift := int64(1) - var i int - for i = hz - 2; i >= 0 && model[i] != ' '; i-- { - if model[i] >= '0' && model[i] <= '9' { - freq += int64(model[i]-'0') * decimalShift - decimalShift *= 10 - } else if model[i] == '.' { - if divisor != 0 { - return - } - divisor = decimalShift - } else { - return - } - } - // we didn't find a space - if i < 0 { - return - } - if divisor != 0 { - c.Hz = (freq * multiplier) / divisor - return - } - c.Hz = freq * multiplier -} - -// VM Will return true if the cpu id indicates we are in -// a virtual machine. -func (c CPUInfo) VM() bool { - return CPU.featureSet.inSet(HYPERVISOR) -} - -// flags contains detected cpu features and characteristics -type flags uint64 - -// log2(bits_in_uint64) -const flagBitsLog2 = 6 -const flagBits = 1 << flagBitsLog2 -const flagMask = flagBits - 1 - -// flagSet contains detected cpu features and characteristics in an array of flags -type flagSet [(lastID + flagMask) / flagBits]flags - -func (s *flagSet) inSet(feat FeatureID) bool { - return s[feat>>flagBitsLog2]&(1<<(feat&flagMask)) != 0 -} - -func (s *flagSet) set(feat FeatureID) { - s[feat>>flagBitsLog2] |= 1 << (feat & flagMask) -} - -// setIf will set a feature if boolean is true. -func (s *flagSet) setIf(cond bool, features ...FeatureID) { - if cond { - for _, offset := range features { - s[offset>>flagBitsLog2] |= 1 << (offset & flagMask) - } - } -} - -func (s *flagSet) unset(offset FeatureID) { - bit := flags(1 << (offset & flagMask)) - s[offset>>flagBitsLog2] = s[offset>>flagBitsLog2] & ^bit -} - -// or with another flagset. -func (s *flagSet) or(other flagSet) { - for i, v := range other[:] { - s[i] |= v - } -} - -// hasSet returns whether all features are present. -func (s *flagSet) hasSet(other flagSet) bool { - for i, v := range other[:] { - if s[i]&v != v { - return false - } - } - return true -} - -// hasSet returns whether all features are present. -func (s *flagSet) hasSetP(other *flagSet) bool { - for i, v := range other[:] { - if s[i]&v != v { - return false - } - } - return true -} - -// hasOneOf returns whether one or more features are present. -func (s *flagSet) hasOneOf(other *flagSet) bool { - for i, v := range other[:] { - if s[i]&v != 0 { - return true - } - } - return false -} - -// nEnabled will return the number of enabled flags. -func (s *flagSet) nEnabled() (n int) { - for _, v := range s[:] { - n += bits.OnesCount64(uint64(v)) - } - return n -} - -func flagSetWith(feat ...FeatureID) flagSet { - var res flagSet - for _, f := range feat { - res.set(f) - } - return res -} - -// ParseFeature will parse the string and return the ID of the matching feature. -// Will return UNKNOWN if not found. -func ParseFeature(s string) FeatureID { - s = strings.ToUpper(s) - for i := firstID; i < lastID; i++ { - if i.String() == s { - return i - } - } - return UNKNOWN -} - -// Strings returns an array of the detected features for FlagsSet. -func (s flagSet) Strings() []string { - if len(s) == 0 { - return []string{""} - } - r := make([]string, 0) - for i := firstID; i < lastID; i++ { - if s.inSet(i) { - r = append(r, i.String()) - } - } - return r -} - -func maxExtendedFunction() uint32 { - eax, _, _, _ := cpuid(0x80000000) - return eax -} - -func maxFunctionID() uint32 { - a, _, _, _ := cpuid(0) - return a -} - -func brandName() string { - if maxExtendedFunction() >= 0x80000004 { - v := make([]uint32, 0, 48) - for i := uint32(0); i < 3; i++ { - a, b, c, d := cpuid(0x80000002 + i) - v = append(v, a, b, c, d) - } - return strings.Trim(string(valAsString(v...)), " ") - } - return "unknown" -} - -func threadsPerCore() int { - mfi := maxFunctionID() - vend, _ := vendorID() - - if mfi < 0x4 || (vend != Intel && vend != AMD) { - return 1 - } - - if mfi < 0xb { - if vend != Intel { - return 1 - } - _, b, _, d := cpuid(1) - if (d & (1 << 28)) != 0 { - // v will contain logical core count - v := (b >> 16) & 255 - if v > 1 { - a4, _, _, _ := cpuid(4) - // physical cores - v2 := (a4 >> 26) + 1 - if v2 > 0 { - return int(v) / int(v2) - } - } - } - return 1 - } - _, b, _, _ := cpuidex(0xb, 0) - if b&0xffff == 0 { - if vend == AMD { - // if >= Zen 2 0x8000001e EBX 15-8 bits means threads per core. - // The number of threads per core is ThreadsPerCore+1 - // See PPR for AMD Family 17h Models 00h-0Fh (page 82) - fam, _, _ := familyModel() - _, _, _, d := cpuid(1) - if (d&(1<<28)) != 0 && fam >= 23 { - if maxExtendedFunction() >= 0x8000001e { - _, b, _, _ := cpuid(0x8000001e) - return int((b>>8)&0xff) + 1 - } - return 2 - } - } - return 1 - } - return int(b & 0xffff) -} - -func logicalCores() int { - mfi := maxFunctionID() - v, _ := vendorID() - switch v { - case Intel: - // Use this on old Intel processors - if mfi < 0xb { - if mfi < 1 { - return 0 - } - // CPUID.1:EBX[23:16] represents the maximum number of addressable IDs (initial APIC ID) - // that can be assigned to logical processors in a physical package. - // The value may not be the same as the number of logical processors that are present in the hardware of a physical package. - _, ebx, _, _ := cpuid(1) - logical := (ebx >> 16) & 0xff - return int(logical) - } - _, b, _, _ := cpuidex(0xb, 1) - return int(b & 0xffff) - case AMD, Hygon: - _, b, _, _ := cpuid(1) - return int((b >> 16) & 0xff) - default: - return 0 - } -} - -func familyModel() (family, model, stepping int) { - if maxFunctionID() < 0x1 { - return 0, 0, 0 - } - eax, _, _, _ := cpuid(1) - // If BaseFamily[3:0] is less than Fh then ExtendedFamily[7:0] is reserved and Family is equal to BaseFamily[3:0]. - family = int((eax >> 8) & 0xf) - extFam := family == 0x6 // Intel is 0x6, needs extended model. - if family == 0xf { - // Add ExtFamily - family += int((eax >> 20) & 0xff) - extFam = true - } - // If BaseFamily[3:0] is less than 0Fh then ExtendedModel[3:0] is reserved and Model is equal to BaseModel[3:0]. - model = int((eax >> 4) & 0xf) - if extFam { - // Add ExtModel - model += int((eax >> 12) & 0xf0) - } - stepping = int(eax & 0xf) - return family, model, stepping -} - -func physicalCores() int { - v, _ := vendorID() - switch v { - case Intel: - lc := logicalCores() - tpc := threadsPerCore() - if lc > 0 && tpc > 0 { - return lc / tpc - } - return 0 - case AMD, Hygon: - lc := logicalCores() - tpc := threadsPerCore() - if lc > 0 && tpc > 0 { - return lc / tpc - } - - // The following is inaccurate on AMD EPYC 7742 64-Core Processor - if maxExtendedFunction() >= 0x80000008 { - _, _, c, _ := cpuid(0x80000008) - if c&0xff > 0 { - return int(c&0xff) + 1 - } - } - } - return 0 -} - -// Except from http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID -var vendorMapping = map[string]Vendor{ - "AMDisbetter!": AMD, - "AuthenticAMD": AMD, - "CentaurHauls": VIA, - "GenuineIntel": Intel, - "TransmetaCPU": Transmeta, - "GenuineTMx86": Transmeta, - "Geode by NSC": NSC, - "VIA VIA VIA ": VIA, - "KVMKVMKVM": KVM, - "Linux KVM Hv": KVM, - "TCGTCGTCGTCG": QEMU, - "Microsoft Hv": MSVM, - "VMwareVMware": VMware, - "XenVMMXenVMM": XenHVM, - "bhyve bhyve ": Bhyve, - "HygonGenuine": Hygon, - "Vortex86 SoC": SiS, - "SiS SiS SiS ": SiS, - "RiseRiseRise": SiS, - "Genuine RDC": RDC, - "QNXQVMBSQG": QNX, - "ACRNACRNACRN": ACRN, - "SRESRESRESRE": SRE, - "Apple VZ": Apple, -} - -func vendorID() (Vendor, string) { - _, b, c, d := cpuid(0) - v := string(valAsString(b, d, c)) - vend, ok := vendorMapping[v] - if !ok { - return VendorUnknown, v - } - return vend, v -} - -func hypervisorVendorID() (Vendor, string) { - // https://lwn.net/Articles/301888/ - _, b, c, d := cpuid(0x40000000) - v := string(valAsString(b, c, d)) - vend, ok := vendorMapping[v] - if !ok { - return VendorUnknown, v - } - return vend, v -} - -func cacheLine() int { - if maxFunctionID() < 0x1 { - return 0 - } - - _, ebx, _, _ := cpuid(1) - cache := (ebx & 0xff00) >> 5 // cflush size - if cache == 0 && maxExtendedFunction() >= 0x80000006 { - _, _, ecx, _ := cpuid(0x80000006) - cache = ecx & 0xff // cacheline size - } - // TODO: Read from Cache and TLB Information - return int(cache) -} - -func (c *CPUInfo) cacheSize() { - c.Cache.L1D = -1 - c.Cache.L1I = -1 - c.Cache.L2 = -1 - c.Cache.L3 = -1 - vendor, _ := vendorID() - switch vendor { - case Intel: - if maxFunctionID() < 4 { - return - } - c.Cache.L1I, c.Cache.L1D, c.Cache.L2, c.Cache.L3 = 0, 0, 0, 0 - for i := uint32(0); ; i++ { - eax, ebx, ecx, _ := cpuidex(4, i) - cacheType := eax & 15 - if cacheType == 0 { - break - } - cacheLevel := (eax >> 5) & 7 - coherency := int(ebx&0xfff) + 1 - partitions := int((ebx>>12)&0x3ff) + 1 - associativity := int((ebx>>22)&0x3ff) + 1 - sets := int(ecx) + 1 - size := associativity * partitions * coherency * sets - switch cacheLevel { - case 1: - if cacheType == 1 { - // 1 = Data Cache - c.Cache.L1D = size - } else if cacheType == 2 { - // 2 = Instruction Cache - c.Cache.L1I = size - } else { - if c.Cache.L1D < 0 { - c.Cache.L1I = size - } - if c.Cache.L1I < 0 { - c.Cache.L1I = size - } - } - case 2: - c.Cache.L2 = size - case 3: - c.Cache.L3 = size - } - } - case AMD, Hygon: - // Untested. - if maxExtendedFunction() < 0x80000005 { - return - } - _, _, ecx, edx := cpuid(0x80000005) - c.Cache.L1D = int(((ecx >> 24) & 0xFF) * 1024) - c.Cache.L1I = int(((edx >> 24) & 0xFF) * 1024) - - if maxExtendedFunction() < 0x80000006 { - return - } - _, _, ecx, _ = cpuid(0x80000006) - c.Cache.L2 = int(((ecx >> 16) & 0xFFFF) * 1024) - - // CPUID Fn8000_001D_EAX_x[N:0] Cache Properties - if maxExtendedFunction() < 0x8000001D || !c.Has(TOPEXT) { - return - } - - // Xen Hypervisor is buggy and returns the same entry no matter ECX value. - // Hack: When we encounter the same entry 100 times we break. - nSame := 0 - var last uint32 - for i := uint32(0); i < math.MaxUint32; i++ { - eax, ebx, ecx, _ := cpuidex(0x8000001D, i) - - level := (eax >> 5) & 7 - cacheNumSets := ecx + 1 - cacheLineSize := 1 + (ebx & 2047) - cachePhysPartitions := 1 + ((ebx >> 12) & 511) - cacheNumWays := 1 + ((ebx >> 22) & 511) - - typ := eax & 15 - size := int(cacheNumSets * cacheLineSize * cachePhysPartitions * cacheNumWays) - if typ == 0 { - return - } - - // Check for the same value repeated. - comb := eax ^ ebx ^ ecx - if comb == last { - nSame++ - if nSame == 100 { - return - } - } - last = comb - - switch level { - case 1: - switch typ { - case 1: - // Data cache - c.Cache.L1D = size - case 2: - // Inst cache - c.Cache.L1I = size - default: - if c.Cache.L1D < 0 { - c.Cache.L1I = size - } - if c.Cache.L1I < 0 { - c.Cache.L1I = size - } - } - case 2: - c.Cache.L2 = size - case 3: - c.Cache.L3 = size - } - } - } -} - -type SGXEPCSection struct { - BaseAddress uint64 - EPCSize uint64 -} - -type SGXSupport struct { - Available bool - LaunchControl bool - SGX1Supported bool - SGX2Supported bool - MaxEnclaveSizeNot64 int64 - MaxEnclaveSize64 int64 - EPCSections []SGXEPCSection -} - -func hasSGX(available, lc bool) (rval SGXSupport) { - rval.Available = available - - if !available { - return - } - - rval.LaunchControl = lc - - a, _, _, d := cpuidex(0x12, 0) - rval.SGX1Supported = a&0x01 != 0 - rval.SGX2Supported = a&0x02 != 0 - rval.MaxEnclaveSizeNot64 = 1 << (d & 0xFF) // pow 2 - rval.MaxEnclaveSize64 = 1 << ((d >> 8) & 0xFF) // pow 2 - rval.EPCSections = make([]SGXEPCSection, 0) - - for subleaf := uint32(2); subleaf < 2+8; subleaf++ { - eax, ebx, ecx, edx := cpuidex(0x12, subleaf) - leafType := eax & 0xf - - if leafType == 0 { - // Invalid subleaf, stop iterating - break - } else if leafType == 1 { - // EPC Section subleaf - baseAddress := uint64(eax&0xfffff000) + (uint64(ebx&0x000fffff) << 32) - size := uint64(ecx&0xfffff000) + (uint64(edx&0x000fffff) << 32) - - section := SGXEPCSection{BaseAddress: baseAddress, EPCSize: size} - rval.EPCSections = append(rval.EPCSections, section) - } - } - - return -} - -type AMDMemEncryptionSupport struct { - Available bool - CBitPossition uint32 - NumVMPL uint32 - PhysAddrReduction uint32 - NumEntryptedGuests uint32 - MinSevNoEsAsid uint32 -} - -func hasAMDMemEncryption(available bool) (rval AMDMemEncryptionSupport) { - rval.Available = available - if !available { - return - } - - _, b, c, d := cpuidex(0x8000001f, 0) - - rval.CBitPossition = b & 0x3f - rval.PhysAddrReduction = (b >> 6) & 0x3F - rval.NumVMPL = (b >> 12) & 0xf - rval.NumEntryptedGuests = c - rval.MinSevNoEsAsid = d - - return -} - -func support() flagSet { - var fs flagSet - mfi := maxFunctionID() - vend, _ := vendorID() - if mfi < 0x1 { - return fs - } - family, model, _ := familyModel() - - _, _, c, d := cpuid(1) - fs.setIf((d&(1<<0)) != 0, X87) - fs.setIf((d&(1<<8)) != 0, CMPXCHG8) - fs.setIf((d&(1<<11)) != 0, SYSEE) - fs.setIf((d&(1<<15)) != 0, CMOV) - fs.setIf((d&(1<<23)) != 0, MMX) - fs.setIf((d&(1<<24)) != 0, FXSR) - fs.setIf((d&(1<<25)) != 0, FXSROPT) - fs.setIf((d&(1<<25)) != 0, SSE) - fs.setIf((d&(1<<26)) != 0, SSE2) - fs.setIf((c&1) != 0, SSE3) - fs.setIf((c&(1<<5)) != 0, VMX) - fs.setIf((c&(1<<9)) != 0, SSSE3) - fs.setIf((c&(1<<19)) != 0, SSE4) - fs.setIf((c&(1<<20)) != 0, SSE42) - fs.setIf((c&(1<<25)) != 0, AESNI) - fs.setIf((c&(1<<1)) != 0, CLMUL) - fs.setIf(c&(1<<22) != 0, MOVBE) - fs.setIf(c&(1<<23) != 0, POPCNT) - fs.setIf(c&(1<<30) != 0, RDRAND) - - // This bit has been reserved by Intel & AMD for use by hypervisors, - // and indicates the presence of a hypervisor. - fs.setIf(c&(1<<31) != 0, HYPERVISOR) - fs.setIf(c&(1<<29) != 0, F16C) - fs.setIf(c&(1<<13) != 0, CX16) - - if vend == Intel && (d&(1<<28)) != 0 && mfi >= 4 { - fs.setIf(threadsPerCore() > 1, HTT) - } - if vend == AMD && (d&(1<<28)) != 0 && mfi >= 4 { - fs.setIf(threadsPerCore() > 1, HTT) - } - fs.setIf(c&1<<26 != 0, XSAVE) - fs.setIf(c&1<<27 != 0, OSXSAVE) - // Check XGETBV/XSAVE (26), OXSAVE (27) and AVX (28) bits - const avxCheck = 1<<26 | 1<<27 | 1<<28 - if c&avxCheck == avxCheck { - // Check for OS support - eax, _ := xgetbv(0) - if (eax & 0x6) == 0x6 { - fs.set(AVX) - switch vend { - case Intel: - // Older than Haswell. - fs.setIf(family == 6 && model < 60, AVXSLOW) - case AMD: - // Older than Zen 2 - fs.setIf(family < 23 || (family == 23 && model < 49), AVXSLOW) - } - } - } - // FMA3 can be used with SSE registers, so no OS support is strictly needed. - // fma3 and OSXSAVE needed. - const fma3Check = 1<<12 | 1<<27 - fs.setIf(c&fma3Check == fma3Check, FMA3) - - // Check AVX2, AVX2 requires OS support, but BMI1/2 don't. - if mfi >= 7 { - _, ebx, ecx, edx := cpuidex(7, 0) - if fs.inSet(AVX) && (ebx&0x00000020) != 0 { - fs.set(AVX2) - } - // CPUID.(EAX=7, ECX=0).EBX - if (ebx & 0x00000008) != 0 { - fs.set(BMI1) - fs.setIf((ebx&0x00000100) != 0, BMI2) - } - fs.setIf(ebx&(1<<2) != 0, SGX) - fs.setIf(ebx&(1<<4) != 0, HLE) - fs.setIf(ebx&(1<<9) != 0, ERMS) - fs.setIf(ebx&(1<<11) != 0, RTM) - fs.setIf(ebx&(1<<14) != 0, MPX) - fs.setIf(ebx&(1<<18) != 0, RDSEED) - fs.setIf(ebx&(1<<19) != 0, ADX) - fs.setIf(ebx&(1<<29) != 0, SHA) - - // CPUID.(EAX=7, ECX=0).ECX - fs.setIf(ecx&(1<<5) != 0, WAITPKG) - fs.setIf(ecx&(1<<7) != 0, CETSS) - fs.setIf(ecx&(1<<8) != 0, GFNI) - fs.setIf(ecx&(1<<9) != 0, VAES) - fs.setIf(ecx&(1<<10) != 0, VPCLMULQDQ) - fs.setIf(ecx&(1<<13) != 0, TME) - fs.setIf(ecx&(1<<25) != 0, CLDEMOTE) - fs.setIf(ecx&(1<<23) != 0, KEYLOCKER) - fs.setIf(ecx&(1<<27) != 0, MOVDIRI) - fs.setIf(ecx&(1<<28) != 0, MOVDIR64B) - fs.setIf(ecx&(1<<29) != 0, ENQCMD) - fs.setIf(ecx&(1<<30) != 0, SGXLC) - - // CPUID.(EAX=7, ECX=0).EDX - fs.setIf(edx&(1<<4) != 0, FSRM) - fs.setIf(edx&(1<<9) != 0, SRBDS_CTRL) - fs.setIf(edx&(1<<10) != 0, MD_CLEAR) - fs.setIf(edx&(1<<11) != 0, RTM_ALWAYS_ABORT) - fs.setIf(edx&(1<<14) != 0, SERIALIZE) - fs.setIf(edx&(1<<15) != 0, HYBRID_CPU) - fs.setIf(edx&(1<<16) != 0, TSXLDTRK) - fs.setIf(edx&(1<<18) != 0, PCONFIG) - fs.setIf(edx&(1<<20) != 0, CETIBT) - fs.setIf(edx&(1<<26) != 0, IBPB) - fs.setIf(edx&(1<<27) != 0, STIBP) - fs.setIf(edx&(1<<28) != 0, FLUSH_L1D) - fs.setIf(edx&(1<<29) != 0, IA32_ARCH_CAP) - fs.setIf(edx&(1<<30) != 0, IA32_CORE_CAP) - fs.setIf(edx&(1<<31) != 0, SPEC_CTRL_SSBD) - - // CPUID.(EAX=7, ECX=1).EAX - eax1, _, _, edx1 := cpuidex(7, 1) - fs.setIf(fs.inSet(AVX) && eax1&(1<<4) != 0, AVXVNNI) - fs.setIf(eax1&(1<<1) != 0, SM3_X86) - fs.setIf(eax1&(1<<2) != 0, SM4_X86) - fs.setIf(eax1&(1<<7) != 0, CMPCCXADD) - fs.setIf(eax1&(1<<10) != 0, MOVSB_ZL) - fs.setIf(eax1&(1<<11) != 0, STOSB_SHORT) - fs.setIf(eax1&(1<<12) != 0, CMPSB_SCADBS_SHORT) - fs.setIf(eax1&(1<<22) != 0, HRESET) - fs.setIf(eax1&(1<<23) != 0, AVXIFMA) - fs.setIf(eax1&(1<<26) != 0, LAM) - - // CPUID.(EAX=7, ECX=1).EDX - fs.setIf(edx1&(1<<4) != 0, AVXVNNIINT8) - fs.setIf(edx1&(1<<5) != 0, AVXNECONVERT) - fs.setIf(edx1&(1<<6) != 0, AMXTRANSPOSE) - fs.setIf(edx1&(1<<7) != 0, AMXTF32) - fs.setIf(edx1&(1<<8) != 0, AMXCOMPLEX) - fs.setIf(edx1&(1<<10) != 0, AVXVNNIINT16) - fs.setIf(edx1&(1<<14) != 0, PREFETCHI) - fs.setIf(edx1&(1<<19) != 0, AVX10) - fs.setIf(edx1&(1<<21) != 0, APX_F) - - // Only detect AVX-512 features if XGETBV is supported - if c&((1<<26)|(1<<27)) == (1<<26)|(1<<27) { - // Check for OS support - eax, _ := xgetbv(0) - - // Verify that XCR0[7:5] = ‘111b’ (OPMASK state, upper 256-bit of ZMM0-ZMM15 and - // ZMM16-ZMM31 state are enabled by OS) - /// and that XCR0[2:1] = ‘11b’ (XMM state and YMM state are enabled by OS). - hasAVX512 := (eax>>5)&7 == 7 && (eax>>1)&3 == 3 - if runtime.GOOS == "darwin" { - hasAVX512 = fs.inSet(AVX) && darwinHasAVX512() - } - if hasAVX512 { - fs.setIf(ebx&(1<<16) != 0, AVX512F) - fs.setIf(ebx&(1<<17) != 0, AVX512DQ) - fs.setIf(ebx&(1<<21) != 0, AVX512IFMA) - fs.setIf(ebx&(1<<26) != 0, AVX512PF) - fs.setIf(ebx&(1<<27) != 0, AVX512ER) - fs.setIf(ebx&(1<<28) != 0, AVX512CD) - fs.setIf(ebx&(1<<30) != 0, AVX512BW) - fs.setIf(ebx&(1<<31) != 0, AVX512VL) - // ecx - fs.setIf(ecx&(1<<1) != 0, AVX512VBMI) - fs.setIf(ecx&(1<<3) != 0, AMXFP8) - fs.setIf(ecx&(1<<6) != 0, AVX512VBMI2) - fs.setIf(ecx&(1<<11) != 0, AVX512VNNI) - fs.setIf(ecx&(1<<12) != 0, AVX512BITALG) - fs.setIf(ecx&(1<<14) != 0, AVX512VPOPCNTDQ) - // edx - fs.setIf(edx&(1<<8) != 0, AVX512VP2INTERSECT) - fs.setIf(edx&(1<<22) != 0, AMXBF16) - fs.setIf(edx&(1<<23) != 0, AVX512FP16) - fs.setIf(edx&(1<<24) != 0, AMXTILE) - fs.setIf(edx&(1<<25) != 0, AMXINT8) - // eax1 = CPUID.(EAX=7, ECX=1).EAX - fs.setIf(eax1&(1<<5) != 0, AVX512BF16) - fs.setIf(eax1&(1<<19) != 0, WRMSRNS) - fs.setIf(eax1&(1<<21) != 0, AMXFP16) - fs.setIf(eax1&(1<<27) != 0, MSRLIST) - } - } - - // CPUID.(EAX=7, ECX=2) - _, _, _, edx = cpuidex(7, 2) - fs.setIf(edx&(1<<0) != 0, PSFD) - fs.setIf(edx&(1<<1) != 0, IDPRED_CTRL) - fs.setIf(edx&(1<<2) != 0, RRSBA_CTRL) - fs.setIf(edx&(1<<4) != 0, BHI_CTRL) - fs.setIf(edx&(1<<5) != 0, MCDT_NO) - - if fs.inSet(SGX) { - eax, _, _, _ := cpuidex(0x12, 0) - fs.setIf(eax&(1<<12) != 0, SGXPQC) - } - - // Add keylocker features. - if fs.inSet(KEYLOCKER) && mfi >= 0x19 { - _, ebx, _, _ := cpuidex(0x19, 0) - fs.setIf(ebx&5 == 5, KEYLOCKERW) // Bit 0 and 2 (1+4) - } - - // Add AVX10 features. - if fs.inSet(AVX10) && mfi >= 0x24 { - _, ebx, _, _ := cpuidex(0x24, 0) - fs.setIf(ebx&(1<<16) != 0, AVX10_128) - fs.setIf(ebx&(1<<17) != 0, AVX10_256) - fs.setIf(ebx&(1<<18) != 0, AVX10_512) - } - - } - - // Processor Extended State Enumeration Sub-leaf (EAX = 0DH, ECX = 1) - // EAX - // Bit 00: XSAVEOPT is available. - // Bit 01: Supports XSAVEC and the compacted form of XRSTOR if set. - // Bit 02: Supports XGETBV with ECX = 1 if set. - // Bit 03: Supports XSAVES/XRSTORS and IA32_XSS if set. - // Bits 31 - 04: Reserved. - // EBX - // Bits 31 - 00: The size in bytes of the XSAVE area containing all states enabled by XCRO | IA32_XSS. - // ECX - // Bits 31 - 00: Reports the supported bits of the lower 32 bits of the IA32_XSS MSR. IA32_XSS[n] can be set to 1 only if ECX[n] is 1. - // EDX? - // Bits 07 - 00: Used for XCR0. Bit 08: PT state. Bit 09: Used for XCR0. Bits 12 - 10: Reserved. Bit 13: HWP state. Bits 31 - 14: Reserved. - if mfi >= 0xd { - if fs.inSet(XSAVE) { - eax, _, _, _ := cpuidex(0xd, 1) - fs.setIf(eax&(1<<0) != 0, XSAVEOPT) - fs.setIf(eax&(1<<1) != 0, XSAVEC) - fs.setIf(eax&(1<<2) != 0, XGETBV1) - fs.setIf(eax&(1<<3) != 0, XSAVES) - } - } - if maxExtendedFunction() >= 0x80000001 { - _, _, c, d := cpuid(0x80000001) - if (c & (1 << 5)) != 0 { - fs.set(LZCNT) - fs.set(POPCNT) - } - // ECX - fs.setIf((c&(1<<0)) != 0, LAHF) - fs.setIf((c&(1<<2)) != 0, SVM) - fs.setIf((c&(1<<6)) != 0, SSE4A) - fs.setIf((c&(1<<10)) != 0, IBS) - fs.setIf((c&(1<<22)) != 0, TOPEXT) - - // EDX - fs.setIf(d&(1<<11) != 0, SYSCALL) - fs.setIf(d&(1<<20) != 0, NX) - fs.setIf(d&(1<<22) != 0, MMXEXT) - fs.setIf(d&(1<<23) != 0, MMX) - fs.setIf(d&(1<<24) != 0, FXSR) - fs.setIf(d&(1<<25) != 0, FXSROPT) - fs.setIf(d&(1<<27) != 0, RDTSCP) - fs.setIf(d&(1<<30) != 0, AMD3DNOWEXT) - fs.setIf(d&(1<<31) != 0, AMD3DNOW) - - /* XOP and FMA4 use the AVX instruction coding scheme, so they can't be - * used unless the OS has AVX support. */ - if fs.inSet(AVX) { - fs.setIf((c&(1<<11)) != 0, XOP) - fs.setIf((c&(1<<16)) != 0, FMA4) - } - - } - if maxExtendedFunction() >= 0x80000007 { - _, b, _, d := cpuid(0x80000007) - fs.setIf((b&(1<<0)) != 0, MCAOVERFLOW) - fs.setIf((b&(1<<1)) != 0, SUCCOR) - fs.setIf((b&(1<<2)) != 0, HWA) - fs.setIf((d&(1<<9)) != 0, CPBOOST) - } - - if maxExtendedFunction() >= 0x80000008 { - _, b, _, _ := cpuid(0x80000008) - fs.setIf(b&(1<<28) != 0, PSFD) - fs.setIf(b&(1<<27) != 0, CPPC) - fs.setIf(b&(1<<24) != 0, SPEC_CTRL_SSBD) - fs.setIf(b&(1<<23) != 0, PPIN) - fs.setIf(b&(1<<21) != 0, TLB_FLUSH_NESTED) - fs.setIf(b&(1<<20) != 0, EFER_LMSLE_UNS) - fs.setIf(b&(1<<19) != 0, IBRS_PROVIDES_SMP) - fs.setIf(b&(1<<18) != 0, IBRS_PREFERRED) - fs.setIf(b&(1<<17) != 0, STIBP_ALWAYSON) - fs.setIf(b&(1<<15) != 0, STIBP) - fs.setIf(b&(1<<14) != 0, IBRS) - fs.setIf((b&(1<<13)) != 0, INT_WBINVD) - fs.setIf(b&(1<<12) != 0, IBPB) - fs.setIf((b&(1<<9)) != 0, WBNOINVD) - fs.setIf((b&(1<<8)) != 0, MCOMMIT) - fs.setIf((b&(1<<4)) != 0, RDPRU) - fs.setIf((b&(1<<3)) != 0, INVLPGB) - fs.setIf((b&(1<<1)) != 0, MSRIRC) - fs.setIf((b&(1<<0)) != 0, CLZERO) - } - - if fs.inSet(SVM) && maxExtendedFunction() >= 0x8000000A { - _, _, _, edx := cpuid(0x8000000A) - fs.setIf((edx>>0)&1 == 1, SVMNP) - fs.setIf((edx>>1)&1 == 1, LBRVIRT) - fs.setIf((edx>>2)&1 == 1, SVML) - fs.setIf((edx>>3)&1 == 1, NRIPS) - fs.setIf((edx>>4)&1 == 1, TSCRATEMSR) - fs.setIf((edx>>5)&1 == 1, VMCBCLEAN) - fs.setIf((edx>>6)&1 == 1, SVMFBASID) - fs.setIf((edx>>7)&1 == 1, SVMDA) - fs.setIf((edx>>10)&1 == 1, SVMPF) - fs.setIf((edx>>12)&1 == 1, SVMPFT) - } - - if maxExtendedFunction() >= 0x8000001a { - eax, _, _, _ := cpuid(0x8000001a) - fs.setIf((eax>>0)&1 == 1, FP128) - fs.setIf((eax>>1)&1 == 1, MOVU) - fs.setIf((eax>>2)&1 == 1, FP256) - } - - if maxExtendedFunction() >= 0x8000001b && fs.inSet(IBS) { - eax, _, _, _ := cpuid(0x8000001b) - fs.setIf((eax>>0)&1 == 1, IBSFFV) - fs.setIf((eax>>1)&1 == 1, IBSFETCHSAM) - fs.setIf((eax>>2)&1 == 1, IBSOPSAM) - fs.setIf((eax>>3)&1 == 1, IBSRDWROPCNT) - fs.setIf((eax>>4)&1 == 1, IBSOPCNT) - fs.setIf((eax>>5)&1 == 1, IBSBRNTRGT) - fs.setIf((eax>>6)&1 == 1, IBSOPCNTEXT) - fs.setIf((eax>>7)&1 == 1, IBSRIPINVALIDCHK) - fs.setIf((eax>>8)&1 == 1, IBS_OPFUSE) - fs.setIf((eax>>9)&1 == 1, IBS_FETCH_CTLX) - fs.setIf((eax>>10)&1 == 1, IBS_OPDATA4) // Doc says "Fixed,0. IBS op data 4 MSR supported", but assuming they mean 1. - fs.setIf((eax>>11)&1 == 1, IBS_ZEN4) - } - - if maxExtendedFunction() >= 0x8000001f && vend == AMD { - a, _, _, _ := cpuid(0x8000001f) - fs.setIf((a>>0)&1 == 1, SME) - fs.setIf((a>>1)&1 == 1, SEV) - fs.setIf((a>>2)&1 == 1, MSR_PAGEFLUSH) - fs.setIf((a>>3)&1 == 1, SEV_ES) - fs.setIf((a>>4)&1 == 1, SEV_SNP) - fs.setIf((a>>5)&1 == 1, VMPL) - fs.setIf((a>>10)&1 == 1, SME_COHERENT) - fs.setIf((a>>11)&1 == 1, SEV_64BIT) - fs.setIf((a>>12)&1 == 1, SEV_RESTRICTED) - fs.setIf((a>>13)&1 == 1, SEV_ALTERNATIVE) - fs.setIf((a>>14)&1 == 1, SEV_DEBUGSWAP) - fs.setIf((a>>15)&1 == 1, IBS_PREVENTHOST) - fs.setIf((a>>16)&1 == 1, VTE) - fs.setIf((a>>24)&1 == 1, VMSA_REGPROT) - } - - if maxExtendedFunction() >= 0x80000021 && vend == AMD { - a, _, c, _ := cpuid(0x80000021) - fs.setIf((a>>31)&1 == 1, SRSO_MSR_FIX) - fs.setIf((a>>30)&1 == 1, SRSO_USER_KERNEL_NO) - fs.setIf((a>>29)&1 == 1, SRSO_NO) - fs.setIf((a>>28)&1 == 1, IBPB_BRTYPE) - fs.setIf((a>>27)&1 == 1, SBPB) - fs.setIf((c>>1)&1 == 1, TSA_L1_NO) - fs.setIf((c>>2)&1 == 1, TSA_SQ_NO) - fs.setIf((a>>5)&1 == 1, TSA_VERW_CLEAR) - } - if vend == AMD { - if family < 0x19 { - // AMD CPUs that are older than Family 19h are not vulnerable to TSA but do not set TSA_L1_NO or TSA_SQ_NO. - // Source: https://www.amd.com/content/dam/amd/en/documents/resources/bulletin/technical-guidance-for-mitigating-transient-scheduler-attacks.pdf - fs.set(TSA_L1_NO) - fs.set(TSA_SQ_NO) - } else if family == 0x1a { - // AMD Family 1Ah models 00h-4Fh and 60h-7Fh are also not vulnerable to TSA but do not set TSA_L1_NO or TSA_SQ_NO. - // Future AMD CPUs will set these CPUID bits if appropriate. CPUs will be designed to set these CPUID bits if appropriate. - notVuln := model <= 0x4f || (model >= 0x60 && model <= 0x7f) - fs.setIf(notVuln, TSA_L1_NO, TSA_SQ_NO) - } - } - - if mfi >= 0x20 { - // Microsoft has decided to purposefully hide the information - // of the guest TEE when VMs are being created using Hyper-V. - // - // This leads us to check for the Hyper-V cpuid features - // (0x4000000C), and then for the `ebx` value set. - // - // For Intel TDX, `ebx` is set as `0xbe3`, being 3 the part - // we're mostly interested about,according to: - // https://github.com/torvalds/linux/blob/d2f51b3516dade79269ff45eae2a7668ae711b25/arch/x86/include/asm/hyperv-tlfs.h#L169-L174 - _, ebx, _, _ := cpuid(0x4000000C) - fs.setIf(ebx == 0xbe3, TDX_GUEST) - } - - if mfi >= 0x21 { - // Intel Trusted Domain Extensions Guests have their own cpuid leaf (0x21). - _, ebx, ecx, edx := cpuid(0x21) - identity := string(valAsString(ebx, edx, ecx)) - fs.setIf(identity == "IntelTDX ", TDX_GUEST) - } - - return fs -} - -func (c *CPUInfo) supportAVX10() uint8 { - if c.maxFunc >= 0x24 && c.featureSet.inSet(AVX10) { - _, ebx, _, _ := cpuidex(0x24, 0) - return uint8(ebx) - } - return 0 -} - -func valAsString(values ...uint32) []byte { - r := make([]byte, 4*len(values)) - for i, v := range values { - dst := r[i*4:] - dst[0] = byte(v & 0xff) - dst[1] = byte((v >> 8) & 0xff) - dst[2] = byte((v >> 16) & 0xff) - dst[3] = byte((v >> 24) & 0xff) - switch { - case dst[0] == 0: - return r[:i*4] - case dst[1] == 0: - return r[:i*4+1] - case dst[2] == 0: - return r[:i*4+2] - case dst[3] == 0: - return r[:i*4+3] - } - } - return r -} - -func parseLeaf0AH(c *CPUInfo, eax, ebx, edx uint32) (info PerformanceMonitoringInfo) { - info.VersionID = uint8(eax & 0xFF) - info.NumGPCounters = uint8((eax >> 8) & 0xFF) - info.GPPMCWidth = uint8((eax >> 16) & 0xFF) - - info.RawEBX = ebx - info.RawEAX = eax - info.RawEDX = edx - - if info.VersionID > 1 { // This information is only valid if VersionID > 1 - info.NumFixedPMC = uint8(edx & 0x1F) // Bits 4:0 - info.FixedPMCWidth = uint8((edx >> 5) & 0xFF) // Bits 12:5 - } - if info.VersionID > 0 { - // first 4 fixed events are always instructions retired, cycles, ref cycles and topdown slots - if ebx == 0x0 && info.NumFixedPMC == 3 { - c.featureSet.set(PMU_FIXEDCOUNTER_INSTRUCTIONS) - c.featureSet.set(PMU_FIXEDCOUNTER_CYCLES) - c.featureSet.set(PMU_FIXEDCOUNTER_REFCYCLES) - } - if ebx == 0x0 && info.NumFixedPMC == 4 { - c.featureSet.set(PMU_FIXEDCOUNTER_INSTRUCTIONS) - c.featureSet.set(PMU_FIXEDCOUNTER_CYCLES) - c.featureSet.set(PMU_FIXEDCOUNTER_REFCYCLES) - c.featureSet.set(PMU_FIXEDCOUNTER_TOPDOWN_SLOTS) - } - if ebx != 0x0 { - if ((ebx >> 0) & 1) == 0 { - c.featureSet.set(PMU_FIXEDCOUNTER_INSTRUCTIONS) - } - if ((ebx >> 1) & 1) == 0 { - c.featureSet.set(PMU_FIXEDCOUNTER_CYCLES) - } - if ((ebx >> 2) & 1) == 0 { - c.featureSet.set(PMU_FIXEDCOUNTER_REFCYCLES) - } - if ((ebx >> 3) & 1) == 0 { - c.featureSet.set(PMU_FIXEDCOUNTER_TOPDOWN_SLOTS) - } - } - } - return info -} diff --git a/vendor/github.com/klauspost/cpuid/v2/cpuid_386.s b/vendor/github.com/klauspost/cpuid/v2/cpuid_386.s deleted file mode 100644 index 8587c3a1..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/cpuid_386.s +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. - -//+build 386,!gccgo,!noasm,!appengine - -// func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32) -TEXT ·asmCpuid(SB), 7, $0 - XORL CX, CX - MOVL op+0(FP), AX - CPUID - MOVL AX, eax+4(FP) - MOVL BX, ebx+8(FP) - MOVL CX, ecx+12(FP) - MOVL DX, edx+16(FP) - RET - -// func asmCpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) -TEXT ·asmCpuidex(SB), 7, $0 - MOVL op+0(FP), AX - MOVL op2+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(index uint32) (eax, edx uint32) -TEXT ·asmXgetbv(SB), 7, $0 - MOVL index+0(FP), CX - BYTE $0x0f; BYTE $0x01; BYTE $0xd0 // XGETBV - MOVL AX, eax+4(FP) - MOVL DX, edx+8(FP) - RET - -// func asmRdtscpAsm() (eax, ebx, ecx, edx uint32) -TEXT ·asmRdtscpAsm(SB), 7, $0 - BYTE $0x0F; BYTE $0x01; BYTE $0xF9 // RDTSCP - MOVL AX, eax+0(FP) - MOVL BX, ebx+4(FP) - MOVL CX, ecx+8(FP) - MOVL DX, edx+12(FP) - RET - -// func asmDarwinHasAVX512() bool -TEXT ·asmDarwinHasAVX512(SB), 7, $0 - MOVL $0, eax+0(FP) - RET diff --git a/vendor/github.com/klauspost/cpuid/v2/cpuid_amd64.s b/vendor/github.com/klauspost/cpuid/v2/cpuid_amd64.s deleted file mode 100644 index bc11f894..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/cpuid_amd64.s +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. - -//+build amd64,!gccgo,!noasm,!appengine - -// func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32) -TEXT ·asmCpuid(SB), 7, $0 - XORQ CX, CX - MOVL op+0(FP), AX - CPUID - MOVL AX, eax+8(FP) - MOVL BX, ebx+12(FP) - MOVL CX, ecx+16(FP) - MOVL DX, edx+20(FP) - RET - -// func asmCpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) -TEXT ·asmCpuidex(SB), 7, $0 - MOVL op+0(FP), AX - MOVL op2+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 asmXgetbv(index uint32) (eax, edx uint32) -TEXT ·asmXgetbv(SB), 7, $0 - MOVL index+0(FP), CX - BYTE $0x0f; BYTE $0x01; BYTE $0xd0 // XGETBV - MOVL AX, eax+8(FP) - MOVL DX, edx+12(FP) - RET - -// func asmRdtscpAsm() (eax, ebx, ecx, edx uint32) -TEXT ·asmRdtscpAsm(SB), 7, $0 - BYTE $0x0F; BYTE $0x01; BYTE $0xF9 // RDTSCP - MOVL AX, eax+0(FP) - MOVL BX, ebx+4(FP) - MOVL CX, ecx+8(FP) - MOVL DX, edx+12(FP) - RET - -// From https://go-review.googlesource.com/c/sys/+/285572/ -// func asmDarwinHasAVX512() bool -TEXT ·asmDarwinHasAVX512(SB), 7, $0-1 - MOVB $0, ret+0(FP) // default to false - -#ifdef GOOS_darwin // return if not darwin -#ifdef GOARCH_amd64 // return if not amd64 -// These values from: -// https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/osfmk/i386/cpu_capabilities.h -#define commpage64_base_address 0x00007fffffe00000 -#define commpage64_cpu_capabilities64 (commpage64_base_address+0x010) -#define commpage64_version (commpage64_base_address+0x01E) -#define hasAVX512F 0x0000004000000000 - MOVQ $commpage64_version, BX - MOVW (BX), AX - CMPW AX, $13 // versions < 13 do not support AVX512 - JL no_avx512 - MOVQ $commpage64_cpu_capabilities64, BX - MOVQ (BX), AX - MOVQ $hasAVX512F, CX - ANDQ CX, AX - JZ no_avx512 - MOVB $1, ret+0(FP) - -no_avx512: -#endif -#endif - RET - diff --git a/vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s b/vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s deleted file mode 100644 index b196f78e..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. - -//+build arm64,!gccgo,!noasm,!appengine - -// See https://www.kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt - -// func getMidr -TEXT ·getMidr(SB), 7, $0 - WORD $0xd5380000 // mrs x0, midr_el1 /* Main ID Register */ - MOVD R0, midr+0(FP) - RET - -// func getProcFeatures -TEXT ·getProcFeatures(SB), 7, $0 - WORD $0xd5380400 // mrs x0, id_aa64pfr0_el1 /* Processor Feature Register 0 */ - MOVD R0, procFeatures+0(FP) - RET - -// func getInstAttributes -TEXT ·getInstAttributes(SB), 7, $0 - WORD $0xd5380600 // mrs x0, id_aa64isar0_el1 /* Instruction Set Attribute Register 0 */ - WORD $0xd5380621 // mrs x1, id_aa64isar1_el1 /* Instruction Set Attribute Register 1 */ - MOVD R0, instAttrReg0+0(FP) - MOVD R1, instAttrReg1+8(FP) - RET - -TEXT ·getVectorLength(SB), 7, $0 - WORD $0xd2800002 // mov x2, #0 - WORD $0x04225022 // addvl x2, x2, #1 - WORD $0xd37df042 // lsl x2, x2, #3 - WORD $0xd2800003 // mov x3, #0 - WORD $0x04635023 // addpl x3, x3, #1 - WORD $0xd37df063 // lsl x3, x3, #3 - MOVD R2, vl+0(FP) - MOVD R3, pl+8(FP) - RET diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go b/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go deleted file mode 100644 index 9ae32d60..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. - -//go:build arm64 && !gccgo && !noasm && !appengine -// +build arm64,!gccgo,!noasm,!appengine - -package cpuid - -import "runtime" - -func getMidr() (midr uint64) -func getProcFeatures() (procFeatures uint64) -func getInstAttributes() (instAttrReg0, instAttrReg1 uint64) -func getVectorLength() (vl, pl uint64) - -func initCPU() { - cpuid = func(uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } - cpuidex = func(x, y uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } - xgetbv = func(uint32) (a, b uint32) { return 0, 0 } - rdtscpAsm = func() (a, b, c, d uint32) { return 0, 0, 0, 0 } -} - -func addInfo(c *CPUInfo, safe bool) { - // Seems to be safe to assume on ARM64 - c.CacheLine = 64 - detectOS(c) - - // ARM64 disabled since it may crash if interrupt is not intercepted by OS. - if safe && !c.Has(ARMCPUID) && runtime.GOOS != "freebsd" { - return - } - midr := getMidr() - - // MIDR_EL1 - Main ID Register - // https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/midr_el1 - // x--------------------------------------------------x - // | Name | bits | visible | - // |--------------------------------------------------| - // | Implementer | [31-24] | y | - // |--------------------------------------------------| - // | Variant | [23-20] | y | - // |--------------------------------------------------| - // | Architecture | [19-16] | y | - // |--------------------------------------------------| - // | PartNum | [15-4] | y | - // |--------------------------------------------------| - // | Revision | [3-0] | y | - // x--------------------------------------------------x - - switch (midr >> 24) & 0xff { - case 0xC0: - c.VendorString = "Ampere Computing" - c.VendorID = Ampere - case 0x41: - c.VendorString = "Arm Limited" - c.VendorID = ARM - case 0x42: - c.VendorString = "Broadcom Corporation" - c.VendorID = Broadcom - case 0x43: - c.VendorString = "Cavium Inc" - c.VendorID = Cavium - case 0x44: - c.VendorString = "Digital Equipment Corporation" - c.VendorID = DEC - case 0x46: - c.VendorString = "Fujitsu Ltd" - c.VendorID = Fujitsu - case 0x49: - c.VendorString = "Infineon Technologies AG" - c.VendorID = Infineon - case 0x4D: - c.VendorString = "Motorola or Freescale Semiconductor Inc" - c.VendorID = Motorola - case 0x4E: - c.VendorString = "NVIDIA Corporation" - c.VendorID = NVIDIA - case 0x50: - c.VendorString = "Applied Micro Circuits Corporation" - c.VendorID = AMCC - case 0x51: - c.VendorString = "Qualcomm Inc" - c.VendorID = Qualcomm - case 0x56: - c.VendorString = "Marvell International Ltd" - c.VendorID = Marvell - case 0x69: - c.VendorString = "Intel Corporation" - c.VendorID = Intel - } - - // Lower 4 bits: Architecture - // Architecture Meaning - // 0b0001 Armv4. - // 0b0010 Armv4T. - // 0b0011 Armv5 (obsolete). - // 0b0100 Armv5T. - // 0b0101 Armv5TE. - // 0b0110 Armv5TEJ. - // 0b0111 Armv6. - // 0b1111 Architectural features are individually identified in the ID_* registers, see 'ID registers'. - // Upper 4 bit: Variant - // An IMPLEMENTATION DEFINED variant number. - // Typically, this field is used to distinguish between different product variants, or major revisions of a product. - c.Family = int(midr>>16) & 0xff - - // PartNum, bits [15:4] - // An IMPLEMENTATION DEFINED primary part number for the device. - // On processors implemented by Arm, if the top four bits of the primary - // part number are 0x0 or 0x7, the variant and architecture are encoded differently. - // Revision, bits [3:0] - // An IMPLEMENTATION DEFINED revision number for the device. - c.Model = int(midr) & 0xffff - - procFeatures := getProcFeatures() - - // ID_AA64PFR0_EL1 - Processor Feature Register 0 - // x--------------------------------------------------x - // | Name | bits | visible | - // |--------------------------------------------------| - // | DIT | [51-48] | y | - // |--------------------------------------------------| - // | SVE | [35-32] | y | - // |--------------------------------------------------| - // | GIC | [27-24] | n | - // |--------------------------------------------------| - // | AdvSIMD | [23-20] | y | - // |--------------------------------------------------| - // | FP | [19-16] | y | - // |--------------------------------------------------| - // | EL3 | [15-12] | n | - // |--------------------------------------------------| - // | EL2 | [11-8] | n | - // |--------------------------------------------------| - // | EL1 | [7-4] | n | - // |--------------------------------------------------| - // | EL0 | [3-0] | n | - // x--------------------------------------------------x - - var f flagSet - // if procFeatures&(0xf<<48) != 0 { - // fmt.Println("DIT") - // } - f.setIf(procFeatures&(0xf<<32) != 0, SVE) - if procFeatures&(0xf<<20) != 15<<20 { - f.set(ASIMD) - // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64pfr0_el1 - // 0b0001 --> As for 0b0000, and also includes support for half-precision floating-point arithmetic. - f.setIf(procFeatures&(0xf<<20) == 1<<20, FPHP, ASIMDHP) - } - f.setIf(procFeatures&(0xf<<16) != 0, FP) - - instAttrReg0, instAttrReg1 := getInstAttributes() - - // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1 - // - // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0 - // x--------------------------------------------------x - // | Name | bits | visible | - // |--------------------------------------------------| - // | RNDR | [63-60] | y | - // |--------------------------------------------------| - // | TLB | [59-56] | y | - // |--------------------------------------------------| - // | TS | [55-52] | y | - // |--------------------------------------------------| - // | FHM | [51-48] | y | - // |--------------------------------------------------| - // | DP | [47-44] | y | - // |--------------------------------------------------| - // | SM4 | [43-40] | y | - // |--------------------------------------------------| - // | SM3 | [39-36] | y | - // |--------------------------------------------------| - // | SHA3 | [35-32] | y | - // |--------------------------------------------------| - // | RDM | [31-28] | y | - // |--------------------------------------------------| - // | ATOMICS | [23-20] | y | - // |--------------------------------------------------| - // | CRC32 | [19-16] | y | - // |--------------------------------------------------| - // | SHA2 | [15-12] | y | - // |--------------------------------------------------| - // | SHA1 | [11-8] | y | - // |--------------------------------------------------| - // | AES | [7-4] | y | - // x--------------------------------------------------x - - f.setIf(instAttrReg0&(0xf<<60) != 0, RNDR) - f.setIf(instAttrReg0&(0xf<<56) != 0, TLB) - f.setIf(instAttrReg0&(0xf<<52) != 0, TS) - f.setIf(instAttrReg0&(0xf<<48) != 0, FHM) - f.setIf(instAttrReg0&(0xf<<44) != 0, ASIMDDP) - f.setIf(instAttrReg0&(0xf<<40) != 0, SM4) - f.setIf(instAttrReg0&(0xf<<36) != 0, SM3) - f.setIf(instAttrReg0&(0xf<<32) != 0, SHA3) - f.setIf(instAttrReg0&(0xf<<28) != 0, ASIMDRDM) - f.setIf(instAttrReg0&(0xf<<20) != 0, ATOMICS) - f.setIf(instAttrReg0&(0xf<<16) != 0, CRC32) - f.setIf(instAttrReg0&(0xf<<12) != 0, SHA2) - // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1 - // 0b0010 --> As 0b0001, plus SHA512H, SHA512H2, SHA512SU0, and SHA512SU1 instructions implemented. - f.setIf(instAttrReg0&(0xf<<12) == 2<<12, SHA512) - f.setIf(instAttrReg0&(0xf<<8) != 0, SHA1) - f.setIf(instAttrReg0&(0xf<<4) != 0, AESARM) - // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1 - // 0b0010 --> As for 0b0001, plus PMULL/PMULL2 instructions operating on 64-bit data quantities. - f.setIf(instAttrReg0&(0xf<<4) == 2<<4, PMULL) - - // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar1_el1 - // - // ID_AA64ISAR1_EL1 - Instruction set attribute register 1 - // x--------------------------------------------------x - // | Name | bits | visible | - // |--------------------------------------------------| - // | GPI | [31-28] | y | - // |--------------------------------------------------| - // | GPA | [27-24] | y | - // |--------------------------------------------------| - // | LRCPC | [23-20] | y | - // |--------------------------------------------------| - // | FCMA | [19-16] | y | - // |--------------------------------------------------| - // | JSCVT | [15-12] | y | - // |--------------------------------------------------| - // | API | [11-8] | y | - // |--------------------------------------------------| - // | APA | [7-4] | y | - // |--------------------------------------------------| - // | DPB | [3-0] | y | - // x--------------------------------------------------x - - // if instAttrReg1&(0xf<<28) != 0 { - // fmt.Println("GPI") - // } - f.setIf(instAttrReg1&(0xf<<28) != 24, GPA) - f.setIf(instAttrReg1&(0xf<<20) != 0, LRCPC) - f.setIf(instAttrReg1&(0xf<<16) != 0, FCMA) - f.setIf(instAttrReg1&(0xf<<12) != 0, JSCVT) - // if instAttrReg1&(0xf<<8) != 0 { - // fmt.Println("API") - // } - // if instAttrReg1&(0xf<<4) != 0 { - // fmt.Println("APA") - // } - f.setIf(instAttrReg1&(0xf<<0) != 0, DCPOP) - - // Store - c.featureSet.or(f) -} diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_ref.go b/vendor/github.com/klauspost/cpuid/v2/detect_ref.go deleted file mode 100644 index 574f9389..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/detect_ref.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. - -//go:build (!amd64 && !386 && !arm64) || gccgo || noasm || appengine -// +build !amd64,!386,!arm64 gccgo noasm appengine - -package cpuid - -func initCPU() { - cpuid = func(uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } - cpuidex = func(x, y uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } - xgetbv = func(uint32) (a, b uint32) { return 0, 0 } - rdtscpAsm = func() (a, b, c, d uint32) { return 0, 0, 0, 0 } - -} - -func addInfo(info *CPUInfo, safe bool) {} -func getVectorLength() (vl, pl uint64) { return 0, 0 } diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_x86.go b/vendor/github.com/klauspost/cpuid/v2/detect_x86.go deleted file mode 100644 index 14a56b93..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/detect_x86.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. - -//go:build (386 && !gccgo && !noasm && !appengine) || (amd64 && !gccgo && !noasm && !appengine) -// +build 386,!gccgo,!noasm,!appengine amd64,!gccgo,!noasm,!appengine - -package cpuid - -func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32) -func asmCpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) -func asmXgetbv(index uint32) (eax, edx uint32) -func asmRdtscpAsm() (eax, ebx, ecx, edx uint32) -func asmDarwinHasAVX512() bool - -func initCPU() { - cpuid = asmCpuid - cpuidex = asmCpuidex - xgetbv = asmXgetbv - rdtscpAsm = asmRdtscpAsm - darwinHasAVX512 = asmDarwinHasAVX512 -} - -func addInfo(c *CPUInfo, safe bool) { - c.maxFunc = maxFunctionID() - c.maxExFunc = maxExtendedFunction() - c.BrandName = brandName() - c.CacheLine = cacheLine() - c.Family, c.Model, c.Stepping = familyModel() - c.featureSet = support() - c.SGX = hasSGX(c.featureSet.inSet(SGX), c.featureSet.inSet(SGXLC)) - c.AMDMemEncryption = hasAMDMemEncryption(c.featureSet.inSet(SME) || c.featureSet.inSet(SEV)) - c.ThreadsPerCore = threadsPerCore() - c.LogicalCores = logicalCores() - c.PhysicalCores = physicalCores() - c.VendorID, c.VendorString = vendorID() - c.HypervisorVendorID, c.HypervisorVendorString = hypervisorVendorID() - c.AVX10Level = c.supportAVX10() - c.cacheSize() - c.frequencies() - if c.maxFunc >= 0x0A { - eax, ebx, _, edx := cpuid(0x0A) - c.PMU = parseLeaf0AH(c, eax, ebx, edx) - } -} - -func getVectorLength() (vl, pl uint64) { return 0, 0 } diff --git a/vendor/github.com/klauspost/cpuid/v2/featureid_string.go b/vendor/github.com/klauspost/cpuid/v2/featureid_string.go deleted file mode 100644 index 2888bae8..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/featureid_string.go +++ /dev/null @@ -1,308 +0,0 @@ -// Code generated by "stringer -type=FeatureID,Vendor"; DO NOT EDIT. - -package cpuid - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[ADX-1] - _ = x[AESNI-2] - _ = x[AMD3DNOW-3] - _ = x[AMD3DNOWEXT-4] - _ = x[AMXBF16-5] - _ = x[AMXFP16-6] - _ = x[AMXINT8-7] - _ = x[AMXFP8-8] - _ = x[AMXTILE-9] - _ = x[AMXTF32-10] - _ = x[AMXCOMPLEX-11] - _ = x[AMXTRANSPOSE-12] - _ = x[APX_F-13] - _ = x[AVX-14] - _ = x[AVX10-15] - _ = x[AVX10_128-16] - _ = x[AVX10_256-17] - _ = x[AVX10_512-18] - _ = x[AVX2-19] - _ = x[AVX512BF16-20] - _ = x[AVX512BITALG-21] - _ = x[AVX512BW-22] - _ = x[AVX512CD-23] - _ = x[AVX512DQ-24] - _ = x[AVX512ER-25] - _ = x[AVX512F-26] - _ = x[AVX512FP16-27] - _ = x[AVX512IFMA-28] - _ = x[AVX512PF-29] - _ = x[AVX512VBMI-30] - _ = x[AVX512VBMI2-31] - _ = x[AVX512VL-32] - _ = x[AVX512VNNI-33] - _ = x[AVX512VP2INTERSECT-34] - _ = x[AVX512VPOPCNTDQ-35] - _ = x[AVXIFMA-36] - _ = x[AVXNECONVERT-37] - _ = x[AVXSLOW-38] - _ = x[AVXVNNI-39] - _ = x[AVXVNNIINT8-40] - _ = x[AVXVNNIINT16-41] - _ = x[BHI_CTRL-42] - _ = x[BMI1-43] - _ = x[BMI2-44] - _ = x[CETIBT-45] - _ = x[CETSS-46] - _ = x[CLDEMOTE-47] - _ = x[CLMUL-48] - _ = x[CLZERO-49] - _ = x[CMOV-50] - _ = x[CMPCCXADD-51] - _ = x[CMPSB_SCADBS_SHORT-52] - _ = x[CMPXCHG8-53] - _ = x[CPBOOST-54] - _ = x[CPPC-55] - _ = x[CX16-56] - _ = x[EFER_LMSLE_UNS-57] - _ = x[ENQCMD-58] - _ = x[ERMS-59] - _ = x[F16C-60] - _ = x[FLUSH_L1D-61] - _ = x[FMA3-62] - _ = x[FMA4-63] - _ = x[FP128-64] - _ = x[FP256-65] - _ = x[FSRM-66] - _ = x[FXSR-67] - _ = x[FXSROPT-68] - _ = x[GFNI-69] - _ = x[HLE-70] - _ = x[HRESET-71] - _ = x[HTT-72] - _ = x[HWA-73] - _ = x[HYBRID_CPU-74] - _ = x[HYPERVISOR-75] - _ = x[IA32_ARCH_CAP-76] - _ = x[IA32_CORE_CAP-77] - _ = x[IBPB-78] - _ = x[IBPB_BRTYPE-79] - _ = x[IBRS-80] - _ = x[IBRS_PREFERRED-81] - _ = x[IBRS_PROVIDES_SMP-82] - _ = x[IBS-83] - _ = x[IBSBRNTRGT-84] - _ = x[IBSFETCHSAM-85] - _ = x[IBSFFV-86] - _ = x[IBSOPCNT-87] - _ = x[IBSOPCNTEXT-88] - _ = x[IBSOPSAM-89] - _ = x[IBSRDWROPCNT-90] - _ = x[IBSRIPINVALIDCHK-91] - _ = x[IBS_FETCH_CTLX-92] - _ = x[IBS_OPDATA4-93] - _ = x[IBS_OPFUSE-94] - _ = x[IBS_PREVENTHOST-95] - _ = x[IBS_ZEN4-96] - _ = x[IDPRED_CTRL-97] - _ = x[INT_WBINVD-98] - _ = x[INVLPGB-99] - _ = x[KEYLOCKER-100] - _ = x[KEYLOCKERW-101] - _ = x[LAHF-102] - _ = x[LAM-103] - _ = x[LBRVIRT-104] - _ = x[LZCNT-105] - _ = x[MCAOVERFLOW-106] - _ = x[MCDT_NO-107] - _ = x[MCOMMIT-108] - _ = x[MD_CLEAR-109] - _ = x[MMX-110] - _ = x[MMXEXT-111] - _ = x[MOVBE-112] - _ = x[MOVDIR64B-113] - _ = x[MOVDIRI-114] - _ = x[MOVSB_ZL-115] - _ = x[MOVU-116] - _ = x[MPX-117] - _ = x[MSRIRC-118] - _ = x[MSRLIST-119] - _ = x[MSR_PAGEFLUSH-120] - _ = x[NRIPS-121] - _ = x[NX-122] - _ = x[OSXSAVE-123] - _ = x[PCONFIG-124] - _ = x[POPCNT-125] - _ = x[PPIN-126] - _ = x[PREFETCHI-127] - _ = x[PSFD-128] - _ = x[RDPRU-129] - _ = x[RDRAND-130] - _ = x[RDSEED-131] - _ = x[RDTSCP-132] - _ = x[RRSBA_CTRL-133] - _ = x[RTM-134] - _ = x[RTM_ALWAYS_ABORT-135] - _ = x[SBPB-136] - _ = x[SERIALIZE-137] - _ = x[SEV-138] - _ = x[SEV_64BIT-139] - _ = x[SEV_ALTERNATIVE-140] - _ = x[SEV_DEBUGSWAP-141] - _ = x[SEV_ES-142] - _ = x[SEV_RESTRICTED-143] - _ = x[SEV_SNP-144] - _ = x[SGX-145] - _ = x[SGXLC-146] - _ = x[SGXPQC-147] - _ = x[SHA-148] - _ = x[SME-149] - _ = x[SME_COHERENT-150] - _ = x[SM3_X86-151] - _ = x[SM4_X86-152] - _ = x[SPEC_CTRL_SSBD-153] - _ = x[SRBDS_CTRL-154] - _ = x[SRSO_MSR_FIX-155] - _ = x[SRSO_NO-156] - _ = x[SRSO_USER_KERNEL_NO-157] - _ = x[SSE-158] - _ = x[SSE2-159] - _ = x[SSE3-160] - _ = x[SSE4-161] - _ = x[SSE42-162] - _ = x[SSE4A-163] - _ = x[SSSE3-164] - _ = x[STIBP-165] - _ = x[STIBP_ALWAYSON-166] - _ = x[STOSB_SHORT-167] - _ = x[SUCCOR-168] - _ = x[SVM-169] - _ = x[SVMDA-170] - _ = x[SVMFBASID-171] - _ = x[SVML-172] - _ = x[SVMNP-173] - _ = x[SVMPF-174] - _ = x[SVMPFT-175] - _ = x[SYSCALL-176] - _ = x[SYSEE-177] - _ = x[TBM-178] - _ = x[TDX_GUEST-179] - _ = x[TLB_FLUSH_NESTED-180] - _ = x[TME-181] - _ = x[TOPEXT-182] - _ = x[TSA_L1_NO-183] - _ = x[TSA_SQ_NO-184] - _ = x[TSA_VERW_CLEAR-185] - _ = x[TSCRATEMSR-186] - _ = x[TSXLDTRK-187] - _ = x[VAES-188] - _ = x[VMCBCLEAN-189] - _ = x[VMPL-190] - _ = x[VMSA_REGPROT-191] - _ = x[VMX-192] - _ = x[VPCLMULQDQ-193] - _ = x[VTE-194] - _ = x[WAITPKG-195] - _ = x[WBNOINVD-196] - _ = x[WRMSRNS-197] - _ = x[X87-198] - _ = x[XGETBV1-199] - _ = x[XOP-200] - _ = x[XSAVE-201] - _ = x[XSAVEC-202] - _ = x[XSAVEOPT-203] - _ = x[XSAVES-204] - _ = x[AESARM-205] - _ = x[ARMCPUID-206] - _ = x[ASIMD-207] - _ = x[ASIMDDP-208] - _ = x[ASIMDHP-209] - _ = x[ASIMDRDM-210] - _ = x[ATOMICS-211] - _ = x[CRC32-212] - _ = x[DCPOP-213] - _ = x[EVTSTRM-214] - _ = x[FCMA-215] - _ = x[FHM-216] - _ = x[FP-217] - _ = x[FPHP-218] - _ = x[GPA-219] - _ = x[JSCVT-220] - _ = x[LRCPC-221] - _ = x[PMULL-222] - _ = x[RNDR-223] - _ = x[TLB-224] - _ = x[TS-225] - _ = x[SHA1-226] - _ = x[SHA2-227] - _ = x[SHA3-228] - _ = x[SHA512-229] - _ = x[SM3-230] - _ = x[SM4-231] - _ = x[SVE-232] - _ = x[PMU_FIXEDCOUNTER_CYCLES-233] - _ = x[PMU_FIXEDCOUNTER_REFCYCLES-234] - _ = x[PMU_FIXEDCOUNTER_INSTRUCTIONS-235] - _ = x[PMU_FIXEDCOUNTER_TOPDOWN_SLOTS-236] - _ = x[lastID-237] - _ = x[firstID-0] -} - -const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXFP8AMXTILEAMXTF32AMXCOMPLEXAMXTRANSPOSEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8AVXVNNIINT16BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBPB_BRTYPEIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSBPBSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSGXPQCSHASMESME_COHERENTSM3_X86SM4_X86SPEC_CTRL_SSBDSRBDS_CTRLSRSO_MSR_FIXSRSO_NOSRSO_USER_KERNEL_NOSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSA_L1_NOTSA_SQ_NOTSA_VERW_CLEARTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFHMFPFPHPGPAJSCVTLRCPCPMULLRNDRTLBTSSHA1SHA2SHA3SHA512SM3SM4SVEPMU_FIXEDCOUNTER_CYCLESPMU_FIXEDCOUNTER_REFCYCLESPMU_FIXEDCOUNTER_INSTRUCTIONSPMU_FIXEDCOUNTER_TOPDOWN_SLOTSlastID" - -var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 61, 68, 75, 85, 97, 102, 105, 110, 119, 128, 137, 141, 151, 163, 171, 179, 187, 195, 202, 212, 222, 230, 240, 251, 259, 269, 287, 302, 309, 321, 328, 335, 346, 358, 366, 370, 374, 380, 385, 393, 398, 404, 408, 417, 435, 443, 450, 454, 458, 472, 478, 482, 486, 495, 499, 503, 508, 513, 517, 521, 528, 532, 535, 541, 544, 547, 557, 567, 580, 593, 597, 608, 612, 626, 643, 646, 656, 667, 673, 681, 692, 700, 712, 728, 742, 753, 763, 778, 786, 797, 807, 814, 823, 833, 837, 840, 847, 852, 863, 870, 877, 885, 888, 894, 899, 908, 915, 923, 927, 930, 936, 943, 956, 961, 963, 970, 977, 983, 987, 996, 1000, 1005, 1011, 1017, 1023, 1033, 1036, 1052, 1056, 1065, 1068, 1077, 1092, 1105, 1111, 1125, 1132, 1135, 1140, 1146, 1149, 1152, 1164, 1171, 1178, 1192, 1202, 1214, 1221, 1240, 1243, 1247, 1251, 1255, 1260, 1265, 1270, 1275, 1289, 1300, 1306, 1309, 1314, 1323, 1327, 1332, 1337, 1343, 1350, 1355, 1358, 1367, 1383, 1386, 1392, 1401, 1410, 1424, 1434, 1442, 1446, 1455, 1459, 1471, 1474, 1484, 1487, 1494, 1502, 1509, 1512, 1519, 1522, 1527, 1533, 1541, 1547, 1553, 1561, 1566, 1573, 1580, 1588, 1595, 1600, 1605, 1612, 1616, 1619, 1621, 1625, 1628, 1633, 1638, 1643, 1647, 1650, 1652, 1656, 1660, 1664, 1670, 1673, 1676, 1679, 1702, 1728, 1757, 1787, 1793} - -func (i FeatureID) String() string { - if i < 0 || i >= FeatureID(len(_FeatureID_index)-1) { - return "FeatureID(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _FeatureID_name[_FeatureID_index[i]:_FeatureID_index[i+1]] -} -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[VendorUnknown-0] - _ = x[Intel-1] - _ = x[AMD-2] - _ = x[VIA-3] - _ = x[Transmeta-4] - _ = x[NSC-5] - _ = x[KVM-6] - _ = x[MSVM-7] - _ = x[VMware-8] - _ = x[XenHVM-9] - _ = x[Bhyve-10] - _ = x[Hygon-11] - _ = x[SiS-12] - _ = x[RDC-13] - _ = x[Ampere-14] - _ = x[ARM-15] - _ = x[Broadcom-16] - _ = x[Cavium-17] - _ = x[DEC-18] - _ = x[Fujitsu-19] - _ = x[Infineon-20] - _ = x[Motorola-21] - _ = x[NVIDIA-22] - _ = x[AMCC-23] - _ = x[Qualcomm-24] - _ = x[Marvell-25] - _ = x[QEMU-26] - _ = x[QNX-27] - _ = x[ACRN-28] - _ = x[SRE-29] - _ = x[Apple-30] - _ = x[lastVendor-31] -} - -const _Vendor_name = "VendorUnknownIntelAMDVIATransmetaNSCKVMMSVMVMwareXenHVMBhyveHygonSiSRDCAmpereARMBroadcomCaviumDECFujitsuInfineonMotorolaNVIDIAAMCCQualcommMarvellQEMUQNXACRNSREApplelastVendor" - -var _Vendor_index = [...]uint8{0, 13, 18, 21, 24, 33, 36, 39, 43, 49, 55, 60, 65, 68, 71, 77, 80, 88, 94, 97, 104, 112, 120, 126, 130, 138, 145, 149, 152, 156, 159, 164, 174} - -func (i Vendor) String() string { - if i < 0 || i >= Vendor(len(_Vendor_index)-1) { - return "Vendor(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _Vendor_name[_Vendor_index[i]:_Vendor_index[i+1]] -} diff --git a/vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go deleted file mode 100644 index da07522e..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2020 Klaus Post, released under MIT License. See LICENSE file. - -package cpuid - -import ( - "runtime" - "strings" - - "golang.org/x/sys/unix" -) - -func detectOS(c *CPUInfo) bool { - if runtime.GOOS != "ios" { - tryToFillCPUInfoFomSysctl(c) - } - // There are no hw.optional sysctl values for the below features on Mac OS 11.0 - // to detect their supported state dynamically. Assume the CPU features that - // Apple Silicon M1 supports to be available as a minimal set of features - // to all Go programs running on darwin/arm64. - // TODO: Add more if we know them. - c.featureSet.setIf(runtime.GOOS != "ios", AESARM, PMULL, SHA1, SHA2) - - return true -} - -func sysctlGetBool(name string) bool { - value, err := unix.SysctlUint32(name) - if err != nil { - return false - } - return value != 0 -} - -func sysctlGetString(name string) string { - value, err := unix.Sysctl(name) - if err != nil { - return "" - } - return value -} - -func sysctlGetInt(unknown int, names ...string) int { - for _, name := range names { - value, err := unix.SysctlUint32(name) - if err != nil { - continue - } - if value != 0 { - return int(value) - } - } - return unknown -} - -func sysctlGetInt64(unknown int, names ...string) int { - for _, name := range names { - value64, err := unix.SysctlUint64(name) - if err != nil { - continue - } - if int(value64) != unknown { - return int(value64) - } - } - return unknown -} - -func setFeature(c *CPUInfo, feature FeatureID, aliases ...string) { - for _, alias := range aliases { - set := sysctlGetBool(alias) - c.featureSet.setIf(set, feature) - if set { - break - } - } -} - -func tryToFillCPUInfoFomSysctl(c *CPUInfo) { - c.BrandName = sysctlGetString("machdep.cpu.brand_string") - - if len(c.BrandName) != 0 { - c.VendorString = strings.Fields(c.BrandName)[0] - } - - c.PhysicalCores = sysctlGetInt(runtime.NumCPU(), "hw.physicalcpu") - c.ThreadsPerCore = sysctlGetInt(1, "machdep.cpu.thread_count", "kern.num_threads") / - sysctlGetInt(1, "hw.physicalcpu") - c.LogicalCores = sysctlGetInt(runtime.NumCPU(), "machdep.cpu.core_count") - c.Family = sysctlGetInt(0, "machdep.cpu.family", "hw.cpufamily") - c.Model = sysctlGetInt(0, "machdep.cpu.model") - c.CacheLine = sysctlGetInt64(0, "hw.cachelinesize") - c.Cache.L1I = sysctlGetInt64(-1, "hw.l1icachesize") - c.Cache.L1D = sysctlGetInt64(-1, "hw.l1dcachesize") - c.Cache.L2 = sysctlGetInt64(-1, "hw.l2cachesize") - c.Cache.L3 = sysctlGetInt64(-1, "hw.l3cachesize") - - // ARM features: - // - // Note: On some Apple Silicon system, some feats have aliases. See: - // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics - // When so, we look at all aliases and consider a feature available when at least one identifier matches. - setFeature(c, AESARM, "hw.optional.arm.FEAT_AES") // AES instructions - setFeature(c, ASIMD, "hw.optional.arm.AdvSIMD", "hw.optional.neon") // Advanced SIMD - setFeature(c, ASIMDDP, "hw.optional.arm.FEAT_DotProd") // SIMD Dot Product - setFeature(c, ASIMDHP, "hw.optional.arm.AdvSIMD_HPFPCvt", "hw.optional.neon_hpfp") // Advanced SIMD half-precision floating point - setFeature(c, ASIMDRDM, "hw.optional.arm.FEAT_RDM") // Rounding Double Multiply Accumulate/Subtract - setFeature(c, ATOMICS, "hw.optional.arm.FEAT_LSE", "hw.optional.armv8_1_atomics") // Large System Extensions (LSE) - setFeature(c, CRC32, "hw.optional.arm.FEAT_CRC32", "hw.optional.armv8_crc32") // CRC32/CRC32C instructions - setFeature(c, DCPOP, "hw.optional.arm.FEAT_DPB") // Data cache clean to Point of Persistence (DC CVAP) - setFeature(c, EVTSTRM, "hw.optional.arm.FEAT_ECV") // Generic timer - setFeature(c, FCMA, "hw.optional.arm.FEAT_FCMA", "hw.optional.armv8_3_compnum") // Floating point complex number addition and multiplication - setFeature(c, FHM, "hw.optional.armv8_2_fhm", "hw.optional.arm.FEAT_FHM") // FMLAL and FMLSL instructions - setFeature(c, FP, "hw.optional.floatingpoint") // Single-precision and double-precision floating point - setFeature(c, FPHP, "hw.optional.arm.FEAT_FP16", "hw.optional.neon_fp16") // Half-precision floating point - setFeature(c, GPA, "hw.optional.arm.FEAT_PAuth") // Generic Pointer Authentication - setFeature(c, JSCVT, "hw.optional.arm.FEAT_JSCVT") // Javascript-style double->int convert (FJCVTZS) - setFeature(c, LRCPC, "hw.optional.arm.FEAT_LRCPC") // Weaker release consistency (LDAPR, etc) - setFeature(c, PMULL, "hw.optional.arm.FEAT_PMULL") // Polynomial Multiply instructions (PMULL/PMULL2) - setFeature(c, RNDR, "hw.optional.arm.FEAT_RNG") // Random Number instructions - setFeature(c, TLB, "hw.optional.arm.FEAT_TLBIOS", "hw.optional.arm.FEAT_TLBIRANGE") // Outer Shareable and TLB range maintenance instructions - setFeature(c, TS, "hw.optional.arm.FEAT_FlagM", "hw.optional.arm.FEAT_FlagM2") // Flag manipulation instructions - setFeature(c, SHA1, "hw.optional.arm.FEAT_SHA1") // SHA-1 instructions (SHA1C, etc) - setFeature(c, SHA2, "hw.optional.arm.FEAT_SHA256") // SHA-2 instructions (SHA256H, etc) - setFeature(c, SHA3, "hw.optional.arm.FEAT_SHA3") // SHA-3 instructions (EOR3, RAXI, XAR, BCAX) - setFeature(c, SHA512, "hw.optional.arm.FEAT_SHA512") // SHA512 instructions - setFeature(c, SM3, "hw.optional.arm.FEAT_SM3") // SM3 instructions - setFeature(c, SM4, "hw.optional.arm.FEAT_SM4") // SM4 instructions - setFeature(c, SVE, "hw.optional.arm.FEAT_SVE") // Scalable Vector Extension -} diff --git a/vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go deleted file mode 100644 index d96d2443..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) 2020 Klaus Post, released under MIT License. See LICENSE file. - -// 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 located -// here https://github.com/golang/sys/blob/master/LICENSE - -package cpuid - -import ( - "encoding/binary" - "io/ioutil" - "runtime" -) - -// HWCAP bits. -const ( - hwcap_FP = 1 << 0 - hwcap_ASIMD = 1 << 1 - hwcap_EVTSTRM = 1 << 2 - hwcap_AES = 1 << 3 - hwcap_PMULL = 1 << 4 - hwcap_SHA1 = 1 << 5 - hwcap_SHA2 = 1 << 6 - hwcap_CRC32 = 1 << 7 - hwcap_ATOMICS = 1 << 8 - hwcap_FPHP = 1 << 9 - hwcap_ASIMDHP = 1 << 10 - hwcap_CPUID = 1 << 11 - hwcap_ASIMDRDM = 1 << 12 - hwcap_JSCVT = 1 << 13 - hwcap_FCMA = 1 << 14 - hwcap_LRCPC = 1 << 15 - hwcap_DCPOP = 1 << 16 - hwcap_SHA3 = 1 << 17 - hwcap_SM3 = 1 << 18 - hwcap_SM4 = 1 << 19 - hwcap_ASIMDDP = 1 << 20 - hwcap_SHA512 = 1 << 21 - hwcap_SVE = 1 << 22 - hwcap_ASIMDFHM = 1 << 23 - hwcap_DIT = 1 << 24 - hwcap_USCAT = 1 << 25 - hwcap_ILRCPC = 1 << 26 - hwcap_FLAGM = 1 << 27 - hwcap_SSBS = 1 << 28 - hwcap_SB = 1 << 29 - hwcap_PACA = 1 << 30 - hwcap_PACG = 1 << 31 - hwcap_GCS = 1 << 32 - - hwcap2_DCPODP = 1 << 0 - hwcap2_SVE2 = 1 << 1 - hwcap2_SVEAES = 1 << 2 - hwcap2_SVEPMULL = 1 << 3 - hwcap2_SVEBITPERM = 1 << 4 - hwcap2_SVESHA3 = 1 << 5 - hwcap2_SVESM4 = 1 << 6 - hwcap2_FLAGM2 = 1 << 7 - hwcap2_FRINT = 1 << 8 - hwcap2_SVEI8MM = 1 << 9 - hwcap2_SVEF32MM = 1 << 10 - hwcap2_SVEF64MM = 1 << 11 - hwcap2_SVEBF16 = 1 << 12 - hwcap2_I8MM = 1 << 13 - hwcap2_BF16 = 1 << 14 - hwcap2_DGH = 1 << 15 - hwcap2_RNG = 1 << 16 - hwcap2_BTI = 1 << 17 - hwcap2_MTE = 1 << 18 - hwcap2_ECV = 1 << 19 - hwcap2_AFP = 1 << 20 - hwcap2_RPRES = 1 << 21 - hwcap2_MTE3 = 1 << 22 - hwcap2_SME = 1 << 23 - hwcap2_SME_I16I64 = 1 << 24 - hwcap2_SME_F64F64 = 1 << 25 - hwcap2_SME_I8I32 = 1 << 26 - hwcap2_SME_F16F32 = 1 << 27 - hwcap2_SME_B16F32 = 1 << 28 - hwcap2_SME_F32F32 = 1 << 29 - hwcap2_SME_FA64 = 1 << 30 - hwcap2_WFXT = 1 << 31 - hwcap2_EBF16 = 1 << 32 - hwcap2_SVE_EBF16 = 1 << 33 - hwcap2_CSSC = 1 << 34 - hwcap2_RPRFM = 1 << 35 - hwcap2_SVE2P1 = 1 << 36 - hwcap2_SME2 = 1 << 37 - hwcap2_SME2P1 = 1 << 38 - hwcap2_SME_I16I32 = 1 << 39 - hwcap2_SME_BI32I32 = 1 << 40 - hwcap2_SME_B16B16 = 1 << 41 - hwcap2_SME_F16F16 = 1 << 42 - hwcap2_MOPS = 1 << 43 - hwcap2_HBC = 1 << 44 - hwcap2_SVE_B16B16 = 1 << 45 - hwcap2_LRCPC3 = 1 << 46 - hwcap2_LSE128 = 1 << 47 - hwcap2_FPMR = 1 << 48 - hwcap2_LUT = 1 << 49 - hwcap2_FAMINMAX = 1 << 50 - hwcap2_F8CVT = 1 << 51 - hwcap2_F8FMA = 1 << 52 - hwcap2_F8DP4 = 1 << 53 - hwcap2_F8DP2 = 1 << 54 - hwcap2_F8E4M3 = 1 << 55 - hwcap2_F8E5M2 = 1 << 56 - hwcap2_SME_LUTV2 = 1 << 57 - hwcap2_SME_F8F16 = 1 << 58 - hwcap2_SME_F8F32 = 1 << 59 - hwcap2_SME_SF8FMA = 1 << 60 - hwcap2_SME_SF8DP4 = 1 << 61 - hwcap2_SME_SF8DP2 = 1 << 62 - hwcap2_POE = 1 << 63 -) - -func detectOS(c *CPUInfo) bool { - // For now assuming no hyperthreading is reasonable. - c.LogicalCores = runtime.NumCPU() - c.PhysicalCores = c.LogicalCores - c.ThreadsPerCore = 1 - if hwcap == 0 { - // We did not get values from the runtime. - // Try reading /proc/self/auxv - - // From https://github.com/golang/sys - const ( - _AT_HWCAP = 16 - _AT_HWCAP2 = 26 - - uintSize = int(32 << (^uint(0) >> 63)) - ) - - buf, err := ioutil.ReadFile("/proc/self/auxv") - if err != nil { - // e.g. on android /proc/self/auxv is not accessible, so silently - // ignore the error and leave Initialized = false. On some - // architectures (e.g. arm64) doinit() implements a fallback - // readout and will set Initialized = true again. - return false - } - bo := binary.LittleEndian - for len(buf) >= 2*(uintSize/8) { - var tag, val uint - switch uintSize { - case 32: - tag = uint(bo.Uint32(buf[0:])) - val = uint(bo.Uint32(buf[4:])) - buf = buf[8:] - case 64: - tag = uint(bo.Uint64(buf[0:])) - val = uint(bo.Uint64(buf[8:])) - buf = buf[16:] - } - switch tag { - case _AT_HWCAP: - hwcap = val - case _AT_HWCAP2: - // Not used - } - } - if hwcap == 0 { - return false - } - } - - // HWCap was populated by the runtime from the auxiliary vector. - // Use HWCap information since reading aarch64 system registers - // is not supported in user space on older linux kernels. - c.featureSet.setIf(isSet(hwcap, hwcap_AES), AESARM) - c.featureSet.setIf(isSet(hwcap, hwcap_ASIMD), ASIMD) - c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDDP), ASIMDDP) - c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDHP), ASIMDHP) - c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDRDM), ASIMDRDM) - c.featureSet.setIf(isSet(hwcap, hwcap_CPUID), ARMCPUID) - c.featureSet.setIf(isSet(hwcap, hwcap_CRC32), CRC32) - c.featureSet.setIf(isSet(hwcap, hwcap_DCPOP), DCPOP) - c.featureSet.setIf(isSet(hwcap, hwcap_EVTSTRM), EVTSTRM) - c.featureSet.setIf(isSet(hwcap, hwcap_FCMA), FCMA) - c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDFHM), FHM) - c.featureSet.setIf(isSet(hwcap, hwcap_FP), FP) - c.featureSet.setIf(isSet(hwcap, hwcap_FPHP), FPHP) - c.featureSet.setIf(isSet(hwcap, hwcap_JSCVT), JSCVT) - c.featureSet.setIf(isSet(hwcap, hwcap_LRCPC), LRCPC) - c.featureSet.setIf(isSet(hwcap, hwcap_PMULL), PMULL) - c.featureSet.setIf(isSet(hwcap, hwcap2_RNG), RNDR) - // c.featureSet.setIf(isSet(hwcap, hwcap_), TLB) - // c.featureSet.setIf(isSet(hwcap, hwcap_), TS) - c.featureSet.setIf(isSet(hwcap, hwcap_SHA1), SHA1) - c.featureSet.setIf(isSet(hwcap, hwcap_SHA2), SHA2) - c.featureSet.setIf(isSet(hwcap, hwcap_SHA3), SHA3) - c.featureSet.setIf(isSet(hwcap, hwcap_SHA512), SHA512) - c.featureSet.setIf(isSet(hwcap, hwcap_SM3), SM3) - c.featureSet.setIf(isSet(hwcap, hwcap_SM4), SM4) - c.featureSet.setIf(isSet(hwcap, hwcap_SVE), SVE) - - // The Samsung S9+ kernel reports support for atomics, but not all cores - // actually support them, resulting in SIGILL. See issue #28431. - // TODO(elias.naur): Only disable the optimization on bad chipsets on android. - c.featureSet.setIf(isSet(hwcap, hwcap_ATOMICS) && runtime.GOOS != "android", ATOMICS) - - return true -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go deleted file mode 100644 index 8733ba34..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2020 Klaus Post, released under MIT License. See LICENSE file. - -//go:build arm64 && !linux && !darwin -// +build arm64,!linux,!darwin - -package cpuid - -import "runtime" - -func detectOS(c *CPUInfo) bool { - c.PhysicalCores = runtime.NumCPU() - // For now assuming 1 thread per core... - c.ThreadsPerCore = 1 - c.LogicalCores = c.PhysicalCores - return false -} diff --git a/vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go deleted file mode 100644 index f8f201b5..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2021 Klaus Post, released under MIT License. See LICENSE file. - -//go:build nounsafe -// +build nounsafe - -package cpuid - -var hwcap uint diff --git a/vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go b/vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go deleted file mode 100644 index 92af622e..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2021 Klaus Post, released under MIT License. See LICENSE file. - -//go:build !nounsafe -// +build !nounsafe - -package cpuid - -import _ "unsafe" // needed for go:linkname - -//go:linkname hwcap internal/cpu.HWCap -var hwcap uint diff --git a/vendor/github.com/klauspost/cpuid/v2/test-architectures.sh b/vendor/github.com/klauspost/cpuid/v2/test-architectures.sh deleted file mode 100644 index 471d986d..00000000 --- a/vendor/github.com/klauspost/cpuid/v2/test-architectures.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -set -e - -go tool dist list | while IFS=/ read os arch; do - echo "Checking $os/$arch..." - echo " normal" - GOARCH=$arch GOOS=$os go build -o /dev/null . - echo " noasm" - GOARCH=$arch GOOS=$os go build -tags noasm -o /dev/null . - echo " appengine" - GOARCH=$arch GOOS=$os go build -tags appengine -o /dev/null . - echo " noasm,appengine" - GOARCH=$arch GOOS=$os go build -tags 'appengine noasm' -o /dev/null . -done diff --git a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm index c4372cf9..d6444ae9 100644 --- a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm +++ b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm @@ -1,4 +1,4 @@ -FROM golang:1.27@sha256:512690a5660563b57d37ecc31129e7f136e831db2aed24a1dbeb8ad7380dc0fa +FROM golang:1.26@sha256:f96cc555eb8db430159a3aa6797cd5bae561945b7b0fe7d0e284c63a3b291609 ENV GOOS=linux ENV GOARCH=arm diff --git a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 index 6c472ef5..a149d842 100644 --- a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 +++ b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 @@ -1,4 +1,4 @@ -FROM golang:1.27@sha256:512690a5660563b57d37ecc31129e7f136e831db2aed24a1dbeb8ad7380dc0fa +FROM golang:1.26@sha256:f96cc555eb8db430159a3aa6797cd5bae561945b7b0fe7d0e284c63a3b291609 ENV GOOS=linux ENV GOARCH=arm64 diff --git a/vendor/github.com/pjbgf/sha1cd/Makefile b/vendor/github.com/pjbgf/sha1cd/Makefile index e746d62a..711c5e4d 100644 --- a/vendor/github.com/pjbgf/sha1cd/Makefile +++ b/vendor/github.com/pjbgf/sha1cd/Makefile @@ -1,18 +1,35 @@ FUZZ_TIME ?= 1m +FUZZ_FLAGS ?= + +# The fuzz targets of each package, along with the tags needed to build them. +FUZZ_TARGETS = ./test/:gofuzz .:sha1cd_asmtest export CGO_ENABLED := 1 +# The hashing tests run a second time with SHA-NI off, so that CPUs with it +# also cover the AVX2 fallback that CPUs without it use. .PHONY: test test: - go test -race -timeout 15s ./... + go test -race -timeout 15s -tags sha1cd_asmtest ./... + SHA1CD_TEST_NOSHANI=1 go test -race -timeout 15s -tags sha1cd_asmtest ./test/ .PHONY: bench bench: go test -benchmem -run=^$$ -bench ^Benchmark ./... +# go test only fuzzes a single target per invocation, so each one is run in +# turn for FUZZ_TIME. .PHONY: fuzz fuzz: - go test -tags gofuzz -fuzz=. -fuzztime=$(FUZZ_TIME) ./test/ + @set -e; for entry in $(FUZZ_TARGETS); do \ + pkg="$${entry%%:*}"; tags="$${entry##*:}"; \ + listed="$$(go test -tags "$$tags" -list '^Fuzz' "$$pkg")"; \ + for target in $$(echo "$$listed" | grep '^Fuzz'); do \ + echo "fuzzing $$target in $$pkg for $(FUZZ_TIME)"; \ + go test $(FUZZ_FLAGS) -tags "$$tags" -run '^$$' -fuzz "^$$target"'$$' \ + -fuzztime=$(FUZZ_TIME) "$$pkg"; \ + done; \ + done # Cross build project in arm/v7. build-arm: @@ -24,9 +41,11 @@ build-arm64: docker build -t sha1cd-arm64 -f Dockerfile.arm64 . docker run --rm sha1cd-arm64 -# Build with cgo disabled. +# Build with cgo disabled. Vetting every package (not just ./cgo) is what +# catches the cgo and non-cgo builds drifting apart in their exported API. build-nocgo: - CGO_ENABLED=0 go build ./cgo + CGO_ENABLED=0 go build ./... + CGO_ENABLED=0 go vet ./... # Run cross-compilation to assure supported architectures. cross-build: build-arm build-arm64 build-nocgo diff --git a/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu.go b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu.go new file mode 100644 index 00000000..dc078c44 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu.go @@ -0,0 +1,28 @@ +// Package cpu detects the CPU features that sha1cd dispatches on. +// +// It covers only what the assembly implementations need, which keeps +// start up cheap and avoids an external dependency. Every flag is false +// where a feature cannot be detected safely, which selects the generic +// implementation. +package cpu + +// X86 holds the features of the current amd64 CPU. All flags are false on +// other architectures. +var X86 struct { + // HasAVX and HasAVX2 are set only when the OS also preserves the YMM + // state, and HasAVX512F only when it preserves the ZMM and opmask state. + HasAVX bool + HasAVX2 bool + HasAVX512F bool + HasBMI1 bool + HasBMI2 bool + HasSHA bool + HasSSSE3 bool + HasSSE41 bool +} + +// ARM64 holds the features of the current arm64 CPU. All flags are false on +// other architectures. +var ARM64 struct { + HasSHA1 bool +} diff --git a/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_amd64.go b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_amd64.go new file mode 100644 index 00000000..84cbea6e --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_amd64.go @@ -0,0 +1,63 @@ +//go:build !noasm && gc && amd64 + +package cpu + +// cpuid and xgetbv are implemented in cpu_amd64.s. +func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) +func xgetbv() (eax, edx uint32) + +func init() { + const ( + // CPUID EAX=1: ECX + ssse3 = 1 << 9 + sse41 = 1 << 19 + osxsave = 1 << 27 + avx = 1 << 28 + + // CPUID EAX=7, ECX=0: EBX + bmi1 = 1 << 3 + avx2 = 1 << 5 + bmi2 = 1 << 8 + avx512f = 1 << 16 + sha = 1 << 29 + + // XCR0 + xmmState = 1 << 1 + ymmState = 1 << 2 + opmaskState = 1 << 5 + zmmHi256State = 1 << 6 + hi16ZMMState = 1 << 7 + zmmState = opmaskState | zmmHi256State | hi16ZMMState + ) + + maxID, _, _, _ := cpuid(0, 0) + if maxID < 1 { + return + } + + _, _, ecx1, _ := cpuid(1, 0) + X86.HasSSSE3 = ecx1&ssse3 != 0 + X86.HasSSE41 = ecx1&sse41 != 0 + + // VEX encoded instructions also need the OS to preserve the YMM state, + // which XGETBV reports once OSXSAVE says it is available. + // macOS enables the ZMM state lazily, so XCR0 may not report it and + // AVX-512 is then left unused, which is safe. + var osYMM, osZMM bool + if ecx1&(osxsave|avx) == osxsave|avx { + xcr0, _ := xgetbv() + osYMM = xcr0&(xmmState|ymmState) == xmmState|ymmState + osZMM = osYMM && xcr0&zmmState == zmmState + } + X86.HasAVX = osYMM + + if maxID < 7 { + return + } + _, ebx7, _, _ := cpuid(7, 0) + X86.HasAVX2 = osYMM && ebx7&avx2 != 0 + X86.HasAVX512F = osZMM && ebx7&avx512f != 0 + X86.HasBMI1 = ebx7&bmi1 != 0 + X86.HasBMI2 = ebx7&bmi2 != 0 + X86.HasSHA = ebx7&sha != 0 +} diff --git a/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_amd64.s b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_amd64.s new file mode 100644 index 00000000..158340dc --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_amd64.s @@ -0,0 +1,22 @@ +//go:build !noasm && gc && amd64 + +#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/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_darwin.go b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_darwin.go new file mode 100644 index 00000000..9a5dfdab --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_darwin.go @@ -0,0 +1,9 @@ +//go:build !noasm && gc && arm64 && darwin + +package cpu + +// Every Apple arm64 chip implements the ARMv8 Cryptographic Extension. The Go +// runtime makes the same assumption for crypto/sha1 on darwin/arm64. +func init() { + ARM64.HasSHA1 = true +} diff --git a/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_freebsd.go b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_freebsd.go new file mode 100644 index 00000000..dfd80dc1 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_freebsd.go @@ -0,0 +1,12 @@ +//go:build !noasm && gc && arm64 && freebsd + +package cpu + +// getisar0 is implemented in cpu_arm64_freebsd.s. +func getisar0() uint64 + +// FreeBSD emulates user space reads of ID_AA64ISAR0_EL1. Its SHA1 field, bits +// [11:8], is non zero when the SHA1 instructions are implemented. +func init() { + ARM64.HasSHA1 = (getisar0()>>8)&0xf != 0 +} diff --git a/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_freebsd.s b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_freebsd.s new file mode 100644 index 00000000..500c0ca9 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_freebsd.s @@ -0,0 +1,9 @@ +//go:build !noasm && gc && arm64 && freebsd + +#include "textflag.h" + +// func getisar0() uint64 +TEXT ·getisar0(SB), NOSPLIT, $0-8 + MRS ID_AA64ISAR0_EL1, R0 + MOVD R0, ret+0(FP) + RET diff --git a/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_linux.go b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_linux.go new file mode 100644 index 00000000..b074c1d0 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_linux.go @@ -0,0 +1,29 @@ +//go:build !noasm && gc && arm64 && linux + +package cpu + +import ( + "os" + _ "unsafe" // for go:linkname +) + +// runtime_getAuxv returns the auxiliary vector the kernel passed to the +// process. The runtime keeps it reachable for golang.org/x/sys/cpu and +// others, see go.dev/issue/57336 and go.dev/issue/67401. +// +//go:linkname runtime_getAuxv runtime.getAuxv +func runtime_getAuxv() []uintptr + +// Linux, and so Android, reports the SHA1 instructions through HWCAP, as +// not every kernel lets user space read the ID registers. +func init() { + hwcap, ok := hwcapFromAuxv(runtime_getAuxv()) + if !ok { + // The procfs copy may not be readable in restricted environments, + // in which case the generic implementation is used. + if buf, err := os.ReadFile("/proc/self/auxv"); err == nil { + hwcap, _ = hwcapFromProcAuxv(buf) + } + } + ARM64.HasSHA1 = hwcap&hwcapSHA1 != 0 +} diff --git a/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_windows.go b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_windows.go new file mode 100644 index 00000000..320be7ca --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/internal/cpu/cpu_arm64_windows.go @@ -0,0 +1,18 @@ +//go:build !noasm && gc && arm64 && windows + +package cpu + +import "syscall" + +// Windows reports the ARMv8 Cryptographic Extension, which includes the SHA1 +// instructions, through IsProcessorFeaturePresent. +func init() { + const _PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE = 30 + + proc := syscall.NewLazyDLL("kernel32.dll").NewProc("IsProcessorFeaturePresent") + if proc.Find() != nil { + return + } + ret, _, _ := proc.Call(_PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) + ARM64.HasSHA1 = ret != 0 +} diff --git a/vendor/github.com/pjbgf/sha1cd/internal/cpu/hwcap.go b/vendor/github.com/pjbgf/sha1cd/internal/cpu/hwcap.go new file mode 100644 index 00000000..17778c74 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/internal/cpu/hwcap.go @@ -0,0 +1,32 @@ +package cpu + +import "encoding/binary" + +const ( + _AT_HWCAP = 16 + + // hwcapSHA1 is HWCAP_SHA1 on linux/arm64. + hwcapSHA1 = 1 << 5 +) + +// hwcapFromAuxv returns AT_HWCAP from an auxiliary vector of tag and value +// pairs, and whether it was present. +func hwcapFromAuxv(auxv []uintptr) (uint64, bool) { + for i := 0; i+1 < len(auxv); i += 2 { + if auxv[i] == _AT_HWCAP { + return uint64(auxv[i+1]), true + } + } + return 0, false +} + +// hwcapFromProcAuxv does the same for the contents of /proc/self/auxv on a +// 64-bit little endian system. +func hwcapFromProcAuxv(buf []byte) (uint64, bool) { + for ; len(buf) >= 16; buf = buf[16:] { + if binary.LittleEndian.Uint64(buf) == _AT_HWCAP { + return binary.LittleEndian.Uint64(buf[8:]), true + } + } + return 0, false +} diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.go b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.go index 6b716abd..7642fc40 100644 --- a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.go +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.go @@ -4,30 +4,39 @@ package sha1cd import ( - "runtime" - - "github.com/klauspost/cpuid/v2" shared "github.com/pjbgf/sha1cd/internal" + "github.com/pjbgf/sha1cd/internal/cpu" + "github.com/pjbgf/sha1cd/ubc" ) -var hasSHANI = (runtime.GOARCH == "amd64" && - cpuid.CPU.Supports(cpuid.AVX) && - cpuid.CPU.Supports(cpuid.SHA) && - cpuid.CPU.Supports(cpuid.SSE3) && - cpuid.CPU.Supports(cpuid.SSE4)) +// hasSHANI reports whether blockAMD64 can run. It uses legacy SSE encodings +// only, so it does not need AVX and also runs on the Goldmont, Goldmont Plus +// and Tremont Atoms, which implement SHA-NI without AVX. +var hasSHANI = cpu.X86.HasSHA && cpu.X86.HasSSSE3 && cpu.X86.HasSSE41 -// blockAMD64 hashes the message p into the current state in h. +// blockAMD64 hashes a single chunk of p into the current state in h. +// p must hold at least one whole chunk. Anything beyond the first chunk is +// ignored, as the collision detection the caller runs afterwards inspects m1 +// and cs for one chunk only. // Both m1 and cs are used to store intermediate results which are used by the collision detection logic. // //go:noescape func blockAMD64(h []uint32, p []byte, m1 []uint32, cs [][5]uint32) func block(dig *digest, p []byte) { - if forceGeneric || !hasSHANI { + switch { + case forceGeneric: + blockGeneric(dig, p) + case hasSHANI: + blockSHANI(dig, p) + case hasAVX2: + blockAVX2(dig, p) + default: blockGeneric(dig, p) - return } +} +func blockSHANI(dig *digest, p []byte) { m1 := [shared.Rounds]uint32{} cs := [shared.PreStepState][shared.WordBuffers]uint32{} @@ -37,14 +46,15 @@ func block(dig *digest, p []byte) { chunk := p[:shared.Chunk] blockAMD64(dig.h[:], chunk, m1[:], cs[:]) - rectifyCompressionState(&m1, &cs) + // Assembly states need repair only when a disturbance vector survives. + if mask := ubc.CalculateDvMask(&m1); mask != 0 { + rectifyCompressionState(&m1, &cs) + if checkCollision(&m1, &cs, &dig.h, mask) { + dig.col = true - col := checkCollision(&m1, &cs, &dig.h) - if col { - dig.col = true - - blockAMD64(dig.h[:], chunk, m1[:], cs[:]) - blockAMD64(dig.h[:], chunk, m1[:], cs[:]) + blockAMD64(dig.h[:], chunk, m1[:], cs[:]) + blockAMD64(dig.h[:], chunk, m1[:], cs[:]) + } } p = p[shared.Chunk:] diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s index 061906a9..d38f9439 100644 --- a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s @@ -12,27 +12,30 @@ // - https://github.com/golang/go/blob/master/src/crypto/sha1/sha1block_amd64.s // Reverse the dword order in abcd via PSHUFD then store the 16 bytes in one -// move, instead of issuing four VPEXTRD's that each go through the store port. +// move, instead of issuing four PEXTRD's that each go through the store port. #define LOADCS(abcd, e, index, target) \ - VPSHUFD $0x1B, abcd, X8; \ - VMOVDQU X8, ((index*20)+0)(target); \ + PSHUFD $0x1B, abcd, X8; \ + MOVOU X8, ((index*20)+0)(target); \ MOVL e, ((index*20)+16)(target); #define LOADM1(m1, index, target) \ - VPSHUFD $0x1B, m1, X8; \ - VMOVDQU X8, ((index*16)+0)(target); + PSHUFD $0x1B, m1, X8; \ + MOVOU X8, ((index*16)+0)(target); // func blockAMD64(h []uint32, p []byte, m1 []uint32, cs [][5]uint32) -// Requires: AVX, SHA, SSE2, SSE4.1, SSSE3 +// Requires: SHA, SSE2, SSE4.1, SSSE3 TEXT ·blockAMD64(SB), NOSPLIT, $80-96 MOVQ h_base+0(FP), DI MOVQ p_base+24(FP), SI MOVQ p_len+32(FP), DX MOVQ m1_base+48(FP), R13 MOVQ cs_base+72(FP), R15 - CMPQ DX, $0x00 - JEQ done - ADDQ SI, DX + + // Truncate the length to whole chunks and skip the block if none is left. + // The caller compresses exactly one chunk per call, so that the collision + // detection it runs afterwards sees this chunk's m1 and cs. + ANDQ $-64, DX + JZ done // Allocate space on the stack for saving ABCD and E0, and align it to 16 bytes LEAQ 15(SP), AX @@ -42,52 +45,51 @@ TEXT ·blockAMD64(SB), NOSPLIT, $80-96 // Load initial hash state PINSRD $0x03, 16(DI), X5 - VMOVDQU (DI), X0 + MOVOU (DI), X0 PAND upper_mask<>+0(SB), X5 PSHUFD $0x1b, X0, X0 - VMOVDQA shuffle_mask<>+0(SB), X7 + MOVO shuffle_mask<>+0(SB), X7 -loop: // Save ABCD and E working values - VMOVDQA X5, (AX) - VMOVDQA X0, 16(AX) + MOVO X5, (AX) + MOVO X0, 16(AX) // LOAD CS 0 - VPEXTRD $3, X5, R12 + PEXTRD $3, X5, R12 LOADCS(X0, R12, 0, R15) // Rounds 0-3 - VMOVDQU (SI), X1 + MOVOU (SI), X1 PSHUFB X7, X1 PADDD X1, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1RNDS4 $0x00, X5, X0 LOADM1(X1, 0, R13) // Rounds 4-7 - VMOVDQU 16(SI), X2 + MOVOU 16(SI), X2 PSHUFB X7, X2 SHA1NEXTE X2, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1RNDS4 $0x00, X6, X0 SHA1MSG1 X2, X1 LOADM1(X2, 1, R13) // Rounds 8-11 - VMOVDQU 32(SI), X3 + MOVOU 32(SI), X3 PSHUFB X7, X3 SHA1NEXTE X3, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1RNDS4 $0x00, X5, X0 SHA1MSG1 X3, X2 PXOR X3, X1 LOADM1(X3, 2, R13) // Rounds 12-15 - VMOVDQU 48(SI), X4 + MOVOU 48(SI), X4 PSHUFB X7, X4 SHA1NEXTE X4, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1MSG2 X4, X1 SHA1RNDS4 $0x00, X6, X0 SHA1MSG1 X4, X3 @@ -96,7 +98,7 @@ loop: // Rounds 16-19 SHA1NEXTE X1, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1MSG2 X1, X2 SHA1RNDS4 $0x00, X5, X0 SHA1MSG1 X1, X4 @@ -105,7 +107,7 @@ loop: // Rounds 20-23 SHA1NEXTE X2, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1MSG2 X2, X3 SHA1RNDS4 $0x01, X6, X0 SHA1MSG1 X2, X1 @@ -114,7 +116,7 @@ loop: // Rounds 24-27 SHA1NEXTE X3, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1MSG2 X3, X4 SHA1RNDS4 $0x01, X5, X0 SHA1MSG1 X3, X2 @@ -123,7 +125,7 @@ loop: // Rounds 28-31 SHA1NEXTE X4, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1MSG2 X4, X1 SHA1RNDS4 $0x01, X6, X0 SHA1MSG1 X4, X3 @@ -132,7 +134,7 @@ loop: // Rounds 32-35 SHA1NEXTE X1, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1MSG2 X1, X2 SHA1RNDS4 $0x01, X5, X0 SHA1MSG1 X1, X4 @@ -141,7 +143,7 @@ loop: // Rounds 36-39 SHA1NEXTE X2, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1MSG2 X2, X3 SHA1RNDS4 $0x01, X6, X0 SHA1MSG1 X2, X1 @@ -150,7 +152,7 @@ loop: // Rounds 40-43 SHA1NEXTE X3, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1MSG2 X3, X4 SHA1RNDS4 $0x02, X5, X0 SHA1MSG1 X3, X2 @@ -159,7 +161,7 @@ loop: // Rounds 44-47 SHA1NEXTE X4, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1MSG2 X4, X1 SHA1RNDS4 $0x02, X6, X0 SHA1MSG1 X4, X3 @@ -168,21 +170,20 @@ loop: // Rounds 48-51 SHA1NEXTE X1, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1MSG2 X1, X2 SHA1RNDS4 $0x02, X5, X0 - VPEXTRD $0, X5, R12 SHA1MSG1 X1, X4 PXOR X1, X3 LOADM1(X1, 12, R13) // derive pre-round 56's E out of round 51's A. - VPEXTRD $3, X0, R12 + PEXTRD $3, X0, R12 ROLL $30, R12 // Rounds 52-55 SHA1NEXTE X2, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1MSG2 X2, X3 SHA1RNDS4 $0x02, X6, X0 SHA1MSG1 X2, X1 @@ -194,21 +195,20 @@ loop: // Rounds 56-59 SHA1NEXTE X3, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1MSG2 X3, X4 SHA1RNDS4 $0x02, X5, X0 - VPEXTRD $0, X5, R12 SHA1MSG1 X3, X2 PXOR X3, X1 LOADM1(X3, 14, R13) // derive pre-round 64's E out of round 59's A. - VPEXTRD $3, X0, R12 + PEXTRD $3, X0, R12 ROLL $30, R12 // Rounds 60-63 SHA1NEXTE X4, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1MSG2 X4, X1 SHA1RNDS4 $0x03, X6, X0 SHA1MSG1 X4, X3 @@ -220,7 +220,7 @@ loop: // Rounds 64-67 SHA1NEXTE X1, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1MSG2 X1, X2 SHA1RNDS4 $0x03, X5, X0 SHA1MSG1 X1, X4 @@ -229,7 +229,7 @@ loop: // Rounds 68-71 SHA1NEXTE X2, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1MSG2 X2, X3 SHA1RNDS4 $0x03, X6, X0 PXOR X2, X4 @@ -237,14 +237,14 @@ loop: // Rounds 72-75 SHA1NEXTE X3, X5 - VMOVDQA X0, X6 + MOVO X0, X6 SHA1MSG2 X3, X4 SHA1RNDS4 $0x03, X5, X0 LOADM1(X3, 18, R13) // Rounds 76-79 SHA1NEXTE X4, X6 - VMOVDQA X0, X5 + MOVO X0, X5 SHA1RNDS4 $0x03, X6, X0 LOADM1(X4, 19, R13) @@ -252,14 +252,9 @@ loop: SHA1NEXTE (AX), X5 PADDD 16(AX), X0 - // Check if we are done, if not return to the loop - ADDQ $0x40, SI - CMPQ SI, DX - JNE loop - // Write the hash state back to digest PSHUFD $0x1b, X0, X0 - VMOVDQU X0, (DI) + MOVOU X0, (DI) PEXTRD $0x03, X5, 16(DI) done: diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.go b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.go index f44f22da..98ac38c2 100644 --- a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.go +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.go @@ -4,15 +4,17 @@ package sha1cd import ( - "runtime" - - "github.com/klauspost/cpuid/v2" shared "github.com/pjbgf/sha1cd/internal" + "github.com/pjbgf/sha1cd/internal/cpu" + "github.com/pjbgf/sha1cd/ubc" ) -var hasSHA1 = (runtime.GOARCH == "arm64" && cpuid.CPU.Supports(cpuid.SHA1)) +var hasSHA1 = cpu.ARM64.HasSHA1 -// blockARM64 hashes the message p into the current state in h. +// blockARM64 hashes a single chunk of p into the current state in h. +// p must hold at least one whole chunk. Anything beyond the first chunk is +// ignored, as the collision detection the caller runs afterwards inspects m1 +// and cs for one chunk only. // Both m1 and cs are used to store intermediate results which are used by the collision detection logic. // //go:noescape @@ -34,13 +36,15 @@ func block(dig *digest, p []byte) { blockARM64(dig.h[:], chunk, m1[:], cs[:]) - rectifyCompressionState(&m1, &cs) - col := checkCollision(&m1, &cs, &dig.h) - if col { - dig.col = true + // Assembly states need repair only when a disturbance vector survives. + if mask := ubc.CalculateDvMask(&m1); mask != 0 { + rectifyCompressionState(&m1, &cs) + if checkCollision(&m1, &cs, &dig.h, mask) { + dig.col = true - blockARM64(dig.h[:], chunk, m1[:], cs[:]) - blockARM64(dig.h[:], chunk, m1[:], cs[:]) + blockARM64(dig.h[:], chunk, m1[:], cs[:]) + blockARM64(dig.h[:], chunk, m1[:], cs[:]) + } } p = p[shared.Chunk:] diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.s b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.s index 63762049..86f19f9e 100644 --- a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.s +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.s @@ -37,15 +37,13 @@ TEXT ·blockARM64(SB), NOSPLIT, $80-96 LSR $6, R2, R2 LSL $6, R2, R2 - ADD R16, R2, R21 VLD1.P 16(R0), [V0.S4] FMOVS (R0), F20 SUB $16, R0, R0 -loop: - CMP R16, R21 - BLS end + // The caller passes exactly one block; skip hashing only if p is shorter. + CBZ R2, end // Load block (p) into 16-bytes vectors. VLD1.P 16(R1), [V4.B16] diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64_dirtyregs.s b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64_dirtyregs.s new file mode 100644 index 00000000..767d8672 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64_dirtyregs.s @@ -0,0 +1,100 @@ +//go:build !noasm && gc && arm64 && !amd64 && sha1cd_asmtest + +#include "textflag.h" + +// callBlockARM64DirtyRegs calls blockARM64 with every general-purpose and +// vector register the caller does not own set to all ones. It is only built +// with the sha1cd_asmtest tag, to catch the assembly reading a register before +// writing it. +// +// func callBlockARM64DirtyRegs(h []uint32, p []byte, m1 []uint32, cs [][5]uint32) +TEXT ·callBlockARM64DirtyRegs(SB), NOSPLIT, $104-96 + MOVD h_base+0(FP), R0 + MOVD R0, 8(RSP) + MOVD h_len+8(FP), R0 + MOVD R0, 16(RSP) + MOVD h_cap+16(FP), R0 + MOVD R0, 24(RSP) + MOVD p_base+24(FP), R0 + MOVD R0, 32(RSP) + MOVD p_len+32(FP), R0 + MOVD R0, 40(RSP) + MOVD p_cap+40(FP), R0 + MOVD R0, 48(RSP) + MOVD m1_base+48(FP), R0 + MOVD R0, 56(RSP) + MOVD m1_len+56(FP), R0 + MOVD R0, 64(RSP) + MOVD m1_cap+64(FP), R0 + MOVD R0, 72(RSP) + MOVD cs_base+72(FP), R0 + MOVD R0, 80(RSP) + MOVD cs_len+80(FP), R0 + MOVD R0, 88(RSP) + MOVD cs_cap+88(FP), R0 + MOVD R0, 96(RSP) + + // R18 is reserved by the platform, R27 by the assembler, R28 holds g, + // R29 is the frame pointer and R30 the link register. + MOVD $-1, R0 + MOVD R0, R1 + MOVD R0, R2 + MOVD R0, R3 + MOVD R0, R4 + MOVD R0, R5 + MOVD R0, R6 + MOVD R0, R7 + MOVD R0, R8 + MOVD R0, R9 + MOVD R0, R10 + MOVD R0, R11 + MOVD R0, R12 + MOVD R0, R13 + MOVD R0, R14 + MOVD R0, R15 + MOVD R0, R16 + MOVD R0, R17 + MOVD R0, R19 + MOVD R0, R20 + MOVD R0, R21 + MOVD R0, R22 + MOVD R0, R23 + MOVD R0, R24 + MOVD R0, R25 + MOVD R0, R26 + + VMOVI $0xff, V0.B16 + VMOVI $0xff, V1.B16 + VMOVI $0xff, V2.B16 + VMOVI $0xff, V3.B16 + VMOVI $0xff, V4.B16 + VMOVI $0xff, V5.B16 + VMOVI $0xff, V6.B16 + VMOVI $0xff, V7.B16 + VMOVI $0xff, V8.B16 + VMOVI $0xff, V9.B16 + VMOVI $0xff, V10.B16 + VMOVI $0xff, V11.B16 + VMOVI $0xff, V12.B16 + VMOVI $0xff, V13.B16 + VMOVI $0xff, V14.B16 + VMOVI $0xff, V15.B16 + VMOVI $0xff, V16.B16 + VMOVI $0xff, V17.B16 + VMOVI $0xff, V18.B16 + VMOVI $0xff, V19.B16 + VMOVI $0xff, V20.B16 + VMOVI $0xff, V21.B16 + VMOVI $0xff, V22.B16 + VMOVI $0xff, V23.B16 + VMOVI $0xff, V24.B16 + VMOVI $0xff, V25.B16 + VMOVI $0xff, V26.B16 + VMOVI $0xff, V27.B16 + VMOVI $0xff, V28.B16 + VMOVI $0xff, V29.B16 + VMOVI $0xff, V30.B16 + VMOVI $0xff, V31.B16 + + BL ·blockARM64(SB) + RET diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_avx2_amd64.go b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_avx2_amd64.go new file mode 100644 index 00000000..910acd48 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_avx2_amd64.go @@ -0,0 +1,55 @@ +//go:build !noasm && gc && amd64 + +package sha1cd + +import ( + shared "github.com/pjbgf/sha1cd/internal" + "github.com/pjbgf/sha1cd/internal/cpu" + "github.com/pjbgf/sha1cd/ubc" +) + +// hasAVX2 reports whether blockAVX2 can run. It is the fallback for CPUs +// without SHA-NI, such as Intel's big cores before Ice Lake. +var hasAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI1 && cpu.X86.HasBMI2 + +// scheduleAVX2 expands the message schedules of the blocks at pa and pb, which +// may be the same, into m1a and m1b. +// +//go:noescape +func scheduleAVX2(pa, pb *byte, m1a, m1b *[shared.Rounds]uint32) + +// roundsBMI2 compresses the block whose schedule is in m1 into h, and stores +// the states before steps 0, 58 and 65 into cs. +// +//go:noescape +func roundsBMI2(h *[shared.WordBuffers]uint32, m1 *[shared.Rounds]uint32, + cs *[shared.PreStepState][shared.WordBuffers]uint32) + +func blockAVX2(dig *digest, p []byte) { + var m1 [2][shared.Rounds]uint32 + cs := [shared.PreStepState][shared.WordBuffers]uint32{} + + for len(p) >= shared.Chunk { + // The schedules do not depend on the chaining state, so expand two + // blocks at once. The rounds must still run one block at a time, as a + // detected collision changes the state the next block starts from. + n, pb := 1, p + if len(p) >= 2*shared.Chunk { + n, pb = 2, p[shared.Chunk:] + } + scheduleAVX2(&p[0], &pb[0], &m1[0], &m1[1]) + + for j := 0; j < n; j++ { + w := &m1[j] + roundsBMI2(&dig.h, w, &cs) + if mask := ubc.CalculateDvMask(w); mask != 0 && checkCollision(w, &cs, &dig.h, mask) { + dig.col = true + + roundsBMI2(&dig.h, w, &cs) + roundsBMI2(&dig.h, w, &cs) + } + } + + p = p[n*shared.Chunk:] + } +} diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_avx2_amd64.s b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_avx2_amd64.s new file mode 100644 index 00000000..9337ed13 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_avx2_amd64.s @@ -0,0 +1,415 @@ +//go:build !noasm && gc && amd64 + +#include "textflag.h" + +// The fallback for CPUs without SHA-NI. The message schedule is expanded with +// AVX2 for two blocks at a time, one per 128-bit lane, as it does not depend +// on the chaining state. The rounds then run one block at a time with scalar +// BMI instructions, so that the collision detection can run between blocks +// and gets the exact states before steps 58 and 65, with no repair needed. + +// func scheduleAVX2(pa, pb *byte, m1a, m1b *[80]uint32) +// Requires: AVX, AVX2 +// +// Expands the blocks at pa and pb, which may be the same, into m1a and m1b. +// Y0-Y7 hold the last eight groups of four words, group g in Y(g%8). +TEXT ·scheduleAVX2(SB), NOSPLIT, $0-32 + MOVQ pa+0(FP), AX + MOVQ pb+8(FP), BX + MOVQ m1a+16(FP), CX + MOVQ m1b+24(FP), DX + VBROADCASTI128 bswap_mask<>(SB), Y13 + + // W[0..3] loaded from the blocks + VMOVDQU 0(AX), X0 + VINSERTI128 $1, 0(BX), Y0, Y0 + VPSHUFB Y13, Y0, Y0 + VMOVDQU X0, 0(CX) + VEXTRACTI128 $1, Y0, 0(DX) + + // W[4..7] loaded from the blocks + VMOVDQU 16(AX), X1 + VINSERTI128 $1, 16(BX), Y1, Y1 + VPSHUFB Y13, Y1, Y1 + VMOVDQU X1, 16(CX) + VEXTRACTI128 $1, Y1, 16(DX) + + // W[8..11] loaded from the blocks + VMOVDQU 32(AX), X2 + VINSERTI128 $1, 32(BX), Y2, Y2 + VPSHUFB Y13, Y2, Y2 + VMOVDQU X2, 32(CX) + VEXTRACTI128 $1, Y2, 32(DX) + + // W[12..15] loaded from the blocks + VMOVDQU 48(AX), X3 + VINSERTI128 $1, 48(BX), Y3, Y3 + VPSHUFB Y13, Y3, Y3 + VMOVDQU X3, 48(CX) + VEXTRACTI128 $1, Y3, 48(DX) + + // W[16..19] = rol1(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]). W[i+3] needs + // W[i] from this group, which is added in afterwards. + VPALIGNR $8, Y0, Y1, Y8 // W[i-14..i-11] + VPXOR Y0, Y8, Y8 // W[i-16..i-13] + VPXOR Y2, Y8, Y8 // W[i-8..i-5] + VPSRLDQ $4, Y3, Y9 // W[i-3..i-1], 0 + VPXOR Y9, Y8, Y8 + VPSRLD $31, Y8, Y9 + VPSLLD $1, Y8, Y4 + VPOR Y9, Y4, Y4 + VPSLLDQ $12, Y8, Y10 // 0, 0, 0, the input to W[i] + VPSRLD $30, Y10, Y9 + VPSLLD $2, Y10, Y10 + VPOR Y9, Y10, Y10 // rol1(W[i]) in the lane of W[i+3] + VPXOR Y10, Y4, Y4 + VMOVDQU X4, 64(CX) + VEXTRACTI128 $1, Y4, 64(DX) + + // W[20..23] = rol1(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]). W[i+3] needs + // W[i] from this group, which is added in afterwards. + VPALIGNR $8, Y1, Y2, Y8 // W[i-14..i-11] + VPXOR Y1, Y8, Y8 // W[i-16..i-13] + VPXOR Y3, Y8, Y8 // W[i-8..i-5] + VPSRLDQ $4, Y4, Y9 // W[i-3..i-1], 0 + VPXOR Y9, Y8, Y8 + VPSRLD $31, Y8, Y9 + VPSLLD $1, Y8, Y5 + VPOR Y9, Y5, Y5 + VPSLLDQ $12, Y8, Y10 // 0, 0, 0, the input to W[i] + VPSRLD $30, Y10, Y9 + VPSLLD $2, Y10, Y10 + VPOR Y9, Y10, Y10 // rol1(W[i]) in the lane of W[i+3] + VPXOR Y10, Y5, Y5 + VMOVDQU X5, 80(CX) + VEXTRACTI128 $1, Y5, 80(DX) + + // W[24..27] = rol1(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]). W[i+3] needs + // W[i] from this group, which is added in afterwards. + VPALIGNR $8, Y2, Y3, Y8 // W[i-14..i-11] + VPXOR Y2, Y8, Y8 // W[i-16..i-13] + VPXOR Y4, Y8, Y8 // W[i-8..i-5] + VPSRLDQ $4, Y5, Y9 // W[i-3..i-1], 0 + VPXOR Y9, Y8, Y8 + VPSRLD $31, Y8, Y9 + VPSLLD $1, Y8, Y6 + VPOR Y9, Y6, Y6 + VPSLLDQ $12, Y8, Y10 // 0, 0, 0, the input to W[i] + VPSRLD $30, Y10, Y9 + VPSLLD $2, Y10, Y10 + VPOR Y9, Y10, Y10 // rol1(W[i]) in the lane of W[i+3] + VPXOR Y10, Y6, Y6 + VMOVDQU X6, 96(CX) + VEXTRACTI128 $1, Y6, 96(DX) + + // W[28..31] = rol1(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]). W[i+3] needs + // W[i] from this group, which is added in afterwards. + VPALIGNR $8, Y3, Y4, Y8 // W[i-14..i-11] + VPXOR Y3, Y8, Y8 // W[i-16..i-13] + VPXOR Y5, Y8, Y8 // W[i-8..i-5] + VPSRLDQ $4, Y6, Y9 // W[i-3..i-1], 0 + VPXOR Y9, Y8, Y8 + VPSRLD $31, Y8, Y9 + VPSLLD $1, Y8, Y7 + VPOR Y9, Y7, Y7 + VPSLLDQ $12, Y8, Y10 // 0, 0, 0, the input to W[i] + VPSRLD $30, Y10, Y9 + VPSLLD $2, Y10, Y10 + VPOR Y9, Y10, Y10 // rol1(W[i]) in the lane of W[i+3] + VPXOR Y10, Y7, Y7 + VMOVDQU X7, 112(CX) + VEXTRACTI128 $1, Y7, 112(DX) + + // W[32..35] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y6, Y7, Y8 // W[i-6..i-3] + VPXOR Y4, Y8, Y8 // W[i-16..i-13] + VPXOR Y1, Y8, Y8 // W[i-28..i-25] + VPXOR Y0, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y0 + VPOR Y9, Y0, Y0 + VMOVDQU X0, 128(CX) + VEXTRACTI128 $1, Y0, 128(DX) + + // W[36..39] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y7, Y0, Y8 // W[i-6..i-3] + VPXOR Y5, Y8, Y8 // W[i-16..i-13] + VPXOR Y2, Y8, Y8 // W[i-28..i-25] + VPXOR Y1, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y1 + VPOR Y9, Y1, Y1 + VMOVDQU X1, 144(CX) + VEXTRACTI128 $1, Y1, 144(DX) + + // W[40..43] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y0, Y1, Y8 // W[i-6..i-3] + VPXOR Y6, Y8, Y8 // W[i-16..i-13] + VPXOR Y3, Y8, Y8 // W[i-28..i-25] + VPXOR Y2, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y2 + VPOR Y9, Y2, Y2 + VMOVDQU X2, 160(CX) + VEXTRACTI128 $1, Y2, 160(DX) + + // W[44..47] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y1, Y2, Y8 // W[i-6..i-3] + VPXOR Y7, Y8, Y8 // W[i-16..i-13] + VPXOR Y4, Y8, Y8 // W[i-28..i-25] + VPXOR Y3, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y3 + VPOR Y9, Y3, Y3 + VMOVDQU X3, 176(CX) + VEXTRACTI128 $1, Y3, 176(DX) + + // W[48..51] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y2, Y3, Y8 // W[i-6..i-3] + VPXOR Y0, Y8, Y8 // W[i-16..i-13] + VPXOR Y5, Y8, Y8 // W[i-28..i-25] + VPXOR Y4, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y4 + VPOR Y9, Y4, Y4 + VMOVDQU X4, 192(CX) + VEXTRACTI128 $1, Y4, 192(DX) + + // W[52..55] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y3, Y4, Y8 // W[i-6..i-3] + VPXOR Y1, Y8, Y8 // W[i-16..i-13] + VPXOR Y6, Y8, Y8 // W[i-28..i-25] + VPXOR Y5, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y5 + VPOR Y9, Y5, Y5 + VMOVDQU X5, 208(CX) + VEXTRACTI128 $1, Y5, 208(DX) + + // W[56..59] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y4, Y5, Y8 // W[i-6..i-3] + VPXOR Y2, Y8, Y8 // W[i-16..i-13] + VPXOR Y7, Y8, Y8 // W[i-28..i-25] + VPXOR Y6, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y6 + VPOR Y9, Y6, Y6 + VMOVDQU X6, 224(CX) + VEXTRACTI128 $1, Y6, 224(DX) + + // W[60..63] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y5, Y6, Y8 // W[i-6..i-3] + VPXOR Y3, Y8, Y8 // W[i-16..i-13] + VPXOR Y0, Y8, Y8 // W[i-28..i-25] + VPXOR Y7, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y7 + VPOR Y9, Y7, Y7 + VMOVDQU X7, 240(CX) + VEXTRACTI128 $1, Y7, 240(DX) + + // W[64..67] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y6, Y7, Y8 // W[i-6..i-3] + VPXOR Y4, Y8, Y8 // W[i-16..i-13] + VPXOR Y1, Y8, Y8 // W[i-28..i-25] + VPXOR Y0, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y0 + VPOR Y9, Y0, Y0 + VMOVDQU X0, 256(CX) + VEXTRACTI128 $1, Y0, 256(DX) + + // W[68..71] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y7, Y0, Y8 // W[i-6..i-3] + VPXOR Y5, Y8, Y8 // W[i-16..i-13] + VPXOR Y2, Y8, Y8 // W[i-28..i-25] + VPXOR Y1, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y1 + VPOR Y9, Y1, Y1 + VMOVDQU X1, 272(CX) + VEXTRACTI128 $1, Y1, 272(DX) + + // W[72..75] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y0, Y1, Y8 // W[i-6..i-3] + VPXOR Y6, Y8, Y8 // W[i-16..i-13] + VPXOR Y3, Y8, Y8 // W[i-28..i-25] + VPXOR Y2, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y2 + VPOR Y9, Y2, Y2 + VMOVDQU X2, 288(CX) + VEXTRACTI128 $1, Y2, 288(DX) + + // W[76..79] = rol2(W[i-6] ^ W[i-16] ^ W[i-28] ^ W[i-32]) + VPALIGNR $8, Y1, Y2, Y8 // W[i-6..i-3] + VPXOR Y7, Y8, Y8 // W[i-16..i-13] + VPXOR Y4, Y8, Y8 // W[i-28..i-25] + VPXOR Y3, Y8, Y8 // W[i-32..i-29] + VPSRLD $30, Y8, Y9 + VPSLLD $2, Y8, Y3 + VPOR Y9, Y3, Y3 + VMOVDQU X3, 304(CX) + VEXTRACTI128 $1, Y3, 304(DX) + + VZEROUPPER + RET + +// Each round adds W[i], K, f(b, c, d) and rol5(a) into e and rotates b by 30. +// The callers rotate the register names instead of moving values around, and +// rol5(a) goes in last, as a is the only input the previous round produced. +#define ROUND_CH(a, b, c, d, e, i) \ + ADDL ((i)*4)(SI), e; \ + ADDL $0x5a827999, e; \ + ANDNL d, b, AX; \ + MOVL c, BX; \ + ANDL b, BX; \ + ADDL AX, e; \ + ADDL BX, e; \ + RORXL $27, a, CX; \ + RORXL $2, b, b; \ + ADDL CX, e + +#define ROUND_PARITY(a, b, c, d, e, i, k) \ + ADDL ((i)*4)(SI), e; \ + ADDL k, e; \ + MOVL b, AX; \ + XORL c, AX; \ + XORL d, AX; \ + ADDL AX, e; \ + RORXL $27, a, CX; \ + RORXL $2, b, b; \ + ADDL CX, e + +// maj(b, c, d) = (b & c) + ((b ^ c) & d), as the two never share a bit. +#define ROUND_MAJ(a, b, c, d, e, i) \ + ADDL ((i)*4)(SI), e; \ + ADDL $0x8f1bbcdc, e; \ + MOVL b, AX; \ + XORL c, AX; \ + ANDL d, AX; \ + MOVL b, BX; \ + ANDL c, BX; \ + ADDL AX, e; \ + ADDL BX, e; \ + RORXL $27, a, CX; \ + RORXL $2, b, b; \ + ADDL CX, e + +#define SAVECS(a, b, c, d, e, index) \ + MOVL a, ((index)*20+0)(DX); \ + MOVL b, ((index)*20+4)(DX); \ + MOVL c, ((index)*20+8)(DX); \ + MOVL d, ((index)*20+12)(DX); \ + MOVL e, ((index)*20+16)(DX) + +// func roundsBMI2(h *[5]uint32, m1 *[80]uint32, cs *[3][5]uint32) +// Requires: BMI1, BMI2 +// +// Compresses the block whose schedule is in m1 into h, storing the states +// before steps 0, 58 and 65 into cs. +TEXT ·roundsBMI2(SB), NOSPLIT, $0-24 + MOVQ h+0(FP), DI + MOVQ m1+8(FP), SI + MOVQ cs+16(FP), DX + MOVL 0(DI), R8 + MOVL 4(DI), R9 + MOVL 8(DI), R10 + MOVL 12(DI), R11 + MOVL 16(DI), R12 + + SAVECS(R8, R9, R10, R11, R12, 0) + ROUND_CH(R8, R9, R10, R11, R12, 0) + ROUND_CH(R12, R8, R9, R10, R11, 1) + ROUND_CH(R11, R12, R8, R9, R10, 2) + ROUND_CH(R10, R11, R12, R8, R9, 3) + ROUND_CH(R9, R10, R11, R12, R8, 4) + ROUND_CH(R8, R9, R10, R11, R12, 5) + ROUND_CH(R12, R8, R9, R10, R11, 6) + ROUND_CH(R11, R12, R8, R9, R10, 7) + ROUND_CH(R10, R11, R12, R8, R9, 8) + ROUND_CH(R9, R10, R11, R12, R8, 9) + ROUND_CH(R8, R9, R10, R11, R12, 10) + ROUND_CH(R12, R8, R9, R10, R11, 11) + ROUND_CH(R11, R12, R8, R9, R10, 12) + ROUND_CH(R10, R11, R12, R8, R9, 13) + ROUND_CH(R9, R10, R11, R12, R8, 14) + ROUND_CH(R8, R9, R10, R11, R12, 15) + ROUND_CH(R12, R8, R9, R10, R11, 16) + ROUND_CH(R11, R12, R8, R9, R10, 17) + ROUND_CH(R10, R11, R12, R8, R9, 18) + ROUND_CH(R9, R10, R11, R12, R8, 19) + ROUND_PARITY(R8, R9, R10, R11, R12, 20, $0x6ed9eba1) + ROUND_PARITY(R12, R8, R9, R10, R11, 21, $0x6ed9eba1) + ROUND_PARITY(R11, R12, R8, R9, R10, 22, $0x6ed9eba1) + ROUND_PARITY(R10, R11, R12, R8, R9, 23, $0x6ed9eba1) + ROUND_PARITY(R9, R10, R11, R12, R8, 24, $0x6ed9eba1) + ROUND_PARITY(R8, R9, R10, R11, R12, 25, $0x6ed9eba1) + ROUND_PARITY(R12, R8, R9, R10, R11, 26, $0x6ed9eba1) + ROUND_PARITY(R11, R12, R8, R9, R10, 27, $0x6ed9eba1) + ROUND_PARITY(R10, R11, R12, R8, R9, 28, $0x6ed9eba1) + ROUND_PARITY(R9, R10, R11, R12, R8, 29, $0x6ed9eba1) + ROUND_PARITY(R8, R9, R10, R11, R12, 30, $0x6ed9eba1) + ROUND_PARITY(R12, R8, R9, R10, R11, 31, $0x6ed9eba1) + ROUND_PARITY(R11, R12, R8, R9, R10, 32, $0x6ed9eba1) + ROUND_PARITY(R10, R11, R12, R8, R9, 33, $0x6ed9eba1) + ROUND_PARITY(R9, R10, R11, R12, R8, 34, $0x6ed9eba1) + ROUND_PARITY(R8, R9, R10, R11, R12, 35, $0x6ed9eba1) + ROUND_PARITY(R12, R8, R9, R10, R11, 36, $0x6ed9eba1) + ROUND_PARITY(R11, R12, R8, R9, R10, 37, $0x6ed9eba1) + ROUND_PARITY(R10, R11, R12, R8, R9, 38, $0x6ed9eba1) + ROUND_PARITY(R9, R10, R11, R12, R8, 39, $0x6ed9eba1) + ROUND_MAJ(R8, R9, R10, R11, R12, 40) + ROUND_MAJ(R12, R8, R9, R10, R11, 41) + ROUND_MAJ(R11, R12, R8, R9, R10, 42) + ROUND_MAJ(R10, R11, R12, R8, R9, 43) + ROUND_MAJ(R9, R10, R11, R12, R8, 44) + ROUND_MAJ(R8, R9, R10, R11, R12, 45) + ROUND_MAJ(R12, R8, R9, R10, R11, 46) + ROUND_MAJ(R11, R12, R8, R9, R10, 47) + ROUND_MAJ(R10, R11, R12, R8, R9, 48) + ROUND_MAJ(R9, R10, R11, R12, R8, 49) + ROUND_MAJ(R8, R9, R10, R11, R12, 50) + ROUND_MAJ(R12, R8, R9, R10, R11, 51) + ROUND_MAJ(R11, R12, R8, R9, R10, 52) + ROUND_MAJ(R10, R11, R12, R8, R9, 53) + ROUND_MAJ(R9, R10, R11, R12, R8, 54) + ROUND_MAJ(R8, R9, R10, R11, R12, 55) + ROUND_MAJ(R12, R8, R9, R10, R11, 56) + ROUND_MAJ(R11, R12, R8, R9, R10, 57) + SAVECS(R10, R11, R12, R8, R9, 1) + ROUND_MAJ(R10, R11, R12, R8, R9, 58) + ROUND_MAJ(R9, R10, R11, R12, R8, 59) + ROUND_PARITY(R8, R9, R10, R11, R12, 60, $0xca62c1d6) + ROUND_PARITY(R12, R8, R9, R10, R11, 61, $0xca62c1d6) + ROUND_PARITY(R11, R12, R8, R9, R10, 62, $0xca62c1d6) + ROUND_PARITY(R10, R11, R12, R8, R9, 63, $0xca62c1d6) + ROUND_PARITY(R9, R10, R11, R12, R8, 64, $0xca62c1d6) + SAVECS(R8, R9, R10, R11, R12, 2) + ROUND_PARITY(R8, R9, R10, R11, R12, 65, $0xca62c1d6) + ROUND_PARITY(R12, R8, R9, R10, R11, 66, $0xca62c1d6) + ROUND_PARITY(R11, R12, R8, R9, R10, 67, $0xca62c1d6) + ROUND_PARITY(R10, R11, R12, R8, R9, 68, $0xca62c1d6) + ROUND_PARITY(R9, R10, R11, R12, R8, 69, $0xca62c1d6) + ROUND_PARITY(R8, R9, R10, R11, R12, 70, $0xca62c1d6) + ROUND_PARITY(R12, R8, R9, R10, R11, 71, $0xca62c1d6) + ROUND_PARITY(R11, R12, R8, R9, R10, 72, $0xca62c1d6) + ROUND_PARITY(R10, R11, R12, R8, R9, 73, $0xca62c1d6) + ROUND_PARITY(R9, R10, R11, R12, R8, 74, $0xca62c1d6) + ROUND_PARITY(R8, R9, R10, R11, R12, 75, $0xca62c1d6) + ROUND_PARITY(R12, R8, R9, R10, R11, 76, $0xca62c1d6) + ROUND_PARITY(R11, R12, R8, R9, R10, 77, $0xca62c1d6) + ROUND_PARITY(R10, R11, R12, R8, R9, 78, $0xca62c1d6) + ROUND_PARITY(R9, R10, R11, R12, R8, 79, $0xca62c1d6) + + ADDL R8, 0(DI) + ADDL R9, 4(DI) + ADDL R10, 8(DI) + ADDL R11, 12(DI) + ADDL R12, 16(DI) + RET + +// Swaps the bytes of each word, as SHA-1 reads the block big endian. +DATA bswap_mask<>+0(SB)/8, $0x0405060700010203 +DATA bswap_mask<>+8(SB)/8, $0x0c0d0e0f08090a0b +GLOBL bswap_mask<>(SB), RODATA|NOPTR, $16 diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_generic.go b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_generic.go index a80148eb..6557410e 100644 --- a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_generic.go +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_generic.go @@ -20,7 +20,9 @@ var forceGeneric bool // blockGeneric is a portable, pure Go version of the SHA-1 block step. // It's used by sha1block_generic.go and tests. func blockGeneric(dig *digest, p []byte) { - var w [16]uint32 + // Expand directly into the schedule retained for collision detection. + // Every word is overwritten for each block, including rehashes. + var m1 [shared.Rounds]uint32 // cs stores the pre-step compression state for only the steps required for the // collision detection, which are 0, 58 and 65. @@ -29,7 +31,6 @@ func blockGeneric(dig *digest, p []byte) { h0, h1, h2, h3, h4 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4] for len(p) >= shared.Chunk { - m1 := [shared.Rounds]uint32{} hi := 1 // Collision attacks are thwarted by hashing a detected near-collision block 3 times. @@ -51,36 +52,27 @@ func blockGeneric(dig *digest, p []byte) { for ; i < 16; i++ { // load step j := i * 4 - w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3]) + m1[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3]) f := b&c | (^b)&d - t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + shared.K0 + t := bits.RotateLeft32(a, 5) + f + e + m1[i] + shared.K0 a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d - - // Store compression state for the collision detection. - m1[i] = w[i&0xf] } for ; i < 20; i++ { - tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf] - w[i&0xf] = tmp<<1 | tmp>>(32-1) + tmp := m1[i-3] ^ m1[i-8] ^ m1[i-14] ^ m1[i-16] + m1[i] = tmp<<1 | tmp>>(32-1) f := b&c | (^b)&d - t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + shared.K0 + t := bits.RotateLeft32(a, 5) + f + e + m1[i] + shared.K0 a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d - - // Store compression state for the collision detection. - m1[i] = w[i&0xf] } for ; i < 40; i++ { - tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf] - w[i&0xf] = tmp<<1 | tmp>>(32-1) + tmp := m1[i-3] ^ m1[i-8] ^ m1[i-14] ^ m1[i-16] + m1[i] = tmp<<1 | tmp>>(32-1) f := b ^ c ^ d - t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + shared.K1 + t := bits.RotateLeft32(a, 5) + f + e + m1[i] + shared.K1 a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d - - // Store compression state for the collision detection. - m1[i] = w[i&0xf] } for ; i < 60; i++ { if i == 58 { @@ -88,15 +80,12 @@ func blockGeneric(dig *digest, p []byte) { cs[1] = [shared.WordBuffers]uint32{a, b, c, d, e} } - tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf] - w[i&0xf] = tmp<<1 | tmp>>(32-1) + tmp := m1[i-3] ^ m1[i-8] ^ m1[i-14] ^ m1[i-16] + m1[i] = tmp<<1 | tmp>>(32-1) f := ((b | c) & d) | (b & c) - t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + shared.K2 + t := bits.RotateLeft32(a, 5) + f + e + m1[i] + shared.K2 a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d - - // Store compression state for the collision detection. - m1[i] = w[i&0xf] } for ; i < 80; i++ { if i == 65 { @@ -104,15 +93,12 @@ func blockGeneric(dig *digest, p []byte) { cs[2] = [shared.WordBuffers]uint32{a, b, c, d, e} } - tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf] - w[i&0xf] = tmp<<1 | tmp>>(32-1) + tmp := m1[i-3] ^ m1[i-8] ^ m1[i-14] ^ m1[i-16] + m1[i] = tmp<<1 | tmp>>(32-1) f := b ^ c ^ d - t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + shared.K3 + t := bits.RotateLeft32(a, 5) + f + e + m1[i] + shared.K3 a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d - - // Store compression state for the collision detection. - m1[i] = w[i&0xf] } h0 += a @@ -128,7 +114,7 @@ func blockGeneric(dig *digest, p []byte) { if hi == 1 { h := [shared.WordBuffers]uint32{h0, h1, h2, h3, h4} - col := checkCollision(&m1, &cs, &h) + col := checkCollision(&m1, &cs, &h, ubc.CalculateDvMask(&m1)) if col { dig.col = true hi++ @@ -147,8 +133,9 @@ func checkCollision( m1 *[shared.Rounds]uint32, cs *[shared.PreStepState][shared.WordBuffers]uint32, h *[shared.WordBuffers]uint32, + mask uint32, ) bool { - if mask := ubc.CalculateDvMask(m1); mask != 0 { + if mask != 0 { dvs := ubc.SHA1_dvs() for i := 0; dvs[i].DvType != 0; i++ { @@ -290,23 +277,22 @@ func rectifyCompressionState( return } - func3 := func(state [shared.WordBuffers]uint32, i int) [shared.WordBuffers]uint32 { - a, b, c, d, e := state[0], state[1], state[2], state[3], state[4] + // The words are loaded and stored one at a time. Passing [5]uint32 values + // around made the compiler reload them with wider moves than they were + // stored with, which stalled on store forwarding each time. + // Advance cs[1] from the state before step 56 to the one before step 58. + a, b, c, d, e := cs[1][0], cs[1][1], cs[1][2], cs[1][3], cs[1][4] + for i := 56; i < 58; i++ { f := ((b | c) & d) | (b & c) t := bits.RotateLeft32(a, 5) + f + e + m1[i] + shared.K2 a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d - return [shared.WordBuffers]uint32{a, b, c, d, e} - } - func4 := func(state [shared.WordBuffers]uint32, i int) [shared.WordBuffers]uint32 { - a, b, c, d, e := state[0], state[1], state[2], state[3], state[4] - f := b ^ c ^ d - t := bits.RotateLeft32(a, 5) + f + e + m1[i] + shared.K3 - a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d - return [shared.WordBuffers]uint32{a, b, c, d, e} } + cs[1][0], cs[1][1], cs[1][2], cs[1][3], cs[1][4] = a, b, c, d, e - cs57 := func3(cs[1], 56) - cs[1] = func3(cs57, 57) - cs[2] = func4(cs[2], 64) + // Advance cs[2] from the state before step 64 to the one before step 65. + a, b, c, d, e = cs[2][0], cs[2][1], cs[2][2], cs[2][3], cs[2][4] + f := b ^ c ^ d + t := bits.RotateLeft32(a, 5) + f + e + m1[64] + shared.K3 + cs[2][0], cs[2][1], cs[2][2], cs[2][3], cs[2][4] = t, a, bits.RotateLeft32(b, 30), c, d } diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_amd64.go b/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_amd64.go new file mode 100644 index 00000000..ad76b64a --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_amd64.go @@ -0,0 +1,51 @@ +//go:build !noasm && gc && amd64 + +package ubc + +import ( + "unsafe" + + "github.com/pjbgf/sha1cd/internal/cpu" +) + +// useAVX512 reports whether calculateDvMaskAVX512 can run. Its only +// instructions outside AVX-512F are VMOVD and VZEROUPPER, which need AVX. +// HasAVX512F is set only when the CPU reports AVX as well. +var useAVX512 = cpu.X86.HasAVX512F + +//go:noescape +func calculateDvMaskAVX512(W *[80]uint32, terms *uint32, groups int) uint32 + +// avx512Lanes is the number of terms a group of avx512Terms describes, and +// avx512Fields the vectors it holds for them. +const ( + avx512Lanes = 16 + avx512Fields = 6 +) + +// avx512Groups is how many passes of the kernel loop the table needs. +const avx512Groups = len(avx512Terms) / (avx512Fields * avx512Lanes) + +// alignedTerms is a copy of avx512Terms that starts on a cache line. The +// linker aligns data to 32 bytes at most, and a 64 byte load that straddles +// two cache lines costs about twice as much. +var alignedTerms = func() *uint32 { + buf := make([]uint32, len(avx512Terms)+16) + off := (64 - uintptr(unsafe.Pointer(&buf[0]))%64) % 64 / 4 + copy(buf[off:], avx512Terms[:]) + return &buf[off] +}() + +// CalculateDvMask takes as input an expanded message block and +// verifies the unavoidable bitconditions for all listed DVs. It returns +// a dvmask where each bit belonging to a DV is set if all unavoidable +// bitconditions for that DV have been met. +func CalculateDvMask(W *[80]uint32) uint32 { + if W == nil { + return 0 + } + if useAVX512 { + return calculateDvMaskAVX512(W, alignedTerms, avx512Groups) + } + return calculateDvMaskGeneric(W) +} diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_avx512_amd64.s b/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_avx512_amd64.s new file mode 100644 index 00000000..ef395324 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_avx512_amd64.s @@ -0,0 +1,52 @@ +//go:build !noasm && gc && amd64 + +#include "textflag.h" + +// func calculateDvMaskAVX512(W *[80]uint32, terms *uint32, groups int) uint32 +// Requires: AVX, AVX512F +// +// Each group of avx512Terms describes 16 of the bit tests of CalculateDvMask, +// as vectors of word indices, shift counts, expected parities and the masks +// that clear the DVs of a failing test. One pass of the loop runs a group. +// +// terms only has to be 64 byte aligned for speed, as otherwise every load of +// it straddles two cache lines. The word indices are biased by 34, matching +// the two vectors of W loaded below. +TEXT ·calculateDvMaskAVX512(SB), NOSPLIT, $0-28 + MOVQ W+0(FP), AX + MOVQ terms+8(FP), BX + MOVQ groups+16(FP), CX + VMOVDQU32 136(AX), Z0 // W[34..49] + VMOVDQU32 200(AX), Z1 // W[50..65] + VPTERNLOGD $0xff, Z2, Z2, Z2 // mask = all ones + MOVL $1, DX + VPBROADCASTD DX, Z3 + +loop: + VMOVDQU32 0(BX), Z4 + VMOVDQU32 64(BX), Z5 + VPERMI2D Z1, Z0, Z4 // W[a] + VPERMI2D Z1, Z0, Z5 // W[b] + VPSRLVD 128(BX), Z4, Z4 // >> ka + VPSRLVD 192(BX), Z5, Z5 // >> kb + VPTERNLOGD $0x96, 256(BX), Z5, Z4 // ^ e + VPTESTMD Z3, Z4, K1 // the terms whose bit test fails + VPANDD 320(BX), Z2, K1, Z2 // clear their DVs + ADDQ $384, BX + DECQ CX + JNZ loop + + // AND the 16 lanes together, first the 128 bit lanes and then the + // words within them. + VSHUFI64X2 $0x4e, Z2, Z2, Z4 + VPANDD Z4, Z2, Z2 + VSHUFI64X2 $0xb1, Z2, Z2, Z4 + VPANDD Z4, Z2, Z2 + VPSHUFD $0x4e, Z2, Z4 + VPANDD Z4, Z2, Z2 + VPSHUFD $0xb1, Z2, Z4 + VPANDD Z4, Z2, Z2 + VMOVD X2, AX + VZEROUPPER + MOVL AX, ret+24(FP) + RET diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_avx512_table_amd64.go b/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_avx512_table_amd64.go new file mode 100644 index 00000000..ffa0b0d0 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_avx512_table_amd64.go @@ -0,0 +1,111 @@ +//go:build !noasm && gc && amd64 + +package ubc + +// avx512Terms holds the bit tests of CalculateDvMask in the layout the +// AVX-512 kernel consumes, 16 terms per group. Each term says that a set of +// DVs survives only if bit ka of W[a] XOR bit kb of W[b] equals e, and names +// the mask that clears those DVs when it does not. +// +// The six vectors of a group are, in order: a-34, b-34, ka, kb, e, and the +// clear mask. Word indices are biased by 34 because the kernel keeps W[34..65] +// in two registers. A group is 384 bytes, and the kernel runs one per pass. +// +// The terms are those of calculateDvMaskGeneric, which is a port of +// ubc_check.c and has not changed since the collision detection was published +// in 2017. TestAVX512MatchesGeneric holds the two implementations to the same +// results over inputs that reach every DV, so a mistake here is a test +// failure rather than a missed collision. The comment above each group names +// its terms as a.ka^b.kb=e. +var avx512Terms = [960]uint32{ + // terms 0-15 + // 44.29^45.29=0 49.29^50.29=0 48.29^49.29=0 47.4^50.29=0 47.29^48.29=0 46.4^49.29=0 46.29^47.29=0 45.4^48.29=0 + // 45.29^46.29=0 44.4^47.29=0 43.4^46.29=0 43.29^44.29=0 42.4^45.29=0 41.4^44.29=0 40.29^41.29=0 54.29^55.29=0 + 0x0000000a, 0x0000000f, 0x0000000e, 0x0000000d, 0x0000000d, 0x0000000c, 0x0000000c, 0x0000000b, 0x0000000b, 0x0000000a, 0x00000009, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000014, + 0x0000000b, 0x00000010, 0x0000000f, 0x00000010, 0x0000000e, 0x0000000f, 0x0000000d, 0x0000000e, 0x0000000c, 0x0000000d, 0x0000000c, 0x0000000a, 0x0000000b, 0x0000000a, 0x00000007, 0x00000015, + 0x0000001d, 0x0000001d, 0x0000001d, 0x00000004, 0x0000001d, 0x00000004, 0x0000001d, 0x00000004, 0x0000001d, 0x00000004, 0x00000004, 0x0000001d, 0x00000004, 0x00000004, 0x0000001d, 0x0000001d, + 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfd7c5f7f, 0x3d7efff7, 0x9f5f7ffb, 0x7dfedddf, 0xcfcfdffd, 0xbf7f7777, 0xe7e7f7fe, 0xdfdfdddb, 0xf5f57dff, 0xefeff775, 0xf7f7fdda, 0xff5ed7df, 0xfdfd7f75, 0xff7edfda, 0x7ff5ff5d, 0x3f77dfff, + // terms 16-31 + // 53.29^54.29=0 52.29^53.29=0 50.4^53.29=0 50.29^51.29=0 49.4^52.29=0 48.4^51.29=0 42.29^43.29=0 41.29^42.29=0 + // 40.4^43.29=0 39.4^42.29=0 38.4^41.29=0 37.4^40.29=0 55.29^56.29=0 52.4^55.29=0 51.4^54.29=0 51.29^52.29=0 + 0x00000013, 0x00000012, 0x00000010, 0x00000010, 0x0000000f, 0x0000000e, 0x00000008, 0x00000007, 0x00000006, 0x00000005, 0x00000004, 0x00000003, 0x00000015, 0x00000012, 0x00000011, 0x00000011, + 0x00000014, 0x00000013, 0x00000013, 0x00000011, 0x00000012, 0x00000011, 0x00000009, 0x00000008, 0x00000009, 0x00000008, 0x00000007, 0x00000006, 0x00000016, 0x00000015, 0x00000014, 0x00000012, + 0x0000001d, 0x0000001d, 0x00000004, 0x0000001d, 0x00000004, 0x00000004, 0x0000001d, 0x0000001d, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x0000001d, 0x00000004, 0x00000004, 0x0000001d, + 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x9fddf7ff, 0xcfeefdff, 0xdfed77ff, 0x75fdffdf, 0xeff6ddff, 0xf7fd777f, 0xffcff5f7, 0xffe7fd7b, 0x7fdff7f5, 0xbfeffdfa, 0x5ff7ff7d, 0xaffdffde, 0x7def7fff, 0x7f6f7fff, 0xbfd7dfff, 0xe7f7ff7f, + // terms 32-47 + // 36.4^40.29=0 53.29^56.29=1 51.29^54.29=1 50.29^52.29=1 49.29^51.29=1 48.29^50.29=1 47.29^49.29=1 46.29^48.29=1 + // 45.6^47.6=0 45.29^47.29=1 44.6^46.6=0 44.29^46.29=1 41.1^42.6=1 40.1^41.6=1 40.4^42.4=1 39.1^40.6=1 + 0x00000002, 0x00000013, 0x00000011, 0x00000010, 0x0000000f, 0x0000000e, 0x0000000d, 0x0000000c, 0x0000000b, 0x0000000b, 0x0000000a, 0x0000000a, 0x00000007, 0x00000006, 0x00000006, 0x00000005, + 0x00000006, 0x00000016, 0x00000014, 0x00000012, 0x00000011, 0x00000010, 0x0000000f, 0x0000000e, 0x0000000d, 0x0000000d, 0x0000000c, 0x0000000c, 0x00000008, 0x00000007, 0x00000008, 0x00000006, + 0x00000004, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x00000006, 0x0000001d, 0x00000006, 0x0000001d, 0x00000001, 0x00000001, 0x00000004, 0x00000001, + 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x00000006, 0x0000001d, 0x00000006, 0x0000001d, 0x00000006, 0x00000006, 0x00000004, 0x00000006, + 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0xffeefdf7, 0xffcf7fff, 0xfff5f7ff, 0xfffeddff, 0xffff777f, 0xffffdddf, 0xfffff777, 0xfffffddb, 0xffffbbbf, 0xffffff75, 0xffffeeef, 0xffffffda, 0xfbfbfeff, 0xfeffbfbf, 0x7ffffff5, 0xffbfefef, + // terms 48-63 + // 39.4^41.4=1 38.4^40.4=1 37.4^39.4=1 36.1^37.6=1 35.4^39.29=0 63.0^64.5=1 63.1^64.6=1 62.0^63.5=1 + // 61.0^62.5=1 61.2^62.7=1 60.0^61.5=1 58.29^59.29=0 57.29^58.29=0 56.4^59.29=0 56.29^59.29=1 56.29^57.29=0 + 0x00000005, 0x00000004, 0x00000003, 0x00000002, 0x00000001, 0x0000001d, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001b, 0x0000001a, 0x00000018, 0x00000017, 0x00000016, 0x00000016, 0x00000016, + 0x00000007, 0x00000006, 0x00000005, 0x00000003, 0x00000005, 0x0000001e, 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001c, 0x0000001b, 0x00000019, 0x00000018, 0x00000019, 0x00000019, 0x00000017, + 0x00000004, 0x00000004, 0x00000004, 0x00000001, 0x00000004, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x0000001d, 0x0000001d, 0x00000004, 0x0000001d, 0x0000001d, + 0x00000004, 0x00000004, 0x00000004, 0x00000006, 0x0000001d, 0x00000005, 0x00000006, 0x00000005, 0x00000005, 0x00000007, 0x00000005, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, + 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0xbffffffa, 0x5ffffffd, 0xaffffffe, 0xfffbefbf, 0xfff7ff7b, 0xffefff7f, 0xfffefffb, 0xfff7ffdf, 0xfffdfff7, 0xfffbffef, 0xfffefffb, 0xddffffff, 0xef7fffff, 0xd7ffffff, 0xf5ffffff, 0xf7dfffff, + // terms 64-79 + // 55.4^58.29=0 54.4^57.29=0 53.4^56.29=0 50.6^51.1=0 48.6^50.6=0 48.29^55.29=1 47.6^49.6=0 47.6^48.1=0 + // 46.6^48.6=0 46.6^47.1=0 44.1^45.6=1 43.6^45.6=0 42.6^44.6=0 42.6^43.1=0 41.6^42.1=0 40.6^41.1=0 + 0x00000015, 0x00000014, 0x00000013, 0x00000010, 0x0000000e, 0x0000000e, 0x0000000d, 0x0000000d, 0x0000000c, 0x0000000c, 0x0000000a, 0x00000009, 0x00000008, 0x00000008, 0x00000007, 0x00000006, + 0x00000018, 0x00000017, 0x00000016, 0x00000011, 0x00000010, 0x00000015, 0x0000000f, 0x0000000e, 0x0000000e, 0x0000000d, 0x0000000b, 0x0000000b, 0x0000000a, 0x00000009, 0x00000008, 0x00000007, + 0x00000004, 0x00000004, 0x00000004, 0x00000006, 0x00000006, 0x0000001d, 0x00000006, 0x00000006, 0x00000006, 0x00000006, 0x00000001, 0x00000006, 0x00000006, 0x00000006, 0x00000006, 0x00000006, + 0x0000001d, 0x0000001d, 0x0000001d, 0x00000001, 0x00000006, 0x0000001d, 0x00000006, 0x00000001, 0x00000006, 0x00000001, 0x00000006, 0x00000006, 0x00000006, 0x00000001, 0x00000001, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xedffffff, 0xf77fffff, 0xfddfffff, 0xfffbefff, 0xfffbefff, 0xffff5fff, 0xffffbbff, 0xfbffffbf, 0xffffeeff, 0xfeffffef, 0xffbfbfff, 0xfffffbbf, 0xfffffeef, 0xfbfbffff, 0xfeffbfff, 0xffbfefff, + // terms 80-95 + // 39.4^43.29=0 38.4^42.29=0 37.1^38.6=1 37.4^41.29=0 36.4^38.4=1 35.1^36.6=1 35.3^39.28=0 61.1^62.6=1 + // 59.5^63.30=0 58.0^63.30=1 62.1^63.6=1 60.5^64.30=0 59.0^64.30=1 40.6^42.6=0 62.2^63.7=1 41.6^43.6=0 + 0x00000005, 0x00000004, 0x00000003, 0x00000003, 0x00000002, 0x00000001, 0x00000001, 0x0000001b, 0x00000019, 0x00000018, 0x0000001c, 0x0000001a, 0x00000019, 0x00000006, 0x0000001c, 0x00000007, + 0x00000009, 0x00000008, 0x00000004, 0x00000007, 0x00000004, 0x00000002, 0x00000005, 0x0000001c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001e, 0x0000001e, 0x00000008, 0x0000001d, 0x00000009, + 0x00000004, 0x00000004, 0x00000001, 0x00000004, 0x00000004, 0x00000001, 0x00000003, 0x00000001, 0x00000005, 0x00000000, 0x00000001, 0x00000005, 0x00000000, 0x00000006, 0x00000002, 0x00000006, + 0x0000001d, 0x0000001d, 0x00000006, 0x0000001d, 0x00000004, 0x00000006, 0x0000001c, 0x00000006, 0x0000001e, 0x0000001e, 0x00000006, 0x0000001e, 0x0000001e, 0x00000006, 0x00000007, 0x00000006, + 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, + 0xfdff7fff, 0xff7fdfff, 0xffffbeff, 0xffdff7ff, 0xd7ffffff, 0xfffffbef, 0xfff7dfff, 0xfffffffe, 0xfffffffe, 0xfffffffe, 0xfffffffd, 0xfffffffd, 0xfffffffd, 0xffffffef, 0xffffffbf, 0xffffffbf, + // terms 96-111 + // 63.2^64.7=1 48.6^49.1=0 49.6^50.1=0 42.1^50.1=1 39.6^40.1=0 38.1^40.1=1 36.4^37.4=1 43.1^51.1=1 + // 37.4^38.4=1 51.6^52.1=0 49.6^51.6=0 37.1^37.6=0 35.5^39.30=0 38.4^39.4=1 47.1^51.1=1 36.3^40.28=0 + 0x0000001d, 0x0000000e, 0x0000000f, 0x00000008, 0x00000005, 0x00000004, 0x00000002, 0x00000009, 0x00000003, 0x00000011, 0x0000000f, 0x00000003, 0x00000001, 0x00000004, 0x0000000d, 0x00000002, + 0x0000001e, 0x0000000f, 0x00000010, 0x00000010, 0x00000006, 0x00000006, 0x00000003, 0x00000011, 0x00000004, 0x00000012, 0x00000011, 0x00000003, 0x00000005, 0x00000005, 0x00000011, 0x00000006, + 0x00000002, 0x00000006, 0x00000006, 0x00000001, 0x00000006, 0x00000001, 0x00000004, 0x00000001, 0x00000004, 0x00000006, 0x00000006, 0x00000001, 0x00000005, 0x00000004, 0x00000001, 0x00000003, + 0x00000007, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000004, 0x00000001, 0x00000004, 0x00000001, 0x00000006, 0x00000006, 0x0000001e, 0x00000004, 0x00000001, 0x0000001c, + 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, + 0xfffffeff, 0xfffffeff, 0xfffffbff, 0xfffffbff, 0xfffffbff, 0xfffffbff, 0xfffff7ff, 0xffffefff, 0xffffdfff, 0xffffbfff, 0xffffbfff, 0xffffbfff, 0xffffbfff, 0xffff7fff, 0xfffbffff, 0xffefffff, + // terms 112-127 + // 35.30^40.28=1 37.3^41.28=0 36.30^41.28=1 53.6^54.1=0 51.6^53.6=0 50.1^54.1=1 45.6^46.1=0 37.5^41.30=0 + // 36.0^41.30=1 55.29^58.29=1 38.3^42.28=0 37.30^42.28=1 54.6^55.1=0 52.6^54.6=0 51.1^55.1=1 45.1^47.1=1 + 0x00000001, 0x00000003, 0x00000002, 0x00000013, 0x00000011, 0x00000010, 0x0000000b, 0x00000003, 0x00000002, 0x00000015, 0x00000004, 0x00000003, 0x00000014, 0x00000012, 0x00000011, 0x0000000b, + 0x00000006, 0x00000007, 0x00000007, 0x00000014, 0x00000013, 0x00000014, 0x0000000c, 0x00000007, 0x00000007, 0x00000018, 0x00000008, 0x00000008, 0x00000015, 0x00000014, 0x00000015, 0x0000000d, + 0x0000001e, 0x00000003, 0x0000001e, 0x00000006, 0x00000006, 0x00000001, 0x00000006, 0x00000005, 0x00000000, 0x0000001d, 0x00000003, 0x0000001e, 0x00000006, 0x00000006, 0x00000001, 0x00000001, + 0x0000001c, 0x0000001c, 0x0000001c, 0x00000001, 0x00000006, 0x00000001, 0x00000001, 0x0000001e, 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001c, 0x00000001, 0x00000006, 0x00000001, 0x00000001, + 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, + 0xffefffff, 0xffdfffff, 0xffdfffff, 0xffbfffff, 0xffbfffff, 0xffbfffff, 0xffbfffff, 0xffbfffff, 0xffbfffff, 0xff7fffff, 0xff7fffff, 0xff7fffff, 0xfeffffff, 0xfeffffff, 0xfeffffff, 0xfeffffff, + // terms 128-143 + // 38.5^42.30=0 37.0^42.30=1 39.3^43.28=0 38.30^43.28=1 55.6^56.1=0 53.6^55.6=0 52.1^56.1=1 46.1^48.1=1 + // 39.5^43.30=0 38.0^43.30=1 59.29^60.29=0 40.3^44.28=0 40.4^44.29=0 39.30^44.28=1 58.29^61.29=1 57.4^61.29=0 + 0x00000004, 0x00000003, 0x00000005, 0x00000004, 0x00000015, 0x00000013, 0x00000012, 0x0000000c, 0x00000005, 0x00000004, 0x00000019, 0x00000006, 0x00000006, 0x00000005, 0x00000018, 0x00000017, + 0x00000008, 0x00000008, 0x00000009, 0x00000009, 0x00000016, 0x00000015, 0x00000016, 0x0000000e, 0x00000009, 0x00000009, 0x0000001a, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000001b, 0x0000001b, + 0x00000005, 0x00000000, 0x00000003, 0x0000001e, 0x00000006, 0x00000006, 0x00000001, 0x00000001, 0x00000005, 0x00000000, 0x0000001d, 0x00000003, 0x00000004, 0x0000001e, 0x0000001d, 0x00000004, + 0x0000001e, 0x0000001e, 0x0000001c, 0x0000001c, 0x00000001, 0x00000006, 0x00000001, 0x00000001, 0x0000001e, 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001d, 0x0000001c, 0x0000001d, 0x0000001d, + 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, + 0xfeffffff, 0xfeffffff, 0xfdffffff, 0xfdffffff, 0xfbffffff, 0xfbffffff, 0xfbffffff, 0xfbffffff, 0xfbffffff, 0xfbffffff, 0xf7ffffff, 0xf7ffffff, 0xf7ffffff, 0xf7ffffff, 0xefffffff, 0xefffffff, + // terms 144-159 + // 41.3^45.28=0 41.4^45.29=0 58.4^62.29=0 42.3^46.28=0 42.4^46.29=0 59.4^63.29=0 57.4^59.29=0 43.3^47.28=0 + // 43.4^47.29=0 60.4^64.29=0 44.3^48.28=0 44.4^48.29=0 35.0^35.0=0 35.0^35.0=0 35.0^35.0=0 35.0^35.0=0 + 0x00000007, 0x00000007, 0x00000018, 0x00000008, 0x00000008, 0x00000019, 0x00000017, 0x00000009, 0x00000009, 0x0000001a, 0x0000000a, 0x0000000a, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x0000000b, 0x0000000b, 0x0000001c, 0x0000000c, 0x0000000c, 0x0000001d, 0x00000019, 0x0000000d, 0x0000000d, 0x0000001e, 0x0000000e, 0x0000000e, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000003, 0x00000004, 0x00000004, 0x00000003, 0x00000004, 0x00000004, 0x00000004, 0x00000003, 0x00000004, 0x00000004, 0x00000003, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0000001c, 0x0000001d, 0x0000001d, 0x0000001c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001c, 0x0000001d, 0x0000001d, 0x0000001c, 0x0000001d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xefffffff, 0xefffffff, 0xdfffffff, 0xdfffffff, 0xdfffffff, 0xbfffffff, 0xbfffffff, 0xbfffffff, 0xbfffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, +} diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_other.go b/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_other.go new file mode 100644 index 00000000..b76282b2 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/dvmask_other.go @@ -0,0 +1,14 @@ +//go:build noasm || !gc || !amd64 + +package ubc + +// CalculateDvMask takes as input an expanded message block and +// verifies the unavoidable bitconditions for all listed DVs. It returns +// a dvmask where each bit belonging to a DV is set if all unavoidable +// bitconditions for that DV have been met. +func CalculateDvMask(W *[80]uint32) uint32 { + if W == nil { + return 0 + } + return calculateDvMaskGeneric(W) +} diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/ubc.go b/vendor/github.com/pjbgf/sha1cd/ubc/ubc.go index bd932051..40447b0e 100644 --- a/vendor/github.com/pjbgf/sha1cd/ubc/ubc.go +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc.go @@ -23,16 +23,12 @@ type DvInfo struct { Dm [80]uint32 } -// CalculateDvMask takes as input an expanded message block and -// verifies the unavoidable bitconditions for all listed DVs. It returns -// a dvmask where each bit belonging to a DV is set if all unavoidable -// bitconditions for that DV have been met. +// calculateDvMaskGeneric is the portable implementation of CalculateDvMask. +// The AVX-512 kernel runs the same bit tests from avx512Terms, and +// TestAVX512MatchesGeneric holds the two to the same results. // //go:nosplit -func CalculateDvMask(W *[80]uint32) uint32 { - if W == nil { - return 0 - } +func calculateDvMaskGeneric(W *[80]uint32) uint32 { mask := uint32(0xFFFFFFFF) mask &= (((((W[44] ^ W[45]) >> 29) & 1) - 1) | ^(DV_I_48_0_bit | DV_I_51_0_bit | DV_I_52_0_bit | DV_II_45_0_bit | DV_II_46_0_bit | DV_II_50_0_bit | DV_II_51_0_bit)) mask &= (((((W[49] ^ W[50]) >> 29) & 1) - 1) | ^(DV_I_46_0_bit | DV_II_45_0_bit | DV_II_50_0_bit | DV_II_51_0_bit | DV_II_55_0_bit | DV_II_56_0_bit)) diff --git a/vendor/go.opentelemetry.io/otel/dependencies.Dockerfile b/vendor/go.opentelemetry.io/otel/dependencies.Dockerfile index ce43a98b..f0cc942b 100644 --- a/vendor/go.opentelemetry.io/otel/dependencies.Dockerfile +++ b/vendor/go.opentelemetry.io/otel/dependencies.Dockerfile @@ -1,4 +1,4 @@ # This is a renovate-friendly source of Docker images. FROM python:3.13.6-slim-bullseye@sha256:e98b521460ee75bca92175c16247bdf7275637a8faaeb2bcfa19d879ae5c4b9a AS python -FROM otel/weaver:v0.27.0@sha256:3049b4079049d4abb1b5632f511ada2c33505a1c60f3f8535e93f87f0696f056 AS weaver +FROM otel/weaver:v0.21.2@sha256:2401de985c38bdb98b43918e2f43aa36b2afed4aa5669ac1c1de0a17301cd36d AS weaver FROM avtodev/markdown-lint:v1@sha256:6aeedc2f49138ce7a1cd0adffc1b1c0321b841dc2102408967d9301c031949ee AS markdown diff --git a/vendor/golang.org/x/crypto/argon2/argon2.go b/vendor/golang.org/x/crypto/argon2/argon2.go index 2b65ec91..57ab8371 100644 --- a/vendor/golang.org/x/crypto/argon2/argon2.go +++ b/vendor/golang.org/x/crypto/argon2/argon2.go @@ -17,8 +17,8 @@ // 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 [RFC 9106 Section 7.3]) for non-interactive operations are time=3 and to -// use the maximum available memory. +// parameters (taken from [RFC 9106 Section 7.3]) for non-interactive +// operations are time=3 and to use the maximum available memory. // // # Argon2id // @@ -26,11 +26,14 @@ // 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 [RFC 9106 Section 7.3]) are time=1 and to -// use the maximum available memory. +// force cost savings due to time-memory tradeoffs than Argon2i. [RFC 9106 +// Section 4] recommends time=1, memory=2*1024*1024 KiB (2 GiB), and threads=4 +// as the first recommended option. If much less memory is available, it +// recommends time=3, memory=64*1024 KiB (64 MiB), and threads=4 as the second +// recommended option. // // [argon2-specs.pdf]: https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +// [RFC 9106 Section 4]: https://www.rfc-editor.org/rfc/rfc9106.html#section-4 // [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3 package argon2 @@ -59,9 +62,9 @@ const ( // // key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32) // -// [RFC 9106 Section 7.3] recommends time=3, and memory=32*1024 as 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 example above uses time=3 and memory=32*1024. Argon2i generally +// requires more passes over memory than Argon2id. If in doubt, prefer IDKey +// and its Argon2id parameter recommendations. // // 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 @@ -69,8 +72,6 @@ const ( // 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. -// -// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3 func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen) } @@ -83,20 +84,20 @@ func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint3 // 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) +// key := argon2.IDKey([]byte("some password"), salt, 1, 2*1024*1024, 4, 32) // -// [RFC 9106 Section 7.3] recommends time=1, and memory=64*1024 as 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 example above uses the first [RFC 9106 Section 4] recommended option. +// If much less memory is available, the second recommended option is time=3, +// memory=64*1024 KiB (64 MiB), and threads=4. // // 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 +// memory=2*1024*1024 sets the memory cost to ~2 GiB. 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. // -// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3 +// [RFC 9106 Section 4]: https://www.rfc-editor.org/rfc/rfc9106.html#section-4 func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen) } diff --git a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go index 8d99551f..b1da4568 100644 --- a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go +++ b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (!amd64 && !loong64 && !ppc64le && !ppc64 && !s390x) || !gc || purego +//go:build (!amd64 && !loong64 && !ppc64le && !ppc64 && !riscv64 && !s390x) || !gc || purego package poly1305 diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go index 315b84ac..55041bf5 100644 --- a/vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build gc && !purego && (amd64 || loong64 || ppc64 || ppc64le) +//go:build gc && !purego && (amd64 || loong64 || ppc64 || ppc64le || riscv64) package poly1305 diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_riscv64.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_riscv64.s new file mode 100644 index 00000000..ce5eb3d4 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_riscv64.s @@ -0,0 +1,158 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego + +#define LOAD64U(base, offset, t0, t1, t2, t3, dst) \ + MOVBU (offset+0*1)(base), t0; \ + MOVBU (offset+1*1)(base), t1; \ + MOVBU (offset+2*1)(base), t2; \ + MOVBU (offset+3*1)(base), t3; \ + SLL $8, t1; \ + SLL $16, t2; \ + SLL $24, t3; \ + OR t1, t0; \ + OR t3, t2; \ + OR t2, t0, dst; \ + MOVBU (offset+4*1)(base), t0; \ + MOVBU (offset+5*1)(base), t1; \ + MOVBU (offset+6*1)(base), t2; \ + MOVBU (offset+7*1)(base), t3; \ + SLL $32, t0; \ + SLL $40, t1; \ + SLL $48, t2; \ + SLL $56, t3; \ + OR t1, t0; \ + OR t3, t2; \ + OR t2, t0; \ + OR t0, dst + +// func update(state *macState, msg []byte) +TEXT ·update(SB), $0-32 + MOV state+0(FP), X5 + MOV msg_base+8(FP), X6 + MOV msg_len+16(FP), X7 + + MOV $16, X8 + + AND $7, X6, X28 + + MOV (0*8)(X5), X9 // h0 + MOV (1*8)(X5), X10 // h1 + MOV (2*8)(X5), X11 // h2 + MOV (3*8)(X5), X12 // r0 + MOV (4*8)(X5), X13 // r1 + + BLT X7, X8, tail + +loop: + BEQZ X28, aligned_load + + LOAD64U(X6, 0*8, X16, X18, X19, X20, X15) // msg[0:8] + LOAD64U(X6, 1*8, X16, X18, X19, X20, X17) // msg[8:16] + JMP block + +aligned_load: + MOV (0*8)(X6), X15 // msg[0:8] + MOV (1*8)(X6), X17 // msg[8:16] + +block: + ADD X15, X9 // h0 (x1 + y1 = z1', if z1' < x1 then z1' overflow) + SLTU X15, X9, X19 // h0.carry + ADD X17, X10, X22 + SLTU X17, X22, X23 + ADD X22, X19, X10 // h1 + SLTU X22, X10, X19 + OR X23, X19 // h1.carry + ADD $1, X19 + ADD X19, X11 // h2 + + ADD $16, X6 // msg = msg[16:] + +multiply: + MULHU X9, X12, X16 // h0r0.hi + MUL X9, X12, X15 // h0r0.lo + MULHU X10, X12, X17 // h1r0.hi + MUL X10, X12, X14 // h1r0.lo + ADD X14, X16 + SLTU X14, X16, X19 + ADD X19, X17 + MUL X11, X12, X20 + ADD X17, X20 + MULHU X9, X13, X17 // h0r1.hi + MUL X9, X13, X14 // h0r1.lo + ADD X14, X16 + SLTU X14, X16, X19 + ADD X19, X17 + MOV X17, X9 + MUL X11, X13, X21 // h2r1 + MULHU X10, X13, X17 // h1r1.hi + MUL X10, X13, X14 // h1r1.lo + ADD X14, X20 + ADD X17, X21, X22 + SLTU X14, X20, X19 + ADD X22, X19, X21 + ADD X9, X20 + SLTU X9, X20, X19 + ADD X19, X21 + AND $3, X20, X11 + AND $-4, X20, X18 + ADD X18, X15, X9 + ADD X21, X16, X22 + SLTU X18, X9, X19 + SLTU X21, X22, X23 + ADD X22, X19, X10 + SLTU X22, X10, X19 + OR X19, X23, X19 + ADD X19, X11 + SLL $62, X21, X22 + SRL $2, X20, X23 + SRL $2, X21, X21 + OR X22, X23, X20 + ADD X20, X9, X9 + ADD X21, X10, X22 + SLTU X20, X9, X19 + SLTU X21, X22, X23 + ADD X22, X19, X10 + SLTU X22, X10, X19 + OR X19, X23, X19 + ADD X19, X11, X11 + + SUB $16, X7, X7 + BGE X7, X8, loop + +tail: + BEQ X7, X0, done + MOV $1, X15 + MOV $0, X16 + ADD X7, X6, X6 + +flush_buffer: + MOVBU -1(X6), X20 + SRL $56, X15, X19 + SLL $8, X16, X23 + SLL $8, X15, X15 + OR X19, X23, X16 + XOR X20, X15 + SUB $1, X7, X7 + SUB $1, X6, X6 + BNE X7, X0, flush_buffer + + ADD X15, X9 + SLTU X15, X9, X19 + ADD X16, X10, X22 + SLTU X16, X22, X23 + ADD X22, X19, X10 + SLTU X22, X10, X19 + OR X23, X19 + ADD X19, X11 + + MOV $16, X7 + JMP multiply + +done: + MOV X9, (0*8)(X5) // h0 + MOV X10, (1*8)(X5) + MOV X11, (2*8)(X5) + RET diff --git a/vendor/golang.org/x/crypto/ssh/agent/forward.go b/vendor/golang.org/x/crypto/ssh/agent/forward.go index fd24ba90..5e7a0ea4 100644 --- a/vendor/golang.org/x/crypto/ssh/agent/forward.go +++ b/vendor/golang.org/x/crypto/ssh/agent/forward.go @@ -41,6 +41,7 @@ func ForwardToAgent(client *ssh.Client, keyring Agent) error { continue } go ssh.DiscardRequests(reqs) + go io.Copy(io.Discard, channel.Stderr()) go func() { ServeAgent(keyring, channel) channel.Close() @@ -72,6 +73,7 @@ func ForwardToRemote(client *ssh.Client, addr string) error { continue } go ssh.DiscardRequests(reqs) + go io.Copy(io.Discard, channel.Stderr()) go forwardUnixSocket(channel, addr) } }() diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/golang.org/x/crypto/ssh/agent/keyring.go index a9e29b6f..a4f4c11e 100644 --- a/vendor/golang.org/x/crypto/ssh/agent/keyring.go +++ b/vendor/golang.org/x/crypto/ssh/agent/keyring.go @@ -104,7 +104,7 @@ func (r *keyring) Unlock(passphrase []byte) error { if !r.locked { return errors.New("agent: not locked") } - if 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { + if subtle.ConstantTimeCompare(passphrase, r.passphrase) != 1 { return fmt.Errorf("agent: incorrect passphrase") } diff --git a/vendor/golang.org/x/crypto/ssh/agent/server.go b/vendor/golang.org/x/crypto/ssh/agent/server.go index f05d22fb..27394125 100644 --- a/vendor/golang.org/x/crypto/ssh/agent/server.go +++ b/vendor/golang.org/x/crypto/ssh/agent/server.go @@ -246,10 +246,10 @@ func setConstraints(key *AddedKey, constraintBytes []byte) error { // on arbitrary inputs; the CRT coefficient recomputation is cubic in // |p| and can consume excessive CPU on oversized keys. func checkRSAKeyParams(N, E, P, Q *big.Int) error { - if N.BitLen() > 8192 { + if N.BitLen() > 16384 { return errors.New("agent: RSA modulus too large") } - if P.BitLen() > 4096 || Q.BitLen() > 4096 { + if P.BitLen() > 8192 || Q.BitLen() > 8192 { return errors.New("agent: RSA prime too large") } if E.BitLen() > 24 { @@ -304,19 +304,60 @@ func parseEd25519Key(req []byte) (*AddedKey, error) { return addedKey, nil } +func checkDSAParams(param *dsa.Parameters) error { + // SSH specifies FIPS 186-2, which only provided a single size + // (1024 bits) DSA key. FIPS 186-3 allows for larger key + // sizes, which would confuse SSH. + if l := param.P.BitLen(); l != 1024 { + return fmt.Errorf("ssh: unsupported DSA key size %d", l) + } + + // FIPS 186-2 specifies that Q must be exactly 160 bits. We must enforce + // this to prevent DoS attacks where an attacker sends a huge Q which makes + // verification slow. + if l := param.Q.BitLen(); l != 160 { + return fmt.Errorf("ssh: unsupported DSA sub-prime size %d", l) + } + + // The generator G is an element of the group, so it must be strictly less + // than the modulus P. + if param.G.Cmp(param.P) >= 0 { + return errors.New("ssh: DSA generator larger than modulus") + } + + // G must be positive. + if param.G.Sign() <= 0 { + return errors.New("ssh: DSA generator must be positive") + } + + return nil +} + func parseDSAKey(req []byte) (*AddedKey, error) { var k dsaKeyMsg if err := ssh.Unmarshal(req, &k); err != nil { return nil, err } + params := dsa.Parameters{ + P: k.P, + Q: k.Q, + G: k.G, + } + if err := checkDSAParams(¶ms); err != nil { + return nil, err + } + + // The public value Y must be a non-zero element of the group, i.e. strictly + // between 0 and P, to prevent a maliciously oversized Y from slowing + // signature operations. + if k.Y.Sign() <= 0 || k.Y.Cmp(k.P) >= 0 { + return nil, errors.New("agent: DSA public value Y out of range") + } + priv := &dsa.PrivateKey{ PublicKey: dsa.PublicKey{ - Parameters: dsa.Parameters{ - P: k.P, - Q: k.Q, - G: k.G, - }, - Y: k.Y, + Parameters: params, + Y: k.Y, }, X: k.X, } diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go index 6f75d77e..a3b802e4 100644 --- a/vendor/golang.org/x/crypto/ssh/certs.go +++ b/vendor/golang.org/x/crypto/ssh/certs.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "net" + "slices" "sort" "time" ) @@ -229,15 +230,20 @@ func parseCert(in []byte, privAlgo string) (*Certificate, error) { return nil, err } c.Reserved = g.Reserved + // Reject a certificate whose signature key is itself a certificate before + // parsing it. Certificates signed by certificates are not supported (see + // PROTOCOL.certkeys), and rejecting after ParsePublicKey returns would allow + // a chain of nested certificates to recurse once per level, exhausting the + // goroutine stack. + if sigAlgo, _, ok := parseString(g.SignatureKey); !ok { + return nil, errShortRead + } else if _, ok := certKeyAlgoNames[string(sigAlgo)]; ok { + return nil, fmt.Errorf("ssh: the signature key type %q is invalid for certificates", sigAlgo) + } k, err := ParsePublicKey(g.SignatureKey) if err != nil { return nil, err } - // The Type() function is intended to return only certificate key types, but - // we use certKeyAlgoNames anyway for safety, to match [Certificate.Type]. - if _, ok := certKeyAlgoNames[k.Type()]; ok { - return nil, fmt.Errorf("ssh: the signature key type %q is invalid for certificates", k.Type()) - } c.SignatureKey = k c.Signature, rest, ok = parseSignatureBody(g.Signature) if !ok || len(rest) > 0 { @@ -300,8 +306,11 @@ const sourceAddressCriticalOption = "source-address" // minimally, the IsAuthority callback should be set. type CertChecker struct { // SupportedCriticalOptions lists the CriticalOptions that the - // server application layer understands. These are only used - // for user certificates. + // application layer understands. A certificate carrying a critical + // option that is not listed here is rejected. + // CertChecker.Authenticate additionally accepts the source-address + // option, which the server enforces on the Permissions that + // Authenticate returns. SupportedCriticalOptions []string // IsUserAuthority should return true if the key is recognized as an @@ -364,8 +373,9 @@ func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) return c.CheckCert(hostname, cert) } -// Authenticate checks a user certificate. Authenticate can be used as -// a value for ServerConfig.PublicKeyCallback. +// Authenticate checks a user certificate. Authenticate can be used as a value +// for ServerConfig.PublicKeyCallback. The source-address critical option is +// allowed, as it will be enforced by the server. func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { cert, ok := pubKey.(*Certificate) if !ok { @@ -384,8 +394,11 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis if !c.IsUserAuthority(cert.SignatureKey) { return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") } - - if err := c.CheckCert(conn.User(), cert); err != nil { + // The source-address critical option is enforced by serverAuthenticate, + // so it is supported regardless of SupportedCriticalOptions + cc := *c + cc.SupportedCriticalOptions = append(slices.Clip(cc.SupportedCriticalOptions), sourceAddressCriticalOption) + if err := cc.CheckCert(conn.User(), cert); err != nil { return nil, err } @@ -393,27 +406,15 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis } // CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and -// the signature of the certificate. +// the signature of the certificate. Critical options that are not listed in +// SupportedCriticalOptions are rejected. func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { if c.IsRevoked != nil && c.IsRevoked(cert) { return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial) } for opt := range cert.CriticalOptions { - // sourceAddressCriticalOption will be enforced by - // serverAuthenticate - if opt == sourceAddressCriticalOption { - continue - } - - found := false - for _, supp := range c.SupportedCriticalOptions { - if supp == opt { - found = true - break - } - } - if !found { + if !slices.Contains(c.SupportedCriticalOptions, opt) { return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) } } diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go index afc9aef1..d6010fd7 100644 --- a/vendor/golang.org/x/crypto/ssh/channel.go +++ b/vendor/golang.org/x/crypto/ssh/channel.go @@ -173,6 +173,12 @@ type channel struct { // (for outbound channels) or received (for inbound channels). decided bool + // established is set to true once the channel is open and may carry normal + // channel traffic: for an outbound channel when the peer's open + // confirmation is received, for an inbound channel when the local side + // accepts it. It is set and read from different goroutines. + established atomic.Bool + // direction contains either channelOutbound, for channels created // locally, or channelInbound, for channels created by the peer. direction channelDirection @@ -216,6 +222,10 @@ type channel struct { // packetPool has a buffer for each extended channel ID to // save allocations during writes. packetPool map[uint32][]byte + + // closeOnce guards close so it is idempotent: closing the internal Go + // channels (msg, incomingRequests) more than once would panic. + closeOnce sync.Once } // writePacket sends a packet. If the packet is a channel close, it updates @@ -340,7 +350,18 @@ func (ch *channel) handleData(packet []byte) error { if extended == 1 { ch.extPending.write(data) } else if extended > 0 { - // discard other extended data. + // RFC 4254, Section 5.2 defines no extended data types other + // than stderr (type 1, handled above) and this package provides + // no API to read them, so the data is discarded. Credit its + // window back immediately: it can never be read, so the + // deduction above would otherwise shrink the window permanently. + // adjustWindow returns io.EOF if the local side has already + // sent a channel close; ignore it like ReadExtended does, since + // an error returned here would terminate the mux read loop and + // tear down the whole connection. + if err := ch.adjustWindow(length); err != nil && err != io.EOF { + return err + } } else { ch.pending.write(data) } @@ -393,17 +414,19 @@ func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) } func (c *channel) close() { - c.pending.eof() - c.extPending.eof() - close(c.msg) - close(c.incomingRequests) - c.writeMu.Lock() - // This is not necessary for a normal channel teardown, but if - // there was another error, it is. - c.sentClose = true - c.writeMu.Unlock() - // Unblock writers. - c.remoteWin.close() + c.closeOnce.Do(func() { + c.pending.eof() + c.extPending.eof() + close(c.msg) + close(c.incomingRequests) + c.writeMu.Lock() + // This is not necessary for a normal channel teardown, but if + // there was another error, it is. + c.sentClose = true + c.writeMu.Unlock() + // Unblock writers. + c.remoteWin.close() + }) } // responseMessageReceived is called when a success or failure message is @@ -417,10 +440,20 @@ func (ch *channel) responseMessageReceived() error { return errors.New("ssh: duplicate response received for channel") } ch.decided = true + ch.established.Store(true) return nil } func (ch *channel) handlePacket(packet []byte) error { + // Only the open response is expected before the channel is established. + if !ch.established.Load() { + switch packet[0] { + case msgChannelOpenConfirm, msgChannelOpenFailure: + default: + return nil + } + } + switch packet[0] { case msgChannelData, msgChannelExtendedData: return ch.handleData(packet) @@ -486,26 +519,28 @@ func (ch *channel) handlePacket(packet []byte) error { default: } default: - ch.msg <- msg + // No other message type is expected on an established channel. + return fmt.Errorf("ssh: unexpected message type %d on channel %d", packet[0], ch.localId) } return nil } func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel { ch := &channel{ - remoteWin: window{Cond: newCond()}, - myWindow: channelWindowSize, - pending: newBuffer(), - extPending: newBuffer(), - direction: direction, - incomingRequests: make(chan *Request, chanSize), - msg: make(chan interface{}, chanSize), - chanType: chanType, - extraData: extraData, - mux: m, - packetPool: make(map[uint32][]byte), + remoteWin: window{Cond: newCond()}, + myWindow: channelWindowSize, + maxIncomingPayload: channelMaxPacket, + pending: newBuffer(), + extPending: newBuffer(), + direction: direction, + incomingRequests: make(chan *Request, chanSize), + msg: make(chan interface{}, chanSize), + chanType: chanType, + extraData: extraData, + mux: m, + packetPool: make(map[uint32][]byte), } - ch.localId = m.chanList.add(ch) + m.chanList.add(ch) return ch } @@ -529,7 +564,6 @@ func (ch *channel) Accept() (Channel, <-chan *Request, error) { if ch.decided { return nil, nil, errDecidedAlready } - ch.maxIncomingPayload = channelMaxPacket confirm := channelOpenConfirmMsg{ PeersID: ch.remoteId, MyID: ch.localId, @@ -537,6 +571,7 @@ func (ch *channel) Accept() (Channel, <-chan *Request, error) { MaxPacketSize: ch.maxIncomingPayload, } ch.decided = true + ch.established.Store(true) if err := ch.sendMessage(confirm); err != nil { return nil, nil, err } diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go index 60af2fc4..138cc900 100644 --- a/vendor/golang.org/x/crypto/ssh/client_auth.go +++ b/vendor/golang.org/x/crypto/ssh/client_auth.go @@ -798,7 +798,7 @@ func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, return authFailure, nil, fmt.Errorf("GSS-API Error:\n"+ "Major Status: %d\n"+ "Minor Status: %d\n"+ - "Error Message: %s\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus, + "Error Message: %q\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus, userAuthGSSAPIErrorResp.Message) case msgUserAuthGSSAPIToken: userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go index 2e44e9c9..aed0fd92 100644 --- a/vendor/golang.org/x/crypto/ssh/common.go +++ b/vendor/golang.org/x/crypto/ssh/common.go @@ -419,7 +419,7 @@ type AlgorithmNegotiationError struct { } func (a *AlgorithmNegotiationError) Error() string { - return fmt.Sprintf("ssh: no common algorithm for %s; we offered: %v, peer offered: %v", + return fmt.Sprintf("ssh: no common algorithm for %s; we offered: %q, peer offered: %q", a.What, a.SupportedAlgorithms, a.RequestedAlgorithms) } @@ -544,7 +544,7 @@ func (c *Config) SetDefaults() { if c.Rand == nil { c.Rand = rand.Reader } - if c.Ciphers == nil { + if len(c.Ciphers) == 0 { c.Ciphers = defaultCiphers } var ciphers []string @@ -556,7 +556,7 @@ func (c *Config) SetDefaults() { } c.Ciphers = ciphers - if c.KeyExchanges == nil { + if len(c.KeyExchanges) == 0 { c.KeyExchanges = defaultKexAlgos } var kexs []string @@ -571,7 +571,7 @@ func (c *Config) SetDefaults() { } c.KeyExchanges = kexs - if c.MACs == nil { + if len(c.MACs) == 0 { c.MACs = defaultMACs } var macs []string diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go index 378f6407..9e0ed089 100644 --- a/vendor/golang.org/x/crypto/ssh/connection.go +++ b/vendor/golang.org/x/crypto/ssh/connection.go @@ -17,7 +17,7 @@ type OpenChannelError struct { } func (e *OpenChannelError) Error() string { - return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) + return fmt.Sprintf("ssh: rejected: %s (%q)", e.Reason, e.Message) } // ConnMetadata holds metadata for the connection. diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go index 4be3cbb6..711a7f7c 100644 --- a/vendor/golang.org/x/crypto/ssh/handshake.go +++ b/vendor/golang.org/x/crypto/ssh/handshake.go @@ -162,7 +162,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt t.remoteAddr = addr t.hostKeyCallback = config.HostKeyCallback t.bannerCallback = config.BannerCallback - if config.HostKeyAlgorithms != nil { + if len(config.HostKeyAlgorithms) > 0 { t.hostKeyAlgorithms = config.HostKeyAlgorithms } else { t.hostKeyAlgorithms = defaultHostKeyAlgos diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go index 334861b7..fbbfb6cf 100644 --- a/vendor/golang.org/x/crypto/ssh/keys.go +++ b/vendor/golang.org/x/crypto/ssh/keys.go @@ -182,14 +182,19 @@ func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey } hosts := string(keyFields[0]) - // keyFields[1] contains the key type (e.g. “ssh-rsa”). - // However, that information is duplicated inside the - // base64-encoded key and so is ignored here. + // keyFields[1] contains the key type (e.g. "ssh-rsa"). This information + // is duplicated within the base64-encoded key blob. As OpenSSH's + // sshkey_read does, we verify that the declared key type matches the + // type embedded in the key blob. + wantType := string(keyFields[1]) key := bytes.Join(keyFields[2:], []byte(" ")) if pubKey, comment, err = parseAuthorizedKey(key); err != nil { return "", nil, nil, "", nil, err } + if pubKey.Type() != wantType { + return "", nil, nil, "", nil, fmt.Errorf("ssh: known hosts key type mismatch: human-readable type %q, encoded type %q", wantType, pubKey.Type()) + } return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil } @@ -228,10 +233,17 @@ func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []str } if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { - return out, comment, options, rest, nil - } else { - lastErr = err + // The first field contains the declared key type. As OpenSSH's + // sshkey_read does, we verify that it matches the type embedded in + // the key blob. Without this check, a single-token option (e.g. + // "restrict") appearing in the key type position could be silently + // discarded along with its intended effect. + if string(in[:i]) == out.Type() { + return out, comment, options, rest, nil + } + err = fmt.Errorf("ssh: authorized keys key type mismatch: human-readable type %q, encoded type %q", in[:i], out.Type()) } + lastErr = err // No key type recognised. Maybe there's an options field at // the beginning. @@ -271,11 +283,15 @@ func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []str } if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { - options = candidateOptions - return out, comment, options, rest, nil - } else { - lastErr = err + // As above, the declared key type (here following the options + // field) must match the type embedded in the key blob. + if string(in[:i]) == out.Type() { + options = candidateOptions + return out, comment, options, rest, nil + } + err = fmt.Errorf("ssh: authorized keys key type mismatch: human-readable type %q, encoded type %q", in[:i], out.Type()) } + lastErr = err in = rest continue @@ -469,10 +485,11 @@ func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { return nil, nil, err } - // 8192 bits is also the maximum RSA key size accepted by crypto/tls for - // signature verification: - // https://github.com/golang/go/blob/69801b25/src/crypto/tls/handshake_client.go#L1096 - if w.N.BitLen() > 8192 { + // 16384 bits is the largest RSA key OpenSSH will generate (ssh-keygen + // caps -b at 16384), so it is the practical upper bound for keys seen on + // the wire. Rejecting anything larger bounds the CPU spent verifying an + // attacker-supplied key and signature, mitigating a denial of service. + if w.N.BitLen() > 16384 { return nil, nil, errors.New("ssh: rsa modulus too large") } if w.E.BitLen() > 24 { @@ -1653,13 +1670,13 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv } // Mirror the validation done in parseRSA for public keys: cap the - // modulus at the same limit enforced by crypto/tls, reject oversized - // or invalid exponents, and additionally bound the prime factors to + // modulus at the OpenSSH-generated maximum, reject oversized or + // invalid exponents, and additionally bound the prime factors to // avoid the expensive CRT coefficient recomputation in pk.Precompute. - if key.N.BitLen() > 8192 { + if key.N.BitLen() > 16384 { return nil, errors.New("ssh: rsa modulus too large") } - if key.P.BitLen() > 4096 || key.Q.BitLen() > 4096 { + if key.P.BitLen() > 8192 || key.Q.BitLen() > 8192 { return nil, errors.New("ssh: rsa prime too large") } if key.E.BitLen() > 24 { diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go index cf520ad9..017c696a 100644 --- a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go +++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go @@ -142,6 +142,15 @@ func keyEq(a, b ssh.PublicKey) bool { return bytes.Equal(a.Marshal(), b.Marshal()) } +// plainKeyBlob returns the serialized public portion of key: for a +// certificate this is the certified key, otherwise the key itself. +func plainKeyBlob(key ssh.PublicKey) string { + if cert, ok := key.(*ssh.Certificate); ok { + return string(cert.Key.Marshal()) + } + return string(key.Marshal()) +} + // IsHostAuthority can be used as a callback in ssh.CertChecker func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool { h, p, err := net.SplitHostPort(address) @@ -160,10 +169,10 @@ func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool // IsRevoked can be used as a callback in ssh.CertChecker func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool { - if _, ok := db.revoked[string(key.Marshal())]; ok { + if _, ok := db.revoked[plainKeyBlob(key)]; ok { return true } - if _, ok := db.revoked[string(key.SignatureKey.Marshal())]; ok { + if _, ok := db.revoked[plainKeyBlob(key.SignatureKey)]; ok { return true } return false @@ -228,7 +237,7 @@ func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error } if marker == markerRevoked { - db.revoked[string(key.Marshal())] = &KnownKey{ + db.revoked[plainKeyBlob(key)] = &KnownKey{ Key: key, Filename: filename, Line: linenum, @@ -341,7 +350,7 @@ func (r *RevokedError) Error() string { // check checks a key against the host database. This should not be // used for verifying certificates. func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.PublicKey) error { - if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil { + if revoked := db.revoked[plainKeyBlob(remoteKey)]; revoked != nil { return &RevokedError{Revoked: *revoked} } diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go index ab22c3d3..1d23dde2 100644 --- a/vendor/golang.org/x/crypto/ssh/messages.go +++ b/vendor/golang.org/x/crypto/ssh/messages.go @@ -44,7 +44,7 @@ type disconnectMsg struct { } func (d *disconnectMsg) Error() string { - return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message) + return fmt.Sprintf("ssh: disconnect, reason %d: %q", d.Reason, d.Message) } // See RFC 4253, section 7.1. diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go index 5775881c..955560bd 100644 --- a/vendor/golang.org/x/crypto/ssh/mux.go +++ b/vendor/golang.org/x/crypto/ssh/mux.go @@ -32,18 +32,21 @@ type chanList struct { offset uint32 } -// Assigns a channel ID to the given channel. -func (c *chanList) add(ch *channel) uint32 { +// add stores the given channel and assigns its localId while holding the +// lock, so that getChan can never return a channel whose localId is not yet +// initialized. +func (c *chanList) add(ch *channel) { c.Lock() defer c.Unlock() for i := range c.chans { if c.chans[i] == nil { c.chans[i] = ch - return uint32(i) + c.offset + ch.localId = uint32(i) + c.offset + return } } c.chans = append(c.chans, ch) - return uint32(len(c.chans)-1) + c.offset + ch.localId = uint32(len(c.chans)-1) + c.offset } // getChan returns the channel for the given ID. @@ -343,8 +346,6 @@ func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Reque func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { ch := m.newChannel(chanType, channelOutbound, extra) - ch.maxIncomingPayload = channelMaxPacket - open := channelOpenMsg{ ChanType: chanType, PeersWindow: ch.myWindow, diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go index 3c0fcc95..e0902626 100644 --- a/vendor/golang.org/x/crypto/ssh/server.go +++ b/vendor/golang.org/x/crypto/ssh/server.go @@ -26,10 +26,16 @@ type Permissions struct { // defines "force-command" (only allow the given command to // execute) and "source-address" (only allow connections from // the given address). The SSH package currently only enforces - // the "source-address" critical option. It is up to server - // implementations to enforce other critical options, such as - // "force-command", by checking them after the SSH handshake - // is successful. In general, SSH servers should reject + // the "source-address" critical option: it is validated against + // the client's remote address whenever it is present in the + // Permissions returned by any authentication callback. Its value + // is a comma-separated list of IP addresses and CIDR blocks; + // consistently with OpenSSH, a connection whose remote address is + // not an IP address, such as a Unix domain socket, never matches + // the list and is rejected when the option is present. It is up + // to server implementations to enforce other critical options, + // such as "force-command", by checking them after the SSH + // handshake is successful. In general, SSH servers should reject // connections that specify critical options that are unknown // or not supported. CriticalOptions map[string]string @@ -223,7 +229,9 @@ type ServerConfig struct { // Permissions object can be the same object, optionally modified, or a // completely new object. If VerifiedPublicKeyCallback is non-nil, // PublicKeyCallback is not allowed to return a PartialSuccessError, which - // can instead be returned by VerifiedPublicKeyCallback. + // can instead be returned by VerifiedPublicKeyCallback. The + // signatureAlgorithm argument is the format of the signature that was + // successfully verified. // // VerifiedPublicKeyCallback does not affect which authentication methods // are included in the list of methods that can be attempted by the client. @@ -442,6 +450,10 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) return perms, err } +// checkSourceAddress matches addr against sourceAddrs, a comma-separated list +// of IP addresses and CIDR blocks. Consistently with OpenSSH, a remote address +// that is not IP-based, such as a Unix domain socket, never matches the list +// and is rejected. func checkSourceAddress(addr net.Addr, sourceAddrs string) error { if addr == nil { return errors.New("ssh: no address known for client, but source-address match required") @@ -449,7 +461,7 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error { tcpAddr, ok := addr.(*net.TCPAddr) if !ok { - return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr) + return fmt.Errorf("ssh: remote address %v is not a TCP address when checking source-address match", addr) } for _, sourceAddr := range strings.Split(sourceAddrs, ",") { @@ -472,6 +484,21 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error { return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) } +// checkSourceAddressCriticalOption enforces the source-address critical +// option, if present in perms, as documented in Permissions.CriticalOptions. +// A present but empty value matches no address, so it denies authentication, +// consistently with OpenSSH, rather than being treated as absent. +func checkSourceAddressCriticalOption(addr net.Addr, perms *Permissions) error { + if perms == nil { + return nil + } + saco, ok := perms.CriticalOptions[sourceAddressCriticalOption] + if !ok { + return nil + } + return checkSourceAddress(addr, saco) +} + func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, token []byte, s *connection, sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) { gssAPIServer := gssapiConfig.Server @@ -685,7 +712,7 @@ userAuthLoop: } if userAuthReq.Service != serviceSSH { - return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service) + return nil, fmt.Errorf("ssh: client attempted to negotiate for unknown service: %q", userAuthReq.Service) } if s.user != userAuthReq.User && partialSuccessReturned { @@ -771,7 +798,8 @@ userAuthLoop: pubKey, err := ParsePublicKey(pubKeyData) if err != nil { - return nil, err + authErr = err + break } candidate, ok := cache.get(s.user, pubKeyData) @@ -784,13 +812,14 @@ userAuthLoop: return nil, errors.New("ssh: invalid library usage: PublicKeyCallback must not return partial success when VerifiedPublicKeyCallback is defined") } - if (candidate.result == nil || isPartialSuccessError) && - candidate.perms != nil && - candidate.perms.CriticalOptions != nil && - candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" { - if err := checkSourceAddress( - s.RemoteAddr(), - candidate.perms.CriticalOptions[sourceAddressCriticalOption]); err != nil { + // This check is authoritative for the Permissions returned by + // PublicKeyCallback: the check at the end of the auth loop sees + // the final Permissions, which VerifiedPublicKeyCallback may + // have replaced, and is skipped on partial success. It also + // makes public key queries fail before the client signs when + // PublicKeyCallback supplies the restriction. + if candidate.result == nil || isPartialSuccessError { + if err := checkSourceAddressCriticalOption(s.RemoteAddr(), candidate.perms); err != nil { candidate.result = err } } @@ -864,14 +893,7 @@ userAuthLoop: // Only call VerifiedPublicKeyCallback after the key has been accepted // and successfully verified. If authErr is non-nil, the key is not // considered verified and the callback must not run. - perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, algo) - } - if authErr == nil && perms != nil && perms.CriticalOptions != nil { - if saco := perms.CriticalOptions[sourceAddressCriticalOption]; saco != "" { - if err := checkSourceAddress(s.RemoteAddr(), saco); err != nil { - authErr = err - } - } + perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, sig.Format) } } case "gssapi-with-mic": @@ -925,6 +947,17 @@ userAuthLoop: authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) } + // The source-address critical option is enforced on the Permissions + // returned by any authentication callback. Permissions returned + // together with a PartialSuccessError skip this check: that is safe + // because they are required to be nil, as enforced in the partial + // success handling below. + if authErr == nil { + if err := checkSourceAddressCriticalOption(s.RemoteAddr(), perms); err != nil { + authErr = err + } + } + authErrs = append(authErrs, authErr) if config.AuthLogCallback != nil { diff --git a/vendor/golang.org/x/crypto/ssh/ssh_gss.go b/vendor/golang.org/x/crypto/ssh/ssh_gss.go index a6249a12..a7a09975 100644 --- a/vendor/golang.org/x/crypto/ssh/ssh_gss.go +++ b/vendor/golang.org/x/crypto/ssh/ssh_gss.go @@ -118,24 +118,28 @@ func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) { OIDS: make([]asn1.ObjectIdentifier, n), } for i := 0; i < int(n); i++ { - var ( - desiredMech []byte - err error - ) + var desiredMech []byte desiredMech, rest, ok = parseString(rest) if !ok { return nil, errors.New("parse string failed") } - if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil { + trailing, err := asn1.Unmarshal(desiredMech, &s.OIDS[i]) + if err != nil { return nil, err } + if len(trailing) != 0 { + return nil, errors.New("trailing bytes after OID") + } + } + if len(rest) != 0 { + return nil, errors.New("trailing bytes after mechanisms") } return s, nil } // See RFC 4462 section 3.6. func buildMIC(sessionID string, username string, service string, authMethod string) []byte { - out := make([]byte, 0, 0) + out := make([]byte, 0) out = appendString(out, sessionID) out = append(out, msgUserAuthRequest) out = appendString(out, username) diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go index 152470fc..8e997da3 100644 --- a/vendor/golang.org/x/crypto/ssh/streamlocal.go +++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go @@ -58,6 +58,7 @@ func (c *Client) dialStreamLocal(socketPath string) (Channel, error) { return nil, err } go DiscardRequests(in) + go io.Copy(io.Discard, ch.Stderr()) return ch, err } @@ -79,6 +80,7 @@ func (l *unixListener) Accept() (net.Conn, error) { return nil, err } go DiscardRequests(incoming) + go io.Copy(io.Discard, ch.Stderr()) return &chanConn{ Channel: ch, diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go index 78c41fe5..213d8a61 100644 --- a/vendor/golang.org/x/crypto/ssh/tcpip.go +++ b/vendor/golang.org/x/crypto/ssh/tcpip.go @@ -332,6 +332,7 @@ func (l *tcpListener) Accept() (net.Conn, error) { return nil, err } go DiscardRequests(incoming) + go io.Copy(io.Discard, ch.Stderr()) return &chanConn{ Channel: ch, @@ -495,6 +496,7 @@ func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel return nil, err } go DiscardRequests(in) + go io.Copy(io.Discard, ch.Stderr()) return ch, nil } diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go index fa3dd6a4..540865df 100644 --- a/vendor/golang.org/x/crypto/ssh/transport.go +++ b/vendor/golang.org/x/crypto/ssh/transport.go @@ -331,13 +331,19 @@ func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err er // chars const maxVersionStringBytes = 255 +// maxPreVersionLines is the maximum number of lines sent by the peer +// before the version string. Each of these lines is limited to a maximum +// of maxVersionStringBytes chars. Lines sent before the version string +// are silently ignored. +const maxPreVersionLines = 1024 + // Read version string as specified by RFC 4253, section 4.2. func readVersion(r io.Reader) ([]byte, error) { versionString := make([]byte, 0, 64) var ok bool var buf [1]byte - for length := 0; length < maxVersionStringBytes; length++ { + for lines := 0; len(versionString) < maxVersionStringBytes && lines < maxPreVersionLines; { _, err := io.ReadFull(r, buf[:]) if err != nil { return nil, err @@ -347,9 +353,9 @@ func readVersion(r io.Reader) ([]byte, error) { if buf[0] == '\n' { if !bytes.HasPrefix(versionString, []byte("SSH-")) { // RFC 4253 says we need to ignore all version string lines - // except the one containing the SSH version (provided that - // all the lines do not exceed 255 bytes in total). + // except the one containing the SSH version. versionString = versionString[:0] + lines++ continue } ok = true diff --git a/vendor/golang.org/x/net/http2/transport_wrap.go b/vendor/golang.org/x/net/http2/transport_wrap.go index eab2e6b0..534e77ab 100644 --- a/vendor/golang.org/x/net/http2/transport_wrap.go +++ b/vendor/golang.org/x/net/http2/transport_wrap.go @@ -55,7 +55,7 @@ type transportConfig struct { // Registered is called by net/http.Transport.RegisterProtocol, // to let us know that it understands the registration mechanism we're using. func (t transportConfig) Registered(t1 *http.Transport) { - t.t.t1 = t1 + t.t.lazyt1 = t1 } func (t transportConfig) DisableCompression() bool { @@ -145,29 +145,30 @@ func (t transportConfig) DialFromContext(ctx context.Context, network, address s type transportInternal struct { initOnce sync.Once - t1 *http.Transport + lazyt1 *http.Transport } -func (t *Transport) init() { +func (t *Transport) init() *http.Transport { t.initOnce.Do(func() { - if t.t1 != nil { + if t.lazyt1 != nil { return } t1 := &http.Transport{} t.configure(t1) }) + return t.lazyt1 } func (t *Transport) configure(t1 *http.Transport) { t1.RegisterProtocol("http/2", transportConfig{t}) - // tr2.t1 is set by transportConfig.Registered. - if t.t1 != t1 { + // tr2.lazyt1 is set by transportConfig.Registered. + if t.lazyt1 != t1 { panic("http2: net/http does not support this version of x/net/http2") } } func (t *Transport) roundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) { - t.init() + t1 := t.init() if req.URL.Scheme == "http" && !t.AllowHTTP { return nil, errors.New("http2: unencrypted HTTP/2 not enabled") @@ -188,22 +189,23 @@ func (t *Transport) roundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res ctx := context.WithValue(req.Context(), http2TransportContextKey{}, t) req = req.WithContext(ctx) - return t.t1.RoundTrip(req) + return t1.RoundTrip(req) } func (t *Transport) closeIdleConnections() { - t.init() - t.t1.CloseIdleConnections() + t1 := t.init() + t1.CloseIdleConnections() } func (t *Transport) newUserClientConn(c net.Conn) (*ClientConn, error) { + t1 := t.init() // http.Transport's NewClientConn doesn't provide a supported way to create // a connection from a net.Conn. (This might be useful to add in the future?) // We're going to craftily sneak one in via the context key, with the // scheme of "http/2" telling NewClientConn to look for it. ctx := context.WithValue(context.Background(), netConnContextKey{}, c) - nhcc, err := t.t1.NewClientConn(ctx, "http/2", "") + nhcc, err := t1.NewClientConn(ctx, "http/2", "") if err != nil { return nil, err } diff --git a/vendor/golang.org/x/net/idna/idna.go b/vendor/golang.org/x/net/idna/idna.go index 22767125..e2f28fed 100644 --- a/vendor/golang.org/x/net/idna/idna.go +++ b/vendor/golang.org/x/net/idna/idna.go @@ -400,7 +400,11 @@ func (p *Profile) process(s string, toASCII bool) (string, error) { // Spec says keep the old label. continue } - if unicode16 && err == nil && len(u) > 0 && isASCII(u) { + if err == nil && len(u) > 0 && isASCII(u) { + // UTS 43 pre-revision 33 doesn't classify a xn-- label + // which contains only ASCII characters as an error, + // but that's a specification bug and a security issue. + // Always return an error in this case. err = punyError(enc) } isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight diff --git a/vendor/modules.txt b/vendor/modules.txt index f35ca434..4b530142 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -280,7 +280,7 @@ github.com/go-git/gcfg github.com/go-git/gcfg/scanner github.com/go-git/gcfg/token github.com/go-git/gcfg/types -# github.com/go-git/go-billy/v5 v5.9.0 +# github.com/go-git/go-billy/v5 v5.9.2 ## explicit; go 1.25.0 github.com/go-git/go-billy/v5 github.com/go-git/go-billy/v5/helper/chroot @@ -288,8 +288,8 @@ github.com/go-git/go-billy/v5/helper/polyfill github.com/go-git/go-billy/v5/memfs github.com/go-git/go-billy/v5/osfs github.com/go-git/go-billy/v5/util -# github.com/go-git/go-git/v5 v5.19.2 -## explicit; go 1.25.0 +# github.com/go-git/go-git/v5 v5.19.3 +## explicit; go 1.26.0 github.com/go-git/go-git/v5 github.com/go-git/go-git/v5/config github.com/go-git/go-git/v5/internal/path_util @@ -403,9 +403,6 @@ github.com/klauspost/compress/internal/le github.com/klauspost/compress/internal/snapref github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash -# github.com/klauspost/cpuid/v2 v2.3.0 -## explicit; go 1.22 -github.com/klauspost/cpuid/v2 # github.com/leonelquinteros/gotext v1.7.2 ## explicit; go 1.23.5 github.com/leonelquinteros/gotext @@ -490,10 +487,11 @@ github.com/opencontainers/image-spec/specs-go/v1 ## explicit; go 1.18 # github.com/opencontainers/runtime-spec v1.1.0 ## explicit -# github.com/pjbgf/sha1cd v0.6.0 -## explicit; go 1.22 +# github.com/pjbgf/sha1cd v0.7.0 +## explicit; go 1.24.0 github.com/pjbgf/sha1cd github.com/pjbgf/sha1cd/internal +github.com/pjbgf/sha1cd/internal/cpu github.com/pjbgf/sha1cd/ubc # github.com/pkg/errors v0.9.1 ## explicit @@ -659,8 +657,8 @@ go.yaml.in/yaml/v2 # go.yaml.in/yaml/v3 v3.0.5 ## explicit; go 1.16 go.yaml.in/yaml/v3 -# golang.org/x/crypto v0.53.0 -## explicit; go 1.25.0 +# golang.org/x/crypto v0.56.0 +## explicit; go 1.26.0 golang.org/x/crypto/argon2 golang.org/x/crypto/blake2b golang.org/x/crypto/blowfish @@ -683,7 +681,7 @@ golang.org/x/exp/slices golang.org/x/exp/slog golang.org/x/exp/slog/internal golang.org/x/exp/slog/internal/buffer -# golang.org/x/net v0.56.0 +# golang.org/x/net v0.57.0 ## explicit; go 1.25.0 golang.org/x/net/context golang.org/x/net/http/httpguts @@ -707,7 +705,7 @@ golang.org/x/sys/windows/registry # golang.org/x/term v0.46.0 ## explicit; go 1.26.0 golang.org/x/term -# golang.org/x/text v0.39.0 +# golang.org/x/text v0.41.0 ## explicit; go 1.25.0 golang.org/x/text/cases golang.org/x/text/internal