Handle CORS requests (#6289)
parent
6fb58a8cdc
commit
34d06f4c6b
@ -0,0 +1,22 @@ |
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations |
||||
|
||||
import ( |
||||
"net/http" |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestCORSNotSet(t *testing.T) { |
||||
prepareTestEnv(t) |
||||
req := NewRequestf(t, "GET", "/api/v1/version") |
||||
session := loginUser(t, "user2") |
||||
resp := session.MakeRequest(t, req, http.StatusOK) |
||||
assert.Equal(t, resp.Code, http.StatusOK) |
||||
corsHeader := resp.Header().Get("Access-Control-Allow-Origin") |
||||
assert.Equal(t, corsHeader, "", "Access-Control-Allow-Origin: generated header should match") // header not set
|
||||
} |
@ -0,0 +1,41 @@ |
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package setting |
||||
|
||||
import ( |
||||
"time" |
||||
|
||||
"code.gitea.io/gitea/modules/log" |
||||
|
||||
"github.com/go-macaron/cors" |
||||
) |
||||
|
||||
var ( |
||||
// CORSConfig defines CORS settings
|
||||
CORSConfig cors.Options |
||||
// EnableCORS defines whether CORS settings is enabled or not
|
||||
EnableCORS bool |
||||
) |
||||
|
||||
func newCORSService() { |
||||
sec := Cfg.Section("cors") |
||||
// Check cors setting.
|
||||
EnableCORS = sec.Key("ENABLED").MustBool(false) |
||||
|
||||
maxAge := sec.Key("MAX_AGE").MustDuration(10 * time.Minute) |
||||
|
||||
CORSConfig = cors.Options{ |
||||
Scheme: sec.Key("SCHEME").String(), |
||||
AllowDomain: sec.Key("ALLOW_DOMAIN").String(), |
||||
AllowSubdomain: sec.Key("ALLOW_SUBDOMAIN").MustBool(), |
||||
Methods: sec.Key("METHODS").Strings(","), |
||||
MaxAgeSeconds: int(maxAge.Seconds()), |
||||
AllowCredentials: sec.Key("ALLOW_CREDENTIALS").MustBool(), |
||||
} |
||||
|
||||
if EnableCORS { |
||||
log.Info("CORS Service Enabled") |
||||
} |
||||
} |
@ -0,0 +1,8 @@ |
||||
module github.com/Unknwon/com |
||||
|
||||
require ( |
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect |
||||
github.com/jtolds/gls v4.2.1+incompatible // indirect |
||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 // indirect |
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c |
||||
) |
@ -0,0 +1,8 @@ |
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= |
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= |
||||
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= |
||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= |
||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= |
||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= |
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w= |
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= |
@ -0,0 +1,12 @@ |
||||
# Binaries for programs and plugins |
||||
*.exe |
||||
*.exe~ |
||||
*.dll |
||||
*.so |
||||
*.dylib |
||||
|
||||
# Test binary, build with `go test -c` |
||||
*.test |
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE |
||||
*.out |
@ -0,0 +1,201 @@ |
||||
Apache License |
||||
Version 2.0, January 2004 |
||||
http://www.apache.org/licenses/ |
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||
|
||||
1. Definitions. |
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, |
||||
and distribution as defined by Sections 1 through 9 of this document. |
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by |
||||
the copyright owner that is granting the License. |
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all |
||||
other entities that control, are controlled by, or are under common |
||||
control with that entity. For the purposes of this definition, |
||||
"control" means (i) the power, direct or indirect, to cause the |
||||
direction or management of such entity, whether by contract or |
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||
outstanding shares, or (iii) beneficial ownership of such entity. |
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity |
||||
exercising permissions granted by this License. |
||||
|
||||
"Source" form shall mean the preferred form for making modifications, |
||||
including but not limited to software source code, documentation |
||||
source, and configuration files. |
||||
|
||||
"Object" form shall mean any form resulting from mechanical |
||||
transformation or translation of a Source form, including but |
||||
not limited to compiled object code, generated documentation, |
||||
and conversions to other media types. |
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or |
||||
Object form, made available under the License, as indicated by a |
||||
copyright notice that is included in or attached to the work |
||||
(an example is provided in the Appendix below). |
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object |
||||
form, that is based on (or derived from) the Work and for which the |
||||
editorial revisions, annotations, elaborations, or other modifications |
||||
represent, as a whole, an original work of authorship. For the purposes |
||||
of this License, Derivative Works shall not include works that remain |
||||
separable from, or merely link (or bind by name) to the interfaces of, |
||||
the Work and Derivative Works thereof. |
||||
|
||||
"Contribution" shall mean any work of authorship, including |
||||
the original version of the Work and any modifications or additions |
||||
to that Work or Derivative Works thereof, that is intentionally |
||||
submitted to Licensor for inclusion in the Work by the copyright owner |
||||
or by an individual or Legal Entity authorized to submit on behalf of |
||||
the copyright owner. For the purposes of this definition, "submitted" |
||||
means any form of electronic, verbal, or written communication sent |
||||
to the Licensor or its representatives, including but not limited to |
||||
communication on electronic mailing lists, source code control systems, |
||||
and issue tracking systems that are managed by, or on behalf of, the |
||||
Licensor for the purpose of discussing and improving the Work, but |
||||
excluding communication that is conspicuously marked or otherwise |
||||
designated in writing by the copyright owner as "Not a Contribution." |
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||
on behalf of whom a Contribution has been received by Licensor and |
||||
subsequently incorporated within the Work. |
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
copyright license to reproduce, prepare Derivative Works of, |
||||
publicly display, publicly perform, sublicense, and distribute the |
||||
Work and such Derivative Works in Source or Object form. |
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
(except as stated in this section) patent license to make, have made, |
||||
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||
where such license applies only to those patent claims licensable |
||||
by such Contributor that are necessarily infringed by their |
||||
Contribution(s) alone or by combination of their Contribution(s) |
||||
with the Work to which such Contribution(s) was submitted. If You |
||||
institute patent litigation against any entity (including a |
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||
or a Contribution incorporated within the Work constitutes direct |
||||
or contributory patent infringement, then any patent licenses |
||||
granted to You under this License for that Work shall terminate |
||||
as of the date such litigation is filed. |
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the |
||||
Work or Derivative Works thereof in any medium, with or without |
||||
modifications, and in Source or Object form, provided that You |
||||
meet the following conditions: |
||||
|
||||
(a) You must give any other recipients of the Work or |
||||
Derivative Works a copy of this License; and |
||||
|
||||
(b) You must cause any modified files to carry prominent notices |
||||
stating that You changed the files; and |
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works |
||||
that You distribute, all copyright, patent, trademark, and |
||||
attribution notices from the Source form of the Work, |
||||
excluding those notices that do not pertain to any part of |
||||
the Derivative Works; and |
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its |
||||
distribution, then any Derivative Works that You distribute must |
||||
include a readable copy of the attribution notices contained |
||||
within such NOTICE file, excluding those notices that do not |
||||
pertain to any part of the Derivative Works, in at least one |
||||
of the following places: within a NOTICE text file distributed |
||||
as part of the Derivative Works; within the Source form or |
||||
documentation, if provided along with the Derivative Works; or, |
||||
within a display generated by the Derivative Works, if and |
||||
wherever such third-party notices normally appear. The contents |
||||
of the NOTICE file are for informational purposes only and |
||||
do not modify the License. You may add Your own attribution |
||||
notices within Derivative Works that You distribute, alongside |
||||
or as an addendum to the NOTICE text from the Work, provided |
||||
that such additional attribution notices cannot be construed |
||||
as modifying the License. |
||||
|
||||
You may add Your own copyright statement to Your modifications and |
||||
may provide additional or different license terms and conditions |
||||
for use, reproduction, or distribution of Your modifications, or |
||||
for any such Derivative Works as a whole, provided Your use, |
||||
reproduction, and distribution of the Work otherwise complies with |
||||
the conditions stated in this License. |
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||
any Contribution intentionally submitted for inclusion in the Work |
||||
by You to the Licensor shall be under the terms and conditions of |
||||
this License, without any additional terms or conditions. |
||||
Notwithstanding the above, nothing herein shall supersede or modify |
||||
the terms of any separate license agreement you may have executed |
||||
with Licensor regarding such Contributions. |
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade |
||||
names, trademarks, service marks, or product names of the Licensor, |
||||
except as required for reasonable and customary use in describing the |
||||
origin of the Work and reproducing the content of the NOTICE file. |
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or |
||||
agreed to in writing, Licensor provides the Work (and each |
||||
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||
implied, including, without limitation, any warranties or conditions |
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||
appropriateness of using or redistributing the Work and assume any |
||||
risks associated with Your exercise of permissions under this License. |
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, |
||||
whether in tort (including negligence), contract, or otherwise, |
||||
unless required by applicable law (such as deliberate and grossly |
||||
negligent acts) or agreed to in writing, shall any Contributor be |
||||
liable to You for damages, including any direct, indirect, special, |
||||
incidental, or consequential damages of any character arising as a |
||||
result of this License or out of the use or inability to use the |
||||
Work (including but not limited to damages for loss of goodwill, |
||||
work stoppage, computer failure or malfunction, or any and all |
||||
other commercial damages or losses), even if such Contributor |
||||
has been advised of the possibility of such damages. |
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing |
||||
the Work or Derivative Works thereof, You may choose to offer, |
||||
and charge a fee for, acceptance of support, warranty, indemnity, |
||||
or other liability obligations and/or rights consistent with this |
||||
License. However, in accepting such obligations, You may act only |
||||
on Your own behalf and on Your sole responsibility, not on behalf |
||||
of any other Contributor, and only if You agree to indemnify, |
||||
defend, and hold each Contributor harmless for any liability |
||||
incurred by, or claims asserted against, such Contributor by reason |
||||
of your accepting any such warranty or additional liability. |
||||
|
||||
END OF TERMS AND CONDITIONS |
||||
|
||||
APPENDIX: How to apply the Apache License to your work. |
||||
|
||||
To apply the Apache License to your work, attach the following |
||||
boilerplate notice, with the fields enclosed by brackets "[]" |
||||
replaced with your own identifying information. (Don't include |
||||
the brackets!) The text should be enclosed in the appropriate |
||||
comment syntax for the file format. We also recommend that a |
||||
file or class name and description of purpose be included on the |
||||
same "printed page" as the copyright notice for easier |
||||
identification within third-party archives. |
||||
|
||||
Copyright [yyyy] [name of copyright owner] |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
@ -0,0 +1,2 @@ |
||||
# cors |
||||
Package cors is a middleware that handles CORS requests & headers for Macaron. |
@ -0,0 +1,139 @@ |
||||
package cors |
||||
|
||||
import ( |
||||
"fmt" |
||||
"log" |
||||
"net/http" |
||||
"net/url" |
||||
"strconv" |
||||
"strings" |
||||
|
||||
macaron "gopkg.in/macaron.v1" |
||||
) |
||||
|
||||
const _VERSION = "0.1.0" |
||||
|
||||
func Version() string { |
||||
return _VERSION |
||||
} |
||||
|
||||
// Options represents a struct for specifying configuration options for the CORS middleware.
|
||||
type Options struct { |
||||
Section string |
||||
Scheme string |
||||
AllowDomain string |
||||
AllowSubdomain bool |
||||
Methods []string |
||||
MaxAgeSeconds int |
||||
AllowCredentials bool |
||||
} |
||||
|
||||
func prepareOptions(options []Options) Options { |
||||
var opt Options |
||||
if len(options) > 0 { |
||||
opt = options[0] |
||||
} |
||||
|
||||
if len(opt.Section) == 0 { |
||||
opt.Section = "cors" |
||||
} |
||||
sec := macaron.Config().Section(opt.Section) |
||||
|
||||
if len(opt.Scheme) == 0 { |
||||
opt.Scheme = sec.Key("SCHEME").MustString("http") |
||||
} |
||||
if len(opt.AllowDomain) == 0 { |
||||
opt.AllowDomain = sec.Key("ALLOW_DOMAIN").MustString("*") |
||||
} |
||||
if !opt.AllowSubdomain { |
||||
opt.AllowSubdomain = sec.Key("ALLOW_SUBDOMAIN").MustBool(false) |
||||
} |
||||
if len(opt.Methods) == 0 { |
||||
opt.Methods = sec.Key("METHODS").Strings(",") |
||||
if len(opt.Methods) == 0 { |
||||
opt.Methods = []string{ |
||||
http.MethodGet, |
||||
http.MethodHead, |
||||
http.MethodPost, |
||||
http.MethodPut, |
||||
http.MethodPatch, |
||||
http.MethodDelete, |
||||
http.MethodOptions, |
||||
} |
||||
} |
||||
} |
||||
if opt.MaxAgeSeconds <= 0 { |
||||
// cache options response for 600 secs
|
||||
// ref: https://stackoverflow.com/questions/54300997/is-it-possible-to-cache-http-options-response?noredirect=1#comment95790277_54300997
|
||||
// ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
|
||||
opt.MaxAgeSeconds = sec.Key("MAX_AGE_SECONDS").MustInt(600) |
||||
} |
||||
if !opt.AllowCredentials { |
||||
opt.AllowCredentials = sec.Key("ALLOW_CREDENTIALS").MustBool(true) |
||||
} |
||||
|
||||
return opt |
||||
} |
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
|
||||
// https://fetch.spec.whatwg.org/#cors-protocol-and-credentials
|
||||
// For requests without credentials, the server may specify "*" as a wildcard, thereby allowing any origin to access the resource.
|
||||
func CORS(options ...Options) macaron.Handler { |
||||
opt := prepareOptions(options) |
||||
return func(ctx *macaron.Context, log *log.Logger) { |
||||
reqOptions := ctx.Req.Method == http.MethodOptions |
||||
|
||||
headers := map[string]string{ |
||||
"access-control-allow-methods": strings.Join(opt.Methods, ","), |
||||
"access-control-allow-headers": ctx.Req.Header.Get("access-control-request-headers"), |
||||
"access-control-max-age": strconv.Itoa(opt.MaxAgeSeconds), |
||||
} |
||||
if opt.AllowDomain == "*" { |
||||
headers["access-control-allow-origin"] = "*" |
||||
} else if opt.AllowDomain != "" { |
||||
origin := ctx.Req.Header.Get("Origin") |
||||
if reqOptions && origin == "" { |
||||
respErrorf(ctx, log, http.StatusBadRequest, "missing origin header in CORS request") |
||||
return |
||||
} |
||||
|
||||
u, err := url.Parse(origin) |
||||
if err != nil { |
||||
respErrorf(ctx, log, http.StatusBadRequest, "Failed to parse CORS origin header. Reason: %v", err) |
||||
return |
||||
} |
||||
|
||||
ok := u.Hostname() == opt.AllowDomain || |
||||
(opt.AllowSubdomain && strings.HasSuffix(u.Hostname(), "."+opt.AllowDomain)) |
||||
if ok { |
||||
u.Scheme = opt.Scheme |
||||
headers["access-control-allow-origin"] = u.String() |
||||
headers["access-control-allow-credentials"] = strconv.FormatBool(opt.AllowCredentials) |
||||
headers["vary"] = "Origin" |
||||
} |
||||
if reqOptions && !ok { |
||||
respErrorf(ctx, log, http.StatusBadRequest, "CORS request from prohibited domain %v", origin) |
||||
return |
||||
} |
||||
} |
||||
ctx.Resp.Before(func(w macaron.ResponseWriter) { |
||||
for k, v := range headers { |
||||
w.Header().Set(k, v) |
||||
} |
||||
}) |
||||
if reqOptions { |
||||
ctx.Status(200) // return response
|
||||
} |
||||
} |
||||
} |
||||
|
||||
func respErrorf(ctx *macaron.Context, log *log.Logger, statusCode int, format string, a ...interface{}) { |
||||
msg := fmt.Sprintf(format, a...) |
||||
log.Println(msg) |
||||
ctx.WriteHeader(statusCode) |
||||
_, err := ctx.Write([]byte(msg)) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
return |
||||
} |
@ -0,0 +1,11 @@ |
||||
module github.com/go-macaron/cors |
||||
|
||||
go 1.12 |
||||
|
||||
require ( |
||||
github.com/Unknwon/com v0.0.0-20190321035513-0fed4efef755 // indirect |
||||
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 // indirect |
||||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 // indirect |
||||
gopkg.in/ini.v1 v1.42.0 // indirect |
||||
gopkg.in/macaron.v1 v1.3.2 |
||||
) |
@ -0,0 +1,19 @@ |
||||
github.com/Unknwon/com v0.0.0-20190321035513-0fed4efef755 h1:1B7wb36fHLSwZfHg6ngZhhtIEHQjiC5H4p7qQGBEffg= |
||||
github.com/Unknwon/com v0.0.0-20190321035513-0fed4efef755/go.mod h1:voKvFVpXBJxdIPeqjoJuLK+UVcRlo/JLjeToGxPYu68= |
||||
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI= |
||||
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191/go.mod h1:VFI2o2q9kYsC4o7VP1HrEVosiZZTd+MVT3YZx4gqvJw= |
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= |
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= |
||||
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= |
||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= |
||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= |
||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= |
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w= |
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= |
||||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 h1:O5YqonU5IWby+w98jVUG9h7zlCWCcH4RHyPVReBmhzk= |
||||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= |
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= |
||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= |
||||
gopkg.in/macaron.v1 v1.3.2 h1:AvWIaPmwBUA87/OWzePkoxeaw6YJWDfBt1pDFPBnLf8= |
||||
gopkg.in/macaron.v1 v1.3.2/go.mod h1:PrsiawTWAGZs6wFbT5hlr7SQ2Ns9h7cUVtcUu4lQOVo= |
@ -0,0 +1,308 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved. |
||||
// Use of this source code is governed by a BSD-style |
||||
// license that can be found in the LICENSE file. |
||||
|
||||
// +build go1.11 |
||||
// +build !gccgo,!appengine |
||||
|
||||
#include "textflag.h" |
||||
|
||||
#define NUM_ROUNDS 10 |
||||
|
||||
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) |
||||
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 |
||||
MOVD dst+0(FP), R1 |
||||
MOVD src+24(FP), R2 |
||||
MOVD src_len+32(FP), R3 |
||||
MOVD key+48(FP), R4 |
||||
MOVD nonce+56(FP), R6 |
||||
MOVD counter+64(FP), R7 |
||||
|
||||
MOVD $·constants(SB), R10 |
||||
MOVD $·incRotMatrix(SB), R11 |
||||
|
||||
MOVW (R7), R20 |
||||
|
||||
AND $~255, R3, R13 |
||||
ADD R2, R13, R12 // R12 for block end |
||||
AND $255, R3, R13 |
||||
loop: |
||||
MOVD $NUM_ROUNDS, R21 |
||||
VLD1 (R11), [V30.S4, V31.S4] |
||||
|
||||
// load contants |
||||
// VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4] |
||||
WORD $0x4D60E940 |
||||
|
||||
// load keys |
||||
// VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4] |
||||
WORD $0x4DFFE884 |
||||
// VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4] |
||||
WORD $0x4DFFE888 |
||||
SUB $32, R4 |
||||
|
||||
// load counter + nonce |
||||
// VLD1R (R7), [V12.S4] |
||||
WORD $0x4D40C8EC |
||||
|
||||
// VLD3R (R6), [V13.S4, V14.S4, V15.S4] |
||||
WORD $0x4D40E8CD |
||||
|
||||
// update counter |
||||
VADD V30.S4, V12.S4, V12.S4 |
||||
|
||||
chacha: |
||||
// V0..V3 += V4..V7 |
||||
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 16) |
||||
VADD V0.S4, V4.S4, V0.S4 |
||||
VADD V1.S4, V5.S4, V1.S4 |
||||
VADD V2.S4, V6.S4, V2.S4 |
||||
VADD V3.S4, V7.S4, V3.S4 |
||||
VEOR V12.B16, V0.B16, V12.B16 |
||||
VEOR V13.B16, V1.B16, V13.B16 |
||||
VEOR V14.B16, V2.B16, V14.B16 |
||||
VEOR V15.B16, V3.B16, V15.B16 |
||||
VREV32 V12.H8, V12.H8 |
||||
VREV32 V13.H8, V13.H8 |
||||
VREV32 V14.H8, V14.H8 |
||||
VREV32 V15.H8, V15.H8 |
||||
// V8..V11 += V12..V15 |
||||
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 12) |
||||
VADD V8.S4, V12.S4, V8.S4 |
||||
VADD V9.S4, V13.S4, V9.S4 |
||||
VADD V10.S4, V14.S4, V10.S4 |
||||
VADD V11.S4, V15.S4, V11.S4 |
||||
VEOR V8.B16, V4.B16, V16.B16 |
||||
VEOR V9.B16, V5.B16, V17.B16 |
||||
VEOR V10.B16, V6.B16, V18.B16 |
||||
VEOR V11.B16, V7.B16, V19.B16 |
||||
VSHL $12, V16.S4, V4.S4 |
||||
VSHL $12, V17.S4, V5.S4 |
||||
VSHL $12, V18.S4, V6.S4 |
||||
VSHL $12, V19.S4, V7.S4 |
||||
VSRI $20, V16.S4, V4.S4 |
||||
VSRI $20, V17.S4, V5.S4 |
||||
VSRI $20, V18.S4, V6.S4 |
||||
VSRI $20, V19.S4, V7.S4 |
||||
|
||||
// V0..V3 += V4..V7 |
||||
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 8) |
||||
VADD V0.S4, V4.S4, V0.S4 |
||||
VADD V1.S4, V5.S4, V1.S4 |
||||
VADD V2.S4, V6.S4, V2.S4 |
||||
VADD V3.S4, V7.S4, V3.S4 |
||||
VEOR V12.B16, V0.B16, V12.B16 |
||||
VEOR V13.B16, V1.B16, V13.B16 |
||||
VEOR V14.B16, V2.B16, V14.B16 |
||||
VEOR V15.B16, V3.B16, V15.B16 |
||||
VTBL V31.B16, [V12.B16], V12.B16 |
||||
VTBL V31.B16, [V13.B16], V13.B16 |
||||
VTBL V31.B16, [V14.B16], V14.B16 |
||||
VTBL V31.B16, [V15.B16], V15.B16 |
||||
|
||||
// V8..V11 += V12..V15 |
||||
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 7) |
||||
VADD V12.S4, V8.S4, V8.S4 |
||||
VADD V13.S4, V9.S4, V9.S4 |
||||
VADD V14.S4, V10.S4, V10.S4 |
||||
VADD V15.S4, V11.S4, V11.S4 |
||||
VEOR V8.B16, V4.B16, V16.B16 |
||||
VEOR V9.B16, V5.B16, V17.B16 |
||||
VEOR V10.B16, V6.B16, V18.B16 |
||||
VEOR V11.B16, V7.B16, V19.B16 |
||||
VSHL $7, V16.S4, V4.S4 |
||||
VSHL $7, V17.S4, V5.S4 |
||||
VSHL $7, V18.S4, V6.S4 |
||||
VSHL $7, V19.S4, V7.S4 |
||||
VSRI $25, V16.S4, V4.S4 |
||||
VSRI $25, V17.S4, V5.S4 |
||||
VSRI $25, V18.S4, V6.S4 |
||||
VSRI $25, V19.S4, V7.S4 |
||||
|
||||
// V0..V3 += V5..V7, V4 |
||||
// V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16) |
||||
VADD V0.S4, V5.S4, V0.S4 |
||||
VADD V1.S4, V6.S4, V1.S4 |
||||
VADD V2.S4, V7.S4, V2.S4 |
||||
VADD V3.S4, V4.S4, V3.S4 |
||||
VEOR V15.B16, V0.B16, V15.B16 |
||||
VEOR V12.B16, V1.B16, V12.B16 |
||||
VEOR V13.B16, V2.B16, V13.B16 |
||||
VEOR V14.B16, V3.B16, V14.B16 |
||||
VREV32 V12.H8, V12.H8 |
||||
VREV32 V13.H8, V13.H8 |
||||
VREV32 V14.H8, V14.H8 |
||||
VREV32 V15.H8, V15.H8 |
||||
|
||||
// V10 += V15; V5 <<<= ((V10 XOR V5), 12)
|
||||
// ... |
||||
VADD V15.S4, V10.S4, V10.S4 |
||||
VADD V12.S4, V11.S4, V11.S4 |
||||
VADD V13.S4, V8.S4, V8.S4 |
||||
VADD V14.S4, V9.S4, V9.S4 |
||||
VEOR V10.B16, V5.B16, V16.B16 |
||||
VEOR V11.B16, V6.B16, V17.B16 |
||||
VEOR V8.B16, V7.B16, V18.B16 |
||||
VEOR V9.B16, V4.B16, V19.B16 |
||||
VSHL $12, V16.S4, V5.S4 |
||||
VSHL $12, V17.S4, V6.S4 |
||||
VSHL $12, V18.S4, V7.S4 |
||||
VSHL $12, V19.S4, V4.S4 |
||||
VSRI $20, V16.S4, V5.S4 |
||||
VSRI $20, V17.S4, V6.S4 |
||||
VSRI $20, V18.S4, V7.S4 |
||||
VSRI $20, V19.S4, V4.S4 |
||||
|
||||
// V0 += V5; V15 <<<= ((V0 XOR V15), 8)
|
||||
// ... |
||||
VADD V5.S4, V0.S4, V0.S4 |
||||
VADD V6.S4, V1.S4, V1.S4 |
||||
VADD V7.S4, V2.S4, V2.S4 |
||||
VADD V4.S4, V3.S4, V3.S4 |
||||
VEOR V0.B16, V15.B16, V15.B16 |
||||
VEOR V1.B16, V12.B16, V12.B16 |
||||
VEOR V2.B16, V13.B16, V13.B16 |
||||
VEOR V3.B16, V14.B16, V14.B16 |
||||
VTBL V31.B16, [V12.B16], V12.B16 |
||||
VTBL V31.B16, [V13.B16], V13.B16 |
||||
VTBL V31.B16, [V14.B16], V14.B16 |
||||
VTBL V31.B16, [V15.B16], V15.B16 |
||||
|
||||
// V10 += V15; V5 <<<= ((V10 XOR V5), 7)
|
||||
// ... |
||||
VADD V15.S4, V10.S4, V10.S4 |
||||
VADD V12.S4, V11.S4, V11.S4 |
||||
VADD V13.S4, V8.S4, V8.S4 |
||||
VADD V14.S4, V9.S4, V9.S4 |
||||
VEOR V10.B16, V5.B16, V16.B16 |
||||
VEOR V11.B16, V6.B16, V17.B16 |
||||
VEOR V8.B16, V7.B16, V18.B16 |
||||
VEOR V9.B16, V4.B16, V19.B16 |
||||
VSHL $7, V16.S4, V5.S4 |
||||
VSHL $7, V17.S4, V6.S4 |
||||
VSHL $7, V18.S4, V7.S4 |
||||
VSHL $7, V19.S4, V4.S4 |
||||
VSRI $25, V16.S4, V5.S4 |
||||
VSRI $25, V17.S4, V6.S4 |
||||
VSRI $25, V18.S4, V7.S4 |
||||
VSRI $25, V19.S4, V4.S4 |
||||
|
||||
SUB $1, R21 |
||||
CBNZ R21, chacha |
||||
|
||||
// VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4] |
||||
WORD $0x4D60E950 |
||||
|
||||
// VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4] |
||||
WORD $0x4DFFE894 |
||||
VADD V30.S4, V12.S4, V12.S4 |
||||
VADD V16.S4, V0.S4, V0.S4 |
||||
VADD V17.S4, V1.S4, V1.S4 |
||||
VADD V18.S4, V2.S4, V2.S4 |
||||
VADD V19.S4, V3.S4, V3.S4 |
||||
// VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4] |
||||
WORD $0x4DFFE898 |
||||
// restore R4 |
||||
SUB $32, R4 |
||||
|
||||
// load counter + nonce |
||||
// VLD1R (R7), [V28.S4] |
||||
WORD $0x4D40C8FC |
||||
// VLD3R (R6), [V29.S4, V30.S4, V31.S4] |
||||
WORD $0x4D40E8DD |
||||
|
||||
VADD V20.S4, V4.S4, V4.S4 |
||||
VADD V21.S4, V5.S4, V5.S4 |
||||
VADD V22.S4, V6.S4, V6.S4 |
||||
VADD V23.S4, V7.S4, V7.S4 |
||||
VADD V24.S4, V8.S4, V8.S4 |
||||
VADD V25.S4, V9.S4, V9.S4 |
||||
VADD V26.S4, V10.S4, V10.S4 |
||||
VADD V27.S4, V11.S4, V11.S4 |
||||
VADD V28.S4, V12.S4, V12.S4 |
||||
VADD V29.S4, V13.S4, V13.S4 |
||||
VADD V30.S4, V14.S4, V14.S4 |
||||
VADD V31.S4, V15.S4, V15.S4 |
||||
|
||||
VZIP1 V1.S4, V0.S4, V16.S4 |
||||
VZIP2 V1.S4, V0.S4, V17.S4 |
||||
VZIP1 V3.S4, V2.S4, V18.S4 |
||||
VZIP2 V3.S4, V2.S4, V19.S4 |
||||
VZIP1 V5.S4, V4.S4, V20.S4 |
||||
VZIP2 V5.S4, V4.S4, V21.S4 |
||||
VZIP1 V7.S4, V6.S4, V22.S4 |
||||
VZIP2 V7.S4, V6.S4, V23.S4 |
||||
VZIP1 V9.S4, V8.S4, V24.S4 |
||||
VZIP2 V9.S4, V8.S4, V25.S4 |
||||
VZIP1 V11.S4, V10.S4, V26.S4 |
||||
VZIP2 V11.S4, V10.S4, V27.S4 |
||||
VZIP1 V13.S4, V12.S4, V28.S4 |
||||
VZIP2 V13.S4, V12.S4, V29.S4 |
||||
VZIP1 V15.S4, V14.S4, V30.S4 |
||||
VZIP2 V15.S4, V14.S4, V31.S4 |
||||
VZIP1 V18.D2, V16.D2, V0.D2 |
||||
VZIP2 V18.D2, V16.D2, V4.D2 |
||||
VZIP1 V19.D2, V17.D2, V8.D2 |
||||
VZIP2 V19.D2, V17.D2, V12.D2 |
||||
VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16] |
||||
|
||||
VZIP1 V22.D2, V20.D2, V1.D2 |
||||
VZIP2 V22.D2, V20.D2, V5.D2 |
||||
VZIP1 V23.D2, V21.D2, V9.D2 |
||||
VZIP2 V23.D2, V21.D2, V13.D2 |
||||
VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16] |
||||
VZIP1 V26.D2, V24.D2, V2.D2 |
||||
VZIP2 V26.D2, V24.D2, V6.D2 |
||||
VZIP1 V27.D2, V25.D2, V10.D2 |
||||
VZIP2 V27.D2, V25.D2, V14.D2 |
||||
VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16] |
||||
VZIP1 V30.D2, V28.D2, V3.D2 |
||||
VZIP2 V30.D2, V28.D2, V7.D2 |
||||
VZIP1 V31.D2, V29.D2, V11.D2 |
||||
VZIP2 V31.D2, V29.D2, V15.D2 |
||||
VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16] |
||||
VEOR V0.B16, V16.B16, V16.B16 |
||||
VEOR V1.B16, V17.B16, V17.B16 |
||||
VEOR V2.B16, V18.B16, V18.B16 |
||||
VEOR V3.B16, V19.B16, V19.B16 |
||||
VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1) |
||||
VEOR V4.B16, V20.B16, V20.B16 |
||||
VEOR V5.B16, V21.B16, V21.B16 |
||||
VEOR V6.B16, V22.B16, V22.B16 |
||||
VEOR V7.B16, V23.B16, V23.B16 |
||||
VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1) |
||||
VEOR V8.B16, V24.B16, V24.B16 |
||||
VEOR V9.B16, V25.B16, V25.B16 |
||||
VEOR V10.B16, V26.B16, V26.B16 |
||||
VEOR V11.B16, V27.B16, V27.B16 |
||||
VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1) |
||||
VEOR V12.B16, V28.B16, V28.B16 |
||||
VEOR V13.B16, V29.B16, V29.B16 |
||||
VEOR V14.B16, V30.B16, V30.B16 |
||||
VEOR V15.B16, V31.B16, V31.B16 |
||||
VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1) |
||||
|
||||
ADD $4, R20 |
||||
MOVW R20, (R7) // update counter |
||||
|
||||
CMP R2, R12 |
||||
BGT loop |
||||
|
||||
RET |
||||
|
||||
|
||||
DATA ·constants+0x00(SB)/4, $0x61707865 |
||||
DATA ·constants+0x04(SB)/4, $0x3320646e |
||||
DATA ·constants+0x08(SB)/4, $0x79622d32 |
||||
DATA ·constants+0x0c(SB)/4, $0x6b206574 |
||||
GLOBL ·constants(SB), NOPTR|RODATA, $32 |
||||
|
||||
DATA ·incRotMatrix+0x00(SB)/4, $0x00000000 |
||||
DATA ·incRotMatrix+0x04(SB)/4, $0x00000001 |
||||
DATA ·incRotMatrix+0x08(SB)/4, $0x00000002 |
||||
DATA ·incRotMatrix+0x0c(SB)/4, $0x00000003 |
||||
DATA ·incRotMatrix+0x10(SB)/4, $0x02010003 |
||||
DATA ·incRotMatrix+0x14(SB)/4, $0x06050407 |
||||
DATA ·incRotMatrix+0x18(SB)/4, $0x0A09080B |
||||
DATA ·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F |
||||
GLOBL ·incRotMatrix(SB), NOPTR|RODATA, $32 |
@ -0,0 +1,31 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.11
|
||||
// +build !gccgo
|
||||
|
||||
package chacha20 |
||||
|
||||
const ( |
||||
haveAsm = true |
||||
bufSize = 256 |
||||
) |
||||
|
||||
//go:noescape
|
||||
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) |
||||
|
||||
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) { |
||||
|
||||
if len(src) >= bufSize { |
||||
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) |
||||
} |
||||
|
||||
if len(src)%bufSize != 0 { |
||||
i := len(src) - len(src)%bufSize |
||||
c.buf = [bufSize]byte{} |
||||
copy(c.buf[:], src[i:]) |
||||
xorKeyStreamVX(c.buf[:], c.buf[:], &c.key, &c.nonce, &c.counter) |
||||
c.len = bufSize - copy(dst[i:], c.buf[:len(src)%bufSize]) |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !amd64 gccgo appengine
|
||||
|
||||
package poly1305 |
||||
|
||||
type mac struct{ macGeneric } |
||||
|
||||
func newMAC(key *[32]byte) mac { return mac{newMACGeneric(key)} } |
@ -0,0 +1,30 @@ |
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cpu |
||||
|
||||
import ( |
||||
"encoding/binary" |
||||
"runtime" |
||||
) |
||||
|
||||
// hostByteOrder returns binary.LittleEndian on little-endian machines and
|
||||
// binary.BigEndian on big-endian machines.
|
||||
func hostByteOrder() binary.ByteOrder { |
||||
switch runtime.GOARCH { |
||||
case "386", "amd64", "amd64p32", |
||||
"arm", "arm64", |
||||
"mipsle", "mips64le", "mips64p32le", |
||||
"ppc64le", |
||||
"riscv", "riscv64": |
||||
return binary.LittleEndian |
||||
case "armbe", "arm64be", |
||||
"mips", "mips64", "mips64p32", |
||||
"ppc", "ppc64", |
||||
"s390", "s390x", |
||||
"sparc", "sparc64": |
||||
return binary.BigEndian |
||||
} |
||||
panic("unknown architecture") |
||||
} |
@ -0,0 +1,126 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package cpu implements processor feature detection for
|
||||
// various CPU architectures.
|
||||
package cpu |
||||
|
||||
// Initialized reports whether the CPU features were initialized.
|
||||
//
|
||||
// For some GOOS/GOARCH combinations initialization of the CPU features depends
|
||||
// on reading an operating specific file, e.g. /proc/self/auxv on linux/arm
|
||||
// Initialized will report false if reading the file fails.
|
||||
var Initialized bool |
||||
|
||||
// CacheLinePad is used to pad structs to avoid false sharing.
|
||||
type CacheLinePad struct{ _ [cacheLineSize]byte } |
||||
|
||||
// X86 contains the supported CPU features of the
|
||||
// current X86/AMD64 platform. If the current platform
|
||||
// is not X86/AMD64 then all feature flags are false.
|
||||
//
|
||||
// X86 is padded to avoid false sharing. Further the HasAVX
|
||||
// and HasAVX2 are only set if the OS supports XMM and YMM
|
||||
// registers in addition to the CPUID feature bit being set.
|
||||
var X86 struct { |
||||
_ CacheLinePad |
||||
HasAES bool // AES hardware implementation (AES NI)
|
||||
HasADX bool // Multi-precision add-carry instruction extensions
|
||||
HasAVX bool // Advanced vector extension
|
||||
HasAVX2 bool // Advanced vector extension 2
|
||||
HasBMI1 bool // Bit manipulation instruction set 1
|
||||
HasBMI2 bool // Bit manipulation instruction set 2
|
||||
HasERMS bool // Enhanced REP for MOVSB and STOSB
|
||||
HasFMA bool // Fused-multiply-add instructions
|
||||
HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers.
|
||||
HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM
|
||||
HasPOPCNT bool // Hamming weight instruction POPCNT.
|
||||
HasRDRAND bool // RDRAND instruction (on-chip random number generator)
|
||||
HasRDSEED bool // RDSEED instruction (on-chip random number generator)
|
||||
HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64)
|
||||
HasSSE3 bool // Streaming SIMD extension 3
|
||||
HasSSSE3 bool // Supplemental streaming SIMD extension 3
|
||||
HasSSE41 bool // Streaming SIMD extension 4 and 4.1
|
||||
HasSSE42 bool // Streaming SIMD extension 4 and 4.2
|
||||
_ CacheLinePad |
||||
} |
||||
|
||||
// ARM64 contains the supported CPU features of the
|
||||
// current ARMv8(aarch64) platform. If the current platform
|
||||
// is not arm64 then all feature flags are false.
|
||||
var ARM64 struct { |
||||
_ CacheLinePad |
||||
HasFP bool // Floating-point instruction set (always available)
|
||||
HasASIMD bool // Advanced SIMD (always available)
|
||||
HasEVTSTRM bool // Event stream support
|
||||
HasAES bool // AES hardware implementation
|
||||
HasPMULL bool // Polynomial multiplication instruction set
|
||||
HasSHA1 bool // SHA1 hardware implementation
|
||||
HasSHA2 bool // SHA2 hardware implementation
|
||||
HasCRC32 bool // CRC32 hardware implementation
|
||||
HasATOMICS bool // Atomic memory operation instruction set
|
||||
HasFPHP bool // Half precision floating-point instruction set
|
||||
HasASIMDHP bool // Advanced SIMD half precision instruction set
|
||||
HasCPUID bool // CPUID identification scheme registers
|
||||
HasASIMDRDM bool // Rounding double multiply add/subtract instruction set
|
||||
HasJSCVT bool // Javascript conversion from floating-point to integer
|
||||
HasFCMA bool // Floating-point multiplication and addition of complex numbers
|
||||
HasLRCPC bool // Release Consistent processor consistent support
|
||||
HasDCPOP bool // Persistent memory support
|
||||
HasSHA3 bool // SHA3 hardware implementation
|
||||
HasSM3 bool // SM3 hardware implementation
|
||||
HasSM4 bool // SM4 hardware implementation
|
||||
HasASIMDDP bool // Advanced SIMD double precision instruction set
|
||||
HasSHA512 bool // SHA512 hardware implementation
|
||||
HasSVE bool // Scalable Vector Extensions
|
||||
HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32
|
||||
_ CacheLinePad |
||||
} |
||||
|
||||
// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms.
|
||||
// If the current platform is not ppc64/ppc64le then all feature flags are false.
|
||||
//
|
||||
// For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00,
|
||||
// since there are no optional categories. There are some exceptions that also
|
||||
// require kernel support to work (DARN, SCV), so there are feature bits for
|
||||
// those as well. The minimum processor requirement is POWER8 (ISA 2.07).
|
||||
// The struct is padded to avoid false sharing.
|
||||
var PPC64 struct { |
||||
_ CacheLinePad |
||||
HasDARN bool // Hardware random number generator (requires kernel enablement)
|
||||
HasSCV bool // Syscall vectored (requires kernel enablement)
|
||||
IsPOWER8 bool // ISA v2.07 (POWER8)
|
||||
IsPOWER9 bool // ISA v3.00 (POWER9)
|
||||
_ CacheLinePad |
||||
} |
||||
|
||||
// S390X contains the supported CPU features of the current IBM Z
|
||||
// (s390x) platform. If the current platform is not IBM Z then all
|
||||
// feature flags are false.
|
||||
//
|
||||
// S390X is padded to avoid false sharing. Further HasVX is only set
|
||||
// if the OS supports vector registers in addition to the STFLE
|
||||
// feature bit being set.
|
||||
var S390X struct { |
||||
_ CacheLinePad |
||||
HasZARCH bool // z/Architecture mode is active [mandatory]
|
||||
HasSTFLE bool // store facility list extended
|
||||
HasLDISP bool // long (20-bit) displacements
|
||||
HasEIMM bool // 32-bit immediates
|
||||
HasDFP bool // decimal floating point
|
||||
HasETF3EH bool // ETF-3 enhanced
|
||||
HasMSA bool // message security assist (CPACF)
|
||||
HasAES bool // KM-AES{128,192,256} functions
|
||||
HasAESCBC bool // KMC-AES{128,192,256} functions
|
||||
HasAESCTR bool // KMCTR-AES{128,192,256} functions
|
||||
HasAESGCM bool // KMA-GCM-AES{128,192,256} functions
|
||||
HasGHASH bool // KIMD-GHASH function
|
||||
HasSHA1 bool // K{I,L}MD-SHA-1 functions
|
||||
HasSHA256 bool // K{I,L}MD-SHA-256 functions
|
||||
HasSHA512 bool // K{I,L}MD-SHA-512 functions
|
||||
HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions
|
||||
HasVX bool // vector facility
|
||||
HasVXE bool // vector-enhancements facility 1
|
||||
_ CacheLinePad |
||||
} |
@ -0,0 +1,30 @@ |
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix,ppc64
|
||||
|
||||
package cpu |
||||
|
||||
import "golang.org/x/sys/unix" |
||||
|
||||
const cacheLineSize = 128 |
||||
|
||||
const ( |
||||
// getsystemcfg constants
|
||||
_SC_IMPL = 2 |
||||
_IMPL_POWER8 = 0x10000 |
||||
_IMPL_POWER9 = 0x20000 |
||||
) |
||||
|
||||
func init() { |
||||
impl := unix.Getsystemcfg(_SC_IMPL) |
||||
if impl&_IMPL_POWER8 != 0 { |
||||
PPC64.IsPOWER8 = true |
||||
} |
||||
if impl&_IMPL_POWER9 != 0 { |
||||
PPC64.IsPOWER9 = true |
||||
} |
||||
|
||||
Initialized = true |
||||
} |
@ -0,0 +1,9 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cpu |
||||
|
||||
const cacheLineSize = 32 |
||||
|
||||
func doinit() {} |
@ -0,0 +1,21 @@ |
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
package cpu |
||||
|
||||
// haveAsmFunctions reports whether the other functions in this file can
|
||||
// be safely called.
|
||||
func haveAsmFunctions() bool { return true } |
||||
|
||||
// The following feature detection functions are defined in cpu_s390x.s.
|
||||
// They are likely to be expensive to call so the results should be cached.
|
||||
func stfle() facilityList |
||||
func kmQuery() queryResult |
||||
func kmcQuery() queryResult |
||||
func kmctrQuery() queryResult |
||||
func kmaQuery() queryResult |
||||
func kimdQuery() queryResult |
||||
func klmdQuery() queryResult |
@ -0,0 +1,16 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build 386 amd64 amd64p32
|
||||
// +build !gccgo
|
||||
|
||||
package cpu |
||||
|
||||
// cpuid is implemented in cpu_x86.s for gc compiler
|
||||
// and in cpu_gccgo.c for gccgo.
|
||||
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) |
||||
|
||||
// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler
|
||||
// and in cpu_gccgo.c for gccgo.
|
||||
func xgetbv() (eax, edx uint32) |
@ -0,0 +1,43 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build 386 amd64 amd64p32
|
||||
// +build gccgo
|
||||
|
||||
#include <cpuid.h> |
||||
#include <stdint.h> |
||||
|
||||
// Need to wrap __get_cpuid_count because it's declared as static.
|
||||
int |
||||
gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, |
||||
uint32_t *eax, uint32_t *ebx, |
||||
uint32_t *ecx, uint32_t *edx) |
||||
{ |
||||
return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); |
||||
} |
||||
|
||||
// xgetbv reads the contents of an XCR (Extended Control Register)
|
||||
// specified in the ECX register into registers EDX:EAX.
|
||||
// Currently, the only supported value for XCR is 0.
|
||||
//
|
||||
// TODO: Replace with a better alternative:
|
||||
//
|
||||
// #include <xsaveintrin.h>
|
||||
//
|
||||
// #pragma GCC target("xsave")
|
||||
//
|
||||
// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) {
|
||||
// unsigned long long x = _xgetbv(0);
|
||||
// *eax = x & 0xffffffff;
|
||||
// *edx = (x >> 32) & 0xffffffff;
|
||||
// }
|
||||
//
|
||||
// Note that _xgetbv is defined starting with GCC 8.
|
||||
void |
||||
gccgoXgetbv(uint32_t *eax, uint32_t *edx) |
||||
{ |
||||
__asm(" xorl %%ecx, %%ecx\n" |
||||
" xgetbv" |
||||
: "=a"(*eax), "=d"(*edx)); |
||||
} |
@ -0,0 +1,26 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build 386 amd64 amd64p32
|
||||
// +build gccgo
|
||||
|
||||
package cpu |
||||
|
||||
//extern gccgoGetCpuidCount
|
||||
func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32) |
||||
|
||||
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) { |
||||
var a, b, c, d uint32 |
||||
gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d) |
||||
return a, b, c, d |
||||
} |
||||
|
||||
//extern gccgoXgetbv
|
||||
func gccgoXgetbv(eax, edx *uint32) |
||||
|
||||
func xgetbv() (eax, edx uint32) { |
||||
var a, d uint32 |
||||
gccgoXgetbv(&a, &d) |
||||
return a, d |
||||
} |
@ -0,0 +1,22 @@ |
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build gccgo
|
||||
|
||||
package cpu |
||||
|
||||
// haveAsmFunctions reports whether the other functions in this file can
|
||||
// be safely called.
|
||||
func haveAsmFunctions() bool { return false } |
||||
|
||||
// TODO(mundaym): the following feature detection functions are currently
|
||||
// stubs. See https://golang.org/cl/162887 for how to fix this.
|
||||
// They are likely to be expensive to call so the results should be cached.
|
||||
func stfle() facilityList { panic("not implemented for gccgo") } |
||||
func kmQuery() queryResult { panic("not implemented for gccgo") } |
||||
func kmcQuery() queryResult { panic("not implemented for gccgo") } |
||||
func kmctrQuery() queryResult { panic("not implemented for gccgo") } |
||||
func kmaQuery() queryResult { panic("not implemented for gccgo") } |
||||
func kimdQuery() queryResult { panic("not implemented for gccgo") } |
||||
func klmdQuery() queryResult { panic("not implemented for gccgo") } |
@ -0,0 +1,59 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//+build !amd64,!amd64p32,!386
|
||||
|
||||
package cpu |
||||
|
||||
import ( |
||||
"io/ioutil" |
||||
) |
||||
|
||||
const ( |
||||
_AT_HWCAP = 16 |
||||
_AT_HWCAP2 = 26 |
||||
|
||||
procAuxv = "/proc/self/auxv" |
||||
|
||||
uintSize = int(32 << (^uint(0) >> 63)) |
||||
) |
||||
|
||||
// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2
|
||||
// These are initialized in cpu_$GOARCH.go
|
||||
// and should not be changed after they are initialized.
|
||||
var hwCap uint |
||||
var hwCap2 uint |
||||
|
||||
func init() { |
||||
buf, err := ioutil.ReadFile(procAuxv) |
||||
if err != nil { |
||||
// e.g. on android /proc/self/auxv is not accessible, so silently
|
||||
// ignore the error and leave Initialized = false
|
||||
return |
||||
} |
||||
|
||||
bo := hostByteOrder() |
||||
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: |
||||
hwCap2 = val |
||||
} |
||||
} |
||||
doinit() |
||||
|
||||
Initialized = true |
||||
} |
@ -0,0 +1,67 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cpu |
||||
|
||||
const cacheLineSize = 64 |
||||
|
||||
// HWCAP/HWCAP2 bits. These are exposed by Linux.
|
||||
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 |
||||
) |
||||
|
||||
func doinit() { |
||||
// HWCAP feature bits
|
||||
ARM64.HasFP = isSet(hwCap, hwcap_FP) |
||||
ARM64.HasASIMD = isSet(hwCap, hwcap_ASIMD) |
||||
ARM64.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) |
||||
ARM64.HasAES = isSet(hwCap, hwcap_AES) |
||||
ARM64.HasPMULL = isSet(hwCap, hwcap_PMULL) |
||||
ARM64.HasSHA1 = isSet(hwCap, hwcap_SHA1) |
||||
ARM64.HasSHA2 = isSet(hwCap, hwcap_SHA2) |
||||
ARM64.HasCRC32 = isSet(hwCap, hwcap_CRC32) |
||||
ARM64.HasATOMICS = isSet(hwCap, hwcap_ATOMICS) |
||||
ARM64.HasFPHP = isSet(hwCap, hwcap_FPHP) |
||||
ARM64.HasASIMDHP = isSet(hwCap, hwcap_ASIMDHP) |
||||
ARM64.HasCPUID = isSet(hwCap, hwcap_CPUID) |
||||
ARM64.HasASIMDRDM = isSet(hwCap, hwcap_ASIMDRDM) |
||||
ARM64.HasJSCVT = isSet(hwCap, hwcap_JSCVT) |
||||
ARM64.HasFCMA = isSet(hwCap, hwcap_FCMA) |
||||
ARM64.HasLRCPC = isSet(hwCap, hwcap_LRCPC) |
||||
ARM64.HasDCPOP = isSet(hwCap, hwcap_DCPOP) |
||||
ARM64.HasSHA3 = isSet(hwCap, hwcap_SHA3) |
||||
ARM64.HasSM3 = isSet(hwCap, hwcap_SM3) |
||||
ARM64.HasSM4 = isSet(hwCap, hwcap_SM4) |
||||
ARM64.HasASIMDDP = isSet(hwCap, hwcap_ASIMDDP) |
||||
ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) |
||||
ARM64.HasSVE = isSet(hwCap, hwcap_SVE) |
||||
ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) |
||||
} |
||||
|
||||
func isSet(hwc uint, value uint) bool { |
||||
return hwc&value != 0 |
||||
} |
@ -0,0 +1,33 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux
|
||||
// +build ppc64 ppc64le
|
||||
|
||||
package cpu |
||||
|
||||
const cacheLineSize = 128 |
||||
|
||||
// HWCAP/HWCAP2 bits. These are exposed by the kernel.
|
||||
const ( |
||||
// ISA Level
|
||||
_PPC_FEATURE2_ARCH_2_07 = 0x80000000 |
||||
_PPC_FEATURE2_ARCH_3_00 = 0x00800000 |
||||
|
||||
// CPU features
|
||||
_PPC_FEATURE2_DARN = 0x00200000 |
||||
_PPC_FEATURE2_SCV = 0x00100000 |
||||
) |
||||
|
||||
func doinit() { |
||||
// HWCAP2 feature bits
|
||||
PPC64.IsPOWER8 = isSet(hwCap2, _PPC_FEATURE2_ARCH_2_07) |
||||
PPC64.IsPOWER9 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_00) |
||||
PPC64.HasDARN = isSet(hwCap2, _PPC_FEATURE2_DARN) |
||||
PPC64.HasSCV = isSet(hwCap2, _PPC_FEATURE2_SCV) |
||||
} |
||||
|
||||
func isSet(hwc uint, value uint) bool { |
||||
return hwc&value != 0 |
||||
} |
@ -0,0 +1,161 @@ |
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cpu |
||||
|
||||
const cacheLineSize = 256 |
||||
|
||||
const ( |
||||
// bit mask values from /usr/include/bits/hwcap.h
|
||||
hwcap_ZARCH = 2 |
||||
hwcap_STFLE = 4 |
||||
hwcap_MSA = 8 |
||||
hwcap_LDISP = 16 |
||||
hwcap_EIMM = 32 |
||||
hwcap_DFP = 64 |
||||
hwcap_ETF3EH = 256 |
||||
hwcap_VX = 2048 |
||||
hwcap_VXE = 8192 |
||||
) |
||||
|
||||
// bitIsSet reports whether the bit at index is set. The bit index
|
||||
// is in big endian order, so bit index 0 is the leftmost bit.
|
||||
func bitIsSet(bits []uint64, index uint) bool { |
||||
return bits[index/64]&((1<<63)>>(index%64)) != 0 |
||||
} |
||||
|
||||
// function is the code for the named cryptographic function.
|
||||
type function uint8 |
||||
|
||||
const ( |
||||
// KM{,A,C,CTR} function codes
|
||||
aes128 function = 18 // AES-128
|
||||
aes192 function = 19 // AES-192
|
||||
aes256 function = 20 // AES-256
|
||||
|
||||
// K{I,L}MD function codes
|
||||
sha1 function = 1 // SHA-1
|
||||
sha256 function = 2 // SHA-256
|
||||
sha512 function = 3 // SHA-512
|
||||
sha3_224 function = 32 // SHA3-224
|
||||
sha3_256 function = 33 // SHA3-256
|
||||
sha3_384 function = 34 // SHA3-384
|
||||
sha3_512 function = 35 // SHA3-512
|
||||
shake128 function = 36 // SHAKE-128
|
||||
shake256 function = 37 // SHAKE-256
|
||||
|
||||
// KLMD function codes
|
||||
ghash function = 65 // GHASH
|
||||
) |
||||
|
||||
// queryResult contains the result of a Query function
|
||||
// call. Bits are numbered in big endian order so the
|
||||
// leftmost bit (the MSB) is at index 0.
|
||||
type queryResult struct { |
||||
bits [2]uint64 |
||||
} |
||||
|
||||
// Has reports whether the given functions are present.
|
||||
func (q *queryResult) Has(fns ...function) bool { |
||||
if len(fns) == 0 { |
||||
panic("no function codes provided") |
||||
} |
||||
for _, f := range fns { |
||||
if !bitIsSet(q.bits[:], uint(f)) { |
||||
return false |
||||
} |
||||
} |
||||
return true |
||||
} |
||||
|
||||
// facility is a bit index for the named facility.
|
||||
type facility uint8 |
||||
|
||||
const ( |
||||
// cryptography facilities
|
||||
msa4 facility = 77 // message-security-assist extension 4
|
||||
msa8 facility = 146 // message-security-assist extension 8
|
||||
) |
||||
|
||||
// facilityList contains the result of an STFLE call.
|
||||
// Bits are numbered in big endian order so the
|
||||
// leftmost bit (the MSB) is at index 0.
|
||||
type facilityList struct { |
||||
bits [4]uint64 |
||||
} |
||||
|
||||
// Has reports whether the given facilities are present.
|
||||
func (s *facilityList) Has(fs ...facility) bool { |
||||
if len(fs) == 0 { |
||||
panic("no facility bits provided") |
||||
} |
||||
for _, f := range fs { |
||||
if !bitIsSet(s.bits[:], uint(f)) { |
||||
return false |
||||
} |
||||
} |
||||
return true |
||||
} |
||||
|
||||
func doinit() { |
||||
// test HWCAP bit vector
|
||||
has := func(featureMask uint) bool { |
||||
return hwCap&featureMask == featureMask |
||||
} |
||||
|
||||
// mandatory
|
||||
S390X.HasZARCH = has(hwcap_ZARCH) |
||||
|
||||
// optional
|
||||
S390X.HasSTFLE = has(hwcap_STFLE) |
||||
S390X.HasLDISP = has(hwcap_LDISP) |
||||
S390X.HasEIMM = has(hwcap_EIMM) |
||||
S390X.HasETF3EH = has(hwcap_ETF3EH) |
||||
S390X.HasDFP = has(hwcap_DFP) |
||||
S390X.HasMSA = has(hwcap_MSA) |
||||
S390X.HasVX = has(hwcap_VX) |
||||
if S390X.HasVX { |
||||
S390X.HasVXE = has(hwcap_VXE) |
||||
} |
||||
|
||||
// We need implementations of stfle, km and so on
|
||||
// to detect cryptographic features.
|
||||
if !haveAsmFunctions() { |
||||
return |
||||
} |
||||
|
||||
// optional cryptographic functions
|
||||
if S390X.HasMSA { |
||||
aes := []function{aes128, aes192, aes256} |
||||
|
||||
// cipher message
|
||||
km, kmc := kmQuery(), kmcQuery() |
||||
S390X.HasAES = km.Has(aes...) |
||||
S390X.HasAESCBC = kmc.Has(aes...) |
||||
if S390X.HasSTFLE { |
||||
facilities := stfle() |
||||
if facilities.Has(msa4) { |
||||
kmctr := kmctrQuery() |
||||
S390X.HasAESCTR = kmctr.Has(aes...) |
||||
} |
||||
if facilities.Has(msa8) { |
||||
kma := kmaQuery() |
||||
S390X.HasAESGCM = kma.Has(aes...) |
||||
} |
||||
} |
||||
|
||||
// compute message digest
|
||||
kimd := kimdQuery() // intermediate (no padding)
|
||||
klmd := klmdQuery() // last (padding)
|
||||
S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) |
||||
S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) |
||||
S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) |
||||
S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist
|
||||
sha3 := []function{ |
||||
sha3_224, sha3_256, sha3_384, sha3_512, |
||||
shake128, shake256, |
||||
} |
||||
S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build mips64 mips64le
|
||||
|
||||
package cpu |
||||
|
||||
const cacheLineSize = 32 |
||||
|
||||
func doinit() {} |
@ -0,0 +1,11 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build mips mipsle
|
||||
|
||||
package cpu |
||||
|
||||
const cacheLineSize = 32 |
||||
|
||||
func doinit() {} |
@ -0,0 +1,11 @@ |
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !linux,arm64
|
||||
|
||||
package cpu |
||||
|
||||
const cacheLineSize = 64 |
||||
|
||||
func doinit() {} |
@ -0,0 +1,57 @@ |
||||
// Copyright 2019 The Go Authors. All rights reserved. |
||||
// Use of this source code is governed by a BSD-style |
||||
// license that can be found in the LICENSE file. |
||||
|
||||
// +build !gccgo |
||||
|
||||
#include "textflag.h" |
||||
|
||||
// func stfle() facilityList |
||||
TEXT ·stfle(SB), NOSPLIT|NOFRAME, $0-32 |
||||
MOVD $ret+0(FP), R1 |
||||
MOVD $3, R0 // last doubleword index to store |
||||
XC $32, (R1), (R1) // clear 4 doublewords (32 bytes) |
||||
WORD $0xb2b01000 // store facility list extended (STFLE) |
||||
RET |
||||
|
||||
// func kmQuery() queryResult |
||||
TEXT ·kmQuery(SB), NOSPLIT|NOFRAME, $0-16 |
||||
MOVD $0, R0 // set function code to 0 (KM-Query) |
||||
MOVD $ret+0(FP), R1 // address of 16-byte return value |
||||
WORD $0xB92E0024 // cipher message (KM) |
||||
RET |
||||
|
||||
// func kmcQuery() queryResult |
||||
TEXT ·kmcQuery(SB), NOSPLIT|NOFRAME, $0-16 |
||||
MOVD $0, R0 // set function code to 0 (KMC-Query) |
||||
MOVD $ret+0(FP), R1 // address of 16-byte return value |
||||
WORD $0xB92F0024 // cipher message with chaining (KMC) |
||||
RET |
||||
|
||||
// func kmctrQuery() queryResult |
||||
TEXT ·kmctrQuery(SB), NOSPLIT|NOFRAME, $0-16 |
||||
MOVD $0, R0 // set function code to 0 (KMCTR-Query) |
||||
MOVD $ret+0(FP), R1 // address of 16-byte return value |
||||
WORD $0xB92D4024 // cipher message with counter (KMCTR) |
||||
RET |
||||
|
||||
// func kmaQuery() queryResult |
||||
TEXT ·kmaQuery(SB), NOSPLIT|NOFRAME, $0-16 |
||||
MOVD $0, R0 // set function code to 0 (KMA-Query) |
||||
MOVD $ret+0(FP), R1 // address of 16-byte return value |
||||
WORD $0xb9296024 // cipher message with authentication (KMA) |
||||
RET |
||||
|
||||
// func kimdQuery() queryResult |
||||
TEXT ·kimdQuery(SB), NOSPLIT|NOFRAME, $0-16 |
||||
MOVD $0, R0 // set function code to 0 (KIMD-Query) |
||||
MOVD $ret+0(FP), R1 // address of 16-byte return value |
||||
WORD $0xB93E0024 // compute intermediate message digest (KIMD) |
||||
RET |
||||
|
||||
// func klmdQuery() queryResult |
||||
TEXT ·klmdQuery(SB), NOSPLIT|NOFRAME, $0-16 |
||||
MOVD $0, R0 // set function code to 0 (KLMD-Query) |
||||
MOVD $ret+0(FP), R1 // address of 16-byte return value |
||||
WORD $0xB93F0024 // compute last message digest (KLMD) |
||||
RET |
@ -0,0 +1,15 @@ |
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build wasm
|
||||
|
||||
package cpu |
||||
|
||||
// We're compiling the cpu package for an unknown (software-abstracted) CPU.
|
||||
// Make CacheLinePad an empty struct and hope that the usual struct alignment
|
||||
// rules are good enough.
|
||||
|
||||
const cacheLineSize = 0 |
||||
|
||||
func doinit() {} |
@ -0,0 +1,59 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build 386 amd64 amd64p32
|
||||
|
||||
package cpu |
||||
|
||||
const cacheLineSize = 64 |
||||
|
||||
func init() { |
||||
Initialized = true |
||||
|
||||
maxID, _, _, _ := cpuid(0, 0) |
||||
|
||||
if maxID < 1 { |
||||
return |
||||
} |
||||
|
||||
_, _, ecx1, edx1 := cpuid(1, 0) |
||||
X86.HasSSE2 = isSet(26, edx1) |
||||
|
||||
X86.HasSSE3 = isSet(0, ecx1) |
||||
X86.HasPCLMULQDQ = isSet(1, ecx1) |
||||
X86.HasSSSE3 = isSet(9, ecx1) |
||||
X86.HasFMA = isSet(12, ecx1) |
||||
X86.HasSSE41 = isSet(19, ecx1) |
||||
X86.HasSSE42 = isSet(20, ecx1) |
||||
X86.HasPOPCNT = isSet(23, ecx1) |
||||
X86.HasAES = isSet(25, ecx1) |
||||
X86.HasOSXSAVE = isSet(27, ecx1) |
||||
X86.HasRDRAND = isSet(30, ecx1) |
||||
|
||||
osSupportsAVX := false |
||||
// For XGETBV, OSXSAVE bit is required and sufficient.
|
||||
if X86.HasOSXSAVE { |
||||
eax, _ := xgetbv() |
||||
// Check if XMM and YMM registers have OS support.
|
||||
osSupportsAVX = isSet(1, eax) && isSet(2, eax) |
||||
} |
||||
|
||||
X86.HasAVX = isSet(28, ecx1) && osSupportsAVX |
||||
|
||||
if maxID < 7 { |
||||
return |
||||
} |
||||
|
||||
_, ebx7, _, _ := cpuid(7, 0) |
||||
X86.HasBMI1 = isSet(3, ebx7) |
||||
X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX |
||||
X86.HasBMI2 = isSet(8, ebx7) |
||||
X86.HasERMS = isSet(9, ebx7) |
||||
X86.HasRDSEED = isSet(18, ebx7) |
||||
X86.HasADX = isSet(19, ebx7) |
||||
} |
||||
|
||||
func isSet(bitpos uint, value uint32) bool { |
||||
return value&(1<<bitpos) != 0 |
||||
} |
@ -0,0 +1,27 @@ |
||||
// Copyright 2018 The Go Authors. All rights reserved. |
||||
// Use of this source code is governed by a BSD-style |
||||
// license that can be found in the LICENSE file. |
||||
|
||||
// +build 386 amd64 amd64p32 |
||||
// +build !gccgo |
||||
|
||||
#include "textflag.h" |
||||
|
||||
// func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) |
||||
TEXT ·cpuid(SB), NOSPLIT, $0-24 |
||||
MOVL eaxArg+0(FP), AX |
||||
MOVL ecxArg+4(FP), CX |
||||
CPUID |
||||
MOVL AX, eax+8(FP) |
||||
MOVL BX, ebx+12(FP) |
||||
MOVL CX, ecx+16(FP) |
||||
MOVL DX, edx+20(FP) |
||||
RET |
||||
|
||||
// func xgetbv() (eax, edx uint32) |
||||
TEXT ·xgetbv(SB),NOSPLIT,$0-8 |
||||
MOVL $0, CX |
||||
XGETBV |
||||
MOVL AX, eax+0(FP) |
||||
MOVL DX, edx+4(FP) |
||||
RET |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue